aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Tromey2013-08-25 14:25:59 -0600
committerTom Tromey2013-08-25 14:25:59 -0600
commit793ea5055aea85ff9227e1bf0c84ab37edba7201 (patch)
treec9799eebe2b797a55fcbfcbd3710c9b5aa70051d
parent1ce4c6398ea453a66f6943552b0ec866a690e9b1 (diff)
parente687aa335a21662f67d2d73063272504a171ffab (diff)
downloademacs-793ea5055aea85ff9227e1bf0c84ab37edba7201.tar.gz
emacs-793ea5055aea85ff9227e1bf0c84ab37edba7201.zip
merge from trunk
-rw-r--r--ChangeLog26
-rw-r--r--Makefile.in9
-rwxr-xr-xautogen/configure44
-rw-r--r--configure.ac49
-rw-r--r--doc/lispref/ChangeLog5
-rw-r--r--doc/lispref/files.texi8
-rw-r--r--lisp/ChangeLog89
-rw-r--r--lisp/align.el409
-rw-r--r--lisp/calc/calc-keypd.el17
-rw-r--r--lisp/calendar/timeclock.el118
-rw-r--r--lisp/emacs-lisp/pp.el6
-rw-r--r--lisp/erc/ChangeLog31
-rw-r--r--lisp/erc/erc-button.el31
-rw-r--r--lisp/erc/erc-list.el15
-rw-r--r--lisp/erc/erc-notify.el54
-rw-r--r--lisp/erc/erc-track.el35
-rw-r--r--lisp/erc/erc.el597
-rw-r--r--lisp/files.el16
-rw-r--r--lisp/minibuffer.el3
-rw-r--r--lisp/progmodes/cc-awk.el81
-rw-r--r--lisp/progmodes/cc-engine.el15
-rw-r--r--lisp/progmodes/cc-langs.el3
-rw-r--r--lisp/progmodes/sh-script.el59
-rw-r--r--lisp/rfn-eshadow.el10
-rw-r--r--lisp/textmodes/fill.el2
-rw-r--r--lisp/window.el5
-rw-r--r--nt/ChangeLog14
-rw-r--r--nt/INSTALL3
-rwxr-xr-xnt/configure.bat15
-rw-r--r--src/ChangeLog121
-rw-r--r--src/alloc.c12
-rw-r--r--src/callproc.c104
-rw-r--r--src/character.c14
-rw-r--r--src/dispextern.h63
-rw-r--r--src/dispnew.c58
-rw-r--r--src/fileio.c118
-rw-r--r--src/frame.h10
-rw-r--r--src/gtkutil.c11
-rw-r--r--src/lisp.h1
-rw-r--r--src/nsterm.m8
-rw-r--r--src/process.c72
-rw-r--r--src/process.h1
-rw-r--r--src/sysdep.c113
-rw-r--r--src/w32.c29
-rw-r--r--src/w32term.c9
-rw-r--r--src/window.c2
-rw-r--r--src/xdisp.c38
-rw-r--r--src/xterm.c9
-rw-r--r--test/ChangeLog6
-rw-r--r--test/automated/eieio-test-methodinvoke.el379
-rw-r--r--test/automated/eieio-test-persist.el213
-rw-r--r--test/automated/eieio-tests.el893
-rw-r--r--[-rwxr-xr-x]test/automated/package-test.el0
-rw-r--r--[-rwxr-xr-x]test/automated/package-x-test.el0
54 files changed, 2968 insertions, 1085 deletions
diff --git a/ChangeLog b/ChangeLog
index 27395616072..35dbeb6065c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
12013-08-22 Paul Eggert <eggert@cs.ucla.edu>
2
3 * configure.ac (EMACS_CONFIG_OPTIONS): Quote systematically (Bug#13274).
4 This improves on the patch already installed, by quoting options
5 that contain spaces and suchlike systematically, so that
6 EMACS_CONFIG_OPTIONS is no longer ambiguous when options contain
7 these characters.
8
92013-08-21 Paul Eggert <eggert@cs.ucla.edu>
10
11 Port close-on-exec pty creation to FreeBSD 9.1-RELEASE (Bug#15129).
12 * configure.ac (PTY_OPEN): If posix_openpt with O_CLOEXEC fails
13 and reports EINVAL, try it again without O_CLOEXEC. This should
14 port PTY_OPEN to FreeBSD 9, which stupidly rejects O_CLOEXEC.
15 What were they thinking?
16
172013-08-20 Paul Eggert <eggert@cs.ucla.edu>
18
19 * Makefile.in (distclean, bootstrap-clean, maintainer-clean):
20 Fix shell-operator precedence problem in previous change.
21
222013-08-20 Glenn Morris <rgm@gnu.org>
23
24 * Makefile.in (distclean, bootstrap-clean, maintainer-clean):
25 Clean test/automated if present.
26
12013-08-19 Paul Eggert <eggert@cs.ucla.edu> 272013-08-19 Paul Eggert <eggert@cs.ucla.edu>
2 28
3 Merge from gnulib, incorporating: 29 Merge from gnulib, incorporating:
diff --git a/Makefile.in b/Makefile.in
index ee74baf45cf..a29fd353346 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -859,6 +859,9 @@ distclean: FRC
859 (cd leim; $(MAKE) $(MFLAGS) distclean) 859 (cd leim; $(MAKE) $(MFLAGS) distclean)
860 (cd lisp; $(MAKE) $(MFLAGS) distclean) 860 (cd lisp; $(MAKE) $(MFLAGS) distclean)
861 (cd nextstep && $(MAKE) $(MFLAGS) distclean) 861 (cd nextstep && $(MAKE) $(MFLAGS) distclean)
862 [ ! -d test/automated ] || { \
863 cd test/automated && $(MAKE) $(MFLAGS) distclean; \
864 }
862 ${top_distclean} 865 ${top_distclean}
863 866
864### `bootstrap-clean' 867### `bootstrap-clean'
@@ -878,6 +881,9 @@ bootstrap-clean: FRC
878 (cd leim; $(MAKE) $(MFLAGS) maintainer-clean) 881 (cd leim; $(MAKE) $(MFLAGS) maintainer-clean)
879 (cd lisp; $(MAKE) $(MFLAGS) bootstrap-clean) 882 (cd lisp; $(MAKE) $(MFLAGS) bootstrap-clean)
880 (cd nextstep && $(MAKE) $(MFLAGS) maintainer-clean) 883 (cd nextstep && $(MAKE) $(MFLAGS) maintainer-clean)
884 [ ! -d test/automated ] || { \
885 cd test/automated && $(MAKE) $(MFLAGS) bootstrap-clean; \
886 }
881 [ ! -f config.log ] || mv -f config.log config.log~ 887 [ ! -f config.log ] || mv -f config.log config.log~
882 ${top_bootclean} 888 ${top_bootclean}
883 889
@@ -898,6 +904,9 @@ top_maintainer_clean=\
898maintainer-clean: bootstrap-clean FRC 904maintainer-clean: bootstrap-clean FRC
899 (cd src; $(MAKE) $(MFLAGS) maintainer-clean) 905 (cd src; $(MAKE) $(MFLAGS) maintainer-clean)
900 (cd lisp; $(MAKE) $(MFLAGS) maintainer-clean) 906 (cd lisp; $(MAKE) $(MFLAGS) maintainer-clean)
907 [ ! -d test/automated ] || { \
908 cd test/automated && $(MAKE) $(MFLAGS) maintainer-clean; \
909 }
901 ${top_maintainer_clean} 910 ${top_maintainer_clean}
902 911
903### This doesn't actually appear in the coding standards, but Karl 912### This doesn't actually appear in the coding standards, but Karl
diff --git a/autogen/configure b/autogen/configure
index a82c52daf98..f35ce6d62cb 100755
--- a/autogen/configure
+++ b/autogen/configure
@@ -3486,16 +3486,37 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
3486 3486
3487 3487
3488 3488
3489emacs_config_options="$@" 3489emacs_config_options=
3490## Add some environment variables, if they were passed via the environment 3490optsep=
3491## rather than on the command-line. 3491for opt in ${1+"$@"} CFLAGS CPPFLAGS LDFLAGS; do
3492for var in CFLAGS CPPFLAGS LDFLAGS; do 3492 case $opt in
3493 case "$emacs_config_options" in 3493 -n | --no-create | --no-recursion)
3494 *$var=*) continue ;; 3494 continue ;;
3495 esac 3495 CFLAGS | CPPFLAGS | LDFLAGS)
3496 eval val="\$${var}" 3496 eval 'test "${'$opt'+set}" = set' || continue
3497 test x"$val" = x && continue 3497 case " $*" in
3498 emacs_config_options="${emacs_config_options}${emacs_config_options:+ }$var=\"$val\"" 3498 *" $opt="*) continue ;;
3499 esac
3500 eval opt=$opt=\$$opt ;;
3501 esac
3502
3503 emacs_shell_specials=$IFS\''"#$&()*;<>?[\\`{|~'
3504 case $opt in
3505 *["$emacs_shell_specials"]*)
3506 case $opt in
3507 *\'*)
3508 emacs_quote_apostrophes="s/'/'\\\\''/g"
3509 opt=`$as_echo "$opt" | sed "$emacs_quote_apostrophes"` ;;
3510 esac
3511 opt="'$opt'"
3512 case $opt in
3513 *['"\\']*)
3514 emacs_quote_for_c='s/["\\]/\\&/g; $!s/$/\\n\\/'
3515 opt=`$as_echo "$opt" | sed "$emacs_quote_for_c"` ;;
3516 esac ;;
3517 esac
3518 as_fn_append emacs_config_options "$optsep$opt"
3519 optsep=' '
3499done 3520done
3500 3521
3501ac_config_headers="$ac_config_headers src/config.h:src/config.in" 3522ac_config_headers="$ac_config_headers src/config.h:src/config.in"
@@ -16573,7 +16594,7 @@ $as_echo "#define UNIX98_PTYS 1" >>confdefs.h
16573 $as_echo "#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); }" >>confdefs.h 16594 $as_echo "#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); }" >>confdefs.h
16574 16595
16575 if test "x$ac_cv_func_posix_openpt" = xyes; then 16596 if test "x$ac_cv_func_posix_openpt" = xyes; then
16576 $as_echo "#define PTY_OPEN fd = posix_openpt (O_RDWR | O_CLOEXEC | O_NOCTTY)" >>confdefs.h 16597 $as_echo "#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 (0)" >>confdefs.h
16577 16598
16578 $as_echo "#define PTY_NAME_SPRINTF /**/" >>confdefs.h 16599 $as_echo "#define PTY_NAME_SPRINTF /**/" >>confdefs.h
16579 16600
@@ -17173,7 +17194,6 @@ cat >>confdefs.h <<_ACEOF
17173#define EMACS_CONFIGURATION "${canonical}" 17194#define EMACS_CONFIGURATION "${canonical}"
17174_ACEOF 17195_ACEOF
17175 17196
17176emacs_config_options=`echo "$emacs_config_options " | sed -e 's/--no-create //' -e 's/--no-recursion //' -e 's/ *$//' -e "s/\"/'/g" -e 's/\\\\/\\\\\\\\/g'`
17177 17197
17178cat >>confdefs.h <<_ACEOF 17198cat >>confdefs.h <<_ACEOF
17179#define EMACS_CONFIG_OPTIONS "${emacs_config_options}" 17199#define EMACS_CONFIG_OPTIONS "${emacs_config_options}"
diff --git a/configure.ac b/configure.ac
index aa7b2922e88..bbd799cadee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -24,18 +24,43 @@ dnl along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24AC_PREREQ(2.65) 24AC_PREREQ(2.65)
25AC_INIT(emacs, 24.3.50) 25AC_INIT(emacs, 24.3.50)
26 26
27dnl Set emacs_config_options to the options of 'configure', quoted for the shell,
28dnl and then quoted again for a C string. Separate options with spaces.
29dnl Add some environment variables, if they were passed via the environment
30dnl rather than on the command-line.
31emacs_config_options=
32optsep=
27dnl This is the documented way to record the args passed to configure, 33dnl This is the documented way to record the args passed to configure,
28dnl rather than $ac_configure_args. 34dnl rather than $ac_configure_args.
29emacs_config_options="$@" 35for opt in ${1+"$@"} CFLAGS CPPFLAGS LDFLAGS; do
30## Add some environment variables, if they were passed via the environment 36 case $opt in
31## rather than on the command-line. 37 -n | --no-create | --no-recursion)
32for var in CFLAGS CPPFLAGS LDFLAGS; do 38 continue ;;
33 case "$emacs_config_options" in 39 CFLAGS | CPPFLAGS | LDFLAGS)
34 *$var=*) continue ;; 40 eval 'test "${'$opt'+set}" = set' || continue
35 esac 41 case " $*" in
36 eval val="\$${var}" 42 *" $opt="*) continue ;;
37 test x"$val" = x && continue 43 esac
38 emacs_config_options="${emacs_config_options}${emacs_config_options:+ }$var=\"$val\"" 44 eval opt=$opt=\$$opt ;;
45 esac
46
47 emacs_shell_specials=$IFS\''"#$&()*;<>?@<:@\\`{|~'
48 case $opt in
49 *[["$emacs_shell_specials"]]*)
50 case $opt in
51 *\'*)
52 emacs_quote_apostrophes="s/'/'\\\\''/g"
53 opt=`AS_ECHO(["$opt"]) | sed "$emacs_quote_apostrophes"` ;;
54 esac
55 opt="'$opt'"
56 case $opt in
57 *[['"\\']]*)
58 emacs_quote_for_c='s/[["\\]]/\\&/g; $!s/$/\\n\\/'
59 opt=`AS_ECHO(["$opt"]) | sed "$emacs_quote_for_c"` ;;
60 esac ;;
61 esac
62 AS_VAR_APPEND([emacs_config_options], ["$optsep$opt"])
63 optsep=' '
39done 64done
40 65
41AC_CONFIG_HEADER(src/config.h:src/config.in) 66AC_CONFIG_HEADER(src/config.h:src/config.in)
@@ -3994,7 +4019,7 @@ case $opsys in
3994 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); }]) 4019 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); }])
3995 dnl if HAVE_POSIX_OPENPT 4020 dnl if HAVE_POSIX_OPENPT
3996 if test "x$ac_cv_func_posix_openpt" = xyes; then 4021 if test "x$ac_cv_func_posix_openpt" = xyes; then
3997 AC_DEFINE(PTY_OPEN, [fd = posix_openpt (O_RDWR | O_CLOEXEC | O_NOCTTY)]) 4022 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 (0)])
3998 AC_DEFINE(PTY_NAME_SPRINTF, []) 4023 AC_DEFINE(PTY_NAME_SPRINTF, [])
3999 dnl if HAVE_GETPT 4024 dnl if HAVE_GETPT
4000 elif test "x$ac_cv_func_getpt" = xyes; then 4025 elif test "x$ac_cv_func_getpt" = xyes; then
@@ -4440,8 +4465,6 @@ fi
4440 4465
4441AC_DEFINE_UNQUOTED(EMACS_CONFIGURATION, "${canonical}", 4466AC_DEFINE_UNQUOTED(EMACS_CONFIGURATION, "${canonical}",
4442 [Define to the canonical Emacs configuration name.]) 4467 [Define to the canonical Emacs configuration name.])
4443dnl Replace any embedded " characters (bug#13274).
4444emacs_config_options=`echo "$emacs_config_options " | sed -e 's/--no-create //' -e 's/--no-recursion //' -e 's/ *$//' -e "s/\"/'/g" -e 's/\\\\/\\\\\\\\/g'`
4445AC_DEFINE_UNQUOTED(EMACS_CONFIG_OPTIONS, "${emacs_config_options}", 4468AC_DEFINE_UNQUOTED(EMACS_CONFIG_OPTIONS, "${emacs_config_options}",
4446 [Define to the options passed to configure.]) 4469 [Define to the options passed to configure.])
4447AH_TEMPLATE(config_opsysfile, [Some platforms that do not use configure 4470AH_TEMPLATE(config_opsysfile, [Some platforms that do not use configure
diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog
index 3f9d23a5476..d2e86c25cc1 100644
--- a/doc/lispref/ChangeLog
+++ b/doc/lispref/ChangeLog
@@ -1,3 +1,8 @@
12013-08-20 Eli Zaretskii <eliz@gnu.org>
2
3 * files.texi (Information about Files): Mention file names with
4 trailing blanks on MS-Windows. (Bug#15130)
5
12013-08-18 Xue Fuqiao <xfq.free@gmail.com> 62013-08-18 Xue Fuqiao <xfq.free@gmail.com>
2 7
3 * positions.texi (Positions): Improve indexing. 8 * positions.texi (Positions): Improve indexing.
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 77b097ae90a..1f7169522cc 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -776,6 +776,14 @@ return information about actual files or directories, so their
776arguments must all exist as actual files or directories unless 776arguments must all exist as actual files or directories unless
777otherwise noted. 777otherwise noted.
778 778
779@cindex file names, trailing whitespace
780@cindex trailing blanks in file names
781Be careful with file names that end in blanks: some filesystems
782(notably, MS-Windows) will ignore trailing whitespace in file names,
783and return information about the file after stripping those blanks
784from the name, not about the file whose name you passed to the
785functions described in this section.
786
779@menu 787@menu
780* Testing Accessibility:: Is a given file readable? Writable? 788* Testing Accessibility:: Is a given file readable? Writable?
781* Kinds of Files:: Is it a directory? A symbolic link? 789* Kinds of Files:: Is it a directory? A symbolic link?
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 28431e9a08d..cbeea784579 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,92 @@
12013-08-25 Alan Mackenzie <acm@muc.de>
2
3 Parse C++ inher-intro when there's a template split over 2 lines.
4
5 * progmodes/cc-engine.el (c-guess-basic-syntax CASE 5C): Code more
6 rigorously the search for "class" etc. followed by ":".
7
8 * progmodes/cc-langs.el (c-opt-<>-sexp-key): Make the value for
9 random languages a regexp which never matches rather than nil.
10
11 Handle "/"s more accurately in test for virtual semicolons (AWK Mode).
12
13 * progmodes/cc-awk.el (c-awk-one-line-possibly-open-string-re)
14 (c-awk-regexp-one-line-possibly-open-char-list-re)
15 (c-awk-one-line-possibly-open-regexp-re)
16 (c-awk-one-line-non-syn-ws*-re): Remove.
17 (c-awk-possibly-open-string-re, c-awk-non-/-syn-ws*-re)
18 (c-awk-space*-/-re, c-awk-space*-regexp-/-re)
19 (c-awk-space*-unclosed-regexp-/-re): New constants.
20 (c-awk-at-vsemi-p): Reformulate better to recognize "/"s which
21 aren't regexp delimiters.
22
23 * progmodes/cc-engine.el (c-crosses-statement-barrier-p): Add in
24 handling for a rare situation in AWK Mode involving unterminated
25 strings/regexps.
26
272013-08-23 Glenn Morris <rgm@gnu.org>
28
29 * files.el (auto-mode-alist): Use sh-mode for .bash_history.
30
31 * files.el (interpreter-mode-alist): Use tcl-mode for expect scripts.
32
33 * files.el (create-file-buffer): If the result would begin with
34 spaces, prepend a "|" instead of removing them. (Bug#15162)
35
362013-08-23 Stefan Monnier <monnier@iro.umontreal.ca>
37
38 * textmodes/fill.el (fill-match-adaptive-prefix): Don't throw away
39 text-properties (bug#15155).
40
41 * calc/calc-keypd.el (calc-keypad-execute): `x-flush-mouse-queue' doesn't
42 exist any more.
43 (calc-keypad-redraw): Remove unused var `pad'.
44 (calc-keypad-press): Remove unused var `menu'.
45
462013-08-23 Martin Rudalics <rudalics@gmx.at>
47
48 * window.el (display-buffer-pop-up-frame):
49 Call pop-up-frame-function with BUFFER current so `make-frame' will
50 use it as the new frame's buffer (Bug#15133).
51
522013-08-22 Stefan Monnier <monnier@iro.umontreal.ca>
53
54 * calendar/timeclock.el: Minor cleanups.
55 (timeclock-ask-before-exiting, timeclock-use-display-time):
56 Use `symbol'.
57 (timeclock-modeline-display): Define as alias before the
58 actual definition.
59 (timeclock-mode-line-display): Use define-minor-mode.
60 (timeclock-day-list-template): Make it a function, add an argument.
61 (timeclock-day-list-required, timeclock-day-list-length)
62 (timeclock-day-list-debt, timeclock-day-list-span)
63 (timeclock-day-list-break): Adjust calls accordingly.
64
652013-08-21 Stefan Monnier <monnier@iro.umontreal.ca>
66
67 * emacs-lisp/pp.el (pp-eval-expression, pp-macroexpand-expression):
68 Use read--expression so that completion works again.
69
702013-08-21 Sam Steingold <sds@gnu.org>
71
72 Add rudimentary inferior shell interaction
73 * progmodes/sh-script.el (sh-shell-process): New buffer-local variable.
74 (sh-set-shell): Reset it.
75 (sh-show-shell, sh-cd-here, sh-send-line-or-region-and-step):
76 New commands (bound to C-c C-z, C-c C-d, and C-c C-n).
77
782013-08-20 Stefan Monnier <monnier@iro.umontreal.ca>
79
80 * align.el: Use lexical-binding.
81 (align-region): Simplify accordingly.
82
832013-08-20 Michael Albinus <michael.albinus@gmx.de>
84
85 * minibuffer.el (completion--sifn-requote): Bind `non-essential'.
86
87 * rfn-eshadow.el (rfn-eshadow-update-overlay): Move binding of
88 `non-essential' up.
89
12013-08-17 Michael Albinus <michael.albinus@gmx.de> 902013-08-17 Michael Albinus <michael.albinus@gmx.de>
2 91
3 * net/tramp.el: 92 * net/tramp.el:
diff --git a/lisp/align.el b/lisp/align.el
index 3d2ca192245..6f55ac9faf1 100644
--- a/lisp/align.el
+++ b/lisp/align.el
@@ -1,4 +1,4 @@
1;;; align.el --- align text to a specific column, by regexp 1;;; align.el --- align text to a specific column, by regexp -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 1999-2013 Free Software Foundation, Inc. 3;; Copyright (C) 1999-2013 Free Software Foundation, Inc.
4 4
@@ -1325,7 +1325,7 @@ aligner would have dealt with are."
1325 (unless (or (and modes (not (memq major-mode 1325 (unless (or (and modes (not (memq major-mode
1326 (eval (cdr modes))))) 1326 (eval (cdr modes)))))
1327 (and run-if (not (funcall (cdr run-if))))) 1327 (and run-if (not (funcall (cdr run-if)))))
1328 (let* ((current-case-fold case-fold-search) 1328 (let* ((case-fold-search case-fold-search)
1329 (case-fold (assq 'case-fold rule)) 1329 (case-fold (assq 'case-fold rule))
1330 (regexp (cdr (assq 'regexp rule))) 1330 (regexp (cdr (assq 'regexp rule)))
1331 (regfunc (and (functionp regexp) regexp)) 1331 (regfunc (and (functionp regexp) regexp))
@@ -1403,215 +1403,202 @@ aligner would have dealt with are."
1403 ;; reports back that the region is ok, then align it. 1403 ;; reports back that the region is ok, then align it.
1404 (when (or (not func) 1404 (when (or (not func)
1405 (funcall func beg end rule)) 1405 (funcall func beg end rule))
1406 (unwind-protect 1406 (let (rule-beg exclude-areas)
1407 (let (rule-beg exclude-areas) 1407 ;; determine first of all where the exclusions
1408 ;; determine first of all where the exclusions 1408 ;; lie in this region
1409 ;; lie in this region 1409 (when exclude-rules
1410 (when exclude-rules 1410 (align-region
1411 ;; guard against a problem with recursion and 1411 beg end 'entire
1412 ;; dynamic binding vs. lexical binding, since 1412 exclude-rules nil
1413 ;; the call to `align-region' below will 1413 (lambda (b e mode)
1414 ;; re-enter this function, and rebind 1414 (or (and mode (listp mode))
1415 ;; `exclude-areas' 1415 (setq exclude-areas
1416 (set (setq exclude-areas 1416 (cons (cons b e)
1417 (make-symbol "align-exclude-areas")) 1417 exclude-areas)))))
1418 nil) 1418 (setq exclude-areas
1419 (align-region 1419 (nreverse
1420 beg end 'entire 1420 (sort exclude-areas #'car-less-than-car))))
1421 exclude-rules nil 1421
1422 `(lambda (b e mode) 1422 ;; set `case-fold-search' according to the
1423 (or (and mode (listp mode)) 1423 ;; (optional) `case-fold' property
1424 (set (quote ,exclude-areas) 1424 (and case-fold
1425 (cons (cons b e) 1425 (setq case-fold-search (cdr case-fold)))
1426 ,exclude-areas))))) 1426
1427 (setq exclude-areas 1427 ;; while we can find the rule in the alignment
1428 (sort (symbol-value exclude-areas) 1428 ;; region..
1429 (function 1429 (while (and (< (point) end-mark)
1430 (lambda (l r) 1430 (setq search-start (point))
1431 (>= (car l) (car r))))))) 1431 (if regfunc
1432 1432 (funcall regfunc end-mark nil)
1433 ;; set `case-fold-search' according to the 1433 (re-search-forward regexp
1434 ;; (optional) `case-fold' property 1434 end-mark t)))
1435 (and case-fold 1435
1436 (setq case-fold-search (cdr case-fold))) 1436 ;; give the user some indication of where we
1437 1437 ;; are, if it's a very large region being
1438 ;; while we can find the rule in the alignment 1438 ;; aligned
1439 ;; region.. 1439 (if report
1440 (while (and (< (point) end-mark) 1440 (let ((symbol (car rule)))
1441 (setq search-start (point)) 1441 (if (and symbol (symbolp symbol))
1442 (if regfunc 1442 (message
1443 (funcall regfunc end-mark nil) 1443 "Aligning `%s' (rule %d of %d) %d%%..."
1444 (re-search-forward regexp 1444 (symbol-name symbol) rule-index rule-count
1445 end-mark t))) 1445 (/ (* (- (point) real-beg) 100)
1446 1446 (- end-mark real-beg)))
1447 ;; give the user some indication of where we 1447 (message
1448 ;; are, if it's a very large region being 1448 "Aligning %d%%..."
1449 ;; aligned 1449 (/ (* (- (point) real-beg) 100)
1450 (if report 1450 (- end-mark real-beg))))))
1451 (let ((symbol (car rule))) 1451
1452 (if (and symbol (symbolp symbol)) 1452 ;; if the search ended us on the beginning of
1453 (message 1453 ;; the next line, move back to the end of the
1454 "Aligning `%s' (rule %d of %d) %d%%..." 1454 ;; previous line.
1455 (symbol-name symbol) rule-index rule-count 1455 (if (and (bolp) (> (point) search-start))
1456 (/ (* (- (point) real-beg) 100) 1456 (forward-char -1))
1457 (- end-mark real-beg))) 1457
1458 (message 1458 ;; lookup the `group' attribute the first time
1459 "Aligning %d%%..." 1459 ;; that we need it
1460 (/ (* (- (point) real-beg) 100) 1460 (unless group-c
1461 (- end-mark real-beg)))))) 1461 (setq groups (or (cdr (assq 'group rule)) 1))
1462 1462 (unless (listp groups)
1463 ;; if the search ended us on the beginning of 1463 (setq groups (list groups)))
1464 ;; the next line, move back to the end of the 1464 (setq first (car groups)))
1465 ;; previous line. 1465
1466 (if (and (bolp) (> (point) search-start)) 1466 (unless spacing-c
1467 (forward-char -1)) 1467 (setq spacing (cdr (assq 'spacing rule))
1468 1468 spacing-c t))
1469 ;; lookup the `group' attribute the first time 1469
1470 ;; that we need it 1470 (unless tab-stop-c
1471 (unless group-c 1471 (setq tab-stop
1472 (setq groups (or (cdr (assq 'group rule)) 1)) 1472 (let ((rule-ts (assq 'tab-stop rule)))
1473 (unless (listp groups) 1473 (cond (rule-ts
1474 (setq groups (list groups))) 1474 (cdr rule-ts))
1475 (setq first (car groups))) 1475 ((symbolp align-to-tab-stop)
1476 1476 (symbol-value align-to-tab-stop))
1477 (unless spacing-c 1477 (t
1478 (setq spacing (cdr (assq 'spacing rule)) 1478 align-to-tab-stop)))
1479 spacing-c t)) 1479 tab-stop-c t))
1480 1480
1481 (unless tab-stop-c 1481 ;; test whether we have found a match on the same
1482 (setq tab-stop 1482 ;; line as a previous match
1483 (let ((rule-ts (assq 'tab-stop rule))) 1483 (when (> (point) eol)
1484 (cond (rule-ts 1484 (setq same nil)
1485 (cdr rule-ts)) 1485 (align--set-marker eol (line-end-position)))
1486 ((symbolp align-to-tab-stop) 1486
1487 (symbol-value align-to-tab-stop)) 1487 ;; lookup the `repeat' attribute the first time
1488 (t 1488 (or repeat-c
1489 align-to-tab-stop))) 1489 (setq repeat (cdr (assq 'repeat rule))
1490 tab-stop-c t)) 1490 repeat-c t))
1491 1491
1492 ;; test whether we have found a match on the same 1492 ;; lookup the `valid' attribute the first time
1493 ;; line as a previous match 1493 (or valid-c
1494 (when (> (point) eol) 1494 (setq valid (assq 'valid rule)
1495 (setq same nil) 1495 valid-c t))
1496 (align--set-marker eol (line-end-position))) 1496
1497 1497 ;; remember the beginning position of this rule
1498 ;; lookup the `repeat' attribute the first time 1498 ;; match, and save the match-data, since either
1499 (or repeat-c 1499 ;; the `valid' form, or the code that searches for
1500 (setq repeat (cdr (assq 'repeat rule)) 1500 ;; section separation, might alter it
1501 repeat-c t)) 1501 (setq rule-beg (match-beginning first)
1502 1502 save-match-data (match-data))
1503 ;; lookup the `valid' attribute the first time 1503
1504 (or valid-c 1504 (or rule-beg
1505 (setq valid (assq 'valid rule) 1505 (error "No match for subexpression %s" first))
1506 valid-c t)) 1506
1507 1507 ;; unless the `valid' attribute is set, and tells
1508 ;; remember the beginning position of this rule 1508 ;; us that the rule is not valid at this point in
1509 ;; match, and save the match-data, since either 1509 ;; the code..
1510 ;; the `valid' form, or the code that searches for 1510 (unless (and valid (not (funcall (cdr valid))))
1511 ;; section separation, might alter it 1511
1512 (setq rule-beg (match-beginning first) 1512 ;; look to see if this match begins a new
1513 save-match-data (match-data)) 1513 ;; section. If so, we should align what we've
1514 1514 ;; collected so far, and then begin collecting
1515 (or rule-beg 1515 ;; anew for the next alignment section
1516 (error "No match for subexpression %s" first)) 1516 (when (and last-point
1517 1517 (align-new-section-p last-point rule-beg
1518 ;; unless the `valid' attribute is set, and tells 1518 thissep))
1519 ;; us that the rule is not valid at this point in 1519 (align-regions regions align-props rule func)
1520 ;; the code.. 1520 (setq regions nil)
1521 (unless (and valid (not (funcall (cdr valid)))) 1521 (setq align-props nil))
1522 1522 (align--set-marker last-point rule-beg t)
1523 ;; look to see if this match begins a new 1523
1524 ;; section. If so, we should align what we've 1524 ;; restore the match data
1525 ;; collected so far, and then begin collecting 1525 (set-match-data save-match-data)
1526 ;; anew for the next alignment section 1526
1527 (when (and last-point 1527 ;; check whether the region to be aligned
1528 (align-new-section-p last-point rule-beg 1528 ;; straddles an exclusion area
1529 thissep)) 1529 (let ((excls exclude-areas))
1530 (align-regions regions align-props rule func) 1530 (setq exclude-p nil)
1531 (setq regions nil) 1531 (while excls
1532 (setq align-props nil)) 1532 (if (and (< (match-beginning (car groups))
1533 (align--set-marker last-point rule-beg t) 1533 (cdar excls))
1534 1534 (> (match-end (car (last groups)))
1535 ;; restore the match data 1535 (caar excls)))
1536 (set-match-data save-match-data) 1536 (setq exclude-p t
1537 1537 excls nil)
1538 ;; check whether the region to be aligned 1538 (setq excls (cdr excls)))))
1539 ;; straddles an exclusion area 1539
1540 (let ((excls exclude-areas)) 1540 ;; go through the parenthesis groups
1541 (setq exclude-p nil) 1541 ;; matching whitespace to be contracted or
1542 (while excls 1542 ;; expanded (or possibly justified, if the
1543 (if (and (< (match-beginning (car groups)) 1543 ;; `justify' attribute was set)
1544 (cdar excls)) 1544 (unless exclude-p
1545 (> (match-end (car (last groups))) 1545 (dolist (g groups)
1546 (caar excls))) 1546 ;; We must use markers, since
1547 (setq exclude-p t 1547 ;; `align-areas' may modify the buffer.
1548 excls nil) 1548 ;; Avoid polluting the markers.
1549 (setq excls (cdr excls))))) 1549 (let* ((group-beg (copy-marker
1550 1550 (match-beginning g) t))
1551 ;; go through the parenthesis groups 1551 (group-end (copy-marker
1552 ;; matching whitespace to be contracted or 1552 (match-end g) t))
1553 ;; expanded (or possibly justified, if the 1553 (region (cons group-beg group-end))
1554 ;; `justify' attribute was set) 1554 (props (cons (if (listp spacing)
1555 (unless exclude-p 1555 (car spacing)
1556 (dolist (g groups) 1556 spacing)
1557 ;; We must use markers, since 1557 (if (listp tab-stop)
1558 ;; `align-areas' may modify the buffer. 1558 (car tab-stop)
1559 ;; Avoid polluting the markers. 1559 tab-stop))))
1560 (let* ((group-beg (copy-marker 1560 (push group-beg markers)
1561 (match-beginning g) t)) 1561 (push group-end markers)
1562 (group-end (copy-marker 1562 (setq index (if same (1+ index) 0))
1563 (match-end g) t)) 1563 (cond
1564 (region (cons group-beg group-end)) 1564 ((nth index regions)
1565 (props (cons (if (listp spacing) 1565 (setcar (nthcdr index regions)
1566 (car spacing) 1566 (cons region
1567 spacing) 1567 (nth index regions))))
1568 (if (listp tab-stop) 1568 (regions
1569 (car tab-stop) 1569 (nconc regions
1570 tab-stop)))) 1570 (list (list region)))
1571 (push group-beg markers) 1571 (nconc align-props (list props)))
1572 (push group-end markers) 1572 (t
1573 (setq index (if same (1+ index) 0)) 1573 (setq regions
1574 (cond 1574 (list (list region)))
1575 ((nth index regions) 1575 (setq align-props (list props)))))
1576 (setcar (nthcdr index regions) 1576 ;; If any further rule matches are found
1577 (cons region 1577 ;; before `eol', they are on the same
1578 (nth index regions)))) 1578 ;; line as this one; this can only
1579 (regions 1579 ;; happen if the `repeat' attribute is
1580 (nconc regions 1580 ;; non-nil.
1581 (list (list region))) 1581 (if (listp spacing)
1582 (nconc align-props (list props))) 1582 (setq spacing (cdr spacing)))
1583 (t 1583 (if (listp tab-stop)
1584 (setq regions 1584 (setq tab-stop (cdr tab-stop)))
1585 (list (list region))) 1585 (setq same t))
1586 (setq align-props (list props))))) 1586
1587 ;; If any further rule matches are found 1587 ;; if `repeat' has not been set, move to
1588 ;; before `eol', they are on the same 1588 ;; the next line; don't bother searching
1589 ;; line as this one; this can only 1589 ;; anymore on this one
1590 ;; happen if the `repeat' attribute is 1590 (if (and (not repeat) (not (bolp)))
1591 ;; non-nil. 1591 (forward-line))
1592 (if (listp spacing) 1592
1593 (setq spacing (cdr spacing))) 1593 ;; if the search did not change point,
1594 (if (listp tab-stop) 1594 ;; move forward to avoid an infinite loop
1595 (setq tab-stop (cdr tab-stop))) 1595 (if (= (point) search-start)
1596 (setq same t)) 1596 (forward-char)))))
1597 1597
1598 ;; if `repeat' has not been set, move to 1598 ;; when they are no more matches for this rule,
1599 ;; the next line; don't bother searching 1599 ;; align whatever was left over
1600 ;; anymore on this one 1600 (if regions
1601 (if (and (not repeat) (not (bolp))) 1601 (align-regions regions align-props rule func))))))))
1602 (forward-line))
1603
1604 ;; if the search did not change point,
1605 ;; move forward to avoid an infinite loop
1606 (if (= (point) search-start)
1607 (forward-char)))))
1608
1609 ;; when they are no more matches for this rule,
1610 ;; align whatever was left over
1611 (if regions
1612 (align-regions regions align-props rule func)))
1613
1614 (setq case-fold-search current-case-fold)))))))
1615 (setq rules (cdr rules) 1602 (setq rules (cdr rules)
1616 rule-index (1+ rule-index))) 1603 rule-index (1+ rule-index)))
1617 ;; This function can use a lot of temporary markers, so instead of 1604 ;; This function can use a lot of temporary markers, so instead of
diff --git a/lisp/calc/calc-keypd.el b/lisp/calc/calc-keypd.el
index a720f12a573..bd24bf7f15d 100644
--- a/lisp/calc/calc-keypd.el
+++ b/lisp/calc/calc-keypd.el
@@ -349,8 +349,7 @@
349 (if (> (length (car key)) cwid) 349 (if (> (length (car key)) cwid)
350 (substring (car key) 0 cwid) 350 (substring (car key) 0 cwid)
351 (car key)))) 351 (car key))))
352 (wid (length name)) 352 (wid (length name)))
353 (pad (- cwid (/ wid 2))))
354 (insert (make-string (/ (- cwid wid) 2) 32) 353 (insert (make-string (/ (- cwid wid) 2) 32)
355 name 354 name
356 (make-string (/ (- cwid wid -1) 2) 32) 355 (make-string (/ (- cwid wid -1) 2) 32)
@@ -399,7 +398,6 @@
399 inv calc-inverse-flag) 398 inv calc-inverse-flag)
400 calc-hyperbolic-flag)) 399 calc-hyperbolic-flag))
401 (invhyp t) 400 (invhyp t)
402 (menu (symbol-value (nth calc-keypad-menu calc-keypad-menus)))
403 (input calc-keypad-input) 401 (input calc-keypad-input)
404 (iexpon (and input 402 (iexpon (and input
405 (or (string-match "\\*[0-9]+\\.\\^" input) 403 (or (string-match "\\*[0-9]+\\.\\^" input)
@@ -535,19 +533,22 @@
535 533
536(defun calc-keypad-left-click (event) 534(defun calc-keypad-left-click (event)
537 "Handle a left-button mouse click in Calc Keypad window." 535 "Handle a left-button mouse click in Calc Keypad window."
536 ;; FIXME: Why not use "@e" instead to select the buffer?
538 (interactive "e") 537 (interactive "e")
539 (with-current-buffer calc-keypad-buffer 538 (with-current-buffer calc-keypad-buffer
540 (goto-char (posn-point (event-start event))) 539 (goto-char (posn-point (event-start event)))
541 (calc-keypad-press))) 540 (calc-keypad-press)))
542 541
543(defun calc-keypad-right-click (event) 542(defun calc-keypad-right-click (_event)
544 "Handle a right-button mouse click in Calc Keypad window." 543 "Handle a right-button mouse click in Calc Keypad window."
544 ;; FIXME: Why not use "@e" instead to select the buffer?
545 (interactive "e") 545 (interactive "e")
546 (with-current-buffer calc-keypad-buffer 546 (with-current-buffer calc-keypad-buffer
547 (calc-keypad-menu))) 547 (calc-keypad-menu)))
548 548
549(defun calc-keypad-middle-click (event) 549(defun calc-keypad-middle-click (_event)
550 "Handle a middle-button mouse click in Calc Keypad window." 550 "Handle a middle-button mouse click in Calc Keypad window."
551 ;; FIXME: Why not use "@e" instead to select the buffer?
551 (interactive "e") 552 (interactive "e")
552 (with-current-buffer calc-keypad-buffer 553 (with-current-buffer calc-keypad-buffer
553 (calc-keypad-menu-back))) 554 (calc-keypad-menu-back)))
@@ -588,7 +589,6 @@
588(defun calc-keypad-execute () 589(defun calc-keypad-execute ()
589 (interactive) 590 (interactive)
590 (let* ((prompt "Calc keystrokes: ") 591 (let* ((prompt "Calc keystrokes: ")
591 (flush 'x-flush-mouse-queue)
592 (prefix nil) 592 (prefix nil)
593 keys cmd) 593 keys cmd)
594 (save-excursion 594 (save-excursion
@@ -605,10 +605,9 @@
605 (progn 605 (progn
606 (setq last-command-event (aref keys (1- (length keys)))) 606 (setq last-command-event (aref keys (1- (length keys))))
607 (command-execute cmd) 607 (command-execute cmd)
608 (setq flush 'not-any-more 608 (setq prefix t
609 prefix t
610 prompt (concat prompt (key-description keys) " "))) 609 prompt (concat prompt (key-description keys) " ")))
611 (eq cmd flush))))) ; skip mouse-up event 610 nil)))) ; skip mouse-up event
612 (message "") 611 (message "")
613 (if (commandp cmd) 612 (if (commandp cmd)
614 (command-execute cmd) 613 (command-execute cmd)
diff --git a/lisp/calendar/timeclock.el b/lisp/calendar/timeclock.el
index 70d064143dc..da074d377b5 100644
--- a/lisp/calendar/timeclock.el
+++ b/lisp/calendar/timeclock.el
@@ -136,7 +136,7 @@ This variable only has effect if set with \\[customize]."
136 (if value 136 (if value
137 (add-hook 'kill-emacs-query-functions 'timeclock-query-out) 137 (add-hook 'kill-emacs-query-functions 'timeclock-query-out)
138 (remove-hook 'kill-emacs-query-functions 'timeclock-query-out)) 138 (remove-hook 'kill-emacs-query-functions 'timeclock-query-out))
139 (setq timeclock-ask-before-exiting value)) 139 (set symbol value))
140 :type 'boolean 140 :type 'boolean
141 :group 'timeclock) 141 :group 'timeclock)
142 142
@@ -174,11 +174,12 @@ a positive argument to force an update."
174 timeclock-update-timer))) 174 timeclock-update-timer)))
175 (setq currently-displaying nil)) 175 (setq currently-displaying nil))
176 (and currently-displaying 176 (and currently-displaying
177 (set-variable 'timeclock-mode-line-display nil)) 177 (setq timeclock-mode-line-display nil))
178 (setq timeclock-use-display-time value) 178 (set symbol value)
179 (and currently-displaying 179 (and currently-displaying
180 (set-variable 'timeclock-mode-line-display t)) 180 (setq timeclock-mode-line-display t))
181 timeclock-use-display-time)) 181 ;; FIXME: The return value isn't used, AFAIK!
182 value))
182 :type 'boolean 183 :type 'boolean
183 :group 'timeclock 184 :group 'timeclock
184 :require 'time) 185 :require 'time)
@@ -269,9 +270,11 @@ The time is bracketed by <> if you are clocked in, otherwise by [].")
269 270
270(define-obsolete-function-alias 'timeclock-modeline-display 271(define-obsolete-function-alias 'timeclock-modeline-display
271 'timeclock-mode-line-display "24.3") 272 'timeclock-mode-line-display "24.3")
273(define-obsolete-variable-alias 'timeclock-modeline-display
274 'timeclock-mode-line-display "24.3")
272 275
273;;;###autoload 276;;;###autoload
274(defun timeclock-mode-line-display (&optional arg) 277(define-minor-mode timeclock-mode-line-display
275 "Toggle display of the amount of time left today in the mode line. 278 "Toggle display of the amount of time left today in the mode line.
276If `timeclock-use-display-time' is non-nil (the default), then 279If `timeclock-use-display-time' is non-nil (the default), then
277the function `display-time-mode' must be active, and the mode line 280the function `display-time-mode' must be active, and the mode line
@@ -280,61 +283,41 @@ the timeclock will use its own sixty second timer to do its
280updating. With prefix ARG, turn mode line display on if and only 283updating. With prefix ARG, turn mode line display on if and only
281if ARG is positive. Returns the new status of timeclock mode line 284if ARG is positive. Returns the new status of timeclock mode line
282display (non-nil means on)." 285display (non-nil means on)."
283 (interactive "P") 286 :global t
284 ;; cf display-time-mode. 287 ;; cf display-time-mode.
285 (setq timeclock-mode-string "") 288 (setq timeclock-mode-string "")
286 (or global-mode-string (setq global-mode-string '(""))) 289 (or global-mode-string (setq global-mode-string '("")))
287 (let ((on-p (if arg 290 (if timeclock-mode-line-display
288 (> (prefix-numeric-value arg) 0) 291 (progn
289 (not timeclock-mode-line-display)))) 292 (or (memq 'timeclock-mode-string global-mode-string)
290 (if on-p 293 (setq global-mode-string
291 (progn 294 (append global-mode-string '(timeclock-mode-string))))
292 (or (memq 'timeclock-mode-string global-mode-string) 295 (add-hook 'timeclock-event-hook 'timeclock-update-mode-line)
293 (setq global-mode-string 296 (when timeclock-update-timer
294 (append global-mode-string '(timeclock-mode-string)))) 297 (cancel-timer timeclock-update-timer)
295 (add-hook 'timeclock-event-hook 'timeclock-update-mode-line) 298 (setq timeclock-update-timer nil))
296 (when timeclock-update-timer 299 (if (boundp 'display-time-hook)
297 (cancel-timer timeclock-update-timer) 300 (remove-hook 'display-time-hook 'timeclock-update-mode-line))
298 (setq timeclock-update-timer nil)) 301 (if timeclock-use-display-time
299 (if (boundp 'display-time-hook) 302 (progn
300 (remove-hook 'display-time-hook 'timeclock-update-mode-line)) 303 ;; Update immediately so there is a visible change
301 (if timeclock-use-display-time 304 ;; on calling this function.
302 (progn 305 (if display-time-mode
303 ;; Update immediately so there is a visible change 306 (timeclock-update-mode-line)
304 ;; on calling this function. 307 (message "Activate `display-time-mode' or turn off \
305 (if display-time-mode
306 (timeclock-update-mode-line)
307 (message "Activate `display-time-mode' or turn off \
308`timeclock-use-display-time' to see timeclock information")) 308`timeclock-use-display-time' to see timeclock information"))
309 (add-hook 'display-time-hook 'timeclock-update-mode-line)) 309 (add-hook 'display-time-hook 'timeclock-update-mode-line))
310 (setq timeclock-update-timer 310 (setq timeclock-update-timer
311 (run-at-time nil 60 'timeclock-update-mode-line)))) 311 (run-at-time nil 60 'timeclock-update-mode-line))))
312 (setq global-mode-string 312 (setq global-mode-string
313 (delq 'timeclock-mode-string global-mode-string)) 313 (delq 'timeclock-mode-string global-mode-string))
314 (remove-hook 'timeclock-event-hook 'timeclock-update-mode-line) 314 (remove-hook 'timeclock-event-hook 'timeclock-update-mode-line)
315 (if (boundp 'display-time-hook) 315 (if (boundp 'display-time-hook)
316 (remove-hook 'display-time-hook 316 (remove-hook 'display-time-hook
317 'timeclock-update-mode-line)) 317 'timeclock-update-mode-line))
318 (when timeclock-update-timer 318 (when timeclock-update-timer
319 (cancel-timer timeclock-update-timer) 319 (cancel-timer timeclock-update-timer)
320 (setq timeclock-update-timer nil))) 320 (setq timeclock-update-timer nil))))
321 (force-mode-line-update)
322 (setq timeclock-mode-line-display on-p)))
323
324(define-obsolete-variable-alias 'timeclock-modeline-display
325 'timeclock-mode-line-display "24.3")
326
327;; This has to be here so that the function definition of
328;; `timeclock-mode-line-display' is known to the "set" function.
329(defcustom timeclock-mode-line-display nil
330 "Toggle mode line display of time remaining.
331You must modify via \\[customize] for this variable to have an effect."
332 :set (lambda (symbol value)
333 (setq timeclock-mode-line-display
334 (timeclock-mode-line-display (or value 0))))
335 :type 'boolean
336 :group 'timeclock
337 :require 'timeclock)
338 321
339(defsubst timeclock-time-to-date (time) 322(defsubst timeclock-time-to-date (time)
340 "Convert the TIME value to a textual date string." 323 "Convert the TIME value to a textual date string."
@@ -835,25 +818,24 @@ This is only provided for coherency when used by
835 "Return a list of all the projects in DAY." 818 "Return a list of all the projects in DAY."
836 (timeclock-entry-list-projects (cddr day))) 819 (timeclock-entry-list-projects (cddr day)))
837 820
838(defmacro timeclock-day-list-template (func) 821(defun timeclock-day-list-template (func day-list)
839 "Template for summing the result of FUNC on each element of DAY-LIST." 822 "Template for summing the result of FUNC on each element of DAY-LIST."
840 `(let ((length 0)) 823 (let ((length 0))
841 (while day-list 824 (dolist (day day-list)
842 (setq length (+ length (,(eval func) (car day-list))) 825 (setq length (+ length (funcall func day))))
843 day-list (cdr day-list))) 826 length))
844 length))
845 827
846(defun timeclock-day-list-required (day-list) 828(defun timeclock-day-list-required (day-list)
847 "Return total required length of DAY-LIST, in seconds." 829 "Return total required length of DAY-LIST, in seconds."
848 (timeclock-day-list-template 'timeclock-day-required)) 830 (timeclock-day-list-template #'timeclock-day-required day-list))
849 831
850(defun timeclock-day-list-length (day-list) 832(defun timeclock-day-list-length (day-list)
851 "Return actual length of DAY-LIST, in seconds." 833 "Return actual length of DAY-LIST, in seconds."
852 (timeclock-day-list-template 'timeclock-day-length)) 834 (timeclock-day-list-template #'timeclock-day-length day-list))
853 835
854(defun timeclock-day-list-debt (day-list) 836(defun timeclock-day-list-debt (day-list)
855 "Return total debt (required - actual) of DAY-LIST." 837 "Return total debt (required - actual) of DAY-LIST."
856 (timeclock-day-list-template 'timeclock-day-debt)) 838 (timeclock-day-list-template #'timeclock-day-debt day-list))
857 839
858(defsubst timeclock-day-list-begin (day-list) 840(defsubst timeclock-day-list-begin (day-list)
859 "Return the start time of DAY-LIST." 841 "Return the start time of DAY-LIST."
@@ -865,11 +847,11 @@ This is only provided for coherency when used by
865 847
866(defun timeclock-day-list-span (day-list) 848(defun timeclock-day-list-span (day-list)
867 "Return the span of DAY-LIST." 849 "Return the span of DAY-LIST."
868 (timeclock-day-list-template 'timeclock-day-span)) 850 (timeclock-day-list-template #'timeclock-day-span day-list))
869 851
870(defun timeclock-day-list-break (day-list) 852(defun timeclock-day-list-break (day-list)
871 "Return the total break of DAY-LIST." 853 "Return the total break of DAY-LIST."
872 (timeclock-day-list-template 'timeclock-day-break)) 854 (timeclock-day-list-template #'timeclock-day-break day-list))
873 855
874(defun timeclock-day-list-projects (day-list) 856(defun timeclock-day-list-projects (day-list)
875 "Return a list of all the projects in DAY-LIST." 857 "Return a list of all the projects in DAY-LIST."
diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el
index b7e553272f2..4cb089aca97 100644
--- a/lisp/emacs-lisp/pp.el
+++ b/lisp/emacs-lisp/pp.el
@@ -127,8 +127,7 @@ after OUT-BUFFER-NAME."
127 "Evaluate EXPRESSION and pretty-print its value. 127 "Evaluate EXPRESSION and pretty-print its value.
128Also add the value to the front of the list in the variable `values'." 128Also add the value to the front of the list in the variable `values'."
129 (interactive 129 (interactive
130 (list (read-from-minibuffer "Eval: " nil read-expression-map t 130 (list (read--expression "Eval: ")))
131 'read-expression-history)))
132 (message "Evaluating...") 131 (message "Evaluating...")
133 (setq values (cons (eval expression) values)) 132 (setq values (cons (eval expression) values))
134 (pp-display-expression (car values) "*Pp Eval Output*")) 133 (pp-display-expression (car values) "*Pp Eval Output*"))
@@ -137,8 +136,7 @@ Also add the value to the front of the list in the variable `values'."
137(defun pp-macroexpand-expression (expression) 136(defun pp-macroexpand-expression (expression)
138 "Macroexpand EXPRESSION and pretty-print its value." 137 "Macroexpand EXPRESSION and pretty-print its value."
139 (interactive 138 (interactive
140 (list (read-from-minibuffer "Macroexpand: " nil read-expression-map t 139 (list (read--expression "Macroexpand: ")))
141 'read-expression-history)))
142 (pp-display-expression (macroexpand expression) "*Pp Macroexpand Output*")) 140 (pp-display-expression (macroexpand expression) "*Pp Macroexpand Output*"))
143 141
144(defun pp-last-sexp () 142(defun pp-last-sexp ()
diff --git a/lisp/erc/ChangeLog b/lisp/erc/ChangeLog
index a23fa508c46..e0628dbb80a 100644
--- a/lisp/erc/ChangeLog
+++ b/lisp/erc/ChangeLog
@@ -1,3 +1,34 @@
12013-08-22 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * erc.el: Use lexical-binding.
4 (erc-user-full-name): Minor CSE simplification.
5 (erc-mode-map): Assume command-remapping is available.
6 (erc-once-with-server-event): Replace `forms' arg with a function arg.
7 (erc-once-with-server-event-global): Remove.
8 (erc-ison-p): Adjust to change in erc-once-with-server-event.
9 (erc-get-buffer-create): Remove arg `proc'.
10 (iswitchb-make-buflist-hook): Declare.
11 (erc-setup-buffer): Use pcase; avoid ((lambda ..) ..).
12 (read-passwd): Assume it exists.
13 (erc-display-line, erc-cmd-IDLE): Avoid add-to-list, adjust to change
14 in erc-once-with-server-event.
15 (erc-cmd-JOIN, erc-set-channel-limit, erc-set-channel-key)
16 (erc-add-query): Minor CSE simplification.
17 (erc-cmd-BANLIST, erc-cmd-MASSUNBAN): Adjust to change
18 in erc-once-with-server-event.
19 (erc-echo-notice-in-user-and-target-buffers): Avoid add-to-list.
20 * erc-track.el: Use lexical-binding.
21 (erc-make-mode-line-buffer-name): Use closures instead of `(lambda...).
22 (erc-faces-in): Avoid add-to-list.
23 * erc-notify.el: Use lexical-binding.
24 (erc-notify-timer): Adjust to change in erc-once-with-server-event.
25 (erc-notify-QUIT): Use a closure instead of `(lambda...).
26 * erc-list.el: Use lexical-binding.
27 (erc-list-install-322-handler, erc-cmd-LIST): Adjust to change in
28 erc-once-with-server-event.
29 * erc-button.el: Use lexical-binding.
30 (erc-button-next-function): Use a closure instead of `(lambda...).
31
12013-05-30 Glenn Morris <rgm@gnu.org> 322013-05-30 Glenn Morris <rgm@gnu.org>
2 33
3 * erc-backend.el: Require erc at run-time too. 34 * erc-backend.el: Require erc at run-time too.
diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el
index 24150138e12..ac8600c57fd 100644
--- a/lisp/erc/erc-button.el
+++ b/lisp/erc/erc-button.el
@@ -1,4 +1,4 @@
1;; erc-button.el --- A way of buttonizing certain things in ERC buffers 1;; erc-button.el --- A way of buttonizing certain things in ERC buffers -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 1996-2004, 2006-2013 Free Software Foundation, Inc. 3;; Copyright (C) 1996-2004, 2006-2013 Free Software Foundation, Inc.
4 4
@@ -432,19 +432,22 @@ call it with the value of the `erc-data' text property."
432(defun erc-button-next-function () 432(defun erc-button-next-function ()
433 "Pseudo completion function that actually jumps to the next button. 433 "Pseudo completion function that actually jumps to the next button.
434For use on `completion-at-point-functions'." 434For use on `completion-at-point-functions'."
435 (when (< (point) (erc-beg-of-input-line)) 435 ;; FIXME: This is an abuse of completion-at-point-functions.
436 `(lambda () 436 (when (< (point) (erc-beg-of-input-line))
437 (let ((here ,(point))) 437 (let ((start (point)))
438 (while (and (get-text-property here 'erc-callback) 438 (lambda ()
439 (not (= here (point-max)))) 439 (let ((here start))
440 (setq here (1+ here))) 440 ;; FIXME: Use next-single-property-change.
441 (while (and (not (get-text-property here 'erc-callback)) 441 (while (and (get-text-property here 'erc-callback)
442 (not (= here (point-max)))) 442 (not (= here (point-max))))
443 (setq here (1+ here))) 443 (setq here (1+ here)))
444 (if (< here (point-max)) 444 (while (not (or (get-text-property here 'erc-callback)
445 (goto-char here) 445 (= here (point-max))))
446 (error "No next button")) 446 (setq here (1+ here)))
447 t)))) 447 (if (< here (point-max))
448 (goto-char here)
449 (error "No next button"))
450 t)))))
448 451
449(defun erc-button-next () 452(defun erc-button-next ()
450 "Go to the next button in this buffer." 453 "Go to the next button in this buffer."
diff --git a/lisp/erc/erc-list.el b/lisp/erc/erc-list.el
index f11dd98ca37..c243073790e 100644
--- a/lisp/erc/erc-list.el
+++ b/lisp/erc/erc-list.el
@@ -1,4 +1,4 @@
1;;; erc-list.el --- /list support for ERC 1;;; erc-list.el --- /list support for ERC -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2008-2013 Free Software Foundation, Inc. 3;; Copyright (C) 2008-2013 Free Software Foundation, Inc.
4 4
@@ -183,7 +183,7 @@
183 ;; Arrange for 323 (end of list) to end this. 183 ;; Arrange for 323 (end of list) to end this.
184 (erc-once-with-server-event 184 (erc-once-with-server-event
185 323 185 323
186 '(progn 186 (lambda (_proc _parsed)
187 (remove-hook 'erc-server-322-functions 'erc-list-handle-322 t))) 187 (remove-hook 'erc-server-322-functions 'erc-list-handle-322 t)))
188 ;; Find the list buffer, empty it, and display it. 188 ;; Find the list buffer, empty it, and display it.
189 (set (make-local-variable 'erc-list-buffer) 189 (set (make-local-variable 'erc-list-buffer)
@@ -209,11 +209,12 @@ should usually be one or more channels, separated by commas.
209Please note that this function only works with IRC servers which conform 209Please note that this function only works with IRC servers which conform
210to RFC and send the LIST header (#321) at start of list transmission." 210to RFC and send the LIST header (#321) at start of list transmission."
211 (erc-with-server-buffer 211 (erc-with-server-buffer
212 (set (make-local-variable 'erc-list-last-argument) line) 212 (set (make-local-variable 'erc-list-last-argument) line)
213 (erc-once-with-server-event 213 (erc-once-with-server-event
214 321 214 321
215 (list 'progn 215 (let ((buf (current-buffer)))
216 (list 'erc-list-install-322-handler (current-buffer))))) 216 (lambda (_proc _parsed)
217 (erc-list-install-322-handler buf)))))
217 (erc-server-send (concat "LIST :" (or (and line (substring line 1)) 218 (erc-server-send (concat "LIST :" (or (and line (substring line 1))
218 "")))) 219 ""))))
219(put 'erc-cmd-LIST 'do-not-parse-args t) 220(put 'erc-cmd-LIST 'do-not-parse-args t)
diff --git a/lisp/erc/erc-notify.el b/lisp/erc/erc-notify.el
index db7067eec08..064bb53f215 100644
--- a/lisp/erc/erc-notify.el
+++ b/lisp/erc/erc-notify.el
@@ -1,4 +1,4 @@
1;;; erc-notify.el --- Online status change notification 1;;; erc-notify.el --- Online status change notification -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2002-2004, 2006-2013 Free Software Foundation, Inc. 3;; Copyright (C) 2002-2004, 2006-2013 Free Software Foundation, Inc.
4 4
@@ -115,27 +115,28 @@ changes."
115 erc-notify-interval)) 115 erc-notify-interval))
116 (erc-once-with-server-event 116 (erc-once-with-server-event
117 303 117 303
118 '(let* ((server (erc-response.sender parsed)) 118 (lambda (proc parsed)
119 (ison-list (delete "" (split-string 119 (let* ((server (erc-response.sender parsed))
120 (erc-response.contents parsed)))) 120 (ison-list (delete "" (split-string
121 (new-list ison-list) 121 (erc-response.contents parsed))))
122 (old-list (erc-with-server-buffer erc-last-ison))) 122 (new-list ison-list)
123 (while new-list 123 (old-list (erc-with-server-buffer erc-last-ison)))
124 (when (not (erc-member-ignore-case (car new-list) old-list)) 124 (while new-list
125 (run-hook-with-args 'erc-notify-signon-hook server (car new-list)) 125 (when (not (erc-member-ignore-case (car new-list) old-list))
126 (erc-display-message 126 (run-hook-with-args 'erc-notify-signon-hook server (car new-list))
127 parsed 'notice proc 127 (erc-display-message
128 'notify_on ?n (car new-list) ?m (erc-network-name))) 128 parsed 'notice proc
129 (setq new-list (cdr new-list))) 129 'notify_on ?n (car new-list) ?m (erc-network-name)))
130 (while old-list 130 (setq new-list (cdr new-list)))
131 (when (not (erc-member-ignore-case (car old-list) ison-list)) 131 (while old-list
132 (run-hook-with-args 'erc-notify-signoff-hook server (car old-list)) 132 (when (not (erc-member-ignore-case (car old-list) ison-list))
133 (erc-display-message 133 (run-hook-with-args 'erc-notify-signoff-hook server (car old-list))
134 parsed 'notice proc 134 (erc-display-message
135 'notify_off ?n (car old-list) ?m (erc-network-name))) 135 parsed 'notice proc
136 (setq old-list (cdr old-list))) 136 'notify_off ?n (car old-list) ?m (erc-network-name)))
137 (setq erc-last-ison ison-list) 137 (setq old-list (cdr old-list)))
138 t)) 138 (setq erc-last-ison ison-list)
139 t)))
139 (erc-server-send 140 (erc-server-send
140 (concat "ISON " (mapconcat 'identity erc-notify-list " "))) 141 (concat "ISON " (mapconcat 'identity erc-notify-list " ")))
141 (setq erc-last-ison-time now))) 142 (setq erc-last-ison-time now)))
@@ -179,10 +180,11 @@ nick from `erc-last-ison' to prevent any further notifications."
179 (let ((nick (erc-extract-nick (erc-response.sender parsed)))) 180 (let ((nick (erc-extract-nick (erc-response.sender parsed))))
180 (when (and (erc-member-ignore-case nick erc-notify-list) 181 (when (and (erc-member-ignore-case nick erc-notify-list)
181 (erc-member-ignore-case nick erc-last-ison)) 182 (erc-member-ignore-case nick erc-last-ison))
182 (setq erc-last-ison (erc-delete-if `(lambda (el) 183 (setq erc-last-ison (erc-delete-if
183 (string= ,(erc-downcase nick) 184 (let ((nick-down (erc-downcase nick)))
184 (erc-downcase el))) 185 (lambda (el)
185 erc-last-ison)) 186 (string= nick-down (erc-downcase el))))
187 erc-last-ison))
186 (run-hook-with-args 'erc-notify-signoff-hook 188 (run-hook-with-args 'erc-notify-signoff-hook
187 (or erc-server-announced-name erc-session-server) 189 (or erc-server-announced-name erc-session-server)
188 nick) 190 nick)
diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el
index 054c135fa67..e6d5b3119a2 100644
--- a/lisp/erc/erc-track.el
+++ b/lisp/erc/erc-track.el
@@ -1,4 +1,4 @@
1;;; erc-track.el --- Track modified channel buffers 1;;; erc-track.el --- Track modified channel buffers -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2002-2013 Free Software Foundation, Inc. 3;; Copyright (C) 2002-2013 Free Software Foundation, Inc.
4 4
@@ -710,7 +710,7 @@ inactive."
710to consider when `erc-track-visibility' is set to 710to consider when `erc-track-visibility' is set to
711only consider active buffers visible.") 711only consider active buffers visible.")
712 712
713(defun erc-user-is-active (&rest ignore) 713(defun erc-user-is-active (&rest _ignore)
714 "Set `erc-buffer-activity'." 714 "Set `erc-buffer-activity'."
715 (when erc-server-connected 715 (when erc-server-connected
716 (setq erc-buffer-activity (erc-current-time)) 716 (setq erc-buffer-activity (erc-current-time))
@@ -745,7 +745,7 @@ only consider active buffers visible.")
745times. Without it, you cannot debug `erc-modified-channels-display', 745times. Without it, you cannot debug `erc-modified-channels-display',
746because the debugger also cases changes to the window-configuration.") 746because the debugger also cases changes to the window-configuration.")
747 747
748(defun erc-modified-channels-update (&rest args) 748(defun erc-modified-channels-update (&rest _args)
749 "This function updates the information in `erc-modified-channels-alist' 749 "This function updates the information in `erc-modified-channels-alist'
750according to buffer visibility. It calls 750according to buffer visibility. It calls
751`erc-modified-channels-display' at the end. This should usually be 751`erc-modified-channels-display' at the end. This should usually be
@@ -791,19 +791,19 @@ If FACES are provided, color STRING with them."
791 (int-to-string count)) 791 (int-to-string count))
792 (copy-sequence string)))) 792 (copy-sequence string))))
793 (define-key map (vector 'mode-line 'mouse-2) 793 (define-key map (vector 'mode-line 'mouse-2)
794 `(lambda (e) 794 (lambda (e)
795 (interactive "e") 795 (interactive "e")
796 (save-selected-window 796 (save-selected-window
797 (select-window 797 (select-window
798 (posn-window (event-start e))) 798 (posn-window (event-start e)))
799 (switch-to-buffer ,buffer)))) 799 (switch-to-buffer buffer))))
800 (define-key map (vector 'mode-line 'mouse-3) 800 (define-key map (vector 'mode-line 'mouse-3)
801 `(lambda (e) 801 (lambda (e)
802 (interactive "e") 802 (interactive "e")
803 (save-selected-window 803 (save-selected-window
804 (select-window 804 (select-window
805 (posn-window (event-start e))) 805 (posn-window (event-start e)))
806 (switch-to-buffer-other-window ,buffer)))) 806 (switch-to-buffer-other-window buffer))))
807 (put-text-property 0 (length name) 'local-map map name) 807 (put-text-property 0 (length name) 'local-map map name)
808 (put-text-property 808 (put-text-property
809 0 (length name) 809 0 (length name)
@@ -976,8 +976,9 @@ is in `erc-mode'."
976 cur) 976 cur)
977 (while (and (setq i (next-single-property-change i 'face str m)) 977 (while (and (setq i (next-single-property-change i 'face str m))
978 (not (= i m))) 978 (not (= i m)))
979 (when (setq cur (get-text-property i 'face str)) 979 (and (setq cur (get-text-property i 'face str))
980 (add-to-list 'faces cur))) 980 (not (member cur faces))
981 (push cur faces)))
981 faces)) 982 faces))
982 983
983(cl-assert 984(cl-assert
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index b2724b9737f..0bfd21d6c3a 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -1,4 +1,4 @@
1;; erc.el --- An Emacs Internet Relay Chat client 1;; erc.el --- An Emacs Internet Relay Chat client -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 1997-2013 Free Software Foundation, Inc. 3;; Copyright (C) 1997-2013 Free Software Foundation, Inc.
4 4
@@ -125,20 +125,11 @@
125 125
126;; compatibility with older ERC releases 126;; compatibility with older ERC releases
127 127
128(if (fboundp 'defvaralias) 128(define-obsolete-variable-alias 'erc-announced-server-name
129 (progn 129 'erc-server-announced-name "ERC 5.1")
130 (defvaralias 'erc-announced-server-name 'erc-server-announced-name) 130(define-obsolete-variable-alias 'erc-process 'erc-server-process "ERC 5.1")
131 (erc-make-obsolete-variable 'erc-announced-server-name 131(define-obsolete-variable-alias 'erc-default-coding-system
132 'erc-server-announced-name 132 'erc-server-coding-system "ERC 5.1")
133 "ERC 5.1")
134 (defvaralias 'erc-process 'erc-server-process)
135 (erc-make-obsolete-variable 'erc-process 'erc-server-process "ERC 5.1")
136 (defvaralias 'erc-default-coding-system 'erc-server-coding-system)
137 (erc-make-obsolete-variable 'erc-default-coding-system
138 'erc-server-coding-system
139 "ERC 5.1"))
140 (message (concat "ERC: The function `defvaralias' is not bound. See the "
141 "NEWS file for variable name changes since ERC 5.0.4.")))
142 133
143(define-obsolete-function-alias 'erc-send-command 134(define-obsolete-function-alias 'erc-send-command
144 'erc-server-send "ERC 5.1") 135 'erc-server-send "ERC 5.1")
@@ -201,9 +192,7 @@ parameters and authentication."
201 (string :tag "Name") 192 (string :tag "Name")
202 (function :tag "Get from function")) 193 (function :tag "Get from function"))
203 :set (lambda (sym val) 194 :set (lambda (sym val)
204 (if (functionp val) 195 (set sym (if (functionp val) (funcall val) val))))
205 (set sym (funcall val))
206 (set sym val))))
207 196
208(defvar erc-password nil 197(defvar erc-password nil
209 "Password to use when authenticating to an IRC server. 198 "Password to use when authenticating to an IRC server.
@@ -388,12 +377,12 @@ If no server buffer exists, return nil."
388 (last-message-time nil)) 377 (last-message-time nil))
389 378
390(defsubst erc-get-channel-user (nick) 379(defsubst erc-get-channel-user (nick)
391 "Finds the (USER . CHANNEL-DATA) element corresponding to NICK 380 "Find the (USER . CHANNEL-DATA) element corresponding to NICK
392in the current buffer's `erc-channel-users' hash table." 381in the current buffer's `erc-channel-users' hash table."
393 (gethash (erc-downcase nick) erc-channel-users)) 382 (gethash (erc-downcase nick) erc-channel-users))
394 383
395(defsubst erc-get-server-user (nick) 384(defsubst erc-get-server-user (nick)
396 "Finds the USER corresponding to NICK in the current server's 385 "Find the USER corresponding to NICK in the current server's
397`erc-server-users' hash table." 386`erc-server-users' hash table."
398 (erc-with-server-buffer 387 (erc-with-server-buffer
399 (gethash (erc-downcase nick) erc-server-users))) 388 (gethash (erc-downcase nick) erc-server-users)))
@@ -480,7 +469,7 @@ Removes all users in the current channel. This is called by
480 (when (and erc-server-connected 469 (when (and erc-server-connected
481 (erc-server-process-alive) 470 (erc-server-process-alive)
482 (hash-table-p erc-channel-users)) 471 (hash-table-p erc-channel-users))
483 (maphash (lambda (nick cdata) 472 (maphash (lambda (nick _cdata)
484 (erc-remove-channel-user nick)) 473 (erc-remove-channel-user nick))
485 erc-channel-users) 474 erc-channel-users)
486 (clrhash erc-channel-users))) 475 (clrhash erc-channel-users)))
@@ -502,25 +491,25 @@ Removes all users in the current channel. This is called by
502 (erc-channel-user-voice (cdr cdata)))))) 491 (erc-channel-user-voice (cdr cdata))))))
503 492
504(defun erc-get-channel-user-list () 493(defun erc-get-channel-user-list ()
505 "Returns a list of users in the current channel. Each element 494 "Return a list of users in the current channel. Each element
506of the list is of the form (USER . CHANNEL-DATA), where USER is 495of the list is of the form (USER . CHANNEL-DATA), where USER is
507an erc-server-user struct, and CHANNEL-DATA is either `nil' or an 496an erc-server-user struct, and CHANNEL-DATA is either nil or an
508erc-channel-user struct. 497erc-channel-user struct.
509 498
510See also: `erc-sort-channel-users-by-activity'" 499See also: `erc-sort-channel-users-by-activity'"
511 (let (users) 500 (let (users)
512 (if (hash-table-p erc-channel-users) 501 (if (hash-table-p erc-channel-users)
513 (maphash (lambda (nick cdata) 502 (maphash (lambda (_nick cdata)
514 (setq users (cons cdata users))) 503 (setq users (cons cdata users)))
515 erc-channel-users)) 504 erc-channel-users))
516 users)) 505 users))
517 506
518(defun erc-get-server-nickname-list () 507(defun erc-get-server-nickname-list ()
519 "Returns a list of known nicknames on the current server." 508 "Return a list of known nicknames on the current server."
520 (erc-with-server-buffer 509 (erc-with-server-buffer
521 (let (nicks) 510 (let (nicks)
522 (when (hash-table-p erc-server-users) 511 (when (hash-table-p erc-server-users)
523 (maphash (lambda (n user) 512 (maphash (lambda (_n user)
524 (setq nicks 513 (setq nicks
525 (cons (erc-server-user-nickname user) 514 (cons (erc-server-user-nickname user)
526 nicks))) 515 nicks)))
@@ -528,10 +517,10 @@ See also: `erc-sort-channel-users-by-activity'"
528 nicks)))) 517 nicks))))
529 518
530(defun erc-get-channel-nickname-list () 519(defun erc-get-channel-nickname-list ()
531 "Returns a list of known nicknames on the current channel." 520 "Return a list of known nicknames on the current channel."
532 (let (nicks) 521 (let (nicks)
533 (when (hash-table-p erc-channel-users) 522 (when (hash-table-p erc-channel-users)
534 (maphash (lambda (n cdata) 523 (maphash (lambda (_n cdata)
535 (setq nicks 524 (setq nicks
536 (cons (erc-server-user-nickname (car cdata)) 525 (cons (erc-server-user-nickname (car cdata))
537 nicks))) 526 nicks)))
@@ -539,11 +528,11 @@ See also: `erc-sort-channel-users-by-activity'"
539 nicks))) 528 nicks)))
540 529
541(defun erc-get-server-nickname-alist () 530(defun erc-get-server-nickname-alist ()
542 "Returns an alist of known nicknames on the current server." 531 "Return an alist of known nicknames on the current server."
543 (erc-with-server-buffer 532 (erc-with-server-buffer
544 (let (nicks) 533 (let (nicks)
545 (when (hash-table-p erc-server-users) 534 (when (hash-table-p erc-server-users)
546 (maphash (lambda (n user) 535 (maphash (lambda (_n user)
547 (setq nicks 536 (setq nicks
548 (cons (cons (erc-server-user-nickname user) nil) 537 (cons (cons (erc-server-user-nickname user) nil)
549 nicks))) 538 nicks)))
@@ -551,10 +540,10 @@ See also: `erc-sort-channel-users-by-activity'"
551 nicks)))) 540 nicks))))
552 541
553(defun erc-get-channel-nickname-alist () 542(defun erc-get-channel-nickname-alist ()
554 "Returns an alist of known nicknames on the current channel." 543 "Return an alist of known nicknames on the current channel."
555 (let (nicks) 544 (let (nicks)
556 (when (hash-table-p erc-channel-users) 545 (when (hash-table-p erc-channel-users)
557 (maphash (lambda (n cdata) 546 (maphash (lambda (_n cdata)
558 (setq nicks 547 (setq nicks
559 (cons (cons (erc-server-user-nickname (car cdata)) nil) 548 (cons (cons (erc-server-user-nickname (car cdata)) nil)
560 nicks))) 549 nicks)))
@@ -562,21 +551,18 @@ See also: `erc-sort-channel-users-by-activity'"
562 nicks))) 551 nicks)))
563 552
564(defun erc-sort-channel-users-by-activity (list) 553(defun erc-sort-channel-users-by-activity (list)
565 "Sorts LIST such that users which have spoken most recently are 554 "Sort LIST such that users which have spoken most recently are listed first.
566listed first. LIST must be of the form (USER . CHANNEL-DATA). 555LIST must be of the form (USER . CHANNEL-DATA).
567 556
568See also: `erc-get-channel-user-list'." 557See also: `erc-get-channel-user-list'."
569 (sort list 558 (sort list
570 (lambda (x y) 559 (lambda (x y)
571 (when (and 560 (when (and (cdr x) (cdr y))
572 (cdr x) (cdr y))
573 (let ((tx (erc-channel-user-last-message-time (cdr x))) 561 (let ((tx (erc-channel-user-last-message-time (cdr x)))
574 (ty (erc-channel-user-last-message-time (cdr y)))) 562 (ty (erc-channel-user-last-message-time (cdr y))))
575 (if tx 563 (and tx
576 (if ty 564 (or (not ty)
577 (time-less-p ty tx) 565 (time-less-p ty tx))))))))
578 t)
579 nil))))))
580 566
581(defun erc-sort-channel-users-alphabetically (list) 567(defun erc-sort-channel-users-alphabetically (list)
582 "Sort LIST so that users' nicknames are in alphabetical order. 568 "Sort LIST so that users' nicknames are in alphabetical order.
@@ -585,15 +571,12 @@ LIST must be of the form (USER . CHANNEL-DATA).
585See also: `erc-get-channel-user-list'." 571See also: `erc-get-channel-user-list'."
586 (sort list 572 (sort list
587 (lambda (x y) 573 (lambda (x y)
588 (when (and 574 (when (and (cdr x) (cdr y))
589 (cdr x) (cdr y))
590 (let ((nickx (downcase (erc-server-user-nickname (car x)))) 575 (let ((nickx (downcase (erc-server-user-nickname (car x))))
591 (nicky (downcase (erc-server-user-nickname (car y))))) 576 (nicky (downcase (erc-server-user-nickname (car y)))))
592 (if nickx 577 (and nickx
593 (if nicky 578 (or (not nicky)
594 (string-lessp nickx nicky) 579 (string-lessp nickx nicky))))))))
595 t)
596 nil))))))
597 580
598(defvar erc-channel-topic nil 581(defvar erc-channel-topic nil
599 "A topic string for the channel. Should only be used in channel-buffers.") 582 "A topic string for the channel. Should only be used in channel-buffers.")
@@ -678,8 +661,8 @@ Any other value disables notice's highlighting altogether."
678 (const :tag "don't highlight notices at all" nil))) 661 (const :tag "don't highlight notices at all" nil)))
679 662
680(defcustom erc-echo-notice-hook nil 663(defcustom erc-echo-notice-hook nil
681 "Specifies a list of functions to call to echo a private 664 "List of functions to call to echo a private notice.
682notice. Each function is called with four arguments, the string 665Each function is called with four arguments, the string
683to display, the parsed server message, the target buffer (or 666to display, the parsed server message, the target buffer (or
684nil), and the sender. The functions are called in order, until a 667nil), and the sender. The functions are called in order, until a
685function evaluates to non-nil. These hooks are called after 668function evaluates to non-nil. These hooks are called after
@@ -709,8 +692,8 @@ See also: `erc-echo-notice-always-hook',
709 692
710(defcustom erc-echo-notice-always-hook 693(defcustom erc-echo-notice-always-hook
711 '(erc-echo-notice-in-default-buffer) 694 '(erc-echo-notice-in-default-buffer)
712 "Specifies a list of functions to call to echo a private 695 "List of functions to call to echo a private notice.
713notice. Each function is called with four arguments, the string 696Each function is called with four arguments, the string
714to display, the parsed server message, the target buffer (or 697to display, the parsed server message, the target buffer (or
715nil), and the sender. The functions are called in order, and all 698nil), and the sender. The functions are called in order, and all
716functions are called. These hooks are called before those 699functions are called. These hooks are called before those
@@ -1062,9 +1045,9 @@ This function is called with narrowing, ala `erc-send-modify-hook'."
1062 :options '(erc-make-read-only)) 1045 :options '(erc-make-read-only))
1063 1046
1064(defcustom erc-send-completed-hook 1047(defcustom erc-send-completed-hook
1065 (when (featurep 'emacspeak) 1048 (when (fboundp 'emacspeak-auditory-icon)
1066 (list (byte-compile 1049 (list (byte-compile
1067 (lambda (str) 1050 (lambda (_str)
1068 (emacspeak-auditory-icon 'select-object))))) 1051 (emacspeak-auditory-icon 'select-object)))))
1069 "Hook called after a message has been parsed by ERC. 1052 "Hook called after a message has been parsed by ERC.
1070 1053
@@ -1115,10 +1098,7 @@ which the local user typed."
1115 1098
1116 ;; Suppress `font-lock-fontify-block' key binding since it 1099 ;; Suppress `font-lock-fontify-block' key binding since it
1117 ;; destroys face properties. 1100 ;; destroys face properties.
1118 (if (fboundp 'command-remapping) 1101 (define-key map [remap font-lock-fontify-block] 'undefined)
1119 (define-key map [remap font-lock-fontify-block] 'undefined)
1120 (substitute-key-definition
1121 'font-lock-fontify-block 'undefined map global-map))
1122 1102
1123 map) 1103 map)
1124 "ERC keymap.") 1104 "ERC keymap.")
@@ -1277,14 +1257,14 @@ if ARG is omitted or nil.
1277 (put ',enable 'definition-name ',name) 1257 (put ',enable 'definition-name ',name)
1278 (put ',disable 'definition-name ',name)))) 1258 (put ',disable 'definition-name ',name))))
1279 1259
1280(defun erc-once-with-server-event (event &rest forms) 1260(defun erc-once-with-server-event (event f)
1281 "Execute FORMS the next time EVENT occurs in the `current-buffer'. 1261 "Run function F the next time EVENT occurs in the `current-buffer'.
1282 1262
1283You should make sure that `current-buffer' is a server buffer. 1263You should make sure that `current-buffer' is a server buffer.
1284 1264
1285This function temporarily adds a function to EVENT's hook to 1265This function temporarily adds a function to EVENT's hook to call F with
1286execute FORMS. After FORMS are run, the function is removed from 1266two arguments (`proc' and `parsed'). After F is called, the function is
1287EVENT's hook. The last expression of FORMS should be either nil 1267removed from EVENT's hook. F should return either nil
1288or t, where nil indicates that the other functions on EVENT's hook 1268or t, where nil indicates that the other functions on EVENT's hook
1289should be run too, and t indicates that other functions should 1269should be run too, and t indicates that other functions should
1290not be run. 1270not be run.
@@ -1298,35 +1278,14 @@ capabilities."
1298 "You should only run `erc-once-with-server-event' in a server buffer")) 1278 "You should only run `erc-once-with-server-event' in a server buffer"))
1299 (let ((fun (make-symbol "fun")) 1279 (let ((fun (make-symbol "fun"))
1300 (hook (erc-get-hook event))) 1280 (hook (erc-get-hook event)))
1301 (put fun 'erc-original-buffer (current-buffer)) 1281 (put fun 'erc-original-buffer (current-buffer))
1302 (fset fun `(lambda (proc parsed) 1282 (fset fun (lambda (proc parsed)
1303 (with-current-buffer (get ',fun 'erc-original-buffer) 1283 (with-current-buffer (get fun 'erc-original-buffer)
1304 (remove-hook ',hook ',fun t)) 1284 (remove-hook hook fun t))
1305 (fmakunbound ',fun) 1285 (fmakunbound fun)
1306 ,@forms)) 1286 (funcall f proc parsed)))
1307 (add-hook hook fun nil t) 1287 (add-hook hook fun nil t)
1308 fun)) 1288 fun))
1309
1310(defun erc-once-with-server-event-global (event &rest forms)
1311 "Execute FORMS the next time EVENT occurs in any server buffer.
1312
1313This function temporarily prepends a function to EVENT's hook to
1314execute FORMS. After FORMS are run, the function is removed from
1315EVENT's hook. The last expression of FORMS should be either nil
1316or t, where nil indicates that the other functions on EVENT's hook
1317should be run too, and t indicates that other functions should
1318not be run.
1319
1320When FORMS execute, the current buffer is the server buffer associated with the
1321connection over which the data was received that triggered EVENT."
1322 (let ((fun (make-symbol "fun"))
1323 (hook (erc-get-hook event)))
1324 (fset fun `(lambda (proc parsed)
1325 (remove-hook ',hook ',fun)
1326 (fmakunbound ',fun)
1327 ,@forms))
1328 (add-hook hook fun nil nil)
1329 fun))
1330 1289
1331(defsubst erc-log (string) 1290(defsubst erc-log (string)
1332 "Logs STRING if logging is on (see `erc-log-p')." 1291 "Logs STRING if logging is on (see `erc-log-p')."
@@ -1353,7 +1312,7 @@ If BUFFER is nil, the current buffer is used."
1353 (and (eq major-mode 'erc-mode) 1312 (and (eq major-mode 'erc-mode)
1354 (null (erc-default-target))))) 1313 (null (erc-default-target)))))
1355 1314
1356(defun erc-open-server-buffer-p (&optional buffer) 1315(defun erc-open-server-buffer-p (&optional buffer) ;FIXME: `buffer' is ignored!
1357 "Return non-nil if argument BUFFER is an ERC server buffer that 1316 "Return non-nil if argument BUFFER is an ERC server buffer that
1358has an open IRC process. 1317has an open IRC process.
1359 1318
@@ -1377,9 +1336,10 @@ If BUFFER is nil, the current buffer is used."
1377 (let ((erc-online-p 'unknown)) 1336 (let ((erc-online-p 'unknown))
1378 (erc-once-with-server-event 1337 (erc-once-with-server-event
1379 303 1338 303
1380 `(let ((ison (split-string (aref parsed 3)))) 1339 (lambda (_proc parsed)
1381 (setq erc-online-p (car (erc-member-ignore-case ,nick ison))) 1340 (let ((ison (split-string (aref parsed 3))))
1382 t)) 1341 (setq erc-online-p (car (erc-member-ignore-case nick ison)))
1342 t)))
1383 (erc-server-send (format "ISON %s" nick)) 1343 (erc-server-send (format "ISON %s" nick))
1384 (while (eq erc-online-p 'unknown) (accept-process-output)) 1344 (while (eq erc-online-p 'unknown) (accept-process-output))
1385 (if (called-interactively-p 'interactive) 1345 (if (called-interactively-p 'interactive)
@@ -1551,7 +1511,7 @@ symbol, it may have these values:
1551 "Check whether ports A and B are equal." 1511 "Check whether ports A and B are equal."
1552 (= (erc-normalize-port a) (erc-normalize-port b))) 1512 (= (erc-normalize-port a) (erc-normalize-port b)))
1553 1513
1554(defun erc-generate-new-buffer-name (server port target &optional proc) 1514(defun erc-generate-new-buffer-name (server port target)
1555 "Create a new buffer name based on the arguments." 1515 "Create a new buffer name based on the arguments."
1556 (when (numberp port) (setq port (number-to-string port))) 1516 (when (numberp port) (setq port (number-to-string port)))
1557 (let ((buf-name (or target 1517 (let ((buf-name (or target
@@ -1582,9 +1542,9 @@ symbol, it may have these values:
1582 ;; fallback to the old <N> uniquification method: 1542 ;; fallback to the old <N> uniquification method:
1583 (or buffer-name (generate-new-buffer-name buf-name)) )) 1543 (or buffer-name (generate-new-buffer-name buf-name)) ))
1584 1544
1585(defun erc-get-buffer-create (server port target &optional proc) 1545(defun erc-get-buffer-create (server port target)
1586 "Create a new buffer based on the arguments." 1546 "Create a new buffer based on the arguments."
1587 (get-buffer-create (erc-generate-new-buffer-name server port target proc))) 1547 (get-buffer-create (erc-generate-new-buffer-name server port target)))
1588 1548
1589 1549
1590(defun erc-member-ignore-case (string list) 1550(defun erc-member-ignore-case (string list)
@@ -1700,6 +1660,7 @@ nil."
1700(defvar iswitchb-temp-buflist) 1660(defvar iswitchb-temp-buflist)
1701(declare-function iswitchb-read-buffer "iswitchb" 1661(declare-function iswitchb-read-buffer "iswitchb"
1702 (prompt &optional default require-match start matches-set)) 1662 (prompt &optional default require-match start matches-set))
1663(defvar iswitchb-make-buflist-hook)
1703 1664
1704(defun erc-iswitchb (&optional arg) 1665(defun erc-iswitchb (&optional arg)
1705 "Use `iswitchb-read-buffer' to prompt for a ERC buffer to switch to. 1666 "Use `iswitchb-read-buffer' to prompt for a ERC buffer to switch to.
@@ -1906,29 +1867,29 @@ removed from the list will be disabled."
1906 1867
1907(defun erc-setup-buffer (buffer) 1868(defun erc-setup-buffer (buffer)
1908 "Consults `erc-join-buffer' to find out how to display `BUFFER'." 1869 "Consults `erc-join-buffer' to find out how to display `BUFFER'."
1909 (cond ((eq erc-join-buffer 'window) 1870 (pcase erc-join-buffer
1910 (if (active-minibuffer-window) 1871 (`window
1911 (display-buffer buffer) 1872 (if (active-minibuffer-window)
1912 (switch-to-buffer-other-window buffer))) 1873 (display-buffer buffer)
1913 ((eq erc-join-buffer 'window-noselect) 1874 (switch-to-buffer-other-window buffer)))
1914 (display-buffer buffer)) 1875 (`window-noselect
1915 ((eq erc-join-buffer 'bury) 1876 (display-buffer buffer))
1916 nil) 1877 (`bury
1917 ((eq erc-join-buffer 'frame) 1878 nil)
1918 (when (or (not erc-reuse-frames) 1879 (`frame
1919 (not (get-buffer-window buffer t))) 1880 (when (or (not erc-reuse-frames)
1920 ((lambda (frame) 1881 (not (get-buffer-window buffer t)))
1921 (raise-frame frame) 1882 (let ((frame (make-frame (or erc-frame-alist
1922 (select-frame frame)) 1883 default-frame-alist))))
1923 (make-frame (or erc-frame-alist 1884 (raise-frame frame)
1924 default-frame-alist))) 1885 (select-frame frame))
1925 (switch-to-buffer buffer) 1886 (switch-to-buffer buffer)
1926 (when erc-frame-dedicated-flag 1887 (when erc-frame-dedicated-flag
1927 (set-window-dedicated-p (selected-window) t)))) 1888 (set-window-dedicated-p (selected-window) t))))
1928 (t 1889 (_
1929 (if (active-minibuffer-window) 1890 (if (active-minibuffer-window)
1930 (display-buffer buffer) 1891 (display-buffer buffer)
1931 (switch-to-buffer buffer))))) 1892 (switch-to-buffer buffer)))))
1932 1893
1933(defun erc-open (&optional server port nick full-name 1894(defun erc-open (&optional server port nick full-name
1934 connect passwd tgt-list channel process) 1895 connect passwd tgt-list channel process)
@@ -2006,19 +1967,20 @@ Returns the buffer for the given server or channel."
2006 ;; The local copy of `erc-nick' - the list of nicks to choose 1967 ;; The local copy of `erc-nick' - the list of nicks to choose
2007 (setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick))) 1968 (setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick)))
2008 ;; password stuff 1969 ;; password stuff
2009 (setq erc-session-password (or passwd 1970 (setq erc-session-password
2010 (let ((secret 1971 (or passwd
2011 (plist-get 1972 (let ((secret
2012 (nth 0 1973 (plist-get
2013 (auth-source-search :host server 1974 (nth 0
2014 :max 1 1975 (auth-source-search :host server
2015 :user nick 1976 :max 1
2016 :port port 1977 :user nick
2017 :require '(:secret))) 1978 :port port
2018 :secret))) 1979 :require '(:secret)))
2019 (if (functionp secret) 1980 :secret)))
2020 (funcall secret) 1981 (if (functionp secret)
2021 secret)))) 1982 (funcall secret)
1983 secret))))
2022 ;; debug output buffer 1984 ;; debug output buffer
2023 (setq erc-dbuf 1985 (setq erc-dbuf
2024 (when erc-log-p 1986 (when erc-log-p
@@ -2080,11 +2042,6 @@ If no buffer matches, return nil."
2080 (erc-port-equal erc-session-port port) 2042 (erc-port-equal erc-session-port port)
2081 (erc-current-nick-p nick))))) 2043 (erc-current-nick-p nick)))))
2082 2044
2083(if (not (fboundp 'read-passwd))
2084 (defun read-passwd (prompt)
2085 "Substitute for `read-passwd' in early emacsen."
2086 (read-from-minibuffer prompt)))
2087
2088(defcustom erc-before-connect nil 2045(defcustom erc-before-connect nil
2089 "Hook called before connecting to a server. 2046 "Hook called before connecting to a server.
2090This hook gets executed before `erc' actually invokes `erc-mode' 2047This hook gets executed before `erc' actually invokes `erc-mode'
@@ -2433,11 +2390,11 @@ If STRING is nil, the function does nothing."
2433 (t (list (current-buffer))))) 2390 (t (list (current-buffer)))))
2434 (when (buffer-live-p buf) 2391 (when (buffer-live-p buf)
2435 (erc-display-line-1 string buf) 2392 (erc-display-line-1 string buf)
2436 (add-to-list 'new-bufs buf))) 2393 (push buf new-bufs)))
2437 (when (null new-bufs) 2394 (when (null new-bufs)
2438 (if (erc-server-buffer-live-p) 2395 (erc-display-line-1 string (if (erc-server-buffer-live-p)
2439 (erc-display-line-1 string (process-buffer erc-server-process)) 2396 (process-buffer erc-server-process)
2440 (erc-display-line-1 string (current-buffer)))))) 2397 (current-buffer))))))
2441 2398
2442(defun erc-display-message-highlight (type string) 2399(defun erc-display-message-highlight (type string)
2443 "Highlight STRING according to TYPE, where erc-TYPE-face is an ERC face. 2400 "Highlight STRING according to TYPE, where erc-TYPE-face is an ERC face.
@@ -2544,7 +2501,7 @@ consumption for long-lived IRC or Emacs sessions."
2544 "Internal counter variable for use with `erc-lurker-cleanup-interval'.") 2501 "Internal counter variable for use with `erc-lurker-cleanup-interval'.")
2545 2502
2546(defvar erc-lurker-cleanup-interval 100 2503(defvar erc-lurker-cleanup-interval 100
2547 "Specifies frequency of cleaning up stale erc-lurker state. 2504 "Frequency of cleaning up stale erc-lurker state.
2548 2505
2549`erc-lurker-update-status' calls `erc-lurker-cleanup' once for 2506`erc-lurker-update-status' calls `erc-lurker-cleanup' once for
2550every `erc-lurker-cleanup-interval' updates to 2507every `erc-lurker-cleanup-interval' updates to
@@ -2552,7 +2509,7 @@ every `erc-lurker-cleanup-interval' updates to
2552consumption of lurker state during long Emacs sessions and/or ERC 2509consumption of lurker state during long Emacs sessions and/or ERC
2553sessions with large numbers of incoming PRIVMSGs.") 2510sessions with large numbers of incoming PRIVMSGs.")
2554 2511
2555(defun erc-lurker-update-status (message) 2512(defun erc-lurker-update-status (_message)
2556 "Update `erc-lurker-state' if necessary. 2513 "Update `erc-lurker-state' if necessary.
2557 2514
2558This function is called from `erc-insert-pre-hook'. If the 2515This function is called from `erc-insert-pre-hook'. If the
@@ -2614,7 +2571,7 @@ displayed hostnames."
2614 :type 'alist) 2571 :type 'alist)
2615 2572
2616(defun erc-canonicalize-server-name (server) 2573(defun erc-canonicalize-server-name (server)
2617 "Returns the canonical network name for SERVER if any, 2574 "Return the canonical network name for SERVER if any,
2618otherwise `erc-server-announced-name'. SERVER is matched against 2575otherwise `erc-server-announced-name'. SERVER is matched against
2619`erc-common-server-suffixes'." 2576`erc-common-server-suffixes'."
2620 (when server 2577 (when server
@@ -2877,7 +2834,7 @@ If no USER argument is specified, list the contents of `erc-ignore-list'."
2877 (interactive) 2834 (interactive)
2878 (let ((ops nil)) 2835 (let ((ops nil))
2879 (if erc-channel-users 2836 (if erc-channel-users
2880 (maphash (lambda (nick user-data) 2837 (maphash (lambda (_nick user-data)
2881 (let ((cuser (cdr user-data))) 2838 (let ((cuser (cdr user-data)))
2882 (if (and cuser 2839 (if (and cuser
2883 (erc-channel-user-op cuser)) 2840 (erc-channel-user-op cuser))
@@ -3007,9 +2964,9 @@ were most recently invited. See also `invitation'."
3007 (switch-to-buffer (car (erc-member-ignore-case chnl 2964 (switch-to-buffer (car (erc-member-ignore-case chnl
3008 joined-channels))) 2965 joined-channels)))
3009 (erc-log (format "cmd: JOIN: %s" chnl)) 2966 (erc-log (format "cmd: JOIN: %s" chnl))
3010 (if (and chnl key) 2967 (erc-server-send (if (and chnl key)
3011 (erc-server-send (format "JOIN %s %s" chnl key)) 2968 (format "JOIN %s %s" chnl key)
3012 (erc-server-send (format "JOIN %s" chnl))))))) 2969 (format "JOIN %s" chnl)))))))
3013 t) 2970 t)
3014 2971
3015(defalias 'erc-cmd-CHANNEL 'erc-cmd-JOIN) 2972(defalias 'erc-cmd-CHANNEL 'erc-cmd-JOIN)
@@ -3120,68 +3077,76 @@ If SERVER is non-nil, use that, rather than the current server."
3120 (let ((origbuf (current-buffer)) 3077 (let ((origbuf (current-buffer))
3121 symlist) 3078 symlist)
3122 (erc-with-server-buffer 3079 (erc-with-server-buffer
3123 (add-to-list 'symlist 3080 (push (cons (erc-once-with-server-event
3124 (cons (erc-once-with-server-event 3081 311 (lambda (_proc parsed)
3125 311 `(string= ,nick 3082 (string= nick
3126 (nth 1 3083 (nth 1 (erc-response.command-args
3127 (erc-response.command-args parsed)))) 3084 parsed)))))
3128 'erc-server-311-functions)) 3085 'erc-server-311-functions)
3129 (add-to-list 'symlist 3086 symlist)
3130 (cons (erc-once-with-server-event 3087 (push (cons (erc-once-with-server-event
3131 312 `(string= ,nick 3088 312 (lambda (_proc parsed)
3132 (nth 1 3089 (string= nick
3133 (erc-response.command-args parsed)))) 3090 (nth 1 (erc-response.command-args
3134 'erc-server-312-functions)) 3091 parsed)))))
3135 (add-to-list 'symlist 3092 'erc-server-312-functions)
3136 (cons (erc-once-with-server-event 3093 symlist)
3137 318 `(string= ,nick 3094 (push (cons (erc-once-with-server-event
3138 (nth 1 3095 318 (lambda (_proc parsed)
3139 (erc-response.command-args parsed)))) 3096 (string= nick
3140 'erc-server-318-functions)) 3097 (nth 1 (erc-response.command-args
3141 (add-to-list 'symlist 3098 parsed)))))
3142 (cons (erc-once-with-server-event 3099 'erc-server-318-functions)
3143 319 `(string= ,nick 3100 symlist)
3144 (nth 1 3101 (push (cons (erc-once-with-server-event
3145 (erc-response.command-args parsed)))) 3102 319 (lambda (_proc parsed)
3146 'erc-server-319-functions)) 3103 (string= nick
3147 (add-to-list 'symlist 3104 (nth 1 (erc-response.command-args
3148 (cons (erc-once-with-server-event 3105 parsed)))))
3149 320 `(string= ,nick 3106 'erc-server-319-functions)
3150 (nth 1 3107 symlist)
3151 (erc-response.command-args parsed)))) 3108 (push (cons (erc-once-with-server-event
3152 'erc-server-320-functions)) 3109 320 (lambda (_proc parsed)
3153 (add-to-list 'symlist 3110 (string= nick
3154 (cons (erc-once-with-server-event 3111 (nth 1 (erc-response.command-args
3155 330 `(string= ,nick 3112 parsed)))))
3156 (nth 1 3113 'erc-server-320-functions)
3157 (erc-response.command-args parsed)))) 3114 symlist)
3158 'erc-server-330-functions)) 3115 (push (cons (erc-once-with-server-event
3159 (add-to-list 'symlist 3116 330 (lambda (_proc parsed)
3160 (cons (erc-once-with-server-event 3117 (string= nick
3161 317 3118 (nth 1 (erc-response.command-args
3162 `(let ((idleseconds 3119 parsed)))))
3163 (string-to-number 3120 'erc-server-330-functions)
3164 (third 3121 symlist)
3165 (erc-response.command-args parsed))))) 3122 (push (cons (erc-once-with-server-event
3166 (erc-display-line 3123 317
3167 (erc-make-notice 3124 (lambda (_proc parsed)
3168 (format "%s has been idle for %s." 3125 (let ((idleseconds
3169 (erc-string-no-properties ,nick) 3126 (string-to-number
3170 (erc-seconds-to-string idleseconds))) 3127 (cl-third
3171 ,origbuf)) 3128 (erc-response.command-args parsed)))))
3172 t) 3129 (erc-display-line
3173 'erc-server-317-functions)) 3130 (erc-make-notice
3174 3131 (format "%s has been idle for %s."
3175 ;; Send the WHOIS command. 3132 (erc-string-no-properties nick)
3176 (erc-cmd-WHOIS nick) 3133 (erc-seconds-to-string idleseconds)))
3177 3134 origbuf)
3178 ;; Remove the uninterned symbols from the server hooks that did not run. 3135 t)))
3179 (run-at-time 20 nil `(lambda () 3136 'erc-server-317-functions)
3180 (with-current-buffer ,(current-buffer) 3137 symlist)
3181 (dolist (sym ',symlist) 3138
3182 (let ((hooksym (cdr sym)) 3139 ;; Send the WHOIS command.
3183 (funcsym (car sym))) 3140 (erc-cmd-WHOIS nick)
3184 (remove-hook hooksym funcsym t)))))))) 3141
3142 ;; Remove the uninterned symbols from the server hooks that did not run.
3143 (run-at-time 20 nil (lambda (buf symlist)
3144 (with-current-buffer buf
3145 (dolist (sym symlist)
3146 (let ((hooksym (cdr sym))
3147 (funcsym (car sym)))
3148 (remove-hook hooksym funcsym t)))))
3149 (current-buffer) symlist)))
3185 t) 3150 t)
3186 3151
3187(defun erc-cmd-DESCRIBE (line) 3152(defun erc-cmd-DESCRIBE (line)
@@ -3690,11 +3655,12 @@ The ban list is fetched from the server if necessary."
3690 (erc-with-server-buffer 3655 (erc-with-server-buffer
3691 (erc-once-with-server-event 3656 (erc-once-with-server-event
3692 368 3657 368
3693 `(with-current-buffer ,chnl-name 3658 (lambda (_proc _parsed)
3659 (with-current-buffer chnl-name
3694 (put 'erc-channel-banlist 'received-from-server t) 3660 (put 'erc-channel-banlist 'received-from-server t)
3695 (setq erc-server-367-functions ',old-367-hook) 3661 (setq erc-server-367-functions old-367-hook)
3696 (erc-cmd-BANLIST) 3662 (erc-cmd-BANLIST)
3697 t)) 3663 t)))
3698 (erc-server-send (format "MODE %s b" chnl))))) 3664 (erc-server-send (format "MODE %s b" chnl)))))
3699 3665
3700 ((null erc-channel-banlist) 3666 ((null erc-channel-banlist)
@@ -3756,28 +3722,29 @@ Unban all currently banned users in the current channel."
3756 ((not (get 'erc-channel-banlist 'received-from-server)) 3722 ((not (get 'erc-channel-banlist 'received-from-server))
3757 (let ((old-367-hook erc-server-367-functions)) 3723 (let ((old-367-hook erc-server-367-functions))
3758 (setq erc-server-367-functions 'erc-banlist-store) 3724 (setq erc-server-367-functions 'erc-banlist-store)
3759 ;; fetch the ban list then callback 3725 ;; fetch the ban list then callback
3760 (erc-with-server-buffer 3726 (erc-with-server-buffer
3761 (erc-once-with-server-event 3727 (erc-once-with-server-event
3762 368 3728 368
3763 `(with-current-buffer ,chnl 3729 (lambda (_proc _parsed)
3764 (put 'erc-channel-banlist 'received-from-server t) 3730 (with-current-buffer chnl
3765 (setq erc-server-367-functions ,old-367-hook) 3731 (put 'erc-channel-banlist 'received-from-server t)
3766 (erc-cmd-MASSUNBAN) 3732 (setq erc-server-367-functions old-367-hook)
3767 t)) 3733 (erc-cmd-MASSUNBAN)
3768 (erc-server-send (format "MODE %s b" chnl))))) 3734 t)))
3735 (erc-server-send (format "MODE %s b" chnl)))))
3769 3736
3770 (t (let ((bans (mapcar 'cdr erc-channel-banlist))) 3737 (t (let ((bans (mapcar 'cdr erc-channel-banlist)))
3771 (when bans 3738 (when bans
3772 ;; Glob the bans into groups of three, and carry out the unban. 3739 ;; Glob the bans into groups of three, and carry out the unban.
3773 ;; eg. /mode #foo -bbb a*!*@* b*!*@* c*!*@* 3740 ;; eg. /mode #foo -bbb a*!*@* b*!*@* c*!*@*
3774 (mapc 3741 (mapc
3775 (lambda (x) 3742 (lambda (x)
3776 (erc-server-send 3743 (erc-server-send
3777 (format "MODE %s -%s %s" (erc-default-target) 3744 (format "MODE %s -%s %s" (erc-default-target)
3778 (make-string (length x) ?b) 3745 (make-string (length x) ?b)
3779 (mapconcat 'identity x " ")))) 3746 (mapconcat 'identity x " "))))
3780 (erc-group-list bans 3)))) 3747 (erc-group-list bans 3))))
3781 t)))) 3748 t))))
3782 3749
3783(defalias 'erc-cmd-MUB 'erc-cmd-MASSUNBAN) 3750(defalias 'erc-cmd-MUB 'erc-cmd-MASSUNBAN)
@@ -3933,9 +3900,9 @@ Prompt for one if called interactively."
3933 (format "Limit for %s (RET to remove limit): " 3900 (format "Limit for %s (RET to remove limit): "
3934 (erc-default-target))))) 3901 (erc-default-target)))))
3935 (let ((tgt (erc-default-target))) 3902 (let ((tgt (erc-default-target)))
3936 (if (and limit (>= (length limit) 1)) 3903 (erc-server-send (if (and limit (>= (length limit) 1))
3937 (erc-server-send (format "MODE %s +l %s" tgt limit)) 3904 (format "MODE %s +l %s" tgt limit)
3938 (erc-server-send (format "MODE %s -l" tgt))))) 3905 (format "MODE %s -l" tgt)))))
3939 3906
3940(defun erc-set-channel-key (&optional key) 3907(defun erc-set-channel-key (&optional key)
3941 "Set a KEY for the current channel. Remove key if nil. 3908 "Set a KEY for the current channel. Remove key if nil.
@@ -3944,9 +3911,9 @@ Prompt for one if called interactively."
3944 (format "Key for %s (RET to remove key): " 3911 (format "Key for %s (RET to remove key): "
3945 (erc-default-target))))) 3912 (erc-default-target)))))
3946 (let ((tgt (erc-default-target))) 3913 (let ((tgt (erc-default-target)))
3947 (if (and key (>= (length key) 1)) 3914 (erc-server-send (if (and key (>= (length key) 1))
3948 (erc-server-send (format "MODE %s +k %s" tgt key)) 3915 (format "MODE %s +k %s" tgt key)
3949 (erc-server-send (format "MODE %s -k" tgt))))) 3916 (format "MODE %s -k" tgt)))))
3950 3917
3951(defun erc-quit-server (reason) 3918(defun erc-quit-server (reason)
3952 "Disconnect from current server after prompting for REASON. 3919 "Disconnect from current server after prompting for REASON.
@@ -4023,7 +3990,7 @@ Displays PROC and PARSED appropriately using `erc-display-message'."
4023See `erc-debug-missing-hooks'.") 3990See `erc-debug-missing-hooks'.")
4024;(make-variable-buffer-local 'erc-server-vectors) 3991;(make-variable-buffer-local 'erc-server-vectors)
4025 3992
4026(defun erc-debug-missing-hooks (proc parsed) 3993(defun erc-debug-missing-hooks (_proc parsed)
4027 "Add PARSED server message ERC does not yet handle to `erc-server-vectors'. 3994 "Add PARSED server message ERC does not yet handle to `erc-server-vectors'.
4028These vectors can be helpful when adding new server message handlers to ERC. 3995These vectors can be helpful when adding new server message handlers to ERC.
4029See `erc-default-server-hook'." 3996See `erc-default-server-hook'."
@@ -4163,7 +4130,7 @@ originated from,
4163and as second argument the event parsed as a vector." 4130and as second argument the event parsed as a vector."
4164 :group 'erc-hooks) 4131 :group 'erc-hooks)
4165 4132
4166(defun erc-display-server-message (proc parsed) 4133(defun erc-display-server-message (_proc parsed)
4167 "Display the message sent by the server as a notice." 4134 "Display the message sent by the server as a notice."
4168 (erc-display-message 4135 (erc-display-message
4169 parsed 'notice 'active (erc-response.contents parsed))) 4136 parsed 'notice 'active (erc-response.contents parsed)))
@@ -4219,7 +4186,7 @@ and as second argument the event parsed as a vector."
4219 :group 'erc-display 4186 :group 'erc-display
4220 :type 'function) 4187 :type 'function)
4221 4188
4222(defun erc-format-nick (&optional user channel-data) 4189(defun erc-format-nick (&optional user _channel-data)
4223 "Return the nickname of USER. 4190 "Return the nickname of USER.
4224See also `erc-format-nick-function'." 4191See also `erc-format-nick-function'."
4225 (when user (erc-server-user-nickname user))) 4192 (when user (erc-server-user-nickname user)))
@@ -4247,7 +4214,7 @@ See also `erc-format-nick-function'."
4247 (let ((prefix "> ")) 4214 (let ((prefix "> "))
4248 (erc-propertize prefix 'face 'erc-default-face)))) 4215 (erc-propertize prefix 'face 'erc-default-face))))
4249 4216
4250(defun erc-echo-notice-in-default-buffer (s parsed buffer sender) 4217(defun erc-echo-notice-in-default-buffer (s parsed buffer _sender)
4251 "Echos a private notice in the default buffer, namely the 4218 "Echos a private notice in the default buffer, namely the
4252target buffer specified by BUFFER, or there is no target buffer, 4219target buffer specified by BUFFER, or there is no target buffer,
4253the server buffer. This function is designed to be added to 4220the server buffer. This function is designed to be added to
@@ -4256,7 +4223,7 @@ and always returns t."
4256 (erc-display-message parsed nil buffer s) 4223 (erc-display-message parsed nil buffer s)
4257 t) 4224 t)
4258 4225
4259(defun erc-echo-notice-in-target-buffer (s parsed buffer sender) 4226(defun erc-echo-notice-in-target-buffer (s parsed buffer _sender)
4260 "Echos a private notice in BUFFER, if BUFFER is non-nil. This 4227 "Echos a private notice in BUFFER, if BUFFER is non-nil. This
4261function is designed to be added to either `erc-echo-notice-hook' 4228function is designed to be added to either `erc-echo-notice-hook'
4262or `erc-echo-notice-always-hook', and returns non-nil if BUFFER 4229or `erc-echo-notice-always-hook', and returns non-nil if BUFFER
@@ -4265,21 +4232,21 @@ is non-nil."
4265 (progn (erc-display-message parsed nil buffer s) t) 4232 (progn (erc-display-message parsed nil buffer s) t)
4266 nil)) 4233 nil))
4267 4234
4268(defun erc-echo-notice-in-minibuffer (s parsed buffer sender) 4235(defun erc-echo-notice-in-minibuffer (s _parsed _buffer _sender)
4269 "Echos a private notice in the minibuffer. This function is 4236 "Echos a private notice in the minibuffer. This function is
4270designed to be added to either `erc-echo-notice-hook' or 4237designed to be added to either `erc-echo-notice-hook' or
4271`erc-echo-notice-always-hook', and always returns t." 4238`erc-echo-notice-always-hook', and always returns t."
4272 (message "%s" (concat "NOTICE: " s)) 4239 (message "%s" (concat "NOTICE: " s))
4273 t) 4240 t)
4274 4241
4275(defun erc-echo-notice-in-server-buffer (s parsed buffer sender) 4242(defun erc-echo-notice-in-server-buffer (s parsed _buffer _sender)
4276 "Echos a private notice in the server buffer. This function is 4243 "Echos a private notice in the server buffer. This function is
4277designed to be added to either `erc-echo-notice-hook' or 4244designed to be added to either `erc-echo-notice-hook' or
4278`erc-echo-notice-always-hook', and always returns t." 4245`erc-echo-notice-always-hook', and always returns t."
4279 (erc-display-message parsed nil nil s) 4246 (erc-display-message parsed nil nil s)
4280 t) 4247 t)
4281 4248
4282(defun erc-echo-notice-in-active-non-server-buffer (s parsed buffer sender) 4249(defun erc-echo-notice-in-active-non-server-buffer (s parsed _buffer _sender)
4283 "Echos a private notice in the active buffer if the active 4250 "Echos a private notice in the active buffer if the active
4284buffer is not the server buffer. This function is designed to be 4251buffer is not the server buffer. This function is designed to be
4285added to either `erc-echo-notice-hook' or 4252added to either `erc-echo-notice-hook' or
@@ -4289,14 +4256,14 @@ buffer is not the server buffer."
4289 (progn (erc-display-message parsed nil 'active s) t) 4256 (progn (erc-display-message parsed nil 'active s) t)
4290 nil)) 4257 nil))
4291 4258
4292(defun erc-echo-notice-in-active-buffer (s parsed buffer sender) 4259(defun erc-echo-notice-in-active-buffer (s parsed _buffer _sender)
4293 "Echos a private notice in the active buffer. This function is 4260 "Echos a private notice in the active buffer. This function is
4294designed to be added to either `erc-echo-notice-hook' or 4261designed to be added to either `erc-echo-notice-hook' or
4295`erc-echo-notice-always-hook', and always returns t." 4262`erc-echo-notice-always-hook', and always returns t."
4296 (erc-display-message parsed nil 'active s) 4263 (erc-display-message parsed nil 'active s)
4297 t) 4264 t)
4298 4265
4299(defun erc-echo-notice-in-user-buffers (s parsed buffer sender) 4266(defun erc-echo-notice-in-user-buffers (s parsed _buffer sender)
4300 "Echos a private notice in all of the buffers for which SENDER 4267 "Echos a private notice in all of the buffers for which SENDER
4301is a member. This function is designed to be added to either 4268is a member. This function is designed to be added to either
4302`erc-echo-notice-hook' or `erc-echo-notice-always-hook', and 4269`erc-echo-notice-hook' or `erc-echo-notice-always-hook', and
@@ -4321,12 +4288,12 @@ default target.
4321See also: `erc-echo-notice-in-user-buffers', 4288See also: `erc-echo-notice-in-user-buffers',
4322`erc-buffer-list-with-nick'." 4289`erc-buffer-list-with-nick'."
4323 (let ((buffers (erc-buffer-list-with-nick sender erc-server-process))) 4290 (let ((buffers (erc-buffer-list-with-nick sender erc-server-process)))
4324 (add-to-list 'buffers buffer) 4291 (unless (memq buffer buffers) (push buffer buffers))
4325 (if buffers 4292 (if buffers ;FIXME: How could it be nil?
4326 (progn (erc-display-message parsed nil buffers s) t) 4293 (progn (erc-display-message parsed nil buffers s) t)
4327 nil))) 4294 nil)))
4328 4295
4329(defun erc-echo-notice-in-first-user-buffer (s parsed buffer sender) 4296(defun erc-echo-notice-in-first-user-buffer (s parsed _buffer sender)
4330 "Echos a private notice in one of the buffers for which SENDER 4297 "Echos a private notice in one of the buffers for which SENDER
4331is a member. This function is designed to be added to either 4298is a member. This function is designed to be added to either
4332`erc-echo-notice-hook' or `erc-echo-notice-always-hook', and 4299`erc-echo-notice-hook' or `erc-echo-notice-always-hook', and
@@ -4504,7 +4471,7 @@ See also `erc-display-message'."
4504 4471
4505(defvar erc-ctcp-query-CLIENTINFO-hook '(erc-ctcp-query-CLIENTINFO)) 4472(defvar erc-ctcp-query-CLIENTINFO-hook '(erc-ctcp-query-CLIENTINFO))
4506 4473
4507(defun erc-ctcp-query-CLIENTINFO (proc nick login host to msg) 4474(defun erc-ctcp-query-CLIENTINFO (_proc nick _login _host _to msg)
4508 "Respond to a CTCP CLIENTINFO query." 4475 "Respond to a CTCP CLIENTINFO query."
4509 (when (string-match "^CLIENTINFO\\(\\s-*\\|\\s-+.*\\)$" msg) 4476 (when (string-match "^CLIENTINFO\\(\\s-*\\|\\s-+.*\\)$" msg)
4510 (let ((s (erc-client-info (erc-trim-string (match-string 1 msg))))) 4477 (let ((s (erc-client-info (erc-trim-string (match-string 1 msg)))))
@@ -4513,7 +4480,7 @@ See also `erc-display-message'."
4513 nil) 4480 nil)
4514 4481
4515(defvar erc-ctcp-query-ECHO-hook '(erc-ctcp-query-ECHO)) 4482(defvar erc-ctcp-query-ECHO-hook '(erc-ctcp-query-ECHO))
4516(defun erc-ctcp-query-ECHO (proc nick login host to msg) 4483(defun erc-ctcp-query-ECHO (_proc nick _login _host _to msg)
4517 "Respond to a CTCP ECHO query." 4484 "Respond to a CTCP ECHO query."
4518 (when (string-match "^ECHO\\s-+\\(.*\\)\\s-*$" msg) 4485 (when (string-match "^ECHO\\s-+\\(.*\\)\\s-*$" msg)
4519 (let ((s (match-string 1 msg))) 4486 (let ((s (match-string 1 msg)))
@@ -4522,7 +4489,7 @@ See also `erc-display-message'."
4522 nil) 4489 nil)
4523 4490
4524(defvar erc-ctcp-query-FINGER-hook '(erc-ctcp-query-FINGER)) 4491(defvar erc-ctcp-query-FINGER-hook '(erc-ctcp-query-FINGER))
4525(defun erc-ctcp-query-FINGER (proc nick login host to msg) 4492(defun erc-ctcp-query-FINGER (_proc nick _login _host _to _msg)
4526 "Respond to a CTCP FINGER query." 4493 "Respond to a CTCP FINGER query."
4527 (unless erc-disable-ctcp-replies 4494 (unless erc-disable-ctcp-replies
4528 (let ((s (if erc-anonymous-login 4495 (let ((s (if erc-anonymous-login
@@ -4538,7 +4505,7 @@ See also `erc-display-message'."
4538 nil) 4505 nil)
4539 4506
4540(defvar erc-ctcp-query-PING-hook '(erc-ctcp-query-PING)) 4507(defvar erc-ctcp-query-PING-hook '(erc-ctcp-query-PING))
4541(defun erc-ctcp-query-PING (proc nick login host to msg) 4508(defun erc-ctcp-query-PING (_proc nick _login _host _to msg)
4542 "Respond to a CTCP PING query." 4509 "Respond to a CTCP PING query."
4543 (when (string-match "^PING\\s-+\\(.*\\)" msg) 4510 (when (string-match "^PING\\s-+\\(.*\\)" msg)
4544 (unless erc-disable-ctcp-replies 4511 (unless erc-disable-ctcp-replies
@@ -4547,21 +4514,21 @@ See also `erc-display-message'."
4547 nil) 4514 nil)
4548 4515
4549(defvar erc-ctcp-query-TIME-hook '(erc-ctcp-query-TIME)) 4516(defvar erc-ctcp-query-TIME-hook '(erc-ctcp-query-TIME))
4550(defun erc-ctcp-query-TIME (proc nick login host to msg) 4517(defun erc-ctcp-query-TIME (_proc nick _login _host _to _msg)
4551 "Respond to a CTCP TIME query." 4518 "Respond to a CTCP TIME query."
4552 (unless erc-disable-ctcp-replies 4519 (unless erc-disable-ctcp-replies
4553 (erc-send-ctcp-notice nick (format "TIME %s" (current-time-string)))) 4520 (erc-send-ctcp-notice nick (format "TIME %s" (current-time-string))))
4554 nil) 4521 nil)
4555 4522
4556(defvar erc-ctcp-query-USERINFO-hook '(erc-ctcp-query-USERINFO)) 4523(defvar erc-ctcp-query-USERINFO-hook '(erc-ctcp-query-USERINFO))
4557(defun erc-ctcp-query-USERINFO (proc nick login host to msg) 4524(defun erc-ctcp-query-USERINFO (_proc nick _login _host _to _msg)
4558 "Respond to a CTCP USERINFO query." 4525 "Respond to a CTCP USERINFO query."
4559 (unless erc-disable-ctcp-replies 4526 (unless erc-disable-ctcp-replies
4560 (erc-send-ctcp-notice nick (format "USERINFO %s" erc-user-information))) 4527 (erc-send-ctcp-notice nick (format "USERINFO %s" erc-user-information)))
4561 nil) 4528 nil)
4562 4529
4563(defvar erc-ctcp-query-VERSION-hook '(erc-ctcp-query-VERSION)) 4530(defvar erc-ctcp-query-VERSION-hook '(erc-ctcp-query-VERSION))
4564(defun erc-ctcp-query-VERSION (proc nick login host to msg) 4531(defun erc-ctcp-query-VERSION (_proc nick _login _host _to _msg)
4565 "Respond to a CTCP VERSION query." 4532 "Respond to a CTCP VERSION query."
4566 (unless erc-disable-ctcp-replies 4533 (unless erc-disable-ctcp-replies
4567 (erc-send-ctcp-notice 4534 (erc-send-ctcp-notice
@@ -4584,7 +4551,7 @@ See also `erc-display-message'."
4584 'CTCP-UNKNOWN ?n nick ?u login ?h host ?m msg)))) 4551 'CTCP-UNKNOWN ?n nick ?u login ?h host ?m msg))))
4585 4552
4586(defvar erc-ctcp-reply-ECHO-hook '(erc-ctcp-reply-ECHO)) 4553(defvar erc-ctcp-reply-ECHO-hook '(erc-ctcp-reply-ECHO))
4587(defun erc-ctcp-reply-ECHO (proc nick login host to msg) 4554(defun erc-ctcp-reply-ECHO (_proc nick _login _host _to msg)
4588 "Handle a CTCP ECHO reply." 4555 "Handle a CTCP ECHO reply."
4589 (when (string-match "^ECHO\\s-+\\(.*\\)\\s-*$" msg) 4556 (when (string-match "^ECHO\\s-+\\(.*\\)\\s-*$" msg)
4590 (let ((message (match-string 1 msg))) 4557 (let ((message (match-string 1 msg)))
@@ -4594,7 +4561,7 @@ See also `erc-display-message'."
4594 nil) 4561 nil)
4595 4562
4596(defvar erc-ctcp-reply-CLIENTINFO-hook '(erc-ctcp-reply-CLIENTINFO)) 4563(defvar erc-ctcp-reply-CLIENTINFO-hook '(erc-ctcp-reply-CLIENTINFO))
4597(defun erc-ctcp-reply-CLIENTINFO (proc nick login host to msg) 4564(defun erc-ctcp-reply-CLIENTINFO (_proc nick _login _host _to msg)
4598 "Handle a CTCP CLIENTINFO reply." 4565 "Handle a CTCP CLIENTINFO reply."
4599 (when (string-match "^CLIENTINFO\\s-+\\(.*\\)\\s-*$" msg) 4566 (when (string-match "^CLIENTINFO\\s-+\\(.*\\)\\s-*$" msg)
4600 (let ((message (match-string 1 msg))) 4567 (let ((message (match-string 1 msg)))
@@ -4604,7 +4571,7 @@ See also `erc-display-message'."
4604 nil) 4571 nil)
4605 4572
4606(defvar erc-ctcp-reply-FINGER-hook '(erc-ctcp-reply-FINGER)) 4573(defvar erc-ctcp-reply-FINGER-hook '(erc-ctcp-reply-FINGER))
4607(defun erc-ctcp-reply-FINGER (proc nick login host to msg) 4574(defun erc-ctcp-reply-FINGER (_proc nick _login _host _to msg)
4608 "Handle a CTCP FINGER reply." 4575 "Handle a CTCP FINGER reply."
4609 (when (string-match "^FINGER\\s-+\\(.*\\)\\s-*$" msg) 4576 (when (string-match "^FINGER\\s-+\\(.*\\)\\s-*$" msg)
4610 (let ((message (match-string 1 msg))) 4577 (let ((message (match-string 1 msg)))
@@ -4614,7 +4581,7 @@ See also `erc-display-message'."
4614 nil) 4581 nil)
4615 4582
4616(defvar erc-ctcp-reply-PING-hook '(erc-ctcp-reply-PING)) 4583(defvar erc-ctcp-reply-PING-hook '(erc-ctcp-reply-PING))
4617(defun erc-ctcp-reply-PING (proc nick login host to msg) 4584(defun erc-ctcp-reply-PING (_proc nick _login _host _to msg)
4618 "Handle a CTCP PING reply." 4585 "Handle a CTCP PING reply."
4619 (if (not (string-match "^PING\\s-+\\([0-9.]+\\)" msg)) 4586 (if (not (string-match "^PING\\s-+\\([0-9.]+\\)" msg))
4620 nil 4587 nil
@@ -4632,7 +4599,7 @@ See also `erc-display-message'."
4632 'bad-ping-response ?n nick ?t time)))))) 4599 'bad-ping-response ?n nick ?t time))))))
4633 4600
4634(defvar erc-ctcp-reply-TIME-hook '(erc-ctcp-reply-TIME)) 4601(defvar erc-ctcp-reply-TIME-hook '(erc-ctcp-reply-TIME))
4635(defun erc-ctcp-reply-TIME (proc nick login host to msg) 4602(defun erc-ctcp-reply-TIME (_proc nick _login _host _to msg)
4636 "Handle a CTCP TIME reply." 4603 "Handle a CTCP TIME reply."
4637 (when (string-match "^TIME\\s-+\\(.*\\)\\s-*$" msg) 4604 (when (string-match "^TIME\\s-+\\(.*\\)\\s-*$" msg)
4638 (let ((message (match-string 1 msg))) 4605 (let ((message (match-string 1 msg)))
@@ -4642,7 +4609,7 @@ See also `erc-display-message'."
4642 nil) 4609 nil)
4643 4610
4644(defvar erc-ctcp-reply-VERSION-hook '(erc-ctcp-reply-VERSION)) 4611(defvar erc-ctcp-reply-VERSION-hook '(erc-ctcp-reply-VERSION))
4645(defun erc-ctcp-reply-VERSION (proc nick login host to msg) 4612(defun erc-ctcp-reply-VERSION (_proc nick _login _host _to msg)
4646 "Handle a CTCP VERSION reply." 4613 "Handle a CTCP VERSION reply."
4647 (when (string-match "^VERSION\\s-+\\(.*\\)\\s-*$" msg) 4614 (when (string-match "^VERSION\\s-+\\(.*\\)\\s-*$" msg)
4648 (let ((message (match-string 1 msg))) 4615 (let ((message (match-string 1 msg)))
@@ -4705,7 +4672,7 @@ received. Should be called with the current buffer set to the
4705channel buffer. 4672channel buffer.
4706 4673
4707See also `erc-channel-begin-receiving-names'." 4674See also `erc-channel-begin-receiving-names'."
4708 (maphash (lambda (nick user) 4675 (maphash (lambda (nick _user)
4709 (if (null (gethash nick erc-channel-new-member-names)) 4676 (if (null (gethash nick erc-channel-new-member-names))
4710 (erc-remove-channel-user nick))) 4677 (erc-remove-channel-user nick)))
4711 erc-channel-users) 4678 erc-channel-users)
@@ -4746,8 +4713,7 @@ channel."
4746 (setq names (delete "" (split-string names-string))) 4713 (setq names (delete "" (split-string names-string)))
4747 (let ((erc-channel-members-changed-hook nil)) 4714 (let ((erc-channel-members-changed-hook nil))
4748 (dolist (item names) 4715 (dolist (item names)
4749 (let ((updatep t) 4716 (let ((updatep t))
4750 ch)
4751 (if (rassq (elt item 0) prefix) 4717 (if (rassq (elt item 0) prefix)
4752 (cond ((= (length item) 1) 4718 (cond ((= (length item) 1)
4753 (setq updatep nil)) 4719 (setq updatep nil))
@@ -4780,8 +4746,7 @@ The buffer where the change happened is current while this hook is called."
4780 4746
4781(defun erc-update-user-nick (nick &optional new-nick 4747(defun erc-update-user-nick (nick &optional new-nick
4782 host login full-name info) 4748 host login full-name info)
4783 "Updates the stored user information for the user with nickname 4749 "Update the stored user information for the user with nickname NICK.
4784NICK.
4785 4750
4786See also: `erc-update-user'." 4751See also: `erc-update-user'."
4787 (erc-update-user (erc-get-server-user nick) new-nick 4752 (erc-update-user (erc-get-server-user nick) new-nick
@@ -4831,8 +4796,8 @@ which USER is a member, and t is returned."
4831(defun erc-update-current-channel-member 4796(defun erc-update-current-channel-member
4832 (nick new-nick &optional add op voice host login full-name info 4797 (nick new-nick &optional add op voice host login full-name info
4833 update-message-time) 4798 update-message-time)
4834 "Updates the stored user information for the user with nickname 4799 "Update the stored user information for the user with nickname NICK.
4835NICK. `erc-update-user' is called to handle changes to nickname, 4800`erc-update-user' is called to handle changes to nickname,
4836HOST, LOGIN, FULL-NAME, and INFO. If OP or VOICE are non-nil, 4801HOST, LOGIN, FULL-NAME, and INFO. If OP or VOICE are non-nil,
4837they must be equal to either `on' or `off', in which case the 4802they must be equal to either `on' or `off', in which case the
4838operator or voice status of the user in the current channel is 4803operator or voice status of the user in the current channel is
@@ -4850,7 +4815,7 @@ If, and only if, changes are made, or the user is added,
4850See also: `erc-update-user' and `erc-update-channel-member'." 4815See also: `erc-update-user' and `erc-update-channel-member'."
4851 (let* (changed user-changed 4816 (let* (changed user-changed
4852 (channel-data (erc-get-channel-user nick)) 4817 (channel-data (erc-get-channel-user nick))
4853 (cuser (if channel-data (cdr channel-data))) 4818 (cuser (cdr channel-data))
4854 (user (if channel-data (car channel-data) 4819 (user (if channel-data (car channel-data)
4855 (erc-get-server-user nick)))) 4820 (erc-get-server-user nick))))
4856 (if cuser 4821 (if cuser
@@ -4908,7 +4873,7 @@ See also: `erc-update-user' and `erc-update-channel-member'."
4908(defun erc-update-channel-member (channel nick new-nick 4873(defun erc-update-channel-member (channel nick new-nick
4909 &optional add op voice host login 4874 &optional add op voice host login
4910 full-name info update-message-time) 4875 full-name info update-message-time)
4911 "Updates user and channel information for the user with 4876 "Update user and channel information for the user with
4912nickname NICK in channel CHANNEL. 4877nickname NICK in channel CHANNEL.
4913 4878
4914See also: `erc-update-current-channel-member'." 4879See also: `erc-update-current-channel-member'."
@@ -4951,7 +4916,6 @@ TOPIC string to the current topic."
4951 "Set the modes for the TGT provided as MODE-STRING." 4916 "Set the modes for the TGT provided as MODE-STRING."
4952 (let* ((modes (erc-parse-modes mode-string)) 4917 (let* ((modes (erc-parse-modes mode-string))
4953 (add-modes (nth 0 modes)) 4918 (add-modes (nth 0 modes))
4954 (remove-modes (nth 1 modes))
4955 ;; list of triples: (mode-char 'on/'off argument) 4919 ;; list of triples: (mode-char 'on/'off argument)
4956 (arg-modes (nth 2 modes))) 4920 (arg-modes (nth 2 modes)))
4957 (cond ((erc-channel-p tgt); channel modes 4921 (cond ((erc-channel-p tgt); channel modes
@@ -5040,6 +5004,7 @@ arg-modes is a list of triples of the form:
5040 "Update the mode information for TGT, provided as MODE-STRING. 5004 "Update the mode information for TGT, provided as MODE-STRING.
5041Optional arguments: NICK, HOST and LOGIN - the attributes of the 5005Optional arguments: NICK, HOST and LOGIN - the attributes of the
5042person who changed the modes." 5006person who changed the modes."
5007 ;; FIXME: neither of nick, host, and login are used!
5043 (let* ((modes (erc-parse-modes mode-string)) 5008 (let* ((modes (erc-parse-modes mode-string))
5044 (add-modes (nth 0 modes)) 5009 (add-modes (nth 0 modes))
5045 (remove-modes (nth 1 modes)) 5010 (remove-modes (nth 1 modes))
@@ -5197,8 +5162,7 @@ START and END describe positions in OBJECT.
5197If VALUE-LIST is nil, set each property in PROPERTIES to t, else set 5162If VALUE-LIST is nil, set each property in PROPERTIES to t, else set
5198each property to the corresponding value in VALUE-LIST." 5163each property to the corresponding value in VALUE-LIST."
5199 (unless value-list 5164 (unless value-list
5200 (setq value-list (mapcar (lambda (x) 5165 (setq value-list (mapcar (lambda (_x) t)
5201 t)
5202 properties))) 5166 properties)))
5203 (while (and properties value-list) 5167 (while (and properties value-list)
5204 (erc-put-text-property 5168 (erc-put-text-property
@@ -5290,7 +5254,7 @@ submitted line to be intentional."
5290 "Regular expression used for matching commands in ERC.") 5254 "Regular expression used for matching commands in ERC.")
5291 5255
5292(defun erc-send-input (input) 5256(defun erc-send-input (input)
5293 "Treat INPUT as typed in by the user. It is assumed that the input 5257 "Treat INPUT as typed in by the user. It is assumed that the input
5294and the prompt is already deleted. 5258and the prompt is already deleted.
5295This returns non-nil only if we actually send anything." 5259This returns non-nil only if we actually send anything."
5296 ;; Handle different kinds of inputs 5260 ;; Handle different kinds of inputs
@@ -5380,8 +5344,8 @@ list of the form: (command args) where both elements are strings."
5380 (when (string-match erc-command-regexp line) 5344 (when (string-match erc-command-regexp line)
5381 (let* ((cmd (erc-command-symbol (match-string 1 line))) 5345 (let* ((cmd (erc-command-symbol (match-string 1 line)))
5382 ;; note: return is nil, we apply this simply for side effects 5346 ;; note: return is nil, we apply this simply for side effects
5383 (canon-defun (while (and cmd (symbolp (symbol-function cmd))) 5347 (_canon-defun (while (and cmd (symbolp (symbol-function cmd)))
5384 (setq cmd (symbol-function cmd)))) 5348 (setq cmd (symbol-function cmd))))
5385 (cmd-fun (or cmd #'erc-cmd-default)) 5349 (cmd-fun (or cmd #'erc-cmd-default))
5386 (arg (if cmd 5350 (arg (if cmd
5387 (if (get cmd-fun 'do-not-parse-args) 5351 (if (get cmd-fun 'do-not-parse-args)
@@ -5449,22 +5413,18 @@ See also `erc-downcase'."
5449 5413
5450(defun erc-add-default-channel (channel) 5414(defun erc-add-default-channel (channel)
5451 "Add CHANNEL to the default channel list." 5415 "Add CHANNEL to the default channel list."
5452 5416 (let ((chl (downcase channel)))
5453 (let ((d1 (car erc-default-recipients))
5454 (d2 (cdr erc-default-recipients))
5455 (chl (downcase channel)))
5456 (setq erc-default-recipients 5417 (setq erc-default-recipients
5457 (cons chl erc-default-recipients)))) 5418 (cons chl erc-default-recipients))))
5458 5419
5459(defun erc-delete-default-channel (channel &optional buffer) 5420(defun erc-delete-default-channel (channel &optional buffer)
5460 "Delete CHANNEL from the default channel list." 5421 "Delete CHANNEL from the default channel list."
5461 (let ((ob (current-buffer))) 5422 (with-current-buffer (if (and buffer
5462 (with-current-buffer (if (and buffer 5423 (bufferp buffer))
5463 (bufferp buffer)) 5424 buffer
5464 buffer 5425 (current-buffer))
5465 (current-buffer)) 5426 (setq erc-default-recipients (delete (downcase channel)
5466 (setq erc-default-recipients (delete (downcase channel) 5427 erc-default-recipients))))
5467 erc-default-recipients)))))
5468 5428
5469(defun erc-add-query (nickname) 5429(defun erc-add-query (nickname)
5470 "Add QUERY'd NICKNAME to the default channel list. 5430 "Add QUERY'd NICKNAME to the default channel list.
@@ -5473,10 +5433,10 @@ The previous default target of QUERY type gets removed."
5473 (let ((d1 (car erc-default-recipients)) 5433 (let ((d1 (car erc-default-recipients))
5474 (d2 (cdr erc-default-recipients)) 5434 (d2 (cdr erc-default-recipients))
5475 (qt (cons 'QUERY (downcase nickname)))) 5435 (qt (cons 'QUERY (downcase nickname))))
5476 (if (and (listp d1) 5436 (setq erc-default-recipients (cons qt (if (and (listp d1)
5477 (eq (car d1) 'QUERY)) 5437 (eq (car d1) 'QUERY))
5478 (setq erc-default-recipients (cons qt d2)) 5438 d2
5479 (setq erc-default-recipients (cons qt erc-default-recipients))))) 5439 erc-default-recipients)))))
5480 5440
5481(defun erc-delete-query () 5441(defun erc-delete-query ()
5482 "Delete the topmost target if it is a QUERY." 5442 "Delete the topmost target if it is a QUERY."
@@ -5527,17 +5487,11 @@ The addressed target is the string before the first colon in MSG."
5527 (let ((nick (erc-server-user-nickname user)) 5487 (let ((nick (erc-server-user-nickname user))
5528 (host (erc-server-user-host user)) 5488 (host (erc-server-user-host user))
5529 (login (erc-server-user-login user))) 5489 (login (erc-server-user-login user)))
5530 (concat (if nick 5490 (concat (or nick "")
5531 nick
5532 "")
5533 "!" 5491 "!"
5534 (if login 5492 (or login "")
5535 login
5536 "")
5537 "@" 5493 "@"
5538 (if host 5494 (or host ""))))
5539 host
5540 ""))))
5541 5495
5542(defun erc-list-match (lst str) 5496(defun erc-list-match (lst str)
5543 "Return non-nil if any regexp in LST matches STR." 5497 "Return non-nil if any regexp in LST matches STR."
@@ -5588,7 +5542,7 @@ This command is sent even if excess flood is detected."
5588 (interactive "P") 5542 (interactive "P")
5589 (erc-set-active-buffer (current-buffer)) 5543 (erc-set-active-buffer (current-buffer))
5590 (let ((tgt (erc-default-target)) 5544 (let ((tgt (erc-default-target))
5591 (erc-force-send t)) 5545 (erc-force-send t)) ;FIXME: Not used anywhere!
5592 (cond ((or (not tgt) (not (erc-channel-p tgt))) 5546 (cond ((or (not tgt) (not (erc-channel-p tgt)))
5593 (erc-display-message nil 'error (current-buffer) 'no-target)) 5547 (erc-display-message nil 'error (current-buffer) 'no-target))
5594 (arg (erc-load-irc-script-lines (list (concat "/mode " tgt " -i")) 5548 (arg (erc-load-irc-script-lines (list (concat "/mode " tgt " -i"))
@@ -5626,7 +5580,7 @@ If CHANNEL is non-nil, toggle MODE for that channel, otherwise use
5626 (interactive "P") 5580 (interactive "P")
5627 (erc-set-active-buffer (current-buffer)) 5581 (erc-set-active-buffer (current-buffer))
5628 (let ((tgt (or channel (erc-default-target))) 5582 (let ((tgt (or channel (erc-default-target)))
5629 (erc-force-send t)) 5583 (erc-force-send t)) ;FIXME: Not used anywhere!
5630 (cond ((or (null tgt) (null (erc-channel-p tgt))) 5584 (cond ((or (null tgt) (null (erc-channel-p tgt)))
5631 (erc-display-message nil 'error 'active 'no-target)) 5585 (erc-display-message nil 'error 'active 'no-target))
5632 ((member mode erc-channel-modes) 5586 ((member mode erc-channel-modes)
@@ -5670,12 +5624,11 @@ specified in the list PATH.
5670If FILE is found, return the path to it." 5624If FILE is found, return the path to it."
5671 (let ((filepath file)) 5625 (let ((filepath file))
5672 (if (file-readable-p filepath) filepath 5626 (if (file-readable-p filepath) filepath
5673 (progn 5627 (while (and path
5674 (while (and path 5628 (progn (setq filepath (expand-file-name file (car path)))
5675 (progn (setq filepath (expand-file-name file (car path))) 5629 (not (file-readable-p filepath))))
5676 (not (file-readable-p filepath)))) 5630 (setq path (cdr path)))
5677 (setq path (cdr path))) 5631 (if path filepath nil))))
5678 (if path filepath nil)))))
5679 5632
5680(defun erc-select-startup-file () 5633(defun erc-select-startup-file ()
5681 "Select an ERC startup file. 5634 "Select an ERC startup file.
@@ -5789,7 +5742,6 @@ If optional NOEXPAND is non-nil, do not expand script-specific
5789sequences, process the lines verbatim. Use this for multiline 5742sequences, process the lines verbatim. Use this for multiline
5790user input." 5743user input."
5791 (let* ((cb (current-buffer)) 5744 (let* ((cb (current-buffer))
5792 (pnt (point))
5793 (s "") 5745 (s "")
5794 (sp (or (erc-command-indicator) (erc-prompt))) 5746 (sp (or (erc-command-indicator) (erc-prompt)))
5795 (args (and (boundp 'erc-script-args) erc-script-args))) 5747 (args (and (boundp 'erc-script-args) erc-script-args)))
@@ -6030,13 +5982,12 @@ entry of `channel-members'."
6030 (user (if channel-data 5982 (user (if channel-data
6031 (car channel-data) 5983 (car channel-data)
6032 (erc-get-server-user word))) 5984 (erc-get-server-user word)))
6033 host login full-name info nick op voice) 5985 host login full-name nick op voice)
6034 (when user 5986 (when user
6035 (setq nick (erc-server-user-nickname user) 5987 (setq nick (erc-server-user-nickname user)
6036 host (erc-server-user-host user) 5988 host (erc-server-user-host user)
6037 login (erc-server-user-login user) 5989 login (erc-server-user-login user)
6038 full-name (erc-server-user-full-name user) 5990 full-name (erc-server-user-full-name user))
6039 info (erc-server-user-info user))
6040 (if cuser 5991 (if cuser
6041 (setq op (erc-channel-user-op cuser) 5992 (setq op (erc-channel-user-op cuser)
6042 voice (erc-channel-user-voice cuser))) 5993 voice (erc-channel-user-voice cuser)))
@@ -6048,7 +5999,7 @@ entry of `channel-members'."
6048 (format " and is +%s%s on %s" 5999 (format " and is +%s%s on %s"
6049 (if op "o" "") 6000 (if op "o" "")
6050 (if voice "v" "") 6001 (if voice "v" "")
6051 (erc-default-target)) 6002 (erc-default-target))
6052 "")) 6003 ""))
6053 user)))) 6004 user))))
6054 6005
@@ -6597,7 +6548,7 @@ See also `format-spec'."
6597(add-hook 'kill-buffer-hook 'erc-kill-buffer-function) 6548(add-hook 'kill-buffer-hook 'erc-kill-buffer-function)
6598 6549
6599(defcustom erc-kill-server-hook '(erc-kill-server) 6550(defcustom erc-kill-server-hook '(erc-kill-server)
6600 "Invoked whenever a server-buffer is killed via `kill-buffer'." 6551 "Invoked whenever a server buffer is killed via `kill-buffer'."
6601 :group 'erc-hooks 6552 :group 'erc-hooks
6602 :type 'hook) 6553 :type 'hook)
6603 6554
@@ -6702,9 +6653,9 @@ Otherwise, connect to HOST:PORT as USER and /join CHANNEL."
6702 6653
6703(provide 'erc) 6654(provide 'erc)
6704 6655
6705;;; Deprecated. We might eventually stop requiring the goodies automatically. 6656;; Deprecated. We might eventually stop requiring the goodies automatically.
6706;;; IMPORTANT: This require must appear _after_ the above (provide 'erc) to 6657;; IMPORTANT: This require must appear _after_ the above (provide 'erc) to
6707;;; avoid a recursive require error when byte-compiling the entire package. 6658;; avoid a recursive require error when byte-compiling the entire package.
6708(require 'erc-goodies) 6659(require 'erc-goodies)
6709 6660
6710;;; erc.el ends here 6661;;; erc.el ends here
diff --git a/lisp/files.el b/lisp/files.el
index efd89605b1b..f9ff3c936bd 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -1603,13 +1603,16 @@ killed."
1603 "Create a suitably named buffer for visiting FILENAME, and return it. 1603 "Create a suitably named buffer for visiting FILENAME, and return it.
1604FILENAME (sans directory) is used unchanged if that name is free; 1604FILENAME (sans directory) is used unchanged if that name is free;
1605otherwise a string <2> or <3> or ... is appended to get an unused name. 1605otherwise a string <2> or <3> or ... is appended to get an unused name.
1606Spaces at the start of FILENAME (sans directory) are removed." 1606
1607Emacs treats buffers whose names begin with a space as internal buffers.
1608To avoid confusion when visiting a file whose name begins with a space,
1609this function prepends a \"|\" to the final result if necessary."
1607 (let ((lastname (file-name-nondirectory filename))) 1610 (let ((lastname (file-name-nondirectory filename)))
1608 (if (string= lastname "") 1611 (if (string= lastname "")
1609 (setq lastname filename)) 1612 (setq lastname filename))
1610 (save-match-data 1613 (generate-new-buffer (if (string-match-p "\\` " lastname)
1611 (string-match "^ *\\(.*\\)" lastname) 1614 (concat "|" lastname)
1612 (generate-new-buffer (match-string 1 lastname))))) 1615 lastname))))
1613 1616
1614(defun generate-new-buffer (name) 1617(defun generate-new-buffer (name)
1615 "Create and return a buffer with a name based on NAME. 1618 "Create and return a buffer with a name based on NAME.
@@ -2272,8 +2275,8 @@ since only a single case-insensitive search through the alist is made."
2272 ("\\.scm\\.[0-9]*\\'" . scheme-mode) 2275 ("\\.scm\\.[0-9]*\\'" . scheme-mode)
2273 ("\\.[ck]?sh\\'\\|\\.shar\\'\\|/\\.z?profile\\'" . sh-mode) 2276 ("\\.[ck]?sh\\'\\|\\.shar\\'\\|/\\.z?profile\\'" . sh-mode)
2274 ("\\.bash\\'" . sh-mode) 2277 ("\\.bash\\'" . sh-mode)
2275 ("\\(/\\|\\`\\)\\.\\(bash_profile\\|z?login\\|bash_login\\|z?logout\\)\\'" . sh-mode) 2278 ("\\(/\\|\\`\\)\\.\\(bash_\\(profile\\|history\\|log\\(in\\|out\\)\\)\\|z?log\\(in\\|out\\)\\)\\'" . sh-mode)
2276 ("\\(/\\|\\`\\)\\.\\(bash_logout\\|shrc\\|[kz]shrc\\|bashrc\\|t?cshrc\\|esrc\\)\\'" . sh-mode) 2279 ("\\(/\\|\\`\\)\\.\\(shrc\\|[kz]shrc\\|bashrc\\|t?cshrc\\|esrc\\)\\'" . sh-mode)
2277 ("\\(/\\|\\`\\)\\.\\([kz]shenv\\|xinitrc\\|startxrc\\|xsession\\)\\'" . sh-mode) 2280 ("\\(/\\|\\`\\)\\.\\([kz]shenv\\|xinitrc\\|startxrc\\|xsession\\)\\'" . sh-mode)
2278 ("\\.m?spec\\'" . sh-mode) 2281 ("\\.m?spec\\'" . sh-mode)
2279 ("\\.m[mes]\\'" . nroff-mode) 2282 ("\\.m[mes]\\'" . nroff-mode)
@@ -2451,6 +2454,7 @@ and `magic-mode-alist', which determines modes based on file contents.")
2451 ("wishx" . tcl-mode) 2454 ("wishx" . tcl-mode)
2452 ("tcl" . tcl-mode) 2455 ("tcl" . tcl-mode)
2453 ("tclsh" . tcl-mode) 2456 ("tclsh" . tcl-mode)
2457 ("expect" . tcl-mode)
2454 ("scm" . scheme-mode) 2458 ("scm" . scheme-mode)
2455 ("ash" . sh-mode) 2459 ("ash" . sh-mode)
2456 ("bash" . sh-mode) 2460 ("bash" . sh-mode)
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index e07d28a54d0..72cb6f7e894 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2246,7 +2246,8 @@ same as `substitute-in-file-name'."
2246 ;; - Cygwin (substitute-in-file-name "C:\bin") => "/usr/bin" 2246 ;; - Cygwin (substitute-in-file-name "C:\bin") => "/usr/bin"
2247 ;; (substitute-in-file-name "C:\") => "/" 2247 ;; (substitute-in-file-name "C:\") => "/"
2248 ;; (substitute-in-file-name "C:\bi") => "/bi" 2248 ;; (substitute-in-file-name "C:\bi") => "/bi"
2249 (let* ((ustr (substitute-in-file-name qstr)) 2249 (let* ((non-essential t)
2250 (ustr (substitute-in-file-name qstr))
2250 (uprefix (substring ustr 0 upos)) 2251 (uprefix (substring ustr 0 upos))
2251 qprefix) 2252 qprefix)
2252 ;; Main assumption: nothing after qpos should affect the text before upos, 2253 ;; Main assumption: nothing after qpos should affect the text before upos,
diff --git a/lisp/progmodes/cc-awk.el b/lisp/progmodes/cc-awk.el
index 4b3fc91b0ff..b5216b43ed9 100644
--- a/lisp/progmodes/cc-awk.el
+++ b/lisp/progmodes/cc-awk.el
@@ -169,9 +169,9 @@
169 (concat "\\=_?\"" c-awk-string-innards-re)) 169 (concat "\\=_?\"" c-awk-string-innards-re))
170;; Matches an AWK string at point up to, but not including, any terminator. 170;; Matches an AWK string at point up to, but not including, any terminator.
171;; A gawk 3.1+ string may look like _"localizable string". 171;; A gawk 3.1+ string may look like _"localizable string".
172(defconst c-awk-one-line-possibly-open-string-re 172(defconst c-awk-possibly-open-string-re
173 (concat "\"\\(" c-awk-string-ch-re "\\|" c-awk-non-eol-esc-pair-re "\\)*" 173 (concat "\"\\(" c-awk-string-ch-re "\\|" c-awk-esc-pair-re "\\)*"
174 "\\(\"\\|\\\\?$\\|\\'\\)")) 174 "\\(\"\\|$\\|\\'\\)"))
175 175
176;; REGEXPS FOR AWK REGEXPS. 176;; REGEXPS FOR AWK REGEXPS.
177(defconst c-awk-regexp-normal-re "[^[/\\\n\r]") 177(defconst c-awk-regexp-normal-re "[^[/\\\n\r]")
@@ -192,25 +192,13 @@
192 "\\|" "[^]\n\r]" "\\)*" "\\(]\\|$\\)")) 192 "\\|" "[^]\n\r]" "\\)*" "\\(]\\|$\\)"))
193;; Matches a regexp char list, up to (but not including) EOL if the ] is 193;; Matches a regexp char list, up to (but not including) EOL if the ] is
194;; missing. 194;; missing.
195(defconst c-awk-regexp-one-line-possibly-open-char-list-re
196 (concat "\\[\\]?\\(" c-awk-non-eol-esc-pair-re "\\|" "[^]\n\r]" "\\)*"
197 "\\(]\\|\\\\?$\\|\\'\\)"))
198;; Matches the head (or all) of a regexp char class, up to (but not
199;; including) the first EOL.
200(defconst c-awk-regexp-innards-re 195(defconst c-awk-regexp-innards-re
201 (concat "\\(" c-awk-esc-pair-re "\\|" c-awk-regexp-char-list-re 196 (concat "\\(" c-awk-esc-pair-re "\\|" c-awk-regexp-char-list-re
202 "\\|" c-awk-regexp-normal-re "\\)*")) 197 "\\|" c-awk-regexp-normal-re "\\)*"))
203;; Matches the inside of an AWK regexp (i.e. without the enclosing /s) 198;; Matches the inside of an AWK regexp (i.e. without the enclosing /s)
204(defconst c-awk-regexp-without-end-re 199(defconst c-awk-regexp-without-end-re
205 (concat "/" c-awk-regexp-innards-re)) 200 (concat "/" c-awk-regexp-innards-re))
206;; Matches an AWK regexp up to, but not including, any terminating /. 201;; Matches an AWK regexp up to, but not including, any terminating /.
207(defconst c-awk-one-line-possibly-open-regexp-re
208 (concat "/\\(" c-awk-non-eol-esc-pair-re
209 "\\|" c-awk-regexp-one-line-possibly-open-char-list-re
210 "\\|" c-awk-regexp-normal-re "\\)*"
211 "\\(/\\|\\\\?$\\|\\'\\)"))
212;; Matches as much of the head of an AWK regexp which fits on one line,
213;; possibly all of it.
214 202
215;; REGEXPS used for scanning an AWK buffer in order to decide IF A '/' IS A 203;; REGEXPS used for scanning an AWK buffer in order to decide IF A '/' IS A
216;; REGEXP OPENER OR A DIVISION SIGN. By "state" in the following is meant 204;; REGEXP OPENER OR A DIVISION SIGN. By "state" in the following is meant
@@ -262,15 +250,24 @@
262 250
263;; REGEXPS USED FOR FINDING THE POSITION OF A "virtual semicolon" 251;; REGEXPS USED FOR FINDING THE POSITION OF A "virtual semicolon"
264(defconst c-awk-_-harmless-nonws-char-re "[^#/\"\\\\\n\r \t]") 252(defconst c-awk-_-harmless-nonws-char-re "[^#/\"\\\\\n\r \t]")
265;; NEW VERSION! (which will be restricted to the current line) 253(defconst c-awk-non-/-syn-ws*-re
266(defconst c-awk-one-line-non-syn-ws*-re 254 (concat
267 (concat "\\([ \t]*" 255 "\\(" c-awk-escaped-nls*-with-space*
268 "\\(" c-awk-_-harmless-nonws-char-re "\\|" 256 "\\(" c-awk-_-harmless-nonws-char-re "\\|"
269 c-awk-non-eol-esc-pair-re "\\|" 257 c-awk-non-eol-esc-pair-re "\\|"
270 c-awk-one-line-possibly-open-string-re "\\|" 258 c-awk-possibly-open-string-re
271 c-awk-one-line-possibly-open-regexp-re 259 "\\)"
272 "\\)" 260 "\\)*"))
273 "\\)*")) 261(defconst c-awk-space*-/-re (concat c-awk-escaped-nls*-with-space* "/"))
262;; Matches optional whitespace followed by "/".
263(defconst c-awk-space*-regexp-/-re
264 (concat c-awk-escaped-nls*-with-space* "\\s\""))
265;; Matches optional whitespace followed by a "/" with string syntax (a matched
266;; regexp delimiter).
267(defconst c-awk-space*-unclosed-regexp-/-re
268 (concat c-awk-escaped-nls*-with-space* "\\s\|"))
269;; Matches optional whitespace followed by a "/" with string fence syntax (an
270;; unmatched regexp delimiter).
274 271
275 272
276;; ACM, 2002/5/29: 273;; ACM, 2002/5/29:
@@ -549,10 +546,36 @@
549(defun c-awk-at-vsemi-p (&optional pos) 546(defun c-awk-at-vsemi-p (&optional pos)
550 ;; Is there a virtual semicolon at POS (or POINT)? 547 ;; Is there a virtual semicolon at POS (or POINT)?
551 (save-excursion 548 (save-excursion
552 (let (nl-prop 549 (let* (nl-prop
553 (pos-or-point (progn (if pos (goto-char pos)) (point)))) 550 (pos-or-point (progn (if pos (goto-char pos)) (point)))
554 (forward-line 0) 551 (bol (c-point 'bol)) (eol (c-point 'eol)))
555 (search-forward-regexp c-awk-one-line-non-syn-ws*-re) 552 (c-awk-beginning-of-logical-line)
553 ;; Next `while' goes round one logical line (ending in, e.g. "\\") per
554 ;; iteration. Such a line is rare, and can only be an open string
555 ;; ending in an escaped \.
556 (while
557 (progn
558 ;; Next `while' goes over a division sign or /regexp/ per iteration.
559 (while
560 (and
561 (< (point) eol)
562 (progn
563 (search-forward-regexp c-awk-non-/-syn-ws*-re eol)
564 (looking-at c-awk-space*-/-re)))
565 (cond
566 ((looking-at c-awk-space*-regexp-/-re) ; /regexp/
567 (forward-sexp))
568 ((looking-at c-awk-space*-unclosed-regexp-/-re) ; Unclosed /regexp
569 (condition-case nil
570 (progn
571 (forward-sexp)
572 (backward-char)) ; Move to end of (logical) line.
573 (error (end-of-line)))) ; Happens at EOB.
574 (t ; division sign
575 (c-forward-syntactic-ws)
576 (forward-char))))
577 (< (point) bol))
578 (forward-line))
556 (and (eq (point) pos-or-point) 579 (and (eq (point) pos-or-point)
557 (progn 580 (progn
558 (while (and (eq (setq nl-prop (c-awk-get-NL-prop-cur-line)) ?\\) 581 (while (and (eq (setq nl-prop (c-awk-get-NL-prop-cur-line)) ?\\)
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index c2ff5011a0e..3d6398014db 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -1271,6 +1271,9 @@ comment at the start of cc-engine.el for more info."
1271 (throw 'done (point))))) 1271 (throw 'done (point)))))
1272 ;; In trailing space after an as yet undetected virtual semicolon? 1272 ;; In trailing space after an as yet undetected virtual semicolon?
1273 (c-backward-syntactic-ws from) 1273 (c-backward-syntactic-ws from)
1274 (when (and (bolp) (not (bobp))) ; Can happen in AWK Mode with an
1275 ; unterminated string/regexp.
1276 (backward-char))
1274 (if (and (< (point) to) 1277 (if (and (< (point) to)
1275 (c-at-vsemi-p)) 1278 (c-at-vsemi-p))
1276 (point) 1279 (point)
@@ -9796,12 +9799,12 @@ comment at the start of cc-engine.el for more info."
9796 (not (eq (char-after) ?:)) 9799 (not (eq (char-after) ?:))
9797 ))) 9800 )))
9798 (save-excursion 9801 (save-excursion
9799 (c-backward-syntactic-ws lim) 9802 (c-beginning-of-statement-1 lim)
9800 (if (eq char-before-ip ?:) 9803 (when (looking-at c-opt-<>-sexp-key)
9801 (progn 9804 (goto-char (match-end 1))
9802 (forward-char -1) 9805 (c-forward-syntactic-ws)
9803 (c-backward-syntactic-ws lim))) 9806 (c-forward-<>-arglist nil)
9804 (back-to-indentation) 9807 (c-forward-syntactic-ws))
9805 (looking-at c-class-key))) 9808 (looking-at c-class-key)))
9806 ;; for Java 9809 ;; for Java
9807 (and (c-major-mode-is 'java-mode) 9810 (and (c-major-mode-is 'java-mode)
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 2c0a1317b04..0116e9ec3dd 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -2163,8 +2163,7 @@ assumed to be set if this isn't nil."
2163(c-lang-defconst c-opt-<>-sexp-key 2163(c-lang-defconst c-opt-<>-sexp-key
2164 ;; Adorned regexp matching keywords that can be followed by an angle 2164 ;; Adorned regexp matching keywords that can be followed by an angle
2165 ;; bracket sexp. Always set when `c-recognize-<>-arglists' is. 2165 ;; bracket sexp. Always set when `c-recognize-<>-arglists' is.
2166 t (if (c-lang-const c-recognize-<>-arglists) 2166 t (c-make-keywords-re t (c-lang-const c-<>-sexp-kwds)))
2167 (c-make-keywords-re t (c-lang-const c-<>-sexp-kwds))))
2168(c-lang-defvar c-opt-<>-sexp-key (c-lang-const c-opt-<>-sexp-key)) 2167(c-lang-defvar c-opt-<>-sexp-key (c-lang-const c-opt-<>-sexp-key))
2169 2168
2170(c-lang-defconst c-brace-id-list-kwds 2169(c-lang-defconst c-brace-id-list-kwds
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index 29020d95226..c8b65e0a029 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -497,6 +497,9 @@ This is buffer-local in every such buffer.")
497 (define-key map "\C-c+" 'sh-add) 497 (define-key map "\C-c+" 'sh-add)
498 (define-key map "\C-\M-x" 'sh-execute-region) 498 (define-key map "\C-\M-x" 'sh-execute-region)
499 (define-key map "\C-c\C-x" 'executable-interpret) 499 (define-key map "\C-c\C-x" 'executable-interpret)
500 (define-key map "\C-c\C-n" 'sh-send-line-or-region-and-step)
501 (define-key map "\C-c\C-d" 'sh-cd-here)
502 (define-key map "\C-c\C-z" 'sh-show-shell)
500 503
501 (define-key map [remap delete-backward-char] 504 (define-key map [remap delete-backward-char]
502 'backward-delete-char-untabify) 505 'backward-delete-char-untabify)
@@ -1462,6 +1465,61 @@ The default is t because I assume that in one Emacs session one is
1462frequently editing existing scripts with different styles.") 1465frequently editing existing scripts with different styles.")
1463 1466
1464 1467
1468;; inferior shell interaction
1469;; TODO: support multiple interactive shells
1470(defvar sh-shell-process nil
1471 "The inferior shell process for interaction.")
1472(make-variable-buffer-local 'sh-shell-process)
1473(defun sh-shell-process (force)
1474 "Get a shell process for interaction.
1475If FORCE is non-nil and no process found, create one."
1476 (if (and sh-shell-process (process-live-p sh-shell-process))
1477 sh-shell-process
1478 (setq sh-shell-process
1479 (let ((found nil) proc
1480 (procs (process-list)))
1481 (while (and (not found) procs
1482 (process-live-p (setq proc (pop procs)))
1483 (process-command proc))
1484 (when (string-equal sh-shell (file-name-nondirectory
1485 (car (process-command proc))))
1486 (setq found proc)))
1487 (or found
1488 (and force
1489 (get-buffer-process
1490 (let ((explicit-shell-file-name sh-shell-file))
1491 (shell)))))))))
1492
1493(defun sh-show-shell ()
1494 "Pop the shell interaction buffer."
1495 (interactive)
1496 (pop-to-buffer (process-buffer (sh-shell-process t))))
1497
1498(defun sh-send-text (text)
1499 "Send the text to the `sh-shell-process'."
1500 (comint-send-string (sh-shell-process t) (concat text "\n")))
1501
1502(defun sh-cd-here ()
1503 "Change directory in the current interaction shell to the current one."
1504 (interactive)
1505 (sh-send-text (concat "cd " default-directory)))
1506
1507(defun sh-send-line-or-region-and-step ()
1508 "Send the current line to the inferior shell and step to the next line.
1509When the region is active, send the region instead."
1510 (interactive)
1511 (let (from to end)
1512 (if (use-region-p)
1513 (setq from (region-beginning)
1514 to (region-end)
1515 end to)
1516 (setq from (line-beginning-position)
1517 to (line-end-position)
1518 end (1+ to)))
1519 (sh-send-text (buffer-substring-no-properties from to))
1520 (goto-char end)))
1521
1522
1465;; mode-command and utility functions 1523;; mode-command and utility functions
1466 1524
1467;;;###autoload 1525;;;###autoload
@@ -2169,6 +2227,7 @@ Calls the value of `sh-set-shell-hook' if set."
2169 (setq font-lock-set-defaults nil) 2227 (setq font-lock-set-defaults nil)
2170 (font-lock-set-defaults) 2228 (font-lock-set-defaults)
2171 (font-lock-fontify-buffer)) 2229 (font-lock-fontify-buffer))
2230 (setq sh-shell-process nil)
2172 (run-hooks 'sh-set-shell-hook)) 2231 (run-hooks 'sh-set-shell-hook))
2173 2232
2174 2233
diff --git a/lisp/rfn-eshadow.el b/lisp/rfn-eshadow.el
index cf5f1d16974..8d29c43980c 100644
--- a/lisp/rfn-eshadow.el
+++ b/lisp/rfn-eshadow.el
@@ -176,11 +176,11 @@ This is intended to be used as a minibuffer `post-command-hook' for
176`file-name-shadow-mode'; the minibuffer should have already 176`file-name-shadow-mode'; the minibuffer should have already
177been set up by `rfn-eshadow-setup-minibuffer'." 177been set up by `rfn-eshadow-setup-minibuffer'."
178 (condition-case nil 178 (condition-case nil
179 (let ((goal (substitute-in-file-name (minibuffer-contents))) 179 (let* ((non-essential t)
180 (mid (overlay-end rfn-eshadow-overlay)) 180 (goal (substitute-in-file-name (minibuffer-contents)))
181 (start (minibuffer-prompt-end)) 181 (mid (overlay-end rfn-eshadow-overlay))
182 (end (point-max)) 182 (start (minibuffer-prompt-end))
183 (non-essential t)) 183 (end (point-max)))
184 (unless 184 (unless
185 ;; Catch the common case where the shadow does not need to move. 185 ;; Catch the common case where the shadow does not need to move.
186 (and mid 186 (and mid
diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el
index 5b6d5f359e6..119b4b04593 100644
--- a/lisp/textmodes/fill.el
+++ b/lisp/textmodes/fill.el
@@ -220,7 +220,7 @@ Remove indentation from each line."
220 (let ((str (or 220 (let ((str (or
221 (and adaptive-fill-function (funcall adaptive-fill-function)) 221 (and adaptive-fill-function (funcall adaptive-fill-function))
222 (and adaptive-fill-regexp (looking-at adaptive-fill-regexp) 222 (and adaptive-fill-regexp (looking-at adaptive-fill-regexp)
223 (match-string-no-properties 0))))) 223 (match-string 0)))))
224 (if (>= (+ (current-left-margin) (length str)) (current-fill-column)) 224 (if (>= (+ (current-left-margin) (length str)) (current-fill-column))
225 ;; Death to insanely long prefixes. 225 ;; Death to insanely long prefixes.
226 nil 226 nil
diff --git a/lisp/window.el b/lisp/window.el
index 64cf0a72110..21e40071782 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -5642,7 +5642,10 @@ new frame."
5642 (fun pop-up-frame-function) 5642 (fun pop-up-frame-function)
5643 frame window) 5643 frame window)
5644 (when (and fun 5644 (when (and fun
5645 (setq frame (funcall fun)) 5645 ;; Make BUFFER current so `make-frame' will use it as the
5646 ;; new frame's buffer (Bug#15133).
5647 (with-current-buffer buffer
5648 (setq frame (funcall fun)))
5646 (setq window (frame-selected-window frame))) 5649 (setq window (frame-selected-window frame)))
5647 (prog1 (window--display-buffer 5650 (prog1 (window--display-buffer
5648 buffer window 'frame alist display-buffer-mark-dedicated) 5651 buffer window 'frame alist display-buffer-mark-dedicated)
diff --git a/nt/ChangeLog b/nt/ChangeLog
index 8ed5caa4aab..ebc823071a3 100644
--- a/nt/ChangeLog
+++ b/nt/ChangeLog
@@ -1,7 +1,17 @@
12013-08-25 Vincent Belaïche <vincentb1@users.sourceforge.net>
2
3 * configure.bat: Rather than disabling, make configure.bat produce
4 some warning that building with configure.bat is deprecated and
5 ask for confirmation to continue.
6
72013-08-25 Glenn Morris <rgm@gnu.org>
8
9 * INSTALL: Refer to INSTALL.MSYS.
10 * configure.bat: Disable it.
11
12013-08-04 Eli Zaretskii <eliz@gnu.org> 122013-08-04 Eli Zaretskii <eliz@gnu.org>
2 13
3 * mingw-cfg.site (ac_cv_func_mkostemp): New var with value of 14 * mingw-cfg.site (ac_cv_func_mkostemp): New var with value of "yes".
4 "yes".
5 15
6 * inc/ms-w32.h (mkostemp): Declare prototype. 16 * inc/ms-w32.h (mkostemp): Declare prototype.
7 (mktemp): Don't redirect to sys_mktemp. 17 (mktemp): Don't redirect to sys_mktemp.
diff --git a/nt/INSTALL b/nt/INSTALL
index 8abd8aff920..594ff9ff752 100644
--- a/nt/INSTALL
+++ b/nt/INSTALL
@@ -4,6 +4,9 @@
4 Copyright (C) 2001-2013 Free Software Foundation, Inc. 4 Copyright (C) 2001-2013 Free Software Foundation, Inc.
5 See the end of the file for license conditions. 5 See the end of the file for license conditions.
6 6
7*** This method of building Emacs is no longer supported. ***
8 Instead, see INSTALL.MSYS.
9
7* For the impatient 10* For the impatient
8 11
9 Here are the concise instructions for configuring and building the 12 Here are the concise instructions for configuring and building the
diff --git a/nt/configure.bat b/nt/configure.bat
index 484fb83d901..8f717fd4168 100755
--- a/nt/configure.bat
+++ b/nt/configure.bat
@@ -58,7 +58,20 @@ rem look for "cygpath" near line 85 of gmake.defs.
58rem [7] not recommended; please report if you try this combination. 58rem [7] not recommended; please report if you try this combination.
59rem [8] tested only on Windows XP. 59rem [8] tested only on Windows XP.
60rem 60rem
61 61echo ****************************************************************
62echo *** THIS METHOD OF BUILDING EMACS IS NO LONGER SUPPORTED. **
63echo *** INSTEAD, FOLLOW THE INSTRUCTIONS FROM INSTALL.MSYS. **
64echo ****************************************************************
65:confirm_continue
66set /p answer=Continue running this script at your own risks ? (Y/N)
67if x%answer% == xy (goto confirm_continue_y)
68if x%answer% == xY (goto confirm_continue_y)
69if x%answer% == xn (goto end)
70if x%answer% == xN (goto end)
71echo Please answer by Y or N
72goto confirm_continue
73
74:confirm_continue_y
62if exist config.log del config.log 75if exist config.log del config.log
63 76
64rem ---------------------------------------------------------------------- 77rem ----------------------------------------------------------------------
diff --git a/src/ChangeLog b/src/ChangeLog
index e21d82bdc09..70d722a02a4 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,124 @@
12013-08-24 Eli Zaretskii <eliz@gnu.org>
2
3 * xdisp.c (get_next_display_element): Don't apply to characters
4 from a display vector the logic of setting it->end_of_box_run_p
5 suitable for characters from a buffer. (Bug#15175)
6
7 * w32.c (fdutimens): Call 'utime', which is implemented on w32.c
8 to handle directories, rather than '_utime' which doesn't.
9 (Bug#15176)
10
112013-08-24 Jan Djärv <jan.h.d@swipnet.se>
12
13 * gtkutil.c (x_wm_set_size_hint): Don't set hints when maximized
14 or fullscreen (Bug#14627).
15
162013-08-24 Paul Eggert <eggert@cs.ucla.edu>
17
18 System-dependent integer overflow fixes.
19 * process.c (Fset_process_window_size): Signal an error if
20 the window size is outside the range supported by the lower level.
21 * sysdep.c (set_window_size): Return negative on error,
22 nonnegative on success, rather than -1, 0, 1 on not in system,
23 failure, success. This is simpler. Caller changed.
24 (serial_configure): Remove unnecessary initialization of local.
25 (procfs_get_total_memory) [GNU_LINUX]: Don't assume system memory
26 size fits in unsigned long; this isn't true on some 32-bit hosts.
27 Avoid buffer overrun if some future version of /proc/meminfo has a
28 variable name longer than 20 bytes.
29 (system_process_attributes) [__FreeBSD__]:
30 Don't assume hw.availpages fits in 'int'.
31
322013-08-23 Paul Eggert <eggert@cs.ucla.edu>
33
34 Don't let very long directory names overrun the stack.
35 Fix some related minor problems involving "//", vfork.
36 * callproc.c (encode_current_directory): New function.
37 (call_process): Don't append "/"; not needed.
38 * fileio.c (file_name_as_directory_slop): New constant.
39 (file_name_as_directory): Allow SRC to be longer than SRCLEN;
40 this can save the caller having to alloca.
41 (Ffile_name_as_directory, Fdirectory_file_name, Fexpand_file_name):
42 Use SAFE_ALLOCA, not alloca.
43 (directory_file_name, Fexpand_file_name): Leave leading "//"
44 alone, since it can be special even on POSIX platforms.
45 * callproc.c (call_process):
46 * process.c (Fformat_network_address):
47 * sysdep.c (sys_subshell):
48 Use encode_current_directory rather than rolling our own.
49 (create_process): No need to encode directory; caller does that now.
50 * process.h (encode_current_directory): New decl.
51 * sysdep.c (sys_subshell): Work even if vfork trashes saved_handlers.
52 Rework to avoid 'goto xyzzy;'.
53
542013-08-23 Eli Zaretskii <eliz@gnu.org>
55
56 * xdisp.c (handle_face_prop): If the default face was remapped use
57 the remapped face for strings from prefix properties. (Bug#15155)
58
592013-08-23 Dmitry Antipov <dmantipov@yandex.ru>
60
61 Minor cleanup for redisplay interface and few related functions.
62 * frame.h (enum text_cursor_kinds): Move from here...
63 * dispextern.h (enum text_cursor_kinds): ...to here.
64 (toplevel): Drop unnecessary declarations.
65 (struct redisplay_interface): Use bool and enum text_cursor_kinds
66 in update_window_end_hook and draw_window_cursor functions.
67 (display_and_set_cursor, x_update_cursor): Adjust prototypes.
68 * nsterm.m (ns_update_window_end, ns_draw_window_cursor):
69 * w32term.c (x_update_window_end,w32_draw_window_cursor):
70 * xterm.c (x_update_window_end, x_draw_window_cursor):
71 * xdisp.c (display_and_set_cursor, update_window_cursor)
72 (update_cursor_in_window_tree, x_update_cursor): Use bool and
73 enum text_cursor_kinds where appropriate.
74
752013-08-23 Dmitry Antipov <dmantipov@yandex.ru>
76
77 Redesign redisplay interface to drop updated_row and updated_area.
78 * dispextern.h (updated_row, updated_area): Remove declaration.
79 (struct redisplay_interface): Pass glyph row and row area parameters
80 to write_glyphs, insert_glyphs and clear_end_of_line functions.
81 (x_write_glyphs, x_insert_glyphs, x_clear_end_of_line):
82 Adjust prototypes.
83 * dispnew.c (updated_row, updated_area): Remove.
84 (redraw_overlapped_rows, update_window_line): Adjust user.
85 (update_marginal_area, update_text_area): Likewise. Pass updated row
86 as a parameter. Prefer enum glyph_row_area to int where appropriate.
87 * xdisp.c (x_write_glyphs, x_insert_glyphs, x_clear_end_of_line):
88 Adjust users.
89
902013-08-22 Paul Eggert <eggert@cs.ucla.edu>
91
92 * process.c (flush_pending_output): Remove stub.
93 All uses removed.
94
952013-08-21 Paul Eggert <eggert@cs.ucla.edu>
96
97 * callproc.c: Fix race that killed background processes (Bug#15144).
98 (call_process): New arg TEMPFILE_INDEX. Callers changed.
99 Record deleted process-id in critical section, not afterwards.
100 Don't mistakenly kill process created by a call-process invocation
101 that discards output and does not wait.
102
1032013-08-21 Dmitry Antipov <dmantipov@yandex.ru>
104
105 Fix compilation with GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE
106 and GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES.
107 * alloc.c (toplevel): Remove unnecessary nested #if...#endif.
108 (mark_maybe_object) [!GC_MARK_STACK]: Define to emacs_abort
109 to shut up compiler in mark_object.
110 (dump_zombies): Convert to global and add EXTERNALLY_VISIBLE.
111
1122013-08-21 Paul Eggert <eggert@cs.ucla.edu>
113
114 * process.c (allocate_pty) [PTY_OPEN]: Set fd's FD_CLOEXEC flag.
115 We can't portably rely on PTY_OPEN doing that, even if
116 it calls posix_openpt with O_CLOEXEC.
117
1182013-08-20 Kenichi Handa <handa@gnu.org>
119
120 * character.c (string_char): Improve commentary.
121
12013-08-20 Paul Eggert <eggert@cs.ucla.edu> 1222013-08-20 Paul Eggert <eggert@cs.ucla.edu>
2 123
3 * image.c (SIGNATURE_DIGESTSIZE): Remove. 124 * image.c (SIGNATURE_DIGESTSIZE): Remove.
diff --git a/src/alloc.c b/src/alloc.c
index 4cc9b3e1a13..9b5f2955aa5 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -314,7 +314,6 @@ static void *min_heap_address, *max_heap_address;
314static struct mem_node mem_z; 314static struct mem_node mem_z;
315#define MEM_NIL &mem_z 315#define MEM_NIL &mem_z
316 316
317#if GC_MARK_STACK || defined GC_MALLOC_CHECK
318static struct mem_node *mem_insert (void *, void *, enum mem_type); 317static struct mem_node *mem_insert (void *, void *, enum mem_type);
319static void mem_insert_fixup (struct mem_node *); 318static void mem_insert_fixup (struct mem_node *);
320static void mem_rotate_left (struct mem_node *); 319static void mem_rotate_left (struct mem_node *);
@@ -322,7 +321,6 @@ static void mem_rotate_right (struct mem_node *);
322static void mem_delete (struct mem_node *); 321static void mem_delete (struct mem_node *);
323static void mem_delete_fixup (struct mem_node *); 322static void mem_delete_fixup (struct mem_node *);
324static struct mem_node *mem_find (void *); 323static struct mem_node *mem_find (void *);
325#endif
326 324
327#endif /* GC_MARK_STACK || GC_MALLOC_CHECK */ 325#endif /* GC_MARK_STACK || GC_MALLOC_CHECK */
328 326
@@ -4237,6 +4235,10 @@ live_buffer_p (struct mem_node *m, void *p)
4237 4235
4238#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES 4236#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
4239 4237
4238/* Currently not used, but may be called from gdb. */
4239
4240void dump_zombies (void) EXTERNALLY_VISIBLE;
4241
4240/* Array of objects that are kept alive because the C stack contains 4242/* Array of objects that are kept alive because the C stack contains
4241 a pattern that looks like a reference to them . */ 4243 a pattern that looks like a reference to them . */
4242 4244
@@ -4619,7 +4621,7 @@ check_gcpros (void)
4619 4621
4620#elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES 4622#elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
4621 4623
4622static void 4624void
4623dump_zombies (void) 4625dump_zombies (void)
4624{ 4626{
4625 int i; 4627 int i;
@@ -4766,6 +4768,10 @@ flush_stack_call_func (void (*func) (void *arg), void *arg)
4766 eassert (current_thread == self); 4768 eassert (current_thread == self);
4767} 4769}
4768 4770
4771#else /* GC_MARK_STACK == 0 */
4772
4773#define mark_maybe_object(obj) emacs_abort ()
4774
4769#endif /* GC_MARK_STACK != 0 */ 4775#endif /* GC_MARK_STACK != 0 */
4770 4776
4771 4777
diff --git a/src/callproc.c b/src/callproc.c
index 2a9162cb5cc..d4b4a26ec3a 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -102,7 +102,7 @@ enum
102 CALLPROC_FDS 102 CALLPROC_FDS
103 }; 103 };
104 104
105static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int); 105static Lisp_Object call_process (ptrdiff_t, Lisp_Object *, int, ptrdiff_t);
106 106
107/* Block SIGCHLD. */ 107/* Block SIGCHLD. */
108 108
@@ -123,6 +123,37 @@ unblock_child_signal (void)
123 pthread_sigmask (SIG_SETMASK, &empty_mask, 0); 123 pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
124} 124}
125 125
126/* Return the current buffer's working directory, or the home
127 directory if it's unreachable, as a string suitable for a system call.
128 Signal an error if the result would not be an accessible directory. */
129
130Lisp_Object
131encode_current_directory (void)
132{
133 Lisp_Object dir;
134 struct gcpro gcpro1;
135
136 dir = BVAR (current_buffer, directory);
137 GCPRO1 (dir);
138
139 dir = Funhandled_file_name_directory (dir);
140
141 /* If the file name handler says that dir is unreachable, use
142 a sensible default. */
143 if (NILP (dir))
144 dir = build_string ("~");
145
146 dir = expand_and_dir_to_file (dir, Qnil);
147
148 if (STRING_MULTIBYTE (dir))
149 dir = ENCODE_FILE (dir);
150 if (! file_accessible_directory_p (SSDATA (dir)))
151 report_file_error ("Setting current directory",
152 BVAR (current_buffer, directory));
153
154 RETURN_UNGCPRO (dir);
155}
156
126/* If P is reapable, record it as a deleted process and kill it. 157/* If P is reapable, record it as a deleted process and kill it.
127 Do this in a critical section. Unless PID is wedged it will be 158 Do this in a critical section. Unless PID is wedged it will be
128 reaped on receipt of the first SIGCHLD after the critical section. */ 159 reaped on receipt of the first SIGCHLD after the critical section. */
@@ -248,14 +279,20 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
248 report_file_error ("Opening process input file", infile); 279 report_file_error ("Opening process input file", infile);
249 record_unwind_protect_int (close_file_unwind, filefd); 280 record_unwind_protect_int (close_file_unwind, filefd);
250 UNGCPRO; 281 UNGCPRO;
251 return unbind_to (count, call_process (nargs, args, filefd)); 282 return unbind_to (count, call_process (nargs, args, filefd, -1));
252} 283}
253 284
254/* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file. 285/* Like Fcall_process (NARGS, ARGS), except use FILEFD as the input file.
286
287 If TEMPFILE_INDEX is nonnegative, it is the specpdl index of an
288 unwinder that is intended to remove the input temporary file; in
289 this case NARGS must be at least 2 and ARGS[1] is the file's name.
290
255 At entry, the specpdl stack top entry must be close_file_unwind (FILEFD). */ 291 At entry, the specpdl stack top entry must be close_file_unwind (FILEFD). */
256 292
257static Lisp_Object 293static Lisp_Object
258call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd) 294call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
295 ptrdiff_t tempfile_index)
259{ 296{
260 Lisp_Object buffer, current_dir, path; 297 Lisp_Object buffer, current_dir, path;
261 bool display_p; 298 bool display_p;
@@ -402,24 +439,10 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd)
402 { 439 {
403 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 440 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
404 441
405 current_dir = BVAR (current_buffer, directory); 442 current_dir = encode_current_directory ();
406 443
407 GCPRO4 (buffer, current_dir, error_file, output_file); 444 GCPRO4 (buffer, current_dir, error_file, output_file);
408 445
409 current_dir = Funhandled_file_name_directory (current_dir);
410 if (NILP (current_dir))
411 /* If the file name handler says that current_dir is unreachable, use
412 a sensible default. */
413 current_dir = build_string ("~/");
414 current_dir = expand_and_dir_to_file (current_dir, Qnil);
415 current_dir = Ffile_name_as_directory (current_dir);
416
417 if (NILP (Ffile_accessible_directory_p (current_dir)))
418 report_file_error ("Setting current directory",
419 BVAR (current_buffer, directory));
420
421 if (STRING_MULTIBYTE (current_dir))
422 current_dir = ENCODE_FILE (current_dir);
423 if (STRINGP (error_file) && STRING_MULTIBYTE (error_file)) 446 if (STRINGP (error_file) && STRING_MULTIBYTE (error_file))
424 error_file = ENCODE_FILE (error_file); 447 error_file = ENCODE_FILE (error_file);
425 if (STRINGP (output_file) && STRING_MULTIBYTE (output_file)) 448 if (STRINGP (output_file) && STRING_MULTIBYTE (output_file))
@@ -661,7 +684,22 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd)
661 child_errno = errno; 684 child_errno = errno;
662 685
663 if (pid > 0) 686 if (pid > 0)
664 synch_process_pid = pid; 687 {
688 synch_process_pid = pid;
689
690 if (INTEGERP (buffer))
691 {
692 if (tempfile_index < 0)
693 record_deleted_pid (pid, Qnil);
694 else
695 {
696 eassert (1 < nargs);
697 record_deleted_pid (pid, args[1]);
698 clear_unwind_protect (tempfile_index);
699 }
700 synch_process_pid = 0;
701 }
702 }
665 703
666 unblock_child_signal (); 704 unblock_child_signal ();
667 unblock_input (); 705 unblock_input ();
@@ -1030,7 +1068,7 @@ If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.
1030usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */) 1068usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &rest ARGS) */)
1031 (ptrdiff_t nargs, Lisp_Object *args) 1069 (ptrdiff_t nargs, Lisp_Object *args)
1032{ 1070{
1033 struct gcpro gcpro1, gcpro2; 1071 struct gcpro gcpro1;
1034 Lisp_Object infile, val; 1072 Lisp_Object infile, val;
1035 ptrdiff_t count = SPECPDL_INDEX (); 1073 ptrdiff_t count = SPECPDL_INDEX ();
1036 Lisp_Object start = args[0]; 1074 Lisp_Object start = args[0];
@@ -1061,8 +1099,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
1061 record_unwind_protect_int (close_file_unwind, fd); 1099 record_unwind_protect_int (close_file_unwind, fd);
1062 } 1100 }
1063 1101
1064 val = infile; 1102 GCPRO1 (infile);
1065 GCPRO2 (infile, val);
1066 1103
1067 if (nargs > 3 && !NILP (args[3])) 1104 if (nargs > 3 && !NILP (args[3]))
1068 Fdelete_region (start, end); 1105 Fdelete_region (start, end);
@@ -1079,16 +1116,7 @@ usage: (call-process-region START END PROGRAM &optional DELETE BUFFER DISPLAY &r
1079 } 1116 }
1080 args[1] = infile; 1117 args[1] = infile;
1081 1118
1082 val = call_process (nargs, args, fd); 1119 val = call_process (nargs, args, fd, empty_input ? -1 : count);
1083
1084 if (!empty_input && 4 < nargs
1085 && (INTEGERP (CONSP (args[4]) ? XCAR (args[4]) : args[4])))
1086 {
1087 record_deleted_pid (synch_process_pid, infile);
1088 synch_process_pid = 0;
1089 clear_unwind_protect (count);
1090 }
1091
1092 RETURN_UNGCPRO (unbind_to (count, val)); 1120 RETURN_UNGCPRO (unbind_to (count, val));
1093} 1121}
1094 1122
@@ -1165,23 +1193,21 @@ child_setup (int in, int out, int err, char **new_argv, bool set_pgrp,
1165 static variables as if the superior had done alloca and will be 1193 static variables as if the superior had done alloca and will be
1166 cleaned up in the usual way. */ 1194 cleaned up in the usual way. */
1167 { 1195 {
1168 register char *temp; 1196 char *temp;
1169 size_t i; /* size_t, because ptrdiff_t might overflow here! */ 1197 ptrdiff_t i;
1170 1198
1171 i = SBYTES (current_dir); 1199 i = SBYTES (current_dir);
1172#ifdef MSDOS 1200#ifdef MSDOS
1173 /* MSDOS must have all environment variables malloc'ed, because 1201 /* MSDOS must have all environment variables malloc'ed, because
1174 low-level libc functions that launch subsidiary processes rely 1202 low-level libc functions that launch subsidiary processes rely
1175 on that. */ 1203 on that. */
1176 pwd_var = xmalloc (i + 6); 1204 pwd_var = xmalloc (i + 5);
1177#else 1205#else
1178 pwd_var = alloca (i + 6); 1206 pwd_var = alloca (i + 5);
1179#endif 1207#endif
1180 temp = pwd_var + 4; 1208 temp = pwd_var + 4;
1181 memcpy (pwd_var, "PWD=", 4); 1209 memcpy (pwd_var, "PWD=", 4);
1182 memcpy (temp, SDATA (current_dir), i); 1210 strcpy (temp, SSDATA (current_dir));
1183 if (!IS_DIRECTORY_SEP (temp[i - 1])) temp[i++] = DIRECTORY_SEP;
1184 temp[i] = 0;
1185 1211
1186#ifndef DOS_NT 1212#ifndef DOS_NT
1187 /* We can't signal an Elisp error here; we're in a vfork. Since 1213 /* We can't signal an Elisp error here; we're in a vfork. Since
diff --git a/src/character.c b/src/character.c
index b2caaa290af..1bde2364e37 100644
--- a/src/character.c
+++ b/src/character.c
@@ -174,11 +174,14 @@ string_char (const unsigned char *p, const unsigned char **advanced, int *len)
174 174
175 if (*p < 0x80 || ! (*p & 0x20) || ! (*p & 0x10)) 175 if (*p < 0x80 || ! (*p & 0x20) || ! (*p & 0x10))
176 { 176 {
177 /* 1-, 2-, and 3-byte sequences can be handled by the macro. */
177 c = STRING_CHAR_ADVANCE (p); 178 c = STRING_CHAR_ADVANCE (p);
178 } 179 }
179 else if (! (*p & 0x08)) 180 else if (! (*p & 0x08))
180 { 181 {
181 c = ((((p)[0] & 0xF) << 18) 182 /* A 4-byte sequence of this form:
183 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
184 c = ((((p)[0] & 0x7) << 18)
182 | (((p)[1] & 0x3F) << 12) 185 | (((p)[1] & 0x3F) << 12)
183 | (((p)[2] & 0x3F) << 6) 186 | (((p)[2] & 0x3F) << 6)
184 | ((p)[3] & 0x3F)); 187 | ((p)[3] & 0x3F));
@@ -186,7 +189,14 @@ string_char (const unsigned char *p, const unsigned char **advanced, int *len)
186 } 189 }
187 else 190 else
188 { 191 {
189 c = ((((p)[1] & 0x3F) << 18) 192 /* A 5-byte sequence of this form:
193
194 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
195
196 Note that the top 4 `x's are always 0, so shifting p[1] can
197 never exceed the maximum valid character codepoint. */
198 c = (/* (((p)[0] & 0x3) << 24) ... always 0, so no need to shift. */
199 (((p)[1] & 0x3F) << 18)
190 | (((p)[2] & 0x3F) << 12) 200 | (((p)[2] & 0x3F) << 12)
191 | (((p)[3] & 0x3F) << 6) 201 | (((p)[3] & 0x3F) << 6)
192 | ((p)[4] & 0x3F)); 202 | ((p)[4] & 0x3F));
diff --git a/src/dispextern.h b/src/dispextern.h
index 7a4fa2ea774..6e1d85de924 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -95,18 +95,17 @@ typedef int Cursor;
95#define NativeRectangle int 95#define NativeRectangle int
96#endif 96#endif
97 97
98/* Structure forward declarations. Some are here because function 98/* Text cursor types. */
99 prototypes below reference structure types before their definition
100 in this file. Some are here because not every file including
101 dispextern.h also includes frame.h and windows.h. */
102
103struct glyph;
104struct glyph_row;
105struct glyph_matrix;
106struct glyph_pool;
107struct frame;
108struct window;
109 99
100enum text_cursor_kinds
101{
102 DEFAULT_CURSOR = -2,
103 NO_CURSOR = -1,
104 FILLED_BOX_CURSOR,
105 HOLLOW_BOX_CURSOR,
106 BAR_CURSOR,
107 HBAR_CURSOR
108};
110 109
111/* Values returned from coordinates_in_window. */ 110/* Values returned from coordinates_in_window. */
112 111
@@ -1197,11 +1196,6 @@ extern bool fonts_changed_p;
1197 1196
1198extern struct glyph space_glyph; 1197extern struct glyph space_glyph;
1199 1198
1200/* Glyph row and area updated by update_window_line. */
1201
1202extern struct glyph_row *updated_row;
1203extern int updated_area;
1204
1205/* Non-zero means last display completed. Zero means it was 1199/* Non-zero means last display completed. Zero means it was
1206 preempted. */ 1200 preempted. */
1207 1201
@@ -2713,12 +2707,17 @@ struct redisplay_interface
2713 2707
2714 /* Write or insert LEN glyphs from STRING at the nominal output 2708 /* Write or insert LEN glyphs from STRING at the nominal output
2715 position. */ 2709 position. */
2716 void (*write_glyphs) (struct window *w, struct glyph *string, int len); 2710 void (*write_glyphs) (struct window *w, struct glyph_row *row,
2717 void (*insert_glyphs) (struct window *w, struct glyph *start, int len); 2711 struct glyph *string, enum glyph_row_area area,
2712 int len);
2713 void (*insert_glyphs) (struct window *w, struct glyph_row *row,
2714 struct glyph *start, enum glyph_row_area area,
2715 int len);
2718 2716
2719 /* Clear from nominal output position to X. X < 0 means clear 2717 /* Clear from nominal output position to X. X < 0 means clear
2720 to right end of display. */ 2718 to right end of display. */
2721 void (*clear_end_of_line) (struct window *w, int x); 2719 void (*clear_end_of_line) (struct window *w, struct glyph_row *row,
2720 enum glyph_row_area area, int x);
2722 2721
2723 /* Function to call to scroll the display as described by RUN on 2722 /* Function to call to scroll the display as described by RUN on
2724 window W. */ 2723 window W. */
@@ -2739,8 +2738,8 @@ struct redisplay_interface
2739 MOUSE_FACE_OVERWRITTEN_P non-zero means that some lines in W 2738 MOUSE_FACE_OVERWRITTEN_P non-zero means that some lines in W
2740 that contained glyphs in mouse-face were overwritten, so we 2739 that contained glyphs in mouse-face were overwritten, so we
2741 have to update the mouse highlight. */ 2740 have to update the mouse highlight. */
2742 void (*update_window_end_hook) (struct window *w, int cursor_on_p, 2741 void (*update_window_end_hook) (struct window *w, bool cursor_on_p,
2743 int mouse_face_overwritten_p); 2742 bool mouse_face_overwritten_p);
2744 2743
2745 /* Move cursor to row/column position VPOS/HPOS, pixel coordinates 2744 /* Move cursor to row/column position VPOS/HPOS, pixel coordinates
2746 Y/X. HPOS/VPOS are window-relative row and column numbers and X/Y 2745 Y/X. HPOS/VPOS are window-relative row and column numbers and X/Y
@@ -2799,10 +2798,10 @@ struct redisplay_interface
2799 0, don't draw cursor. If ACTIVE_P is 1, system caret 2798 0, don't draw cursor. If ACTIVE_P is 1, system caret
2800 should track this cursor (when applicable). */ 2799 should track this cursor (when applicable). */
2801 void (*draw_window_cursor) (struct window *w, 2800 void (*draw_window_cursor) (struct window *w,
2802 struct glyph_row *glyph_row, 2801 struct glyph_row *glyph_row,
2803 int x, int y, 2802 int x, int y,
2804 int cursor_type, int cursor_width, 2803 enum text_cursor_kinds cursor_type,
2805 int on_p, int active_p); 2804 int cursor_width, bool on_p, bool active_p);
2806 2805
2807/* Draw vertical border for window W from (X,Y_0) to (X,Y_1). */ 2806/* Draw vertical border for window W from (X,Y_0) to (X,Y_1). */
2808 void (*draw_vertical_window_border) (struct window *w, 2807 void (*draw_vertical_window_border) (struct window *w,
@@ -3178,9 +3177,12 @@ extern void x_get_glyph_overhangs (struct glyph *, struct frame *,
3178 int *, int *); 3177 int *, int *);
3179extern void x_produce_glyphs (struct it *); 3178extern void x_produce_glyphs (struct it *);
3180 3179
3181extern void x_write_glyphs (struct window *, struct glyph *, int); 3180extern void x_write_glyphs (struct window *, struct glyph_row *,
3182extern void x_insert_glyphs (struct window *, struct glyph *, int len); 3181 struct glyph *, enum glyph_row_area, int);
3183extern void x_clear_end_of_line (struct window *, int); 3182extern void x_insert_glyphs (struct window *, struct glyph_row *,
3183 struct glyph *, enum glyph_row_area, int);
3184extern void x_clear_end_of_line (struct window *, struct glyph_row *,
3185 enum glyph_row_area, int);
3184 3186
3185extern struct cursor_pos output_cursor; 3187extern struct cursor_pos output_cursor;
3186 3188
@@ -3192,13 +3194,12 @@ extern void draw_phys_cursor_glyph (struct window *,
3192extern void get_phys_cursor_geometry (struct window *, struct glyph_row *, 3194extern void get_phys_cursor_geometry (struct window *, struct glyph_row *,
3193 struct glyph *, int *, int *, int *); 3195 struct glyph *, int *, int *, int *);
3194extern void erase_phys_cursor (struct window *); 3196extern void erase_phys_cursor (struct window *);
3195extern void display_and_set_cursor (struct window *, 3197extern void display_and_set_cursor (struct window *, bool, int, int, int, int);
3196 int, int, int, int, int);
3197 3198
3198extern void set_output_cursor (struct cursor_pos *); 3199extern void set_output_cursor (struct cursor_pos *);
3199extern void x_cursor_to (struct window *, int, int, int, int); 3200extern void x_cursor_to (struct window *, int, int, int, int);
3200 3201
3201extern void x_update_cursor (struct frame *, int); 3202extern void x_update_cursor (struct frame *, bool);
3202extern void x_clear_cursor (struct window *); 3203extern void x_clear_cursor (struct window *);
3203extern void x_draw_vertical_border (struct window *w); 3204extern void x_draw_vertical_border (struct window *w);
3204 3205
diff --git a/src/dispnew.c b/src/dispnew.c
index b7e44e425bf..3c6b89bde68 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -135,11 +135,6 @@ struct frame *last_nonminibuf_frame;
135 135
136static bool delayed_size_change; 136static bool delayed_size_change;
137 137
138/* Glyph row updated in update_window_line, and area that is updated. */
139
140struct glyph_row *updated_row;
141int updated_area;
142
143/* A glyph for a space. */ 138/* A glyph for a space. */
144 139
145struct glyph space_glyph; 140struct glyph space_glyph;
@@ -3230,14 +3225,12 @@ redraw_overlapped_rows (struct window *w, int yb)
3230 3225
3231 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) 3226 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
3232 { 3227 {
3233 updated_row = row;
3234 updated_area = area;
3235 FRAME_RIF (f)->cursor_to (w, i, 0, row->y, 3228 FRAME_RIF (f)->cursor_to (w, i, 0, row->y,
3236 area == TEXT_AREA ? row->x : 0); 3229 area == TEXT_AREA ? row->x : 0);
3237 if (row->used[area]) 3230 if (row->used[area])
3238 FRAME_RIF (f)->write_glyphs (w, row->glyphs[area], 3231 FRAME_RIF (f)->write_glyphs (w, row, row->glyphs[area],
3239 row->used[area]); 3232 area, row->used[area]);
3240 FRAME_RIF (f)->clear_end_of_line (w, -1); 3233 FRAME_RIF (f)->clear_end_of_line (w, row, area, -1);
3241 } 3234 }
3242 3235
3243 row->overlapped_p = 0; 3236 row->overlapped_p = 0;
@@ -3511,22 +3504,20 @@ update_window (struct window *w, bool force_p)
3511 AREA can be either LEFT_MARGIN_AREA or RIGHT_MARGIN_AREA. */ 3504 AREA can be either LEFT_MARGIN_AREA or RIGHT_MARGIN_AREA. */
3512 3505
3513static void 3506static void
3514update_marginal_area (struct window *w, int area, int vpos) 3507update_marginal_area (struct window *w, struct glyph_row *updated_row,
3508 enum glyph_row_area area, int vpos)
3515{ 3509{
3516 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); 3510 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
3517 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); 3511 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
3518 3512
3519 /* Let functions in xterm.c know what area subsequent X positions
3520 will be relative to. */
3521 updated_area = area;
3522
3523 /* Set cursor to start of glyphs, write them, and clear to the end 3513 /* Set cursor to start of glyphs, write them, and clear to the end
3524 of the area. I don't think that something more sophisticated is 3514 of the area. I don't think that something more sophisticated is
3525 necessary here, since marginal areas will not be the default. */ 3515 necessary here, since marginal areas will not be the default. */
3526 rif->cursor_to (w, vpos, 0, desired_row->y, 0); 3516 rif->cursor_to (w, vpos, 0, desired_row->y, 0);
3527 if (desired_row->used[area]) 3517 if (desired_row->used[area])
3528 rif->write_glyphs (w, desired_row->glyphs[area], desired_row->used[area]); 3518 rif->write_glyphs (w, updated_row, desired_row->glyphs[area],
3529 rif->clear_end_of_line (w, -1); 3519 area, desired_row->used[area]);
3520 rif->clear_end_of_line (w, updated_row, area, -1);
3530} 3521}
3531 3522
3532 3523
@@ -3534,17 +3525,13 @@ update_marginal_area (struct window *w, int area, int vpos)
3534 Value is true if display has changed. */ 3525 Value is true if display has changed. */
3535 3526
3536static bool 3527static bool
3537update_text_area (struct window *w, int vpos) 3528update_text_area (struct window *w, struct glyph_row *updated_row, int vpos)
3538{ 3529{
3539 struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos); 3530 struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos);
3540 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); 3531 struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos);
3541 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); 3532 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
3542 bool changed_p = 0; 3533 bool changed_p = 0;
3543 3534
3544 /* Let functions in xterm.c know what area subsequent X positions
3545 will be relative to. */
3546 updated_area = TEXT_AREA;
3547
3548 /* If rows are at different X or Y, or rows have different height, 3535 /* If rows are at different X or Y, or rows have different height,
3549 or the current row is marked invalid, write the entire line. */ 3536 or the current row is marked invalid, write the entire line. */
3550 if (!current_row->enabled_p 3537 if (!current_row->enabled_p
@@ -3567,11 +3554,11 @@ update_text_area (struct window *w, int vpos)
3567 rif->cursor_to (w, vpos, 0, desired_row->y, desired_row->x); 3554 rif->cursor_to (w, vpos, 0, desired_row->y, desired_row->x);
3568 3555
3569 if (desired_row->used[TEXT_AREA]) 3556 if (desired_row->used[TEXT_AREA])
3570 rif->write_glyphs (w, desired_row->glyphs[TEXT_AREA], 3557 rif->write_glyphs (w, updated_row, desired_row->glyphs[TEXT_AREA],
3571 desired_row->used[TEXT_AREA]); 3558 TEXT_AREA, desired_row->used[TEXT_AREA]);
3572 3559
3573 /* Clear to end of window. */ 3560 /* Clear to end of window. */
3574 rif->clear_end_of_line (w, -1); 3561 rif->clear_end_of_line (w, updated_row, TEXT_AREA, -1);
3575 changed_p = 1; 3562 changed_p = 1;
3576 3563
3577 /* This erases the cursor. We do this here because 3564 /* This erases the cursor. We do this here because
@@ -3708,7 +3695,8 @@ update_text_area (struct window *w, int vpos)
3708 } 3695 }
3709 3696
3710 rif->cursor_to (w, vpos, start_hpos, desired_row->y, start_x); 3697 rif->cursor_to (w, vpos, start_hpos, desired_row->y, start_x);
3711 rif->write_glyphs (w, start, i - start_hpos); 3698 rif->write_glyphs (w, updated_row, start,
3699 TEXT_AREA, i - start_hpos);
3712 changed_p = 1; 3700 changed_p = 1;
3713 } 3701 }
3714 } 3702 }
@@ -3717,7 +3705,8 @@ update_text_area (struct window *w, int vpos)
3717 if (i < desired_row->used[TEXT_AREA]) 3705 if (i < desired_row->used[TEXT_AREA])
3718 { 3706 {
3719 rif->cursor_to (w, vpos, i, desired_row->y, x); 3707 rif->cursor_to (w, vpos, i, desired_row->y, x);
3720 rif->write_glyphs (w, desired_glyph, desired_row->used[TEXT_AREA] - i); 3708 rif->write_glyphs (w, updated_row, desired_glyph,
3709 TEXT_AREA, desired_row->used[TEXT_AREA] - i);
3721 changed_p = 1; 3710 changed_p = 1;
3722 } 3711 }
3723 3712
@@ -3739,7 +3728,7 @@ update_text_area (struct window *w, int vpos)
3739 if (i >= desired_row->used[TEXT_AREA]) 3728 if (i >= desired_row->used[TEXT_AREA])
3740 rif->cursor_to (w, vpos, i, desired_row->y, 3729 rif->cursor_to (w, vpos, i, desired_row->y,
3741 desired_row->pixel_width); 3730 desired_row->pixel_width);
3742 rif->clear_end_of_line (w, -1); 3731 rif->clear_end_of_line (w, updated_row, TEXT_AREA, -1);
3743 changed_p = 1; 3732 changed_p = 1;
3744 } 3733 }
3745 else if (desired_row->pixel_width < current_row->pixel_width) 3734 else if (desired_row->pixel_width < current_row->pixel_width)
@@ -3767,7 +3756,7 @@ update_text_area (struct window *w, int vpos)
3767 } 3756 }
3768 else 3757 else
3769 xlim = current_row->pixel_width; 3758 xlim = current_row->pixel_width;
3770 rif->clear_end_of_line (w, xlim); 3759 rif->clear_end_of_line (w, updated_row, TEXT_AREA, xlim);
3771 changed_p = 1; 3760 changed_p = 1;
3772 } 3761 }
3773 } 3762 }
@@ -3786,10 +3775,6 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
3786 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w))); 3775 struct redisplay_interface *rif = FRAME_RIF (XFRAME (WINDOW_FRAME (w)));
3787 bool changed_p = 0; 3776 bool changed_p = 0;
3788 3777
3789 /* Set the row being updated. This is important to let xterm.c
3790 know what line height values are in effect. */
3791 updated_row = desired_row;
3792
3793 /* A row can be completely invisible in case a desired matrix was 3778 /* A row can be completely invisible in case a desired matrix was
3794 built with a vscroll and then make_cursor_line_fully_visible shifts 3779 built with a vscroll and then make_cursor_line_fully_visible shifts
3795 the matrix. Make sure to make such rows current anyway, since 3780 the matrix. Make sure to make such rows current anyway, since
@@ -3803,7 +3788,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
3803 if (!desired_row->full_width_p && w->left_margin_cols > 0) 3788 if (!desired_row->full_width_p && w->left_margin_cols > 0)
3804 { 3789 {
3805 changed_p = 1; 3790 changed_p = 1;
3806 update_marginal_area (w, LEFT_MARGIN_AREA, vpos); 3791 update_marginal_area (w, desired_row, LEFT_MARGIN_AREA, vpos);
3807 /* Setting this flag will ensure the vertical border, if 3792 /* Setting this flag will ensure the vertical border, if
3808 any, between this window and the one on its left will be 3793 any, between this window and the one on its left will be
3809 redrawn. This is necessary because updating the left 3794 redrawn. This is necessary because updating the left
@@ -3812,7 +3797,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
3812 } 3797 }
3813 3798
3814 /* Update the display of the text area. */ 3799 /* Update the display of the text area. */
3815 if (update_text_area (w, vpos)) 3800 if (update_text_area (w, desired_row, vpos))
3816 { 3801 {
3817 changed_p = 1; 3802 changed_p = 1;
3818 if (current_row->mouse_face_p) 3803 if (current_row->mouse_face_p)
@@ -3823,7 +3808,7 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
3823 if (!desired_row->full_width_p && w->right_margin_cols > 0) 3808 if (!desired_row->full_width_p && w->right_margin_cols > 0)
3824 { 3809 {
3825 changed_p = 1; 3810 changed_p = 1;
3826 update_marginal_area (w, RIGHT_MARGIN_AREA, vpos); 3811 update_marginal_area (w, desired_row, RIGHT_MARGIN_AREA, vpos);
3827 } 3812 }
3828 3813
3829 /* Draw truncation marks etc. */ 3814 /* Draw truncation marks etc. */
@@ -3842,7 +3827,6 @@ update_window_line (struct window *w, int vpos, bool *mouse_face_overwritten_p)
3842 3827
3843 /* Update current_row from desired_row. */ 3828 /* Update current_row from desired_row. */
3844 make_current (w->desired_matrix, w->current_matrix, vpos); 3829 make_current (w->desired_matrix, w->current_matrix, vpos);
3845 updated_row = NULL;
3846 return changed_p; 3830 return changed_p;
3847} 3831}
3848 3832
diff --git a/src/fileio.c b/src/fileio.c
index 08caf102266..7cad8d29da2 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -504,6 +504,10 @@ get a current directory to run processes in. */)
504 return Ffile_name_directory (filename); 504 return Ffile_name_directory (filename);
505} 505}
506 506
507/* Maximum number of bytes that DST will be longer than SRC
508 in file_name_as_directory. This occurs when SRCLEN == 0. */
509enum { file_name_as_directory_slop = 2 };
510
507/* Convert from file name SRC of length SRCLEN to directory name in 511/* Convert from file name SRC of length SRCLEN to directory name in
508 DST. MULTIBYTE non-zero means the file name in SRC is a multibyte 512 DST. MULTIBYTE non-zero means the file name in SRC is a multibyte
509 string. On UNIX, just make sure there is a terminating /. Return 513 string. On UNIX, just make sure there is a terminating /. Return
@@ -521,14 +525,10 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen,
521 return 2; 525 return 2;
522 } 526 }
523 527
524 strcpy (dst, src); 528 memcpy (dst, src, srclen);
525
526 if (!IS_DIRECTORY_SEP (dst[srclen - 1])) 529 if (!IS_DIRECTORY_SEP (dst[srclen - 1]))
527 { 530 dst[srclen++] = DIRECTORY_SEP;
528 dst[srclen] = DIRECTORY_SEP; 531 dst[srclen] = 0;
529 dst[srclen + 1] = '\0';
530 srclen++;
531 }
532#ifdef DOS_NT 532#ifdef DOS_NT
533 dostounix_filename (dst, multibyte); 533 dostounix_filename (dst, multibyte);
534#endif 534#endif
@@ -547,7 +547,8 @@ For a Unix-syntax file name, just appends a slash. */)
547{ 547{
548 char *buf; 548 char *buf;
549 ptrdiff_t length; 549 ptrdiff_t length;
550 Lisp_Object handler; 550 Lisp_Object handler, val;
551 USE_SAFE_ALLOCA;
551 552
552 CHECK_STRING (file); 553 CHECK_STRING (file);
553 if (NILP (file)) 554 if (NILP (file))
@@ -569,10 +570,12 @@ For a Unix-syntax file name, just appends a slash. */)
569 if (!NILP (Vw32_downcase_file_names)) 570 if (!NILP (Vw32_downcase_file_names))
570 file = Fdowncase (file); 571 file = Fdowncase (file);
571#endif 572#endif
572 buf = alloca (SBYTES (file) + 10); 573 buf = SAFE_ALLOCA (SBYTES (file) + file_name_as_directory_slop + 1);
573 length = file_name_as_directory (buf, SSDATA (file), SBYTES (file), 574 length = file_name_as_directory (buf, SSDATA (file), SBYTES (file),
574 STRING_MULTIBYTE (file)); 575 STRING_MULTIBYTE (file));
575 return make_specified_string (buf, -1, length, STRING_MULTIBYTE (file)); 576 val = make_specified_string (buf, -1, length, STRING_MULTIBYTE (file));
577 SAFE_FREE ();
578 return val;
576} 579}
577 580
578/* Convert from directory name SRC of length SRCLEN to file name in 581/* Convert from directory name SRC of length SRCLEN to file name in
@@ -584,18 +587,17 @@ static ptrdiff_t
584directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte) 587directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte)
585{ 588{
586 /* Process as Unix format: just remove any final slash. 589 /* Process as Unix format: just remove any final slash.
587 But leave "/" unchanged; do not change it to "". */ 590 But leave "/" and "//" unchanged. */
588 strcpy (dst, src); 591 while (srclen > 1
589 if (srclen > 1
590 && IS_DIRECTORY_SEP (dst[srclen - 1])
591#ifdef DOS_NT 592#ifdef DOS_NT
592 && !IS_ANY_SEP (dst[srclen - 2]) 593 && !IS_ANY_SEP (src[srclen - 2])
593#endif 594#endif
594 ) 595 && IS_DIRECTORY_SEP (src[srclen - 1])
595 { 596 && ! (srclen == 2 && IS_DIRECTORY_SEP (src[0])))
596 dst[srclen - 1] = 0; 597 srclen--;
597 srclen--; 598
598 } 599 memcpy (dst, src, srclen);
600 dst[srclen] = 0;
599#ifdef DOS_NT 601#ifdef DOS_NT
600 dostounix_filename (dst, multibyte); 602 dostounix_filename (dst, multibyte);
601#endif 603#endif
@@ -613,7 +615,8 @@ In Unix-syntax, this function just removes the final slash. */)
613{ 615{
614 char *buf; 616 char *buf;
615 ptrdiff_t length; 617 ptrdiff_t length;
616 Lisp_Object handler; 618 Lisp_Object handler, val;
619 USE_SAFE_ALLOCA;
617 620
618 CHECK_STRING (directory); 621 CHECK_STRING (directory);
619 622
@@ -636,10 +639,12 @@ In Unix-syntax, this function just removes the final slash. */)
636 if (!NILP (Vw32_downcase_file_names)) 639 if (!NILP (Vw32_downcase_file_names))
637 directory = Fdowncase (directory); 640 directory = Fdowncase (directory);
638#endif 641#endif
639 buf = alloca (SBYTES (directory) + 20); 642 buf = SAFE_ALLOCA (SBYTES (directory) + 1);
640 length = directory_file_name (buf, SSDATA (directory), SBYTES (directory), 643 length = directory_file_name (buf, SSDATA (directory), SBYTES (directory),
641 STRING_MULTIBYTE (directory)); 644 STRING_MULTIBYTE (directory));
642 return make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory)); 645 val = make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory));
646 SAFE_FREE ();
647 return val;
643} 648}
644 649
645static const char make_temp_name_tbl[64] = 650static const char make_temp_name_tbl[64] =
@@ -837,6 +842,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
837 Lisp_Object handler, result, handled_name; 842 Lisp_Object handler, result, handled_name;
838 bool multibyte; 843 bool multibyte;
839 Lisp_Object hdir; 844 Lisp_Object hdir;
845 USE_SAFE_ALLOCA;
840 846
841 CHECK_STRING (name); 847 CHECK_STRING (name);
842 848
@@ -1011,11 +1017,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1011 || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3]) 1017 || (p[2] == '.' && (IS_DIRECTORY_SEP (p[3])
1012 || p[3] == 0)))) 1018 || p[3] == 0))))
1013 lose = 1; 1019 lose = 1;
1014 /* We want to replace multiple `/' in a row with a single 1020 /* Replace multiple slashes with a single one, except
1015 slash. */ 1021 leave leading "//" alone. */
1016 else if (p > nm 1022 else if (IS_DIRECTORY_SEP (p[0])
1017 && IS_DIRECTORY_SEP (p[0]) 1023 && IS_DIRECTORY_SEP (p[1])
1018 && IS_DIRECTORY_SEP (p[1])) 1024 && (p != nm || IS_DIRECTORY_SEP (p[2])))
1019 lose = 1; 1025 lose = 1;
1020 p++; 1026 p++;
1021 } 1027 }
@@ -1098,10 +1104,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1098 else /* ~user/filename */ 1104 else /* ~user/filename */
1099 { 1105 {
1100 char *o, *p; 1106 char *o, *p;
1101 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++); 1107 for (p = nm; *p && !IS_DIRECTORY_SEP (*p); p++)
1102 o = alloca (p - nm + 1); 1108 continue;
1109 o = SAFE_ALLOCA (p - nm + 1);
1103 memcpy (o, nm, p - nm); 1110 memcpy (o, nm, p - nm);
1104 o [p - nm] = 0; 1111 o[p - nm] = 0;
1105 1112
1106 block_input (); 1113 block_input ();
1107 pw = getpwnam (o + 1); 1114 pw = getpwnam (o + 1);
@@ -1217,7 +1224,8 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1217 if (!IS_DIRECTORY_SEP (nm[0])) 1224 if (!IS_DIRECTORY_SEP (nm[0]))
1218 { 1225 {
1219 ptrdiff_t newlen = strlen (newdir); 1226 ptrdiff_t newlen = strlen (newdir);
1220 char *tmp = alloca (newlen + strlen (nm) + 2); 1227 char *tmp = alloca (newlen + file_name_as_directory_slop
1228 + strlen (nm) + 1);
1221 file_name_as_directory (tmp, newdir, newlen, multibyte); 1229 file_name_as_directory (tmp, newdir, newlen, multibyte);
1222 strcat (tmp, nm); 1230 strcat (tmp, nm);
1223 nm = tmp; 1231 nm = tmp;
@@ -1271,31 +1279,18 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1271 1279
1272 if (newdir) 1280 if (newdir)
1273 { 1281 {
1274 /* Get rid of any slash at the end of newdir, unless newdir is 1282 /* Ignore any slash at the end of newdir, unless newdir is
1275 just / or // (an incomplete UNC name). */ 1283 just "/" or "//". */
1276 length = strlen (newdir); 1284 length = strlen (newdir);
1277 tlen = length + 1; 1285 while (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
1278 if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1]) 1286 && ! (length == 2 && IS_DIRECTORY_SEP (newdir[0])))
1279#ifdef WINDOWSNT 1287 length--;
1280 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
1281#endif
1282 )
1283 {
1284 char *temp = alloca (length);
1285 memcpy (temp, newdir, length - 1);
1286 temp[length - 1] = 0;
1287 length--;
1288 newdir = temp;
1289 }
1290 } 1288 }
1291 else 1289 else
1292 { 1290 length = 0;
1293 length = 0;
1294 tlen = 0;
1295 }
1296 1291
1297 /* Now concatenate the directory and name to new space in the stack frame. */ 1292 /* Now concatenate the directory and name to new space in the stack frame. */
1298 tlen += strlen (nm) + 1; 1293 tlen = length + file_name_as_directory_slop + strlen (nm) + 1;
1299#ifdef DOS_NT 1294#ifdef DOS_NT
1300 /* Reserve space for drive specifier and escape prefix, since either 1295 /* Reserve space for drive specifier and escape prefix, since either
1301 or both may need to be inserted. (The Microsoft x86 compiler 1296 or both may need to be inserted. (The Microsoft x86 compiler
@@ -1303,7 +1298,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1303 target = alloca (tlen + 4); 1298 target = alloca (tlen + 4);
1304 target += 4; 1299 target += 4;
1305#else /* not DOS_NT */ 1300#else /* not DOS_NT */
1306 target = alloca (tlen); 1301 target = SAFE_ALLOCA (tlen);
1307#endif /* not DOS_NT */ 1302#endif /* not DOS_NT */
1308 *target = 0; 1303 *target = 0;
1309 1304
@@ -1320,7 +1315,10 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1320 if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0]) 1315 if (!(drive && nm[0] && IS_DIRECTORY_SEP (newdir[0])
1321 && newdir[1] == '\0')) 1316 && newdir[1] == '\0'))
1322#endif 1317#endif
1323 strcpy (target, newdir); 1318 {
1319 memcpy (target, newdir, length);
1320 target[length] = 0;
1321 }
1324 } 1322 }
1325 else 1323 else
1326 file_name_as_directory (target, newdir, length, multibyte); 1324 file_name_as_directory (target, newdir, length, multibyte);
@@ -1380,8 +1378,9 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1380 ++o; 1378 ++o;
1381 p += 3; 1379 p += 3;
1382 } 1380 }
1383 else if (p > target && IS_DIRECTORY_SEP (p[1])) 1381 else if (IS_DIRECTORY_SEP (p[1])
1384 /* Collapse multiple `/' in a row. */ 1382 && (p != target || IS_DIRECTORY_SEP (p[2])))
1383 /* Collapse multiple "/", except leave leading "//" alone. */
1385 p++; 1384 p++;
1386 else 1385 else
1387 { 1386 {
@@ -1429,11 +1428,12 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1429 { 1428 {
1430 handled_name = call3 (handler, Qexpand_file_name, 1429 handled_name = call3 (handler, Qexpand_file_name,
1431 result, default_directory); 1430 result, default_directory);
1432 if (STRINGP (handled_name)) 1431 if (! STRINGP (handled_name))
1433 return handled_name; 1432 error ("Invalid handler in `file-name-handler-alist'");
1434 error ("Invalid handler in `file-name-handler-alist'"); 1433 result = handled_name;
1435 } 1434 }
1436 1435
1436 SAFE_FREE ();
1437 return result; 1437 return result;
1438} 1438}
1439 1439
diff --git a/src/frame.h b/src/frame.h
index e44003b15ca..2dcb7562524 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -56,16 +56,6 @@ enum vertical_scroll_bar_type
56 vertical_scroll_bar_right 56 vertical_scroll_bar_right
57}; 57};
58 58
59enum text_cursor_kinds
60{
61 DEFAULT_CURSOR = -2,
62 NO_CURSOR = -1,
63 FILLED_BOX_CURSOR,
64 HOLLOW_BOX_CURSOR,
65 BAR_CURSOR,
66 HBAR_CURSOR
67};
68
69enum fullscreen_type 59enum fullscreen_type
70{ 60{
71 FULLSCREEN_NONE, 61 FULLSCREEN_NONE,
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 7e304d417d8..8e255ac4bfb 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1341,6 +1341,7 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
1341 int base_width, base_height; 1341 int base_width, base_height;
1342 int min_rows = 0, min_cols = 0; 1342 int min_rows = 0, min_cols = 0;
1343 int win_gravity = f->win_gravity; 1343 int win_gravity = f->win_gravity;
1344 Lisp_Object fs_state, frame;
1344 1345
1345 /* Don't set size hints during initialization; that apparently leads 1346 /* Don't set size hints during initialization; that apparently leads
1346 to a race condition. See the thread at 1347 to a race condition. See the thread at
@@ -1348,6 +1349,16 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
1348 if (NILP (Vafter_init_time) || !FRAME_GTK_OUTER_WIDGET (f)) 1349 if (NILP (Vafter_init_time) || !FRAME_GTK_OUTER_WIDGET (f))
1349 return; 1350 return;
1350 1351
1352 XSETFRAME (frame, f);
1353 fs_state = Fframe_parameter (frame, Qfullscreen);
1354 if (EQ (fs_state, Qmaximized) || EQ (fs_state, Qfullboth))
1355 {
1356 /* Don't set hints when maximized or fullscreen. Apparently KWin and
1357 Gtk3 don't get along and the frame shrinks (!).
1358 */
1359 return;
1360 }
1361
1351 if (flags) 1362 if (flags)
1352 { 1363 {
1353 memset (&size_hints, 0, sizeof (size_hints)); 1364 memset (&size_hints, 0, sizeof (size_hints));
diff --git a/src/lisp.h b/src/lisp.h
index 60a553cc7d1..51c09e0abb3 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4177,7 +4177,6 @@ extern void init_sys_modes (struct tty_display_info *);
4177extern void reset_sys_modes (struct tty_display_info *); 4177extern void reset_sys_modes (struct tty_display_info *);
4178extern void init_all_sys_modes (void); 4178extern void init_all_sys_modes (void);
4179extern void reset_all_sys_modes (void); 4179extern void reset_all_sys_modes (void);
4180extern void flush_pending_output (int) ATTRIBUTE_CONST;
4181extern void child_setup_tty (int); 4180extern void child_setup_tty (int);
4182extern void setup_pty (int); 4181extern void setup_pty (int);
4183extern int set_window_size (int, int, int); 4182extern int set_window_size (int, int, int);
diff --git a/src/nsterm.m b/src/nsterm.m
index f374bfd90c6..287c119ba73 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -742,8 +742,8 @@ ns_update_window_begin (struct window *w)
742 742
743 743
744static void 744static void
745ns_update_window_end (struct window *w, int cursor_on_p, 745ns_update_window_end (struct window *w, bool cursor_on_p,
746 int mouse_face_overwritten_p) 746 bool mouse_face_overwritten_p)
747/* -------------------------------------------------------------------------- 747/* --------------------------------------------------------------------------
748 Finished a grouped sequence of drawing calls 748 Finished a grouped sequence of drawing calls
749 external (RIF) call; for one window called before update_end 749 external (RIF) call; for one window called before update_end
@@ -2341,8 +2341,8 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2341 2341
2342static void 2342static void
2343ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, 2343ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
2344 int x, int y, int cursor_type, int cursor_width, 2344 int x, int y, enum text_cursor_kinds cursor_type,
2345 int on_p, int active_p) 2345 int cursor_width, bool on_p, bool active_p)
2346/* -------------------------------------------------------------------------- 2346/* --------------------------------------------------------------------------
2347 External call (RIF): draw cursor. 2347 External call (RIF): draw cursor.
2348 Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. 2348 Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
diff --git a/src/process.c b/src/process.c
index 1d1741d8b7e..3edc3b4f061 100644
--- a/src/process.c
+++ b/src/process.c
@@ -826,6 +826,15 @@ allocate_pty (char pty_name[PTY_NAME_SIZE])
826 826
827 if (fd >= 0) 827 if (fd >= 0)
828 { 828 {
829#ifdef PTY_OPEN
830 /* Set FD's close-on-exec flag. This is needed even if
831 PT_OPEN calls posix_openpt with O_CLOEXEC, since POSIX
832 doesn't require support for that combination.
833 Multithreaded platforms where posix_openpt ignores
834 O_CLOEXEC (or where PTY_OPEN doesn't call posix_openpt)
835 have a race condition between the PTY_OPEN and here. */
836 fcntl (fd, F_SETFD, FD_CLOEXEC);
837#endif
829 /* check to make certain that both sides are available 838 /* check to make certain that both sides are available
830 this avoids a nasty yet stupid bug in rlogins */ 839 this avoids a nasty yet stupid bug in rlogins */
831#ifdef PTY_TTY_NAME_SPRINTF 840#ifdef PTY_TTY_NAME_SPRINTF
@@ -1322,15 +1331,18 @@ DEFUN ("process-thread", Fprocess_thread, Sprocess_thread,
1322DEFUN ("set-process-window-size", Fset_process_window_size, 1331DEFUN ("set-process-window-size", Fset_process_window_size,
1323 Sset_process_window_size, 3, 3, 0, 1332 Sset_process_window_size, 3, 3, 0,
1324 doc: /* Tell PROCESS that it has logical window size HEIGHT and WIDTH. */) 1333 doc: /* Tell PROCESS that it has logical window size HEIGHT and WIDTH. */)
1325 (register Lisp_Object process, Lisp_Object height, Lisp_Object width) 1334 (Lisp_Object process, Lisp_Object height, Lisp_Object width)
1326{ 1335{
1327 CHECK_PROCESS (process); 1336 CHECK_PROCESS (process);
1328 CHECK_RANGED_INTEGER (height, 0, INT_MAX); 1337
1329 CHECK_RANGED_INTEGER (width, 0, INT_MAX); 1338 /* All known platforms store window sizes as 'unsigned short'. */
1339 CHECK_RANGED_INTEGER (height, 0, USHRT_MAX);
1340 CHECK_RANGED_INTEGER (width, 0, USHRT_MAX);
1330 1341
1331 if (XPROCESS (process)->infd < 0 1342 if (XPROCESS (process)->infd < 0
1332 || set_window_size (XPROCESS (process)->infd, 1343 || (set_window_size (XPROCESS (process)->infd,
1333 XINT (height), XINT (width)) <= 0) 1344 XINT (height), XINT (width))
1345 < 0))
1334 return Qnil; 1346 return Qnil;
1335 else 1347 else
1336 return Qt; 1348 return Qt;
@@ -1590,22 +1602,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
1590 function. The argument list is protected by the caller, so all 1602 function. The argument list is protected by the caller, so all
1591 we really have to worry about is buffer. */ 1603 we really have to worry about is buffer. */
1592 { 1604 {
1593 struct gcpro gcpro1, gcpro2; 1605 struct gcpro gcpro1;
1594 1606 GCPRO1 (buffer);
1595 current_dir = BVAR (current_buffer, directory); 1607 current_dir = encode_current_directory ();
1596
1597 GCPRO2 (buffer, current_dir);
1598
1599 current_dir = Funhandled_file_name_directory (current_dir);
1600 if (NILP (current_dir))
1601 /* If the file name handler says that current_dir is unreachable, use
1602 a sensible default. */
1603 current_dir = build_string ("~/");
1604 current_dir = expand_and_dir_to_file (current_dir, Qnil);
1605 if (NILP (Ffile_accessible_directory_p (current_dir)))
1606 report_file_error ("Setting current directory",
1607 BVAR (current_buffer, directory));
1608
1609 UNGCPRO; 1608 UNGCPRO;
1610 } 1609 }
1611 1610
@@ -1852,7 +1851,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1852 bool pty_flag = 0; 1851 bool pty_flag = 0;
1853 char pty_name[PTY_NAME_SIZE]; 1852 char pty_name[PTY_NAME_SIZE];
1854 Lisp_Object lisp_pty_name = Qnil; 1853 Lisp_Object lisp_pty_name = Qnil;
1855 Lisp_Object encoded_current_dir;
1856 1854
1857 inchannel = outchannel = -1; 1855 inchannel = outchannel = -1;
1858 1856
@@ -1914,15 +1912,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1914 /* This may signal an error. */ 1912 /* This may signal an error. */
1915 setup_process_coding_systems (process); 1913 setup_process_coding_systems (process);
1916 1914
1917 encoded_current_dir = ENCODE_FILE (current_dir);
1918
1919 block_input (); 1915 block_input ();
1920 block_child_signal (); 1916 block_child_signal ();
1921 1917
1922#ifndef WINDOWSNT 1918#ifndef WINDOWSNT
1923 /* vfork, and prevent local vars from being clobbered by the vfork. */ 1919 /* vfork, and prevent local vars from being clobbered by the vfork. */
1924 { 1920 {
1925 Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir; 1921 Lisp_Object volatile current_dir_volatile = current_dir;
1926 Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; 1922 Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name;
1927 char **volatile new_argv_volatile = new_argv; 1923 char **volatile new_argv_volatile = new_argv;
1928 int volatile forkin_volatile = forkin; 1924 int volatile forkin_volatile = forkin;
@@ -1931,7 +1927,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
1931 1927
1932 pid = vfork (); 1928 pid = vfork ();
1933 1929
1934 encoded_current_dir = encoded_current_dir_volatile; 1930 current_dir = current_dir_volatile;
1935 lisp_pty_name = lisp_pty_name_volatile; 1931 lisp_pty_name = lisp_pty_name_volatile;
1936 new_argv = new_argv_volatile; 1932 new_argv = new_argv_volatile;
1937 forkin = forkin_volatile; 1933 forkin = forkin_volatile;
@@ -2043,11 +2039,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2043 if (pty_flag) 2039 if (pty_flag)
2044 child_setup_tty (xforkout); 2040 child_setup_tty (xforkout);
2045#ifdef WINDOWSNT 2041#ifdef WINDOWSNT
2046 pid = child_setup (xforkin, xforkout, xforkout, 2042 pid = child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir);
2047 new_argv, 1, encoded_current_dir);
2048#else /* not WINDOWSNT */ 2043#else /* not WINDOWSNT */
2049 child_setup (xforkin, xforkout, xforkout, 2044 child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir);
2050 new_argv, 1, encoded_current_dir);
2051#endif /* not WINDOWSNT */ 2045#endif /* not WINDOWSNT */
2052 } 2046 }
2053 2047
@@ -4012,15 +4006,12 @@ deactivate_process (Lisp_Object proc)
4012 } 4006 }
4013#endif 4007#endif
4014 4008
4015 inchannel = p->infd;
4016
4017 /* Beware SIGCHLD hereabouts. */ 4009 /* Beware SIGCHLD hereabouts. */
4018 if (inchannel >= 0)
4019 flush_pending_output (inchannel);
4020 4010
4021 for (i = 0; i < PROCESS_OPEN_FDS; i++) 4011 for (i = 0; i < PROCESS_OPEN_FDS; i++)
4022 close_process_fd (&p->open_fd[i]); 4012 close_process_fd (&p->open_fd[i]);
4023 4013
4014 inchannel = p->infd;
4024 if (inchannel >= 0) 4015 if (inchannel >= 0)
4025 { 4016 {
4026 p->infd = -1; 4017 p->infd = -1;
@@ -5928,10 +5919,9 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
5928 return; 5919 return;
5929 } 5920 }
5930 5921
5931 switch (signo)
5932 {
5933#ifdef SIGCONT 5922#ifdef SIGCONT
5934 case SIGCONT: 5923 if (signo == SIGCONT)
5924 {
5935 p->raw_status_new = 0; 5925 p->raw_status_new = 0;
5936 pset_status (p, Qrun); 5926 pset_status (p, Qrun);
5937 p->tick = ++process_tick; 5927 p->tick = ++process_tick;
@@ -5940,14 +5930,8 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
5940 status_notify (NULL); 5930 status_notify (NULL);
5941 redisplay_preserve_echo_area (13); 5931 redisplay_preserve_echo_area (13);
5942 } 5932 }
5943 break;
5944#endif /* ! defined (SIGCONT) */
5945 case SIGINT:
5946 case SIGQUIT:
5947 case SIGKILL:
5948 flush_pending_output (p->infd);
5949 break;
5950 } 5933 }
5934#endif
5951 5935
5952 /* If we don't have process groups, send the signal to the immediate 5936 /* If we don't have process groups, send the signal to the immediate
5953 subprocess. That isn't really right, but it's better than any 5937 subprocess. That isn't really right, but it's better than any
diff --git a/src/process.h b/src/process.h
index 95881d10f58..e8bafe689b1 100644
--- a/src/process.h
+++ b/src/process.h
@@ -221,6 +221,7 @@ enum
221 221
222extern void block_child_signal (void); 222extern void block_child_signal (void);
223extern void unblock_child_signal (void); 223extern void unblock_child_signal (void);
224extern Lisp_Object encode_current_directory (void);
224extern void record_kill_process (struct Lisp_Process *, Lisp_Object); 225extern void record_kill_process (struct Lisp_Process *, Lisp_Object);
225 226
226/* Defined in sysdep.c. */ 227/* Defined in sysdep.c. */
diff --git a/src/sysdep.c b/src/sysdep.c
index 201ba9d104d..0d732526528 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -337,16 +337,6 @@ child_status_changed (pid_t child, int *status, int options)
337 return get_child_status (child, status, WNOHANG | options, 0); 337 return get_child_status (child, status, WNOHANG | options, 0);
338} 338}
339 339
340/*
341 * flush any pending output
342 * (may flush input as well; it does not matter the way we use it)
343 */
344
345void
346flush_pending_output (int channel)
347{
348 /* FIXME: maybe this function should be removed */
349}
350 340
351/* Set up the terminal at the other end of a pseudo-terminal that 341/* Set up the terminal at the other end of a pseudo-terminal that
352 we will be controlling an inferior through. 342 we will be controlling an inferior through.
@@ -481,10 +471,20 @@ sys_subshell (void)
481 pid_t pid; 471 pid_t pid;
482 int status; 472 int status;
483 struct save_signal saved_handlers[5]; 473 struct save_signal saved_handlers[5];
484 Lisp_Object dir; 474 char *str = SSDATA (encode_current_directory ());
485 unsigned char *volatile str_volatile = 0; 475
486 unsigned char *str; 476#ifdef DOS_NT
487 int len; 477 pid = 0;
478#else
479 {
480 char *volatile str_volatile = str;
481 pid = vfork ();
482 str = str_volatile;
483 }
484#endif
485
486 if (pid < 0)
487 error ("Can't spawn subshell");
488 488
489 saved_handlers[0].code = SIGINT; 489 saved_handlers[0].code = SIGINT;
490 saved_handlers[1].code = SIGQUIT; 490 saved_handlers[1].code = SIGQUIT;
@@ -496,31 +496,8 @@ sys_subshell (void)
496 saved_handlers[3].code = 0; 496 saved_handlers[3].code = 0;
497#endif 497#endif
498 498
499 /* Mentioning current_buffer->buffer would mean including buffer.h,
500 which somehow wedges the hp compiler. So instead... */
501
502 dir = intern ("default-directory");
503 if (NILP (Fboundp (dir)))
504 goto xyzzy;
505 dir = Fsymbol_value (dir);
506 if (!STRINGP (dir))
507 goto xyzzy;
508
509 dir = expand_and_dir_to_file (Funhandled_file_name_directory (dir), Qnil);
510 str_volatile = str = alloca (SCHARS (dir) + 2);
511 len = SCHARS (dir);
512 memcpy (str, SDATA (dir), len);
513 if (str[len - 1] != '/') str[len++] = '/';
514 str[len] = 0;
515 xyzzy:
516
517#ifdef DOS_NT 499#ifdef DOS_NT
518 pid = 0;
519 save_signal_handlers (saved_handlers); 500 save_signal_handlers (saved_handlers);
520#else
521 pid = vfork ();
522 if (pid == -1)
523 error ("Can't spawn subshell");
524#endif 501#endif
525 502
526 if (pid == 0) 503 if (pid == 0)
@@ -538,11 +515,10 @@ sys_subshell (void)
538 sh = "sh"; 515 sh = "sh";
539 516
540 /* Use our buffer's default directory for the subshell. */ 517 /* Use our buffer's default directory for the subshell. */
541 str = str_volatile; 518 if (chdir (str) != 0)
542 if (str && chdir ((char *) str) != 0)
543 { 519 {
544#ifndef DOS_NT 520#ifndef DOS_NT
545 emacs_perror ((char *) str); 521 emacs_perror (str);
546 _exit (EXIT_CANCELED); 522 _exit (EXIT_CANCELED);
547#endif 523#endif
548 } 524 }
@@ -556,8 +532,6 @@ sys_subshell (void)
556 if (epwd) 532 if (epwd)
557 { 533 {
558 strcpy (old_pwd, epwd); 534 strcpy (old_pwd, epwd);
559 if (str[len - 1] == '/')
560 str[len - 1] = '\0';
561 setenv ("PWD", str, 1); 535 setenv ("PWD", str, 1);
562 } 536 }
563 st = system (sh); 537 st = system (sh);
@@ -1196,7 +1170,8 @@ get_tty_size (int fd, int *widthp, int *heightp)
1196} 1170}
1197 1171
1198/* Set the logical window size associated with descriptor FD 1172/* Set the logical window size associated with descriptor FD
1199 to HEIGHT and WIDTH. This is used mainly with ptys. */ 1173 to HEIGHT and WIDTH. This is used mainly with ptys.
1174 Return a negative value on failure. */
1200 1175
1201int 1176int
1202set_window_size (int fd, int height, int width) 1177set_window_size (int fd, int height, int width)
@@ -1208,10 +1183,7 @@ set_window_size (int fd, int height, int width)
1208 size.ws_row = height; 1183 size.ws_row = height;
1209 size.ws_col = width; 1184 size.ws_col = width;
1210 1185
1211 if (ioctl (fd, TIOCSWINSZ, &size) == -1) 1186 return ioctl (fd, TIOCSWINSZ, &size);
1212 return 0; /* error */
1213 else
1214 return 1;
1215 1187
1216#else 1188#else
1217#ifdef TIOCSSIZE 1189#ifdef TIOCSSIZE
@@ -1221,10 +1193,7 @@ set_window_size (int fd, int height, int width)
1221 size.ts_lines = height; 1193 size.ts_lines = height;
1222 size.ts_cols = width; 1194 size.ts_cols = width;
1223 1195
1224 if (ioctl (fd, TIOCGSIZE, &size) == -1) 1196 return ioctl (fd, TIOCGSIZE, &size);
1225 return 0;
1226 else
1227 return 1;
1228#else 1197#else
1229 return -1; 1198 return -1;
1230#endif /* not SunOS-style */ 1199#endif /* not SunOS-style */
@@ -2485,7 +2454,7 @@ serial_configure (struct Lisp_Process *p,
2485 Lisp_Object childp2 = Qnil; 2454 Lisp_Object childp2 = Qnil;
2486 Lisp_Object tem = Qnil; 2455 Lisp_Object tem = Qnil;
2487 struct termios attr; 2456 struct termios attr;
2488 int err = -1; 2457 int err;
2489 char summary[4] = "???"; /* This usually becomes "8N1". */ 2458 char summary[4] = "???"; /* This usually becomes "8N1". */
2490 2459
2491 childp2 = Fcopy_sequence (p->childp); 2460 childp2 = Fcopy_sequence (p->childp);
@@ -2852,29 +2821,41 @@ procfs_ttyname (int rdev)
2852 return build_string (name); 2821 return build_string (name);
2853} 2822}
2854 2823
2855static unsigned long 2824static uintmax_t
2856procfs_get_total_memory (void) 2825procfs_get_total_memory (void)
2857{ 2826{
2858 FILE *fmem; 2827 FILE *fmem;
2859 unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */ 2828 uintmax_t retval = 2 * 1024 * 1024; /* default: 2 GiB */
2829 int c;
2860 2830
2861 block_input (); 2831 block_input ();
2862 fmem = emacs_fopen ("/proc/meminfo", "r"); 2832 fmem = emacs_fopen ("/proc/meminfo", "r");
2863 2833
2864 if (fmem) 2834 if (fmem)
2865 { 2835 {
2866 unsigned long entry_value; 2836 uintmax_t entry_value;
2867 char entry_name[20]; /* the longest I saw is 13+1 */ 2837 bool done;
2838
2839 do
2840 switch (fscanf (fmem, "MemTotal: %"SCNuMAX, &entry_value))
2841 {
2842 case 1:
2843 retval = entry_value;
2844 done = 1;
2845 break;
2846
2847 case 0:
2848 while ((c = getc (fmem)) != EOF && c != '\n')
2849 continue;
2850 done = c == EOF;
2851 break;
2852
2853 default:
2854 done = 1;
2855 break;
2856 }
2857 while (!done);
2868 2858
2869 while (!feof (fmem) && !ferror (fmem))
2870 {
2871 if (fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value) >= 2
2872 && strcmp (entry_name, "MemTotal:") == 0)
2873 {
2874 retval = entry_value;
2875 break;
2876 }
2877 }
2878 fclose (fmem); 2859 fclose (fmem);
2879 } 2860 }
2880 unblock_input (); 2861 unblock_input ();
@@ -3275,7 +3256,7 @@ system_process_attributes (Lisp_Object pid)
3275{ 3256{
3276 int proc_id; 3257 int proc_id;
3277 int pagesize = getpagesize (); 3258 int pagesize = getpagesize ();
3278 int npages; 3259 unsigned long npages;
3279 int fscale; 3260 int fscale;
3280 struct passwd *pw; 3261 struct passwd *pw;
3281 struct group *gr; 3262 struct group *gr;
diff --git a/src/w32.c b/src/w32.c
index 21dbf49ed7c..7f9b96a77a5 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -2503,8 +2503,6 @@ gettimeofday (struct timeval *__restrict tv, struct timezone *__restrict tz)
2503int 2503int
2504fdutimens (int fd, char const *file, struct timespec const timespec[2]) 2504fdutimens (int fd, char const *file, struct timespec const timespec[2])
2505{ 2505{
2506 struct _utimbuf ut;
2507
2508 if (!timespec) 2506 if (!timespec)
2509 { 2507 {
2510 errno = ENOSYS; 2508 errno = ENOSYS;
@@ -2515,12 +2513,28 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
2515 errno = EBADF; 2513 errno = EBADF;
2516 return -1; 2514 return -1;
2517 } 2515 }
2518 ut.actime = timespec[0].tv_sec; 2516 /* _futime's prototype defines 2nd arg as having the type 'struct
2519 ut.modtime = timespec[1].tv_sec; 2517 _utimbuf', while utime needs to accept 'struct utimbuf' for
2518 compatibility with Posix. So we need to use 2 different (but
2519 equivalent) types to avoid compiler warnings, sigh. */
2520 if (fd >= 0) 2520 if (fd >= 0)
2521 return _futime (fd, &ut); 2521 {
2522 struct _utimbuf _ut;
2523
2524 _ut.actime = timespec[0].tv_sec;
2525 _ut.modtime = timespec[1].tv_sec;
2526 return _futime (fd, &_ut);
2527 }
2522 else 2528 else
2523 return _utime (file, &ut); 2529 {
2530 struct utimbuf ut;
2531
2532 ut.actime = timespec[0].tv_sec;
2533 ut.modtime = timespec[1].tv_sec;
2534 /* Call 'utime', which is implemented below, not the MS library
2535 function, which fails on directories. */
2536 return utime (file, &ut);
2537 }
2524} 2538}
2525 2539
2526 2540
@@ -4501,6 +4515,9 @@ fstat (int desc, struct stat * buf)
4501 return 0; 4515 return 0;
4502} 4516}
4503 4517
4518/* A version of 'utime' which handles directories as well as
4519 files. */
4520
4504int 4521int
4505utime (const char *name, struct utimbuf *times) 4522utime (const char *name, struct utimbuf *times)
4506{ 4523{
diff --git a/src/w32term.c b/src/w32term.c
index 7d51850559b..7a15323551b 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -210,7 +210,6 @@ static int volatile input_signal_count;
210int w32_message_fd = -1; 210int w32_message_fd = -1;
211#endif /* CYGWIN */ 211#endif /* CYGWIN */
212 212
213static void x_update_window_end (struct window *, int, int);
214static void w32_handle_tool_bar_click (struct frame *, 213static void w32_handle_tool_bar_click (struct frame *,
215 struct input_event *); 214 struct input_event *);
216static void w32_define_cursor (Window, Cursor); 215static void w32_define_cursor (Window, Cursor);
@@ -676,8 +675,8 @@ w32_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
676 here. */ 675 here. */
677 676
678static void 677static void
679x_update_window_end (struct window *w, int cursor_on_p, 678x_update_window_end (struct window *w, bool cursor_on_p,
680 int mouse_face_overwritten_p) 679 bool mouse_face_overwritten_p)
681{ 680{
682 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); 681 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
683 682
@@ -5300,8 +5299,8 @@ w32_clear_frame_area (struct frame *f, int x, int y, int width, int height)
5300 5299
5301static void 5300static void
5302w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, 5301w32_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
5303 int x, int y, int cursor_type, int cursor_width, 5302 int x, int y, enum text_cursor_kinds cursor_type,
5304 int on_p, int active_p) 5303 int cursor_width, bool on_p, bool active_p)
5305{ 5304{
5306 if (on_p) 5305 if (on_p)
5307 { 5306 {
diff --git a/src/window.c b/src/window.c
index a1a069e0e7d..b02b30cd0b2 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5408,7 +5408,7 @@ struct save_window_data
5408 Lisp_Object saved_windows; 5408 Lisp_Object saved_windows;
5409 5409
5410 /* All fields above are traced by the GC. 5410 /* All fields above are traced by the GC.
5411 From `fame-cols' down, the fields are ignored by the GC. */ 5411 From `frame-cols' down, the fields are ignored by the GC. */
5412 5412
5413 int frame_cols, frame_lines, frame_menu_bar_lines; 5413 int frame_cols, frame_lines, frame_menu_bar_lines;
5414 int frame_tool_bar_lines; 5414 int frame_tool_bar_lines;
diff --git a/src/xdisp.c b/src/xdisp.c
index ea1cd7dd2bc..3ff4603b727 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3912,10 +3912,14 @@ handle_face_prop (struct it *it)
3912 /* For strings from a `display' property, use the face at 3912 /* For strings from a `display' property, use the face at
3913 IT's current buffer position as the base face to merge 3913 IT's current buffer position as the base face to merge
3914 with, so that overlay strings appear in the same face as 3914 with, so that overlay strings appear in the same face as
3915 surrounding text, unless they specify their own 3915 surrounding text, unless they specify their own faces.
3916 faces. */ 3916 For strings from wrap-prefix and line-prefix properties,
3917 use the default face, possibly remapped via
3918 Vface_remapping_alist. */
3917 base_face_id = it->string_from_prefix_prop_p 3919 base_face_id = it->string_from_prefix_prop_p
3918 ? DEFAULT_FACE_ID 3920 ? (!NILP (Vface_remapping_alist)
3921 ? lookup_basic_face (it->f, DEFAULT_FACE_ID)
3922 : DEFAULT_FACE_ID)
3919 : underlying_face_id (it); 3923 : underlying_face_id (it);
3920 } 3924 }
3921 3925
@@ -7046,7 +7050,9 @@ get_next_display_element (struct it *it)
7046 } 7050 }
7047 } 7051 }
7048 } 7052 }
7049 else 7053 /* next_element_from_display_vector sets this flag according to
7054 faces of the display vector glyphs, see there. */
7055 else if (it->method != GET_FROM_DISPLAY_VECTOR)
7050 { 7056 {
7051 int face_id = face_after_it_pos (it); 7057 int face_id = face_after_it_pos (it);
7052 it->end_of_box_run_p 7058 it->end_of_box_run_p
@@ -25763,12 +25769,12 @@ x_produce_glyphs (struct it *it)
25763 25769
25764/* EXPORT for RIF: 25770/* EXPORT for RIF:
25765 Output LEN glyphs starting at START at the nominal cursor position. 25771 Output LEN glyphs starting at START at the nominal cursor position.
25766 Advance the nominal cursor over the text. The global variable 25772 Advance the nominal cursor over the text. UPDATED_ROW is the glyph row
25767 updated_row is the glyph row being updated, and updated_area is the 25773 being updated, and UPDATED_AREA is the area of that row being updated. */
25768 area of that row being updated. */
25769 25774
25770void 25775void
25771x_write_glyphs (struct window *w, struct glyph *start, int len) 25776x_write_glyphs (struct window *w, struct glyph_row *updated_row,
25777 struct glyph *start, enum glyph_row_area updated_area, int len)
25772{ 25778{
25773 int x, hpos, chpos = w->phys_cursor.hpos; 25779 int x, hpos, chpos = w->phys_cursor.hpos;
25774 25780
@@ -25811,7 +25817,8 @@ x_write_glyphs (struct window *w, struct glyph *start, int len)
25811 Insert LEN glyphs from START at the nominal cursor position. */ 25817 Insert LEN glyphs from START at the nominal cursor position. */
25812 25818
25813void 25819void
25814x_insert_glyphs (struct window *w, struct glyph *start, int len) 25820x_insert_glyphs (struct window *w, struct glyph_row *updated_row,
25821 struct glyph *start, enum glyph_row_area updated_area, int len)
25815{ 25822{
25816 struct frame *f; 25823 struct frame *f;
25817 int line_height, shift_by_width, shifted_region_width; 25824 int line_height, shift_by_width, shifted_region_width;
@@ -25863,11 +25870,12 @@ x_insert_glyphs (struct window *w, struct glyph *start, int len)
25863 (inclusive) to pixel column TO_X (exclusive). The idea is that 25870 (inclusive) to pixel column TO_X (exclusive). The idea is that
25864 everything from TO_X onward is already erased. 25871 everything from TO_X onward is already erased.
25865 25872
25866 TO_X is a pixel position relative to updated_area of currently 25873 TO_X is a pixel position relative to UPDATED_AREA of currently
25867 updated window W. TO_X == -1 means clear to the end of this area. */ 25874 updated window W. TO_X == -1 means clear to the end of this area. */
25868 25875
25869void 25876void
25870x_clear_end_of_line (struct window *w, int to_x) 25877x_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
25878 enum glyph_row_area updated_area, int to_x)
25871{ 25879{
25872 struct frame *f; 25880 struct frame *f;
25873 int max_x, min_y, max_y; 25881 int max_x, min_y, max_y;
@@ -26463,7 +26471,7 @@ erase_phys_cursor (struct window *w)
26463 where to put the cursor is specified by HPOS, VPOS, X and Y. */ 26471 where to put the cursor is specified by HPOS, VPOS, X and Y. */
26464 26472
26465void 26473void
26466display_and_set_cursor (struct window *w, int on, 26474display_and_set_cursor (struct window *w, bool on,
26467 int hpos, int vpos, int x, int y) 26475 int hpos, int vpos, int x, int y)
26468{ 26476{
26469 struct frame *f = XFRAME (w->frame); 26477 struct frame *f = XFRAME (w->frame);
@@ -26547,7 +26555,7 @@ display_and_set_cursor (struct window *w, int on,
26547 of ON. */ 26555 of ON. */
26548 26556
26549static void 26557static void
26550update_window_cursor (struct window *w, int on) 26558update_window_cursor (struct window *w, bool on)
26551{ 26559{
26552 /* Don't update cursor in windows whose frame is in the process 26560 /* Don't update cursor in windows whose frame is in the process
26553 of being deleted. */ 26561 of being deleted. */
@@ -26583,7 +26591,7 @@ update_window_cursor (struct window *w, int on)
26583 in the window tree rooted at W. */ 26591 in the window tree rooted at W. */
26584 26592
26585static void 26593static void
26586update_cursor_in_window_tree (struct window *w, int on_p) 26594update_cursor_in_window_tree (struct window *w, bool on_p)
26587{ 26595{
26588 while (w) 26596 while (w)
26589 { 26597 {
@@ -26602,7 +26610,7 @@ update_cursor_in_window_tree (struct window *w, int on_p)
26602 Don't change the cursor's position. */ 26610 Don't change the cursor's position. */
26603 26611
26604void 26612void
26605x_update_cursor (struct frame *f, int on_p) 26613x_update_cursor (struct frame *f, bool on_p)
26606{ 26614{
26607 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p); 26615 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
26608} 26616}
diff --git a/src/xterm.c b/src/xterm.c
index b5c5a5cb584..cea952f44d2 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -292,8 +292,6 @@ static void x_set_window_size_1 (struct frame *, int, int, int);
292static void x_raise_frame (struct frame *); 292static void x_raise_frame (struct frame *);
293static void x_lower_frame (struct frame *); 293static void x_lower_frame (struct frame *);
294static const XColor *x_color_cells (Display *, int *); 294static const XColor *x_color_cells (Display *, int *);
295static void x_update_window_end (struct window *, int, int);
296
297static int x_io_error_quitter (Display *); 295static int x_io_error_quitter (Display *);
298static struct terminal *x_create_terminal (struct x_display_info *); 296static struct terminal *x_create_terminal (struct x_display_info *);
299void x_delete_terminal (struct terminal *); 297void x_delete_terminal (struct terminal *);
@@ -612,7 +610,8 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
612 here. */ 610 here. */
613 611
614static void 612static void
615x_update_window_end (struct window *w, int cursor_on_p, int mouse_face_overwritten_p) 613x_update_window_end (struct window *w, bool cursor_on_p,
614 bool mouse_face_overwritten_p)
616{ 615{
617 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); 616 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
618 617
@@ -7372,7 +7371,9 @@ x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
7372/* RIF: Draw cursor on window W. */ 7371/* RIF: Draw cursor on window W. */
7373 7372
7374static void 7373static void
7375x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x, int y, int cursor_type, int cursor_width, int on_p, int active_p) 7374x_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, int x,
7375 int y, enum text_cursor_kinds cursor_type,
7376 int cursor_width, bool on_p, bool active_p)
7376{ 7377{
7377 struct frame *f = XFRAME (WINDOW_FRAME (w)); 7378 struct frame *f = XFRAME (WINDOW_FRAME (w));
7378 7379
diff --git a/test/ChangeLog b/test/ChangeLog
index 5f3006ec7bf..969bc3c4939 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,9 @@
12013-08-21 David Engster <deng@randomsample.de>
2
3 * automated/eieio-tests.el, automated/eieio-test-persist.el:
4 * automated/eieio-test-methodinvoke.el: EIEIO tests from CEDET
5 upstream. Changed to use ERT.
6
12013-08-14 Daniel Hackney <dan@haxney.org> 72013-08-14 Daniel Hackney <dan@haxney.org>
2 8
3 * package-test.el: Remove tar-package-building functions. Tar file 9 * package-test.el: Remove tar-package-building functions. Tar file
diff --git a/test/automated/eieio-test-methodinvoke.el b/test/automated/eieio-test-methodinvoke.el
new file mode 100644
index 00000000000..76a28919f21
--- /dev/null
+++ b/test/automated/eieio-test-methodinvoke.el
@@ -0,0 +1,379 @@
1;;; eieio-testsinvoke.el -- eieio tests for method invokation
2
3;; Copyright (C) 2005, 2008, 2010, 2013 Free Software Foundation, Inc.
4
5;; Author: Eric. M. Ludlam <zappo@gnu.org>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21
22;;; Commentary:
23;;
24;; Test method invocation order. From the common lisp reference
25;; manual:
26;;
27;; QUOTE:
28;; - All the :before methods are called, in most-specific-first
29;; order. Their values are ignored. An error is signaled if
30;; call-next-method is used in a :before method.
31;;
32;; - The most specific primary method is called. Inside the body of a
33;; primary method, call-next-method may be used to call the next
34;; most specific primary method. When that method returns, the
35;; previous primary method can execute more code, perhaps based on
36;; the returned value or values. The generic function no-next-method
37;; is invoked if call-next-method is used and there are no more
38;; applicable primary methods. The function next-method-p may be
39;; used to determine whether a next method exists. If
40;; call-next-method is not used, only the most specific primary
41;; method is called.
42;;
43;; - All the :after methods are called, in most-specific-last order.
44;; Their values are ignored. An error is signaled if
45;; call-next-method is used in a :after method.
46;;
47;;
48;; Also test behavior of `call-next-method'. From clos.org:
49;;
50;; QUOTE:
51;; When call-next-method is called with no arguments, it passes the
52;; current method's original arguments to the next method.
53
54(require 'eieio)
55(require 'ert)
56
57(defvar eieio-test-method-order-list nil
58 "List of symbols stored during method invocation.")
59
60(defun eieio-test-method-store ()
61 "Store current invocation class symbol in the invocation order list."
62 (let* ((keysym (aref [ :STATIC :BEFORE :PRIMARY :AFTER ]
63 (or eieio-generic-call-key 0)))
64 (c (list eieio-generic-call-methodname keysym (eieio--scoped-class))))
65 (setq eieio-test-method-order-list
66 (cons c eieio-test-method-order-list))))
67
68(defun eieio-test-match (rightanswer)
69 "Do a test match."
70 (if (equal rightanswer eieio-test-method-order-list)
71 t
72 (error "eieio-test-methodinvoke.el: Test Failed!")))
73
74(defvar eieio-test-call-next-method-arguments nil
75 "List of passed to methods during execution of `call-next-method'.")
76
77(defun eieio-test-arguments-for (class)
78 "Returns arguments passed to method of CLASS during `call-next-method'."
79 (cdr (assoc class eieio-test-call-next-method-arguments)))
80
81(defclass eitest-A () ())
82(defclass eitest-AA (eitest-A) ())
83(defclass eitest-AAA (eitest-AA) ())
84(defclass eitest-B-base1 () ())
85(defclass eitest-B-base2 () ())
86(defclass eitest-B (eitest-B-base1 eitest-B-base2) ())
87
88(defmethod eitest-F :BEFORE ((p eitest-B-base1))
89 (eieio-test-method-store))
90
91(defmethod eitest-F :BEFORE ((p eitest-B-base2))
92 (eieio-test-method-store))
93
94(defmethod eitest-F :BEFORE ((p eitest-B))
95 (eieio-test-method-store))
96
97(defmethod eitest-F ((p eitest-B))
98 (eieio-test-method-store)
99 (call-next-method))
100
101(defmethod eitest-F ((p eitest-B-base1))
102 (eieio-test-method-store)
103 (call-next-method))
104
105(defmethod eitest-F ((p eitest-B-base2))
106 (eieio-test-method-store)
107 (when (next-method-p)
108 (call-next-method))
109 )
110
111(defmethod eitest-F :AFTER ((p eitest-B-base1))
112 (eieio-test-method-store))
113
114(defmethod eitest-F :AFTER ((p eitest-B-base2))
115 (eieio-test-method-store))
116
117(defmethod eitest-F :AFTER ((p eitest-B))
118 (eieio-test-method-store))
119
120(ert-deftest eieio-test-method-order-list-3 ()
121 (let ((eieio-test-method-order-list nil)
122 (ans '(
123 (eitest-F :BEFORE eitest-B)
124 (eitest-F :BEFORE eitest-B-base1)
125 (eitest-F :BEFORE eitest-B-base2)
126
127 (eitest-F :PRIMARY eitest-B)
128 (eitest-F :PRIMARY eitest-B-base1)
129 (eitest-F :PRIMARY eitest-B-base2)
130
131 (eitest-F :AFTER eitest-B-base2)
132 (eitest-F :AFTER eitest-B-base1)
133 (eitest-F :AFTER eitest-B)
134 )))
135 (eitest-F (eitest-B nil))
136 (setq eieio-test-method-order-list (nreverse eieio-test-method-order-list))
137 (eieio-test-match ans)))
138
139;;; Test static invokation
140;;
141(defmethod eitest-H :STATIC ((class eitest-A))
142 "No need to do work in here."
143 'moose)
144
145(ert-deftest eieio-test-method-order-list-4 ()
146 ;; Both of these situations should succeed.
147 (should (eitest-H eitest-A))
148 (should (eitest-H (eitest-A nil))))
149
150;;; Return value from :PRIMARY
151;;
152(defmethod eitest-I :BEFORE ((a eitest-A))
153 (eieio-test-method-store)
154 ":before")
155
156(defmethod eitest-I :PRIMARY ((a eitest-A))
157 (eieio-test-method-store)
158 ":primary")
159
160(defmethod eitest-I :AFTER ((a eitest-A))
161 (eieio-test-method-store)
162 ":after")
163
164(ert-deftest eieio-test-method-order-list-5 ()
165 (let ((eieio-test-method-order-list nil)
166 (ans (eitest-I (eitest-A nil))))
167 (should (string= ans ":primary"))))
168
169;;; Multiple inheritance and the 'constructor' method.
170;;
171;; Constructor is a static method, so this is really testing
172;; static method invocation and multiple inheritance.
173;;
174(defclass C-base1 () ())
175(defclass C-base2 () ())
176(defclass C (C-base1 C-base2) ())
177
178(defmethod constructor :STATIC ((p C-base1) &rest args)
179 (eieio-test-method-store)
180 (if (next-method-p) (call-next-method))
181 )
182
183(defmethod constructor :STATIC ((p C-base2) &rest args)
184 (eieio-test-method-store)
185 (if (next-method-p) (call-next-method))
186 )
187
188(defmethod constructor :STATIC ((p C) &rest args)
189 (eieio-test-method-store)
190 (call-next-method)
191 )
192
193(ert-deftest eieio-test-method-order-list-6 ()
194 (let ((eieio-test-method-order-list nil)
195 (ans '(
196 (constructor :STATIC C)
197 (constructor :STATIC C-base1)
198 (constructor :STATIC C-base2)
199 )))
200 (C nil)
201 (setq eieio-test-method-order-list (nreverse eieio-test-method-order-list))
202 (eieio-test-match ans)))
203
204;;; Diamond Test
205;;
206;; For a diamond shaped inheritance structure, (call-next-method) can break.
207;; As such, there are two possible orders.
208
209(defclass D-base0 () () :method-invocation-order :depth-first)
210(defclass D-base1 (D-base0) () :method-invocation-order :depth-first)
211(defclass D-base2 (D-base0) () :method-invocation-order :depth-first)
212(defclass D (D-base1 D-base2) () :method-invocation-order :depth-first)
213
214(defmethod eitest-F ((p D))
215 "D"
216 (eieio-test-method-store)
217 (call-next-method))
218
219(defmethod eitest-F ((p D-base0))
220 "D-base0"
221 (eieio-test-method-store)
222 ;; This should have no next
223 ;; (when (next-method-p) (call-next-method))
224 )
225
226(defmethod eitest-F ((p D-base1))
227 "D-base1"
228 (eieio-test-method-store)
229 (call-next-method))
230
231(defmethod eitest-F ((p D-base2))
232 "D-base2"
233 (eieio-test-method-store)
234 (when (next-method-p)
235 (call-next-method))
236 )
237
238(ert-deftest eieio-test-method-order-list-7 ()
239 (let ((eieio-test-method-order-list nil)
240 (ans '(
241 (eitest-F :PRIMARY D)
242 (eitest-F :PRIMARY D-base1)
243 ;; (eitest-F :PRIMARY D-base2)
244 (eitest-F :PRIMARY D-base0)
245 )))
246 (eitest-F (D nil))
247 (setq eieio-test-method-order-list (nreverse eieio-test-method-order-list))
248 (eieio-test-match ans)))
249
250;;; Other invocation order
251
252(defclass E-base0 () () :method-invocation-order :breadth-first)
253(defclass E-base1 (E-base0) () :method-invocation-order :breadth-first)
254(defclass E-base2 (E-base0) () :method-invocation-order :breadth-first)
255(defclass E (E-base1 E-base2) () :method-invocation-order :breadth-first)
256
257(defmethod eitest-F ((p E))
258 (eieio-test-method-store)
259 (call-next-method))
260
261(defmethod eitest-F ((p E-base0))
262 (eieio-test-method-store)
263 ;; This should have no next
264 ;; (when (next-method-p) (call-next-method))
265 )
266
267(defmethod eitest-F ((p E-base1))
268 (eieio-test-method-store)
269 (call-next-method))
270
271(defmethod eitest-F ((p E-base2))
272 (eieio-test-method-store)
273 (when (next-method-p)
274 (call-next-method))
275 )
276
277(ert-deftest eieio-test-method-order-list-8 ()
278 (let ((eieio-test-method-order-list nil)
279 (ans '(
280 (eitest-F :PRIMARY E)
281 (eitest-F :PRIMARY E-base1)
282 (eitest-F :PRIMARY E-base2)
283 (eitest-F :PRIMARY E-base0)
284 )))
285 (eitest-F (E nil))
286 (setq eieio-test-method-order-list (nreverse eieio-test-method-order-list))
287 (eieio-test-match ans)))
288
289;;; Jan's methodinvoke order w/ multiple inheritance and :after methods.
290;;
291(defclass eitest-Ja ()
292 ())
293
294(defmethod initialize-instance :after ((this eitest-Ja) &rest slots)
295 ;(message "+Ja")
296 (when (next-method-p)
297 (call-next-method))
298 ;(message "-Ja")
299 )
300
301(defclass eitest-Jb ()
302 ())
303
304(defmethod initialize-instance :after ((this eitest-Jb) &rest slots)
305 ;(message "+Jb")
306 (when (next-method-p)
307 (call-next-method))
308 ;(message "-Jb")
309 )
310
311(defclass eitest-Jc (eitest-Jb)
312 ())
313
314(defclass eitest-Jd (eitest-Jc eitest-Ja)
315 ())
316
317(defmethod initialize-instance ((this eitest-Jd) &rest slots)
318 ;(message "+Jd")
319 (when (next-method-p)
320 (call-next-method))
321 ;(message "-Jd")
322 )
323
324(ert-deftest eieio-test-method-order-list-9 ()
325 (should (eitest-Jd "test")))
326
327;;; call-next-method with replacement arguments across a simple class hierarchy.
328;;
329
330(defclass CNM-0 ()
331 ())
332
333(defclass CNM-1-1 (CNM-0)
334 ())
335
336(defclass CNM-1-2 (CNM-0)
337 ())
338
339(defclass CNM-2 (CNM-1-1 CNM-1-2)
340 ())
341
342(defmethod CNM-M ((this CNM-0) args)
343 (push (cons 'CNM-0 (copy-sequence args))
344 eieio-test-call-next-method-arguments)
345 (when (next-method-p)
346 (call-next-method
347 this (cons 'CNM-0 args))))
348
349(defmethod CNM-M ((this CNM-1-1) args)
350 (push (cons 'CNM-1-1 (copy-sequence args))
351 eieio-test-call-next-method-arguments)
352 (when (next-method-p)
353 (call-next-method
354 this (cons 'CNM-1-1 args))))
355
356(defmethod CNM-M ((this CNM-1-2) args)
357 (push (cons 'CNM-1-2 (copy-sequence args))
358 eieio-test-call-next-method-arguments)
359 (when (next-method-p)
360 (call-next-method)))
361
362(defmethod CNM-M ((this CNM-2) args)
363 (push (cons 'CNM-2 (copy-sequence args))
364 eieio-test-call-next-method-arguments)
365 (when (next-method-p)
366 (call-next-method
367 this (cons 'CNM-2 args))))
368
369(ert-deftest eieio-test-method-order-list-10 ()
370 (let ((eieio-test-call-next-method-arguments nil))
371 (CNM-M (CNM-2 "") '(INIT))
372 (should (equal (eieio-test-arguments-for 'CNM-0)
373 '(CNM-1-1 CNM-2 INIT)))
374 (should (equal (eieio-test-arguments-for 'CNM-1-1)
375 '(CNM-2 INIT)))
376 (should (equal (eieio-test-arguments-for 'CNM-1-2)
377 '(CNM-1-1 CNM-2 INIT)))
378 (should (equal (eieio-test-arguments-for 'CNM-2)
379 '(INIT)))))
diff --git a/test/automated/eieio-test-persist.el b/test/automated/eieio-test-persist.el
new file mode 100644
index 00000000000..cdf308a39ab
--- /dev/null
+++ b/test/automated/eieio-test-persist.el
@@ -0,0 +1,213 @@
1;;; eieio-persist.el --- Tests for eieio-persistent class
2
3;; Copyright (C) 2011-2013 Free Software Foundation, Inc.
4
5;; Author: Eric M. Ludlam <eric@siege-engine.com>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21
22;;; Commentary:
23;;
24;; The eieio-persistent base-class provides a vital service, that
25;; could be used to accidentally load in malicious code. As such,
26;; something as simple as calling eval on the generated code can't be
27;; used. These tests exercises various flavors of data that might be
28;; in a persistent object, and tries to save/load them.
29
30;;; Code:
31(require 'eieio)
32(require 'eieio-base)
33(require 'ert)
34
35(defun persist-test-save-and-compare (original)
36 "Compare the object ORIGINAL against the one read fromdisk."
37
38 (eieio-persistent-save original)
39
40 (let* ((file (oref original :file))
41 (class (eieio-object-class original))
42 (fromdisk (eieio-persistent-read file class))
43 (cv (class-v class))
44 (slot-names (eieio--class-public-a cv))
45 (slot-deflt (eieio--class-public-d cv))
46 )
47 (unless (object-of-class-p fromdisk class)
48 (error "Persistent class %S != original class %S"
49 (eieio-object-class fromdisk)
50 class))
51
52 (while slot-names
53 (let* ((oneslot (car slot-names))
54 (origvalue (eieio-oref original oneslot))
55 (fromdiskvalue (eieio-oref fromdisk oneslot))
56 (initarg-p (eieio-attribute-to-initarg class oneslot))
57 )
58
59 (if initarg-p
60 (unless (equal origvalue fromdiskvalue)
61 (error "Slot %S Original Val %S != Persistent Val %S"
62 oneslot origvalue fromdiskvalue))
63 ;; Else !initarg-p
64 (unless (equal (car slot-deflt) fromdiskvalue)
65 (error "Slot %S Persistent Val %S != Default Value %S"
66 oneslot fromdiskvalue (car slot-deflt))))
67
68 (setq slot-names (cdr slot-names)
69 slot-deflt (cdr slot-deflt))
70 ))))
71
72;;; Simple Case
73;;
74;; Simplest case is a mix of slots with and without initargs.
75
76(defclass persist-simple (eieio-persistent)
77 ((slot1 :initarg :slot1
78 :type symbol
79 :initform moose)
80 (slot2 :initarg :slot2
81 :initform "foo")
82 (slot3 :initform 2))
83 "A Persistent object with two initializable slots, and one not.")
84
85(ert-deftest eieio-test-persist-simple-1 ()
86 (let ((persist-simple-1
87 (persist-simple "simple 1" :slot1 'goose :slot2 "testing"
88 :file (concat default-directory "test-ps1.pt"))))
89 (should persist-simple-1)
90
91 ;; When the slot w/out an initarg has not been changed
92 (persist-test-save-and-compare persist-simple-1)
93
94 ;; When the slot w/out an initarg HAS been changed
95 (oset persist-simple-1 slot3 3)
96 (persist-test-save-and-compare persist-simple-1)
97 (delete-file (oref persist-simple-1 file))))
98
99;;; Slot Writers
100;;
101;; Replica of the test in eieio-tests.el -
102
103(defclass persist-:printer (eieio-persistent)
104 ((slot1 :initarg :slot1
105 :initform 'moose
106 :printer PO-slot1-printer)
107 (slot2 :initarg :slot2
108 :initform "foo"))
109 "A Persistent object with two initializable slots.")
110
111(defun PO-slot1-printer (slotvalue)
112 "Print the slot value SLOTVALUE to stdout.
113Assume SLOTVALUE is a symbol of some sort."
114 (princ "'")
115 (princ (symbol-name slotvalue))
116 (princ " ;; RAN PRINTER")
117 nil)
118
119(ert-deftest eieio-test-persist-printer ()
120 (let ((persist-:printer-1
121 (persist-:printer "persist" :slot1 'goose :slot2 "testing"
122 :file (concat default-directory "test-ps2.pt"))))
123 (should persist-:printer-1)
124 (persist-test-save-and-compare persist-:printer-1)
125
126 (let* ((find-file-hook nil)
127 (tbuff (find-file-noselect "test-ps2.pt"))
128 )
129 (condition-case nil
130 (unwind-protect
131 (with-current-buffer tbuff
132 (goto-char (point-min))
133 (re-search-forward "RAN PRINTER"))
134 (kill-buffer tbuff))
135 (error "persist-:printer-1's Slot1 printer function didn't work.")))
136 (delete-file (oref persist-:printer-1 file))))
137
138;;; Slot with Object
139;;
140;; A slot that contains another object that isn't persistent
141(defclass persist-not-persistent ()
142 ((slot1 :initarg :slot1
143 :initform 1)
144 (slot2 :initform 2))
145 "Class for testing persistent saving of an object that isn't
146persistent. This class is instead used as a slot value in a
147persistent class.")
148
149(defclass persistent-with-objs-slot (eieio-persistent)
150 ((pnp :initarg :pnp
151 :type (or null persist-not-persistent)
152 :initform nil))
153 "Class for testing the saving of slots with objects in them.")
154
155(ert-deftest eieio-test-non-persistent-as-slot ()
156 (let ((persist-wos
157 (persistent-with-objs-slot
158 "persist wos 1"
159 :pnp (persist-not-persistent "pnp 1" :slot1 3)
160 :file (concat default-directory "test-ps3.pt"))))
161
162 (persist-test-save-and-compare persist-wos)
163 (delete-file (oref persist-wos file))))
164
165;;; Slot with Object child of :type
166;;
167;; A slot that contains another object that isn't persistent
168(defclass persist-not-persistent-subclass (persist-not-persistent)
169 ((slot3 :initarg :slot1
170 :initform 1)
171 (slot4 :initform 2))
172 "Class for testing persistent saving of an object subclass that isn't
173persistent. This class is instead used as a slot value in a
174persistent class.")
175
176(defclass persistent-with-objs-slot-subs (eieio-persistent)
177 ((pnp :initarg :pnp
178 :type (or null persist-not-persistent-child)
179 :initform nil))
180 "Class for testing the saving of slots with objects in them.")
181
182(ert-deftest eieio-test-non-persistent-as-slot-child ()
183 (let ((persist-woss
184 (persistent-with-objs-slot-subs
185 "persist woss 1"
186 :pnp (persist-not-persistent-subclass "pnps 1" :slot1 3)
187 :file (concat default-directory "test-ps4.pt"))))
188
189 (persist-test-save-and-compare persist-woss)
190 (delete-file (oref persist-woss file))))
191
192;;; Slot with a list of Objects
193;;
194;; A slot that contains another object that isn't persistent
195(defclass persistent-with-objs-list-slot (eieio-persistent)
196 ((pnp :initarg :pnp
197 :type persist-not-persistent-list
198 :initform nil))
199 "Class for testing the saving of slots with objects in them.")
200
201(ert-deftest eieio-test-slot-with-list-of-objects ()
202 (let ((persist-wols
203 (persistent-with-objs-list-slot
204 "persist wols 1"
205 :pnp (list (persist-not-persistent "pnp 1" :slot1 3)
206 (persist-not-persistent "pnp 2" :slot1 4)
207 (persist-not-persistent "pnp 3" :slot1 5))
208 :file (concat default-directory "test-ps5.pt"))))
209
210 (persist-test-save-and-compare persist-wols)
211 (delete-file (oref persist-wols file))))
212
213;;; eieio-test-persist.el ends here
diff --git a/test/automated/eieio-tests.el b/test/automated/eieio-tests.el
new file mode 100644
index 00000000000..2d8ae4c7d43
--- /dev/null
+++ b/test/automated/eieio-tests.el
@@ -0,0 +1,893 @@
1;;; eieio-tests.el -- eieio tests routines
2
3;; Copyright (C) 1999-2003, 2005-2010, 2012-2013 Free Software
4;; Foundation, Inc.
5
6;; Author: Eric M. Ludlam <zappo@gnu.org>
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software: you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22
23;;; Commentary:
24;;
25;; Test the various features of EIEIO.
26
27(require 'ert)
28(require 'eieio)
29(require 'eieio-base)
30(require 'eieio-opt)
31
32(eval-when-compile (require 'cl))
33
34;;; Code:
35;; Set up some test classes
36(defclass class-a ()
37 ((water :initarg :water
38 :initform h20
39 :type symbol
40 :documentation "Detail about water.")
41 (classslot :initform penguin
42 :type symbol
43 :documentation "A class allocated slot."
44 :allocation :class)
45 (test-tag :initform nil
46 :documentation "Used to make sure methods are called.")
47 (self :initform nil
48 :type (or null class-a)
49 :documentation "Test self referencing types.")
50 )
51 "Class A")
52
53(defclass class-b ()
54 ((land :initform "Sc"
55 :type string
56 :documentation "Detail about land."))
57 "Class B")
58
59(defclass class-ab (class-a class-b)
60 ((amphibian :initform "frog"
61 :documentation "Detail about amphibian on land and water."))
62 "Class A and B combined.")
63
64(defclass class-c ()
65 ((slot-1 :initarg :moose
66 :initform moose
67 :type symbol
68 :allocation :instance
69 :documentation "Fisrt slot testing slot arguments."
70 :custom symbol
71 :label "Wild Animal"
72 :group borg
73 :protection :public)
74 (slot-2 :initarg :penguin
75 :initform "penguin"
76 :type string
77 :allocation :instance
78 :documentation "Second slot testing slot arguments."
79 :custom string
80 :label "Wild bird"
81 :group vorlon
82 :accessor get-slot-2
83 :protection :private)
84 (slot-3 :initarg :emu
85 :initform emu
86 :type symbol
87 :allocation :class
88 :documentation "Third slot test class allocated accessor"
89 :custom symbol
90 :label "Fuzz"
91 :group tokra
92 :accessor get-slot-3
93 :protection :private)
94 )
95 (:custom-groups (foo))
96 "A class for testing slot arguments."
97 )
98
99(defclass class-subc (class-c)
100 ((slot-1 ;; :initform moose - don't override this
101 )
102 (slot-2 :initform "linux" ;; Do override this one
103 :protection :private
104 ))
105 "A class for testing slot arguments.")
106
107;;; Defining a class with a slot tag error
108;;
109;; Temporarily disable this test because of macro expansion changes in
110;; current Emacs trunk. It can be re-enabled when we have moved
111;; `eieio-defclass' into the `defclass' macro and the
112;; `eval-and-compile' there is removed.
113
114;; (let ((eieio-error-unsupported-class-tags t))
115;; (condition-case nil
116;; (progn
117;; (defclass class-error ()
118;; ((error-slot :initarg :error-slot
119;; :badslottag 1))
120;; "A class with a bad slot tag.")
121;; (error "No error was thrown for badslottag"))
122;; (invalid-slot-type nil)))
123
124;; (let ((eieio-error-unsupported-class-tags nil))
125;; (condition-case nil
126;; (progn
127;; (defclass class-error ()
128;; ((error-slot :initarg :error-slot
129;; :badslottag 1))
130;; "A class with a bad slot tag."))
131;; (invalid-slot-type
132;; (error "invalid-slot-type thrown when eieio-error-unsupported-class-tags is nil")
133;; )))
134
135(ert-deftest eieio-test-01-mix-alloc-initarg ()
136 ;; Only run this test if the message framework thingy works.
137 (when (and (message "foo") (string= "foo" (current-message)))
138
139 ;; Defining this class should generate a warning(!) message that
140 ;; you should not mix :initarg with class allocated slots.
141 (defclass class-alloc-initarg ()
142 ((throwwarning :initarg :throwwarning
143 :allocation :class))
144 "Throw a warning mixing allocation class and an initarg.")
145
146 ;; Check that message is there
147 (should (current-message))
148 (should (string-match "Class allocated slots do not need :initarg"
149 (current-message)))))
150
151(defclass abstract-class ()
152 ((some-slot :initarg :some-slot
153 :initform nil
154 :documentation "A slot."))
155 :documentation "An abstract class."
156 :abstract t)
157
158(ert-deftest eieio-test-02-abstract-class ()
159 ;; Abstract classes cannot be instantiated, so this should throw an
160 ;; error
161 (should-error (abstract-class "Test")))
162
163(defgeneric generic1 () "First generic function")
164
165(ert-deftest eieio-test-03-generics ()
166 (defun anormalfunction () "A plain function for error testing." nil)
167 (should-error
168 (progn
169 (defgeneric anormalfunction ()
170 "Attempt to turn it into a generic.")))
171
172 ;; Check that generic-p works
173 (should (generic-p 'generic1))
174
175 (defmethod generic1 ((c class-a))
176 "Method on generic1."
177 'monkey)
178
179 (defmethod generic1 (not-an-object)
180 "Method generic1 that can take a non-object."
181 not-an-object)
182
183 (let ((ans-obj (generic1 (class-a "test")))
184 (ans-num (generic1 666)))
185 (should (eq ans-obj 'monkey))
186 (should (eq ans-num 666))))
187
188(defclass static-method-class ()
189 ((some-slot :initform nil
190 :allocation :class
191 :documentation "A slot."))
192 :documentation "A class used for testing static methods.")
193
194(defmethod static-method-class-method :STATIC ((c static-method-class) value)
195 "Test static methods.
196Argument C is the class bound to this static method."
197 (if (eieio-object-p c) (setq c (eieio-object-class c)))
198 (oset-default c some-slot value))
199
200(ert-deftest eieio-test-04-static-method ()
201 ;; Call static method on a class and see if it worked
202 (static-method-class-method static-method-class 'class)
203 (should (eq (oref static-method-class some-slot) 'class))
204 (static-method-class-method (static-method-class "test") 'object)
205 (should (eq (oref static-method-class some-slot) 'object)))
206
207(ert-deftest eieio-test-05-static-method-2 ()
208 (defclass static-method-class-2 (static-method-class)
209 ()
210 "A second class after the previous for static methods.")
211
212 (defmethod static-method-class-method :STATIC ((c static-method-class-2) value)
213 "Test static methods.
214Argument C is the class bound to this static method."
215 (if (eieio-object-p c) (setq c (eieio-object-class c)))
216 (oset-default c some-slot (intern (concat "moose-" (symbol-name value)))))
217
218 (static-method-class-method static-method-class-2 'class)
219 (should (eq (oref static-method-class-2 some-slot) 'moose-class))
220 (static-method-class-method (static-method-class-2 "test") 'object)
221 (should (eq (oref static-method-class-2 some-slot) 'moose-object)))
222
223
224;;; Perform method testing
225;;
226
227;;; Multiple Inheritance, and method signal testing
228;;
229(defvar eitest-ab nil)
230(defvar eitest-a nil)
231(defvar eitest-b nil)
232(ert-deftest eieio-test-06-allocate-objects ()
233 ;; allocate an object to use
234 (should (setq eitest-ab (class-ab "abby")))
235 (should (setq eitest-a (class-a "aye")))
236 (should (setq eitest-b (class-b "fooby"))))
237
238(ert-deftest eieio-test-07-make-instance ()
239 (should (make-instance 'class-ab))
240 (should (make-instance 'class-a :water 'cho))
241 (should (make-instance 'class-b "a name")))
242
243(defmethod class-cn ((a class-a))
244 "Try calling `call-next-method' when there isn't one.
245Argument A is object of type symbol `class-a'."
246 (call-next-method))
247
248(defmethod no-next-method ((a class-a) &rest args)
249 "Override signal throwing for variable `class-a'.
250Argument A is the object of class variable `class-a'."
251 'moose)
252
253(ert-deftest eieio-test-08-call-next-method ()
254 ;; Play with call-next-method
255 (should (eq (class-cn eitest-ab) 'moose)))
256
257(defmethod no-applicable-method ((b class-b) method &rest args)
258 "No need.
259Argument B is for booger.
260METHOD is the method that was attempting to be called."
261 'moose)
262
263(ert-deftest eieio-test-09-no-applicable-method ()
264 ;; Non-existing methods.
265 (should (eq (class-cn eitest-b) 'moose)))
266
267(defmethod class-fun ((a class-a))
268 "Fun with class A."
269 'moose)
270
271(defmethod class-fun ((b class-b))
272 "Fun with class B."
273 (error "Class B fun should not be called")
274 )
275
276(defmethod class-fun-foo ((b class-b))
277 "Foo Fun with class B."
278 'moose)
279
280(defmethod class-fun2 ((a class-a))
281 "More fun with class A."
282 'moose)
283
284(defmethod class-fun2 ((b class-b))
285 "More fun with class B."
286 (error "Class B fun2 should not be called")
287 )
288
289(defmethod class-fun2 ((ab class-ab))
290 "More fun with class AB."
291 (call-next-method))
292
293;; How about if B is the only slot?
294(defmethod class-fun3 ((b class-b))
295 "Even More fun with class B."
296 'moose)
297
298(defmethod class-fun3 ((ab class-ab))
299 "Even More fun with class AB."
300 (call-next-method))
301
302(ert-deftest eieio-test-10-multiple-inheritance ()
303 ;; play with methods and mi
304 (should (eq (class-fun eitest-ab) 'moose))
305 (should (eq (class-fun-foo eitest-ab) 'moose))
306 ;; Play with next-method and mi
307 (should (eq (class-fun2 eitest-ab) 'moose))
308 (should (eq (class-fun3 eitest-ab) 'moose)))
309
310(ert-deftest eieio-test-11-self ()
311 ;; Try the self referencing test
312 (should (oset eitest-a self eitest-a))
313 (should (oset eitest-ab self eitest-ab)))
314
315
316(defvar class-fun-value-seq '())
317(defmethod class-fun-value :BEFORE ((a class-a))
318 "Return `before', and push `before' in `class-fun-value-seq'."
319 (push 'before class-fun-value-seq)
320 'before)
321
322(defmethod class-fun-value :PRIMARY ((a class-a))
323 "Return `primary', and push `primary' in `class-fun-value-seq'."
324 (push 'primary class-fun-value-seq)
325 'primary)
326
327(defmethod class-fun-value :AFTER ((a class-a))
328 "Return `after', and push `after' in `class-fun-value-seq'."
329 (push 'after class-fun-value-seq)
330 'after)
331
332(ert-deftest eieio-test-12-generic-function-call ()
333 ;; Test value of a generic function call
334 ;;
335 (let* ((class-fun-value-seq nil)
336 (value (class-fun-value eitest-a)))
337 ;; Test if generic function call returns the primary method's value
338 (should (eq value 'primary))
339 ;; Make sure :before and :after methods were run
340 (should (equal class-fun-value-seq '(after primary before)))))
341
342;;; Test initialization methods
343;;
344
345(ert-deftest eieio-test-13-init-methods ()
346 (defmethod initialize-instance ((a class-a) &rest slots)
347 "Initialize the slots of class-a."
348 (call-next-method)
349 (if (/= (oref a test-tag) 1)
350 (error "shared-initialize test failed."))
351 (oset a test-tag 2))
352
353 (defmethod shared-initialize ((a class-a) &rest slots)
354 "Shared initialize method for class-a."
355 (call-next-method)
356 (oset a test-tag 1))
357
358 (let ((ca (class-a "class act")))
359 (should-not (/= (oref ca test-tag) 2))))
360
361
362;;; Perform slot testing
363;;
364(ert-deftest eieio-test-14-slots ()
365 ;; Check slot existence
366 (should (oref eitest-ab water))
367 (should (oref eitest-ab land))
368 (should (oref eitest-ab amphibian)))
369
370(ert-deftest eieio-test-15-slot-missing ()
371
372 (defmethod slot-missing ((ab class-ab) &rest foo)
373 "If a slot in AB is unbound, return something cool. FOO."
374 'moose)
375
376 (should (eq (oref eitest-ab ooga-booga) 'moose))
377 (should-error (oref eitest-a ooga-booga) :type 'invalid-slot-name))
378
379(ert-deftest eieio-test-16-slot-makeunbound ()
380 (slot-makeunbound eitest-a 'water)
381 ;; Should now be unbound
382 (should-not (slot-boundp eitest-a 'water))
383 ;; But should still exist
384 (should (slot-exists-p eitest-a 'water))
385 (should-not (slot-exists-p eitest-a 'moose))
386 ;; oref of unbound slot must fail
387 (should-error (oref eitest-a water) :type 'unbound-slot))
388
389(defvar eitest-vsca nil)
390(defvar eitest-vscb nil)
391(defclass virtual-slot-class ()
392 ((base-value :initarg :base-value))
393 "Class has real slot :base-value and simulated slot :derived-value.")
394(defmethod slot-missing ((vsc virtual-slot-class)
395 slot-name operation &optional new-value)
396 "Simulate virtual slot derived-value."
397 (cond
398 ((or (eq slot-name :derived-value)
399 (eq slot-name 'derived-value))
400 (with-slots (base-value) vsc
401 (if (eq operation 'oref)
402 (+ base-value 1)
403 (setq base-value (- new-value 1)))))
404 (t (call-next-method))))
405
406(ert-deftest eieio-test-17-virtual-slot ()
407 (setq eitest-vsca (virtual-slot-class "eitest-vsca" :base-value 1))
408 ;; Check slot values
409 (should (= (oref eitest-vsca :base-value) 1))
410 (should (= (oref eitest-vsca :derived-value) 2))
411
412 (oset eitest-vsca :derived-value 3)
413 (should (= (oref eitest-vsca :base-value) 2))
414 (should (= (oref eitest-vsca :derived-value) 3))
415
416 (oset eitest-vsca :base-value 3)
417 (should (= (oref eitest-vsca :base-value) 3))
418 (should (= (oref eitest-vsca :derived-value) 4))
419
420 ;; should also be possible to initialize instance using virtual slot
421
422 (setq eitest-vscb (virtual-slot-class "eitest-vscb" :derived-value 5))
423 (should (= (oref eitest-vscb :base-value) 4))
424 (should (= (oref eitest-vscb :derived-value) 5)))
425
426(ert-deftest eieio-test-18-slot-unbound ()
427
428 (defmethod slot-unbound ((a class-a) &rest foo)
429 "If a slot in A is unbound, ignore FOO."
430 'moose)
431
432 (should (eq (oref eitest-a water) 'moose))
433
434 ;; Check if oset of unbound works
435 (oset eitest-a water 'moose)
436 (should (eq (oref eitest-a water) 'moose))
437
438 ;; oref/oref-default comparison
439 (should-not (eq (oref eitest-a water) (oref-default eitest-a water)))
440
441 ;; oset-default -> oref/oref-default comparison
442 (oset-default (eieio-object-class eitest-a) water 'moose)
443 (should (eq (oref eitest-a water) (oref-default eitest-a water)))
444
445 ;; After setting 'water to 'moose, make sure a new object has
446 ;; the right stuff.
447 (oset-default (eieio-object-class eitest-a) water 'penguin)
448 (should (eq (oref (class-a "foo") water) 'penguin))
449
450 ;; Revert the above
451 (defmethod slot-unbound ((a class-a) &rest foo)
452 "If a slot in A is unbound, ignore FOO."
453 ;; Disable the old slot-unbound so we can run this test
454 ;; more than once
455 (call-next-method)))
456
457(ert-deftest eieio-test-19-slot-type-checking ()
458 ;; Slot type checking
459 ;; We should not be able to set a string here
460 (should-error (oset eitest-ab water "a string, not a symbol") :type 'invalid-slot-type)
461 (should-error (oset eitest-ab classslot "a string, not a symbol") :type 'invalid-slot-type)
462 (should-error (class-a "broken-type-a" :water "a string not a symbol") :type 'invalid-slot-type))
463
464(ert-deftest eieio-test-20-class-allocated-slots ()
465 ;; Test out class allocated slots
466 (defvar eitest-aa nil)
467 (setq eitest-aa (class-a "another"))
468
469 ;; Make sure class slots do not track between objects
470 (let ((newval 'moose))
471 (oset eitest-aa classslot newval)
472 (should (eq (oref eitest-a classslot) newval))
473 (should (eq (oref eitest-aa classslot) newval)))
474
475 ;; Slot should be bound
476 (should (slot-boundp eitest-a 'classslot))
477 (should (slot-boundp class-a 'classslot))
478
479 (slot-makeunbound eitest-a 'classslot)
480
481 (should-not (slot-boundp eitest-a 'classslot))
482 (should-not (slot-boundp class-a 'classslot)))
483
484
485(defvar eieio-test-permuting-value nil)
486(defvar eitest-pvinit nil)
487(eval-and-compile
488 (setq eieio-test-permuting-value 1))
489
490(defclass inittest nil
491 ((staticval :initform 1)
492 (symval :initform eieio-test-permuting-value)
493 (evalval :initform (symbol-value 'eieio-test-permuting-value))
494 (evalnow :initform (symbol-value 'eieio-test-permuting-value)
495 :allocation :class)
496 )
497 "Test initforms that eval.")
498
499(ert-deftest eieio-test-21-eval-at-construction-time ()
500 ;; initforms that need to be evalled at construction time.
501 (setq eieio-test-permuting-value 2)
502 (setq eitest-pvinit (inittest "permuteme"))
503
504 (should (eq (oref eitest-pvinit staticval) 1))
505 (should (eq (oref eitest-pvinit symval) 'eieio-test-permuting-value))
506 (should (eq (oref eitest-pvinit evalval) 2))
507 (should (eq (oref eitest-pvinit evalnow) 1)))
508
509(defvar eitest-tests nil)
510
511(ert-deftest eieio-test-22-init-forms-dont-match-runnable ()
512 ;; Init forms with types that don't match the runnable.
513 (defclass eitest-subordinate nil
514 ((text :initform "" :type string))
515 "Test class that will be a calculated value.")
516
517 (defclass eitest-superior nil
518 ((sub :initform (eitest-subordinate "test")
519 :type eitest-subordinate))
520 "A class with an initform that creates a class.")
521
522 (should (setq eitest-tests (eitest-superior "test")))
523
524 (should-error
525 (eval
526 '(defclass broken-init nil
527 ((broken :initform 1
528 :type string))
529 "This class should break."))
530 :type 'invalid-slot-type))
531
532(ert-deftest eieio-test-23-inheritance-check ()
533 (should (child-of-class-p class-ab class-a))
534 (should (child-of-class-p class-ab class-b))
535 (should (object-of-class-p eitest-a class-a))
536 (should (object-of-class-p eitest-ab class-a))
537 (should (object-of-class-p eitest-ab class-b))
538 (should (object-of-class-p eitest-ab class-ab))
539 (should (eq (eieio-class-parents class-a) nil))
540 (should (equal (eieio-class-parents class-ab) '(class-a class-b)))
541 (should (same-class-p eitest-a class-a))
542 (should (class-a-p eitest-a))
543 (should (not (class-a-p eitest-ab)))
544 (should (class-a-child-p eitest-a))
545 (should (class-a-child-p eitest-ab))
546 (should (not (class-a-p "foo")))
547 (should (not (class-a-child-p "foo"))))
548
549(ert-deftest eieio-test-24-object-predicates ()
550 (let ((listooa (list (class-ab "ab") (class-a "a")))
551 (listoob (list (class-ab "ab") (class-b "b"))))
552 (should (class-a-list-p listooa))
553 (should (class-b-list-p listoob))
554 (should-not (class-b-list-p listooa))
555 (should-not (class-a-list-p listoob))))
556
557(defvar eitest-t1 nil)
558(ert-deftest eieio-test-25-slot-tests ()
559 (setq eitest-t1 (class-c "C1"))
560 ;; Slot initialization
561 (should (eq (oref eitest-t1 slot-1) 'moose))
562 (should (eq (oref eitest-t1 :moose) 'moose))
563 ;; Don't pass reference of private slot
564 (should-error (oref eitest-t1 slot-2) :type 'invalid-slot-name)
565 ;; Check private slot accessor
566 (should (string= (get-slot-2 eitest-t1) "penguin"))
567 ;; Pass string instead of symbol
568 (should-error (class-c "C2" :moose "not a symbol") :type 'invalid-slot-type)
569 (should (eq (get-slot-3 eitest-t1) 'emu))
570 (should (eq (get-slot-3 class-c) 'emu))
571 ;; Check setf
572 (setf (get-slot-3 eitest-t1) 'setf-emu)
573 (should (eq (get-slot-3 eitest-t1) 'setf-emu))
574 ;; Roll back
575 (setf (get-slot-3 eitest-t1) 'emu))
576
577(defvar eitest-t2 nil)
578(ert-deftest eieio-test-26-default-inheritance ()
579 ;; See previous test, nor for subclass
580 (setq eitest-t2 (class-subc "subc"))
581 (should (eq (oref eitest-t2 slot-1) 'moose))
582 (should (eq (oref eitest-t2 :moose) 'moose))
583 (should (string= (get-slot-2 eitest-t2) "linux"))
584 (should-error (oref eitest-t2 slot-2) :type 'invalid-slot-name)
585 (should (string= (get-slot-2 eitest-t2) "linux"))
586 (should-error (class-subc "C2" :moose "not a symbol") :type 'invalid-slot-type))
587
588;;(ert-deftest eieio-test-27-inherited-new-value ()
589 ;;; HACK ALERT: The new value of a class slot is inherited by the
590 ;; subclass! This is probably a bug. We should either share the slot
591 ;; so sets on the baseclass change the subclass, or we should inherit
592 ;; the original value.
593;; (should (eq (get-slot-3 eitest-t2) 'emu))
594;; (should (eq (get-slot-3 class-subc) 'emu))
595;; (setf (get-slot-3 eitest-t2) 'setf-emu)
596;; (should (eq (get-slot-3 eitest-t2) 'setf-emu)))
597
598;; Slot protection
599(defclass prot-0 ()
600 ()
601 "Protection testing baseclass.")
602
603(defmethod prot0-slot-2 ((s2 prot-0))
604 "Try to access slot-2 from this class which doesn't have it.
605The object S2 passed in will be of class prot-1, which does have
606the slot. This could be allowed, and currently is in EIEIO.
607Needed by the eieio persistant base class."
608 (oref s2 slot-2))
609
610(defclass prot-1 (prot-0)
611 ((slot-1 :initarg :slot-1
612 :initform nil
613 :protection :public)
614 (slot-2 :initarg :slot-2
615 :initform nil
616 :protection :protected)
617 (slot-3 :initarg :slot-3
618 :initform nil
619 :protection :private))
620 "A class for testing the :protection option.")
621
622(defclass prot-2 (prot-1)
623 nil
624 "A class for testing the :protection option.")
625
626(defmethod prot1-slot-2 ((s2 prot-1))
627 "Try to access slot-2 in S2."
628 (oref s2 slot-2))
629
630(defmethod prot1-slot-2 ((s2 prot-2))
631 "Try to access slot-2 in S2."
632 (oref s2 slot-2))
633
634(defmethod prot1-slot-3-only ((s2 prot-1))
635 "Try to access slot-3 in S2.
636Do not override for `prot-2'."
637 (oref s2 slot-3))
638
639(defmethod prot1-slot-3 ((s2 prot-1))
640 "Try to access slot-3 in S2."
641 (oref s2 slot-3))
642
643(defmethod prot1-slot-3 ((s2 prot-2))
644 "Try to access slot-3 in S2."
645 (oref s2 slot-3))
646
647(defvar eitest-p1 nil)
648(defvar eitest-p2 nil)
649(ert-deftest eieio-test-28-slot-protection ()
650 (setq eitest-p1 (prot-1 ""))
651 (setq eitest-p2 (prot-2 ""))
652 ;; Access public slots
653 (oref eitest-p1 slot-1)
654 (oref eitest-p2 slot-1)
655 ;; Accessing protected slot out of context must fail
656 (should-error (oref eitest-p1 slot-2) :type 'invalid-slot-name)
657 ;; Access protected slot in method
658 (prot1-slot-2 eitest-p1)
659 ;; Protected slot in subclass method
660 (prot1-slot-2 eitest-p2)
661 ;; Protected slot from parent class method
662 (prot0-slot-2 eitest-p1)
663 ;; Accessing private slot out of context must fail
664 (should-error (oref eitest-p1 slot-3) :type 'invalid-slot-name)
665 ;; Access private slot in ethod
666 (prot1-slot-3 eitest-p1)
667 ;; Access private slot in subclass method must fail
668 (should-error (prot1-slot-3 eitest-p2) :type 'invalid-slot-name)
669 ;; Access private slot by same class
670 (prot1-slot-3-only eitest-p1)
671 ;; Access private slot by subclass in sameclass method
672 (prot1-slot-3-only eitest-p2))
673
674;;; eieio-instance-inheritor
675;; Test to make sure this works.
676(defclass II (eieio-instance-inheritor)
677 ((slot1 :initform 1)
678 (slot2)
679 (slot3))
680 "Instance Inheritor test class.")
681
682(defvar eitest-II1 nil)
683(defvar eitest-II2 nil)
684(defvar eitest-II3 nil)
685(ert-deftest eieio-test-29-instance-inheritor ()
686 (setq eitest-II1 (II "II Test."))
687 (oset eitest-II1 slot2 'cat)
688 (setq eitest-II2 (clone eitest-II1 "eitest-II2 Test."))
689 (oset eitest-II2 slot1 'moose)
690 (setq eitest-II3 (clone eitest-II2 "eitest-II3 Test."))
691 (oset eitest-II3 slot3 'penguin)
692
693 ;; Test level 1 inheritance
694 (should (eq (oref eitest-II3 slot1) 'moose))
695 ;; Test level 2 inheritance
696 (should (eq (oref eitest-II3 slot2) 'cat))
697 ;; Test level 0 inheritance
698 (should (eq (oref eitest-II3 slot3) 'penguin)))
699
700(defclass slotattr-base ()
701 ((initform :initform init)
702 (type :type list)
703 (initarg :initarg :initarg)
704 (protection :protection :private)
705 (custom :custom (repeat string)
706 :label "Custom Strings"
707 :group moose)
708 (docstring :documentation
709 "Replace the doc-string for this property.")
710 (printer :printer printer1)
711 )
712 "Baseclass we will attempt to subclass.
713Subclasses to override slot attributes.")
714
715(defclass slotattr-ok (slotattr-base)
716 ((initform :initform no-init)
717 (initarg :initarg :initblarg)
718 (custom :custom string
719 :label "One String"
720 :group cow)
721 (docstring :documentation
722 "A better doc string for this class.")
723 (printer :printer printer2)
724 )
725 "This class should allow overriding of various slot attributes.")
726
727
728(ert-deftest eieio-test-30-slot-attribute-override ()
729 ;; Subclass should not override :protection slot attribute
730 (should-error
731 (eval
732 '(defclass slotattr-fail (slotattr-base)
733 ((protection :protection :public)
734 )
735 "This class should throw an error.")))
736
737 ;; Subclass should not override :type slot attribute
738 (should-error
739 (eval
740 '(defclass slotattr-fail (slotattr-base)
741 ((type :type string)
742 )
743 "This class should throw an error.")))
744
745 ;; Initform should override instance allocation
746 (let ((obj (slotattr-ok "moose")))
747 (should (eq (oref obj initform) 'no-init))))
748
749(defclass slotattr-class-base ()
750 ((initform :allocation :class
751 :initform init)
752 (type :allocation :class
753 :type list)
754 (initarg :allocation :class
755 :initarg :initarg)
756 (protection :allocation :class
757 :protection :private)
758 (custom :allocation :class
759 :custom (repeat string)
760 :label "Custom Strings"
761 :group moose)
762 (docstring :allocation :class
763 :documentation
764 "Replace the doc-string for this property.")
765 )
766 "Baseclass we will attempt to subclass.
767Subclasses to override slot attributes.")
768
769(defclass slotattr-class-ok (slotattr-class-base)
770 ((initform :initform no-init)
771 (initarg :initarg :initblarg)
772 (custom :custom string
773 :label "One String"
774 :group cow)
775 (docstring :documentation
776 "A better doc string for this class.")
777 )
778 "This class should allow overriding of various slot attributes.")
779
780
781(ert-deftest eieio-test-31-slot-attribute-override-class-allocation ()
782 ;; Same as test-30, but with class allocation
783 (should-error
784 (eval
785 '(defclass slotattr-fail (slotattr-class-base)
786 ((protection :protection :public)
787 )
788 "This class should throw an error.")))
789 (should-error
790 (eval
791 '(defclass slotattr-fail (slotattr-class-base)
792 ((type :type string)
793 )
794 "This class should throw an error.")))
795 (should (eq (oref-default slotattr-class-ok initform) 'no-init)))
796
797(ert-deftest eieio-test-32-slot-attribute-override-2 ()
798 (let* ((cv (class-v 'slotattr-ok))
799 (docs (eieio--class-public-doc cv))
800 (names (eieio--class-public-a cv))
801 (cust (eieio--class-public-custom cv))
802 (label (eieio--class-public-custom-label cv))
803 (group (eieio--class-public-custom-group cv))
804 (types (eieio--class-public-type cv))
805 (args (eieio--class-initarg-tuples cv))
806 (i 0))
807 ;; :initarg should override for subclass
808 (should (assoc :initblarg args))
809
810 (while (< i (length names))
811 (cond
812 ((eq (nth i names) 'custom)
813 ;; Custom slot attributes must override
814 (should (eq (nth i cust) 'string))
815 ;; Custom label slot attribute must override
816 (should (string= (nth i label) "One String"))
817 (let ((grp (nth i group)))
818 ;; Custom group slot attribute must combine
819 (should (and (memq 'moose grp) (memq 'cow grp)))))
820 (t nil))
821
822 (setq i (1+ i)))))
823
824(defvar eitest-CLONETEST1 nil)
825(defvar eitest-CLONETEST2 nil)
826
827(ert-deftest eieio-test-32-test-clone-boring-objects ()
828 ;; A simple make instance with EIEIO extension
829 (should (setq eitest-CLONETEST1 (make-instance 'class-a "a")))
830 (should (setq eitest-CLONETEST2 (clone eitest-CLONETEST1)))
831
832 ;; CLOS form of make-instance
833 (should (setq eitest-CLONETEST1 (make-instance 'class-a)))
834 (should (setq eitest-CLONETEST2 (clone eitest-CLONETEST1))))
835
836(defclass IT (eieio-instance-tracker)
837 ((tracking-symbol :initform IT-list)
838 (slot1 :initform 'die))
839 "Instance Tracker test object.")
840
841(ert-deftest eieio-test-33-instance-tracker ()
842 (let (IT-list IT1)
843 (should (setq IT1 (IT "trackme")))
844 ;; The instance tracker must find this
845 (should (eieio-instance-tracker-find 'die 'slot1 'IT-list))
846 ;; Test deletion
847 (delete-instance IT1)
848 (should-not (eieio-instance-tracker-find 'die 'slot1 'IT-list))))
849
850(defclass SINGLE (eieio-singleton)
851 ((a-slot :initarg :a-slot :initform t))
852 "A Singleton test object.")
853
854(ert-deftest eieio-test-34-singletons ()
855 (let ((obj1 (SINGLE "Moose"))
856 (obj2 (SINGLE "Cow")))
857 (should (eieio-object-p obj1))
858 (should (eieio-object-p obj2))
859 (should (eq obj1 obj2))
860 (should (oref obj1 a-slot))))
861
862(defclass NAMED (eieio-named)
863 ((some-slot :initform nil)
864 )
865 "A class inheriting from eieio-named.")
866
867(ert-deftest eieio-test-35-named-object ()
868 (let (N)
869 (should (setq N (NAMED "Foo")))
870 (should (string= "Foo" (oref N object-name)))
871 (should-error (oref N missing-slot) :type 'invalid-slot-name)
872 (oset N object-name "NewName")
873 (should (string= "NewName" (oref N object-name)))))
874
875(defclass opt-test1 ()
876 ()
877 "Abstract base class"
878 :abstract t)
879
880(defclass opt-test2 (opt-test1)
881 ()
882 "Instantiable child")
883
884(ert-deftest eieio-test-36-build-class-alist ()
885 (should (= (length (eieio-build-class-alist opt-test1 nil)) 2))
886 (should (= (length (eieio-build-class-alist opt-test1 t)) 1)))
887
888(ert-deftest eieio-test-37-persistent-classes ()
889 (load-file "eieio-test-persist.el"))
890
891(provide 'eieio-tests)
892
893;;; eieio-tests.el ends here
diff --git a/test/automated/package-test.el b/test/automated/package-test.el
index 799009063e1..799009063e1 100755..100644
--- a/test/automated/package-test.el
+++ b/test/automated/package-test.el
diff --git a/test/automated/package-x-test.el b/test/automated/package-x-test.el
index beb18358085..beb18358085 100755..100644
--- a/test/automated/package-x-test.el
+++ b/test/automated/package-x-test.el