# HG changeset patch # User Karoly Lorentey # Date 1137459402 0 # Node ID de425e4eb0bc257606f1bef1fd19054ff089f672 # Parent 8438f5473d99f6c8430a60e9f163f95fcb29d36f# Parent fbd379b34f0a72810762d7ce7db0c5666811521d Merged from miles@gnu.org--gnu-2005 (patch 182-184, 691-699) Patches applied: * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-691 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-692 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-693 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-694 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-695 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-696 Update from CVS * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-697 Checkout man/cc-mode.texi from CVS with RCS keywords disabled * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-698 Merge from gnus--rel--5.10 * miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-699 Update from CVS * miles@gnu.org--gnu-2005/gnus--rel--5.10--patch-182 Merge from emacs--cvs-trunk--0 * miles@gnu.org--gnu-2005/gnus--rel--5.10--patch-183 Update from CVS * miles@gnu.org--gnu-2005/gnus--rel--5.10--patch-184 Update from CVS git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-496 diff -r 8438f5473d99 -r de425e4eb0bc ChangeLog --- a/ChangeLog Thu Jan 12 11:20:02 2006 +0000 +++ b/ChangeLog Tue Jan 17 00:56:42 2006 +0000 @@ -1,3 +1,9 @@ +2006-01-12 Andreas Schwab + + * configure.in: Move AC_AIX and AC_GNU_SOURCE before first compile + check. + * configure: Regenerate. + 2006-01-02 Chong Yidong * configure.in: Use -Wno-pointer-sign if available. diff -r 8438f5473d99 -r de425e4eb0bc configure --- a/configure Thu Jan 12 11:20:02 2006 +0000 +++ b/configure Tue Jan 17 00:56:42 2006 +0000 @@ -310,7 +310,7 @@ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAINT build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT LN_S CPP INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA RANLIB ac_ct_RANLIB INSTALL_INFO GZIP_PROG EGREP LIBSOUND SET_MAKE PKG_CONFIG GTK_CFLAGS GTK_LIBS ALLOCA liblockfile LIBOBJS NEED_SETGID KMEM_GROUP GETLOADAVG_LIBS GETOPT_H GETOPTOBJS version configuration canonical srcdir lispdir locallisppath lisppath x_default_search_path etcdir archlibdir docdir bitmapdir gamedir gameuser c_switch_system c_switch_machine LD_SWITCH_X_SITE LD_SWITCH_X_SITE_AUX C_SWITCH_X_SITE X_TOOLKIT_TYPE machfile opsysfile carbon_appdir LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAINT build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP LN_S INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA RANLIB ac_ct_RANLIB INSTALL_INFO GZIP_PROG LIBSOUND SET_MAKE PKG_CONFIG GTK_CFLAGS GTK_LIBS ALLOCA liblockfile LIBOBJS NEED_SETGID KMEM_GROUP GETLOADAVG_LIBS GETOPT_H GETOPTOBJS version configuration canonical srcdir lispdir locallisppath lisppath x_default_search_path etcdir archlibdir docdir bitmapdir gamedir gameuser c_switch_system c_switch_machine LD_SWITCH_X_SITE LD_SWITCH_X_SITE_AUX C_SWITCH_X_SITE X_TOOLKIT_TYPE machfile opsysfile carbon_appdir LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -3668,12 +3668,298 @@ CC="$CC $NON_GCC_TEST_OPTIONS" fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + + +echo "$as_me:$LINENO: checking for AIX" >&5 +echo $ECHO_N "checking for AIX... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef _AIX + yes +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "yes" >/dev/null 2>&1; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +cat >>confdefs.h <<\_ACEOF +#define _ALL_SOURCE 1 +_ACEOF + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +rm -f conftest* + + + +cat >>confdefs.h <<\_ACEOF +#define _GNU_SOURCE 1 +_ACEOF + + + ### Use -Wno-pointer-sign if the compiler supports it echo "$as_me:$LINENO: checking whether gcc understands -Wno-pointer-sign" >&5 echo $ECHO_N "checking whether gcc understands -Wno-pointer-sign... $ECHO_C" >&6 SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wno-pointer-sign" - cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF @@ -4351,53 +4637,6 @@ rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - -echo "$as_me:$LINENO: checking for egrep" >&5 -echo $ECHO_N "checking for egrep... $ECHO_C" >&6 -if test "${ac_cv_prog_egrep+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if echo a | (grep -E '(a|b)') >/dev/null 2>&1 - then ac_cv_prog_egrep='grep -E' - else ac_cv_prog_egrep='egrep' - fi -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 -echo "${ECHO_T}$ac_cv_prog_egrep" >&6 - EGREP=$ac_cv_prog_egrep - - - -echo "$as_me:$LINENO: checking for AIX" >&5 -echo $ECHO_N "checking for AIX... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef _AIX - yes -#endif - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "yes" >/dev/null 2>&1; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -cat >>confdefs.h <<\_ACEOF -#define _ALL_SOURCE 1 -_ACEOF - -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi -rm -f conftest* - - - - #### Extract some information from the operating system and machine files. { echo "$as_me:$LINENO: checking the machine- and system-dependent files to find out @@ -4549,13 +4788,6 @@ - -cat >>confdefs.h <<\_ACEOF -#define _GNU_SOURCE 1 -_ACEOF - - - # Check whether --enable-largefile or --disable-largefile was given. if test "${enable_largefile+set}" = set; then enableval="$enable_largefile" @@ -8072,7 +8304,7 @@ cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include +#include _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 @@ -8099,7 +8331,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 for ac_dir in $ac_x_header_dirs; do - if test -r "$ac_dir/X11/Intrinsic.h"; then + if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi @@ -8113,18 +8345,18 @@ # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS - LIBS="-lXt $LIBS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -int -main () -{ -XtMalloc (0) + LIBS="-lX11 $LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +XrmInitialize () ; return 0; } @@ -8162,7 +8394,7 @@ do # Don't even attempt the hair of trying to link an X program! for ac_extension in a so sl; do - if test -r $ac_dir/libXt.$ac_extension; then + if test -r $ac_dir/libX11.$ac_extension; then ac_x_libraries=$ac_dir break 2 fi @@ -21664,18 +21896,24 @@ ac_cv_func_fork_works=cross else cat >conftest.$ac_ext <<_ACEOF -/* By Ruediger Kuhlmann. */ - #include - #if HAVE_UNISTD_H - # include - #endif - /* Some systems only have a dummy stub for fork() */ - int main () - { - if (fork() < 0) - exit (1); - exit (0); - } +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* By Ruediger Kuhlmann. */ + if (fork() < 0) + exit (1); + exit (0); + + ; + return 0; +} _ACEOF rm -f conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 @@ -23121,8 +23359,9 @@ s,@ac_ct_CC@,$ac_ct_CC,;t t s,@EXEEXT@,$EXEEXT,;t t s,@OBJEXT@,$OBJEXT,;t t +s,@CPP@,$CPP,;t t +s,@EGREP@,$EGREP,;t t s,@LN_S@,$LN_S,;t t -s,@CPP@,$CPP,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t @@ -23130,7 +23369,6 @@ s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@INSTALL_INFO@,$INSTALL_INFO,;t t s,@GZIP_PROG@,$GZIP_PROG,;t t -s,@EGREP@,$EGREP,;t t s,@LIBSOUND@,$LIBSOUND,;t t s,@SET_MAKE@,$SET_MAKE,;t t s,@PKG_CONFIG@,$PKG_CONFIG,;t t diff -r 8438f5473d99 -r de425e4eb0bc configure.in --- a/configure.in Thu Jan 12 11:20:02 2006 +0000 +++ b/configure.in Tue Jan 17 00:56:42 2006 +0000 @@ -3,7 +3,7 @@ dnl autoconf dnl in the directory containing this script. dnl -dnl Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +dnl Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 dnl Free Software Foundation, Inc. dnl dnl This file is part of GNU Emacs. @@ -1261,6 +1261,10 @@ CC="$CC $NON_GCC_TEST_OPTIONS" fi +dnl checks for Unix variants +AC_AIX +AC_GNU_SOURCE + ### Use -Wno-pointer-sign if the compiler supports it AC_MSG_CHECKING([whether gcc understands -Wno-pointer-sign]) SAVE_CFLAGS="$CFLAGS" @@ -1320,10 +1324,6 @@ LDFLAGS=$late_LDFLAGS [AC_MSG_RESULT(no)]) -dnl checks for Unix variants -AC_AIX - - #### Extract some information from the operating system and machine files. AC_CHECKING([the machine- and system-dependent files to find out @@ -1473,8 +1473,6 @@ dnl For AC_FUNC_GETLOADAVG, at least: AC_CONFIG_LIBOBJ_DIR(src) -AC_GNU_SOURCE - dnl Do this early because it can frob feature test macros for Unix-98 &c. AC_SYS_LARGEFILE diff -r 8438f5473d99 -r de425e4eb0bc etc/ChangeLog --- a/etc/ChangeLog Thu Jan 12 11:20:02 2006 +0000 +++ b/etc/ChangeLog Tue Jan 17 00:56:42 2006 +0000 @@ -1,3 +1,11 @@ +2006-01-15 Dan Nicolaescu + + * e/eterm-color.ti: Re-enable the ri entry. Add kich1. + +2006-01-13 Richard M. Stallman + + * emacs.1: +N applies only to next file. + 2005-12-28 Dan Nicolaescu * e/eterm-color.ti: Temporarily disable the ri entry. diff -r 8438f5473d99 -r de425e4eb0bc etc/e/eterm-color Binary file etc/e/eterm-color has changed diff -r 8438f5473d99 -r de425e4eb0bc etc/e/eterm-color.ti --- a/etc/e/eterm-color.ti Thu Jan 12 11:20:02 2006 +0000 +++ b/etc/e/eterm-color.ti Tue Jan 17 00:56:42 2006 +0000 @@ -47,12 +47,13 @@ kdch1=\E[3~, kend=\E[4~, khome=\E[1~, + kich1=\E[2~, knp=\E[6~, kpp=\E[5~, op=\E[39;49m, rc=\E8, rev=\E[7m, -# ri=\EM, #temporarily disable, it causes problems for mutt + ri=\EM, rmir=\E[4l, rmso=\E[27m, rmul=\E[24m, diff -r 8438f5473d99 -r de425e4eb0bc etc/emacs.1 --- a/etc/emacs.1 Thu Jan 12 11:20:02 2006 +0000 +++ b/etc/emacs.1 Tue Jan 17 00:56:42 2006 +0000 @@ -100,7 +100,7 @@ Go to the line specified by .I number (do not insert a space between the "+" sign and -the number). +the number). This applies only to the next file specified. .TP .BI \+ line:column Go to the specified diff -r 8438f5473d99 -r de425e4eb0bc etc/orgcard.ps --- a/etc/orgcard.ps Thu Jan 12 11:20:02 2006 +0000 +++ b/etc/orgcard.ps Tue Jan 17 00:56:42 2006 +0000 @@ -10,7 +10,7 @@ %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips -t landscape -o orgcard.ps orgcard.dvi %DVIPSParameters: dpi=600, compressed -%DVIPSSource: TeX output 2006.01.05:0904 +%DVIPSSource: TeX output 2006.01.13:1223 %%BeginProcSet: texc.pro %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S @@ -352,204 +352,210 @@ CCBD1F58ABBF1F53AD21E3BFF25EEEB046F66A924E5F431EBD7228050BE2DF43 0B9B538DAAD511EED97630CD9A9C05CC49DC251325A93EA842C6D07B44BE620F 08E66B611F54314B0177E299304F2294F8DEDE9914736944F125A50B5007373E -588AD80D9983CE7824DA30CEE5DC3114D69D7ACEC0758D8201805B82925EF3C1 -3A6757674B84D9B585F981DDFFB42163EADF90346248E014A74E3FB3E6276FC1 -B4289FCDB4FDBE9C70CAF38E410965A3610F649DF8F81C73B87FBE27D44A3CA6 -D7883821CA22795E3EED184F4F59AC687AC06DC4DE7FD098E0EA61C494A5E960 -643D78025B1D18B4B7FBACCE2DEA453E35C08A6AC093F45FA0B1DE132F743CBA -75F2E7BE0311132C0E63C69D5182B98AEFC610F61D1E1EA51120D8A9F5DFFA8C -37C0ECCA2120E1DF7A551343BD7573FA24144A8D59CA684FF9FCC1E023A3401E -9797D658E92CED2255A273E429FAF43B0355E27EC83974BA4675520B2DC70DDA -DF783452C679BB77759479CB02FF3377BCCD8580E3D87D34CD579AA3F89AAB44 -E526EE761B0D371E27B5A02A5C494C5169651FA79795D332045B3E7F2CA100FA -FA8ADA74DCA851DA1BC7531E58EE08FC22F2F35E94D5DA013A4C9669B2825D26 -021982566B4347E518E82602B0CE5CBA1CD38E8B3CEBBFDF9E9811C896313F37 -51D5F7162441E4B2DF18A7A34326114950BE85B3E5AB465D54652575AAC03DF3 -E50E9FE8D184D33534E12AB92DF20BD72DC129A86CCC24981FF82E297D0B0F9E -0B66137443B501B5FA711C7DF380DB1F64404DA241D1EF5F2D012A0293405302 -F828BF879F46962DFAF75F44D4A394DB9D42E4874477097FF6F8DB9BC8712BC8 -661A95A2467073355FE697CBE1D8E298569935E5405C22555C40DB775A808F54 -642939D8E4F76C61B2FE966F4FB55319873127C8EEB05732A1538FE03EC2D8CB -9089DE328A396DAB3908179FEA2FC3F2ECC48593049FD23114A04B474FF4FBED -4D3B8835148CCB742574F4914B7201CE41A57A42EF61099509E5C42B744611C2 -B40581A6BCF6FA223E5B5221B8BB16AC6EEE3774130E121F23A04E1548F58899 -41C9DD31E720AE7392E4E2CE0ED4B691620CDB0228D3BEE1F4BA6E289E33B7A5 -6DFDA767F5927F00BD22D4BA6397B37BBDE84BF9017C01DD5319AC7D33F8C007 -AF43EF247FDF67CE6627D4A0B0F00A3E58DF6323BDF1100660FF18496649C2EE -6BF1D9940404E2E4B7BB00C807808BACEFF0581E38B9A7F03888BA67E73E002F -871DA37277AB6ED4FB27AF66B9A02C62313495E94113D667CB3FA94DE087C6FA -2481136385B557165CDEA492CE335DB20BFAFE7A3015C95D8C88F6F3065D7F72 -5484F8B665295CAF3E207C758FD9533889D7EE5E16D08577A97185871BAB4CFE -CC58C88B3B0BA4130727C2800D2C305855369729B8CD09AFF83FFFCC3A85014E -7358281AD0C842CC1FB985DB59470AE90BE27190DE79134F2C18447150A6706F -5597A256370F4EFCDF59A7EA8C9BFA2A194DC5F1975D7E875F036BBA686FDC22 -8E9934A3ECE619598C0CD24B3226D55BDC6BF23ED4659DE24072454622A47FC1 -ECDF8D1B202F9178BC1075A4AD29D85545F9C08E16F5BC07C7218FE4C8914D89 -BC259609E90B47B956DE309C40E2943ED6CD471A8506FD38066AB96F573E7922 -B77B4386FDFBB8AC7154342C810D452827169AB8FDB73F50AB7EB6E38A930807 -F91212373CDDBE84FFF86ABAFBAE766F519D1DA26404D7EDFFA803DCB8382EFE -DA1C3D22D195805069C848619646B126333D0605BD76497030E0D3E32EFFAD65 -F84003741FCCC4DFF67CA124B41DA9F0CAD27A1A46E38DA588B443C4301216DA -5DA7A473F9C5F04B2B47446168A2017136ABFA92F6EE9C5DA2B1A92CE664659A -027899D7BE0B322ACC0EF38EA681B4D90F5073C4B4064F8053AC54ABC1594883 -E4D836FD382F00043D97ECE2DEDDFE704F10CC450E4451679E373041B9814AF1 -0D2FE34CC22F7938562B506BC63C03AC904943C4CDCEE5D25F9B65816561962A -68EC20E9BD6E4964226F8C64DC410AEE5DF5F607ACC023BB583D471EAD0B8190 -912DC0D8BFFA623F944AA1AB0BB1545DFBA26229F161201DADB7E07FBFA9040F -5D6D30EBAF57A2EF4A82A30D67825A35E24F350F9F700B42BC926ADF418F6375 -A7C7AE27FF720E9A71817E395F33E8341B70DEF491B6C4AE4051D825B09535D3 -4A0E7B0853CC42956A0A2F1A7421FEBB020D1F178371271DA9893AA2082DED36 -F834704E1CDCACEEC30EFC5514FA218E88E8C9EBD5814124D637221AE0D898D1 -2EFDDF9296D8AD971873D821B5E972F89E24659DADC4D82EE284F6247933EBD6 -643E846894BF9F2A272965E7D3E1466C1AD086099C214CD475F5191FFA282F92 -6EE857FE6AFDD3FF7664E82E0E265CD5487389254F38042EBB5F9866C5B24154 -DA003C177D7E9384E8426D7B88D5701AE7C530A50F6D027904C041F690143008 -D6246306E4644AED88E76F83949352CE1329B1A5D07A1FDA04DA0BBE5F30A925 -740235EAC5DD32F81545836873EC429AD95E7F56BFE4DF70399A7AD2476EF29E -45517385D898071118D2DE56D7A2294CB12D3E22EA35234E752DF7F061A5FF8F -5765C7C13FC74144738679B42351E3B82CA2C91F619B5D06C1FD36661F4397B0 -7540457CCB3D2FB735BBD9ADAA24756DAD45CD5921AAB588DCC80103E1C50290 -204EC4F7F5DF74D8CFF0EEA530CA2D0E88C86431F22062276E9BF9BD68FB8517 -7245261F180FEB9CD574A82A17B8A134BBBDC9B5B7954831DCFA68E0B4266C6C -F99588BF404005CE59C53E94B767B9EFDC1E5674970D097CC221C0C3BC825F17 -62D9F00A1B46B915BC8F0BF7AB31B3F688C9C968F516FC3DEEB149981EED2A47 -C51C8E8CA61F1744B31F483A52ECBE76606F24D90B13569A546420032EAE0F29 -0A564955B4BE1058A9E6EA3B320A15282EE2449E928C8E405BF3FECE131B30E3 -77FC3A735A6E2242C1E4A27793A0E1BB63FF7F6958E5312FE1549DDDD8E15BD1 -7BB07C6564D029C830B89880B4F49207C1602EE590898896EC49BE45DA8906B7 -380D59CE86D7AAB6B0762F624C88D886488B7F6AE9F1328FC400869CE4EEFD7E -7BF55C3DFD059FA20338C9BB33D807236EA2EF6E1C0C1E9EB095DA69FE2831FA -4A0F750418D935F1F0E45AECAA61ADE9D96012511981710FC4225F5C7660A2F7 -0A417E5910F4F05D43E8AE0872B16F4E46554848927F59BDA1EBC5724ACA6B1B -6A62FA03E86D85104E88ADCBD253734F9D078543E3A9F1985FA4D4A77DF2C55C -6F5E9257851A953F1BEF7192B89A409B5566AAC7DDA66F6DE4D89FDF39994611 -5B95857B8B6362BAEA1C939F638E527CA9F58683236B1886E5763B518D5A9F50 -012A1D991AECF0E327594A12476A68C715130D197C1EE81CEEB4DE9E05F7F4EB -0F06054BA90F9CC30C27BE06803ADBE520115F0FB8BA26B0DA1E5A8D28F1CB00 -F7808BD2B0D629A0BE002C11FEAD0A59555E90851E47D466BD87069845B2A6E8 -53E054711A465359DAF057550B8EE9F11F8CA6DEFE6FA70FCAC9856ED992244D -B6D8DF2428F1D09C54C41F54F939DB26081DC63D0E8AC0690E72E76EF2F004B3 -7204E227BD70421CE589A5689FA540C2889BE8B9841193BC020FC07B7B245580 -996EB478FDB9C2F3F7CF02CAFAF3005F12CC496EA254D56F4A26D841E31B2360 -8A1716DBC1A0312F66A2B19A55399BFD9D80DF17982829C3A5F790634FD86DAB -542413C0E19CC1F40FBFB296DCF1DAD4135F688AE11C2A5896EF0C8A54F298B8 -B9C21D82E15BE4B03C7F4D0D6861F28E86D25D98292D7C7C38EE483C2D6AE68F -5CC883C30B92FFDE6D60FD21E9E0E3441C317EE946448D26F8D169A074C92CD7 -D2FE4ADA122D99FDBACEC5D884F728266B21A6B5974B74A21884CC847747F648 -1CF5A52ADB32B3CA4DF108D086734E7F57E2DD6800F22D73F1A579B06EBE6F81 -BD6DBEFF758FC63934F89E8CCE37101AC52AE651F3BD8BC6689297E04D740F6D -56543897EFD747491B65582F6C2896FF3C8521E6948745BA255720AD93C36766 -5669C5C91E00A093608D3376F3107F2536046299BEFE221929CE0414E50D8054 -F07AA336F93C01F28FFF407F6B726155F48F339D97E10D628DE2D5E0A2ECF9AC -6E17695CFBEC59A0EAF50110EDE388579FE3C3EEC98A1F0414F2EC9D3A1612E2 -849A21EB33FFED0B4A753D44B6CCF61D7DA8603513059E5A5523D2FE01D2E970 -EFC7152105BB94A40C08792A75D94EF8333B6A392C51F6FF1BE5904B5877B655 -28E17551A83463B9DD6D6B2F419BD21119B7A9D14325311066AC1A20DB8986C5 -4DB51E16782B5AE654F4C0C9A92C5A1555FB54B1B7E70DADF9A303514E7F7E7B -E99C885DF161FA302CF928BC04535666D5508D2E01514B2DC740E3715BFD603C -D1CEF587FA9AF69D6D8019A2DF5DC33D61F1D324037A06563AE6985CA5DE4C61 -28663AAF1815F8F0B1266C2EDF1A3322FF108170DFCBC13DF794B6A4E64D7202 -E4200951568C73DCF0F2153D724DBC35F1EDA6B31FBF8E1E35C6781A47D1899C -5710361657554359A7B07794967936966E29765A4E2B4741165EABA8A0ED123D -13B77EA9CAFD065B3DF2967F1FC142B0435583E6D221FD15307C8A388E2CD9F2 -F7012BC7BF2D910F639F60F55508AF5A479FA963E7AA049F23A1D8EC24A90BAF -3537A956F8F16D2242300ADCAFE145B44F89DD449B2AE64F41BB4F92DD45F6C3 -CC091487708BD252CDF835D511714F4B51749BBD34A5D812700EFBDF072A40BD -6CE38DFC9A196589D6FC09FCCBCB7CA871FCC35B25354537B959F01E84C1F959 -9E8397B308A3BCCDFA304213116594C3D1925A815B57AA7C631773B5FD518EF6 -238F548ABA462BC1D0A17E76B53CCB2BBF7E8A785620B41C8018109CB45CE895 -BDAD0F89B25B81E4A0478D4A242D3A7A4406D932C0E9FD28E65C57CC3F146E1F -09867E0FCE83F7C2083ADDA5C5A9FB5BF48F89DA0C4BBD45E7120016314098B4 -C6D2C37F5F7709AD5822EAC452FBA28CFEB01E3BF2DAF25C1B559F07152FAEFD -96641B74A4249E88962604CC67F39881A685491DA88705585A7EAA097A2688CB -FC4A8E722D560B2442B3E7EB02F34E30A8A049705DC0C1D181438E85EE53C3D9 -EB5A320A83315AD4B4D26443754B49EA70A16FFCCF753F7B1E6C7EEAD9F7ED75 -7005A52BAC977F57287B77DA642B1467B580E481D97938D1B57519B1970351E6 -A752CE77704369B0E3FA910874DC76415AD1FB4E605F0C806A1A044F300C859C -9A76CFCF2B65CA446AC2CAFF3D9148D662EB88B39D854A4A799DEBB1BF06F120 -D0DF95A54D183ABB65041EBEB986A132B2543EF98EE749F8976279A5448CD151 -896074E5140A766A0A9E95B73C737D09FB6DE3EF8E85B87F477935A04476B0E8 -50CE7A918AB5DEB38BFB8525587CC5B6759CD3C82C2623F628C116A40D3B2AB1 -AEC0D515C14191760DFDAC3BC2154A356211A12A7EE704096F258C66F786311C -03E84B5C05C311B04F1BCBF61FA40B6BB8E2E080B42178F225F37CC1A96CDCC0 -4ACD792C9F0AC7E7E3992238C0E4E88B04A93797E17ACBF04FCE6494299AA9B0 -37A73C4059FFBC949ADDBC0AF181B728AC3369CC6DCE58F7AC4A52A686B74C08 -56C30D0BF291B127F7435F8AA711F98342423BD6DD25D69E3D6E197AEBF90AC5 -E9675FFE7BF93DD5E6C8A89780ECC425B3D735A89C671FA5D70125CFE3B72DF3 -A54F27293135BD071CA5D2365A135A3395D39A508CD434F45793A610852E3D62 -1C717D529A82D93B90E2FF31629413B7AC1DF1EC4D6577980C34357F47899BE2 -CC95866E2140CD64D51AECA4BAF717F4D4BA13F1310F51AE6CF80689F7A1BD04 -1474C8E2B7A640DFCDCDECB7FF9690E8E6FF62FA9842293A1264D9C4AA5FC6DE -84C36FB9334F5F9CA1B3DC4516D4CA3BD116605F5C5D0FB2F30FA080F83891DF -1A23D9C420B3F204085591E4C88C7B26452B329DD0B1F9EDC7B065F21A4B6F60 -349D37A85C5985667040DDE858B27C832CB50CCE7BB9E1EC9C2D5C1B0F05D027 -65A743C13523FFFD455B9C8DE573E76522A8912AF192008DF97D7DED77FB56E6 -FC220D2E27CA29ABE1A138D3FEF84A0306D4DE8ABA3B65D6AACCF1E456C14293 -13A2E52EEAD3CE4D2980714C087C0606768FCE35D9F84873379C90A118B9F4D3 -6008721909002435E6242C5BDB4F85AD82D5C9D548B5786F50821A59FA41D0CC -F096FD004329DDB25C494E4E1D63065EF6CE62C5C59084082182E139109B0E25 -09B500940B0B254F6E76445AB01617C35831FF74DDEA2C582D7E1B736A23322A -4564662F5D21F638CE58055212A66C29755303AF713D54BC4EF5BDD0AF37FE84 -04986F5DB72899B3642B53E80BE87161B5106E8C0114A985CD72DB6E6D3171C0 -8AC789185A6608C45889D19C9574E8B1042846B5E53F303273ACD9985F92874B -0395250173AABA938AF4551E955106AF3D1FAB12AEF599E758278C9C4B0B6EAC -346765F34498198FDB4D2ED8EE4399921A3D380DA97F573E76588A46A927E56B -02EBBE1A628EAD4DCF52726AB2D444450598904C10C0BEEA4D4D313B03ED8BB8 -D5E1125C7F4A24F3F4757365B838BBBB93E232CEB9E8A02531B4E9D116D56E7D -5A9D547E7A00301433B3B8906D494A47B358C51E09BF70DCBE06D594E4A27C54 -83020848F8052038C052AC353AEF3E9D3EBBCD74357873ACDA704659A7962538 -B2D7829C4808D58E17B2DB2E20E464B53445674ED6B373CDE6DFC48AF4268447 -7DA072CB3B480B0D1C26B9753F5A34BAC7380F43ADE718172C399D335A2E88B3 -F14DBF6F091FA427B89FD51C12401441AD767AEEB19CCC2643FEA6BFAF53A057 -F7594CFB89E5DAECDFE36D1CA884C287B5AD943EEC86FB91BCE72693E7586E59 -F594D067F101A95A1CFE062799F9B6AE9E14E1CEE9A9AC23975B534749D9912E -B5190AF0CBA729B70BCBF2433BC8C2808CB6A3A64E87A140E4532AF41F55CE51 -2BF9B4EF348B1F8CC7500847A076EAA125670223BA1BBDC979707493F7DE73CC -78D79A4CF61F4AB8A819F9DF633BE00ACFACFC63438BD5F9CB65F7DBE1C1A99E -AE9E8141EB065D30C17A79C2FC3686F2D13A187C69353374DDE142619D7C6989 -9414C36749E400F0D56C0DD786448421F4D638A1D545BDA0DA9637953D299743 -7A4519B437DEAB7461B69C96DC33B3834897568ACF6C66628DEF7AE597ACCFBB -E273232CC0BFE67E9B89B7F0AC82F5C629E512411A9060D02623BAB507671545 -09EA818A7C0A94A01007DD0D7DD286C22B9ED463836B1D328290B3836FAB5F25 -380917C153901773BBE997031F8267CC91FE3C1916DF6AC46E44791A0863198F -8FB8478724C22BB2732F945B39E4541C0168C45FC18FC7CCAC13FBEA39A93806 -6DEF0FBD7507AD086EA89EB278DB92A9F44D9A8584754643FFFF9C411587D22A -C317E99C08DD469A3A2CB264C3899725338B923F660E1DB69BDC42D5C8BE2193 -B3139B8F53777949C20CFFE8918249DA5606C5F826997E18664085BCFC8FE460 -8D8B5EE4D0EF5D9C2F78246F757F01D2C2CE8EE265DA8038A276EA69BB8651A5 -2418E8479CB00E750644F3745408AE4ECF34B6774AA58D43D28C46DF56A9CCE0 -D7EB1B3E4010F1914A6AD8B0ED7A9104A16A1B2DED8937A5779B2B7E6F724FCF -FBAFD79D2B7840E3F6E4378CE20185DAF51CD5DCDA7F797E5EF992C9B7BD2089 -FEB3A7165FA82A23E5CB0C99003BD75E3B9B00D5308C5C71FA9A4B2E3FC31B84 -35AC901ABEF4AEDBD785E30DEB848014955D1D0B25932AD4420B4FA52830FC10 -EFDABB03B27E85BBBFA667C76E4B5A68F4BC2D2F0BF631E43DC0A18522911998 -834B89CBFE29DEF493B9E87B93D7D9D886FAAC41023231E069E6B0FE3BF904A6 -7149D092E733AA2CA5442C49CC496662F11EA262C67CD191E9BB8FCDF54DEFC5 -ABF141056F515EB48AE9DD502F285F2488119652DA821EA3BF2E7D9895601DBA -0B042D7D2CB609A542734B3F63FC3AF4FDA552BA15DA5E02C23CEB0F0BB14DB5 -2100EC71E868218241E86741638AA14DC1FCE8C1CB035D61C1F9F67EE3D85BFD -BF9EA07AEC4787D7C40557DCA541E7CBDCCDA950AE2E95ABF82633E20F2A58CF -14D205265FF7A1A3524562F62C4C3FA62043B4518AFB0616BEA02145B679BEE9 -CF367A8E5C053F22A004B8ECC26CE1FD6C425A37F9F7EA73AF4A9E9E2366B573 -BA26C25CA60D1436CB40824EF20C87734EBF7FB87EFE47C0292750EA29667BFC -5DA8A01867A94332D779082BDC1114E128ACC6518F8D9B3A21AD8AF7463A42E2 -FB7E29BBBA59189421BAF708893FBB471406F264DEF7F9CA2C42A4956F8CA7D5 -BAC73FCB2B21D6F16836D2E5BC7ED04638ED3D0C480B0E057B05075C0A92464C -6F6E151C818246B845E5056ABD9DBD8219D4086DF9BE0E13F594450B737C0512 -DE7BCF813764645FC7696D572A873CF1075B1627279D6E3EC493627E06DBD02B -C978BB7D39F80CF960354B963F4302281538C6EB420E55E899D9D101798D5CD9 -3E8FC2675D6A5CB2F2423542FB62CDD78A962EB2D63833E6DE848FEE15430A66 -AD244BD768A3BC8307C833997EFD0735A852B6539E7E873A62461F32820B062E -ED77AF1F260D9B4EC55C60C0B2658528C088357C039DF1F3F85AE16917C77273 -55CE42CAC9C5499E07508FEC82BA810C6AF5AB0F597F3174F91DDD9007100491 -1859D303E60AE00ECED21FF7258B613B342C57C22947D60DA3143C3FBC073FB4 -E41E8268DA25ED1D3E030915576519155CCDA8053BBA3BDFBA018C368A077545 -DB789190EC4E7D7EB9AAB77E54F49B07783EEF138026C7101CD5315D14E0F9FB -2BEFC34B5B1A03D2449A1ED3F26DCB75EA542C995EFE140B51B9508737817A9C -962FE2A0B3650F7770C6310F8A0DDD48EC86BA3958F5343C61A2971B413B52F2 -38E66EC71F73DBC29E6798DF7CFCB3103F1841A4D8FCE51983F03EA288BC0045 -0D3565C494E7BFF2178F273FD714ECF7DCD6519A9BB36F95E05A3F2449F89DD9 -E564458349C34A3CD770EFF268495183A0 +588AD80D9983CE7824DA30CEE5DC3114D69D7ACEC0758D8201805B82925EF3C2 +C87A1A169C5ADE44B561EC1660E617FB39D1B1547B33C0FEB33C3A1D7340A62A +CD9CEFA49481F19B39A704A53A0B98A11744143CDDA0E668E6325935C6497A9F +AFF471194932AFECBF25B441AD55A43751FBAB76F3E544C4254AEC4BEB5CFE4C +C1318C3A0FAD0E8C1BABEE20B203E1DD9412E66BC55BEBD6FBBEBA84F56604FD +85D50F733D9794611F4137EC10ACB4C4ECA5A81CAACC45213E92ED3C26726BBE +91430E7633A2BDB8EA3D0C55259D7DBE468AC0964A63728C9B8EA4E15CF0EEA3 +2E754B9170EAE6B8818DCCDDAD643B9F6C91C3C5B245CD442358C60AF390DC76 +342E659D4EC45552626F069F346F46B18062CE26D5912336C6B29FCBFA5C3113 +ED86E44B529CD95B7B5B934D899762C4F3457F56ACCC763BCCD5BD08975EB5F1 +C5216DA4CBF3409EC71054B0145183F7DFB31517D199EB16D4C6DB0AF05E5720 +10B06F395BE3C8C59CEEBCEA1E00F9EA3FD880AC197508CEC11E33B6B6EABE3C +0FAEBF246743F62D280875D052656696AA88DABB918F79279A980754F3DCFBEF +7999E7FB7C9E7F88CB15E1596F08E48FA74F1CB613B587BFE72717437E38D08A +C8B160982A6F92CD0BAD7E033766BB1D92F78F22FE5750D002AB2C7A101A57D6 +3E7ABA9BD4B8C0A4F2820123BBCCD520B9608AFD4372366D876F848ED068245B +6BC1DDF4B826E4A9FEC4390CEB2DAAA63D9D013B706059347709F3E996C3682A +F88D827B8B7E1206BF2B2A394AFB00B1207819DAE82D1132989702B219E4EA71 +A2BD6EDA183C552C874DBD142E826B583311784EEBFBE96D3716E0DA9C4B1CD1 +C7D649FE269C801411290846EB69BECFA24AACFE8895AC574ED538951B84CDBE +4D935C15DADFFD2179C53655CE2728B017DCBAA14D7B7140AA7B42492E7C568A +C718B186FE248F58148FBEAC7CF56A67E1B7CF6E5A3D6B5675AA8005BDD71A6F +40B90E5B304E43F0BCBAE31238B09B65AA17F09B0CEB3A609156CF83E92AB27B +BD1E80DCCF305D627821FB110676D0BA0F02790A51804686143AB72EAB98AAC7 +CB4E052BC8A19362655F0DD0AC4B8578BB227830D9D713116725A3BB05CB2F84 +9A84884D80116E47E5FA2802EBE7439A8484A9FF18A5F5838731C6C55EF3B749 +ECEDADC2671F81A2787323E372AC20D3E02849D3096C64EB86393B374DB0DFBC +393E9F0364F58CF81BC788C7B779BA0ED32A26389CBDE9E5A96E79D014C0B5F2 +D57F9B968ED9FE793AA0E1A02432E1A5075947D96909DC06A06C467CB86F428B +BCFB5149725BAFAD34F733692AD90AFCE2B3A9281CEBDE9EFD67DA0A79BC0AA6 +E6C47F2FD4E8698109A28915DAA6CBA5FCBD52EAEAC8087796A4309EBCFB2DE6 +295ED1CE5C51255C05F9258F958E9F7A7A5AD52F8D9715B99CC3CDD77A5212FD +BFAC311D3E5699D5D5BAD6DE8C425B118D9636F4AD4EEA8FBA4BDF3B15C2A939 +926162F94D522B0990E7204BF3A81E3E72C9A80D7688BA28DEE8F88155F8CB15 +02EF6C6BD3C9A961B591DC80C24CE9E9BE24254911D558534A7B4AE0CEB01487 +B6451320B37891175CAE2F534828978831AFC6846CDF9A2B86FC209A5DC8983B +1A6B5BD7D9D33AAF2D7340ACACD7E03CB238D0366E83852B2BBE428063A4FCEF +B6E48332E6633F790971A587A3F038A256D181B5584691A9405732D33A2F55FE +8BD68E07E6E01A27FC74BCC9946204A478D13C51490E9D76C4EE375190026156 +FD879EBC0A579DBCB69058B252735F3A864B0C42B7555ADD028DCB937087EE86 +7108667781A85ED8A09260BE52B90B1BB8B6A268169D09AFEFD0C58085ED5550 +58866429B1FFB47465BB91C94DD392DF00A1900E021990C23952430AAC50E079 +5685C686685BB26743FCE9E9ED88D3A523AA10E4317703BF7EA74C15B3ECD49E +33216F52B45B23195E133522498B357511593C41D45660503B93A02FE7DFA71B +51FC7E10E28F60367293388C4D143F49AADD411685A9BF60B6D544E32B8C0902 +8ECA67229D25B79A56639B67A4E40B8A2CEE1B92CEC3121F869520F469BBEA38 +B6E631B249E53EB6A8A886ED97E5C09372B31F724F165A5BEE9385CF89FEFCF9 +F6CD28226E6D60A32A6C2ECFF8E473F816F6CC1A90C1783A3E6303B99B11959B +510B684B9257617EFBE7DB72BAF6F5756B22110B675CE11A2A88148DE330AD84 +C8DBF2C79BB6D2199F42677B85F30C0D6885B0A316B1E53CFB32675179AA088A +45995F1A1D323CF8BDB3E769B851F5BFB6C619CA74CEFE9650F58C96EC512385 +F7A8C8B0CA55F030B7CEB6A7CF577A544744B62424A403A69A4BB6C5EA42375B +DDFD2D1D74FFE633474D4ABA14C24EB7F44BB6E69F759E23FF799E07733E4C7A +F142DD6563A83DB58E7FA1BB7BA82776441875E6B0D44801762E3CA70C8B738A +2B52E48BEC09C29544B6D24513708C7C86AEA3BB56AD0675CBB8CD6E41AD01E4 +DD6F54B5D6CC95AEB2D7D4C1C45D6274DD3FD7449982BDB5609BD3ADB64A73C4 +6F9C5897CFF003130758DB267EB173CF4DBF412C3F69012675FDCA9A8E8D2353 +5C272A4843F249A8CA0E03CB00B503AEB6C1BEC84B87420520EAD65AC7FEF5B9 +0489D803DCCB72AD4F7875335165467D04BDA6CACADBAF5A8BB8B26C153A491D +AFDBD9695BDA29BC2FEEB2849CEE6F4C22FE5C40044105ED2288FE0C96865CF4 +093D21C3A6930538DD2ADBFCDF61072F55156267A7069A0E3025090B2CEB4C7D +9303AC8A31EE3274BAFCF6A1A069D506D4DCE7051C33292C8087DAE14E1D0A9F +40293446B6C01DB83E64E57705AF674684C1BE9527F8B4E242B3CAF61C77E3E4 +AB8EF5BC4CCDEFBBFDA737A7931354DB5AB2A94EBF0EF06E535F03CEC3CA2F2A +568426AFB6B49CB5AB4D5571C9BDA39649E652B44A6A2B140B4E33639ED32A6A +ECDBDCD764AE3428091516C10F4F350A801452AE6BB44D990640AB2A54976F26 +13780C2757C57691D4F47B2538C532F5769ED5CC1BCD4A9285209B7306109F0F +C864E491D5F0FBEE125BF87807951FBA44D152F99FDB9B79A927AD91C423AEF4 +1E7AD1BB32D54808200E350F0F75B2C74574B6A752F3227B2005D768299C755F +07A94926A42A5806B21C44A01983B93B2AF6C916693939A8E917E4CE81A8B007 +9475395D9E2D4696D216AB1D23F022DEFDCF1B31CB06045BA1A7545F921F1088 +B863CD5848A20DEDD289A2D7B05AD6DD68F9FF8F2C4D9145042A1CD985DC1E4E +C2F6C2446DE2E7DD577E3E4378DD6180F79444A7DC8A3FAC02970E2009484816 +1E88FB6188486646B178C7119CA520CCA3503481D895D23D73B5598130AF4FF5 +5E6ECC3EA740B1030BE7CB8343FB90E0FF74D76FE27AE3B799BE36103748518C +6CDB243CE716A0CF5FAC0A5F18E2328EC5190B4B00D14A9D71E135E5A13B7DA2 +476FE03E36B5B56E0B561CA963B25CA77DCEAE2952FA2D1EC8CB7DCCD4DA7A35 +485550BD92A50948436E12DD1FB75003B4B851DC45E41A2461FCD300A2811430 +57EFC3E99C44FB0DD0BAD0B7BA4F97E1B752731C02FAB1CD9038F63A358ED8A2 +5BB20E431A2A41731F167962426AA59FC40F87C820F3990557147A24CB69579D +ED6E60D5EC6FEDEBBECC5BA12B07D4F72C47D306AE8194791D2EAF9A65457ECF +63C187646D3A224B810CE2D1BB39FB02FDC1011C1840CB1632B9850E1C562CD1 +11F9456D74E001D63E3D5FC3E43B7F063089A5647A9021DD30D44E63933A5F1B +607A9BBD0F40DCEC2AEC59D2C408E0BBB369BA8B9893F44A6DC0485EFA64C339 +352CA32A841600C551C528EF69319293CEF00DE4E2481C98FEAED5E3232F316B +564446846604D48232DC65D721F780D0A11154DC5A305366F729782EFFE96B1E +FFF2D987570DB27A22F3322108CF43AD05CF27052FE2B9E964CF01CF5F0B8E19 +6E024C1557959972FC95341E057E1659850B20F565FC0EA76C2ADC7FDEBE4F2E +D4E9001F81BB6A4B8F7351831FF0D5EFB01B298C7E24B2FB493B1BF54875AC38 +8D80014166113412DECE47EFBBE682078A1B5E05A6FB2BB3E93364BDB3DB352F +781773B3E905AB5C5AC04D8111E9AAB5A213CE077435090CFB6DDCB3EC0A4DD2 +F9F946E2EB070E75C0512664014B4E090188526C471DA6F83BBEF74FE52D5597 +063400F44E7016615D743E90F10B54336BEF61F5234B1DF4860A4A4074A96263 +6854BD1E4AF82CB7D7A8DC04E4FB6C34557C9BA80C8743EF343C404228D71DE0 +E5A5A519D3BF01A08A967DCCF44ED06A889FE2107A3DA114E941621D2CB3E8A5 +F4E3DA4B76C3D1BAF6A5CDDBC8513AAFF9F1D22E7DF630EBB82116A075F890F9 +BF73E9777D380CF92C9B1762FA23407E03DD26642FADB9C85944D0E15CA82FDD +5638C26B10B9B94E74DD979BF5A6B6C0AC54C94C6E6716246612627CE4DA4C17 +3AE7772E2B93562AEFB3184A7A9F866FA10901DA58E3BEB70831FC9C1C886EE4 +9DDF0D69B286EB138EE735A382BF96D9B7EC33546F2C788128A3B1ED4CD2AC7D +76C5F3B82DCAFB8AB073256A7F98C1530BE8C94FF9213FDCA56ADC17E6F56552 +87D1313366EE7CCC237857C93401628B7A0F4704720FD4966F16AFA4A764358E +EB0AD53B9C8104070E2D23E9AB793E9F67A2313DC6622213DD8E32FF245C6214 +FC6D5021A48367398061976699FA83F0FE81854D55204CE03258CB6333231FD5 +8852B52D255EFA8F6D6527D7F1C900C991026DDEF6E79B74921BB404D4F1410B +9D2950BA20EF04FC230CA4E8D6E703F63F3A8207BDCC5D1E9BADF8C6D9E2283C +A9D500BEF4E00A29D1005B2D5E80C60EE5B35CB347DA7B7973692F41BA6B4C5B +16E0A6B2B96CAE2BB0AC882FFA9DB50247804437B19B05EC3249A8F6C19D1E58 +4729BBE4925537B69F58ED323A77A860E8ED78D3C4E86C45F8F427EFF375E618 +E4FDBB7CFF3A4E2C9C37EA3004AC75BA08FB2D116455267F37D817AF272C4CF9 +A3DB2C3F683E088B4B743220BEB2106E18D8BD9DBFFC1DB72430AD9F641AD4E1 +5ACE49F9114948A9C8B48055C969711F3EB2B7F725E6441C7A86E1F0C4E53958 +947F12FEE137D5611395B5D4AF05F55BFD8B5D9620580749CC37DD096E7871E3 +B2009A73FE91BC2E23CAC6F815038CBFC911A4B400A30BBE38A7622F51BDA1AF +893065EAC1AE86A73F22A6E282ED1B46B35CA484748BDEE6C056FF6263920E85 +EF4A82D8CB9F9BA7D20B11E928EAE18971183438BBAD0041D3A843F019E23173 +3B13DF0B9D24C86693AAA4CDB5FA11C5BAA449F68AE47DDEFB80E99F59B8E7E8 +0E8A083E0BBAAB211CF82B37B92B2513FAD2E847FDA67C25305610BB86008BF5 +30D2BBC717E071B373EB848AA0E871A0C09C9488F744AE6A46F3BE82106508FC +50C748514FE65F96F52FA865CA60C831A0F4C11E1C500C6C6113EEDC75AD2051 +67E4DB9A5B1555F9614B6C0C3D1B12DB6194BE578E985E53679C66AAEDD60C68 +0E3AC42E06CC5AEF1167DB0002D79973AAFAE17B083ACD5CF95F661054525867 +FEE6E96EBB0FB243371CDB940534214E9C6EB160A18EAD2ADBFBA1CDC709845D +FE9DF2ABB313BD9809DC40FE278A7FAA6C61B7E3DBF96EEE2C7F17F20581362C +E9EEE3D4E7B3057509F5498AFF226AC267CDD6EFBE12F4573301D4535D0C2AAC +C82FDD61E39357478A30431CFC9040FE2BFE4509DA82C54241307E5EB39BB22C +D604C6091038278EB66053EDAAF62DFBA92946772C64A12D814D907563C30D50 +5924AD6C0F10DD0F721B91AE8B9654FB5B86375DA94D595AD1999CD46C94E3E1 +F1DBADA3287C010DBCC163FC68D3584E1067ECD33CBF6C231E27B27BF89548F1 +71DE0EDBD2AC2AAEF09A56461F30C2286BF98A49AEE50B9DE275D8D04CAAE61D +3BC5688432C09BBF7673D72D308172D9F04101966E9231A2A19C92DAA8BD21DC +B88284250523E122A154CC8072271F53EE8F4EE562AD06C10D0F5BF0C635DE44 +D198EB6B947B7DC15465F08C5CA3466339B6FA18F7B95708A9BCF8AB81D1F9C5 +570EDF54B50D657A89415719D03B15D582DD66D5FBF26449E4D26DC46ED4F454 +9081D0DB9B054D69874E868E3810D1696D5E381AA4D788154E21B0D28CF90CB7 +AE0BE0D6F5E62A82BEE840DB125672C93BBCC46632765684444E0FE4B2BEC283 +D5075E0E5A34D26250B128F5AB178D11BE1BA8E561276BF49FA3B58C02BF5DB5 +0A505D1F8815F6C7BB7F4774A97B114E89F222A08E5EB8676A320728CD2826C0 +EA8816874C355C40D0AED9D1CFFACB1501C592678E3C111D94E3F7189CE094AD +B9DFDBB44AA289349CFD2A9993BDDF072B7A3EDAE60531C593453575D9742CED +FF2ECF2B12CD59CA4FD7952462303F6081D0232084DA9DB8A4693FD2D3AAFE7D +A2A61015F67FF76683FA6EC38B25198EED132AC393394129BCF0AF0E6F048A09 +E5E5D074B2B1C49F9B86DFDD559F243F270A6190816D4E86A11E1BECE43C0E7A +1BB7E691DC79DB786617EE61B907E4A8DD71BF94B4F032229CB18E1A4A803B38 +D9943851ACA9B591416E20975B8EB628BF751CFC42F929AF5D04813EF388DA71 +B23B0AFA8BE1A9B36A19681DD00FEEA84AA6D65CBD7990877D1A4119051B81F3 +6350A67EF0DFB24F5890D539B63EA6DE95C5583A8320B3924934F9A68C1BF5D3 +6FD4FB3EB40AEAE4B3E85A382AF9735FE1AAE7FC6B66FCB1E33D04E7A89F35E4 +5D855A455541209543EE482D0ABAAF77D76E4F2278AD4A59EBEB2C921E83C28E +38F7BDA6500188BCC8E7B4BDE917FD343B5DC6E74994D8A9332EA7622335BF9D +2CB069AFBAA4E01ECDC4D5DB0B34337A12B6168DD40FAF8801A17BF219A63938 +4779A96B9A7F1E670531956F374C727DD893CDD06C3EBBC48AA8C7FCE062C19E +6DFF6F14DCB27EE097771E83AC8CCA0BB363FC98ED29DDA10459E5AAD3BC1415 +651C347A04466E35C1B3744ADC671C461120D2359C4DBFD0D243555D9B182CFD +189022DED77374687BA5758C88FC19E3A6149E526E11E87A9CAD9B19CB47E00D +70CB4E4B0172AA46DDF138EF9A4A94D7B59252D9E8E170CDB048BB7CA28F4538 +CC3A0B72913DD82E327A3A62E7EE1E950976E5228BAADEA7A1C761175556FA84 +FAFAFA55C9A9A5F9F2340FDB199105E4CCA0CF364099EB3227BC0A8AA7189DFE +3CEF5E1B68EBFFA7D8E603A3414CBC37D5E5A1261F66E5B739D6BA2F52877435 +FEB61C789D6CC48482A28679707F9C8E0073B75072B9E10AE09FAA28184A8C00 +66FE6FECC229635097E1E5A8DDF889AC85F6AA555C433A0C7E7A73D2F683D887 +45225F82587B6EDC9F24A18C24699ED304E05F7B0A5C5F20A6DB61EC2F8EE502 +814CBB41B0481B3BBAC69AA4B4F6A251B41B5ECD0F04E9C256813DAF5374D9D1 +8A5057894B93A1F5A9BBC56E63EC2B11B09818D20E984D37943047E7F010FA87 +74E4918D3E56679FF00FDC1D94B0C52206B4D570FA3CAC26FCF17FE89D73DA9E +7AAFE36245EDD811F91D9E83C96704CFE68A29778677A6C02820EF9B09D471F6 +D03191013A6334CDA003270C92CE05DE4B6194BACBFE4CBB80FF15D9A31A4DF9 +82BC8BFCFCA725B26874D1B26456F6FE83216F677210469963DC5683DB7BBFAC +ED2DE1ACAC4AB4E24195E19C447EB4744E5026326EEC560DEF375749AEE07A4E +78C8FAFB5056731503FBC10F47FB37D49F3855582FDB5F8D1B204AEE50D11458 +CF253A7D990A84F4C89295C72AF21FCEDCA1C0CEAAED6B1DE83FD59573A2A566 +16C90BE27AF719832E6E5A98E9BE7DC65108AD80F40B52EFCEC672D1D94E299E +8EC5DAE81EF454BDE9184A00F5F8BB51BF564603214B23D41C026BD751308706 +3BD8678F5794641193D38F99EFC088E5C9B5639374951D050D19CB54BDA58EAF +636DD6C8B5664EC1529C2E964DB260652DB183CE0887450F1AEDA8D9575C5B32 +EBCB5F71C9C1DBD6341AD5AC442220026A32805085E0BFCAC682C09483AF5CD9 +47ABE381D20A2F905E533D297BDF5AF066A7925DE0223321DAC4C282C79E1856 +3090310656A17D312F7BB259742B7549A27DB6CEDD2803794642BA7C78EC96DD +A8DD2E13E16E81512FF2AD34F123EAC904FE853780C2400234D36FB8ABB07319 +0D46D294513300E318D23766FAB236ECFE7A93705FBC960341AA7E2163DC9D81 +5E2A578EB0FDD05E41885E6A5D88A946025B27767CF4F495A787592F0235D22D +9923308AADB018D6ED705F29B38EAEB3473BC53BB341DDA4C1D62F5CAD1C22AF +192338BAD441B3B7616D78B717920C005EBBC853612A0A7E41426DD96194BC2C +3ECD5784183D76AADF3EDE1828165A3A5B8D864CA7DF794C80C40E766C3A6410 +20DAC3B63B9BC698487D7E1AAC34F10E0799636C45AC6AA60B4CCBF9979D67B0 +F2EBF45561323648A125BDFD4E34B23E9C63CEEF8723A50D35C9DA31F829113B +B3F4E2C999B1A31865E09A9279B006ECDB6613894A2509C19D6AE205BD7E9315 +0D973B8E82227C6499A9FFF9AF0F5282812EA44B1BCED229D17590713A2DA5AD +30C6C6BDD8D321B17CAC678FE0ED8951B6CFE4AE7FB2FE96594A5086DD767696 +CA6DE0CC91DE3A68CE8EDEDE33E4B49E5E0E3B6AD558E7585BD5A1AE4F1D16C3 +202F267953CD390FF26200E172CB890782E0C43B51C95C55EFA95DA98CF4CA5A +B189838F3832ADF48D8AEB00909D5C07587B26F63BA03A13B0345E9B99E7B1D0 +47427A74353825472C5AB49DD95A90D253CEB066C49D6A4356E072DF5BBF394F +3FA04F54C4A822DFC7FF45AA337B9006BA63DF5D6AFCC7870B2D1AB4A954DB76 +C5B93562408402578D610DD64A09ED30D71D9341F1CFB44922F42DCDACFEE2FE +B8E0EA576DC60840FC3269FF313FEBC57C5D958016C859D2D80BB270E6E93738 +D314BFD28BDACD48697001CF13E9B29D1D1C5785ECF6040F43DA204FD29A924C +E32C8A2AA8ED8BA00C16D46A4EED8CCE9AF13393E8FB6F5FFFEC3A421105F8AD +FF596DA77FAC7567745BFCAAEDE63F080F24AC62A05DD8934D616D1B6A336AE9 +B1ACE43ACBB79549204AC02B7F4ADA2B29E8B081EE02152C7778954F9F61FB67 +6014CF4FFAA5A446334847DBFD348DF16BFFA90B0A8D5E76721E62CC46903CE4 +4C076460459EE651504D119F10D5D046FBF7BCAA97E7D0CCD822A6D442B9BC8B +9EA43A5BC643998A7FE6C97C967B3AEF0019270BEB8EAB12F396CB363D43F70D +7AA971F68B33F1158663FA39DD34934884F5DE842F 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 @@ -2307,8 +2313,8 @@ @start /Fa 242[61 13[{ TeXbbad153fEncoding ReEncodeFont }1 49.8132 /CMSY6 rf /Fb 134[32 1[43 32 34 24 24 24 1[34 30 34 50 18 32 1[18 34 30 19 27 34 27 34 30 13[34 44 -1[41 47 1[54 3[22 1[47 39 2[43 1[45 6[18 3[30 1[30 1[30 -1[30 1[18 21 18 44[{ TeXf7b6d320Encoding ReEncodeFont }40 +1[41 47 1[54 3[22 1[47 39 2[43 1[45 6[18 3[30 1[30 30 +30 1[30 1[18 21 18 44[{ TeXf7b6d320Encoding ReEncodeFont }41 49.8132 /CMR6 rf /Fc 135[33 3[24 29 4[40 58 18 2[22 36 2[33 36 33 33 36 50[22 46[{ TeX74afc74cEncoding ReEncodeFont }14 66.4176 /CMTI8 rf /Fd 134[43 43 59 43 45 32 32 34 1[45 @@ -2347,7 +2353,7 @@ %%Page: 1 1 TeXDict begin @landscape 1 0 bop -169 -357 a Fj(Org-Mo)t(de)45 b(Reference)h(Card)g(\(1/2\))546 -242 y Fi(\(for)23 b(v)n(ersion)h -(4.02\))-150 -39 y Fh(Getting)37 b(Started)-150 89 y +(4.03\))-150 -39 y Fh(Getting)37 b(Started)-150 89 y Fg(\(add-to-list)i('auto-mode-alist)h('\("\\\\.org$")e(.)e (org-mode\)\))-150 172 y(\(define-key)i(global-map)h("\\C-cl")e ('org-store-link\))1504 148 y Ff(2)-150 254 y Fg(\(define-key)h @@ -2560,70 +2566,68 @@ %%Page: 2 2 TeXDict begin @landscape 2 1 bop -169 -357 a Fj(Org-Mo)t(de)45 b(Reference)h(Card)g(\(2/2\))546 -242 y Fi(\(for)23 b(v)n(ersion)h -(4.02\))-150 -45 y Fh(Agenda)37 b(Views)-150 102 y Fi(add/mo)n(v)n(e)25 +(4.03\))-150 -36 y Fh(Agenda)37 b(Views)-150 120 y Fi(add/mo)n(v)n(e)25 b(curren)n(t)f(\014le)g(to)g(fron)n(t)g(of)f(agenda)197 -b Fg(C-c)36 b([)-150 172 y Fi(remo)n(v)n(e)24 b(curren)n(t)g(\014le)g -(from)f(y)n(our)g(agenda)299 b Fg(C-c)36 b(])-150 242 +b Fg(C-c)36 b([)-150 190 y Fi(remo)n(v)n(e)24 b(curren)n(t)g(\014le)g +(from)f(y)n(our)g(agenda)299 b Fg(C-c)36 b(])-150 259 y Fi(cycle)24 b(through)h(agenda)g(\014le)f(list)551 -b Fg(C-,)-150 349 y Fi(compile)24 b(agenda)h(for)e(the)h(curren)n(t)g -(w)n(eek)320 b Fg(C-c)36 b(a)g(a)1537 325 y Ff(2)-150 -429 y Fi(compile)24 b(global)g(TODO)f(list)640 b Fg(C-c)36 -b(a)g(t)1537 406 y Ff(2)-150 510 y Fi(compile)24 b(TODO)f(list)g(for)g +b Fg(C-,)-150 368 y Fi(compile)24 b(agenda)h(for)e(the)h(curren)n(t)g +(w)n(eek)320 b Fg(C-c)36 b(a)g(a)1537 345 y Ff(2)-150 +449 y Fi(compile)24 b(global)g(TODO)f(list)640 b Fg(C-c)36 +b(a)g(t)1537 425 y Ff(2)-150 529 y Fi(compile)24 b(TODO)f(list)g(for)g (sp)r(eci\014c)h(k)n(eyw)n(ord)218 b Fg(C-c)36 b(a)g(T)1537 -486 y Ff(2)-150 590 y Fi(matc)n(h)25 b(tags)f(in)f(agenda)j(\014les)637 -b Fg(C-c)36 b(a)g(m)1537 567 y Ff(2)-150 660 y Fi(agenda)25 +506 y Ff(2)-150 610 y Fi(matc)n(h)25 b(tags)f(in)f(agenda)j(\014les)637 +b Fg(C-c)36 b(a)g(m)1537 586 y Ff(2)-150 680 y Fi(agenda)25 b(for)e(date)i(at)f(cursor)661 b Fg(C-c)36 b(C-o)-150 -730 y Fi(sho)n(w)24 b(timeline)f(of)h(curren)n(t)g(org)f(\014le)458 -b Fg(C-c)36 b(C-r)-150 860 y Fi(T)-6 b(o)24 b(set)g(categories,)h(add)f -(lines)f(lik)n(e)814 837 y Ff(3)851 860 y Fi(:)-150 933 -y Fg(#+CATEGORY:)38 b(MyCateg)-150 1030 y Fd(Commands)26 +749 y Fi(sho)n(w)24 b(timeline)f(of)h(curren)n(t)g(org)f(\014le)458 +b Fg(C-c)36 b(C-r)-150 882 y Fi(T)-6 b(o)24 b(set)g(categories,)h(add)f +(lines)f(lik)n(e)814 859 y Ff(3)851 882 y Fi(:)-150 957 +y Fg(#+CATEGORY:)38 b(MyCateg)-150 1055 y Fd(Commands)26 b(a)n(v)-5 b(ailable)25 b(in)i(an)g(agenda)g(bu\013er)-150 -1126 y(View)g(Org)g(\014le)-150 1222 y Fi(sho)n(w)d(original)f(lo)r -(cation)h(of)g(item)524 b Fg(SPC)-150 1292 y Fi(...)30 +1153 y(View)g(Org)g(\014le)-150 1252 y Fi(sho)n(w)d(original)f(lo)r +(cation)h(of)g(item)524 b Fg(SPC)-150 1321 y Fi(...)30 b(also)24 b(a)n(v)l(ailable)g(with)781 b Fg(mouse-3)-150 -1362 y Fi(sho)n(w)24 b(and)g(recen)n(ter)h(windo)n(w)626 -b Fg(L)-150 1431 y Fi(goto)25 b(original)e(lo)r(cation)h(in)g(other)g -(windo)n(w)260 b Fg(TAB)-150 1501 y Fi(...)30 b(also)24 -b(a)n(v)l(ailable)g(with)781 b Fg(mouse-2)-150 1571 y +1391 y Fi(sho)n(w)24 b(and)g(recen)n(ter)h(windo)n(w)626 +b Fg(L)-150 1461 y Fi(goto)25 b(original)e(lo)r(cation)h(in)g(other)g +(windo)n(w)260 b Fg(TAB)-150 1531 y Fi(...)30 b(also)24 +b(a)n(v)l(ailable)g(with)781 b Fg(mouse-2)-150 1600 y Fi(goto)25 b(original)e(lo)r(cation,)h(delete)h(other)f(windo)n(ws)91 -b Fg(RET)-150 1641 y Fi(toggle)25 b(follo)n(w-mo)r(de)861 -b Fg(f)-150 1737 y Fd(Change)27 b(displa)n(y)-150 1833 -y Fi(delete)e(other)f(windo)n(ws)791 b Fg(o)-150 1903 +b Fg(RET)-150 1670 y Fi(toggle)25 b(follo)n(w-mo)r(de)861 +b Fg(f)-150 1768 y Fd(Change)27 b(displa)n(y)-150 1867 +y Fi(delete)e(other)f(windo)n(ws)791 b Fg(o)-150 1937 y Fi(switc)n(h)24 b(to)g(daily)g(/)g(w)n(eekly)g(view)534 -b Fg(d)36 b(/)f(w)-150 1973 y Fi(toggle)25 b(inclusion)e(of)h(diary)f -(en)n(tries)473 b Fg(D)-150 2043 y Fi(toggle)25 b(time)f(grid)f(for)g -(daily)g(sc)n(hedule)388 b Fg(g)-150 2112 y Fi(toggle)25 +b Fg(d)36 b(/)f(w)-150 2006 y Fi(toggle)25 b(inclusion)e(of)h(diary)f +(en)n(tries)473 b Fg(D)-150 2076 y Fi(toggle)25 b(time)f(grid)f(for)g +(daily)g(sc)n(hedule)388 b Fg(g)-150 2146 y Fi(toggle)25 b(displa)n(y)e(of)h(logb)r(o)r(ok)g(en)n(tries)446 b -Fg(l)-150 2182 y Fi(refresh)23 b(agenda)i(bu\013er)f(with)g(an)n(y)g(c) -n(hanges)239 b Fg(r)-150 2252 y Fi(displa)n(y)24 b(the)g(follo)n(wing)f -Fg(org-agenda-ndays)221 b(RIGHT)-150 2322 y Fi(displa)n(y)24 +Fg(l)-150 2215 y Fi(refresh)23 b(agenda)i(bu\013er)f(with)g(an)n(y)g(c) +n(hanges)239 b Fg(r)-150 2285 y Fi(displa)n(y)24 b(the)g(follo)n(wing)f +Fg(org-agenda-ndays)221 b(RIGHT)-150 2355 y Fi(displa)n(y)24 b(the)g(previous)g Fg(org-agenda-ndays)238 b(LEFT)-150 -2391 y Fi(goto)25 b(to)r(da)n(y)1110 b Fg(.)-150 2488 -y Fd(Remote)27 b(editing)-150 2584 y Fi(digit)d(argumen)n(t)984 -b Fg(0-9)-150 2654 y Fi(c)n(hange)25 b(state)g(of)f(curren)n(t)g(TODO)f -(item)333 b Fg(t)-150 2724 y Fi(set)24 b(tags)h(for)d(curren)n(t)j -(headline)573 b Fg(:)-150 2793 y Fi(set)24 b(priorit)n(y)f(of)g(curren) -n(t)i(item)612 b Fg(p)-150 2876 y Fi(raise)23 b(priorit)n(y)g(of)g -(curren)n(t)i(item)557 b Fg(S-UP)1430 2852 y Ff(4)-150 -2956 y Fi(lo)n(w)n(er)23 b(priorit)n(y)g(of)h(curren)n(t)g(item)538 -b Fg(S-DOWN)1500 2933 y Ff(4)-150 3026 y Fi(displa)n(y)24 -b(w)n(eigh)n(ted)h(priorit)n(y)e(of)g(curren)n(t)h(item)189 -b Fg(P)-150 3106 y Fi(c)n(hange)25 b(timestamp)g(to)f(one)g(da)n(y)h -(earlier)315 b Fg(S-LEFT)1500 3083 y Ff(4)-150 3187 y -Fi(c)n(hange)25 b(timestamp)g(to)f(one)g(da)n(y)h(later)367 -b Fg(S-RIGHT)1535 3163 y Ff(4)-150 3256 y Fi(c)n(hange)25 -b(timestamp)g(to)f(to)r(da)n(y)598 b Fg(>)-150 3326 y +2425 y Fi(goto)25 b(to)r(da)n(y)1110 b Fg(.)-150 2523 +y Fd(Remote)27 b(editing)-150 2621 y Fi(digit)d(argumen)n(t)984 +b Fg(0-9)-150 2691 y Fi(c)n(hange)25 b(state)g(of)f(curren)n(t)g(TODO)f +(item)333 b Fg(t)-150 2761 y Fi(sho)n(w)24 b(tags)g(of)g(curren)n(t)g +(headline)536 b Fg(T)-150 2831 y Fi(set)24 b(tags)h(for)d(curren)n(t)j +(headline)573 b Fg(:)-150 2900 y Fi(set)24 b(priorit)n(y)f(of)g(curren) +n(t)i(item)612 b Fg(p)-150 2983 y Fi(raise/lo)n(w)n(er)23 +b(priorit)n(y)g(of)h(curren)n(t)g(item)361 b Fg(S-UP/DOWN)1605 +2959 y Ff(4)-150 3052 y Fi(displa)n(y)24 b(w)n(eigh)n(ted)h(priorit)n +(y)e(of)g(curren)n(t)h(item)189 b Fg(P)-150 3133 y Fi(c)n(hange)25 +b(timestamp)g(to)f(one)g(da)n(y)h(earlier/later)139 b +Fg(S-LEFT/RIGHT)1710 3109 y Ff(4)-150 3203 y Fi(c)n(hange)25 +b(timestamp)g(to)f(to)r(da)n(y)598 b Fg(>)-150 3272 y Fi(insert)23 b(new)i(en)n(try)f(in)n(to)g(diary)612 b -Fg(i)-150 3423 y Fd(Calendar)26 b(commands)-150 3519 +Fg(i)-150 3371 y Fd(Calendar)26 b(commands)-150 3469 y Fi(\014nd)e(agenda)h(cursor)f(date)g(in)g(calendar)350 -b Fg(c)-150 3589 y Fi(compute)25 b(agenda)g(for)e(calendar)i(cursor)e -(date)180 b Fg(c)-150 3658 y Fi(sho)n(w)24 b(phases)g(of)f(the)i(mo)r -(on)669 b Fg(M)-150 3728 y Fi(sho)n(w)24 b(sunrise/sunset)g(times)636 -b Fg(S)-150 3798 y Fi(sho)n(w)24 b(holida)n(ys)1014 b -Fg(H)-150 3868 y Fi(con)n(v)n(ert)25 b(date)g(to)f(other)g(calendars) -478 b Fg(C)-150 3964 y Fd(Quit)27 b(and)g(Exit)-150 4060 +b Fg(c)-150 3539 y Fi(compute)25 b(agenda)g(for)e(calendar)i(cursor)e +(date)180 b Fg(c)-150 3608 y Fi(sho)n(w)24 b(phases)g(of)f(the)i(mo)r +(on)669 b Fg(M)-150 3678 y Fi(sho)n(w)24 b(sunrise/sunset)g(times)636 +b Fg(S)-150 3748 y Fi(sho)n(w)24 b(holida)n(ys)1014 b +Fg(H)-150 3818 y Fi(con)n(v)n(ert)25 b(date)g(to)f(other)g(calendars) +478 b Fg(C)-150 3916 y Fd(Quit)27 b(and)g(Exit)-150 4014 y Fi(quit)d(agenda,)h(remo)n(v)n(e)f(agenda)h(bu\013er)376 -b Fg(q)-150 4130 y Fi(exit)24 b(agenda,)h(remo)n(v)n(e)f(all)f(agenda)i +b Fg(q)-150 4084 y Fi(exit)24 b(agenda,)h(remo)n(v)n(e)f(all)f(agenda)i (bu\013ers)258 b Fg(x)2046 -364 y Fh(Exp)s(orting)2046 -229 y Fi(Exp)r(orting)32 b(creates)g(\014les)g(with)f(extensions)i Fc(.txt)k Fi(and)32 b Fc(.html)38 b Fi(in)31 b(the)2046 @@ -2757,7 +2761,7 @@ Fg(org-CUA-compatibility)p Fi(.)4535 3770 y Fb(Cop)n(yrigh)n(t)4838 3768 y(c)4821 3770 y Fa(\015)d Fb(2006)i(F)-5 b(ree)21 b(Soft)n(w)n(are)i(F)-5 b(oundation,)20 b(Inc.)4795 3826 -y(v4.02)h(for)h(Org-Mo)r(de)e(4.02,)i(2006)4912 3882 +y(v4.03)h(for)h(Org-Mo)r(de)e(4.03,)i(2006)4912 3882 y(Author:)k(Philip)18 b(Ro)r(ok)n(e)4473 3937 y(based)j(on)g(refcard)g (design)g(and)f(format)i(b)n(y)f(Stephen)f(Gildea)4242 4022 y(P)n(ermission)28 b(is)f(gran)n(ted)i(to)f(mak)n(e)h(and)e diff -r 8438f5473d99 -r de425e4eb0bc etc/orgcard.tex --- a/etc/orgcard.tex Thu Jan 12 11:20:02 2006 +0000 +++ b/etc/orgcard.tex Tue Jan 17 00:56:42 2006 +0000 @@ -1,4 +1,4 @@ -% Reference Card for Org Mode 4.02 +% Reference Card for Org Mode 4.03 % %**start of header \newcount\columnsperpage @@ -58,7 +58,7 @@ % Thanks to Paul Rubin, Bob Chassell, Len Tower, and Richard Mlynarik % for their many good ideas. -\def\orgversionnumber{4.02} +\def\orgversionnumber{4.03} \def\year{2006} \def\shortcopyrightnotice{\vskip 1ex plus 2 fill @@ -570,13 +570,15 @@ \key{digit argument}{0-9} \key{change state of current TODO item}{t} +\key{show tags of current headline}{T} \key{set tags for current headline}{:} \key{set priority of current item}{p} -\key{raise priority of current item}{S-UP$^4$} -\key{lower priority of current item}{S-DOWN$^4$} +\key{raise/lower priority of current item}{S-UP/DOWN$^4$} +%\key{lower priority of current item}{S-DOWN$^4$} \key{display weighted priority of current item}{P} -\key{change timestamp to one day earlier}{S-LEFT$^4$} -\key{change timestamp to one day later}{S-RIGHT$^4$} +\key{change timestamp to one day earlier/later}{S-LEFT/RIGHT$^4$} +%\key{change timestamp to one day earlier}{S-LEFT$^4$} +%\key{change timestamp to one day later}{S-RIGHT$^4$} \key{change timestamp to today}{>} \key{insert new entry into diary}{i} diff -r 8438f5473d99 -r de425e4eb0bc lisp/ChangeLog --- a/lisp/ChangeLog Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/ChangeLog Tue Jan 17 00:56:42 2006 +0000 @@ -1,3 +1,171 @@ +2006-01-15 Dan Nicolaescu + + * term.el (term-raw-map): Add mapping for insert. + (term-send-insert): New. + (term-mode): Make variables local here instead of doing it in + `term-emulate-terminal'. + (term-emulate-terminal): Delete incorrect optimization for cr+lf. + Scroll reverse needs to take into account the scroll + region. Saving and restoring the cursor should save the color + attributes too. + (term-reset-terminal): Reset the scroll region. + (term-handle-ansi-escape): Cursor up and down should take into + account the scroll region. + (term-set-scroll-region): Renamed from `term-scroll-region'. Move + to 0,0 after setting the region. + (term-handle-scroll): Handle scroll up. + (term-down): Fix off by one error. + (term-delete-lines): Do not delete outside the scroll region. + (term-insert-lines): Take into account the scroll region. + +2006-01-15 Stefan Monnier + + * textmodes/ispell.el (ispell-internal-change-dictionary) + (ispell-change-dictionary): Undo most of last change of 2006-01-13. + (start, end): Move declaration outside of eval-when-compile. + + * textmodes/flyspell.el (flyspell-kill-ispell-hook): New fun. + (flyspell-mode-on): Use it. + + * textmodes/ispell.el (ispell-kill-ispell): Run new hook + ispell-kill-ispell-hook. + +2006-01-14 Luc Teirlinck + + * cus-edit.el (Custom-set, Custom-save, Custom-reset-current) + (Custom-reset-saved): Do not ask for confirmation in single option + buffers. + +2006-01-13 Romain Francoise + + * add-log.el (add-change-log-entry, change-log-merge): + Conditionally use `hard-newline'. + +2006-01-13 Martin Rudalics (tiny change) + + * wid-edit.el (widget-field-end): If the overlay is no longer + associated with a buffer, behave as if the overlay didn't exist. + + * cus-edit.el (custom-add-see-also, custom-add-parent-links): + Make sure the links use the `custom-link' face. + +2006-01-13 Stefan Monnier + + * progmodes/ld-script.el (auto-mode-alist): Use \' rather than $. + (ld-script-mode): Don't set indent-line-function since we don't + have one. + +2006-01-13 Carsten Dominik + + * textmodes/org.el: (org-open-file): Use mailcap for selecting an + application. + (org-file-apps-defaults-gnu): Use mailcap as the default for + selecting an application on a UNIX system. + (org-agenda-show-tags): New command. + (org-table-insert-hline): Keep cursor in current table line. + (org-table-convert): Offset effect of modifying + `org-table-insert-hline'. + (org-format-agenda-item): New optional argument TAG. + (org-compile-prefix-format): Handle %T format for the tag. + (org-expand-wide-chars): New function. + (org-table-insert-row, org-table-insert-hline): + Use `org-expand-wide-chars'. + (org-open-file): Fix bug in program launch. + (org-get-time-of-day): Fix bug with times before 1am. + (org-agenda-menu): Addes tags commands. + +2006-01-13 Agustin Martin + + * textmodes/ispell.el (ispell-init-process): Include the used + dictionary in ispell process start message. + (ispell-internal-change-dictionary): When flyspell-mode is active + and dictionary is changed, make sure ispell process is restarted + and flyspell word cache cleared out for the current buffer. + (ispell-change-dictionary): Make sure flyspell word cache is + cleared out in all buffers with active flyspell mode when + dictionary is globally changed. + Call ispell-internal-change-dictionary after dictionary change. + +2006-01-13 Eli Zaretskii + + * emacs-lisp/bytecomp.el (batch-byte-recompile-directory): Doc fix. + + * makefile.w32-in (MH_E_SRC): Synchronize with Makefile.in. + (pre-mh-loaddefs.el-SH, pre-mh-loaddefs.el-CMD): Update Copyright + years. Fix small differences wrt Makefile.in. + (recompile): Use --eval '(batch-byte-recompile-directory 0)', like + Makefile.in does. + +2006-01-12 Bill Wohler + + * Makefile.in (MH_E_SRC): Replace mh-index.el and mh-pick.el with + mh-search.el. + +2006-01-12 Masatake YAMATO + + * progmodes/ld-script.el: Update copyright year. + +2006-01-12 Chong Yidong + + * cus-theme.el (custom-theme-add-variable, custom-theme-add-face): + Don't add widget if setting undefined. + +2006-01-12 John Paul Wallington + + * help-fns.el (describe-variable): Remove newlines from void + variable output. + +2006-01-13 Nick Roberts + + * wdired.el (wdired-mode-map): Add help echo for + wdired-abort-changes. + + * man.el (Man-file-name-regexp): Adjust for a list of files. + +2006-01-12 Masatake YAMATO + + * progmodes/ld-script.el (auto-mode-alist): Support + suffix conventions used in netbsd and eCos. + +2006-01-11 Luc Teirlinck + + * cus-edit.el (custom-reset-menu, custom-buffer-create-internal) + (custom-variable-menu, custom-face-menu, custom-group-menu) + (Custom-mode-menu): Change names of menu items. (As discussed on + emacs-devel.) + (custom-face-menu): Add "Undo Edits" item. + + * startup.el (init-file-user): defcustom -> defvar. + + * tooltip.el (tooltip-mode): Doc fix. + +2006-01-11 Stefan Monnier + + * reveal.el (reveal-post-command): window-buffer signals an error on + dead windows rather than returning nil. + (reveal-open-new-overlays): An overlay might die while we open others. + +2006-01-11 Bill Wohler + + * cus-dep.el (generated-custom-dependencies-file): Fix typo and + phrasing in docstring. + + * Makefile.in (MH_E_SRC): Rename from MH-E-SRC since the dashes + can give some systems gas. Add new file mh-buffers.el. + +2006-01-06 Masatake YAMATO + + * font-lock.el (cpp-font-lock-keywords): Font lock keywords for + C preprocessor forward ported from GNU Emacs 21.2. + + * progmodes/asm-mode.el (asm-font-lock-keywords): + Use `cpp-font-lock-keywords'. + + * progmodes/ld-script.el (ld-script-font-lock-keywords): Ditto. + + * progmodes/ld-script.el (auto-mode-alist): Use \\> instead + of $ for "\\.ld[s]?". + 2006-01-10 Stefan Monnier * progmodes/tcl.el (tcl-indent-command): Use indent-for-tab-command. diff -r 8438f5473d99 -r de425e4eb0bc lisp/Makefile.in --- a/lisp/Makefile.in Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/Makefile.in Tue Jan 17 00:56:42 2006 +0000 @@ -220,21 +220,21 @@ # Update MH-E internal autoloads. These are not to be confused with # the autoloads for the MH-E entry points, which are already in # loaddefs.el. -MH-E-SRC = $(lisp)/mh-e/mh-acros.el $(lisp)/mh-e/mh-alias.el \ - $(lisp)/mh-e/mh-comp.el $(lisp)/mh-e/mh-customize.el \ - $(lisp)/mh-e/mh-e.el $(lisp)/mh-e/mh-funcs.el \ - $(lisp)/mh-e/mh-mime.el $(lisp)/mh-e/mh-pick.el \ - $(lisp)/mh-e/mh-print.el $(lisp)/mh-e/mh-inc.el \ - $(lisp)/mh-e/mh-init.el $(lisp)/mh-e/mh-index.el \ - $(lisp)/mh-e/mh-identity.el $(lisp)/mh-e/mh-junk.el \ +MH_E_SRC = $(lisp)/mh-e/mh-acros.el $(lisp)/mh-e/mh-alias.el \ + $(lisp)/mh-e/mh-buffers.el $(lisp)/mh-e/mh-comp.el \ + $(lisp)/mh-e/mh-customize.el $(lisp)/mh-e/mh-e.el \ + $(lisp)/mh-e/mh-funcs.el $(lisp)/mh-e/mh-identity.el \ + $(lisp)/mh-e/mh-inc.el $(lisp)/mh-e/mh-init.el \ + $(lisp)/mh-e/mh-junk.el $(lisp)/mh-e/mh-mime.el \ + $(lisp)/mh-e/mh-print.el $(lisp)/mh-e/mh-search.el \ $(lisp)/mh-e/mh-seq.el $(lisp)/mh-e/mh-speed.el \ $(lisp)/mh-e/mh-utils.el mh-autoloads: $(lisp)/mh-e/mh-loaddefs.el -$(lisp)/mh-e/mh-loaddefs.el: $(MH-E-SRC) +$(lisp)/mh-e/mh-loaddefs.el: $(MH_E_SRC) echo ";;; mh-loaddefs.el --- automatically extracted autoloads" > $@ echo ";;" >> $@ - echo ";; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc." >> $@ + echo ";; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc." >> $@ echo ";; Author: Bill Wohler " >> $@ echo ";; Keywords: mail" >> $@ echo ";;; Commentary:" >> $@ diff -r 8438f5473d99 -r de425e4eb0bc lisp/add-log.el --- a/lisp/add-log.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/add-log.el Tue Jan 17 00:56:42 2006 +0000 @@ -1,7 +1,7 @@ ;;; add-log.el --- change log maintenance commands for Emacs ;; Copyright (C) 1985, 1986, 1988, 1993, 1994, 1997, 1998, 2000, 2002, -;; 2003, 2004, 2005 Free Software Foundation, Inc. +;; 2003, 2004, 2005, 2006 Free Software Foundation, Inc. ;; Maintainer: FSF ;; Keywords: tools @@ -551,7 +551,8 @@ (forward-line 1) (insert (nth (random (length new-entries)) new-entries) - hard-newline hard-newline) + (if use-hard-newlines hard-newline "\n") + (if use-hard-newlines hard-newline "\n")) (forward-line -1))) ;; Determine where we should stop searching for a usable @@ -584,7 +585,8 @@ ;; Delete excess empty lines; make just 2. (while (and (not (eobp)) (looking-at "^\\s *$")) (delete-region (point) (line-beginning-position 2))) - (insert hard-newline hard-newline) + (insert (if use-hard-newlines hard-newline "\n") + (if use-hard-newlines hard-newline "\n")) (forward-line -2) (indent-relative-maybe)) (t @@ -593,7 +595,9 @@ (forward-line 1)) (while (and (not (eobp)) (looking-at "^\\s *$")) (delete-region (point) (line-beginning-position 2))) - (insert hard-newline hard-newline hard-newline) + (insert (if use-hard-newlines hard-newline "\n") + (if use-hard-newlines hard-newline "\n") + (if use-hard-newlines hard-newline "\n")) (forward-line -2) (indent-to left-margin) (insert "* ") @@ -1066,7 +1070,7 @@ (and (= ?\n (char-before)) (or (<= (1- (point)) (point-min)) (= ?\n (char-before (1- (point))))))) - (insert hard-newline)) + (insert (if use-hard-newlines hard-newline "\n"))) ;; Move to the end of it to terminate outer loop. (with-current-buffer other-buf (goto-char (point-max))) diff -r 8438f5473d99 -r de425e4eb0bc lisp/cus-dep.el --- a/lisp/cus-dep.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/cus-dep.el Tue Jan 17 00:56:42 2006 +0000 @@ -1,6 +1,7 @@ ;;; cus-dep.el --- find customization dependencies ;; -;; Copyright (C) 1997, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 1997, 2002, 2003, 2004, 2005, +;; 2006 Free Software Foundation, Inc. ;; ;; Author: Per Abrahamsen ;; Keywords: internal @@ -31,7 +32,7 @@ (require 'cus-face) (defvar generated-custom-dependencies-file "cus-load.el" - "File \\[cusom-make-dependencies] puts custom dependencies into.") + "Output file for \\[custom-make-dependencies].") (defun custom-make-dependencies () "Batch function to extract custom dependencies from .el files. diff -r 8438f5473d99 -r de425e4eb0bc lisp/cus-edit.el --- a/lisp/cus-edit.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/cus-edit.el Tue Jan 17 00:56:42 2006 +0000 @@ -88,7 +88,7 @@ ;; compatibility. ;; You can see (and modify and save) this unevaluated value by selecting -;; "Show initial Lisp expression" from the Lisp interface. This will +;; "Show Saved Lisp Expression" from the Lisp interface. This will ;; give you the unevaluated saved value, if any, otherwise the ;; unevaluated standard value. @@ -746,32 +746,39 @@ (defun Custom-set () "Set the current value of all edited settings in the buffer." (interactive) - (if (y-or-n-p "Set all values according to this buffer? ") - (let ((children custom-options)) + (let ((children custom-options)) + (if (or (and (= 1 (length children)) + (memq (widget-type (car children)) + '(custom-variable custom-face))) + (y-or-n-p "Set all values according to this buffer? ")) (mapc (lambda (child) (when (eq (widget-get child :custom-state) 'modified) (widget-apply child :custom-set))) - children)) - (message "Aborted"))) + children) + (message "Aborted")))) (defun Custom-save () "Set all edited settings, then save all settings that have been set. If a setting was edited and set before, this saves it. If a setting was merely edited before, this sets it then saves it." (interactive) - (if (yes-or-no-p "Save all settings in this buffer? ") - (let ((children custom-options)) - (mapc (lambda (child) - (when (memq (widget-get child :custom-state) - '(modified set changed rogue)) - (widget-apply child :custom-save))) - children) - (custom-save-all)) - (message "Aborted"))) + (let ((children custom-options)) + (if (or (and (= 1 (length children)) + (memq (widget-type (car children)) + '(custom-variable custom-face))) + (yes-or-no-p "Save all settings in this buffer? ")) + (progn + (mapc (lambda (child) + (when (memq (widget-get child :custom-state) + '(modified set changed rogue)) + (widget-apply child :custom-save))) + children) + (custom-save-all)) + (message "Aborted")))) (defvar custom-reset-menu - '(("Reset to current settings" . Custom-reset-current) - ("Reset to saved settings" . Custom-reset-saved) + '(("Undo Edits" . Custom-reset-current) + ("Reset to Saved" . Custom-reset-saved) ("Erase Customization (use standard values)" . Custom-reset-standard)) "Alist of actions for the `Reset' button. The key is a string containing the name of the action, the value is a @@ -790,27 +797,33 @@ (defun Custom-reset-current (&rest ignore) "Reset all edited settings in the buffer to show their current values." (interactive) - (if (y-or-n-p "Reset all settings' buffer text to show current values? ") - (let ((children custom-options)) + (let ((children custom-options)) + (if (or (and (= 1 (length children)) + (memq (widget-type (car children)) + '(custom-variable custom-face))) + (y-or-n-p "Reset all settings' buffer text to show current values? ")) (mapc (lambda (widget) (if (memq (widget-get widget :custom-state) '(modified changed)) (widget-apply widget :custom-reset-current))) - children)) - (message "Aborted"))) + children) + (message "Aborted")))) (defun Custom-reset-saved (&rest ignore) "Reset all edited or set settings in the buffer to their saved value. This also shows the saved values in the buffer." (interactive) - (if (y-or-n-p "Reset all settings (current values and buffer text) to saved values? ") - (let ((children custom-options)) + (let ((children custom-options)) + (if (or (and (= 1 (length children)) + (memq (widget-type (car children)) + '(custom-variable custom-face))) + (y-or-n-p "Reset all settings (current values and buffer text) to saved values? ")) (mapc (lambda (widget) (if (memq (widget-get widget :custom-state) '(modified set changed rogue)) (widget-apply widget :custom-reset-saved))) - children)) - (message "Aborted"))) + children) + (message "Aborted")))) (defun Custom-reset-standard (&rest ignore) "Erase all customization (either current or saved) for the group members. @@ -1509,7 +1522,7 @@ (custom-reset event)))) (widget-insert "\n ") (widget-create 'push-button - :tag "Reset to Current" + :tag "Undo Edits" :help-echo "\ Reset all edited text in this buffer to reflect current values." :action 'Custom-reset-current) @@ -2201,7 +2214,10 @@ (insert prefix)) (insert "See also ") (while links - (push (widget-create-child-and-convert widget (car links)) + (push (widget-create-child-and-convert + widget (car links) + :button-face 'custom-link + :mouse-face 'highlight) buttons) (setq links (cdr links)) (cond ((null links) @@ -2246,7 +2262,10 @@ (when links (insert "\nParent documentation: ") (while links - (push (widget-create-child-and-convert widget (car links)) + (push (widget-create-child-and-convert + widget (car links) + :button-face 'custom-link + :mouse-face 'highlight) buttons) (setq links (cdr links)) (cond ((null links) @@ -2628,40 +2647,40 @@ (get (widget-value widget) 'standard-value)) (defvar custom-variable-menu - `(("Set for current session" custom-variable-set + `(("Set for Current Session" custom-variable-set (lambda (widget) (eq (widget-get widget :custom-state) 'modified))) ,@(when (or custom-file user-init-file) - '(("Save for future sessions" custom-variable-save + '(("Save for Future Sessions" custom-variable-save (lambda (widget) (memq (widget-get widget :custom-state) '(modified set changed rogue)))))) - ("---" ignore ignore) - ("Reset to current value" custom-redraw + ("Undo Edits" custom-redraw (lambda (widget) (and (default-boundp (widget-value widget)) (memq (widget-get widget :custom-state) '(modified changed))))) - ("Reset to saved value" custom-variable-reset-saved + ("Reset to Saved" custom-variable-reset-saved (lambda (widget) (and (or (get (widget-value widget) 'saved-value) (get (widget-value widget) 'saved-variable-comment)) (memq (widget-get widget :custom-state) '(modified set changed rogue))))) - ("Reset to backup value" custom-variable-reset-backup - (lambda (widget) - (get (widget-value widget) 'backup-value))) ,@(when (or custom-file user-init-file) - '(("Erase customization" custom-variable-reset-standard + '(("Erase Customization" custom-variable-reset-standard (lambda (widget) (and (get (widget-value widget) 'standard-value) (memq (widget-get widget :custom-state) '(modified set changed saved rogue))))))) + ("Set to Backup Value" custom-variable-reset-backup + (lambda (widget) + (get (widget-value widget) 'backup-value))) ("---" ignore ignore) - ("Add comment" custom-comment-show custom-comment-invisible-p) - ("Show value widget" custom-variable-edit + ("Add Comment" custom-comment-show custom-comment-invisible-p) + ("---" ignore ignore) + ("Show Current Value" custom-variable-edit (lambda (widget) (eq (widget-get widget :custom-form) 'lisp))) - ("Show Lisp expression" custom-variable-edit-lisp + ("Show Saved Lisp Expression" custom-variable-edit-lisp (lambda (widget) (eq (widget-get widget :custom-form) 'edit)))) "Alist of actions for the `custom-variable' widget. @@ -3302,27 +3321,30 @@ (message "Creating face editor...done")))))) (defvar custom-face-menu - `(("Set for current session" custom-face-set) + `(("Set for Current Session" custom-face-set) ,@(when (or custom-file user-init-file) - '(("Save for future sessions" custom-face-save-command))) - ("---" ignore ignore) - ("Reset to saved face" custom-face-reset-saved + '(("Save for Future Sessions" custom-face-save-command))) + ("Undo Edits" custom-redraw + (lambda (widget) + (memq (widget-get widget :custom-state) '(modified changed)))) + ("Reset to Saved" custom-face-reset-saved (lambda (widget) (or (get (widget-value widget) 'saved-face) (get (widget-value widget) 'saved-face-comment)))) ,@(when (or custom-file user-init-file) - '(("Erase customization" custom-face-reset-standard + '(("Erase Customization" custom-face-reset-standard (lambda (widget) (get (widget-value widget) 'face-defface-spec))))) ("---" ignore ignore) - ("Add comment" custom-comment-show custom-comment-invisible-p) - ("Show all attributes" custom-face-edit-all + ("Add Comment" custom-comment-show custom-comment-invisible-p) + ("---" ignore ignore) + ("For Current Display" custom-face-edit-selected + (lambda (widget) + (not (eq (widget-get widget :custom-form) 'selected)))) + ("For All Kinds of Displays" custom-face-edit-all (lambda (widget) (not (eq (widget-get widget :custom-form) 'all)))) - ("Show current attributes" custom-face-edit-selected - (lambda (widget) - (not (eq (widget-get widget :custom-form) 'selected)))) - ("Show Lisp expression" custom-face-edit-lisp + ("Show Lisp Expression" custom-face-edit-lisp (lambda (widget) (not (eq (widget-get widget :custom-form) 'lisp))))) "Alist of actions for the `custom-face' widget. @@ -3900,22 +3922,21 @@ (insert "/\n"))))) (defvar custom-group-menu - `(("Set for current session" custom-group-set + `(("Set for Current Session" custom-group-set (lambda (widget) (eq (widget-get widget :custom-state) 'modified))) ,@(when (or custom-file user-init-file) - '(("Save for future sessions" custom-group-save + '(("Save for Future Sessions" custom-group-save (lambda (widget) (memq (widget-get widget :custom-state) '(modified set)))))) - ("---" ignore ignore) - ("Reset to current settings" custom-group-reset-current + ("Undo Edits" custom-group-reset-current (lambda (widget) (memq (widget-get widget :custom-state) '(modified)))) - ("Reset to saved settings" custom-group-reset-saved + ("Reset to Saved" custom-group-reset-saved (lambda (widget) (memq (widget-get widget :custom-state) '(modified set)))) ,@(when (or custom-file user-init-file) - '(("Reset to standard settings" custom-group-reset-standard + '(("Erase Customization" custom-group-reset-standard (lambda (widget) (memq (widget-get widget :custom-state) '(modified set saved))))))) "Alist of actions for the `custom-group' widget. @@ -4374,9 +4395,9 @@ ,(customize-menu-create 'customize) ["Set" Custom-set t] ["Save" Custom-save t] - ["Reset to current settings" Custom-reset-current t] - ["Reset to saved settings" Custom-reset-saved t] - ["Erase customizations" Custom-reset-standard t] + ["Undo Edits" Custom-reset-current t] + ["Reset to Saved" Custom-reset-saved t] + ["Erase Customization" Custom-reset-standard t] ["Info" (info "(emacs)Easy Customization") t])) (defun Custom-goto-parent () diff -r 8438f5473d99 -r de425e4eb0bc lisp/cus-theme.el --- a/lisp/cus-theme.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/cus-theme.el Tue Jan 17 00:56:42 2006 +0000 @@ -154,20 +154,25 @@ (defun custom-theme-add-variable (symbol) (interactive "vVariable name: ") - (save-excursion - (goto-char custom-theme-insert-variable-marker) - (if (assq symbol custom-theme-variables) - (message "%s is already in the theme" (symbol-name symbol)) - (widget-insert "\n") - (let ((widget (widget-create 'custom-variable - :tag (custom-unlispify-tag-name symbol) - :custom-level 0 - :action 'custom-theme-variable-action - :custom-state 'unknown - :value symbol))) - (push (cons symbol widget) custom-theme-variables) - (custom-magic-reset widget)) - (widget-setup)))) + (cond ((assq symbol custom-theme-variables) + (message "%s is already in the theme" (symbol-name symbol))) + ((not (boundp symbol)) + (message "%s is not defined as a variable" (symbol-name symbol))) + ((eq symbol 'custom-enabled-themes) + (message "Custom theme cannot contain `custom-enabled-themes'")) + (t + (save-excursion + (goto-char custom-theme-insert-variable-marker) + (widget-insert "\n") + (let ((widget (widget-create 'custom-variable + :tag (custom-unlispify-tag-name symbol) + :custom-level 0 + :action 'custom-theme-variable-action + :custom-state 'unknown + :value symbol))) + (push (cons symbol widget) custom-theme-variables) + (custom-magic-reset widget)) + (widget-setup))))) (defvar custom-theme-variable-menu `(("Reset to Current" custom-redraw @@ -220,20 +225,23 @@ (defun custom-theme-add-face (symbol) (interactive (list (read-face-name "Face name" nil nil))) - (save-excursion - (goto-char custom-theme-insert-face-marker) - (if (assq symbol custom-theme-faces) - (message "%s is already in the theme" (symbol-name symbol)) - (widget-insert "\n") - (let ((widget (widget-create 'custom-face - :tag (custom-unlispify-tag-name symbol) - :custom-level 0 - :action 'custom-theme-face-action - :custom-state 'unknown - :value symbol))) - (push (cons symbol widget) custom-theme-faces) - (custom-magic-reset widget) - (widget-setup))))) + (cond ((assq symbol custom-theme-faces) + (message "%s is already in the theme" (symbol-name symbol))) + ((not (facep symbol)) + (message "%s is not defined as a face" (symbol-name symbol))) + (t + (save-excursion + (goto-char custom-theme-insert-face-marker) + (widget-insert "\n") + (let ((widget (widget-create 'custom-face + :tag (custom-unlispify-tag-name symbol) + :custom-level 0 + :action 'custom-theme-face-action + :custom-state 'unknown + :value symbol))) + (push (cons symbol widget) custom-theme-faces) + (custom-magic-reset widget) + (widget-setup)))))) (defvar custom-theme-face-menu `(("Reset to Theme Value" custom-face-reset-theme diff -r 8438f5473d99 -r de425e4eb0bc lisp/emacs-lisp/bytecomp.el --- a/lisp/emacs-lisp/bytecomp.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/emacs-lisp/bytecomp.el Tue Jan 17 00:56:42 2006 +0000 @@ -4101,7 +4101,11 @@ (defun batch-byte-recompile-directory (&optional arg) "Run `byte-recompile-directory' on the dirs remaining on the command line. Must be used only with `-batch', and kills Emacs on completion. -For example, invoke `emacs -batch -f batch-byte-recompile-directory .'." +For example, invoke `emacs -batch -f batch-byte-recompile-directory .'. + +Optional argument ARG is passed as second argument ARG to +`batch-recompile-directory'; see there for its possible values +and corresponding effects." ;; command-line-args-left is what is left of the command line (startup.el) (defvar command-line-args-left) ;Avoid 'free variable' warning (if (not noninteractive) diff -r 8438f5473d99 -r de425e4eb0bc lisp/font-lock.el --- a/lisp/font-lock.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/font-lock.el Tue Jan 17 00:56:42 2006 +0000 @@ -1963,6 +1963,78 @@ (goto-char (or (scan-sexps (point) 1) (point-max)))) (goto-char (match-end 2))) (error t))))) + +;; C preprocessor(cpp) is used outside of C, C++ and Objective-C source file. +;; e.g. assembler code and GNU linker script in Linux kernel. +;; `cpp-font-lock-keywords' is handy for modes for the files. +;; +;; Here we cannot use `regexp-opt' because because regex-opt is not preloaded +;; while font-lock.el is preloaded to emacs. So values pre-calculated with +;; regexp-opt are used here. + +;; `cpp-font-lock-keywords-source-directives' is calculated from: +;; +;; (regexp-opt +;; '("define" "elif" "else" "endif" "error" "file" "if" "ifdef" +;; "ifndef" "include" "line" "pragma" "undef")) +;; +(defconst cpp-font-lock-keywords-source-directives + "define\\|e\\(?:l\\(?:if\\|se\\)\\|ndif\\|rror\\)\\|file\\|i\\(?:f\\(?:n?def\\)?\\|nclude\\)\\|line\\|pragma\\|undef" + "Regular expressoin used in `cpp-font-lock-keywords'.") + +;; `cpp-font-lock-keywords-source-depth' is calculated from: +;; +;; (regexp-opt-depth (regexp-opt +;; '("define" "elif" "else" "endif" "error" "file" "if" "ifdef" +;; "ifndef" "include" "line" "pragma" "undef"))) +;; +(defconst cpp-font-lock-keywords-source-depth 0 + "An integer representing regular expression depth of `cpp-font-lock-keywords-source-directives'. +Used in `cpp-font-lock-keywords'.") + +(defconst cpp-font-lock-keywords + (let* ((directives cpp-font-lock-keywords-source-directives) + (directives-depth cpp-font-lock-keywords-source-depth)) + (list + ;; + ;; Fontify error directives. + '("^#[ \t]*error[ \t]+\\(.+\\)" 1 font-lock-warning-face prepend) + ;; + ;; Fontify filenames in #include <...> preprocessor directives as strings. + '("^#[ \t]*\\(?:import\\|include\\)[ \t]*\\(<[^>\"\n]*>?\\)" + 1 font-lock-string-face prepend) + ;; + ;; Fontify function macro names. + '("^#[ \t]*define[ \t]+\\([[:alpha:]_][[:alnum:]_$]*\\)(" + (1 font-lock-function-name-face prepend) + ;; + ;; Macro arguments. + ((lambda (limit) + (re-search-forward + "\\(?:\\([[:alpha:]_][[:alnum:]_]*\\)[,]?\\)" + (or (save-excursion (re-search-forward ")" limit t)) + limit) + t)) + nil nil (1 font-lock-variable-name-face prepend))) + ;; + ;; Fontify symbol names in #elif or #if ... defined preprocessor directives. + '("^#[ \t]*\\(?:elif\\|if\\)\\>" + ("\\<\\(defined\\)\\>[ \t]*(?\\([[:alpha:]_][[:alnum:]_]*\\)?" nil nil + (1 font-lock-builtin-face prepend) (2 font-lock-variable-name-face prepend t))) + ;; + ;; Fontify otherwise as symbol names, and the preprocessor directive names. + (list + (concat "^\\(#[ \t]*\\(?:" directives + "\\)\\)\\>[ \t!]*\\([[:alpha:]_][[:alnum:]_]*\\)?") + '(1 font-lock-preprocessor-face prepend) + (list (+ 2 directives-depth) + 'font-lock-variable-name-face nil t)))) + "Font lock keyords for C preprocessor directives. +`c-mode', `c++-mode' and `objc-mode' have their own +font lock keyords for C preprocessor directives. This definition is for the +other modes in which C preprocessor directives are used. e.g. `asm-mode' and +`ld-script-mode'.") + ;; Lisp. diff -r 8438f5473d99 -r de425e4eb0bc lisp/gnus/ChangeLog --- a/lisp/gnus/ChangeLog Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/gnus/ChangeLog Tue Jan 17 00:56:42 2006 +0000 @@ -1,3 +1,29 @@ +2006-01-16 Katsumi Yamaoka + + * mm-uu.el (mm-uu-text-plain-type): New variable. + (mm-uu-pgp-signed-extract-1): Use it. + (mm-uu-pgp-encrypted-extract-1): Use it. + (mm-uu-dissect): Use it; allow two optional arguments; one is a + flag specifying whether there's no message header; the other is + for a MIME type and parameters; bind mm-uu-text-plain-type with + the later one. + (mm-uu-dissect-text-parts): New function. + + * gnus-art.el (gnus-display-mime): Use mm-uu-dissect-text-parts to + dissect text parts. + +2006-01-13 Katsumi Yamaoka + + * gnus-art.el (article-wash-html): Use + gnus-summary-show-article-charset-alist if a numeric arg is given. + (gnus-article-wash-html-with-w3m-standalone): New function. + + * mm-view.el (mm-text-html-renderer-alist): Map w3m-standalone to + mm-inline-text-html-render-with-w3m-standalone. + (mm-text-html-washer-alist): Map w3m-standalone to + gnus-article-wash-html-with-w3m-standalone. + (mm-inline-text-html-render-with-w3m-standalone): New function. + 2006-01-10 Katsumi Yamaoka * nnrss.el (nnrss-wash-html-in-text-plain-parts): New variable. diff -r 8438f5473d99 -r de425e4eb0bc lisp/gnus/gnus-art.el --- a/lisp/gnus/gnus-art.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/gnus/gnus-art.el Tue Jan 17 00:56:42 2006 +0000 @@ -2467,25 +2467,36 @@ (defun article-wash-html (&optional read-charset) "Format an HTML article. -If READ-CHARSET, ask for a coding system." +If READ-CHARSET, ask for a coding system. If it is a number, the +charset defined in `gnus-summary-show-article-charset-alist' is used." (interactive "P") (save-excursion (let ((inhibit-read-only t) charset) - (when (gnus-buffer-live-p gnus-original-article-buffer) - (with-current-buffer gnus-original-article-buffer - (let* ((ct (gnus-fetch-field "content-type")) - (ctl (and ct - (ignore-errors - (mail-header-parse-content-type ct))))) - (setq charset (and ctl - (mail-content-type-get ctl 'charset))) - (when (stringp charset) - (setq charset (intern (downcase charset))))))) - (when read-charset - (setq charset (mm-read-coding-system "Charset: " charset))) - (unless charset - (setq charset gnus-newsgroup-charset)) + (if read-charset + (if (or (and (numberp read-charset) + (setq charset + (cdr + (assq read-charset + gnus-summary-show-article-charset-alist)))) + (setq charset (mm-read-coding-system "Charset: "))) + (let ((gnus-summary-show-article-charset-alist + (list (cons 1 charset)))) + (with-current-buffer gnus-summary-buffer + (gnus-summary-show-article 1))) + (error "No charset is given")) + (when (gnus-buffer-live-p gnus-original-article-buffer) + (with-current-buffer gnus-original-article-buffer + (let* ((ct (gnus-fetch-field "content-type")) + (ctl (and ct + (ignore-errors + (mail-header-parse-content-type ct))))) + (setq charset (and ctl + (mail-content-type-get ctl 'charset))) + (when (stringp charset) + (setq charset (intern (downcase charset))))))) + (unless charset + (setq charset gnus-newsgroup-charset))) (article-goto-body) (save-window-excursion (save-restriction @@ -2526,6 +2537,20 @@ ;; Put the mark meaning this part was rendered by emacs-w3m. 'mm-inline-text-html-with-w3m t)))) +(eval-when-compile (defvar charset)) ;; Bound by `article-wash-html'. + +(defun gnus-article-wash-html-with-w3m-standalone () + "Wash the current buffer with w3m." + (unless (mm-coding-system-p charset) + ;; The default. + (setq charset 'iso-8859-1)) + (let ((coding-system-for-write charset) + (coding-system-for-read charset)) + (call-process-region + (point-min) (point-max) + "w3m" t t nil "-dump" "-T" "text/html" + "-I" (symbol-name charset) "-O" (symbol-name charset)))) + (defun article-hide-list-identifiers () "Remove list identifies from the Subject header. The `gnus-list-identifiers' variable specifies what to do." @@ -4718,11 +4743,15 @@ ;; We have to do this since selecting the window ;; may change the point. So we set the window point. (set-window-point window point))) - (let* ((handles (or ihandles - (mm-dissect-buffer nil gnus-article-loose-mime) - (and gnus-article-emulate-mime - (mm-uu-dissect)))) - (inhibit-read-only t) handle name type b e display) + (let ((handles ihandles) + (inhibit-read-only t) + handle) + (cond (handles) + ((setq handles (mm-dissect-buffer nil gnus-article-loose-mime)) + (when gnus-article-emulate-mime + (mm-uu-dissect-text-parts handles))) + (gnus-article-emulate-mime + (setq handles (mm-uu-dissect)))) (when (and (not ihandles) (not gnus-displaying-mime)) ;; Top-level call; we clean up. diff -r 8438f5473d99 -r de425e4eb0bc lisp/gnus/mm-uu.el --- a/lisp/gnus/mm-uu.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/gnus/mm-uu.el Tue Jan 17 00:56:42 2006 +0000 @@ -174,6 +174,10 @@ mm-uu-type-alist) :group 'gnus-article-mime) +(defvar mm-uu-text-plain-type '("text/plain" (charset . gnus-decoded)) + "MIME type and parameters for text/plain parts. +`gnus-decoded' is a fake charset, which means no further decoding.") + ;; functions (defsubst mm-uu-type (entry) @@ -375,7 +379,7 @@ (while (re-search-forward "^- " nil t) (replace-match "" t t) (forward-line 1))) - (list (mm-make-handle buf '("text/plain" (charset . gnus-decoded)))))) + (list (mm-make-handle buf mm-uu-text-plain-type)))) (defun mm-uu-pgp-signed-extract () (let ((mm-security-handle (list (format "multipart/signed")))) @@ -407,9 +411,7 @@ (with-current-buffer buf (mml2015-clean-buffer) (funcall (mml2015-clear-decrypt-function)))) - (list - (mm-make-handle buf - '("text/plain" (charset . gnus-decoded)))))) + (list (mm-make-handle buf mm-uu-text-plain-type)))) (defun mm-uu-pgp-encrypted-extract () (let ((mm-security-handle (list (format "multipart/encrypted")))) @@ -443,23 +445,24 @@ '("application/pgp-keys")))) ;;;###autoload -(defun mm-uu-dissect () - "Dissect the current buffer and return a list of uu handles." +(defun mm-uu-dissect (&optional noheader mime-type) + "Dissect the current buffer and return a list of uu handles. +The optional NOHEADER means there's no header in the buffer. +MIME-TYPE specifies a MIME type and parameters, which defaults to the +value of `mm-uu-text-plain-type'." (let ((case-fold-search t) - text-start start-point end-point file-name result - text-plain-type entry func) + (mm-uu-text-plain-type (or mime-type mm-uu-text-plain-type)) + text-start start-point end-point file-name result entry func) (save-excursion (goto-char (point-min)) (cond + (noheader) ((looking-at "\n") (forward-line)) ((search-forward "\n\n" nil t) t) (t (goto-char (point-max)))) - ;;; gnus-decoded is a fake charset, which means no further - ;;; decoding. - (setq text-start (point) - text-plain-type '("text/plain" (charset . gnus-decoded))) + (setq text-start (point)) (while (re-search-forward mm-uu-beginning-regexp nil t) (setq start-point (match-beginning 0)) (let ((alist mm-uu-type-alist) @@ -488,7 +491,7 @@ (re-search-forward "." start-point t))) (push (mm-make-handle (mm-uu-copy-to-buffer text-start start-point) - text-plain-type) + mm-uu-text-plain-type) result)) (push (funcall (mm-uu-function-extract entry)) @@ -501,11 +504,32 @@ (re-search-forward "." nil t))) (push (mm-make-handle (mm-uu-copy-to-buffer text-start (point-max)) - text-plain-type) + mm-uu-text-plain-type) result)) (setq result (cons "multipart/mixed" (nreverse result)))) result))) +(defun mm-uu-dissect-text-parts (handle) + "Dissect text parts and put uu handles into HANDLE." + (let ((buffer (mm-handle-buffer handle)) + type children) + (cond ((stringp buffer) + (dolist (elem (cdr handle)) + (mm-uu-dissect-text-parts elem))) + ((bufferp buffer) + (when (and (setq type (mm-handle-media-type handle)) + (stringp type) + (string-match "\\`text/" type) + (with-current-buffer buffer + (setq children + (mm-uu-dissect t (mm-handle-type handle))))) + (kill-buffer buffer) + (setcar handle (car children)) + (setcdr handle (cdr children)))) + (t + (dolist (elem handle) + (mm-uu-dissect-text-parts elem)))))) + (provide 'mm-uu) ;; arch-tag: 7db076bf-53db-4320-aa19-ca76a1d2ab2c diff -r 8438f5473d99 -r de425e4eb0bc lisp/gnus/mm-view.el --- a/lisp/gnus/mm-view.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/gnus/mm-view.el Tue Jan 17 00:56:42 2006 +0000 @@ -51,8 +51,7 @@ (defvar mm-text-html-renderer-alist '((w3 . mm-inline-text-html-render-with-w3) (w3m . mm-inline-text-html-render-with-w3m) - (w3m-standalone mm-inline-render-with-stdin nil - "w3m" "-dump" "-T" "text/html") + (w3m-standalone . mm-inline-text-html-render-with-w3m-standalone) (links mm-inline-render-with-file mm-links-remove-leading-blank "links" "-dump" file) @@ -64,8 +63,7 @@ (defvar mm-text-html-washer-alist '((w3 . gnus-article-wash-html-with-w3) (w3m . gnus-article-wash-html-with-w3m) - (w3m-standalone mm-inline-wash-with-stdin nil - "w3m" "-dump" "-T" "text/html") + (w3m-standalone . gnus-article-wash-html-with-w3m-standalone) (links mm-inline-wash-with-file mm-links-remove-leading-blank "links" "-dump" file) @@ -264,6 +262,30 @@ (delete-region ,(point-min-marker) ,(point-max-marker))))))))) +(defun mm-inline-text-html-render-with-w3m-standalone (handle) + "Render a text/html part using w3m." + (let ((source (mm-get-part handle)) + (charset (mail-content-type-get (mm-handle-type handle) 'charset)) + cs) + (unless (and charset + (setq cs (mm-charset-to-coding-system charset)) + (not (eq cs 'ascii))) + ;; The default. + (setq charset "iso-8859-1" + cs 'iso-8859-1)) + (mm-insert-inline + handle + (mm-with-unibyte-buffer + (insert source) + (mm-enable-multibyte) + (let ((coding-system-for-write 'binary) + (coding-system-for-read cs)) + (call-process-region + (point-min) (point-max) + "w3m" t t nil "-dump" "-T" "text/html" + "-I" charset "-O" charset)) + (buffer-string))))) + (defun mm-links-remove-leading-blank () ;; Delete the annoying three spaces preceding each line of links ;; output. diff -r 8438f5473d99 -r de425e4eb0bc lisp/help-fns.el --- a/lisp/help-fns.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/help-fns.el Tue Jan 17 00:56:42 2006 +0000 @@ -1,7 +1,7 @@ ;;; help-fns.el --- Complex help functions ;; Copyright (C) 1985, 1986, 1993, 1994, 1998, 1999, 2000, 2001, -;; 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +;; 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. ;; Maintainer: FSF ;; Keywords: help, internal @@ -560,10 +560,10 @@ (help-xref-button 1 'help-variable-def variable file-name))) (if valvoid - (princ "It is void as a variable.\n") + (princ "It is void as a variable.") (princ "Its "))) (if valvoid - (princ " is void as a variable.\n") + (princ " is void as a variable.") (princ "'s ")))) (if valvoid nil diff -r 8438f5473d99 -r de425e4eb0bc lisp/iswitchb.el --- a/lisp/iswitchb.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/iswitchb.el Tue Jan 17 00:56:42 2006 +0000 @@ -559,7 +559,7 @@ (define-key map "\C-j" 'iswitchb-select-buffer-text) (define-key map "\C-t" 'iswitchb-toggle-regexp) (define-key map "\C-x\C-f" 'iswitchb-find-file) - (define-key map "\C-a" 'iswitchb-toggle-ignore) + (define-key map "\C-n" 'iswitchb-toggle-ignore) (define-key map "\C-c" 'iswitchb-toggle-case) (define-key map "\C-k" 'iswitchb-kill-buffer) (define-key map "\C-m" 'iswitchb-exit-minibuffer) diff -r 8438f5473d99 -r de425e4eb0bc lisp/makefile.w32-in --- a/lisp/makefile.w32-in Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/makefile.w32-in Tue Jan 17 00:56:42 2006 +0000 @@ -289,20 +289,21 @@ # Recompile all Lisp files which are newer than their .elc files. # Note that this doesn't create .elc files. It only recompiles if an # .elc is present. - -recompile: mh-autoloads doit - $(emacs) -f batch-byte-recompile-directory $(lisp) +# WARNING: Do NOT split the part inside $(ARGQUOTE)s into multiple lines as +# this can break with GNU Make 3.81 and later if sh.exe is used. +recompile: mh-autoloads doit $(lisp)/progmodes/cc-mode.elc + $(emacs) --eval $(ARGQUOTE)(batch-byte-recompile-directory 0)$(ARGQUOTE) $(lisp) # Update MH-E internal autoloads. These are not to be confused with # the autoloads for the MH-E entry points, which are already in # loaddefs.el. MH_E_SRC = $(lisp)/mh-e/mh-acros.el $(lisp)/mh-e/mh-alias.el \ - $(lisp)/mh-e/mh-comp.el $(lisp)/mh-e/mh-customize.el \ - $(lisp)/mh-e/mh-e.el $(lisp)/mh-e/mh-funcs.el \ - $(lisp)/mh-e/mh-mime.el $(lisp)/mh-e/mh-pick.el \ - $(lisp)/mh-e/mh-print.el $(lisp)/mh-e/mh-inc.el \ - $(lisp)/mh-e/mh-init.el $(lisp)/mh-e/mh-index.el \ - $(lisp)/mh-e/mh-identity.el $(lisp)/mh-e/mh-junk.el \ + $(lisp)/mh-e/mh-buffers.el $(lisp)/mh-e/mh-comp.el \ + $(lisp)/mh-e/mh-customize.el $(lisp)/mh-e/mh-e.el \ + $(lisp)/mh-e/mh-funcs.el $(lisp)/mh-e/mh-identity.el \ + $(lisp)/mh-e/mh-inc.el $(lisp)/mh-e/mh-init.el \ + $(lisp)/mh-e/mh-junk.el $(lisp)/mh-e/mh-mime.el \ + $(lisp)/mh-e/mh-print.el $(lisp)/mh-e/mh-search.el \ $(lisp)/mh-e/mh-seq.el $(lisp)/mh-e/mh-speed.el \ $(lisp)/mh-e/mh-utils.el @@ -322,37 +323,37 @@ pre-mh-loaddefs.el-SH: echo ";;; mh-loaddefs.el --- automatically extracted autoloads" > $@ echo ";;" >> $@ - echo ";;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc." >> $@ - echo ";;; Author: Bill Wohler " >> $@ - echo ";;; Keywords: mail" >> $@ + echo ";; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc." >> $@ + echo ";; Author: Bill Wohler " >> $@ + echo ";; Keywords: mail" >> $@ echo ";;; Commentary:" >> $@ echo ";;; Change Log:" >> $@ echo ";;; Code:" >> $@ echo " " >> $@ echo "(provide 'mh-loaddefs)" >> $@ - echo ";;; Local Variables:" >> $@ - echo ";;; version-control: never" >> $@ - echo ";;; no-byte-compile: t" >> $@ - echo ";;; no-update-autoloads: t" >> $@ - echo ";;; End:" >> $@ + echo ";; Local Variables:" >> $@ + echo ";; version-control: never" >> $@ + echo ";; no-byte-compile: t" >> $@ + echo ";; no-update-autoloads: t" >> $@ + echo ";; End:" >> $@ echo ";;; mh-loaddefs.el ends here" >> $@ pre-mh-loaddefs.el-CMD: echo ;;; mh-loaddefs.el --- automatically extracted autoloads> $@ echo ;;>> $@ - echo ;;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.>> $@ - echo ;;; Author: Bill Wohler (wohler@newt.com)>> $@ - echo ;;; Keywords: mail>> $@ + echo ;; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.>> $@ + echo ;; Author: Bill Wohler (wohler@newt.com)>> $@ + echo ;; Keywords: mail>> $@ echo ;;; Commentary:>> $@ echo ;;; Change Log:>> $@ echo ;;; Code:>> $@ echo. >> $@ echo (provide 'mh-loaddefs)>> $@ - echo ;;; Local Variables:>> $@ - echo ;;; version-control: never>> $@ - echo ;;; no-byte-compile: t>> $@ - echo ;;; no-update-autoloads: t>> $@ - echo ;;; End:>> $@ + echo ;; Local Variables:>> $@ + echo ;; version-control: never>> $@ + echo ;; no-byte-compile: t>> $@ + echo ;; no-update-autoloads: t>> $@ + echo ;; End:>> $@ echo ;;; mh-loaddefs.el ends here>> $@ # Prepare a bootstrap in the lisp subdirectory. diff -r 8438f5473d99 -r de425e4eb0bc lisp/man.el --- a/lisp/man.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/man.el Tue Jan 17 00:56:42 2006 +0000 @@ -304,7 +304,7 @@ (defvar Man-include-regexp "#[ \t]*include[ \t]*" "Regular expression describing the #include (directive of cpp).") -(defvar Man-file-name-regexp "[^<>\" \t\n]+" +(defvar Man-file-name-regexp "[^<>\", \t\n]+" "Regular expression describing <> in #include line (directive of cpp).") (defvar Man-normal-file-prefix-regexp "[/~$]" diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/ChangeLog --- a/lisp/mh-e/ChangeLog Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/ChangeLog Tue Jan 17 00:56:42 2006 +0000 @@ -1,7 +1,228 @@ +2006-01-15 Bill Wohler + + * mh-e.el (mh-limit-map, mh-help-messages): Change keybinding of + mh-narrow-to-from from / f to / m; mh-narrow-to-range from / r to + / g. + + * mh-utils.el (mh-show-limit-map): Ditto. + + * mh-exec.el: Require mh-acros, mh-buffers, and mh-utils for + standalone compile. + (mh-progs, mh-lib, mh-lib-progs): Move here from mh-init.el. + + * mh-init.el (mh-progs, mh-lib, mh-lib-progs): Move to mh-exec.el, + where they are used. + + * mh-comp.el (mh-pgp-support-flag): Move here from mh-utils.el; + needed to help remove dependency on mh-utils. + + * mh-exec.el: New file. Move process support routines here from + mh-utils.el. + + * mh-init.el (mh-utils): Remove require. + (mh-exec): Add require. + (mh-profile-component, mh-profile-component-value): Move here from + mh-utils.el. + + * mh-utils.el (mh-pgp-support-flag): Move to mh-comp.el to reduce + dependencies on mh-utils.el. + (mh-profile-component, mh-profile-component-value): Move to + mh-init.el since that's the only place that uses them. (Other than + mh-alias.el; I'm thinking that mh-find-path can set variable from + the Aliasfile component like it does the other components). + (mh-index-max-cmdline-args, mh-xargs, mh-quote-for-shell) + (mh-exec-cmd, mh-exec-cmd-error, mh-exec-cmd-daemon) + (mh-exec-cmd-env-daemon, mh-process-daemon, mh-exec-cmd-quiet) + (defvar, mh-exec-cmd-output) + (mh-exchange-point-and-mark-preserving-active-mark) + (mh-exec-lib-cmd-output, mh-handle-process-error): Move to new + file mh-exec.el so that mh-init.el doesn't have to depend on + mh-utils.el, breaking circular dependency. + + * mh-alias.el: + * mh-customize.el: + * mh-e.el: + * mh-funcs.el: + * mh-gnus.el: + * mh-identity.el: + * mh-inc.el: + * mh-junk.el: + * mh-mime.el: + * mh-print.el: + * mh-search.el: + * mh-seq.el: + * mh-speed.el: Added debugging statements (commented out) around + requires to help find dependency loops. Will remove them when + issues are resolved. + +2006-01-14 Bill Wohler + + * mh-customize.el (mh-index): Rename group to mh-search and sort + group definition and options accordingly. + (mh-index-program): Rename to mh-search-program. + (mh-kill-folder-suppress-prompt-hooks): Rename mh-index-p to + mh-search-p. + (mh-search-mode-hook): Change group from mh-index to mh-search. + (mh-index-folder): Rename to mh-search-folder. Change group from + mh-index to mh-search. + + * mh-e.el (mh-folder-font-lock-keywords): Rename mh-index-folder + to mh-search-folder. + + * mh-search.el (mh-indexer) Rename to mh-searcher. The commands + pick and grep are searchers too but aren't indexed. + (mh-index-execute-search-function): Rename to mh-search-function. + (mh-index-next-result-function): Rename to + mh-search-next-result-function. + (mh-index-regexp-builder): Rename to mh-search-regexp-builder. + (mh-search): Since redo-search-flag defaults to nil and is of + lesser importance, make it an optional argument and place it after + the folder and search-regexp arguments. Sync docstring with + manual. + (mh-search-mode-map): Autoload so that keys are shown in help even + before mh-search is loaded. + (mh-search-mode): Sync docstring with manual. + (mh-index-do-search): Rename argument indexer to searcher. Sync + docstring with manual. + (mh-pick-do-search): Sync docstring with manual. + (mh-index-p): Rename to mh-search-p. + (mh-indexer-choices): Rename to mh-search-choices. + (mh-index-choose): Rename to mh-search-choose. Rename argument + indexer to searcher. + (mh-swish++-execute-search, mh-swish-execute-search) + (mh-mairix-execute-search, mh-namazu-execute-search): Drop "and + read the results" from docstring since these functions don't. + (mh-pick-execute-search, mh-grep-execute-search): Sync docstring + with manual. + (mh-index-generate-pretty-name): Prune -search from string so that + folder names for pick searches are the same as those of other + searches. + +2006-01-13 Bill Wohler + + * mh-acros.el (require): Added Satyaki's comment regarding what + needs to happen to remove this defadvice which caused a little + discussion on emacs-devel today (see Subject: mh-e/mh-acros.el + advices `require' incorrectly). + + * mh-search.el (mh-index-next-result-function): Add format to + docstring. + (mh-mairix-next-result): Use nil instead of () which doesn't stand + out as well. + (mh-pick-execute-search): Operate across all folders if no folder + given and recurse folder(s). + (mh-pick-next-result): Handle new output. + + * mh-utils.el: (mh-collect-folder-names): Fix docstring. + (mh-children-p, mh-folder-list): New functions. + +2006-01-12 Bill Wohler + + * mh-search.el: New file containing contents of mh-index.el and + mh-pick.el. C-c C-c launches your mh-index-program; C-c C-p runs + pick. Pick no longer sets the "search" sequence. Instead, it + brings up a folder view that we're accustomed to. (closes SF + #829207). + (mh-index-search): Rename to mh-search. + (mh-pick-menu): Rename menu from Pick to Search. Rename Execute + the Search to Perform Search and call mh-do-search. Add Search + with Pick menu item. + (mh-do-search): Delete. + (mh-search-mode): Rename from mh-pick-mode. + (MH-Search): Rename mode from MH-Pick. + (mh-search-mode-map): Rename from mh-pick-mode-map. + (mh-search-mode-help-messages): Rename from + mh-pick-mode-help-messages. + (mh-index-choose): Don't reuse the last value of mh-indexer; when + mh-pick-do-search sets it to 'pick, we don't necessarily want to + stay with that choice! + + * mh-index.el: + * mh-pick.el: Merge into mh-search.el and delete. + + * mh-customize.el (mh-index-program): Change mh-index-search to + mh-search in docstring. + (mh-tool-bar-search-function): Change default from + mh-search-folder to mh-search. Remove mh-search-folder as choice + and rename mh-index-search choice to mh-search. Fix docstring. + (mh-pick-mode-hook): Rename to mh-search-mode-hook and change + mh-search-folder to mh-search in docstring. + + * mh-e.el (mh-folder-folder-menu): Delete Search a Folder. Change + Indexed Search to Search. Use mh-search instead of + mh-index-search. + (mh-folder-map): Delete i (mh-index-search) keybinding. Change s + from mh-show-search-folder to mh-search. + + * mh-seq.el (mh-put-msg-in-seq): Fix docstring now that + mh-search-folder no longer creates the search sequence. + + * mh-utils.el (mh-show-search-folder): Delete. + (mh-show-folder-map): Delete i (mh-index-search) keybinding. + Change s from mh-show-search-folder to mh-search. + (mh-show-folder-menu): Delete Search a Folder. Change Indexed + Search to Search. Use mh-search instead of mh-index-search. + (mh-index-max-cmdline-args, mh-xargs, mh-quote-for-shell): Move + here from deleted mh-index.el. + +2006-01-11 Bill Wohler + + * mh-acros.el (mh-defun-compat, mh-defmacro-compat): Move here + from mh-gnus.el. + + * mh-gnus.el: Require mh-acros. + (mh-defmacro-compat, mh-defun-compat): Move to mh-acros.el. + + * mh-utils.el (mh-x-image-url-cache-canonicalize): Use + url-hexify-string to remove special characters from filenames + (closes SF #1396499). Note that this invalidates the existing + names in your cache so you might as well remove + ~/Mail/.mhe-x-image-cache/* now. + (url-unreserved-chars, url-hexify-string): Define if not defined. + Copied from url-util.el in Emacs22 for Emacs 21. + + * mh-buffers.el: New file. Contains constants and code from + mh-index.el and mh-utils.el. + + * mh-alias.el: + * mh-comp.el: + * mh-e.el: + * mh-funcs.el: + * mh-init.el: + * mh-junk.el: + * mh-mime.el: + * mh-print.el: + * mh-seq.el: Require new file mh-buffers.el. + + * mh-index.el: Require new file mh-buffers.el. + (mh-index-temp-buffer, mh-checksum-buffer): Move to new file + mh-buffers.el. + + * mh-utils.el: Require new file mh-buffers.el. + (mh-temp-buffer, mh-temp-fetch-buffer) + (mh-aliases-buffer, mh-folders-buffer, mh-help-buffer) + (mh-info-buffer, mh-log-buffer, mh-mail-delivery-buffer) + (mh-recipients-buffer, mh-sequences-buffer, mh-log-buffer-lines) + (mh-truncate-log-buffer): Move to new file mh-buffers.el. + + * mh-comp.el (mh-forward): Cosmetics on prompt when draft exists. + (mh-send-letter): Add -msgid to mh-send-args (closes SF #725425). + 2006-01-10 Bill Wohler + * mh-comp.el (mh-insert-letter): If you choose a different folder, + the cur message is used. Sync docstring with manual (closes SF + #1205890). + + * mh-mime.el (mh-compose-forward): Use standard range argument + instead of messages. Use more powerful mh-read-range instead of + read-string. Sync docstring with manual (close SF #1205890). + * mh-index.el (mh-index-search): Checking mh-find-path-run is unnecessary. + (mh-index-next-folder): Don't back up a line when going backwards + since this skips the current folder heading if point is on the + first message after the folder heading (closes SF #1126188). * mh-init.el (mh-sys-path): Co-locate with mh-variants, which uses it. diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-acros.el --- a/lisp/mh-e/mh-acros.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-acros.el Tue Jan 17 00:56:42 2006 +0000 @@ -1,6 +1,6 @@ ;;; mh-acros.el --- Macros used in MH-E -;; Copyright (C) 2004 Free Software Foundation, Inc. +;; Copyright (C) 2004, 2006 Free Software Foundation, Inc. ;; Author: Satyaki Das ;; Maintainer: Bill Wohler @@ -74,6 +74,26 @@ `(when (fboundp ',function) (funcall ',function ,@args)))) +(defmacro mh-defun-compat (function arg-list &rest body) + "This is a macro to define functions which are not defined. +It is used for functions which were added to Emacs recently. +If FUNCTION is not defined then it is defined to have argument +list, ARG-LIST and body, BODY." + (let ((defined-p (fboundp function))) + (unless defined-p + `(defun ,function ,arg-list ,@body)))) +(put 'mh-defun-compat 'lisp-indent-function 'defun) + +(defmacro mh-defmacro-compat (function arg-list &rest body) + "This is a macro to define functions which are not defined. +It is used for macros which were added to Emacs recently. +If FUNCTION is not defined then it is defined to have argument +list, ARG-LIST and body, BODY." + (let ((defined-p (fboundp function))) + (unless defined-p + `(defmacro ,function ,arg-list ,@body)))) +(put 'mh-defmacro-compat 'lisp-indent-function 'defun) + (defmacro mh-make-local-hook (hook) "Make HOOK local if needed. XEmacs and versions of GNU Emacs before 21.1 require @@ -130,6 +150,9 @@ (list 'nth ,x z))) (quote ,struct-name)))) +;; A better solution would be to use Stefan's change in bytecomp.el. +;; If it were checked in, we can drop the advice to require and it +;; will make things nicer elsewhere too. (defadvice require (around mh-prefer-el activate) "Modify `require' to load uncompiled MH-E files." (or (featurep (ad-get-arg 0)) diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-alias.el --- a/lisp/mh-e/mh-alias.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-alias.el Tue Jan 17 00:56:42 2006 +0000 @@ -31,9 +31,12 @@ ;;; Code: +;;(message "> mh-alias") (eval-when-compile (require 'mh-acros)) (mh-require-cl) +(require 'mh-buffers) (require 'mh-e) +;;(message "< mh-alias") (load "cmr" t t) ; Non-fatal dependency for ; completing-read-multiple. (eval-when-compile (defvar mail-abbrev-syntax-table)) diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-buffers.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/mh-e/mh-buffers.el Tue Jan 17 00:56:42 2006 +0000 @@ -0,0 +1,90 @@ +;;; mh-buffers.el --- Temporary buffer constants and utilities used by MH-E + +;; Copyright (C) 1993, 1995, 1997, +;; 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + +;; Author: Bill Wohler +;; Maintainer: Bill Wohler +;; Keywords: mail +;; See: mh-e.el + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; Temporary buffer constants and utilities used by MH-E. + +;;; Change Log: + +;;; Code: + +;; The names of ephemeral buffers have a " *mh-" prefix (so that they +;; are hidden and can be programmatically removed in mh-quit), and the +;; variable names have the form mh-temp-.*-buffer. +(defconst mh-temp-buffer " *mh-temp*") ;scratch +(defconst mh-temp-checksum-buffer " *mh-checksum*") +(defconst mh-temp-fetch-buffer " *mh-fetch*") ;wget/curl/fetch output +(defconst mh-temp-index-buffer " *mh-index*") + +;; The names of MH-E buffers that are not ephemeral and can be used by +;; the user (and deleted by the user when no longer needed) have a +;; "*MH-E " prefix (so they can be programmatically removed in +;; mh-quit), and the variable names have the form mh-.*-buffer. +;; Temporary buffers for search results +(defconst mh-aliases-buffer "*MH-E Aliases*") ;alias lookups +(defconst mh-folders-buffer "*MH-E Folders*") ;folder list +(defconst mh-help-buffer "*MH-E Help*") ;quick help +(defconst mh-info-buffer "*MH-E Info*") ;version information buffer +(defconst mh-log-buffer "*MH-E Log*") ;output of MH commands and so on +(defconst mh-mail-delivery-buffer "*MH-E Mail Delivery*") ;mail delivery log +(defconst mh-recipients-buffer "*MH-E Recipients*") ;killed when draft sent +(defconst mh-sequences-buffer "*MH-E Sequences*") ;sequences list + +(defvar mh-log-buffer-lines 100 + "Number of lines to keep in `mh-log-buffer'.") + + + +(defun mh-truncate-log-buffer () + "If `mh-log-buffer' is too big then truncate it. +If the number of lines in `mh-log-buffer' exceeds +`mh-log-buffer-lines' then keep only the last +`mh-log-buffer-lines'. As a side effect the point is set to the +end of the log buffer. + +The function returns the size of the final size of the log buffer." + (with-current-buffer (get-buffer-create mh-log-buffer) + (goto-char (point-max)) + (save-excursion + (when (equal (forward-line (- mh-log-buffer-lines)) 0) + (delete-region (point-min) (point)))) + (unless (or (bobp) + (save-excursion + (and (equal (forward-line -1) 0) (equal (char-after) ? )))) + (insert "\n \n")) + (buffer-size))) + +(provide 'mh-buffers) + +;; Local Variables: +;; indent-tabs-mode: nil +;; sentence-end-double-space: nil +;; End: + +;; arch-tag: 812e9f29-78b8-4e73-ada9-aa61dc1ceecb +;;; mh-buffers.el ends here diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-comp.el --- a/lisp/mh-e/mh-comp.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-comp.el Tue Jan 17 00:56:42 2006 +0000 @@ -33,16 +33,19 @@ ;;; Code: +;;(message "> mh-comp") (eval-when-compile (require 'mh-acros)) (mh-require-cl) (require 'easymenu) (require 'gnus-util) +(require 'mh-buffers) (require 'mh-e) (require 'mh-gnus) (eval-when (compile load eval) (ignore-errors (require 'mailabbrev))) +;;(message "< mh-comp") @@ -378,7 +381,7 @@ ;; forw always leaves file in "draft" since it doesn't have -draft (draft-name (expand-file-name "draft" mh-user-path)) (draft (cond ((or (not (file-exists-p draft-name)) - (y-or-n-p "The file 'draft' exists. Discard it? ")) + (y-or-n-p "The file draft exists; discard it? ")) (mh-exec-cmd "forw" "-build" (if (and (mh-variant-p 'nmh) mh-compose-forward-as-mime-flag) @@ -861,6 +864,9 @@ ;;; Mode for composing and sending a draft message. +(defvar mh-pgp-support-flag (not (not (locate-library "mml2015"))) + "Non-nil means PGP support is available.") + (put 'mh-letter-mode 'mode-class 'special) ;; Menu extracted from mh-menubar.el V1.1 (31 July 2001) @@ -1475,12 +1481,16 @@ (and (boundp 'default-buffer-file-coding-system ) default-buffer-file-coding-system) 'iso-latin-1)))) + ;; Adding a Message-ID field looks good, makes it easier to search for + ;; message in your +outbox, and best of all doesn't break threading for + ;; the recipient if you reply to a message in your +outbox. + (setq mh-send-args (concat "-msgid " mh-send-args)) ;; The default BCC encapsulation will make a MIME message unreadable. ;; With nmh use the -mime arg to prevent this. (if (and (mh-variant-p 'nmh) (mh-goto-header-field "Bcc:") (mh-goto-header-field "Content-Type:")) - (setq mh-send-args (format "-mime %s" mh-send-args))) + (setq mh-send-args (concat "-mime " mh-send-args))) (cond (arg (pop-to-buffer mh-mail-delivery-buffer) (erase-buffer) @@ -1514,23 +1524,33 @@ (defun mh-insert-letter (folder message verbatim) "Insert a message. -This command prompts you for the FOLDER and MESSAGE number and inserts +This command prompts you for the FOLDER and MESSAGE number, which +defaults to the current message in that folder. It then inserts the message, indented by `mh-ins-buf-prefix' (\"> \") unless -`mh-yank-behavior' is set to one of the supercite flavors in which -case supercite is used to format the message. Certain undesirable -header fields (see `mh-invisible-header-fields-compiled') are removed -before insertion. +`mh-yank-behavior' is set to one of the supercite flavors in +which case supercite is used to format the message. Certain +undesirable header fields (see +`mh-invisible-header-fields-compiled') are removed before +insertion. If given a prefix argument VERBATIM, the header is left intact, the message is not indented, and \"> \" is not inserted before each line. This command leaves the mark before the letter and point after it." (interactive - (list (mh-prompt-for-folder "Message from" mh-sent-from-folder nil) - (read-string (concat "Message number" - (if (numberp mh-sent-from-msg) - (format " (default %d): " mh-sent-from-msg) - ": "))) - current-prefix-arg)) + (let* ((folder + (mh-prompt-for-folder "Message from" + mh-sent-from-folder nil)) + (default + (if (and (equal folder mh-sent-from-folder) + (numberp mh-sent-from-msg)) + mh-sent-from-msg + (nth 0 (mh-translate-range folder "cur")))) + (message + (read-string (concat "Message number" + (or (and default + (format " (default %d): " default)) + ": "))))) + (list folder message current-prefix-arg))) (save-restriction (narrow-to-region (point) (point)) (let ((start (point-min))) diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-customize.el --- a/lisp/mh-e/mh-customize.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-customize.el Tue Jan 17 00:56:42 2006 +0000 @@ -63,6 +63,7 @@ ;;; Code: +;;(message "> mh-customize") (provide 'mh-customize) (eval-when-compile (require 'mh-acros)) @@ -78,6 +79,7 @@ (require 'mh-identity) (require 'mh-init) (require 'mh-loaddefs)) +;;(message "< mh-customize") ;; For compiler warnings... (eval-when-compile @@ -134,12 +136,6 @@ :link '(custom-manual "(mh-e)Incorporating Mail") :group 'mh-e) -(defgroup mh-index nil - "Searching." - :link '(custom-manual "(mh-e)Searching") - :prefix "mh-index-" - :group 'mh-e) - (defgroup mh-junk nil "Dealing with junk mail." :link '(custom-manual "(mh-e)Junk") @@ -164,6 +160,12 @@ :prefix "mh-" :group 'mh-e) +(defgroup mh-search nil + "Searching." + :link '(custom-manual "(mh-e)Searching") + :prefix "mh-search-" + :group 'mh-e) + (defgroup mh-sending-mail nil "Sending mail." :prefix "mh-" @@ -713,30 +715,6 @@ -;;; Searching (:group 'mh-index) - -(defcustom mh-index-program nil - "Indexing program that MH-E shall use. - -The default setting of this option is \"Auto-detect\" which means -that MH-E will automatically choose one of swish++, swish-e, -mairix, namazu, pick and grep in that order. If, for example, you -have both swish++ and mairix installed and you want to use -mairix, then you can set this option to \"mairix\". - -More information about setting up an indexing program to use with -MH-E can be found in the documentation of `mh-index-search'." - :type '(choice (const :tag "Auto-detect" nil) - (const :tag "swish++" swish++) - (const :tag "swish-e" swish) - (const :tag "mairix" mairix) - (const :tag "namazu" namazu) - (const :tag "pick" pick) - (const :tag "grep" grep)) - :group 'mh-index) - - - ;;; Dealing with Junk Mail (:group 'mh-junk) ;; Spam fighting program chosen @@ -1114,6 +1092,30 @@ +;;; Searching (:group 'mh-search) + +(defcustom mh-search-program nil + "Search program that MH-E shall use. + +The default setting of this option is \"Auto-detect\" which means +that MH-E will automatically choose one of swish++, swish-e, +mairix, namazu, pick and grep in that order. If, for example, you +have both swish++ and mairix installed and you want to use +mairix, then you can set this option to \"mairix\". + +More information about setting up an indexing program to use with +MH-E can be found in the documentation of `mh-search'." + :type '(choice (const :tag "Auto-detect" nil) + (const :tag "swish++" swish++) + (const :tag "swish-e" swish) + (const :tag "mairix" mairix) + (const :tag "namazu" namazu) + (const :tag "pick" pick) + (const :tag "grep" grep)) + :group 'mh-search) + + + ;;; Sending Mail (:group 'mh-sending-mail) (defcustom mh-compose-forward-as-mime-flag t @@ -1879,14 +1881,13 @@ ;;; The Tool Bar (:group 'mh-tool-bar) -(defcustom mh-tool-bar-search-function 'mh-search-folder +(defcustom mh-tool-bar-search-function 'mh-search "*Function called by the tool bar search button. -Available functions include `mh-search-folder', the default, and -`mh-index-search'. You can also choose \"Other Function\" from -the \"Value Menu\" and enter a function of your own choosing." - :type '(choice (const mh-search-folder) - (const mh-index-search) +By default, this is set to `mh-search'. You can also choose +\"Other Function\" from the \"Value Menu\" and enter a function +of your own choosing." + :type '(choice (const mh-search) (function :tag "Other Function")) :group 'mh-tool-bar) @@ -2401,15 +2402,15 @@ :group 'mh-hooks :group 'mh-letter) -(defcustom mh-kill-folder-suppress-prompt-hooks '(mh-index-p) +(defcustom mh-kill-folder-suppress-prompt-hooks '(mh-search-p) "Abnormal hook run at the beginning of \\\\[mh-kill-folder]. The hook functions are called with no arguments and should return a non-nil value to suppress the normal prompt when you remove a folder. This is useful for folders that are easily regenerated. -The default value of `mh-index-p' suppresses the prompt on -folders generated by an index search. +The default value of `mh-search-p' suppresses the prompt on +folders generated by searching. WARNING: Use this hook with care. If there is a bug in your hook which returns t on \"+inbox\" and you hit \\[mh-kill-folder] by @@ -2436,16 +2437,16 @@ :group 'mh-hooks :group 'mh-letter) -(defcustom mh-pick-mode-hook nil - "Hook run upon entry to `mh-pick-mode'\\. +(defcustom mh-search-mode-hook nil + "Hook run upon entry to `mh-search-mode'\\. If you find that you do the same thing over and over when editing the search template, you may wish to bind some shortcuts to keys. This can be done with this hook which is called when -\\[mh-search-folder] is run on a new pattern." +\\[mh-search] is run on a new pattern." :type 'hook :group 'mh-hooks - :group 'mh-index) + :group 'mh-search) (defcustom mh-quit-hook nil "Hook run by \\\\[mh-quit] after quitting MH-E. @@ -2630,7 +2631,7 @@ :group 'mh-faces :group 'mh-folder) -(defface mh-index-folder +(defface mh-search-folder '((((class color) (background light)) (:foreground "dark green" :bold t)) (((class color) (background dark)) @@ -2639,7 +2640,7 @@ (:bold t))) "Folder heading face in MH-Folder buffers created by searches." :group 'mh-faces - :group 'mh-index) + :group 'mh-search) (defface mh-letter-header-field '((((class color) (background light)) diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-e.el --- a/lisp/mh-e/mh-e.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-e.el Tue Jan 17 00:56:42 2006 +0000 @@ -85,6 +85,7 @@ ;;; Code: +;;(message "> mh-e") (provide 'mh-e) (eval-when-compile (require 'mh-acros)) @@ -92,8 +93,10 @@ (require 'easymenu) (require 'gnus-util) +(require 'mh-buffers) (require 'mh-seq) (require 'mh-utils) +;;(message "< mh-e") (defconst mh-version "7.85+cvs" "Version number of MH-E.") @@ -330,7 +333,7 @@ (list ;; Folders when displaying index buffer (list "^\\+.*" - '(0 'mh-index-folder)) + '(0 'mh-search-folder)) ;; Marked for deletion (list (concat mh-scan-deleted-msg-regexp ".*") '(0 'mh-folder-deleted)) @@ -1734,8 +1737,7 @@ ["List Folders" mh-list-folders t] ["Visit a Folder..." mh-visit-folder t] ["View New Messages" mh-index-new-messages t] - ["Search a Folder..." mh-search-folder t] - ["Indexed Search..." mh-index-search t] + ["Search..." mh-search t] "--" ["Quit MH-E" mh-quit t])) @@ -1861,9 +1863,9 @@ 'mh-folder-view-stack () ; Stack of previous views of the ; folder. 'mh-index-data nil ; If the folder was created by a call - ; to mh-index-search this contains info + ; to mh-search, this contains info ; about the search results. - 'mh-index-previous-search nil ; Previous folder and search-regexp + 'mh-index-previous-search nil ; folder, indexer, search-regexp 'mh-index-msg-checksum-map nil ; msg -> checksum map 'mh-index-checksum-origin-map nil ; checksum -> ( orig-folder, orig-msg ) 'mh-index-sequence-search-flag nil ; folder resulted from sequence search @@ -2704,7 +2706,6 @@ "S" mh-sort-folder "c" mh-catchup "f" mh-alt-visit-folder - "i" mh-index-search "k" mh-kill-folder "l" mh-list-folders "n" mh-index-new-messages @@ -2712,7 +2713,7 @@ "p" mh-pack-folder "q" mh-index-sequenced-messages "r" mh-rescan-folder - "s" mh-search-folder + "s" mh-search "u" mh-undo-folder "v" mh-visit-folder) @@ -2755,8 +2756,8 @@ "'" mh-narrow-to-tick "?" mh-prefix-help "c" mh-narrow-to-cc - "f" mh-narrow-to-from - "r" mh-narrow-to-range + "g" mh-narrow-to-range + "m" mh-narrow-to-from "s" mh-narrow-to-subject "t" mh-narrow-to-to "w" mh-widen) @@ -2814,7 +2815,7 @@ "\n [T]hread, [/]limit, e[X]tract, [D]igest, [I]nc spools.") (?F "[l]ist; [v]isit folder;\n" - "[n]ew messages; [']ticked messages; [s]earch; [i]ndexed search;\n" + "[n]ew messages; [']ticked messages; [s]earch;\n" "[p]ack; [S]ort; [r]escan; [k]ill") (?P "[p]rint message to [f]ile; old-style [l]pr printing;\n" "Toggle printing of [C]olors, [F]aces") @@ -2822,7 +2823,7 @@ "[s]equences, [l]ist,\n" "[d]elete message from sequence, [k]ill sequence") (?T "[t]oggle, [d]elete, [o]refile thread") - (?/ "Limit to [c]c, [f]rom, [r]ange, [s]ubject, [t]o; [w]iden") + (?/ "Limit to [c]c, ran[g]e, fro[m], [s]ubject, [t]o; [w]iden") (?X "un[s]har, [u]udecode message") (?D "[b]urst digest") (?K "[v]iew, [i]nline, [o]utput/save MIME part; save [a]ll parts; \n" diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-exec.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/mh-e/mh-exec.el Tue Jan 17 00:56:42 2006 +0000 @@ -0,0 +1,264 @@ +;;; mh-exec.el --- MH-E process support + +;; Copyright (C) 1993, 1995, 1997, +;; 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + +;; Author: Bill Wohler +;; Maintainer: Bill Wohler +;; Keywords: mail +;; See: mh-e.el + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; Issue shell and MH commands + +;;; Change Log: + +;;; Code: + +(eval-when-compile (require 'mh-acros)) +(mh-require-cl) + +(require 'mh-buffers) +(require 'mh-utils) + +(defvar mh-progs nil + "Directory containing MH commands, such as inc, repl, and rmm.") + +;;;###autoload +(put 'mh-progs 'risky-local-variable t) + +(defvar mh-lib nil + "Directory containing the MH library. +This directory contains, among other things, the components file.") + +;;;###autoload +(put 'mh-lib 'risky-local-variable t) + +(defvar mh-lib-progs nil + "Directory containing MH helper programs. +This directory contains, among other things, the mhl program.") + +;;;###autoload +(put 'mh-lib-progs 'risky-local-variable t) + +(defvar mh-index-max-cmdline-args 500 + "Maximum number of command line args.") + +(defun mh-xargs (cmd &rest args) + "Partial imitation of xargs. +The current buffer contains a list of strings, one on each line. +The function will execute CMD with ARGS and pass the first +`mh-index-max-cmdline-args' strings to it. This is repeated till +all the strings have been used." + (goto-char (point-min)) + (let ((current-buffer (current-buffer))) + (with-temp-buffer + (let ((out (current-buffer))) + (set-buffer current-buffer) + (while (not (eobp)) + (let ((arg-list (reverse args)) + (count 0)) + (while (and (not (eobp)) (< count mh-index-max-cmdline-args)) + (push (buffer-substring-no-properties (point) (line-end-position)) + arg-list) + (incf count) + (forward-line)) + (apply #'call-process cmd nil (list out nil) nil + (nreverse arg-list)))) + (erase-buffer) + (insert-buffer-substring out))))) + +;; XXX This should be applied anywhere MH-E calls out to /bin/sh. +(defun mh-quote-for-shell (string) + "Quote STRING for /bin/sh. +Adds double-quotes around entire string and quotes the characters +\\, `, and $ with a backslash." + (concat "\"" + (loop for x across string + concat (format (if (memq x '(?\\ ?` ?$)) "\\%c" "%c") x)) + "\"")) + +(defun mh-exec-cmd (command &rest args) + "Execute mh-command COMMAND with ARGS. +The side effects are what is desired. Any output is assumed to be +an error and is shown to the user. The output is not read or +parsed by MH-E." + (save-excursion + (set-buffer (get-buffer-create mh-log-buffer)) + (let* ((initial-size (mh-truncate-log-buffer)) + (start (point)) + (args (mh-list-to-string args))) + (apply 'call-process (expand-file-name command mh-progs) nil t nil args) + (when (> (buffer-size) initial-size) + (save-excursion + (goto-char start) + (insert "Errors when executing: " command) + (loop for arg in args do (insert " " arg)) + (insert "\n")) + (save-window-excursion + (switch-to-buffer-other-window mh-log-buffer) + (sit-for 5)))))) + +(defun mh-exec-cmd-error (env command &rest args) + "In environment ENV, execute mh-command COMMAND with ARGS. +ENV is nil or a string of space-separated \"var=value\" elements. +Signals an error if process does not complete successfully." + (save-excursion + (set-buffer (get-buffer-create mh-temp-buffer)) + (erase-buffer) + (let ((process-environment process-environment)) + ;; XXX: We should purge the list that split-string returns of empty + ;; strings. This can happen in XEmacs if leading or trailing spaces + ;; are present. + (dolist (elem (if (stringp env) (split-string env " ") ())) + (push elem process-environment)) + (mh-handle-process-error + command (apply #'call-process (expand-file-name command mh-progs) + nil t nil (mh-list-to-string args)))))) + +(defun mh-exec-cmd-daemon (command filter &rest args) + "Execute MH command COMMAND in the background. + +If FILTER is non-nil then it is used to process the output +otherwise the default filter `mh-process-daemon' is used. See +`set-process-filter' for more details of FILTER. + +ARGS are passed to COMMAND as command line arguments." + (save-excursion + (set-buffer (get-buffer-create mh-log-buffer)) + (mh-truncate-log-buffer)) + (let* ((process-connection-type nil) + (process (apply 'start-process + command nil + (expand-file-name command mh-progs) + (mh-list-to-string args)))) + (set-process-filter process (or filter 'mh-process-daemon)) + process)) + +(defun mh-exec-cmd-env-daemon (env command filter &rest args) + "In ennvironment ENV, execute mh-command COMMAND in the background. + +ENV is nil or a string of space-separated \"var=value\" elements. +Signals an error if process does not complete successfully. + +If FILTER is non-nil then it is used to process the output +otherwise the default filter `mh-process-daemon' is used. See +`set-process-filter' for more details of FILTER. + +ARGS are passed to COMMAND as command line arguments." + (let ((process-environment process-environment)) + (dolist (elem (if (stringp env) (split-string env " ") ())) + (push elem process-environment)) + (apply #'mh-exec-cmd-daemon command filter args))) + +(defun mh-process-daemon (process output) + "PROCESS daemon that puts OUTPUT into a temporary buffer. +Any output from the process is displayed in an asynchronous +pop-up window." + (with-current-buffer (get-buffer-create mh-log-buffer) + (insert-before-markers output) + (display-buffer mh-log-buffer))) + +(defun mh-exec-cmd-quiet (raise-error command &rest args) + "Signal RAISE-ERROR if COMMAND with ARGS fails. +Execute MH command COMMAND with ARGS. ARGS is a list of strings. +Return at start of mh-temp buffer, where output can be parsed and +used. +Returns value of `call-process', which is 0 for success, unless +RAISE-ERROR is non-nil, in which case an error is signaled if +`call-process' returns non-0." + (set-buffer (get-buffer-create mh-temp-buffer)) + (erase-buffer) + (let ((value + (apply 'call-process + (expand-file-name command mh-progs) nil t nil + args))) + (goto-char (point-min)) + (if raise-error + (mh-handle-process-error command value) + value))) + +;; Shush compiler. +(eval-when-compile (defvar mark-active)) + +(defun mh-exec-cmd-output (command display &rest args) + "Execute MH command COMMAND with DISPLAY flag and ARGS. +Put the output into buffer after point. +Set mark after inserted text. +Output is expected to be shown to user, not parsed by MH-E." + (push-mark (point) t) + (apply 'call-process + (expand-file-name command mh-progs) nil t display + (mh-list-to-string args)) + + ;; The following is used instead of 'exchange-point-and-mark because the + ;; latter activates the current region (between point and mark), which + ;; turns on highlighting. So prior to this bug fix, doing "inc" would + ;; highlight a region containing the new messages, which is undesirable. + ;; The bug wasn't seen in emacs21 but still occurred in XEmacs21.4. + (mh-exchange-point-and-mark-preserving-active-mark)) + +(defun mh-exchange-point-and-mark-preserving-active-mark () + "Put the mark where point is now, and point where the mark is now. +This command works even when the mark is not active, and +preserves whether the mark is active or not." + (interactive nil) + (let ((is-active (and (boundp 'mark-active) mark-active))) + (let ((omark (mark t))) + (if (null omark) + (error "No mark set in this buffer")) + (set-mark (point)) + (goto-char omark) + (if (boundp 'mark-active) + (setq mark-active is-active)) + nil))) + +(defun mh-exec-lib-cmd-output (command &rest args) + "Execute MH library command COMMAND with ARGS. +Put the output into buffer after point. +Set mark after inserted text." + (apply 'mh-exec-cmd-output (expand-file-name command mh-lib-progs) nil args)) + +(defun mh-handle-process-error (command status) + "Raise error if COMMAND returned non-zero STATUS, otherwise return STATUS." + (if (equal status 0) + status + (goto-char (point-min)) + (insert (if (integerp status) + (format "%s: exit code %d\n" command status) + (format "%s: %s\n" command status))) + (save-excursion + (let ((error-message (buffer-substring (point-min) (point-max)))) + (set-buffer (get-buffer-create mh-log-buffer)) + (mh-truncate-log-buffer) + (insert error-message))) + (error "%s failed, check buffer %s for error message" + command mh-log-buffer))) + +(provide 'mh-exec) + +;; Local Variables: +;; indent-tabs-mode: nil +;; sentence-end-double-space: nil +;; End: + +;; arch-tag: 2857996c-e624-46b2-a58d-979cd279d288 +;;; mh-utils.el ends here diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-funcs.el --- a/lisp/mh-e/mh-funcs.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-funcs.el Tue Jan 17 00:56:42 2006 +0000 @@ -35,9 +35,12 @@ ;;; Code: +;;(message "> mh-funcs") (eval-when-compile (require 'mh-acros)) (mh-require-cl) +(require 'mh-buffers) (require 'mh-e) +;;(message "< mh-funcs") diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-gnus.el --- a/lisp/mh-e/mh-gnus.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-gnus.el Tue Jan 17 00:56:42 2006 +0000 @@ -1,6 +1,6 @@ ;;; mh-gnus.el --- Make MH-E compatible with installed version of Gnus. -;; Copyright (C) 2003, 2004 Free Software Foundation, Inc. +;; Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. ;; Author: Satyaki Das ;; Maintainer: Bill Wohler @@ -30,6 +30,10 @@ ;;; Code: +;;(message "> mh-gnus") +(eval-when-compile (require 'mh-acros)) +;;(message "< mh-gnus") + ;; Load libraries in a non-fatal way in order to see if certain functions are ;; pre-defined. (load "mailabbrev" t t) @@ -39,34 +43,14 @@ (load "mml" t t) (load "smiley" t t) -(defmacro mh-defun-compat (function arg-list &rest body) - "This is a macro to define functions which are not defined. -It is used for Gnus utility functions which were added recently. -If FUNCTION is not defined then it is defined to have argument -list, ARG-LIST and body, BODY." - (let ((defined-p (fboundp function))) - (unless defined-p - `(defun ,function ,arg-list ,@body)))) -(put 'mh-defun-compat 'lisp-indent-function 'defun) - -(defmacro mh-defmacro-compat (function arg-list &rest body) - "This is a macro to define functions which are not defined. -It is used for Gnus utility functions which were added recently. -If FUNCTION is not defined then it is defined to have argument -list, ARG-LIST and body, BODY." - (let ((defined-p (fboundp function))) - (unless defined-p - `(defmacro ,function ,arg-list ,@body)))) -(put 'mh-defmacro-compat 'lisp-indent-function 'defun) - -;; Copy of original function from gnus-util.el. +;; Copy of function from gnus-util.el. (mh-defun-compat gnus-local-map-property (map) "Return a list suitable for a text property list specifying keymap MAP." (cond (mh-xemacs-flag (list 'keymap map)) ((>= emacs-major-version 21) (list 'keymap map)) (t (list 'local-map map)))) -;; Copy of original function from mm-decode.el. +;; Copy of function from mm-decode.el. (mh-defun-compat mm-merge-handles (handles1 handles2) (append (if (listp (car handles1)) handles1 (list handles1)) (if (listp (car handles2)) handles2 (list handles2)))) @@ -96,11 +80,11 @@ (mh-defun-compat mm-possibly-verify-or-decrypt (parts ctl) nil) -;; Copy of original macro is in mm-decode.el. +;; Copy of macro in mm-decode.el. (mh-defmacro-compat mm-handle-multipart-ctl-parameter (handle parameter) `(get-text-property 0 ,parameter (car ,handle))) -;; Copy of original function in mm-decode.el. +;; Copy of function in mm-decode.el. (mh-defun-compat mm-readable-p (handle) "Say whether the content of HANDLE is readable." (and (< (with-current-buffer (mm-handle-buffer handle) @@ -110,7 +94,7 @@ (and (eq (mm-body-7-or-8) '7bit) (not (mm-long-lines-p 76)))))) -;; Copy of original function in mm-bodies.el. +;; Copy of function in mm-bodies.el. (mh-defun-compat mm-long-lines-p (length) "Say whether any of the lines in the buffer is longer than LENGTH." (save-excursion @@ -132,7 +116,7 @@ "Older versions of Emacs don't have this function." nil) -;; Copy of original function in mml.el. +;; Copy of function in mml.el. (mh-defun-compat mml-minibuffer-read-disposition (type &optional default) (unless default (setq default (if (and (string-match "\\`text/" type) diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-identity.el --- a/lisp/mh-e/mh-identity.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-identity.el Tue Jan 17 00:56:42 2006 +0000 @@ -39,9 +39,11 @@ ;;; Code: +;;(message "> mh-identity") (eval-when-compile (require 'mh-acros)) (require 'mh-comp) +;;(message "< mh-identity") (autoload 'mml-insert-tag "mml") diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-inc.el --- a/lisp/mh-e/mh-inc.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-inc.el Tue Jan 17 00:56:42 2006 +0000 @@ -34,8 +34,10 @@ ;;; Code: +;;(message "> mh-inc") (eval-when-compile (require 'mh-acros)) (mh-require-cl) +;;(message "< mh-inc") (defvar mh-inc-spool-map (make-sparse-keymap) "Keymap for MH-E's mh-inc-spool commands.") diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-index.el --- a/lisp/mh-e/mh-index.el Thu Jan 12 11:20:02 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1693 +0,0 @@ -;;; mh-index -- MH-E interface to indexing programs - -;; Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. - -;; Author: Satyaki Das -;; Maintainer: Bill Wohler -;; Keywords: mail -;; See: mh-e.el - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -;; Boston, MA 02110-1301, USA. - -;;; Commentary: - -;; (1) The following search engines are supported: -;; swish++ -;; swish-e -;; mairix -;; namazu -;; pick -;; grep -;; -;; (2) To use this package, you first have to build an index. Please read -;; the documentation for `mh-index-search' to get started. That -;; documentation will direct you to the specific instructions for your -;; particular indexer. - -;;; Change Log: - -;;; Code: - -(eval-when-compile (require 'mh-acros)) -(mh-require-cl) - -(require 'mh-e) -(require 'mh-mime) -(require 'mh-pick) - -(autoload 'gnus-local-map-property "gnus-util") -(autoload 'gnus-eval-format "gnus-spec") -(autoload 'widget-convert-button "wid-edit") - -;; Support different indexing programs -(defvar mh-indexer-choices - '((swish++ - mh-swish++-binary mh-swish++-execute-search mh-swish++-next-result - mh-swish++-regexp-builder) - (swish - mh-swish-binary mh-swish-execute-search mh-swish-next-result nil) - (mairix - mh-mairix-binary mh-mairix-execute-search mh-mairix-next-result - mh-mairix-regexp-builder) - (namazu - mh-namazu-binary mh-namazu-execute-search mh-namazu-next-result nil) - (pick - mh-pick-binary mh-pick-execute-search mh-pick-next-result - mh-pick-regexp-builder) - (grep - mh-grep-binary mh-grep-execute-search mh-grep-next-result nil)) - "List of possible indexer choices.") -(defvar mh-indexer nil - "Chosen index program.") -(defvar mh-index-execute-search-function nil - "Function which executes the search program.") -(defvar mh-index-next-result-function nil - "Function to parse the next line of output.") -(defvar mh-index-regexp-builder nil - "Function used to construct search regexp.") - -;; FIXME: This should be a defcustom... -(defvar mh-index-folder "+mhe-index" - "Folder that contains the folders resulting from the index searches.") - -;; Temporary buffers for search results -(defvar mh-index-temp-buffer " *mh-index-temp*") -(defvar mh-checksum-buffer " *mh-checksum-buffer*") - - - -;; A few different checksum programs are supported. The supported programs -;; are: -;; 1. md5sum -;; 2. md5 -;; 3. openssl -;; -;; To add support for your favorite checksum program add a clause to the cond -;; statement in mh-checksum-choose. This should set the variable -;; mh-checksum-cmd to the command line needed to run the checsum program and -;; should set mh-checksum-parser to a function which returns a cons cell -;; containing the message number and checksum string. - -(defvar mh-checksum-cmd) -(defvar mh-checksum-parser) - -(defun mh-checksum-choose () - "Check if a program to create a checksum is present." - (unless (boundp 'mh-checksum-cmd) - (let ((exec-path (append '("/sbin" "/usr/sbin") exec-path))) - (cond ((executable-find "md5sum") - (setq mh-checksum-cmd (list (executable-find "md5sum"))) - (setq mh-checksum-parser #'mh-md5sum-parser)) - ((executable-find "openssl") - (setq mh-checksum-cmd (list (executable-find "openssl") "md5")) - (setq mh-checksum-parser #'mh-openssl-parser)) - ((executable-find "md5") - (setq mh-checksum-cmd (list (executable-find "md5"))) - (setq mh-checksum-parser #'mh-md5-parser)) - (t (error "No suitable checksum program")))))) - -(defun mh-md5sum-parser () - "Parse md5sum output." - (let ((begin (line-beginning-position)) - (end (line-end-position)) - first-space last-slash) - (setq first-space (search-forward " " end t)) - (goto-char end) - (setq last-slash (search-backward "/" begin t)) - (cond ((and first-space last-slash) - (cons (car (read-from-string (buffer-substring-no-properties - (1+ last-slash) end))) - (buffer-substring-no-properties begin (1- first-space)))) - (t (cons nil nil))))) - -(defun mh-openssl-parser () - "Parse openssl output." - (let ((begin (line-beginning-position)) - (end (line-end-position)) - last-space last-slash) - (goto-char end) - (setq last-space (search-backward " " begin t)) - (setq last-slash (search-backward "/" begin t)) - (cond ((and last-slash last-space) - (cons (car (read-from-string (buffer-substring-no-properties - (1+ last-slash) (1- last-space)))) - (buffer-substring-no-properties (1+ last-space) end)))))) - -(defalias 'mh-md5-parser 'mh-openssl-parser) - - - -;; Make sure that we don't produce too long a command line. -(defvar mh-index-max-cmdline-args 500 - "Maximum number of command line args.") - -(defun mh-index-execute (cmd &rest args) - "Partial imitation of xargs. -The current buffer contains a list of strings, one on each line. -The function will execute CMD with ARGS and pass the first -`mh-index-max-cmdline-args' strings to it. This is repeated till -all the strings have been used." - (goto-char (point-min)) - (let ((current-buffer (current-buffer))) - (with-temp-buffer - (let ((out (current-buffer))) - (set-buffer current-buffer) - (while (not (eobp)) - (let ((arg-list (reverse args)) - (count 0)) - (while (and (not (eobp)) (< count mh-index-max-cmdline-args)) - (push (buffer-substring-no-properties (point) (line-end-position)) - arg-list) - (incf count) - (forward-line)) - (apply #'call-process cmd nil (list out nil) nil - (nreverse arg-list)))) - (erase-buffer) - (insert-buffer-substring out))))) - - - -(defun mh-index-update-single-msg (msg checksum origin-map) - "Update various maps for one message. -MSG is a index folder message, CHECKSUM its MD5 hash and -ORIGIN-MAP, if non-nil, a hashtable containing which maps each -message in the index folder to the folder and message that it was -copied from. The function updates the hash tables -`mh-index-msg-checksum-map' and `mh-index-checksum-origin-map'. - -This function should only be called in the appropriate index -folder buffer." - (cond ((and origin-map (gethash checksum mh-index-checksum-origin-map)) - (let* ((intermediate (gethash msg origin-map)) - (ofolder (car intermediate)) - (omsg (cdr intermediate))) - ;; This is most probably a duplicate. So eliminate it. - (call-process "rm" nil nil nil - (format "%s%s/%s" mh-user-path - (substring mh-current-folder 1) msg)) - (when (gethash ofolder mh-index-data) - (remhash omsg (gethash ofolder mh-index-data))))) - (t - (setf (gethash msg mh-index-msg-checksum-map) checksum) - (when origin-map - (setf (gethash checksum mh-index-checksum-origin-map) - (gethash msg origin-map)))))) - -;;;###mh-autoload -(defun mh-index-update-maps (folder &optional origin-map) - "Annotate all as yet unannotated messages in FOLDER with their MD5 hash. -As a side effect msg -> checksum map is updated. Optional -argument ORIGIN-MAP is a hashtable which maps each message in the -index folder to the original folder and message from whence it -was copied. If present the checksum -> (origin-folder, -origin-index) map is updated too." - (clrhash mh-index-msg-checksum-map) - (save-excursion - ;; Clear temp buffer - (set-buffer (get-buffer-create mh-checksum-buffer)) - (erase-buffer) - ;; Run scan to check if any messages needs MD5 annotations at all - (with-temp-buffer - (mh-exec-cmd-output mh-scan-prog nil "-width" "80" - "-format" "%(msg)\n%{x-mhe-checksum}\n" - folder "all") - (goto-char (point-min)) - (let (msg checksum) - (while (not (eobp)) - (setq msg (buffer-substring-no-properties - (point) (line-end-position))) - (forward-line) - (save-excursion - (cond ((not (string-match "^[0-9]*$" msg))) - ((eolp) - ;; need to compute checksum - (set-buffer mh-checksum-buffer) - (insert mh-user-path (substring folder 1) "/" msg "\n")) - (t - ;; update maps - (setq checksum (buffer-substring-no-properties - (point) (line-end-position))) - (let ((msg (car (read-from-string msg)))) - (set-buffer folder) - (mh-index-update-single-msg msg checksum origin-map))))) - (forward-line)))) - ;; Run checksum program if needed - (unless (and (eobp) (bobp)) - (apply #'mh-index-execute mh-checksum-cmd) - (goto-char (point-min)) - (while (not (eobp)) - (let* ((intermediate (funcall mh-checksum-parser)) - (msg (car intermediate)) - (checksum (cdr intermediate))) - (when msg - ;; annotate - (mh-exec-cmd "anno" folder msg "-component" "X-MHE-Checksum" - "-nodate" "-text" checksum "-inplace") - ;; update maps - (save-excursion - (set-buffer folder) - (mh-index-update-single-msg msg checksum origin-map))) - (forward-line))))) - (mh-index-write-data)) - -(defvar mh-unpropagated-sequences '(cur range subject search) - "List of sequences that aren't preserved.") - -(defun mh-unpropagated-sequences () - "Return a list of sequences that aren't propagated to the source folders. -It is just the sequences in the variable -`mh-unpropagated-sequences' in addition to the -Previous-Sequence (see mh-profile 5)." - (if mh-previous-seq - (cons mh-previous-seq mh-unpropagated-sequences) - mh-unpropagated-sequences)) - -;;;###mh-autoload -(defun mh-create-sequence-map (seq-list) - "Return a map from msg number to list of sequences in which it is present. -SEQ-LIST is an assoc list whose keys are sequence names and whose -cdr is the list of messages in that sequence." - (loop with map = (make-hash-table) - for seq in seq-list - when (and (not (memq (car seq) (mh-unpropagated-sequences))) - (mh-valid-seq-p (car seq))) - do (loop for msg in (cdr seq) - do (push (car seq) (gethash msg map))) - finally return map)) - -;;;###mh-autoload -(defun mh-index-create-sequences () - "Mirror sequences present in source folders in index folder." - (let ((seq-hash (make-hash-table :test #'equal)) - (seq-list ())) - (loop for folder being the hash-keys of mh-index-data - do (setf (gethash folder seq-hash) - (mh-create-sequence-map - (mh-read-folder-sequences folder nil)))) - (dolist (msg (mh-translate-range mh-current-folder "all")) - (let* ((checksum (gethash msg mh-index-msg-checksum-map)) - (pair (gethash checksum mh-index-checksum-origin-map)) - (ofolder (car pair)) - (omsg (cdr pair))) - (loop for seq in (ignore-errors - (gethash omsg (gethash ofolder seq-hash))) - do (if (assoc seq seq-list) - (push msg (cdr (assoc seq seq-list))) - (push (list seq msg) seq-list))))) - (loop for seq in seq-list - do (apply #'mh-exec-cmd "mark" mh-current-folder - "-sequence" (symbol-name (car seq)) "-add" - (mapcar #'(lambda (x) (format "%s" x)) (cdr seq)))))) - -(defvar mh-flists-results-folder "sequence" - "Subfolder for `mh-index-folder' where flists output is placed.") -(defvar mh-flists-sequence) -(defvar mh-flists-called-flag nil) - -(defun mh-index-generate-pretty-name (string) - "Given STRING generate a name which is suitable for use as a folder name. -White space from the beginning and end are removed. All spaces in -the name are replaced with underscores and all / are replaced -with $. If STRING is longer than 20 it is truncated too. STRING -could be a list of strings in which case they are concatenated to -construct the base name." - (with-temp-buffer - (if (stringp string) - (insert string) - (when (car string) (insert (car string))) - (dolist (s (cdr string)) - (insert "_" s))) - (setq string (mh-replace-string "-lbrace" " ")) - (setq string (mh-replace-string "-rbrace" " ")) - (subst-char-in-region (point-min) (point-max) ?( ? t) - (subst-char-in-region (point-min) (point-max) ?) ? t) - (subst-char-in-region (point-min) (point-max) ?- ? t) - (goto-char (point-min)) - (while (and (not (eobp)) (memq (char-after) '(? ?\t ?\n ?\r ?_))) - (delete-char 1)) - (goto-char (point-max)) - (while (and (not (bobp)) (memq (char-before) '(? ?\t ?\n ?\r ?_))) - (delete-backward-char 1)) - (subst-char-in-region (point-min) (point-max) ? ?_ t) - (subst-char-in-region (point-min) (point-max) ?\t ?_ t) - (subst-char-in-region (point-min) (point-max) ?\n ?_ t) - (subst-char-in-region (point-min) (point-max) ?\r ?_ t) - (subst-char-in-region (point-min) (point-max) ?/ ?$ t) - (let ((out (truncate-string-to-width (buffer-string) 20))) - (cond ((eq mh-indexer 'flists) - (format "%s/%s" mh-flists-results-folder mh-flists-sequence)) - ((equal out mh-flists-results-folder) (concat out "1")) - (t out))))) - -;;;###mh-autoload -(defun* mh-index-search (redo-search-flag folder search-regexp - &optional window-config) - "Perform an indexed search in an MH mail folder. - -Use a prefix argument to repeat the last search. - -Unlike regular searches, the prompt for the folder to search can -be \"all\" to search all folders; in addition, the search works -recursively on the listed folder. The search criteria are entered -in an MH-Pick buffer as described in `mh-search-folder'.\\ - -To perform the search, type \\[mh-do-search]. Another difference -from the regular searches is that because the search operates on -more than one folder, the messages that are found are put in a -temporary sub-folder of \"+mhe-index\" and are displayed in an -MH-Folder buffer. This buffer is special because it displays -messages from multiple folders; each set of messages from a given -folder has a heading with the folder name.\\ - -The appearance of the heading can be modified by customizing the -face `mh-index-folder'. You can jump back and forth between the -headings using the commands \\[mh-index-next-folder] and -\\[mh-index-previous-folder]. - -In addition, the command \\[mh-index-visit-folder] can be used to -visit the folder of the message at point. Initially, only the -messages that matched the search criteria are displayed in the -folder. While the temporary buffer has its own set of message -numbers, the actual messages numbers are shown in the visited -folder. Thus, the command \\[mh-index-visit-folder] is useful to -find the actual message number of an interesting message, or to -view surrounding messages with the command \\[mh-rescan-folder]. - -Because this folder is temporary, you'll probably get in the -habit of killing it when you're done with -\\[mh-kill-folder]. - -If you have run the command \\[mh-search-folder], but change your -mind while entering the search criteria and actually want to run -an indexed search, then you can use the command -\\\\[mh-index-do-search] in the MH-Pick -buffer.\\ - -The command \\[mh-index-search] runs the command defined by the -option `mh-index-program'. The default value is \"Auto-detect\" -which means that MH-E will automatically choose one of -\"swish++\", \"swish-e\", \"mairix\", \"namazu\", \"pick\" and -\"grep\" in that order. If, for example, you have both -\"swish++\" and \"mairix\" installed and you want to use -\"mairix\", then you can set this option to \"mairix\". - - *NOTE* - - The \"pick\" and \"grep\" commands do not perform a - recursive search on the given folder. - -This command uses an \"X-MHE-Checksum:\" header field to cache -the MD5 checksum of a message. This means that if an incoming -message already contains an \"X-MHE-Checksum:\" field, that -message might not be found by this command. The following -\"procmail\" recipe avoids this problem by renaming the existing -header field: - - :0 wf - | formail -R \"X-MHE-Checksum\" \"X-Old-MHE-Checksum\" - -The documentation for the following commands describe how to set -up the various indexing programs to use with MH-E. The \"pick\" -and \"grep\" commands do not require additional configuration. - - - `mh-swish++-execute-search' - - `mh-swish-execute-search' - - `mh-mairix-execute-search' - - `mh-namazu-execute-search' - - `mh-pick-execute-search' - - `mh-grep-execute-search' - -In a program, if REDO-SEARCH-FLAG is non-nil and the current -folder buffer was generated by a index search, then the search is -repeated. Otherwise, FOLDER is searched with SEARCH-REGEXP and -the results are presented in an MH-E folder. If FOLDER is \"+\" -then mail in all folders are searched. Optional argument -WINDOW-CONFIG stores the window configuration that will be -restored after the user quits the folder containing the index -search results." - (interactive - (list current-prefix-arg - (progn - (mh-find-path) - (or (and current-prefix-arg mh-index-sequence-search-flag) - (and current-prefix-arg (car mh-index-previous-search)) - (mh-prompt-for-folder "Search" "+" nil "all" t))) - (progn - ;; Yes, we do want to call mh-index-choose every time in case the - ;; user has switched the indexer manually. - (unless (mh-index-choose) (error "No indexing program found")) - (or (and current-prefix-arg (cadr mh-index-previous-search)) - mh-index-regexp-builder - (read-string (format "%s regexp: " - (upcase-initials - (symbol-name mh-indexer)))))) - (if (and (not - (and current-prefix-arg (cadr mh-index-previous-search))) - mh-index-regexp-builder) - (current-window-configuration) - nil))) - ;; Redoing a sequence search? - (when (and redo-search-flag mh-index-data mh-index-sequence-search-flag - (not mh-flists-called-flag)) - (let ((mh-flists-called-flag t)) - (apply #'mh-index-sequenced-messages mh-index-previous-search)) - (return-from mh-index-search)) - ;; We have fancy query parsing - (when (symbolp search-regexp) - (mh-search-folder folder window-config) - (setq mh-searching-function 'mh-index-do-search) - (return-from mh-index-search)) - (mh-checksum-choose) - (let ((result-count 0) - (old-window-config (or window-config mh-previous-window-config)) - (previous-search mh-index-previous-search) - (index-folder (format "%s/%s" mh-index-folder - (mh-index-generate-pretty-name search-regexp)))) - ;; Create a new folder for the search results or recreate the old one... - (if (and redo-search-flag mh-index-previous-search) - (let ((buffer-name (buffer-name (current-buffer)))) - (mh-process-or-undo-commands buffer-name) - (save-excursion (mh-exec-cmd-quiet nil "rmf" buffer-name)) - (mh-exec-cmd-quiet nil "folder" "-create" "-fast" buffer-name) - (setq index-folder buffer-name)) - (setq index-folder (mh-index-new-folder index-folder search-regexp))) - - (let ((folder-path (format "%s%s" mh-user-path (substring folder 1))) - (folder-results-map (make-hash-table :test #'equal)) - (origin-map (make-hash-table :test #'equal))) - ;; Run search program... - (message "Executing %s... " mh-indexer) - (funcall mh-index-execute-search-function folder-path search-regexp) - - ;; Parse indexer output - (message "Processing %s output... " mh-indexer) - (goto-char (point-min)) - (loop for next-result = (funcall mh-index-next-result-function) - while next-result - do (unless (eq next-result 'error) - (unless (gethash (car next-result) folder-results-map) - (setf (gethash (car next-result) folder-results-map) - (make-hash-table :test #'equal))) - (setf (gethash (cadr next-result) - (gethash (car next-result) folder-results-map)) - t))) - - ;; Copy the search results over - (maphash #'(lambda (folder msgs) - (let ((cur (car (mh-translate-range folder "cur"))) - (msgs (sort (loop for msg being the hash-keys of msgs - collect msg) - #'<))) - (mh-exec-cmd "refile" msgs "-src" folder - "-link" index-folder) - ;; Restore cur to old value, that refile changed - (when cur - (mh-exec-cmd-quiet nil "mark" folder "-add" "-zero" - "-sequence" "cur" (format "%s" cur))) - (loop for msg in msgs - do (incf result-count) - (setf (gethash result-count origin-map) - (cons folder msg))))) - folder-results-map) - - ;; Vist the results folder - (mh-visit-folder index-folder () (list folder-results-map origin-map)) - - (goto-char (point-min)) - (forward-line) - (mh-update-sequences) - (mh-recenter nil) - - ;; Update the speedbar, if needed - (when (mh-speed-flists-active-p) - (mh-speed-flists t mh-current-folder)) - - ;; Maintain history - (when (or (and redo-search-flag previous-search) window-config) - (setq mh-previous-window-config old-window-config)) - (setq mh-index-previous-search (list folder search-regexp)) - - ;; Write out data to disk - (unless mh-flists-called-flag (mh-index-write-data)) - - (message "%s found %s matches in %s folders" - (upcase-initials (symbol-name mh-indexer)) - (loop for msg-hash being hash-values of mh-index-data - sum (hash-table-count msg-hash)) - (loop for msg-hash being hash-values of mh-index-data - count (> (hash-table-count msg-hash) 0)))))) - - - -;;; Functions to serialize index data... - -(defun mh-index-write-data () - "Write index data to file." - (ignore-errors - (unless (eq major-mode 'mh-folder-mode) - (error "Can't be called from folder in \"%s\"" major-mode)) - (let ((data mh-index-data) - (msg-checksum-map mh-index-msg-checksum-map) - (checksum-origin-map mh-index-checksum-origin-map) - (previous-search mh-index-previous-search) - (sequence-search-flag mh-index-sequence-search-flag) - (outfile (concat buffer-file-name mh-index-data-file)) - (print-length nil) - (print-level nil)) - (with-temp-file outfile - (mh-index-write-hashtable - data (lambda (x) (loop for y being the hash-keys of x collect y))) - (mh-index-write-hashtable msg-checksum-map #'identity) - (mh-index-write-hashtable checksum-origin-map #'identity) - (pp previous-search (current-buffer)) (insert "\n") - (pp sequence-search-flag (current-buffer)) (insert "\n"))))) - -;;;###mh-autoload -(defun mh-index-read-data () - "Read index data from file." - (ignore-errors - (unless (eq major-mode 'mh-folder-mode) - (error "Can't be called from folder in \"%s\"" major-mode)) - (let ((infile (concat buffer-file-name mh-index-data-file)) - t1 t2 t3 t4 t5) - (with-temp-buffer - (insert-file-contents-literally infile) - (goto-char (point-min)) - (setq t1 (mh-index-read-hashtable - (lambda (data) - (loop with table = (make-hash-table :test #'equal) - for x in data do (setf (gethash x table) t) - finally return table))) - t2 (mh-index-read-hashtable #'identity) - t3 (mh-index-read-hashtable #'identity) - t4 (read (current-buffer)) - t5 (read (current-buffer)))) - (setq mh-index-data t1 - mh-index-msg-checksum-map t2 - mh-index-checksum-origin-map t3 - mh-index-previous-search t4 - mh-index-sequence-search-flag t5)))) - -(defun mh-index-write-hashtable (table proc) - "Write TABLE to `current-buffer'. -PROC is used to serialize the values corresponding to the hash -table keys." - (pp (loop for x being the hash-keys of table - collect (cons x (funcall proc (gethash x table)))) - (current-buffer)) - (insert "\n")) - -(defun mh-index-read-hashtable (proc) - "From BUFFER read a hash table serialized as a list. -PROC is used to convert the value to actual data." - (loop with table = (make-hash-table :test #'equal) - for pair in (read (current-buffer)) - do (setf (gethash (car pair) table) (funcall proc (cdr pair))) - finally return table)) - -;;;###mh-autoload -(defun mh-index-p () - "Non-nil means that this folder was generated by an index search." - mh-index-data) - -;;;###mh-autoload -(defun mh-index-do-search () - "Find messages that match the qualifications in the current pattern buffer." - (interactive) - (unless (mh-index-choose) (error "No indexing program found")) - (let* ((regexp-list (mh-pick-parse-search-buffer)) - (pattern (funcall mh-index-regexp-builder regexp-list))) - (if pattern - (mh-index-search nil mh-current-folder pattern - mh-previous-window-config) - (error "No search terms")))) - -;;;###mh-autoload -(defun mh-index-parse-search-regexp (input-string) - "Construct parse tree for INPUT-STRING. -All occurrences of &, |, ! and ~ in INPUT-STRING are replaced by -AND, OR and NOT as appropriate. Then the resulting string is -parsed." - (let (input) - (with-temp-buffer - (insert input-string) - ;; replace tabs - (mh-replace-string "\t" " ") - ;; synonyms of AND - (mh-replace-string " AND " " and ") - (mh-replace-string "&" " and ") - (mh-replace-string " -and " " and ") - ;; synonyms of OR - (mh-replace-string " OR " " or ") - (mh-replace-string "|" " or ") - (mh-replace-string " -or " " or ") - ;; synonyms of NOT - (mh-replace-string " NOT " " not ") - (mh-replace-string "!" " not ") - (mh-replace-string "~" " not ") - (mh-replace-string " -not " " not ") - ;; synonyms of left brace - (mh-replace-string "(" " ( ") - (mh-replace-string " -lbrace " " ( ") - ;; synonyms of right brace - (mh-replace-string ")" " ) ") - (mh-replace-string " -rbrace " " ) ") - ;; get the normalized input - (setq input (format "( %s )" (buffer-substring (point-min) (point-max))))) - - (let ((tokens (mh-index-add-implicit-ops (split-string input))) - (op-stack ()) - (operand-stack ()) - oper1) - (dolist (token tokens) - (cond ((equal token "(") (push 'paren op-stack)) - ((equal token "not") (push 'not op-stack)) - ((equal token "or") (push 'or op-stack)) - ((equal token "and") (push 'and op-stack)) - ((equal token ")") - (multiple-value-setq (op-stack operand-stack) - (mh-index-evaluate op-stack operand-stack)) - (when (eq (car op-stack) 'not) - (setq op-stack (cdr op-stack)) - (push `(not ,(pop operand-stack)) operand-stack)) - (when (eq (car op-stack) 'and) - (setq op-stack (cdr op-stack)) - (setq oper1 (pop operand-stack)) - (push `(and ,(pop operand-stack) ,oper1) operand-stack))) - ((eq (car op-stack) 'not) - (setq op-stack (cdr op-stack)) - (push `(not ,token) operand-stack) - (when (eq (car op-stack) 'and) - (setq op-stack (cdr op-stack)) - (setq oper1 (pop operand-stack)) - (push `(and ,(pop operand-stack) ,oper1) operand-stack))) - ((eq (car op-stack) 'and) - (setq op-stack (cdr op-stack)) - (push `(and ,(pop operand-stack) ,token) operand-stack)) - (t (push token operand-stack)))) - (prog1 (pop operand-stack) - (when (or op-stack operand-stack) - (error "Invalid regexp: %s" input)))))) - -(defun mh-index-add-implicit-ops (tokens) - "Add implicit operators in the list TOKENS." - (let ((result ()) - (literal-seen nil) - current) - (while tokens - (setq current (pop tokens)) - (cond ((or (equal current ")") (equal current "and") (equal current "or")) - (setq literal-seen nil) - (push current result)) - ((and literal-seen - (push "and" result) - (setq literal-seen nil) - nil)) - (t - (push current result) - (unless (or (equal current "(") (equal current "not")) - (setq literal-seen t))))) - (nreverse result))) - -(defun mh-index-evaluate (op-stack operand-stack) - "Read expression till starting paren based on OP-STACK and OPERAND-STACK." - (block mh-index-evaluate - (let (op oper1) - (while op-stack - (setq op (pop op-stack)) - (cond ((eq op 'paren) - (return-from mh-index-evaluate (values op-stack operand-stack))) - ((eq op 'not) - (push `(not ,(pop operand-stack)) operand-stack)) - ((or (eq op 'and) (eq op 'or)) - (setq oper1 (pop operand-stack)) - (push `(,op ,(pop operand-stack) ,oper1) operand-stack)))) - (error "Ran out of tokens")))) - -;;;###mh-autoload -(defun mh-index-next-folder (&optional backward-flag) - "Jump to the next folder marker. - -With non-nil optional argument BACKWARD-FLAG, jump to the previous -group of results." - (interactive "P") - (if (null mh-index-data) - (message "Only applicable in an MH-E index search buffer") - (let ((point (point))) - (forward-line (if backward-flag -1 1)) - (cond ((if backward-flag - (re-search-backward "^+" (point-min) t) - (re-search-forward "^+" (point-max) t)) - (beginning-of-line)) - ((and (if backward-flag - (goto-char (point-max)) - (goto-char (point-min))) - nil)) - ((if backward-flag - (re-search-backward "^+" (point-min) t) - (re-search-forward "^+" (point-max) t)) - (beginning-of-line)) - (t (goto-char point)))))) - -;;;###mh-autoload -(defun mh-index-previous-folder () - "Jump to the previous folder marker." - (interactive) - (mh-index-next-folder t)) - -(defun mh-folder-exists-p (folder) - "Check if FOLDER exists." - (and (mh-folder-name-p folder) - (save-excursion - (with-temp-buffer - (mh-exec-cmd-output "folder" nil "-fast" "-nocreate" folder) - (goto-char (point-min)) - (not (eobp)))))) - -(defun mh-msg-exists-p (msg folder) - "Check if MSG exists in FOLDER." - (file-exists-p (format "%s%s/%s" mh-user-path (substring folder 1) msg))) - -(defun mh-index-new-folder (name search-regexp) - "Return a folder name based on NAME for search results of SEARCH-REGEXP. - -If folder NAME already exists and was generated for the same -SEARCH-REGEXP then it is reused. - -Otherwise if the folder NAME was generated from a different -search then check if NAME<2> can be used. Otherwise try NAME<3>. -This is repeated till we find a new folder name. - -If the folder returned doesn't exist then it is created." - (unless (mh-folder-name-p name) - (error "The argument should be a valid MH folder name")) - (let ((chosen-name - (loop for i from 1 - for candidate = (if (equal i 1) name (format "%s<%s>" name i)) - when (or (not (mh-folder-exists-p candidate)) - (equal (mh-index-folder-search-regexp candidate) - search-regexp)) - return candidate))) - ;; Do pending refiles/deletes... - (when (get-buffer chosen-name) - (mh-process-or-undo-commands chosen-name)) - ;; Recreate folder... - (save-excursion (mh-exec-cmd-quiet nil "rmf" chosen-name)) - (mh-exec-cmd-quiet nil "folder" "-create" "-fast" chosen-name) - (mh-remove-from-sub-folders-cache chosen-name) - (when (boundp 'mh-speed-folder-map) - (mh-speed-add-folder chosen-name)) - chosen-name)) - -(defun mh-index-folder-search-regexp (folder) - "If FOLDER was created by a index search, return the search regexp. -Return nil if FOLDER doesn't exist or the .mhe_index file is -garbled." - (ignore-errors - (with-temp-buffer - (insert-file-contents - (format "%s%s/%s" mh-user-path (substring folder 1) mh-index-data-file)) - (goto-char (point-min)) - (forward-list 3) - (cadr (read (current-buffer)))))) - -;;;###mh-autoload -(defun mh-index-insert-folder-headers () - "Annotate the search results with original folder names." - (let ((cur-msg (mh-get-msg-num nil)) - (old-buffer-modified-flag (buffer-modified-p)) - (buffer-read-only nil) - current-folder last-folder) - (goto-char (point-min)) - (while (not (eobp)) - (setq current-folder (car (gethash (gethash (mh-get-msg-num nil) - mh-index-msg-checksum-map) - mh-index-checksum-origin-map))) - (when (and current-folder (not (equal current-folder last-folder))) - (insert (if last-folder "\n" "") current-folder "\n") - (setq last-folder current-folder)) - (forward-line)) - (when cur-msg - (mh-notate-cur) - (mh-goto-msg cur-msg t)) - (set-buffer-modified-p old-buffer-modified-flag)) - (mh-index-create-imenu-index)) - -;;;###mh-autoload -(defun mh-index-create-imenu-index () - "Create alist of folder names and positions in index folder buffers." - (save-excursion - (setq which-func-mode t) - (let ((alist ())) - (goto-char (point-min)) - (while (re-search-forward "^+" nil t) - (save-excursion - (beginning-of-line) - (push (cons (buffer-substring-no-properties - (point) (line-end-position)) - (set-marker (make-marker) (point))) - alist))) - (setq imenu--index-alist (nreverse alist))))) - -;;;###mh-autoload -(defun mh-index-group-by-folder () - "Partition the messages based on source folder. -Returns an alist with the the folder names in the car and the cdr -being the list of messages originally from that folder." - (save-excursion - (goto-char (point-min)) - (let ((result-table (make-hash-table :test #'equal))) - (loop for msg being hash-keys of mh-index-msg-checksum-map - do (push msg (gethash (car (gethash - (gethash msg mh-index-msg-checksum-map) - mh-index-checksum-origin-map)) - result-table))) - (loop for x being the hash-keys of result-table - collect (cons x (nreverse (gethash x result-table))))))) - -;;;###mh-autoload -(defun mh-index-delete-folder-headers () - "Delete the folder headers." - (let ((cur-msg (mh-get-msg-num nil)) - (old-buffer-modified-flag (buffer-modified-p)) - (buffer-read-only nil)) - (while (and (not cur-msg) (not (eobp))) - (forward-line) - (setq cur-msg (mh-get-msg-num nil))) - (goto-char (point-min)) - (while (not (eobp)) - (if (or (char-equal (char-after) ?+) (char-equal (char-after) 10)) - (delete-region (point) (progn (forward-line) (point))) - (forward-line))) - (when cur-msg (mh-goto-msg cur-msg t t)) - (set-buffer-modified-p old-buffer-modified-flag))) - -;;;###mh-autoload -(defun mh-index-visit-folder () - "Visit original folder from where the message at point was found." - (interactive) - (unless mh-index-data - (error "Not in an index folder")) - (let (folder msg) - (save-excursion - (cond ((and (bolp) (eolp)) - (ignore-errors (forward-line -1)) - (setq msg (mh-get-msg-num t))) - ((equal (char-after (line-beginning-position)) ?+) - (setq folder (buffer-substring-no-properties - (line-beginning-position) (line-end-position)))) - (t (setq msg (mh-get-msg-num t))))) - (when (not folder) - (setq folder (car (gethash (gethash msg mh-index-msg-checksum-map) - mh-index-checksum-origin-map)))) - (when (or (not (get-buffer folder)) - (y-or-n-p (format "Reuse buffer displaying %s? " folder))) - (mh-visit-folder - folder (loop for x being the hash-keys of (gethash folder mh-index-data) - when (mh-msg-exists-p x folder) collect x))))) - -(defun mh-index-match-checksum (msg folder checksum) - "Check if MSG in FOLDER has X-MHE-Checksum header value of CHECKSUM." - (with-temp-buffer - (mh-exec-cmd-output mh-scan-prog nil "-width" "80" - "-format" "%{x-mhe-checksum}\n" folder msg) - (goto-char (point-min)) - (string-equal (buffer-substring-no-properties (point) (line-end-position)) - checksum))) - -(defun mh-index-matching-source-msgs (msgs &optional delete-from-index-data) - "Return a table of original messages and folders for messages in MSGS. -If optional argument DELETE-FROM-INDEX-DATA is non-nil, then each -of the messages, whose counter-part is found in some source -folder, is removed from `mh-index-data'." - (let ((table (make-hash-table :test #'equal))) - (dolist (msg msgs) - (let* ((checksum (gethash msg mh-index-msg-checksum-map)) - (pair (gethash checksum mh-index-checksum-origin-map))) - (when (and checksum (car pair) (cdr pair) - (mh-index-match-checksum (cdr pair) (car pair) checksum)) - (push (cdr pair) (gethash (car pair) table)) - (when delete-from-index-data - (remhash (cdr pair) (gethash (car pair) mh-index-data)))))) - table)) - -;;;###mh-autoload -(defun mh-index-execute-commands () - "Delete/refile the actual messages. -The copies in the searched folder are then deleted/refiled to get -the desired result. Before deleting the messages we make sure -that the message being deleted is identical to the one that the -user has marked in the index buffer." - (save-excursion - (let ((folders ()) - (mh-speed-flists-inhibit-flag t)) - (maphash - (lambda (folder msgs) - (push folder folders) - (if (not (get-buffer folder)) - ;; If source folder not open, just delete the messages... - (apply #'mh-exec-cmd "rmm" folder (mh-coalesce-msg-list msgs)) - ;; Otherwise delete the messages in the source buffer... - (save-excursion - (set-buffer folder) - (let ((old-refile-list mh-refile-list) - (old-delete-list mh-delete-list)) - (setq mh-refile-list nil - mh-delete-list msgs) - (unwind-protect (mh-execute-commands) - (setq mh-refile-list - (mapcar (lambda (x) - (cons (car x) - (loop for y in (cdr x) - unless (memq y msgs) collect y))) - old-refile-list) - mh-delete-list - (loop for x in old-delete-list - unless (memq x msgs) collect x)) - (mh-set-folder-modified-p (mh-outstanding-commands-p)) - (when (mh-outstanding-commands-p) - (mh-notate-deleted-and-refiled))))))) - (mh-index-matching-source-msgs (append (loop for x in mh-refile-list - append (cdr x)) - mh-delete-list) - t)) - folders))) - -;;;###mh-autoload -(defun mh-index-add-to-sequence (seq msgs) - "Add to SEQ the messages in the list MSGS. -This function updates the source folder sequences. Also makes an -attempt to update the source folder buffer if we have it open." - ;; Don't need to do anything for cur - (save-excursion - (when (and (not (memq seq (mh-unpropagated-sequences))) - (mh-valid-seq-p seq)) - (let ((folders ()) - (mh-speed-flists-inhibit-flag t)) - (maphash (lambda (folder msgs) - (push folder folders) - ;; Add messages to sequence in source folder... - (apply #'mh-exec-cmd-quiet nil "mark" folder - "-add" "-nozero" "-sequence" (symbol-name seq) - (mapcar (lambda (x) (format "%s" x)) - (mh-coalesce-msg-list msgs))) - ;; Update source folder buffer if we have it open... - (when (get-buffer folder) - (save-excursion - (set-buffer folder) - (mh-put-msg-in-seq msgs seq)))) - (mh-index-matching-source-msgs msgs)) - folders)))) - -;;;###mh-autoload -(defun mh-index-delete-from-sequence (seq msgs) - "Delete from SEQ the messages in MSGS. -This function updates the source folder sequences. Also makes an -attempt to update the source folder buffer if present." - (save-excursion - (when (and (not (memq seq (mh-unpropagated-sequences))) - (mh-valid-seq-p seq)) - (let ((folders ()) - (mh-speed-flists-inhibit-flag t)) - (maphash (lambda (folder msgs) - (push folder folders) - ;; Remove messages from sequence in source folder... - (apply #'mh-exec-cmd-quiet nil "mark" folder - "-del" "-nozero" "-sequence" (symbol-name seq) - (mapcar (lambda (x) (format "%s" x)) - (mh-coalesce-msg-list msgs))) - ;; Update source folder buffer if we have it open... - (when (get-buffer folder) - (save-excursion - (set-buffer folder) - (mh-delete-msg-from-seq msgs seq t)))) - (mh-index-matching-source-msgs msgs)) - folders)))) - - - -;; Pick interface - -(defvar mh-index-pick-folder) -(defvar mh-pick-binary "pick") - -(defun mh-pick-execute-search (folder-path search-regexp) - "Execute pick. - -Unlike the other index search programs \"pick\" only searches -messages present in the folder itself and does not descend into -any sub-folders that may be present. - -In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP -is used to search." - (set-buffer (get-buffer-create mh-index-temp-buffer)) - (erase-buffer) - (setq mh-index-pick-folder - (concat "+" (substring folder-path (length mh-user-path)))) - (apply #'call-process (expand-file-name "pick" mh-progs) nil '(t nil) nil - mh-index-pick-folder "-list" search-regexp) - (goto-char (point-min))) - -(defun mh-pick-next-result () - "Return the next pick search result." - (prog1 (block nil - (when (eobp) (return nil)) - (unless (re-search-forward "^[1-9][0-9]*$" (line-end-position) t) - (return 'error)) - (list mh-index-pick-folder - (car (read-from-string (buffer-substring-no-properties - (line-beginning-position) - (line-end-position)))) - nil)) - (forward-line))) - - - -;; Grep interface - -(defvar mh-grep-binary (executable-find "grep")) - -(defun mh-grep-execute-search (folder-path search-regexp) - "Execute grep and read the results. - -Unlike the other index search programs \"grep\" only searches -messages present in the folder itself and does not descend into -any sub-folders that may be present. - -In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP -is used to search." - (set-buffer (get-buffer-create mh-index-temp-buffer)) - (erase-buffer) - (call-process mh-grep-binary nil '(t nil) nil - "-i" "-r" search-regexp folder-path) - (goto-char (point-min))) - -(defun mh-grep-next-result () - "Read the next result. -Parse it and return the message folder, message index and the -match. If no other matches left then return nil. If the current -record is invalid return 'error." - (prog1 - (block nil - (when (eobp) - (return nil)) - (let ((eol-pos (line-end-position)) - (bol-pos (line-beginning-position)) - folder-start msg-end) - (goto-char bol-pos) - (unless (search-forward mh-user-path eol-pos t) - (return 'error)) - (setq folder-start (point)) - (unless (search-forward ":" eol-pos t) - (return 'error)) - (let ((match (buffer-substring-no-properties (point) eol-pos))) - (forward-char -1) - (setq msg-end (point)) - (unless (search-backward "/" folder-start t) - (return 'error)) - (list (format "+%s" (buffer-substring-no-properties - folder-start (point))) - (let ((val (ignore-errors (read-from-string - (buffer-substring-no-properties - (1+ (point)) msg-end))))) - (if (and (consp val) (integerp (car val))) - (car val) - (return 'error))) - match)))) - (forward-line))) - - - -;; Mairix interface - -(defvar mh-mairix-binary (executable-find "mairix")) -(defvar mh-mairix-directory ".mairix") -(defvar mh-mairix-folder nil) - -(defun mh-mairix-execute-search (folder-path search-regexp-list) - "Execute mairix and read the results. - -In the examples below, replace \"/home/user/Mail\" with the path -to your MH directory. - -First create the directory \"/home/user/Mail/.mairix\". Then -create the file \"/home/user/Mail/.mairix/config\" with the -following contents: - - base=/home/user/Mail - - # List of folders that should be indexed. 3 dots at the end means there - # are subfolders within the folder - mh=archive...:inbox:drafts:news:sent:trash - - vfolder_format=raw - database=/home/user/Mail/mairix/database - -Use the following command line to generate the mairix index. Run -this daily from cron: - - mairix -f /home/user/Mail/.mairix/config - -In a program, FOLDER-PATH is the directory in which -SEARCH-REGEXP-LIST is used to search." - (set-buffer (get-buffer-create mh-index-temp-buffer)) - (erase-buffer) - (unless mh-mairix-binary - (error "Set `mh-mairix-binary' appropriately")) - (apply #'call-process mh-mairix-binary nil '(t nil) nil - "-r" "-f" (format "%s%s/config" mh-user-path mh-mairix-directory) - search-regexp-list) - (goto-char (point-min)) - (setq mh-mairix-folder - (let ((last-char (substring folder-path (1- (length folder-path))))) - (if (equal last-char "/") - folder-path - (format "%s/" folder-path))))) - -(defun mh-mairix-next-result () - "Return next result from mairix output." - (prog1 - (block nil - (when (or (eobp) (and (bolp) (eolp))) - (return nil)) - (unless (eq (char-after) ?/) - (return 'error)) - (let ((start (point)) - end msg-start) - (setq end (line-end-position)) - (unless (search-forward mh-mairix-folder end t) - (return 'error)) - (goto-char (match-beginning 0)) - (unless (equal (point) start) - (return 'error)) - (goto-char end) - (unless (search-backward "/" start t) - (return 'error)) - (setq msg-start (1+ (point))) - (goto-char start) - (unless (search-forward mh-user-path end t) - (return 'error)) - (list (format "+%s" (buffer-substring-no-properties - (point) (1- msg-start))) - (car (read-from-string - (buffer-substring-no-properties msg-start end))) - ()))) - (forward-line))) - -(defun mh-mairix-regexp-builder (regexp-list) - "Generate query for mairix. -REGEXP-LIST is an alist of fields and values." - (let ((result ())) - (dolist (pair regexp-list) - (when (cdr pair) - (push - (concat - (cond ((eq (car pair) 'to) "t:") - ((eq (car pair) 'from) "f:") - ((eq (car pair) 'cc) "c:") - ((eq (car pair) 'subject) "s:") - ((eq (car pair) 'date) "d:") - (t "")) - (let ((sop (cdr (mh-mairix-convert-to-sop* (cdr pair)))) - (final "")) - (dolist (conjunct sop) - (let ((expr-list (cdr conjunct)) - (expr-string "")) - (dolist (e expr-list) - (setq expr-string (concat expr-string "," - (if (atom e) "" "~") - (if (atom e) e (cadr e))))) - (setq final (concat final "/" (substring expr-string 1))))) - (substring final 1))) - result))) - result)) - -(defun mh-mairix-convert-to-sop* (expr) - "Convert EXPR to sum of product form." - (cond ((atom expr) `(or (and ,expr))) - ((eq (car expr) 'or) - (cons 'or - (loop for e in (mapcar #'mh-mairix-convert-to-sop* (cdr expr)) - append (cdr e)))) - ((eq (car expr) 'and) - (let ((conjuncts (mapcar #'mh-mairix-convert-to-sop* (cdr expr))) - result next-factor) - (setq result (pop conjuncts)) - (while conjuncts - (setq next-factor (pop conjuncts)) - (setq result (let ((res ())) - (dolist (t1 (cdr result)) - (dolist (t2 (cdr next-factor)) - (push `(and ,@(cdr t1) ,@(cdr t2)) res))) - (cons 'or res)))) - result)) - ((atom (cadr expr)) `(or (and ,expr))) - ((eq (caadr expr) 'not) (mh-mairix-convert-to-sop* (cadadr expr))) - ((eq (caadr expr) 'and) (mh-mairix-convert-to-sop* - `(or ,@(mapcar #'(lambda (x) `(not ,x)) - (cdadr expr))))) - ((eq (caadr expr) 'or) (mh-mairix-convert-to-sop* - `(and ,@(mapcar #'(lambda (x) `(not ,x)) - (cdadr expr))))) - (t (error "Unreachable: %s" expr)))) - - - -;; Interface to unseen messages script - -(defvar mh-flists-search-folders) - -;; XXX: This should probably be in mh-utils.el and used in other places where -;; MH-E calls out to /bin/sh. -(defun mh-index-quote-for-shell (string) - "Quote STRING for /bin/sh." - (concat "\"" - (loop for x across string - concat (format (if (memq x '(?\\ ?` ?$)) "\\%c" "%c") x)) - "\"")) - -(defun mh-flists-execute (&rest args) - "Execute flists. -Search for messages belonging to `mh-flists-sequence' in the -folders specified by `mh-flists-search-folders'. If -`mh-recursive-folders-flag' is t, then the folders are searched -recursively. All parameters ARGS are ignored." - (set-buffer (get-buffer-create mh-index-temp-buffer)) - (erase-buffer) - (unless (executable-find "sh") - (error "Didn't find sh")) - (with-temp-buffer - (let ((seq (symbol-name mh-flists-sequence))) - (insert "for folder in `" (expand-file-name "flists" mh-progs) " " - (cond ((eq mh-flists-search-folders t) - (mh-index-quote-for-shell mh-inbox)) - ((eq mh-flists-search-folders nil) "") - ((listp mh-flists-search-folders) - (loop for folder in mh-flists-search-folders - concat - (concat " " (mh-index-quote-for-shell folder))))) - (if mh-recursive-folders-flag " -recurse" "") - " -sequence " seq " -noshowzero -fast` ; do\n" - (expand-file-name "mhpath" mh-progs) " \"+$folder\" " seq "\n" - "done\n")) - (call-process-region - (point-min) (point-max) "sh" nil (get-buffer mh-index-temp-buffer)))) - -;;;###mh-autoload -(defun mh-index-sequenced-messages (folders sequence) - "Display messages in any sequence. - -All messages from the FOLDERS in `mh-new-messages-folders' in the -SEQUENCE you provide are listed. With a prefix argument, enter a -space-separated list of folders at the prompt, or nothing to -search all folders." - (interactive - (list (if current-prefix-arg - (split-string (read-string "Search folder(s) (default all): ")) - mh-new-messages-folders) - (mh-read-seq-default "Search" nil))) - (unless sequence (setq sequence mh-unseen-seq)) - (let* ((mh-flists-search-folders folders) - (mh-flists-sequence sequence) - (mh-flists-called-flag t) - (mh-indexer 'flists) - (mh-index-execute-search-function 'mh-flists-execute) - (mh-index-next-result-function 'mh-mairix-next-result) - (mh-mairix-folder mh-user-path) - (mh-index-regexp-builder nil) - (new-folder (format "%s/%s/%s" mh-index-folder - mh-flists-results-folder sequence)) - (window-config (if (equal new-folder mh-current-folder) - mh-previous-window-config - (current-window-configuration))) - (redo-flag nil) - message) - (cond ((buffer-live-p (get-buffer new-folder)) - ;; The destination folder is being visited. Trick `mh-index-search' - ;; into thinking that the folder resulted from a previous search. - (set-buffer new-folder) - (setq mh-index-previous-search (list folders sequence)) - (setq redo-flag t)) - ((mh-folder-exists-p new-folder) - ;; Folder exists but we don't have it open. That means they are - ;; stale results from a old flists search. Clear it out. - (mh-exec-cmd-quiet nil "rmf" new-folder))) - (setq message (mh-index-search redo-flag "+" mh-flists-results-folder - window-config) - mh-index-sequence-search-flag t - mh-index-previous-search (list folders sequence)) - (mh-index-write-data) - (when (stringp message) (message "%s" message)))) - -;;;###mh-autoload -(defun mh-index-new-messages (folders) - "Display unseen messages. - -If you use a program such as \"procmail\" to use \"rcvstore\" to file -your incoming mail automatically, you can display new, unseen, -messages using this command. All messages in the \"unseen\" -sequence from the folders in `mh-new-messages-folders' are -listed. - -With a prefix argument, enter a space-separated list of FOLDERS, -or nothing to search all folders." - (interactive - (list (if current-prefix-arg - (split-string (read-string "Search folder(s) (default all): ")) - mh-new-messages-folders))) - (mh-index-sequenced-messages folders mh-unseen-seq)) - -;;;###mh-autoload -(defun mh-index-ticked-messages (folders) - "Display ticked messages. - -All messages in `mh-tick-seq' from the folders in -`mh-ticked-messages-folders' are listed. - -With a prefix argument, enter a space-separated list of FOLDERS, -or nothing to search all folders." - (interactive - (list (if current-prefix-arg - (split-string (read-string "Search folder(s) (default all): ")) - mh-ticked-messages-folders))) - (mh-index-sequenced-messages folders mh-tick-seq)) - - - -;; Swish interface - -(defvar mh-swish-binary (executable-find "swish-e")) -(defvar mh-swish-directory ".swish") -(defvar mh-swish-folder nil) - -;;;###mh-autoload -(defun mh-swish-execute-search (folder-path search-regexp) - "Execute swish-e and read the results. - -In the examples below, replace \"/home/user/Mail\" with the path -to your MH directory. - -First create the directory \"/home/user/Mail/.swish\". Then -create the file \"/home/user/Mail/.swish/config\" with the -following contents: - - DefaultContents TXT* - IndexDir /home/user/Mail - IndexFile /home/user/Mail/.swish/index - IndexName \"Mail Index\" - IndexDescription \"Mail Index\" - IndexPointer \"http://nowhere\" - IndexAdmin \"nobody\" - #MetaNames automatic - IndexReport 3 - FollowSymLinks no - UseStemming no - IgnoreTotalWordCountWhenRanking yes - WordCharacters abcdefghijklmnopqrstuvwxyz0123456789- - BeginCharacters abcdefghijklmnopqrstuvwxyz - EndCharacters abcdefghijklmnopqrstuvwxyz0123456789 - IgnoreLimit 50 1000 - IndexComments 0 - FileRules filename contains \\D - FileRules pathname contains /home/user/Mail/.swish - FileRules pathname contains /home/user/Mail/mhe-index - -This configuration does not index the folders that hold the -results of your searches in \"+mhe-index\" since they tend to be -ephemeral and the original messages are indexed anyway. - -If there are any directories you would like to ignore, append -lines like the following to \"config\": - - FileRules pathname contains /home/user/Mail/scripts - -Use the following command line to generate the swish index. Run -this daily from cron: - - swish-e -c /home/user/Mail/.swish/config - -In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP -is used to search." - (set-buffer (get-buffer-create mh-index-temp-buffer)) - (erase-buffer) - (unless mh-swish-binary - (error "Set `mh-swish-binary' appropriately")) - (call-process mh-swish-binary nil '(t nil) nil - "-w" search-regexp - "-f" (format "%s%s/index" mh-user-path mh-swish-directory)) - (goto-char (point-min)) - (setq mh-swish-folder - (let ((last-char (substring folder-path (1- (length folder-path))))) - (if (equal last-char "/") - folder-path - (format "%s/" folder-path))))) - -(defun mh-swish-next-result () - "Get the next result from swish output." - (prog1 - (block nil - (when (or (eobp) (equal (char-after (point)) ?.)) - (return nil)) - (when (equal (char-after (point)) ?#) - (return 'error)) - (let* ((start (search-forward " " (line-end-position) t)) - (end (search-forward " " (line-end-position) t))) - (unless (and start end) - (return 'error)) - (setq end (1- end)) - (unless (file-exists-p (buffer-substring-no-properties start end)) - (return 'error)) - (unless (search-backward "/" start t) - (return 'error)) - (list (let* ((s (buffer-substring-no-properties start (1+ (point))))) - (unless (string-match mh-swish-folder s) - (return 'error)) - (if (and (string-match mh-user-path s) - (< (match-end 0) (1- (length s)))) - (format "+%s" - (substring s (match-end 0) (1- (length s)))) - (return 'error))) - (let* ((s (buffer-substring-no-properties (1+ (point)) end)) - (val (ignore-errors (read-from-string s)))) - (if (and (consp val) (numberp (car val))) - (car val) - (return 'error))) - nil))) - (forward-line))) - - - -;; Swish++ interface - -(defvar mh-swish++-binary (or (executable-find "search++") - (executable-find "search"))) -(defvar mh-swish++-directory ".swish++") - -;;;###mh-autoload -(defun mh-swish++-execute-search (folder-path search-regexp) - "Execute swish++ and read the results. - -In the examples below, replace \"/home/user/Mail\" with the path to -your MH directory. - -First create the directory \"/home/user/Mail/.swish++\". Then create -the file \"/home/user/Mail/.swish++/swish++.conf\" with the following -contents: - - IncludeMeta Bcc Cc Comments Content-Description From Keywords - IncludeMeta Newsgroups Resent-To Subject To - IncludeMeta Message-Id References In-Reply-To - IncludeFile Mail * - IndexFile /home/user/Mail/.swish++/swish++.index - -Use the following command line to generate the swish index. Run -this daily from cron: - - find /home/user/Mail -path /home/user/Mail/mhe-index -prune \\ - -o -path /home/user/Mail/.swish++ -prune \\ - -o -name \"[0-9]*\" -print \\ - | index -c /home/user/Mail/.swish++/swish++.conf - - -This command does not index the folders that hold the results of your -searches in \"+mhe-index\" since they tend to be ephemeral and the -original messages are indexed anyway. - -On some systems (Debian GNU/Linux, for example), use \"index++\" -instead of \"index\". - -In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP is -used to search." - (set-buffer (get-buffer-create mh-index-temp-buffer)) - (erase-buffer) - (unless mh-swish++-binary - (error "Set `mh-swish++-binary' appropriately")) - (call-process mh-swish++-binary nil '(t nil) nil - "-m" "10000" - (format "-i%s%s/swish++.index" - mh-user-path mh-swish++-directory) - search-regexp) - (goto-char (point-min)) - (setq mh-swish-folder - (let ((last-char (substring folder-path (1- (length folder-path))))) - (if (equal last-char "/") - folder-path - (format "%s/" folder-path))))) - -(defalias 'mh-swish++-next-result 'mh-swish-next-result) - -(defun mh-swish++-regexp-builder (regexp-list) - "Generate query for swish++. -REGEXP-LIST is an alist of fields and values." - (let ((regexp "")) - (dolist (elem regexp-list) - (when (cdr elem) - (setq regexp (concat regexp " and " - (if (car elem) "(" "") - (if (car elem) (symbol-name (car elem)) "") - (if (car elem) " = " "") - (mh-swish++-print-regexp (cdr elem)) - (if (car elem) ")" ""))))) - (substring regexp 4))) - -(defun mh-swish++-print-regexp (expr) - "Return infix expression corresponding to EXPR." - (cond ((atom expr) (format "%s" expr)) - ((eq (car expr) 'not) - (format "(not %s)" (mh-swish++-print-regexp (cadr expr)))) - (t (format "(%s %s %s)" (mh-swish++-print-regexp (cadr expr)) - (symbol-name (car expr)) - (mh-swish++-print-regexp (caddr expr)))))) - - - -;; Namazu interface - -(defvar mh-namazu-binary (executable-find "namazu")) -(defvar mh-namazu-directory ".namazu") -(defvar mh-namazu-folder nil) - -;;;###mh-autoload -(defun mh-namazu-execute-search (folder-path search-regexp) - "Execute namazu and read the results. - -In the examples below, replace \"/home/user/Mail\" with the path to -your MH directory. - -First create the directory \"/home/user/Mail/.namazu\". Then create -the file \"/home/user/Mail/.namazu/mknmzrc\" with the following -contents: - - package conf; # Don't remove this line! - $ADDRESS = 'user@localhost'; - $ALLOW_FILE = \"[0-9]*\"; - $EXCLUDE_PATH = \"^/home/user/Mail/(mhe-index|spam)\"; - -This configuration does not index the folders that hold the results of -your searches in \"+mhe-index\" since they tend to be ephemeral and -the original messages are indexed anyway. - -Use the following command line to generate the namazu index. Run this -daily from cron: - - mknmz -f /home/user/Mail/.namazu/mknmzrc -O /home/user/Mail/.namazu \\ - /home/user/Mail - -In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP -is used to search." - (let ((namazu-index-directory - (format "%s%s" mh-user-path mh-namazu-directory))) - (unless (file-exists-p namazu-index-directory) - (error "Namazu directory %s not present" namazu-index-directory)) - (unless (executable-find mh-namazu-binary) - (error "Set `mh-namazu-binary' appropriately")) - (set-buffer (get-buffer-create mh-index-temp-buffer)) - (erase-buffer) - (call-process mh-namazu-binary nil '(t nil) nil - "-alR" search-regexp namazu-index-directory) - (goto-char (point-min)) - (setq mh-namazu-folder - (let ((last (substring folder-path (1- (length folder-path))))) - (if (equal last "/") - folder-path - (format "%s/" folder-path)))))) - -(defun mh-namazu-next-result () - "Get the next result from namazu output." - (prog1 - (block nil - (when (eobp) (return nil)) - (let ((file-name (buffer-substring-no-properties - (point) (line-end-position)))) - (unless (equal (string-match mh-namazu-folder file-name) 0) - (return 'error)) - (unless (file-exists-p file-name) - (return 'error)) - (string-match mh-user-path file-name) - (let* ((folder/msg (substring file-name (match-end 0))) - (mark (mh-search-from-end ?/ folder/msg))) - (unless mark (return 'error)) - (list (format "+%s" (substring folder/msg 0 mark)) - (let ((n (ignore-errors (read-from-string - (substring folder/msg (1+ mark)))))) - (if (and (consp n) (numberp (car n))) - (car n) - (return 'error))) - nil)))) - (forward-line))) - - - -;;;###mh-autoload -(defun mh-index-choose () - "Choose an indexing function. -The side-effects of this function are that the variables -`mh-indexer', `mh-index-execute-search-function', and -`mh-index-next-result-function' are set according to the first -indexer in `mh-indexer-choices' present on the system." - (block nil - ;; The following favors the user's preference; otherwise, the last - ;; automatically chosen indexer is used for efficiency rather than going - ;; through the list. - (let ((program-alist (cond (mh-index-program - (list - (assoc mh-index-program mh-indexer-choices))) - (mh-indexer - (list (assoc mh-indexer mh-indexer-choices))) - (t mh-indexer-choices)))) - (while program-alist - (let* ((current (pop program-alist)) - (executable (symbol-value (cadr current)))) - (when executable - (setq mh-indexer (car current)) - (setq mh-index-execute-search-function (nth 2 current)) - (setq mh-index-next-result-function (nth 3 current)) - (setq mh-index-regexp-builder (nth 4 current)) - (return mh-indexer)))) - nil))) - - - -(provide 'mh-index) - -;; Local Variables: -;; indent-tabs-mode: nil -;; sentence-end-double-space: nil -;; End: - -;; arch-tag: 607762ad-0dff-4fe1-a27e-6c0dde0dcc47 -;;; mh-index ends here diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-init.el --- a/lisp/mh-e/mh-init.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-init.el Tue Jan 17 00:56:42 2006 +0000 @@ -39,9 +39,12 @@ ;;; Code: +;;(message "> mh-init") (eval-when-compile (require 'mh-acros)) (mh-require-cl) -(require 'mh-utils) +(require 'mh-buffers) +(require 'mh-exec) +;;(message "< mh-init") (defvar mh-sys-path '("/usr/local/nmh/bin" ; nmh default @@ -65,27 +68,9 @@ ;; was installed into. But if you installed MH after building Emacs, ;; this would almost certainly be wrong, so now we do it at run time. -(defvar mh-progs nil - "Directory containing MH commands, such as inc, repl, and rmm.") - -(defvar mh-lib nil - "Directory containing the MH library. -This directory contains, among other things, the components file.") - -(defvar mh-lib-progs nil - "Directory containing MH helper programs. -This directory contains, among other things, the mhl program.") - (defvar mh-flists-present-flag nil "Non-nil means that we have \"flists\".") -;;;###autoload -(put 'mh-progs 'risky-local-variable t) -;;;###autoload -(put 'mh-lib 'risky-local-variable t) -;;;###autoload -(put 'mh-lib-progs 'risky-local-variable t) - (defvar mh-variants nil "List describing known MH variants. Do not access this variable directly as it may not have yet been initialized. @@ -356,6 +341,31 @@ +;;; MH profile + +(defun mh-profile-component (component) + "Return COMPONENT value from mhparam, or nil if unset." + (save-excursion + (mh-exec-cmd-quiet nil "mhparam" "-components" component) + (mh-profile-component-value component))) + +(defun mh-profile-component-value (component) + "Find and return the value of COMPONENT in the current buffer. +Returns nil if the component is not in the buffer." + (let ((case-fold-search t)) + (goto-char (point-min)) + (cond ((not (re-search-forward (format "^%s:" component) nil t)) nil) + ((looking-at "[\t ]*$") nil) + (t + (re-search-forward "[\t ]*\\([^\t \n].*\\)$" nil t) + (let ((start (match-beginning 1))) + (end-of-line) + (buffer-substring start (point))))))) + + + +;;; MH-E images + ;; Shush compiler. (eval-when-compile (defvar image-load-path)) diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-junk.el --- a/lisp/mh-e/mh-junk.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-junk.el Tue Jan 17 00:56:42 2006 +0000 @@ -32,9 +32,12 @@ ;;; Code: +;;(message "< mh-junk") (eval-when-compile (require 'mh-acros)) (mh-require-cl) +(require 'mh-buffers) (require 'mh-e) +;;(message "> mh-junk") ;; Interactive functions callable from the folder buffer ;;;###mh-autoload diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-mime.el --- a/lisp/mh-e/mh-mime.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-mime.el Tue Jan 17 00:56:42 2006 +0000 @@ -36,12 +36,15 @@ ;;; Code: +;;(message "> mh-mime") (eval-when-compile (require 'mh-acros)) (mh-require-cl) (require 'gnus-util) +(require 'mh-buffers) (require 'mh-comp) (require 'mh-gnus) +;;(message "< mh-mime") (autoload 'article-emphasize "gnus-art") (autoload 'gnus-article-goto-header "gnus-art") @@ -73,41 +76,36 @@ (call-interactively 'mh-mh-attach-file))) ;;;###mh-autoload -(defun mh-compose-forward (&optional description folder messages) +(defun mh-compose-forward (&optional description folder range) "Add tag to forward a message. You are prompted for a content DESCRIPTION, the name of the -FOLDER in which the messages to forward are located, and the -MESSAGES' numbers. +FOLDER in which the messages to forward are located, and a RANGE +of messages, which defaults to the current message in that +folder. Check the documentation of `mh-interactive-range' to see +how RANGE is read in interactive use. The option `mh-compose-insertion' controls what type of tags are inserted." - (interactive (let* - ((description (mml-minibuffer-read-description)) - (folder (mh-prompt-for-folder "Message from" - mh-sent-from-folder nil)) - (messages (let ((default-message - (if (and (equal - folder mh-sent-from-folder) - (numberp mh-sent-from-msg)) - mh-sent-from-msg - (nth 0 (mh-translate-range - folder "cur"))))) - (if default-message - (read-string - (format "Messages (default %d): " - default-message) - nil nil - (number-to-string default-message)) - (read-string (format "Messages: ")))))) - (list description folder messages))) - (let - ((range)) - (if (null messages) - (setq messages "")) - (setq range (mh-translate-range folder messages)) - (if (null range) - (error "No messages in specified range")) - (dolist (message range) + (interactive + (let* ((description + (mml-minibuffer-read-description)) + (folder + (mh-prompt-for-folder "Message from" + mh-sent-from-folder nil)) + (default + (if (and (equal folder mh-sent-from-folder) + (numberp mh-sent-from-msg)) + mh-sent-from-msg + (nth 0 (mh-translate-range folder "cur")))) + (range + (mh-read-range "Forward" folder + (or (and default + (number-to-string default)) + t) + t t))) + (list description folder range))) + (let ((messages (mapconcat 'identity (mh-list-to-string range) " "))) + (dolist (message (mh-translate-range folder messages)) (if (equal mh-compose-insertion 'mml) (mh-mml-forward-message description folder (format "%s" message)) (mh-mh-forward-message description folder (format "%s" message)))))) @@ -134,7 +132,7 @@ "Regexp matching valid media types used in MIME attachment compositions.") (defvar mh-have-file-command 'undefined - "Cached value of `mh-have-file-command'. + "Cached value of function `mh-have-file-command'. Do not reference this variable directly as it might not have been initialized. Always use the command `mh-have-file-command'.") diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-pick.el --- a/lisp/mh-e/mh-pick.el Thu Jan 12 11:20:02 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,402 +0,0 @@ -;;; mh-pick.el --- make a search pattern and search for a message in MH-E - -;; Copyright (C) 1993, 1995, -;; 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. - -;; Author: Bill Wohler -;; Maintainer: Bill Wohler -;; Keywords: mail -;; See: mh-e.el - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -;; Boston, MA 02110-1301, USA. - -;;; Commentary: - -;; Internal support for MH-E package. - -;;; Change Log: - -;;; Code: - -(eval-when-compile (require 'mh-acros)) -(mh-require-cl) -(require 'mh-e) -(require 'easymenu) -(require 'gnus-util) - -;;; Internal variables: - -(defvar mh-pick-mode-map (make-sparse-keymap) - "Keymap for searching folder.") - -(defvar mh-searching-folder nil) ;Folder this pick is searching. -(defvar mh-searching-function nil) - -(defconst mh-pick-single-dash '(cc date from subject to) - "Search components that are supported by single-dash option in pick.") - -;;;###mh-autoload -(defun mh-search-folder (folder window-config) - "Search FOLDER for messages matching a pattern. - -With this command, you can search a folder for messages to or -from a particular person or about a particular subject. In fact, -you can also search for messages containing selected strings in -any arbitrary header field or any string found within the -messages. - -You are first prompted for the name of the folder to search and -then placed in the following buffer in MH-Pick mode: - - From: - To: - Cc: - Date: - Subject: - -------- - -Edit this template by entering your search criteria in an -appropriate header field that is already there, or create a new -field yourself. If the string you're looking for could be -anywhere in a message, then place the string underneath the row -of dashes. The command \\[mh-search-folder] uses the MH command -\"pick\" to do the real work. - -There are no semantics associated with the search criteria--they -are simply treated as strings. Case is ignored when all lowercase -is used, and regular expressions (a la \"ed\") are available. It -is all right to specify several search criteria. What happens -then is that a logical _and_ of the various fields is performed. -If you prefer a logical _or_ operation, run \\[mh-search-folder] -multiple times. - -As an example, let's say that we want to find messages from -Ginnean about horseback riding in the Kosciusko National -Park (Australia) during January, 1994. Normally we would start -with a broad search and narrow it down if necessary to produce a -manageable amount of data, but we'll cut to the chase and create -a fairly restrictive set of criteria as follows: - - From: ginnean - To: - Cc: - Date: Jan 1994 - Subject: horse.*kosciusko - -------- - -As with MH-Letter mode, MH-Pick provides commands like -\\\\[mh-to-field] to help you fill in the -blanks. - -To perform the search, type \\[mh-do-search]. The selected -messages are placed in the \"search\" sequence, which you can use -later in forwarding, printing, or narrowing your field of view. -Subsequent searches are appended to the \"search\" sequence. If, -however, you wish to start with a clean slate, first delete the -\"search\" sequence. - -If you're searching in a folder that is already displayed in an -MH-Folder buffer, only those messages contained in the buffer are -used for the search. Therefore, if you want to search in all -messages, first kill the folder's buffer with -\\\\[kill-buffer] or scan the entire folder -with \\[mh-rescan-folder]. - -If you find that you do the same thing over and over when editing -the search template, you may wish to bind some shortcuts to keys. -This can be done with the variable `mh-pick-mode-hook', which is -called when \\[mh-search-folder] is run on a new pattern. - -If you have run the \\[mh-index-search] command, but change your -mind while entering the search criteria and actually want to run -a regular search, then you can use the command -\\\\[mh-pick-do-search] in the MH-Pick buffer. - -In a program, argument WINDOW-CONFIG is the current window -configuration and is used when the search folder is dismissed." - (interactive (list (mh-prompt-for-folder "Search" mh-current-folder nil nil t) - (current-window-configuration))) - (let ((pick-folder (if (equal folder "+") mh-current-folder folder))) - (switch-to-buffer-other-window "search-pattern") - (if (or (zerop (buffer-size)) - (not (y-or-n-p "Reuse pattern? "))) - (mh-make-pick-template) - (message "")) - (setq mh-searching-function 'mh-pick-do-search - mh-searching-folder pick-folder) - (mh-make-local-vars 'mh-current-folder folder - 'mh-previous-window-config window-config) - (message "%s" (substitute-command-keys - (concat "Type \\[mh-do-search] to search messages, " - "\\[mh-help] for help"))))) - -(defun mh-make-pick-template () - "Initialize the current buffer with a template for a pick pattern." - (let ((inhibit-read-only t)) (erase-buffer)) - (insert "From: \n" - "To: \n" - "Cc: \n" - "Date: \n" - "Subject: \n" - "---------\n") - (mh-pick-mode) - (goto-char (point-min)) - (dotimes (i 5) - (add-text-properties (point) (1+ (point)) '(front-sticky t)) - (add-text-properties (- (line-end-position) 2) (1- (line-end-position)) - '(rear-nonsticky t)) - (add-text-properties (point) (1- (line-end-position)) '(read-only t)) - (forward-line)) - (add-text-properties (point) (1+ (point)) '(front-sticky t)) - (add-text-properties (point) (1- (line-end-position)) '(read-only t)) - (goto-char (point-max))) - - - -;;; Build mh-pick-mode menu - -;; Menu extracted from mh-menubar.el V1.1 (31 July 2001) -(easy-menu-define - mh-pick-menu mh-pick-mode-map "Menu for MH-E pick-mode" - '("Pick" - ["Execute the Search" mh-pick-do-search t])) - - - - -;;; Help Messages - -;; Group messages logically, more or less. -(defvar mh-pick-mode-help-messages - '((nil - "Search messages using pick: \\[mh-pick-do-search]\n" - "Search messages using index: \\[mh-index-do-search]\n" - "Move to a field by typing C-c C-f C-\n" - "where is the first letter of the desired field.")) - "Key binding cheat sheet. - -This is an associative array which is used to show the most common -commands. The key is a prefix char. The value is one or more strings -which are concatenated together and displayed in the minibuffer if ? -is pressed after the prefix character. The special key nil is used to -display the non-prefixed commands. - -The substitutions described in `substitute-command-keys' are performed -as well.") - -(put 'mh-pick-mode 'mode-class 'special) - -(define-derived-mode mh-pick-mode fundamental-mode "MH-Pick" - "Mode for creating search templates in MH-E.\\ - -After each field name, enter the pattern to search for. If a field's -value does not matter for the search, leave it empty. To search the -entire message, supply the pattern in the \"body\" of the template. -Each non-empty field must be matched for a message to be selected. To -effect a logical \"or\", use \\[mh-search-folder] multiple times. When -you have finished, type \\[mh-pick-do-search] to do the search. - -The hook `mh-pick-mode-hook' is called upon entry to this mode. - -\\{mh-pick-mode-map}" - - (make-local-variable 'mh-searching-folder) - (make-local-variable 'mh-searching-function) - (make-local-variable 'mh-help-messages) - (easy-menu-add mh-pick-menu) - (setq mh-help-messages mh-pick-mode-help-messages)) - -;;;###mh-autoload -(defun mh-pick-do-search () - "Find messages that match the qualifications in the current pattern buffer. - -Messages are searched for in the folder named in -`mh-searching-folder'. Add the messages found to the sequence -named \"search\"." - (interactive) - (let ((pattern-list (mh-pick-parse-search-buffer)) - (folder mh-searching-folder) - (new-buffer-flag nil) - (window-config mh-previous-window-config) - range pick-args msgs) - (unless pattern-list - (error "No search pattern specified")) - (save-excursion - (cond ((get-buffer folder) - (set-buffer folder) - (setq range (if (and mh-first-msg-num mh-last-msg-num) - (format "%d-%d" mh-first-msg-num mh-last-msg-num) - "all"))) - (t - (mh-make-folder folder) - (setq range "all") - (setq new-buffer-flag t)))) - (setq pick-args (mh-pick-regexp-builder pattern-list)) - (when pick-args - (setq msgs (mh-seq-from-command folder 'search - `("pick" ,folder ,range ,@pick-args)))) - (message "Searching...done") - (if (not new-buffer-flag) - (switch-to-buffer folder) - (mh-scan-folder folder msgs) - (setq mh-previous-window-config window-config)) - (mh-add-msgs-to-seq msgs 'search) - (delete-other-windows))) - -;;;###mh-autoload -(defun mh-do-search () - "Use the default searching function. - -If \\[mh-search-folder] was used to create the search pattern -then pick is used to search the folder. Otherwise if -\\[mh-index-search] was used then the indexing program specified -in `mh-index-program' is used." - (interactive) - (if (symbolp mh-searching-function) - (funcall mh-searching-function) - (error "No searching function defined"))) - -(defun mh-seq-from-command (folder seq command) - "In FOLDER, make a sequence named SEQ by executing COMMAND. -COMMAND is a list. The first element is a program name and the -subsequent elements are its arguments, all strings." - (let ((msg) - (msgs ()) - (case-fold-search t)) - (save-excursion - (save-window-excursion - (if (eq 0 (apply 'mh-exec-cmd-quiet nil command)) - ;; "pick" outputs one number per line - (while (setq msg (car (mh-read-msg-list))) - (setq msgs (cons msg msgs)) - (forward-line 1)))) - (set-buffer folder) - (setq msgs (nreverse msgs)) ;put in ascending order - msgs))) - -(defun mh-pick-parse-search-buffer () - "Parse the search buffer contents. -The function returns a alist. The car of each element is either -the header name to search in or nil to search the whole message. -The cdr of the element is the pattern to search." - (save-excursion - (let ((pattern-list ()) - (in-body-flag nil) - start begin) - (goto-char (point-min)) - (while (not (eobp)) - (if (search-forward "--------" (line-end-position) t) - (setq in-body-flag t) - (beginning-of-line) - (setq begin (point)) - (setq start (if in-body-flag - (point) - (search-forward ":" (line-end-position) t) - (point))) - (push (cons (and (not in-body-flag) - (intern (downcase - (buffer-substring-no-properties - begin (1- start))))) - (mh-index-parse-search-regexp - (buffer-substring-no-properties - start (line-end-position)))) - pattern-list)) - (forward-line)) - pattern-list))) - - - -;; Functions specific to how pick works... -(defun mh-pick-construct-regexp (expr component) - "Construct pick compatible expression corresponding to EXPR. -COMPONENT is the component to search." - (cond ((atom expr) (list component expr)) - ((eq (car expr) 'and) - `("-lbrace" ,@(mh-pick-construct-regexp (cadr expr) component) "-and" - ,@(mh-pick-construct-regexp (caddr expr) component) "-rbrace")) - ((eq (car expr) 'or) - `("-lbrace" ,@(mh-pick-construct-regexp (cadr expr) component) "-or" - ,@(mh-pick-construct-regexp (caddr expr) component) "-rbrace")) - ((eq (car expr) 'not) - `("-lbrace" "-not" ,@(mh-pick-construct-regexp (cadr expr) component) - "-rbrace")) - (t (error "Unknown operator %s seen" (car expr))))) - -;; All implementations of pick have special options -cc, -date, -from and -;; -subject that allow to search for corresponding components. Any other -;; component is searched using option --COMPNAME, for example: `pick -;; --x-mailer mh-e'. Mailutils "pick" supports this option using a certain -;; kludge, but it prefers the following syntax for this purpose: -;; "--component=COMPNAME --pattern=PATTERN". -;; -- Sergey Poznyakoff, Aug 2003 -(defun mh-pick-regexp-builder (pattern-list) - "Generate pick search expression from PATTERN-LIST." - (let ((result ())) - (dolist (pattern pattern-list) - (when (cdr pattern) - (setq result `(,@result "-and" "-lbrace" - ,@(mh-pick-construct-regexp - (if (and (mh-variant-p 'mu-mh) (car pattern)) - (format "--pattern=%s" (cdr pattern)) - (cdr pattern)) - (if (car pattern) - (cond - ((mh-variant-p 'mu-mh) - (format "--component=%s" (car pattern))) - ((member (car pattern) mh-pick-single-dash) - (format "-%s" (car pattern))) - (t - (format "--%s" (car pattern)))) - "-search")) - "-rbrace")))) - (cdr result))) - - - -;;; Build the pick-mode keymap: - -;; If this changes, modify mh-pick-mode-help-messages accordingly, above. -(gnus-define-keys mh-pick-mode-map - "\C-c?" mh-help - "\C-c\C-i" mh-index-do-search - "\C-c\C-p" mh-pick-do-search - "\C-c\C-c" mh-do-search - "\C-c\C-f\C-b" mh-to-field - "\C-c\C-f\C-c" mh-to-field - "\C-c\C-f\C-d" mh-to-field - "\C-c\C-f\C-f" mh-to-field - "\C-c\C-f\C-r" mh-to-field - "\C-c\C-f\C-s" mh-to-field - "\C-c\C-f\C-t" mh-to-field - "\C-c\C-fb" mh-to-field - "\C-c\C-fc" mh-to-field - "\C-c\C-fd" mh-to-field - "\C-c\C-ff" mh-to-field - "\C-c\C-fr" mh-to-field - "\C-c\C-fs" mh-to-field - "\C-c\C-ft" mh-to-field) - -(provide 'mh-pick) - -;; Local Variables: -;; indent-tabs-mode: nil -;; sentence-end-double-space: nil -;; End: - -;; arch-tag: aef2b271-7768-42bd-a782-9a14ba9f83f7 -;;; mh-pick.el ends here diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-print.el --- a/lisp/mh-e/mh-print.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-print.el Tue Jan 17 00:56:42 2006 +0000 @@ -1,6 +1,6 @@ ;;; mh-print.el --- MH-E printing support -;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. ;; Author: Jeffrey C Honig ;; Maintainer: Bill Wohler @@ -30,12 +30,15 @@ ;;; Code: +;;(message "> mh-print") (eval-when-compile (require 'mh-acros)) (mh-require-cl) (require 'ps-print) +(require 'mh-buffers) (require 'mh-utils) (require 'mh-funcs) (eval-when-compile (require 'mh-seq)) +;;(message "< mh-print") (defvar mh-ps-print-color-option ps-print-color-p "Specify how buffer's text color is printed. diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-search.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/mh-e/mh-search.el Tue Jan 17 00:56:42 2006 +0000 @@ -0,0 +1,1918 @@ +;;; mh-search --- MH-E search + +;; Copyright (C) 1993, 1995, +;; 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + +;; Author: Indexed search by Satyaki Das +;; Maintainer: Bill Wohler +;; Keywords: mail +;; See: mh-e.el + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; (1) The following search engines are supported: +;; swish++ +;; swish-e +;; mairix +;; namazu +;; pick +;; grep +;; +;; (2) To use this package, you first have to build an index. Please +;; read the documentation for `mh-search' to get started. That +;; documentation will direct you to the specific instructions for +;; your particular searcher. + +;;; Change Log: + +;;; Code: + +;;(message "> mh-search") +(eval-when-compile (require 'mh-acros)) +(mh-require-cl) + +(require 'gnus-util) +(require 'mh-buffers) +(require 'mh-e) +;;(message "< mh-search") + +(defvar mh-searcher nil + "Cached value of chosen search program.") + +(defvar mh-search-function nil + "Function which executes the search program.") + +(defvar mh-search-next-result-function nil + "Function to parse the next line of output. +Expected to return a list of three strings: name of the folder, +message number, and optionally the match.") + +(defvar mh-search-regexp-builder nil + "Function used to construct search regexp.") + +(defvar mh-index-folder "+mhe-index" + "Folder that contains the folders resulting from the index searches.") + +(defvar mh-flists-results-folder "sequence" + "Subfolder for `mh-index-folder' where flists output is placed.") + +(defvar mh-flists-sequence) + +(defvar mh-flists-called-flag nil) + + + +;;; MH-Search mode + +;;;###mh-autoload +(defun* mh-search (folder search-regexp + &optional redo-search-flag window-config) + "Search your MH mail. + +This command helps you find messages in your entire corpus of +mail. You can search for messages to or from a particular person +or about a particular subject. In fact, you can also search for +messages containing selected strings in any arbitrary header +field or any string found within the messages. + +Out of the box, MH-E uses \"pick\" to find messages. With a +little extra effort, you can set an indexing program which +rewards you with extremely quick results. The drawback is that +sometimes the index does not contain the words you're looking +for. You can still use \"pick\" in these situations. + +You are prompted for the FOLDER to search. This can be \"all\" to +search all folders. Note that the search works recursively on the +listed folder. + +Next, an MH-Search buffer appears where you can enter search +criteria SEARCH-REGEXP. + + From: + To: + Cc: + Date: + Subject: + -------- + +Edit this template by entering your search criteria in an +appropriate header field that is already there, or create a new +field yourself. If the string you're looking for could be +anywhere in a message, then place the string underneath the row +of dashes. + +As an example, let's say that we want to find messages from +Ginnean about horseback riding in the Kosciusko National +Park (Australia) during January, 1994. Normally we would start +with a broad search and narrow it down if necessary to produce a +manageable amount of data, but we'll cut to the chase and create +a fairly restrictive set of criteria as follows:\\ + + From: ginnean + To: + Cc: + Date: Jan 1994 + Subject: + -------- + horse + kosciusko + +As with MH-Letter mode, MH-Search provides commands like +\\[mh-to-field] to help you fill in the blanks.\\ + +If you find that you do the same thing over and over when editing +the search template, you may wish to bind some shortcuts to keys. +This can be done with the variable `mh-search-mode-hook', which is +called when \\[mh-search] is run on a new pattern.\\ + +To perform the search, type \\[mh-index-do-search]. + +Sometimes you're searching for text that is either not indexed, +or hasn't been indexed yet. In this case you can override the +default method with the pick method by running the command +\\[mh-pick-do-search]. + +The messages that are found are put in a temporary sub-folder of +\"+mhe-index\" and are displayed in an MH-Folder buffer. This +buffer is special because it displays messages from multiple +folders; each set of messages from a given folder has a heading +with the folder name.\\ + +The appearance of the heading can be modified by customizing the +face `mh-search-folder'. You can jump back and forth between the +headings using the commands \\[mh-index-next-folder] and +\\[mh-index-previous-folder]. + +In addition, the command \\[mh-index-visit-folder] can be used to +visit the folder of the message at point. Initially, only the +messages that matched the search criteria are displayed in the +folder. While the temporary buffer has its own set of message +numbers, the actual messages numbers are shown in the visited +folder. Thus, the command \\[mh-index-visit-folder] is useful to +find the actual message number of an interesting message, or to +view surrounding messages with the command \\[mh-rescan-folder]. + +Because this folder is temporary, you'll probably get in the +habit of killing it when you're done with \\[mh-kill-folder]. + +You can regenerate the results by running this command with a +prefix argument REDO-SEARCH-FLAG. + +Note: This command uses an \"X-MHE-Checksum:\" header field to +cache the MD5 checksum of a message. This means that if an +incoming message already contains an \"X-MHE-Checksum:\" field, +that message might not be found by this command. The following +\"procmail\" recipe avoids this problem by renaming the existing +header field: + + :0 wf + | formail -R \"X-MHE-Checksum\" \"X-Old-MHE-Checksum\" + +Configuring Indexed Searches + +The command \\[mh-search] runs the command defined by the option +`mh-search-program'. The default value is \"Auto-detect\" which +means that MH-E will automatically choose one of \"swish++\", +\"swish-e\", \"mairix\", \"namazu\", \"pick\" and \"grep\" in +that order. If, for example, you have both \"swish++\" and +\"mairix\" installed and you want to use \"mairix\", then you can +set this option to \"mairix\". + +The documentation for the following commands describe how to set +up the various indexing programs to use with MH-E. + + - `mh-swish++-execute-search' + - `mh-swish-execute-search' + - `mh-mairix-execute-search' + - `mh-namazu-execute-search' + - `mh-pick-execute-search' + - `mh-grep-execute-search' + +In a program, if FOLDER is \"+\" or nil, then mail in all folders +are searched. Optional argument WINDOW-CONFIG stores the window +configuration that will be restored after the user quits the +folder containing the index search results." + (interactive + (list (progn + (mh-find-path) + ;; Yes, we do want to call mh-search-choose every time in case the + ;; user has switched the searcher manually. + (unless (mh-search-choose (and current-prefix-arg + mh-index-previous-search + (cadr mh-index-previous-search))) + (error "No search program found")) + (or (and current-prefix-arg mh-index-sequence-search-flag) + (and current-prefix-arg (car mh-index-previous-search)) + (mh-prompt-for-folder "Search" "+" nil "all" t))) + (or (and current-prefix-arg (caddr mh-index-previous-search)) + mh-search-regexp-builder + (read-string (format "%s regexp: " + (upcase-initials (symbol-name mh-searcher))))) + current-prefix-arg + (if (and (not (and current-prefix-arg + (caddr mh-index-previous-search))) + mh-search-regexp-builder) + (current-window-configuration) + nil))) + ;; Redoing a sequence search? + (when (and redo-search-flag mh-index-data mh-index-sequence-search-flag + (not mh-flists-called-flag)) + (let ((mh-flists-called-flag t)) + (apply #'mh-index-sequenced-messages mh-index-previous-search)) + (return-from mh-search)) + ;; We have fancy query parsing. + (when (symbolp search-regexp) + (mh-search-folder folder window-config) + (return-from mh-search)) + ;; Begin search proper. + (mh-checksum-choose) + (let ((result-count 0) + (old-window-config (or window-config mh-previous-window-config)) + (previous-search mh-index-previous-search) + (index-folder (format "%s/%s" mh-index-folder + (mh-index-generate-pretty-name search-regexp)))) + ;; Create a new folder for the search results or recreate the old one... + (if (and redo-search-flag mh-index-previous-search) + (let ((buffer-name (buffer-name (current-buffer)))) + (mh-process-or-undo-commands buffer-name) + (save-excursion (mh-exec-cmd-quiet nil "rmf" buffer-name)) + (mh-exec-cmd-quiet nil "folder" "-create" "-fast" buffer-name) + (setq index-folder buffer-name)) + (setq index-folder (mh-index-new-folder index-folder search-regexp))) + + (let ((folder-path (format "%s%s" mh-user-path (substring folder 1))) + (folder-results-map (make-hash-table :test #'equal)) + (origin-map (make-hash-table :test #'equal))) + ;; Run search program... + (message "Executing %s... " mh-searcher) + (funcall mh-search-function folder-path search-regexp) + + ;; Parse searcher output. + (message "Processing %s output... " mh-searcher) + (goto-char (point-min)) + (loop for next-result = (funcall mh-search-next-result-function) + while next-result + do (unless (eq next-result 'error) + (unless (gethash (car next-result) folder-results-map) + (setf (gethash (car next-result) folder-results-map) + (make-hash-table :test #'equal))) + (setf (gethash (cadr next-result) + (gethash (car next-result) folder-results-map)) + t))) + + ;; Copy the search results over. + (maphash #'(lambda (folder msgs) + (let ((cur (car (mh-translate-range folder "cur"))) + (msgs (sort (loop for msg being the hash-keys of msgs + collect msg) + #'<))) + (mh-exec-cmd "refile" msgs "-src" folder + "-link" index-folder) + ;; Restore cur to old value, that refile changed + (when cur + (mh-exec-cmd-quiet nil "mark" folder "-add" "-zero" + "-sequence" "cur" (format "%s" cur))) + (loop for msg in msgs + do (incf result-count) + (setf (gethash result-count origin-map) + (cons folder msg))))) + folder-results-map) + + ;; Vist the results folder. + (mh-visit-folder index-folder () (list folder-results-map origin-map)) + + (goto-char (point-min)) + (forward-line) + (mh-update-sequences) + (mh-recenter nil) + + ;; Update the speedbar, if needed. + (when (mh-speed-flists-active-p) + (mh-speed-flists t mh-current-folder)) + + ;; Maintain history. + (when (or (and redo-search-flag previous-search) window-config) + (setq mh-previous-window-config old-window-config)) + (setq mh-index-previous-search (list folder mh-searcher search-regexp)) + + ;; Write out data to disk. + (unless mh-flists-called-flag (mh-index-write-data)) + + (message "%s found %s matches in %s folders" + (upcase-initials (symbol-name mh-searcher)) + (loop for msg-hash being hash-values of mh-index-data + sum (hash-table-count msg-hash)) + (loop for msg-hash being hash-values of mh-index-data + count (> (hash-table-count msg-hash) 0)))))) + +(defun mh-search-folder (folder window-config) + "Search FOLDER for messages matching a pattern. + +In a program, argument WINDOW-CONFIG is the current window +configuration and is used when the search folder is dismissed." + (interactive (list (mh-prompt-for-folder "Search" mh-current-folder nil nil t) + (current-window-configuration))) + (let ((pick-folder (if (equal folder "+") mh-current-folder folder))) + (switch-to-buffer-other-window "search-pattern") + (if (or (zerop (buffer-size)) + (not (y-or-n-p "Reuse pattern? "))) + (mh-make-pick-template) + (message "")) + (mh-make-local-vars 'mh-current-folder folder + 'mh-previous-window-config window-config) + (message "%s" (substitute-command-keys + (concat "Type \\[mh-index-do-search] to search messages, " + "\\[mh-pick-do-search] to use pick, " + "\\[mh-help] for help"))))) + +(defun mh-make-pick-template () + "Initialize the current buffer with a template for a pick pattern." + (let ((inhibit-read-only t)) (erase-buffer)) + (insert "From: \n" + "To: \n" + "Cc: \n" + "Date: \n" + "Subject: \n" + "---------\n") + (mh-search-mode) + (goto-char (point-min)) + (dotimes (i 5) + (add-text-properties (point) (1+ (point)) '(front-sticky t)) + (add-text-properties (- (line-end-position) 2) (1- (line-end-position)) + '(rear-nonsticky t)) + (add-text-properties (point) (1- (line-end-position)) '(read-only t)) + (forward-line)) + (add-text-properties (point) (1+ (point)) '(front-sticky t)) + (add-text-properties (point) (1- (line-end-position)) '(read-only t)) + (goto-char (point-max))) + +;;;###mh-autoload +(defvar mh-search-mode-map (make-sparse-keymap) + "Keymap for searching folder.") + +;;;###mh-autoload +;; If this changes, modify mh-search-mode-help-messages accordingly, below. +(gnus-define-keys mh-search-mode-map + "\C-c?" mh-help + "\C-c\C-c" mh-index-do-search + "\C-c\C-p" mh-pick-do-search + "\C-c\C-f\C-b" mh-to-field + "\C-c\C-f\C-c" mh-to-field + "\C-c\C-f\C-d" mh-to-field + "\C-c\C-f\C-f" mh-to-field + "\C-c\C-f\C-r" mh-to-field + "\C-c\C-f\C-s" mh-to-field + "\C-c\C-f\C-t" mh-to-field + "\C-c\C-fb" mh-to-field + "\C-c\C-fc" mh-to-field + "\C-c\C-fd" mh-to-field + "\C-c\C-ff" mh-to-field + "\C-c\C-fr" mh-to-field + "\C-c\C-fs" mh-to-field + "\C-c\C-ft" mh-to-field) + +(easy-menu-define + mh-pick-menu mh-search-mode-map "Menu for MH-E Search" + '("Search" + ["Perform Search" mh-index-do-search t] + ["Search with pick" mh-pick-do-search t])) + +;; Group messages logically, more or less. +(defvar mh-search-mode-help-messages + '((nil + "Perform search: \\[mh-index-do-search]\n" + "Search with pick: \\[mh-pick-do-search]\n" + "Move to a field by typing C-c C-f C-\n" + "where is the first letter of the desired field\n" + "(except for From: which uses \"m\").")) + "Key binding cheat sheet. + +This is an associative array which is used to show the most common +commands. The key is a prefix char. The value is one or more strings +which are concatenated together and displayed in the minibuffer if ? +is pressed after the prefix character. The special key nil is used to +display the non-prefixed commands. + +The substitutions described in `substitute-command-keys' are performed +as well.") + +(put 'mh-search-mode 'mode-class 'special) + +(define-derived-mode mh-search-mode fundamental-mode "MH-Search" + "Mode for creating search templates in MH-E.\\ + +Edit this template by entering your search criteria in an +appropriate header field that is already there, or create a new +field yourself. If the string you're looking for could be +anywhere in a message, then place the string underneath the row +of dashes. + +To perform the search, type \\[mh-index-do-search]. + +Sometimes you're searching for text that is either not indexed, +or hasn't been indexed yet. In this case you can override the +default method with the pick method by running the command +\\[mh-pick-do-search]. + +The hook `mh-search-mode-hook' is called upon entry to this mode. + +\\{mh-search-mode-map}" + + (make-local-variable 'mh-help-messages) + (easy-menu-add mh-pick-menu) + (setq mh-help-messages mh-search-mode-help-messages)) + +;;;###mh-autoload +(defun mh-index-do-search (&optional searcher) + "Find messages using `mh-search-program'. +If optional argument SEARCHER is present, use it instead of +`mh-search-program'." + (interactive) + (unless (mh-search-choose searcher) (error "No search program found")) + (let* ((regexp-list (mh-pick-parse-search-buffer)) + (pattern (funcall mh-search-regexp-builder regexp-list))) + (if pattern + (mh-search mh-current-folder pattern nil mh-previous-window-config) + (error "No search terms")))) + +;;;###mh-autoload +(defun mh-pick-do-search () + "Find messages using \"pick\". + +Uses the pick method described in `mh-pick-execute-search'." + (interactive) + (mh-index-do-search 'pick)) + +(defun mh-pick-parse-search-buffer () + "Parse the search buffer contents. +The function returns a alist. The car of each element is either +the header name to search in or nil to search the whole message. +The cdr of the element is the pattern to search." + (save-excursion + (let ((pattern-list ()) + (in-body-flag nil) + start begin) + (goto-char (point-min)) + (while (not (eobp)) + (if (search-forward "--------" (line-end-position) t) + (setq in-body-flag t) + (beginning-of-line) + (setq begin (point)) + (setq start (if in-body-flag + (point) + (search-forward ":" (line-end-position) t) + (point))) + (push (cons (and (not in-body-flag) + (intern (downcase + (buffer-substring-no-properties + begin (1- start))))) + (mh-index-parse-search-regexp + (buffer-substring-no-properties + start (line-end-position)))) + pattern-list)) + (forward-line)) + pattern-list))) + +;;;###mh-autoload +(defun mh-index-parse-search-regexp (input-string) + "Construct parse tree for INPUT-STRING. +All occurrences of &, |, ! and ~ in INPUT-STRING are replaced by +AND, OR and NOT as appropriate. Then the resulting string is +parsed." + (let (input) + (with-temp-buffer + (insert input-string) + ;; replace tabs + (mh-replace-string "\t" " ") + ;; synonyms of AND + (mh-replace-string " AND " " and ") + (mh-replace-string "&" " and ") + (mh-replace-string " -and " " and ") + ;; synonyms of OR + (mh-replace-string " OR " " or ") + (mh-replace-string "|" " or ") + (mh-replace-string " -or " " or ") + ;; synonyms of NOT + (mh-replace-string " NOT " " not ") + (mh-replace-string "!" " not ") + (mh-replace-string "~" " not ") + (mh-replace-string " -not " " not ") + ;; synonyms of left brace + (mh-replace-string "(" " ( ") + (mh-replace-string " -lbrace " " ( ") + ;; synonyms of right brace + (mh-replace-string ")" " ) ") + (mh-replace-string " -rbrace " " ) ") + ;; get the normalized input + (setq input (format "( %s )" (buffer-substring (point-min) (point-max))))) + + (let ((tokens (mh-index-add-implicit-ops (split-string input))) + (op-stack ()) + (operand-stack ()) + oper1) + (dolist (token tokens) + (cond ((equal token "(") (push 'paren op-stack)) + ((equal token "not") (push 'not op-stack)) + ((equal token "or") (push 'or op-stack)) + ((equal token "and") (push 'and op-stack)) + ((equal token ")") + (multiple-value-setq (op-stack operand-stack) + (mh-index-evaluate op-stack operand-stack)) + (when (eq (car op-stack) 'not) + (setq op-stack (cdr op-stack)) + (push `(not ,(pop operand-stack)) operand-stack)) + (when (eq (car op-stack) 'and) + (setq op-stack (cdr op-stack)) + (setq oper1 (pop operand-stack)) + (push `(and ,(pop operand-stack) ,oper1) operand-stack))) + ((eq (car op-stack) 'not) + (setq op-stack (cdr op-stack)) + (push `(not ,token) operand-stack) + (when (eq (car op-stack) 'and) + (setq op-stack (cdr op-stack)) + (setq oper1 (pop operand-stack)) + (push `(and ,(pop operand-stack) ,oper1) operand-stack))) + ((eq (car op-stack) 'and) + (setq op-stack (cdr op-stack)) + (push `(and ,(pop operand-stack) ,token) operand-stack)) + (t (push token operand-stack)))) + (prog1 (pop operand-stack) + (when (or op-stack operand-stack) + (error "Invalid regexp: %s" input)))))) + +(defun mh-index-add-implicit-ops (tokens) + "Add implicit operators in the list TOKENS." + (let ((result ()) + (literal-seen nil) + current) + (while tokens + (setq current (pop tokens)) + (cond ((or (equal current ")") (equal current "and") (equal current "or")) + (setq literal-seen nil) + (push current result)) + ((and literal-seen + (push "and" result) + (setq literal-seen nil) + nil)) + (t + (push current result) + (unless (or (equal current "(") (equal current "not")) + (setq literal-seen t))))) + (nreverse result))) + +(defun mh-index-evaluate (op-stack operand-stack) + "Read expression till starting paren based on OP-STACK and OPERAND-STACK." + (block mh-index-evaluate + (let (op oper1) + (while op-stack + (setq op (pop op-stack)) + (cond ((eq op 'paren) + (return-from mh-index-evaluate (values op-stack operand-stack))) + ((eq op 'not) + (push `(not ,(pop operand-stack)) operand-stack)) + ((or (eq op 'and) (eq op 'or)) + (setq oper1 (pop operand-stack)) + (push `(,op ,(pop operand-stack) ,oper1) operand-stack)))) + (error "Ran out of tokens")))) + + + +;;; Sequence browsing + +;;;###mh-autoload +(defun mh-index-new-messages (folders) + "Display unseen messages. + +If you use a program such as \"procmail\" to use \"rcvstore\" to file +your incoming mail automatically, you can display new, unseen, +messages using this command. All messages in the \"unseen\" +sequence from the folders in `mh-new-messages-folders' are +listed. + +With a prefix argument, enter a space-separated list of FOLDERS, +or nothing to search all folders." + (interactive + (list (if current-prefix-arg + (split-string (read-string "Search folder(s) (default all): ")) + mh-new-messages-folders))) + (mh-index-sequenced-messages folders mh-unseen-seq)) + +;;;###mh-autoload +(defun mh-index-ticked-messages (folders) + "Display ticked messages. + +All messages in `mh-tick-seq' from the folders in +`mh-ticked-messages-folders' are listed. + +With a prefix argument, enter a space-separated list of FOLDERS, +or nothing to search all folders." + (interactive + (list (if current-prefix-arg + (split-string (read-string "Search folder(s) (default all): ")) + mh-ticked-messages-folders))) + (mh-index-sequenced-messages folders mh-tick-seq)) + +;;;###mh-autoload +(defun mh-index-sequenced-messages (folders sequence) + "Display messages in any sequence. + +All messages from the FOLDERS in `mh-new-messages-folders' in the +SEQUENCE you provide are listed. With a prefix argument, enter a +space-separated list of folders at the prompt, or nothing to +search all folders." + (interactive + (list (if current-prefix-arg + (split-string (read-string "Search folder(s) (default all): ")) + mh-new-messages-folders) + (mh-read-seq-default "Search" nil))) + (unless sequence (setq sequence mh-unseen-seq)) + (let* ((mh-flists-search-folders folders) + (mh-flists-sequence sequence) + (mh-flists-called-flag t) + (mh-searcher 'flists) + (mh-search-function 'mh-flists-execute) + (mh-search-next-result-function 'mh-mairix-next-result) + (mh-mairix-folder mh-user-path) + (mh-search-regexp-builder nil) + (new-folder (format "%s/%s/%s" mh-index-folder + mh-flists-results-folder sequence)) + (window-config (if (equal new-folder mh-current-folder) + mh-previous-window-config + (current-window-configuration))) + (redo-flag nil) + message) + (cond ((buffer-live-p (get-buffer new-folder)) + ;; The destination folder is being visited. Trick `mh-search' + ;; into thinking that the folder resulted from a previous search. + (set-buffer new-folder) + (setq mh-index-previous-search (list folders mh-searcher sequence)) + (setq redo-flag t)) + ((mh-folder-exists-p new-folder) + ;; Folder exists but we don't have it open. That means they are + ;; stale results from a old flists search. Clear it out. + (mh-exec-cmd-quiet nil "rmf" new-folder))) + (setq message (mh-search "+" mh-flists-results-folder + redo-flag window-config) + mh-index-sequence-search-flag t + mh-index-previous-search (list folders mh-searcher sequence)) + (mh-index-write-data) + (when (stringp message) (message "%s" message)))) + +(defvar mh-flists-search-folders) + +(defun mh-flists-execute (&rest args) + "Execute flists. +Search for messages belonging to `mh-flists-sequence' in the +folders specified by `mh-flists-search-folders'. If +`mh-recursive-folders-flag' is t, then the folders are searched +recursively. All parameters ARGS are ignored." + (set-buffer (get-buffer-create mh-temp-index-buffer)) + (erase-buffer) + (unless (executable-find "sh") + (error "Didn't find sh")) + (with-temp-buffer + (let ((seq (symbol-name mh-flists-sequence))) + (insert "for folder in `" (expand-file-name "flists" mh-progs) " " + (cond ((eq mh-flists-search-folders t) + (mh-quote-for-shell mh-inbox)) + ((eq mh-flists-search-folders nil) "") + ((listp mh-flists-search-folders) + (loop for folder in mh-flists-search-folders + concat + (concat " " (mh-quote-for-shell folder))))) + (if mh-recursive-folders-flag " -recurse" "") + " -sequence " seq " -noshowzero -fast` ; do\n" + (expand-file-name "mhpath" mh-progs) " \"+$folder\" " seq "\n" + "done\n")) + (call-process-region + (point-min) (point-max) "sh" nil (get-buffer mh-temp-index-buffer)))) + + + +;;; Folder navigation and utilities + +;;;###mh-autoload +(defun mh-index-group-by-folder () + "Partition the messages based on source folder. +Returns an alist with the the folder names in the car and the cdr +being the list of messages originally from that folder." + (save-excursion + (goto-char (point-min)) + (let ((result-table (make-hash-table :test #'equal))) + (loop for msg being hash-keys of mh-index-msg-checksum-map + do (push msg (gethash (car (gethash + (gethash msg mh-index-msg-checksum-map) + mh-index-checksum-origin-map)) + result-table))) + (loop for x being the hash-keys of result-table + collect (cons x (nreverse (gethash x result-table))))))) + +;;;###mh-autoload +(defun mh-index-insert-folder-headers () + "Annotate the search results with original folder names." + (let ((cur-msg (mh-get-msg-num nil)) + (old-buffer-modified-flag (buffer-modified-p)) + (buffer-read-only nil) + current-folder last-folder) + (goto-char (point-min)) + (while (not (eobp)) + (setq current-folder (car (gethash (gethash (mh-get-msg-num nil) + mh-index-msg-checksum-map) + mh-index-checksum-origin-map))) + (when (and current-folder (not (equal current-folder last-folder))) + (insert (if last-folder "\n" "") current-folder "\n") + (setq last-folder current-folder)) + (forward-line)) + (when cur-msg + (mh-notate-cur) + (mh-goto-msg cur-msg t)) + (set-buffer-modified-p old-buffer-modified-flag)) + (mh-index-create-imenu-index)) + +;;;###mh-autoload +(defun mh-index-delete-folder-headers () + "Delete the folder headers." + (let ((cur-msg (mh-get-msg-num nil)) + (old-buffer-modified-flag (buffer-modified-p)) + (buffer-read-only nil)) + (while (and (not cur-msg) (not (eobp))) + (forward-line) + (setq cur-msg (mh-get-msg-num nil))) + (goto-char (point-min)) + (while (not (eobp)) + (if (or (char-equal (char-after) ?+) (char-equal (char-after) 10)) + (delete-region (point) (progn (forward-line) (point))) + (forward-line))) + (when cur-msg (mh-goto-msg cur-msg t t)) + (set-buffer-modified-p old-buffer-modified-flag))) + +;;;###mh-autoload +(defun mh-index-create-imenu-index () + "Create alist of folder names and positions in index folder buffers." + (save-excursion + (setq which-func-mode t) + (let ((alist ())) + (goto-char (point-min)) + (while (re-search-forward "^+" nil t) + (save-excursion + (beginning-of-line) + (push (cons (buffer-substring-no-properties + (point) (line-end-position)) + (set-marker (make-marker) (point))) + alist))) + (setq imenu--index-alist (nreverse alist))))) + +;;;###mh-autoload +(defun mh-index-next-folder (&optional backward-flag) + "Jump to the next folder marker. + +With non-nil optional argument BACKWARD-FLAG, jump to the previous +group of results." + (interactive "P") + (if (null mh-index-data) + (message "Only applicable in an MH-E index search buffer") + (let ((point (point))) + (forward-line (if backward-flag 0 1)) + (cond ((if backward-flag + (re-search-backward "^+" (point-min) t) + (re-search-forward "^+" (point-max) t)) + (beginning-of-line)) + ((and (if backward-flag + (goto-char (point-max)) + (goto-char (point-min))) + nil)) + ((if backward-flag + (re-search-backward "^+" (point-min) t) + (re-search-forward "^+" (point-max) t)) + (beginning-of-line)) + (t (goto-char point)))))) + +;;;###mh-autoload +(defun mh-index-previous-folder () + "Jump to the previous folder marker." + (interactive) + (mh-index-next-folder t)) + +;;;###mh-autoload +(defun mh-index-visit-folder () + "Visit original folder from where the message at point was found." + (interactive) + (unless mh-index-data + (error "Not in an index folder")) + (let (folder msg) + (save-excursion + (cond ((and (bolp) (eolp)) + (ignore-errors (forward-line -1)) + (setq msg (mh-get-msg-num t))) + ((equal (char-after (line-beginning-position)) ?+) + (setq folder (buffer-substring-no-properties + (line-beginning-position) (line-end-position)))) + (t (setq msg (mh-get-msg-num t))))) + (when (not folder) + (setq folder (car (gethash (gethash msg mh-index-msg-checksum-map) + mh-index-checksum-origin-map)))) + (when (or (not (get-buffer folder)) + (y-or-n-p (format "Reuse buffer displaying %s? " folder))) + (mh-visit-folder + folder (loop for x being the hash-keys of (gethash folder mh-index-data) + when (mh-msg-exists-p x folder) collect x))))) + +;;;###mh-autoload +(defun mh-search-p () + "Non-nil means that this folder was generated by searching." + mh-index-data) + +;;;###mh-autoload +(defun mh-index-execute-commands () + "Delete/refile the actual messages. +The copies in the searched folder are then deleted/refiled to get +the desired result. Before deleting the messages we make sure +that the message being deleted is identical to the one that the +user has marked in the index buffer." + (save-excursion + (let ((folders ()) + (mh-speed-flists-inhibit-flag t)) + (maphash + (lambda (folder msgs) + (push folder folders) + (if (not (get-buffer folder)) + ;; If source folder not open, just delete the messages... + (apply #'mh-exec-cmd "rmm" folder (mh-coalesce-msg-list msgs)) + ;; Otherwise delete the messages in the source buffer... + (save-excursion + (set-buffer folder) + (let ((old-refile-list mh-refile-list) + (old-delete-list mh-delete-list)) + (setq mh-refile-list nil + mh-delete-list msgs) + (unwind-protect (mh-execute-commands) + (setq mh-refile-list + (mapcar (lambda (x) + (cons (car x) + (loop for y in (cdr x) + unless (memq y msgs) collect y))) + old-refile-list) + mh-delete-list + (loop for x in old-delete-list + unless (memq x msgs) collect x)) + (mh-set-folder-modified-p (mh-outstanding-commands-p)) + (when (mh-outstanding-commands-p) + (mh-notate-deleted-and-refiled))))))) + (mh-index-matching-source-msgs (append (loop for x in mh-refile-list + append (cdr x)) + mh-delete-list) + t)) + folders))) + + + +;;; Indexing functions + +;; Support different search programs +(defvar mh-search-choices + '((swish++ + mh-swish++-binary mh-swish++-execute-search mh-swish++-next-result + mh-swish++-regexp-builder) + (swish + mh-swish-binary mh-swish-execute-search mh-swish-next-result nil) + (mairix + mh-mairix-binary mh-mairix-execute-search mh-mairix-next-result + mh-mairix-regexp-builder) + (namazu + mh-namazu-binary mh-namazu-execute-search mh-namazu-next-result nil) + (pick + mh-pick-binary mh-pick-execute-search mh-pick-next-result + mh-pick-regexp-builder) + (grep + mh-grep-binary mh-grep-execute-search mh-grep-next-result nil)) + "List of possible searcher choices.") + +(defun mh-search-choose (&optional searcher) + "Choose a searching function. +The side-effects of this function are that the variables +`mh-searcher', `mh-search-function', and +`mh-search-next-result-function' are set according to the first +searcher in `mh-search-choices' present on the system. If +optional argument SEARCHER is present, use it instead of +`mh-search-program'." + (block nil + (let ((program-alist (cond (searcher + (list (assoc searcher mh-search-choices))) + (mh-search-program + (list + (assoc mh-search-program mh-search-choices))) + (t mh-search-choices)))) + (while program-alist + (let* ((current (pop program-alist)) + (executable (symbol-value (cadr current)))) + (when executable + (setq mh-searcher (car current)) + (setq mh-search-function (nth 2 current)) + (setq mh-search-next-result-function (nth 3 current)) + (setq mh-search-regexp-builder (nth 4 current)) + (return mh-searcher)))) + nil))) + +;;; Swish++ interface + +(defvar mh-swish++-binary (or (executable-find "search++") + (executable-find "search"))) +(defvar mh-swish++-directory ".swish++") +(defvar mh-swish-folder nil) + +;;;###mh-autoload +(defun mh-swish++-execute-search (folder-path search-regexp) + "Execute swish++. + +In the examples below, replace \"/home/user/Mail\" with the path to +your MH directory. + +First create the directory \"/home/user/Mail/.swish++\". Then create +the file \"/home/user/Mail/.swish++/swish++.conf\" with the following +contents: + + IncludeMeta Bcc Cc Comments Content-Description From Keywords + IncludeMeta Newsgroups Resent-To Subject To + IncludeMeta Message-Id References In-Reply-To + IncludeFile Mail * + IndexFile /home/user/Mail/.swish++/swish++.index + +Use the following command line to generate the swish index. Run +this daily from cron: + + find /home/user/Mail -path /home/user/Mail/mhe-index -prune \\ + -o -path /home/user/Mail/.swish++ -prune \\ + -o -name \"[0-9]*\" -print \\ + | index -c /home/user/Mail/.swish++/swish++.conf - + +This command does not index the folders that hold the results of your +searches in \"+mhe-index\" since they tend to be ephemeral and the +original messages are indexed anyway. + +On some systems (Debian GNU/Linux, for example), use \"index++\" +instead of \"index\". + +In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP is +used to search." + (set-buffer (get-buffer-create mh-temp-index-buffer)) + (erase-buffer) + (unless mh-swish++-binary + (error "Set `mh-swish++-binary' appropriately")) + (call-process mh-swish++-binary nil '(t nil) nil + "-m" "10000" + (format "-i%s%s/swish++.index" + mh-user-path mh-swish++-directory) + search-regexp) + (goto-char (point-min)) + (setq mh-swish-folder + (let ((last-char (substring folder-path (1- (length folder-path))))) + (if (equal last-char "/") + folder-path + (format "%s/" folder-path))))) + +(defalias 'mh-swish++-next-result 'mh-swish-next-result) + +(defun mh-swish++-regexp-builder (regexp-list) + "Generate query for swish++. +REGEXP-LIST is an alist of fields and values." + (let ((regexp "")) + (dolist (elem regexp-list) + (when (cdr elem) + (setq regexp (concat regexp " and " + (if (car elem) "(" "") + (if (car elem) (symbol-name (car elem)) "") + (if (car elem) " = " "") + (mh-swish++-print-regexp (cdr elem)) + (if (car elem) ")" ""))))) + (substring regexp 4))) + +(defun mh-swish++-print-regexp (expr) + "Return infix expression corresponding to EXPR." + (cond ((atom expr) (format "%s" expr)) + ((eq (car expr) 'not) + (format "(not %s)" (mh-swish++-print-regexp (cadr expr)))) + (t (format "(%s %s %s)" (mh-swish++-print-regexp (cadr expr)) + (symbol-name (car expr)) + (mh-swish++-print-regexp (caddr expr)))))) + +;;; Swish interface + +(defvar mh-swish-binary (executable-find "swish-e")) +(defvar mh-swish-directory ".swish") + +;;;###mh-autoload +(defun mh-swish-execute-search (folder-path search-regexp) + "Execute swish-e. + +In the examples below, replace \"/home/user/Mail\" with the path +to your MH directory. + +First create the directory \"/home/user/Mail/.swish\". Then +create the file \"/home/user/Mail/.swish/config\" with the +following contents: + + DefaultContents TXT* + IndexDir /home/user/Mail + IndexFile /home/user/Mail/.swish/index + IndexName \"Mail Index\" + IndexDescription \"Mail Index\" + IndexPointer \"http://nowhere\" + IndexAdmin \"nobody\" + #MetaNames automatic + IndexReport 3 + FollowSymLinks no + UseStemming no + IgnoreTotalWordCountWhenRanking yes + WordCharacters abcdefghijklmnopqrstuvwxyz0123456789- + BeginCharacters abcdefghijklmnopqrstuvwxyz + EndCharacters abcdefghijklmnopqrstuvwxyz0123456789 + IgnoreLimit 50 1000 + IndexComments 0 + FileRules filename contains \\D + FileRules pathname contains /home/user/Mail/.swish + FileRules pathname contains /home/user/Mail/mhe-index + +This configuration does not index the folders that hold the +results of your searches in \"+mhe-index\" since they tend to be +ephemeral and the original messages are indexed anyway. + +If there are any directories you would like to ignore, append +lines like the following to \"config\": + + FileRules pathname contains /home/user/Mail/scripts + +Use the following command line to generate the swish index. Run +this daily from cron: + + swish-e -c /home/user/Mail/.swish/config + +In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP +is used to search." + (set-buffer (get-buffer-create mh-temp-index-buffer)) + (erase-buffer) + (unless mh-swish-binary + (error "Set `mh-swish-binary' appropriately")) + (call-process mh-swish-binary nil '(t nil) nil + "-w" search-regexp + "-f" (format "%s%s/index" mh-user-path mh-swish-directory)) + (goto-char (point-min)) + (setq mh-swish-folder + (let ((last-char (substring folder-path (1- (length folder-path))))) + (if (equal last-char "/") + folder-path + (format "%s/" folder-path))))) + +(defun mh-swish-next-result () + "Get the next result from swish output." + (prog1 + (block nil + (when (or (eobp) (equal (char-after (point)) ?.)) + (return nil)) + (when (equal (char-after (point)) ?#) + (return 'error)) + (let* ((start (search-forward " " (line-end-position) t)) + (end (search-forward " " (line-end-position) t))) + (unless (and start end) + (return 'error)) + (setq end (1- end)) + (unless (file-exists-p (buffer-substring-no-properties start end)) + (return 'error)) + (unless (search-backward "/" start t) + (return 'error)) + (list (let* ((s (buffer-substring-no-properties start (1+ (point))))) + (unless (string-match mh-swish-folder s) + (return 'error)) + (if (and (string-match mh-user-path s) + (< (match-end 0) (1- (length s)))) + (format "+%s" + (substring s (match-end 0) (1- (length s)))) + (return 'error))) + (let* ((s (buffer-substring-no-properties (1+ (point)) end)) + (val (ignore-errors (read-from-string s)))) + (if (and (consp val) (numberp (car val))) + (car val) + (return 'error))) + nil))) + (forward-line))) + +;;; Mairix interface + +(defvar mh-mairix-binary (executable-find "mairix")) +(defvar mh-mairix-directory ".mairix") +(defvar mh-mairix-folder nil) + +;;;###mh-autoload +(defun mh-mairix-execute-search (folder-path search-regexp-list) + "Execute mairix. + +In the examples below, replace \"/home/user/Mail\" with the path +to your MH directory. + +First create the directory \"/home/user/Mail/.mairix\". Then +create the file \"/home/user/Mail/.mairix/config\" with the +following contents: + + base=/home/user/Mail + + # List of folders that should be indexed. 3 dots at the end means there + # are subfolders within the folder + mh=archive...:inbox:drafts:news:sent:trash + + vfolder_format=raw + database=/home/user/Mail/mairix/database + +Use the following command line to generate the mairix index. Run +this daily from cron: + + mairix -f /home/user/Mail/.mairix/config + +In a program, FOLDER-PATH is the directory in which +SEARCH-REGEXP-LIST is used to search." + (set-buffer (get-buffer-create mh-temp-index-buffer)) + (erase-buffer) + (unless mh-mairix-binary + (error "Set `mh-mairix-binary' appropriately")) + (apply #'call-process mh-mairix-binary nil '(t nil) nil + "-r" "-f" (format "%s%s/config" mh-user-path mh-mairix-directory) + search-regexp-list) + (goto-char (point-min)) + (setq mh-mairix-folder + (let ((last-char (substring folder-path (1- (length folder-path))))) + (if (equal last-char "/") + folder-path + (format "%s/" folder-path))))) + +(defun mh-mairix-next-result () + "Return next result from mairix output." + (prog1 + (block nil + (when (or (eobp) (and (bolp) (eolp))) + (return nil)) + (unless (eq (char-after) ?/) + (return 'error)) + (let ((start (point)) + end msg-start) + (setq end (line-end-position)) + (unless (search-forward mh-mairix-folder end t) + (return 'error)) + (goto-char (match-beginning 0)) + (unless (equal (point) start) + (return 'error)) + (goto-char end) + (unless (search-backward "/" start t) + (return 'error)) + (setq msg-start (1+ (point))) + (goto-char start) + (unless (search-forward mh-user-path end t) + (return 'error)) + (list (format "+%s" (buffer-substring-no-properties + (point) (1- msg-start))) + (car (read-from-string + (buffer-substring-no-properties msg-start end))) + nil))) + (forward-line))) + +(defun mh-mairix-regexp-builder (regexp-list) + "Generate query for mairix. +REGEXP-LIST is an alist of fields and values." + (let ((result ())) + (dolist (pair regexp-list) + (when (cdr pair) + (push + (concat + (cond ((eq (car pair) 'to) "t:") + ((eq (car pair) 'from) "f:") + ((eq (car pair) 'cc) "c:") + ((eq (car pair) 'subject) "s:") + ((eq (car pair) 'date) "d:") + (t "")) + (let ((sop (cdr (mh-mairix-convert-to-sop* (cdr pair)))) + (final "")) + (dolist (conjunct sop) + (let ((expr-list (cdr conjunct)) + (expr-string "")) + (dolist (e expr-list) + (setq expr-string (concat expr-string "," + (if (atom e) "" "~") + (if (atom e) e (cadr e))))) + (setq final (concat final "/" (substring expr-string 1))))) + (substring final 1))) + result))) + result)) + +(defun mh-mairix-convert-to-sop* (expr) + "Convert EXPR to sum of product form." + (cond ((atom expr) `(or (and ,expr))) + ((eq (car expr) 'or) + (cons 'or + (loop for e in (mapcar #'mh-mairix-convert-to-sop* (cdr expr)) + append (cdr e)))) + ((eq (car expr) 'and) + (let ((conjuncts (mapcar #'mh-mairix-convert-to-sop* (cdr expr))) + result next-factor) + (setq result (pop conjuncts)) + (while conjuncts + (setq next-factor (pop conjuncts)) + (setq result (let ((res ())) + (dolist (t1 (cdr result)) + (dolist (t2 (cdr next-factor)) + (push `(and ,@(cdr t1) ,@(cdr t2)) res))) + (cons 'or res)))) + result)) + ((atom (cadr expr)) `(or (and ,expr))) + ((eq (caadr expr) 'not) (mh-mairix-convert-to-sop* (cadadr expr))) + ((eq (caadr expr) 'and) (mh-mairix-convert-to-sop* + `(or ,@(mapcar #'(lambda (x) `(not ,x)) + (cdadr expr))))) + ((eq (caadr expr) 'or) (mh-mairix-convert-to-sop* + `(and ,@(mapcar #'(lambda (x) `(not ,x)) + (cdadr expr))))) + (t (error "Unreachable: %s" expr)))) + +;;; Namazu interface + +(defvar mh-namazu-binary (executable-find "namazu")) +(defvar mh-namazu-directory ".namazu") +(defvar mh-namazu-folder nil) + +;;;###mh-autoload +(defun mh-namazu-execute-search (folder-path search-regexp) + "Execute namazu. + +In the examples below, replace \"/home/user/Mail\" with the path to +your MH directory. + +First create the directory \"/home/user/Mail/.namazu\". Then create +the file \"/home/user/Mail/.namazu/mknmzrc\" with the following +contents: + + package conf; # Don't remove this line! + $ADDRESS = 'user@localhost'; + $ALLOW_FILE = \"[0-9]*\"; + $EXCLUDE_PATH = \"^/home/user/Mail/(mhe-index|spam)\"; + +This configuration does not index the folders that hold the results of +your searches in \"+mhe-index\" since they tend to be ephemeral and +the original messages are indexed anyway. + +Use the following command line to generate the namazu index. Run this +daily from cron: + + mknmz -f /home/user/Mail/.namazu/mknmzrc -O /home/user/Mail/.namazu \\ + /home/user/Mail + +In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP +is used to search." + (let ((namazu-index-directory + (format "%s%s" mh-user-path mh-namazu-directory))) + (unless (file-exists-p namazu-index-directory) + (error "Namazu directory %s not present" namazu-index-directory)) + (unless (executable-find mh-namazu-binary) + (error "Set `mh-namazu-binary' appropriately")) + (set-buffer (get-buffer-create mh-temp-index-buffer)) + (erase-buffer) + (call-process mh-namazu-binary nil '(t nil) nil + "-alR" search-regexp namazu-index-directory) + (goto-char (point-min)) + (setq mh-namazu-folder + (let ((last (substring folder-path (1- (length folder-path))))) + (if (equal last "/") + folder-path + (format "%s/" folder-path)))))) + +(defun mh-namazu-next-result () + "Get the next result from namazu output." + (prog1 + (block nil + (when (eobp) (return nil)) + (let ((file-name (buffer-substring-no-properties + (point) (line-end-position)))) + (unless (equal (string-match mh-namazu-folder file-name) 0) + (return 'error)) + (unless (file-exists-p file-name) + (return 'error)) + (string-match mh-user-path file-name) + (let* ((folder/msg (substring file-name (match-end 0))) + (mark (mh-search-from-end ?/ folder/msg))) + (unless mark (return 'error)) + (list (format "+%s" (substring folder/msg 0 mark)) + (let ((n (ignore-errors (read-from-string + (substring folder/msg (1+ mark)))))) + (if (and (consp n) (numberp (car n))) + (car n) + (return 'error))) + nil)))) + (forward-line))) + +;;; Pick interface + +(defvar mh-index-pick-folder) +(defvar mh-pick-binary "pick") +(defconst mh-pick-single-dash '(cc date from subject to) + "Search components that are supported by single-dash option in pick.") + +;;;###mh-autoload +(defun mh-pick-execute-search (folder-path search-regexp) + "Execute pick. + +Read \"pick(1)\" or the section Finding Messages with pick in the +MH book to find out more about how to enter the criteria (see URL +`http://www.ics.uci.edu/~mh/book/mh/finpic.htm'). + +In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP +is used to search." + (set-buffer (get-buffer-create mh-temp-index-buffer)) + (erase-buffer) + (let ((folders + (mh-folder-list (substring folder-path (length mh-user-path))))) + (loop for folder in folders do + (setq folder (concat "+" folder)) + (insert folder "\n") + (apply #'call-process (expand-file-name "pick" mh-progs) + nil '(t nil) nil folder "-list" search-regexp))) + (goto-char (point-min))) + +(defun mh-pick-next-result () + "Return the next pick search result." + (prog1 + (block nil + (when (eobp) (return nil)) + (when (search-forward-regexp "^\+" (line-end-position) t) + (setq mh-index-pick-folder + (buffer-substring-no-properties (line-beginning-position) + (line-end-position))) + (return 'error)) + (unless (search-forward-regexp "^[1-9][0-9]*$" (line-end-position) t) + (return 'error)) + (list mh-index-pick-folder + (string-to-number + (buffer-substring-no-properties (line-beginning-position) + (line-end-position))) + nil)) + (forward-line))) + +;; All implementations of pick have special options -cc, -date, -from and +;; -subject that allow to search for corresponding components. Any other +;; component is searched using option --COMPNAME, for example: `pick +;; --x-mailer mh-e'. Mailutils "pick" supports this option using a certain +;; kludge, but it prefers the following syntax for this purpose: +;; "--component=COMPNAME --pattern=PATTERN". +;; -- Sergey Poznyakoff, Aug 2003 +(defun mh-pick-regexp-builder (pattern-list) + "Generate pick search expression from PATTERN-LIST." + (let ((result ())) + (dolist (pattern pattern-list) + (when (cdr pattern) + (setq result `(,@result "-and" "-lbrace" + ,@(mh-pick-construct-regexp + (if (and (mh-variant-p 'mu-mh) (car pattern)) + (format "--pattern=%s" (cdr pattern)) + (cdr pattern)) + (if (car pattern) + (cond + ((mh-variant-p 'mu-mh) + (format "--component=%s" (car pattern))) + ((member (car pattern) mh-pick-single-dash) + (format "-%s" (car pattern))) + (t + (format "--%s" (car pattern)))) + "-search")) + "-rbrace")))) + (cdr result))) + +(defun mh-pick-construct-regexp (expr component) + "Construct pick compatible expression corresponding to EXPR. +COMPONENT is the component to search." + (cond ((atom expr) (list component expr)) + ((eq (car expr) 'and) + `("-lbrace" ,@(mh-pick-construct-regexp (cadr expr) component) "-and" + ,@(mh-pick-construct-regexp (caddr expr) component) "-rbrace")) + ((eq (car expr) 'or) + `("-lbrace" ,@(mh-pick-construct-regexp (cadr expr) component) "-or" + ,@(mh-pick-construct-regexp (caddr expr) component) "-rbrace")) + ((eq (car expr) 'not) + `("-lbrace" "-not" ,@(mh-pick-construct-regexp (cadr expr) component) + "-rbrace")) + (t (error "Unknown operator %s seen" (car expr))))) + +;;; Grep interface + +(defvar mh-grep-binary (executable-find "grep")) + +;;;###mh-autoload +(defun mh-grep-execute-search (folder-path search-regexp) + "Execute grep. + +Unlike the other search methods, this method does not use the +MH-Search buffer. Instead, you simply enter a regular expression +in the minibuffer. For help in constructing regular expressions, +see your man page for \"grep\". + +In a program, FOLDER-PATH is the directory in which SEARCH-REGEXP +is used to search." + (set-buffer (get-buffer-create mh-temp-index-buffer)) + (erase-buffer) + (call-process mh-grep-binary nil '(t nil) nil + "-i" "-r" search-regexp folder-path) + (goto-char (point-min))) + +(defun mh-grep-next-result () + "Read the next result. +Parse it and return the message folder, message index and the +match. If no other matches left then return nil. If the current +record is invalid return 'error." + (prog1 + (block nil + (when (eobp) + (return nil)) + (let ((eol-pos (line-end-position)) + (bol-pos (line-beginning-position)) + folder-start msg-end) + (goto-char bol-pos) + (unless (search-forward mh-user-path eol-pos t) + (return 'error)) + (setq folder-start (point)) + (unless (search-forward ":" eol-pos t) + (return 'error)) + (let ((match (buffer-substring-no-properties (point) eol-pos))) + (forward-char -1) + (setq msg-end (point)) + (unless (search-backward "/" folder-start t) + (return 'error)) + (list (format "+%s" (buffer-substring-no-properties + folder-start (point))) + (let ((val (ignore-errors (read-from-string + (buffer-substring-no-properties + (1+ (point)) msg-end))))) + (if (and (consp val) (integerp (car val))) + (car val) + (return 'error))) + match)))) + (forward-line))) + + + +;;; Folder support + +(defun mh-index-generate-pretty-name (string) + "Given STRING generate a name which is suitable for use as a folder name. +White space from the beginning and end are removed. All spaces in +the name are replaced with underscores and all / are replaced +with $. If STRING is longer than 20 it is truncated too. STRING +could be a list of strings in which case they are concatenated to +construct the base name." + (with-temp-buffer + (if (stringp string) + (insert string) + (when (car string) (insert (car string))) + (dolist (s (cdr string)) + (insert "_" s))) + (setq string (mh-replace-string "-lbrace" " ")) + (setq string (mh-replace-string "-rbrace" " ")) + (setq string (mh-replace-string "-search" " ")) + (subst-char-in-region (point-min) (point-max) ?( ? t) + (subst-char-in-region (point-min) (point-max) ?) ? t) + (subst-char-in-region (point-min) (point-max) ?- ? t) + (goto-char (point-min)) + (while (and (not (eobp)) (memq (char-after) '(? ?\t ?\n ?\r ?_))) + (delete-char 1)) + (goto-char (point-max)) + (while (and (not (bobp)) (memq (char-before) '(? ?\t ?\n ?\r ?_))) + (delete-backward-char 1)) + (subst-char-in-region (point-min) (point-max) ? ?_ t) + (subst-char-in-region (point-min) (point-max) ?\t ?_ t) + (subst-char-in-region (point-min) (point-max) ?\n ?_ t) + (subst-char-in-region (point-min) (point-max) ?\r ?_ t) + (subst-char-in-region (point-min) (point-max) ?/ ?$ t) + (let ((out (truncate-string-to-width (buffer-string) 20))) + (cond ((eq mh-searcher 'flists) + (format "%s/%s" mh-flists-results-folder mh-flists-sequence)) + ((equal out mh-flists-results-folder) (concat out "1")) + (t out))))) + +(defun mh-folder-exists-p (folder) + "Check if FOLDER exists." + (and (mh-folder-name-p folder) + (save-excursion + (with-temp-buffer + (mh-exec-cmd-output "folder" nil "-fast" "-nocreate" folder) + (goto-char (point-min)) + (not (eobp)))))) + +(defun mh-msg-exists-p (msg folder) + "Check if MSG exists in FOLDER." + (file-exists-p (format "%s%s/%s" mh-user-path (substring folder 1) msg))) + +(defun mh-index-new-folder (name search-regexp) + "Return a folder name based on NAME for search results of SEARCH-REGEXP. + +If folder NAME already exists and was generated for the same +SEARCH-REGEXP then it is reused. + +Otherwise if the folder NAME was generated from a different +search then check if NAME<2> can be used. Otherwise try NAME<3>. +This is repeated till we find a new folder name. + +If the folder returned doesn't exist then it is created." + (unless (mh-folder-name-p name) + (error "The argument should be a valid MH folder name")) + (let ((chosen-name + (loop for i from 1 + for candidate = (if (equal i 1) name (format "%s<%s>" name i)) + when (or (not (mh-folder-exists-p candidate)) + (equal (mh-index-folder-search-regexp candidate) + search-regexp)) + return candidate))) + ;; Do pending refiles/deletes... + (when (get-buffer chosen-name) + (mh-process-or-undo-commands chosen-name)) + ;; Recreate folder... + (save-excursion (mh-exec-cmd-quiet nil "rmf" chosen-name)) + (mh-exec-cmd-quiet nil "folder" "-create" "-fast" chosen-name) + (mh-remove-from-sub-folders-cache chosen-name) + (when (boundp 'mh-speed-folder-map) + (mh-speed-add-folder chosen-name)) + chosen-name)) + +(defun mh-index-folder-search-regexp (folder) + "If FOLDER was created by a index search, return the search regexp. +Return nil if FOLDER doesn't exist or the .mhe_index file is +garbled." + (ignore-errors + (with-temp-buffer + (insert-file-contents + (format "%s%s/%s" mh-user-path (substring folder 1) mh-index-data-file)) + (goto-char (point-min)) + (forward-list 3) + (cadr (read (current-buffer)))))) + + + +;;; Sequence support + +;;;###mh-autoload +(defun mh-index-create-sequences () + "Mirror sequences present in source folders in index folder." + (let ((seq-hash (make-hash-table :test #'equal)) + (seq-list ())) + (loop for folder being the hash-keys of mh-index-data + do (setf (gethash folder seq-hash) + (mh-create-sequence-map + (mh-read-folder-sequences folder nil)))) + (dolist (msg (mh-translate-range mh-current-folder "all")) + (let* ((checksum (gethash msg mh-index-msg-checksum-map)) + (pair (gethash checksum mh-index-checksum-origin-map)) + (ofolder (car pair)) + (omsg (cdr pair))) + (loop for seq in (ignore-errors + (gethash omsg (gethash ofolder seq-hash))) + do (if (assoc seq seq-list) + (push msg (cdr (assoc seq seq-list))) + (push (list seq msg) seq-list))))) + (loop for seq in seq-list + do (apply #'mh-exec-cmd "mark" mh-current-folder + "-sequence" (symbol-name (car seq)) "-add" + (mapcar #'(lambda (x) (format "%s" x)) (cdr seq)))))) + +;;;###mh-autoload +(defun mh-create-sequence-map (seq-list) + "Return a map from msg number to list of sequences in which it is present. +SEQ-LIST is an assoc list whose keys are sequence names and whose +cdr is the list of messages in that sequence." + (loop with map = (make-hash-table) + for seq in seq-list + when (and (not (memq (car seq) (mh-unpropagated-sequences))) + (mh-valid-seq-p (car seq))) + do (loop for msg in (cdr seq) + do (push (car seq) (gethash msg map))) + finally return map)) + +;;;###mh-autoload +(defun mh-index-add-to-sequence (seq msgs) + "Add to SEQ the messages in the list MSGS. +This function updates the source folder sequences. Also makes an +attempt to update the source folder buffer if we have it open." + ;; Don't need to do anything for cur + (save-excursion + (when (and (not (memq seq (mh-unpropagated-sequences))) + (mh-valid-seq-p seq)) + (let ((folders ()) + (mh-speed-flists-inhibit-flag t)) + (maphash (lambda (folder msgs) + (push folder folders) + ;; Add messages to sequence in source folder... + (apply #'mh-exec-cmd-quiet nil "mark" folder + "-add" "-nozero" "-sequence" (symbol-name seq) + (mapcar (lambda (x) (format "%s" x)) + (mh-coalesce-msg-list msgs))) + ;; Update source folder buffer if we have it open... + (when (get-buffer folder) + (save-excursion + (set-buffer folder) + (mh-put-msg-in-seq msgs seq)))) + (mh-index-matching-source-msgs msgs)) + folders)))) + +;;;###mh-autoload +(defun mh-index-delete-from-sequence (seq msgs) + "Delete from SEQ the messages in MSGS. +This function updates the source folder sequences. Also makes an +attempt to update the source folder buffer if present." + (save-excursion + (when (and (not (memq seq (mh-unpropagated-sequences))) + (mh-valid-seq-p seq)) + (let ((folders ()) + (mh-speed-flists-inhibit-flag t)) + (maphash (lambda (folder msgs) + (push folder folders) + ;; Remove messages from sequence in source folder... + (apply #'mh-exec-cmd-quiet nil "mark" folder + "-del" "-nozero" "-sequence" (symbol-name seq) + (mapcar (lambda (x) (format "%s" x)) + (mh-coalesce-msg-list msgs))) + ;; Update source folder buffer if we have it open... + (when (get-buffer folder) + (save-excursion + (set-buffer folder) + (mh-delete-msg-from-seq msgs seq t)))) + (mh-index-matching-source-msgs msgs)) + folders)))) + +(defvar mh-unpropagated-sequences '(cur range subject search) + "List of sequences that aren't preserved.") + +(defun mh-unpropagated-sequences () + "Return a list of sequences that aren't propagated to the source folders. +It is just the sequences in the variable +`mh-unpropagated-sequences' in addition to the +Previous-Sequence (see mh-profile 5)." + (if mh-previous-seq + (cons mh-previous-seq mh-unpropagated-sequences) + mh-unpropagated-sequences)) + +(defun mh-index-matching-source-msgs (msgs &optional delete-from-index-data) + "Return a table of original messages and folders for messages in MSGS. +If optional argument DELETE-FROM-INDEX-DATA is non-nil, then each +of the messages, whose counter-part is found in some source +folder, is removed from `mh-index-data'." + (let ((table (make-hash-table :test #'equal))) + (dolist (msg msgs) + (let* ((checksum (gethash msg mh-index-msg-checksum-map)) + (pair (gethash checksum mh-index-checksum-origin-map))) + (when (and checksum (car pair) (cdr pair) + (mh-index-match-checksum (cdr pair) (car pair) checksum)) + (push (cdr pair) (gethash (car pair) table)) + (when delete-from-index-data + (remhash (cdr pair) (gethash (car pair) mh-index-data)))))) + table)) + +(defun mh-index-match-checksum (msg folder checksum) + "Check if MSG in FOLDER has X-MHE-Checksum header value of CHECKSUM." + (with-temp-buffer + (mh-exec-cmd-output mh-scan-prog nil "-width" "80" + "-format" "%{x-mhe-checksum}\n" folder msg) + (goto-char (point-min)) + (string-equal (buffer-substring-no-properties (point) (line-end-position)) + checksum))) + + + +;;; Serialization of index data + +(defun mh-index-write-data () + "Write index data to file." + (ignore-errors + (unless (eq major-mode 'mh-folder-mode) + (error "Can't be called from folder in \"%s\"" major-mode)) + (let ((data mh-index-data) + (msg-checksum-map mh-index-msg-checksum-map) + (checksum-origin-map mh-index-checksum-origin-map) + (previous-search mh-index-previous-search) + (sequence-search-flag mh-index-sequence-search-flag) + (outfile (concat buffer-file-name mh-index-data-file)) + (print-length nil) + (print-level nil)) + (with-temp-file outfile + (mh-index-write-hashtable + data (lambda (x) (loop for y being the hash-keys of x collect y))) + (mh-index-write-hashtable msg-checksum-map #'identity) + (mh-index-write-hashtable checksum-origin-map #'identity) + (pp previous-search (current-buffer)) (insert "\n") + (pp sequence-search-flag (current-buffer)) (insert "\n"))))) + +(defun mh-index-write-hashtable (table proc) + "Write TABLE to `current-buffer'. +PROC is used to serialize the values corresponding to the hash +table keys." + (pp (loop for x being the hash-keys of table + collect (cons x (funcall proc (gethash x table)))) + (current-buffer)) + (insert "\n")) + +;;;###mh-autoload +(defun mh-index-read-data () + "Read index data from file." + (ignore-errors + (unless (eq major-mode 'mh-folder-mode) + (error "Can't be called from folder in \"%s\"" major-mode)) + (let ((infile (concat buffer-file-name mh-index-data-file)) + t1 t2 t3 t4 t5) + (with-temp-buffer + (insert-file-contents-literally infile) + (goto-char (point-min)) + (setq t1 (mh-index-read-hashtable + (lambda (data) + (loop with table = (make-hash-table :test #'equal) + for x in data do (setf (gethash x table) t) + finally return table))) + t2 (mh-index-read-hashtable #'identity) + t3 (mh-index-read-hashtable #'identity) + t4 (read (current-buffer)) + t5 (read (current-buffer)))) + (setq mh-index-data t1 + mh-index-msg-checksum-map t2 + mh-index-checksum-origin-map t3 + mh-index-previous-search t4 + mh-index-sequence-search-flag t5)))) + +(defun mh-index-read-hashtable (proc) + "From BUFFER read a hash table serialized as a list. +PROC is used to convert the value to actual data." + (loop with table = (make-hash-table :test #'equal) + for pair in (read (current-buffer)) + do (setf (gethash (car pair) table) (funcall proc (cdr pair))) + finally return table)) + + + +;;; Checksum routines + +;; A few different checksum programs are supported. The supported programs +;; are: +;; +;; 1. md5sum +;; 2. md5 +;; 3. openssl +;; +;; To add support for your favorite checksum program add a clause to the cond +;; statement in mh-checksum-choose. This should set the variable +;; mh-checksum-cmd to the command line needed to run the checsum program and +;; should set mh-checksum-parser to a function which returns a cons cell +;; containing the message number and checksum string. + +(defvar mh-checksum-cmd) +(defvar mh-checksum-parser) + +(defun mh-checksum-choose () + "Check if a program to create a checksum is present." + (unless (boundp 'mh-checksum-cmd) + (let ((exec-path (append '("/sbin" "/usr/sbin") exec-path))) + (cond ((executable-find "md5sum") + (setq mh-checksum-cmd (list (executable-find "md5sum"))) + (setq mh-checksum-parser #'mh-md5sum-parser)) + ((executable-find "openssl") + (setq mh-checksum-cmd (list (executable-find "openssl") "md5")) + (setq mh-checksum-parser #'mh-openssl-parser)) + ((executable-find "md5") + (setq mh-checksum-cmd (list (executable-find "md5"))) + (setq mh-checksum-parser #'mh-md5-parser)) + (t (error "No suitable checksum program")))))) + +(defun mh-md5sum-parser () + "Parse md5sum output." + (let ((begin (line-beginning-position)) + (end (line-end-position)) + first-space last-slash) + (setq first-space (search-forward " " end t)) + (goto-char end) + (setq last-slash (search-backward "/" begin t)) + (cond ((and first-space last-slash) + (cons (car (read-from-string (buffer-substring-no-properties + (1+ last-slash) end))) + (buffer-substring-no-properties begin (1- first-space)))) + (t (cons nil nil))))) + +(defun mh-openssl-parser () + "Parse openssl output." + (let ((begin (line-beginning-position)) + (end (line-end-position)) + last-space last-slash) + (goto-char end) + (setq last-space (search-backward " " begin t)) + (setq last-slash (search-backward "/" begin t)) + (cond ((and last-slash last-space) + (cons (car (read-from-string (buffer-substring-no-properties + (1+ last-slash) (1- last-space)))) + (buffer-substring-no-properties (1+ last-space) end)))))) + +(defalias 'mh-md5-parser 'mh-openssl-parser) + +;;;###mh-autoload +(defun mh-index-update-maps (folder &optional origin-map) + "Annotate all as yet unannotated messages in FOLDER with their MD5 hash. +As a side effect msg -> checksum map is updated. Optional +argument ORIGIN-MAP is a hashtable which maps each message in the +index folder to the original folder and message from whence it +was copied. If present the checksum -> (origin-folder, +origin-index) map is updated too." + (clrhash mh-index-msg-checksum-map) + (save-excursion + ;; Clear temp buffer + (set-buffer (get-buffer-create mh-temp-checksum-buffer)) + (erase-buffer) + ;; Run scan to check if any messages needs MD5 annotations at all + (with-temp-buffer + (mh-exec-cmd-output mh-scan-prog nil "-width" "80" + "-format" "%(msg)\n%{x-mhe-checksum}\n" + folder "all") + (goto-char (point-min)) + (let (msg checksum) + (while (not (eobp)) + (setq msg (buffer-substring-no-properties + (point) (line-end-position))) + (forward-line) + (save-excursion + (cond ((not (string-match "^[0-9]*$" msg))) + ((eolp) + ;; need to compute checksum + (set-buffer mh-temp-checksum-buffer) + (insert mh-user-path (substring folder 1) "/" msg "\n")) + (t + ;; update maps + (setq checksum (buffer-substring-no-properties + (point) (line-end-position))) + (let ((msg (car (read-from-string msg)))) + (set-buffer folder) + (mh-index-update-single-msg msg checksum origin-map))))) + (forward-line)))) + ;; Run checksum program if needed + (unless (and (eobp) (bobp)) + (apply #'mh-xargs mh-checksum-cmd) + (goto-char (point-min)) + (while (not (eobp)) + (let* ((intermediate (funcall mh-checksum-parser)) + (msg (car intermediate)) + (checksum (cdr intermediate))) + (when msg + ;; annotate + (mh-exec-cmd "anno" folder msg "-component" "X-MHE-Checksum" + "-nodate" "-text" checksum "-inplace") + ;; update maps + (save-excursion + (set-buffer folder) + (mh-index-update-single-msg msg checksum origin-map))) + (forward-line))))) + (mh-index-write-data)) + +(defun mh-index-update-single-msg (msg checksum origin-map) + "Update various maps for one message. +MSG is a index folder message, CHECKSUM its MD5 hash and +ORIGIN-MAP, if non-nil, a hashtable containing which maps each +message in the index folder to the folder and message that it was +copied from. The function updates the hash tables +`mh-index-msg-checksum-map' and `mh-index-checksum-origin-map'. + +This function should only be called in the appropriate index +folder buffer." + (cond ((and origin-map (gethash checksum mh-index-checksum-origin-map)) + (let* ((intermediate (gethash msg origin-map)) + (ofolder (car intermediate)) + (omsg (cdr intermediate))) + ;; This is most probably a duplicate. So eliminate it. + (call-process "rm" nil nil nil + (format "%s%s/%s" mh-user-path + (substring mh-current-folder 1) msg)) + (when (gethash ofolder mh-index-data) + (remhash omsg (gethash ofolder mh-index-data))))) + (t + (setf (gethash msg mh-index-msg-checksum-map) checksum) + (when origin-map + (setf (gethash checksum mh-index-checksum-origin-map) + (gethash msg origin-map)))))) + +(provide 'mh-search) + +;; Local Variables: +;; indent-tabs-mode: nil +;; sentence-end-double-space: nil +;; End: + +;; arch-tag: 607762ad-0dff-4fe1-a27e-6c0dde0dcc47 +;;; mh-search ends here diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-seq.el --- a/lisp/mh-e/mh-seq.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-seq.el Tue Jan 17 00:56:42 2006 +0000 @@ -71,10 +71,13 @@ ;;; Code: +;;(message "> mh-seq") (eval-when-compile (require 'mh-acros)) (mh-require-cl) +(require 'mh-buffers) (require 'mh-e) +;;(message "< mh-seq") @@ -290,11 +293,6 @@ (defun mh-put-msg-in-seq (range sequence) "Add RANGE to SEQUENCE\\. -To place a message in a sequence, use this command to do it -manually, or use the MH command \"pick\" or the MH-E version of -\"pick\", \\[mh-search-folder], which create a sequence -automatically. - Give this command a RANGE and you can add all the messages in a sequence to another sequence (for example, \"\\[universal-argument] \\[mh-put-msg-in-seq] SourceSequence RET diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-speed.el --- a/lisp/mh-e/mh-speed.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-speed.el Tue Jan 17 00:56:42 2006 +0000 @@ -33,12 +33,13 @@ ;;; Code: -;; Requires +;;(message "> mh-speed") (eval-when-compile (require 'mh-acros)) (mh-require-cl) (require 'mh-e) (require 'speedbar) (require 'timer) +;;(message "< mh-speed") ;; Global variables (defvar mh-speed-refresh-flag nil) diff -r 8438f5473d99 -r de425e4eb0bc lisp/mh-e/mh-utils.el --- a/lisp/mh-e/mh-utils.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/mh-e/mh-utils.el Tue Jan 17 00:56:42 2006 +0000 @@ -33,6 +33,7 @@ ;;; Code: +;;(message "> mh-utils") (eval-and-compile (defvar recursive-load-depth-limit) (if (and (boundp 'recursive-load-depth-limit) @@ -45,10 +46,12 @@ (require 'font-lock) (require 'gnus-util) +(require 'mh-buffers) (require 'mh-customize) (require 'mh-inc) (require 'mouse) (require 'sendmail) +;;(message "< mh-utils") ;; Non-fatal dependencies (load "hl-line" t t) @@ -196,9 +199,6 @@ (defvar mh-globals-hash (make-hash-table) "Keeps track of MIME data on a per buffer basis.") -(defvar mh-pgp-support-flag (not (not (locate-library "mml2015"))) - "Non-nil means PGP support is available.") - (defvar mh-mm-inline-media-tests `(("image/jpeg" mm-inline-image @@ -517,28 +517,6 @@ Set to \"+inbox\" if no such component. Name of the Inbox folder.") -;; The names of ephemeral buffers have a " *mh-" prefix (so that they are -;; hidden and can be programmatically removed in mh-quit), and the variable -;; names have the form mh-temp-.*-buffer. -(defconst mh-temp-buffer " *mh-temp*") ;scratch -(defconst mh-temp-fetch-buffer " *mh-fetch*") ;wget/curl/fetch output - -;; The names of MH-E buffers that are not ephemeral and can be used by the -;; user (and deleted by the user when no longer needed) have a "*MH-E " prefix -;; (so they can be programmatically removed in mh-quit), and the variable -;; names have the form mh-.*-buffer. -(defconst mh-aliases-buffer "*MH-E Aliases*") ;alias lookups -(defconst mh-folders-buffer "*MH-E Folders*") ;folder list -(defconst mh-help-buffer "*MH-E Help*") ;quick help -(defconst mh-info-buffer "*MH-E Info*") ;version information buffer -(defconst mh-log-buffer "*MH-E Log*") ;output of MH commands and so on -(defconst mh-mail-delivery-buffer "*MH-E Mail Delivery*") ;mail delivery log -(defconst mh-recipients-buffer "*MH-E Recipients*") ;killed when draft sent -(defconst mh-sequences-buffer "*MH-E Sequences*") ;sequences list - -(defvar mh-log-buffer-lines 100 - "Number of lines to keep in `mh-log-buffer'.") - (defvar mh-previous-window-config nil "Window configuration before MH-E command.") @@ -868,7 +846,6 @@ (mh-defun-show-buffer mh-show-pack-folder mh-pack-folder) (mh-defun-show-buffer mh-show-kill-folder mh-kill-folder t) (mh-defun-show-buffer mh-show-list-folders mh-list-folders t) -(mh-defun-show-buffer mh-show-search-folder mh-search-folder t) (mh-defun-show-buffer mh-show-undo-folder mh-undo-folder) (mh-defun-show-buffer mh-show-delete-msg-from-seq mh-delete-msg-from-seq) @@ -973,14 +950,13 @@ "S" mh-show-sort-folder "c" mh-show-catchup "f" mh-show-visit-folder - "i" mh-index-search "k" mh-show-kill-folder "l" mh-show-list-folders "n" mh-index-new-messages "o" mh-show-visit-folder "q" mh-show-index-sequenced-messages "r" mh-show-rescan-folder - "s" mh-show-search-folder + "s" mh-search "t" mh-show-toggle-threads "u" mh-show-undo-folder "v" mh-show-visit-folder) @@ -1024,8 +1000,8 @@ "'" mh-show-narrow-to-tick "?" mh-prefix-help "c" mh-show-narrow-to-cc - "f" mh-show-narrow-to-from - "r" mh-show-narrow-to-range + "g" mh-show-narrow-to-range + "m" mh-show-narrow-to-from "s" mh-show-narrow-to-subject "t" mh-show-narrow-to-to "w" mh-show-widen) @@ -1119,8 +1095,7 @@ ["List Folders" mh-show-list-folders t] ["Visit a Folder..." mh-show-visit-folder t] ["View New Messages" mh-show-index-new-messages t] - ["Search a Folder..." mh-show-search-folder t] - ["Indexed Search..." mh-index-search t] + ["Search..." mh-search t] "--" ["Quit MH-E" mh-quit t])) @@ -1487,14 +1462,42 @@ "Scale image in INPUT file and write to OUTPUT file using ImageMagick." (call-process "convert" nil nil nil "-geometry" "96x48" input output)) +;; Copy of constant from url-util.el in Emacs 22; needed by Emacs 21. +(if (not (boundp 'url-unreserved-chars)) + (defconst url-unreserved-chars + '( + ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z + ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z + ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 + ?- ?_ ?. ?! ?~ ?* ?' ?\( ?\)) + "A list of characters that are _NOT_ reserved in the URL spec. +This is taken from RFC 2396.")) + +;; Copy of function from url-util.el in Emacs 22; needed by Emacs 21. +(mh-defun-compat url-hexify-string (str) + "Escape characters in a string." + (mapconcat + (lambda (char) + ;; Fixme: use a char table instead. + (if (not (memq char url-unreserved-chars)) + (if (> char 255) + (error "Hexifying multibyte character %s" str) + (format "%%%02X" char)) + (char-to-string char))) + str "")) + (defun mh-x-image-url-cache-canonicalize (url) "Canonicalize URL. -Replace the ?/ character with a ?! character and append .png." - (format "%s/%s.png" mh-x-image-cache-directory +Replace the ?/ character with a ?! character and append .png. +Also replaces special characters with `url-hexify-string' since +not all characters, such as :, are legal within Windows +filenames. See URL `http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp'." + (format "%s/%s.png" mh-x-image-cache-directory + (url-hexify-string (with-temp-buffer (insert url) (mh-replace-string "/" "!") - (buffer-string)))) + (buffer-string))))) (defun mh-x-image-set-download-state (file data) "Setup a symbolic link from FILE to DATA." @@ -1950,25 +1953,6 @@ (or dont-show (not return-value) (mh-maybe-show number)) return-value)) -(defun mh-profile-component (component) - "Return COMPONENT value from mhparam, or nil if unset." - (save-excursion - (mh-exec-cmd-quiet nil "mhparam" "-components" component) - (mh-profile-component-value component))) - -(defun mh-profile-component-value (component) - "Find and return the value of COMPONENT in the current buffer. -Returns nil if the component is not in the buffer." - (let ((case-fold-search t)) - (goto-char (point-min)) - (cond ((not (re-search-forward (format "^%s:" component) nil t)) nil) - ((looking-at "[\t ]*$") nil) - (t - (re-search-forward "[\t ]*\\([^\t \n].*\\)$" nil t) - (let ((start (match-beginning 1))) - (end-of-line) - (buffer-substring start (point))))))) - (defun mh-set-folder-modified-p (flag) "Mark current folder as modified or unmodified according to FLAG." (set-buffer-modified-p flag)) @@ -2055,7 +2039,7 @@ ;; Initialize mh-sub-folders-cache... (defun mh-collect-folder-names () - "Collect folder names by running \"flists\"." + "Collect folder names by running \"folders\"." (unless mh-flists-process (setq mh-flists-process (mh-exec-cmd-daemon "folders" 'mh-collect-folder-names-filter @@ -2154,6 +2138,44 @@ ((not (equal (aref folder 0) ?+)) (setq folder (concat "+" folder))))) folder) +(defmacro mh-children-p (folder) + "Return t if FOLDER from sub-folders cache has children. +The car of folder is the name, and the cdr is either t or some +sort of count that I do not understand. It's too small to be the +number of messages in the sub-folders and too large to be the +number of sub-folders. XXX" + `(if (cdr ,folder) + t + nil)) + +(defun mh-folder-list (folder) + "Return FOLDER and its descendents. +Returns a list of strings. For example, + + '(\"inbox\" \"lists\" \"lists/mh-e\"). + +If folder is nil, then all folders are considered. Respects the +value of `mh-recursive-folders-flag'. If this flag is nil, and +the sub-folders have not been explicitly viewed, then they will +not be returned." + (let ((folder-list)) + ;; Normalize folder. Strip leading +. Add trailing slash. If no + ;; folder is specified, ensure it is nil to ensure we get the + ;; top-level folders; otherwise mh-sub-folders returns all the + ;; files in / if given an empty string or +. + (when folder + (setq folder (replace-regexp-in-string "^\+" "" folder)) + (setq folder (replace-regexp-in-string "/*$" "/" folder)) + (if (equal folder "") + (setq folder nil))) + (loop for f in (mh-sub-folders folder) do + (setq folder-list (append folder-list (list (concat folder (car f))))) + (if (mh-children-p f) + (setq folder-list + (append folder-list + (mh-folder-list (concat folder (car f))))))) + folder-list)) + (defun mh-sub-folders (folder &optional add-trailing-slash-flag) "Find the subfolders of FOLDER. The function avoids running folders unnecessarily by caching the @@ -2384,185 +2406,9 @@ (mh-expand-file-name folder-name))))) folder-name)) -(defun mh-truncate-log-buffer () - "If `mh-log-buffer' is too big then truncate it. -If the number of lines in `mh-log-buffer' exceeds -`mh-log-buffer-lines' then keep only the last -`mh-log-buffer-lines'. As a side effect the point is set to the -end of the log buffer. - -The function returns the size of the final size of the log buffer." - (with-current-buffer (get-buffer-create mh-log-buffer) - (goto-char (point-max)) - (save-excursion - (when (equal (forward-line (- mh-log-buffer-lines)) 0) - (delete-region (point-min) (point)))) - (unless (or (bobp) - (save-excursion - (and (equal (forward-line -1) 0) (equal (char-after) ? )))) - (insert "\n \n")) - (buffer-size))) - -;;; Issue commands to MH. - -(defun mh-exec-cmd (command &rest args) - "Execute mh-command COMMAND with ARGS. -The side effects are what is desired. Any output is assumed to be -an error and is shown to the user. The output is not read or -parsed by MH-E." - (save-excursion - (set-buffer (get-buffer-create mh-log-buffer)) - (let* ((initial-size (mh-truncate-log-buffer)) - (start (point)) - (args (mh-list-to-string args))) - (apply 'call-process (expand-file-name command mh-progs) nil t nil args) - (when (> (buffer-size) initial-size) - (save-excursion - (goto-char start) - (insert "Errors when executing: " command) - (loop for arg in args do (insert " " arg)) - (insert "\n")) - (save-window-excursion - (switch-to-buffer-other-window mh-log-buffer) - (sit-for 5)))))) - -(defun mh-exec-cmd-error (env command &rest args) - "In environment ENV, execute mh-command COMMAND with ARGS. -ENV is nil or a string of space-separated \"var=value\" elements. -Signals an error if process does not complete successfully." - (save-excursion - (set-buffer (get-buffer-create mh-temp-buffer)) - (erase-buffer) - (let ((process-environment process-environment)) - ;; XXX: We should purge the list that split-string returns of empty - ;; strings. This can happen in XEmacs if leading or trailing spaces - ;; are present. - (dolist (elem (if (stringp env) (split-string env " ") ())) - (push elem process-environment)) - (mh-handle-process-error - command (apply #'call-process (expand-file-name command mh-progs) - nil t nil (mh-list-to-string args)))))) - -(defun mh-exec-cmd-daemon (command filter &rest args) - "Execute MH command COMMAND in the background. - -If FILTER is non-nil then it is used to process the output -otherwise the default filter `mh-process-daemon' is used. See -`set-process-filter' for more details of FILTER. - -ARGS are passed to COMMAND as command line arguments." - (save-excursion - (set-buffer (get-buffer-create mh-log-buffer)) - (mh-truncate-log-buffer)) - (let* ((process-connection-type nil) - (process (apply 'start-process - command nil - (expand-file-name command mh-progs) - (mh-list-to-string args)))) - (set-process-filter process (or filter 'mh-process-daemon)) - process)) - -(defun mh-exec-cmd-env-daemon (env command filter &rest args) - "In ennvironment ENV, execute mh-command COMMAND in the background. - -ENV is nil or a string of space-separated \"var=value\" elements. -Signals an error if process does not complete successfully. - -If FILTER is non-nil then it is used to process the output -otherwise the default filter `mh-process-daemon' is used. See -`set-process-filter' for more details of FILTER. - -ARGS are passed to COMMAND as command line arguments." - (let ((process-environment process-environment)) - (dolist (elem (if (stringp env) (split-string env " ") ())) - (push elem process-environment)) - (apply #'mh-exec-cmd-daemon command filter args))) - -(defun mh-process-daemon (process output) - "PROCESS daemon that puts OUTPUT into a temporary buffer. -Any output from the process is displayed in an asynchronous -pop-up window." - (with-current-buffer (get-buffer-create mh-log-buffer) - (insert-before-markers output) - (display-buffer mh-log-buffer))) - -(defun mh-exec-cmd-quiet (raise-error command &rest args) - "Signal RAISE-ERROR if COMMAND with ARGS fails. -Execute MH command COMMAND with ARGS. ARGS is a list of strings. -Return at start of mh-temp buffer, where output can be parsed and -used. -Returns value of `call-process', which is 0 for success, unless -RAISE-ERROR is non-nil, in which case an error is signaled if -`call-process' returns non-0." - (set-buffer (get-buffer-create mh-temp-buffer)) - (erase-buffer) - (let ((value - (apply 'call-process - (expand-file-name command mh-progs) nil t nil - args))) - (goto-char (point-min)) - (if raise-error - (mh-handle-process-error command value) - value))) - -;; Shush compiler. -(eval-when-compile (defvar mark-active)) - -(defun mh-exchange-point-and-mark-preserving-active-mark () - "Put the mark where point is now, and point where the mark is now. -This command works even when the mark is not active, and -preserves whether the mark is active or not." - (interactive nil) - (let ((is-active (and (boundp 'mark-active) mark-active))) - (let ((omark (mark t))) - (if (null omark) - (error "No mark set in this buffer")) - (set-mark (point)) - (goto-char omark) - (if (boundp 'mark-active) - (setq mark-active is-active)) - nil))) - -(defun mh-exec-cmd-output (command display &rest args) - "Execute MH command COMMAND with DISPLAY flag and ARGS. -Put the output into buffer after point. -Set mark after inserted text. -Output is expected to be shown to user, not parsed by MH-E." - (push-mark (point) t) - (apply 'call-process - (expand-file-name command mh-progs) nil t display - (mh-list-to-string args)) - - ;; The following is used instead of 'exchange-point-and-mark because the - ;; latter activates the current region (between point and mark), which - ;; turns on highlighting. So prior to this bug fix, doing "inc" would - ;; highlight a region containing the new messages, which is undesirable. - ;; The bug wasn't seen in emacs21 but still occurred in XEmacs21.4. - (mh-exchange-point-and-mark-preserving-active-mark)) - -(defun mh-exec-lib-cmd-output (command &rest args) - "Execute MH library command COMMAND with ARGS. -Put the output into buffer after point. -Set mark after inserted text." - (apply 'mh-exec-cmd-output (expand-file-name command mh-lib-progs) nil args)) - -(defun mh-handle-process-error (command status) - "Raise error if COMMAND returned non-zero STATUS, otherwise return STATUS." - (if (equal status 0) - status - (goto-char (point-min)) - (insert (if (integerp status) - (format "%s: exit code %d\n" command status) - (format "%s: %s\n" command status))) - (save-excursion - (let ((error-message (buffer-substring (point-min) (point-max)))) - (set-buffer (get-buffer-create mh-log-buffer)) - (mh-truncate-log-buffer) - (insert error-message))) - (error "%s failed, check buffer %s for error message" - command mh-log-buffer))) +;;; List and string manipulation (defun mh-list-to-string (l) "Flatten the list L and make every element of the new list into a string." diff -r 8438f5473d99 -r de425e4eb0bc lisp/progmodes/asm-mode.el --- a/lisp/progmodes/asm-mode.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/progmodes/asm-mode.el Tue Jan 17 00:56:42 2006 +0000 @@ -83,19 +83,21 @@ "Keymap for Asm mode.") (defconst asm-font-lock-keywords - '(("^\\(\\(\\sw\\|\\s_\\)+\\)\\>:?[ \t]*\\(\\sw+\\(\\.\\sw+\\)*\\)?" - (1 font-lock-function-name-face) (3 font-lock-keyword-face nil t)) - ;; label started from ".". - ("^\\(\\.\\(\\sw\\|\\s_\\)+\\)\\>:" - 1 font-lock-function-name-face) - ("^\\((\\sw+)\\)?\\s +\\(\\(\\.?\\sw\\|\\s_\\)+\\(\\.\\sw+\\)*\\)" - 2 font-lock-keyword-face) - ;; directive started from ".". - ("^\\(\\.\\(\\sw\\|\\s_\\)+\\)\\>[^:]?" - 1 font-lock-keyword-face) - ;; %register - ("%\\sw+" . font-lock-variable-name-face)) - "Additional expressions to highlight in Assembler mode.") + (append + '(("^\\(\\(\\sw\\|\\s_\\)+\\)\\>:?[ \t]*\\(\\sw+\\(\\.\\sw+\\)*\\)?" + (1 font-lock-function-name-face) (3 font-lock-keyword-face nil t)) + ;; label started from ".". + ("^\\(\\.\\(\\sw\\|\\s_\\)+\\)\\>:" + 1 font-lock-function-name-face) + ("^\\((\\sw+)\\)?\\s +\\(\\(\\.?\\sw\\|\\s_\\)+\\(\\.\\sw+\\)*\\)" + 2 font-lock-keyword-face) + ;; directive started from ".". + ("^\\(\\.\\(\\sw\\|\\s_\\)+\\)\\>[^:]?" + 1 font-lock-keyword-face) + ;; %register + ("%\\sw+" . font-lock-variable-name-face)) + cpp-font-lock-keywords) + "Additional expressions to highlight in Assembler mode.") ;;;###autoload (defun asm-mode () diff -r 8438f5473d99 -r de425e4eb0bc lisp/progmodes/ld-script.el --- a/lisp/progmodes/ld-script.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/progmodes/ld-script.el Tue Jan 17 00:56:42 2006 +0000 @@ -1,6 +1,6 @@ ;;; ld-script.el --- GNU linker script editing mode for Emacs -;; Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. ;; Author: Masatake YAMATO ;; Keywords: languages, faces @@ -36,7 +36,7 @@ (defvar ld-script-location-counter-face 'ld-script-location-counter) (defface ld-script-location-counter - '((t (:weight bold :inherit font-lock-builtin-face))) + '((t :weight bold :inherit font-lock-builtin-face)) "Face for location counter in GNU ld script." :group 'ld-script) @@ -114,30 +114,37 @@ "Builtin functions of GNU ld script.") (defvar ld-script-font-lock-keywords - `((,(regexp-opt ld-script-keywords 'words) - 1 font-lock-keyword-face) - (,(regexp-opt ld-script-builtins 'words) - 1 font-lock-builtin-face) - ("/DISCARD/" . font-lock-warning-face) - ("##\\|#[^#\n]+$" . font-lock-preprocessor-face) - ("\\W\\(\\.\\)\\W" 1 ld-script-location-counter-face) - ) + (append + `((,(regexp-opt ld-script-keywords 'words) + 1 font-lock-keyword-face) + (,(regexp-opt ld-script-builtins 'words) + 1 font-lock-builtin-face) + ("/DISCARD/" . font-lock-warning-face) + ("\\W\\(\\.\\)\\W" 1 ld-script-location-counter-face) + ) + cpp-font-lock-keywords) "Default font-lock-keywords for `ld-script-mode'.") +;; Linux-2.6.9 uses some different suffix for linker scripts: +;; "ld", "lds", "lds.S", "lds.in", "ld.script", and "ld.script.balo". +;; eCos uses "ld" and "ldi". +;; Netbsd uses "ldscript.*". ;;;###autoload -(add-to-list 'auto-mode-alist '("\\.ld[s]?\\(\\.in\\)?$" . ld-script-mode)) +(add-to-list 'auto-mode-alist '("\\.ld[si]?\\>" . ld-script-mode)) +(add-to-list 'auto-mode-alist '("ld\\.?script\\>" . ld-script-mode)) + ;;;###autoload -(add-to-list 'auto-mode-alist '("\\.x[bdsru]?[cn]?$" . ld-script-mode)) +(add-to-list 'auto-mode-alist '("\\.x[bdsru]?[cn]?\\'" . ld-script-mode)) ;;;###autoload (define-derived-mode ld-script-mode nil "LD-Script" "A major mode to edit GNU ld script files" (set (make-local-variable 'comment-start) "/* ") (set (make-local-variable 'comment-end) " */") - (set (make-local-variable 'indent-line-function) #'indent-relative) - (set (make-local-variable 'font-lock-defaults) '(ld-script-font-lock-keywords nil))) + (set (make-local-variable 'font-lock-defaults) + '(ld-script-font-lock-keywords nil))) (provide 'ld-script) -;;; arch-tag: 83280b6b-e6fc-4d00-a630-922d7aec5593 +;; arch-tag: 83280b6b-e6fc-4d00-a630-922d7aec5593 ;;; ld-script.el ends here diff -r 8438f5473d99 -r de425e4eb0bc lisp/reveal.el --- a/lisp/reveal.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/reveal.el Tue Jan 17 00:56:42 2006 +0000 @@ -85,7 +85,8 @@ ;; a window which does not show this buffer any more. (cond ((eq (car x) (selected-window)) (cdr x)) - ((not (eq (window-buffer (car x)) (current-buffer))) + ((not (and (window-live-p (car x)) + (eq (window-buffer (car x)) (current-buffer)))) ;; Adopt this since it's owned by a window that's ;; either not live or at least not showing this ;; buffer any more. @@ -104,35 +105,37 @@ (overlays-at (mark))) (overlays-at (point)))) (setq old-ols (delq ol old-ols)) - (let ((inv (overlay-get ol 'invisible)) open) - (when (and inv - ;; There's an `invisible' property. Make sure it's - ;; actually invisible, and ellipsised. - (and (consp buffer-invisibility-spec) - (cdr (assq inv buffer-invisibility-spec))) - (or (setq open - (or (overlay-get ol 'reveal-toggle-invisible) - (and (symbolp inv) - (get inv 'reveal-toggle-invisible)) - (overlay-get ol 'isearch-open-invisible-temporary))) - (overlay-get ol 'isearch-open-invisible) - (and (consp buffer-invisibility-spec) - (cdr (assq inv buffer-invisibility-spec)))) - (overlay-put ol 'reveal-invisible inv)) - (push (cons (selected-window) ol) reveal-open-spots) - (if (null open) - (overlay-put ol 'invisible nil) - ;; Use the provided opening function and repeat (since the - ;; opening function might have hidden a subpart around point). - (setq repeat t) - (condition-case err - (funcall open ol nil) - (error (message "!!Reveal-show (funcall %s %s nil): %s !!" - open ol err) - ;; Let's default to a meaningful behavior to avoid - ;; getting stuck in an infinite loop. - (setq repeat nil) - (overlay-put ol 'invisible nil))))))))) + (when (overlay-start ol) ;Check it's still live. + (let ((inv (overlay-get ol 'invisible)) open) + (when (and inv + ;; There's an `invisible' property. Make sure it's + ;; actually invisible, and ellipsised. + (and (consp buffer-invisibility-spec) + (cdr (assq inv buffer-invisibility-spec))) + (or (setq open + (or (overlay-get ol 'reveal-toggle-invisible) + (and (symbolp inv) + (get inv 'reveal-toggle-invisible)) + (overlay-get ol 'isearch-open-invisible-temporary))) + (overlay-get ol 'isearch-open-invisible) + (and (consp buffer-invisibility-spec) + (cdr (assq inv buffer-invisibility-spec)))) + (overlay-put ol 'reveal-invisible inv)) + (push (cons (selected-window) ol) reveal-open-spots) + (if (null open) + (overlay-put ol 'invisible nil) + ;; Use the provided opening function and repeat (since the + ;; opening function might have hidden a subpart around point + ;; or moved/killed some of the overlays). + (setq repeat t) + (condition-case err + (funcall open ol nil) + (error (message "!!Reveal-show (funcall %s %s nil): %s !!" + open ol err) + ;; Let's default to a meaningful behavior to avoid + ;; getting stuck in an infinite loop. + (setq repeat nil) + (overlay-put ol 'invisible nil)))))))))) old-ols) (defun reveal-close-old-overlays (old-ols) diff -r 8438f5473d99 -r de425e4eb0bc lisp/startup.el --- a/lisp/startup.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/startup.el Tue Jan 17 00:56:42 2006 +0000 @@ -204,7 +204,7 @@ :type 'function :group 'initialization) -(defcustom init-file-user nil +(defvar init-file-user nil "Identity of user whose `.emacs' file is or was read. The value is nil if `-q' or `--no-init-file' was specified, meaning do not load any init file. @@ -219,9 +219,7 @@ looked for. Setting `init-file-user' does not prevent Emacs from loading -`site-start.el'. The only way to do that is to use `--no-site-file'." - :type '(choice (const :tag "none" nil) string) - :group 'initialization) +`site-start.el'. The only way to do that is to use `--no-site-file'.") (defcustom site-run-file "site-start" "File containing site-wide run-time initializations. diff -r 8438f5473d99 -r de425e4eb0bc lisp/term.el --- a/lisp/term.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/term.el Tue Jan 17 00:56:42 2006 +0000 @@ -1,7 +1,7 @@ ;;; term.el --- general command interpreter in a window stuff ;; Copyright (C) 1988, 1990, 1992, 1994, 1995, 2002, 2003, -;; 2004, 2005 Free Software Foundation, Inc. +;; 2004, 2005, 2006 Free Software Foundation, Inc. ;; Author: Per Bothner ;; Maintainer: Dan Nicolaescu , Per Bothner @@ -917,6 +917,7 @@ (define-key term-raw-map [backspace] 'term-send-backspace) (define-key term-raw-map [home] 'term-send-home) (define-key term-raw-map [end] 'term-send-end) + (define-key term-raw-map [insert] 'term-send-insert) (define-key term-raw-map [S-prior] 'scroll-down) (define-key term-raw-map [S-next] 'scroll-up) (define-key term-raw-map [S-insert] 'term-paste) @@ -1068,6 +1069,13 @@ (make-local-variable 'term-ansi-current-reverse) (make-local-variable 'term-ansi-current-invisible) + (make-local-variable 'term-terminal-parameter) + (make-local-variable 'term-terminal-previous-parameter) + (make-local-variable 'term-terminal-previous-parameter-2) + (make-local-variable 'term-terminal-previous-parameter-3) + (make-local-variable 'term-terminal-previous-parameter-4) + (make-local-variable 'term-terminal-more-parameters) + (make-local-variable 'term-terminal-state) (make-local-variable 'term-kill-echo-list) (make-local-variable 'term-start-line-column) @@ -1119,7 +1127,7 @@ (setq term-start-line-column nil) (setq term-current-row nil) (setq term-current-column nil) - (term-scroll-region 0 height)) + (term-set-scroll-region 0 height)) ;; Recursive routine used to check if any string in term-kill-echo-list ;; matches part of the buffer before point. @@ -1227,6 +1235,7 @@ (defun term-send-right () (interactive) (term-send-raw-string "\eOC")) (defun term-send-left () (interactive) (term-send-raw-string "\eOD")) (defun term-send-home () (interactive) (term-send-raw-string "\e[1~")) +(defun term-send-insert() (interactive) (term-send-raw-string "\e[2~")) (defun term-send-end () (interactive) (term-send-raw-string "\e[4~")) (defun term-send-prior () (interactive) (term-send-raw-string "\e[5~")) (defun term-send-next () (interactive) (term-send-raw-string "\e[6~")) @@ -2748,7 +2757,7 @@ ;; around. Go to the beginning of ;; the next line and switch to state ;; 0. - (term-down 1) + (term-down 1 t) (term-move-columns (- (term-current-column))) (setq term-terminal-state 0))) (setq count (- funny i)) @@ -2786,7 +2795,7 @@ (setq pos (point)) (term-move-columns columns) (delete-region pos (point))) - ;; In insert if the if the current line + ;; In insert mode if the current line ;; has become too long it needs to be ;; chopped off. (when term-insert-mode @@ -2825,25 +2834,12 @@ (when (= term-width (term-current-column)) (term-move-columns -1)))) ((eq char ?\r) ;; (terminfo: cr) - ;; Optimize CRLF at end of buffer: - (cond ((and (< (setq temp (1+ i)) str-length) - (eq (aref str temp) ?\n) - (= (point) (point-max)) - (not (or term-pager-count - term-kill-echo-list - term-scroll-with-delete))) - (insert ?\n) - (term-adjust-current-row-cache 1) - (setq term-start-line-column 0) - (setq term-current-column 0) - (setq i temp)) - (t ;; Not followed by LF or can't optimize: - (term-vertical-motion 0) - (setq term-current-column term-start-line-column)))) + (term-vertical-motion 0) + (setq term-current-column term-start-line-column)) ((eq char ?\n) ;; (terminfo: cud1, ind) - (if (not (and term-kill-echo-list - (term-check-kill-echo-list))) - (term-down 1 t))) + (unless (and term-kill-echo-list + (term-check-kill-echo-list)) + (term-down 1 t))) ((eq char ?\b) ;; (terminfo: cub1) (term-move-columns -1)) ((eq char ?\033) ; Escape @@ -2874,12 +2870,6 @@ ;;; Note that now the init value of term-terminal-previous-parameter has ;;; been changed to -1 - (make-local-variable 'term-terminal-parameter) - (make-local-variable 'term-terminal-previous-parameter) - (make-local-variable 'term-terminal-previous-parameter-2) - (make-local-variable 'term-terminal-previous-parameter-3) - (make-local-variable 'term-terminal-previous-parameter-4) - (make-local-variable 'term-terminal-more-parameters) (setq term-terminal-parameter 0) (setq term-terminal-previous-parameter -1) (setq term-terminal-previous-parameter-2 -1) @@ -2898,18 +2888,47 @@ ;; (term-goto term-current-row 0) ;; (setq term-terminal-state 0)) ((eq char ?M) ;; scroll reversed (terminfo: ri) - (term-down -1) + (if (or (< (term-current-row) term-scroll-start) + (>= (1- (term-current-row)) + term-scroll-start)) + ;; Scrolling up will not move outside + ;; the scroll region. + (term-down -1) + ;; Scrolling the scroll region is needed. + (term-down -1 t)) (setq term-terminal-state 0)) ((eq char ?7) ;; Save cursor (terminfo: sc) (term-handle-deferred-scroll) (setq term-saved-cursor - (cons (term-current-row) - (term-horizontal-column))) + (list (term-current-row) + (term-horizontal-column) + term-ansi-current-bg-color + term-ansi-current-bold + term-ansi-current-color + term-ansi-current-invisible + term-ansi-current-reverse + term-ansi-current-underline + term-current-face) + ) (setq term-terminal-state 0)) ((eq char ?8) ;; Restore cursor (terminfo: rc) - (if term-saved-cursor - (term-goto (car term-saved-cursor) - (cdr term-saved-cursor))) + (when term-saved-cursor + (term-goto (nth 0 term-saved-cursor) + (nth 1 term-saved-cursor)) + (setq term-ansi-current-bg-color + (nth 2 term-saved-cursor) + term-ansi-current-bold + (nth 3 term-saved-cursor) + term-ansi-current-color + (nth 4 term-saved-cursor) + term-ansi-current-invisible + (nth 5 term-saved-cursor) + term-ansi-current-reverse + (nth 6 term-saved-cursor) + term-ansi-current-underline + (nth 7 term-saved-cursor) + term-current-face + (nth 8 term-saved-cursor))) (setq term-terminal-state 0)) ((eq char ?c) ;; \Ec - Reset (terminfo: rs1) ;; This is used by the "clear" program. @@ -2921,6 +2940,8 @@ ;; ((eq char ?#) ;; (when (eq (aref str (1+ i)) ?8) ;; (setq i (1+ i)) + ;; (setq term-scroll-start 0) + ;; (setq term-scroll-end term-height) ;; (setq term-terminal-state 0))) ((setq term-terminal-state 0)))) ((eq term-terminal-state 3) ; Seen Esc [ @@ -3048,6 +3069,8 @@ (erase-buffer) (setq term-current-row 0) (setq term-current-column 1) + (setq term-scroll-start 0) + (setq term-scroll-end term-height) (setq term-insert-mode nil) (setq term-current-face nil) (setq term-ansi-current-underline nil) @@ -3194,8 +3217,8 @@ (defun term-handle-ansi-escape (proc char) (cond - ((or (eq char ?H) ; cursor motion (terminfo: cup,home) - ;; (eq char ?f) ; xterm seems to handle this sequence too, not + ((or (eq char ?H) ;; cursor motion (terminfo: cup,home) + ;; (eq char ?f) ;; xterm seems to handle this sequence too, not ;; needed for now ) (if (<= term-terminal-parameter 0) @@ -3212,10 +3235,23 @@ ;; \E[A - cursor up (terminfo: cuu, cuu1) ((eq char ?A) (term-handle-deferred-scroll) - (term-down (- (max 1 term-terminal-parameter)) t)) + (let ((tcr (term-current-row))) + (term-down + (if (< (- tcr term-terminal-parameter) term-scroll-start) + ;; If the amount to move is before scroll start, move + ;; to scroll start. + (- term-scroll-start tcr) + (if (>= term-terminal-parameter tcr) + (- tcr) + (- (max 1 term-terminal-parameter)))) t))) ;; \E[B - cursor down (terminfo: cud) ((eq char ?B) - (term-down (max 1 term-terminal-parameter) t)) + (let ((tcr (term-current-row))) + (unless (= tcr (1- term-scroll-end)) + (term-down + (if (> (+ tcr term-terminal-parameter) term-scroll-end) + (- term-scroll-end 1 tcr) + (max 1 term-terminal-parameter)) t)))) ;; \E[C - cursor right (terminfo: cuf, cuf1) ((eq char ?C) (term-move-columns @@ -3264,12 +3300,12 @@ ;;(terminfo: smso,rmso,smul,rmul,rev,bold,sgr0,invis,op,setab,setaf) ((eq char ?m) (when (= term-terminal-more-parameters 1) - (if (>= term-terminal-previous-parameter-4 0) - (term-handle-colors-array term-terminal-previous-parameter-4)) - (if (>= term-terminal-previous-parameter-3 0) - (term-handle-colors-array term-terminal-previous-parameter-3)) - (if (>= term-terminal-previous-parameter-2 0) - (term-handle-colors-array term-terminal-previous-parameter-2)) + (when (>= term-terminal-previous-parameter-4 0) + (term-handle-colors-array term-terminal-previous-parameter-4)) + (when (>= term-terminal-previous-parameter-3 0) + (term-handle-colors-array term-terminal-previous-parameter-3)) + (when (>= term-terminal-previous-parameter-2 0) + (term-handle-colors-array term-terminal-previous-parameter-2)) (term-handle-colors-array term-terminal-previous-parameter)) (term-handle-colors-array term-terminal-parameter)) @@ -3280,14 +3316,14 @@ (format "\e[%s;%sR" (1+ (term-current-row)) (1+ (term-horizontal-column))))) - ;; \E[r - Set scrolling region - ((eq char ?r) ;; (terminfo: csr) - (term-scroll-region + ;; \E[r - Set scrolling region (terminfo: csr) + ((eq char ?r) + (term-set-scroll-region (1- term-terminal-previous-parameter) term-terminal-parameter)) (t))) -(defun term-scroll-region (top bottom) +(defun term-set-scroll-region (top bottom) "Set scrolling region. TOP is the top-most line (inclusive) of the new scrolling region, while BOTTOM is the line following the new scrolling region (e.g. exclusive). @@ -3305,8 +3341,7 @@ (not (and (= term-scroll-start 0) (= term-scroll-end term-height))))) (term-move-columns (- (term-current-column))) - (term-goto - term-scroll-start (term-current-column))) + (term-goto 0 0)) ;; (defun term-switch-to-alternate-sub-buffer (set) ;; ;; If asked to switch to (from) the alternate sub-buffer, and already (not) @@ -3589,21 +3624,36 @@ (defun term-handle-scroll (down) (let ((scroll-needed - (- (+ (term-current-row) down 1) term-scroll-end))) - (if (> scroll-needed 0) + (- (+ (term-current-row) down) + (if (< down 0) term-scroll-start term-scroll-end)))) + (if (or (and (< down 0) (< scroll-needed 0)) + (and (> down 0) (> scroll-needed 0))) (let ((save-point (copy-marker (point))) (save-top)) (goto-char term-home-marker) (cond (term-scroll-with-delete - ;; delete scroll-needed lines at term-scroll-start - (term-vertical-motion term-scroll-start) - (setq save-top (point)) - (term-vertical-motion scroll-needed) - (delete-region save-top (point)) - (goto-char save-point) - (term-vertical-motion down) - (term-adjust-current-row-cache (- scroll-needed)) + (if (< down 0) + (progn + ;; Delete scroll-needed lines at term-scroll-end, + ;; then insert scroll-needed lines. + (term-vertical-motion (1- term-scroll-end)) + (end-of-line) + (setq save-top (point)) + (term-vertical-motion scroll-needed) + (end-of-line) + (delete-region save-top (point)) + (goto-char save-point) + (setq down (- scroll-needed down)) + (term-vertical-motion down)) + ;; Delete scroll-needed lines at term-scroll-start. + (term-vertical-motion term-scroll-start) + (setq save-top (point)) + (term-vertical-motion scroll-needed) + (delete-region save-top (point)) + (goto-char save-point) + (term-vertical-motion down) + (term-adjust-current-row-cache (- scroll-needed))) (setq term-current-column nil) - (term-insert-char ?\n scroll-needed)) + (term-insert-char ?\n (abs scroll-needed))) ((and (numberp term-pager-count) (< (setq term-pager-count (- term-pager-count down)) 0)) @@ -3626,7 +3676,7 @@ (term-adjust-current-row-cache down) (when (or (/= (point) (point-max)) (< down 0)) (setq down (- down (term-vertical-motion down))))) - (cond ((> down 0) + (cond ((>= down 0) ;; Extend buffer with extra blank lines if needed. (term-insert-char ?\n down) (setq term-current-column 0) @@ -3714,22 +3764,22 @@ ;;; at the end of this screen line to make room. (defun term-insert-spaces (count) - (let ((save-point (point)) (save-eol) (point-at-eol)) + (let ((save-point (point)) (save-eol) (pnt-at-eol)) (term-vertical-motion 1) - (if (bolp) - (backward-char)) + (when (bolp) + (backward-char)) (setq save-eol (point)) (save-excursion (end-of-line) - (setq point-at-eol (point))) + (setq pnt-at-eol (point))) (move-to-column (+ (term-start-line-column) (- term-width count)) t) ;; If move-to-column extends the current line it will use the face ;; from the last character on the line, set the face for the chars ;; to default. - (when (> (point) (point-at-eol)) - (put-text-property point-at-eol (point) 'face 'default)) - (if (> save-eol (point)) - (delete-region (point) save-eol)) + (when (>= (point) pnt-at-eol) + (put-text-property pnt-at-eol (point) 'face 'default)) + (when (> save-eol (point)) + (delete-region (point) save-eol)) (goto-char save-point) (term-insert-char ? count) (goto-char save-point))) @@ -3739,6 +3789,8 @@ (save-current-column term-current-column) (save-start-line-column term-start-line-column) (save-current-row (term-current-row))) + (when (>= (+ save-current-row lines) term-scroll-end) + (setq lines (- lines (- (+ save-current-row lines) term-scroll-end)))) (term-down lines) (delete-region start (point)) (term-down (- term-scroll-end save-current-row lines)) @@ -3754,7 +3806,17 @@ (save-current-column term-current-column) (save-start-line-column term-start-line-column) (save-current-row (term-current-row))) - (term-down (- term-scroll-end save-current-row lines)) + ;; Inserting lines should take into account the scroll region. + (if (< save-current-row term-scroll-start) + ;; If point is before scroll start, + (progn + (setq lines (- lines (- term-scroll-start save-current-row))) + (term-down (- term-scroll-start save-current-row)) + (setq start (point))) + ;; The number of inserted lines shouldn't exceed the scroll region end. + (when (>= (+ save-current-row lines) term-scroll-end) + (setq lines (- lines (- (+ save-current-row lines) term-scroll-end)))) + (term-down (- term-scroll-end save-current-row lines))) (setq start-deleted (point)) (term-down lines) (delete-region start-deleted (point)) diff -r 8438f5473d99 -r de425e4eb0bc lisp/textmodes/flyspell.el --- a/lisp/textmodes/flyspell.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/textmodes/flyspell.el Tue Jan 17 00:56:42 2006 +0000 @@ -525,6 +525,12 @@ (member (or ispell-local-dictionary ispell-dictionary) flyspell-dictionaries-that-consider-dash-as-word-delimiter))))) +(defun flyspell-kill-ispell-hook () + (setq flyspell-last-buffer nil) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (kill-local-variable 'flyspell-word-cache-word)))) + ;;*---------------------------------------------------------------------*/ ;;* flyspell-mode-on ... */ ;;*---------------------------------------------------------------------*/ @@ -536,6 +542,8 @@ (or ispell-local-dictionary ispell-dictionary (if flyspell-default-dictionary (ispell-change-dictionary flyspell-default-dictionary))) + ;; Make sure we flush our caches when needed. + (add-hook 'ispell-kill-ispell-hook 'flyspell-kill-ispell-hook) ;; we have to force ispell to accept the local definition or ;; otherwise it could be too late, the local dictionary may ;; be forgotten! diff -r 8438f5473d99 -r de425e4eb0bc lisp/textmodes/ispell.el --- a/lisp/textmodes/ispell.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/textmodes/ispell.el Tue Jan 17 00:56:42 2006 +0000 @@ -1,7 +1,7 @@ ;;; ispell.el --- interface to International Ispell Versions 3.1 and 3.2 ;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, -;; 2004, 2005 Free Software Foundation, Inc. +;; 2004, 2005, 2006 Free Software Foundation, Inc. ;; Author: Ken Stevens ;; Maintainer: Ken Stevens @@ -2504,7 +2504,8 @@ (setq ispell-filter nil ispell-filter-continue nil) ;; may need to restart to select new personal dictionary. (ispell-kill-ispell t) - (message "Starting new Ispell process...") + (message "Starting new Ispell process [%s] ..." + (or ispell-local-dictionary ispell-dictionary "default")) (sit-for 0) (setq ispell-library-directory (ispell-check-version) ispell-process-directory default-directory @@ -2556,6 +2557,9 @@ "Kill current Ispell process (so that you may start a fresh one). With NO-ERROR, just return non-nil if there was no Ispell running." (interactive) + ;; This hook is typically used by flyspell to flush some variables used + ;; to optimize the common cases. + (run-hooks 'ispell-kill-ispell-hook) (if (not (and ispell-process (eq (ispell-process-status) 'run))) (or no-error @@ -2619,6 +2623,7 @@ (setq ispell-local-dictionary dict) (setq ispell-local-dictionary-overridden t)) (error "Undefined dictionary: %s" dict)) + (ispell-internal-change-dictionary) (message "%s Ispell dictionary set to %s" (if arg "Global" "Local") dict)))) @@ -2632,7 +2637,6 @@ (ispell-kill-ispell t) (setq ispell-current-dictionary dict)))) - ;;; Spelling of comments are checked when ispell-check-comments is non-nil. ;;;###autoload @@ -2964,9 +2968,8 @@ coding))))) ;;; Avoid error messages when compiling for these dynamic variables. -(eval-when-compile - (defvar start) - (defvar end)) +(defvar start) +(defvar end) (defun ispell-process-line (string shift) "Sends a LINE of text to ispell and processes the result. diff -r 8438f5473d99 -r de425e4eb0bc lisp/textmodes/org.el --- a/lisp/textmodes/org.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/textmodes/org.el Tue Jan 17 00:56:42 2006 +0000 @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://www.astro.uva.nl/~dominik/Tools/org/ -;; Version: 4.02 +;; Version: 4.03 ;; ;; This file is part of GNU Emacs. ;; @@ -81,6 +81,12 @@ ;; ;; Changes since version 4.00: ;; --------------------------- +;; Version 4.03 +;; - Table alignment fixed for use with wide characters. +;; - `C-c -' leaves cursor in current table line. +;; - The current TAG can be incorporated into the agenda prefix. +;; See option `org-agenda-prefix-format' for details. +;; ;; Version 4.02 ;; - Minor bug fixes and improvements around tag searches. ;; - XEmacs compatibility fixes. @@ -105,7 +111,7 @@ ;;; Customization variables -(defvar org-version "4.01" +(defvar org-version "4.03" "The version number of the file org.el.") (defun org-version () (interactive) @@ -565,6 +571,7 @@ %c the category of the item, \"Diary\" for entries from the diary, or as given by the CATEGORY keyword or derived from the file name. + %T the first tag of the item. %t the time-of-day specification if one applies to the entry, in the format HH:MM %s Scheduling/Deadline information, a short string @@ -1012,29 +1019,7 @@ :type 'boolean) (defconst org-file-apps-defaults-gnu - '((t . emacs) - ("jpg" . "xv %s") - ("gif" . "xv %s") - ("ppm" . "xv %s") - ("pgm" . "xv %s") - ("pbm" . "xv %s") - ("tif" . "xv %s") - ("png" . "xv %s") - ("ps" . "gv %s") - ("ps.gz" . "gv %s") - ("eps" . "gv %s") - ("eps.gz" . "gv %s") - ("dvi" . "xdvi %s") - ("mpeg" . "plaympeg %s") - ("mp3" . "plaympeg %s") - ("fig" . "xfig %s") - ("pdf" . "acroread %s") - ("doc" . "soffice %s") - ("ppt" . "soffice %s") - ("pps" . "soffice %s") - ("html" . "netscape -remote openURL(%s,new-window)") - ("htm" . "netscape -remote openURL(%s,new-window)") - ("xs" . "soffice %s")) + '((t . mailcap)) "Default file applications on a UNIX/LINUX system. See `org-file-apps'.") @@ -4186,6 +4171,7 @@ (define-key org-agenda-mode-map "q" 'org-agenda-quit) (define-key org-agenda-mode-map "x" 'org-agenda-exit) (define-key org-agenda-mode-map "P" 'org-agenda-show-priority) +(define-key org-agenda-mode-map "T" 'org-agenda-show-tags) (define-key org-agenda-mode-map "n" 'next-line) (define-key org-agenda-mode-map "p" 'previous-line) (define-key org-agenda-mode-map "\C-n" 'org-agenda-next-date-line) @@ -4232,7 +4218,9 @@ :style toggle :selected org-agenda-follow-mode :active t] "--" ["Cycle TODO" org-agenda-todo t] - ["Set Tags" org-agenda-set-tags t] + ("Tags" + ["Show all Tags" org-agenda-show-tags t] + ["Set Tags" org-agenda-set-tags t]) ("Reschedule" ["Reschedule +1 day" org-agenda-date-later (org-agenda-check-type nil 'agenda 'timeline)] ["Reschedule -1 day" org-agenda-date-earlier (org-agenda-check-type nil 'agenda 'timeline)] @@ -4946,7 +4934,7 @@ (setq entries (mapcar (lambda (x) - (setq x (org-format-agenda-item "" x "Diary" 'time)) + (setq x (org-format-agenda-item "" x "Diary" nil 'time)) ;; Extend the text properties to the beginning of the line (add-text-properties 0 (length x) @@ -5297,14 +5285,15 @@ "\\)\\>") org-not-done-regexp) "[^\n\r]*\\)")) - marker priority category + marker priority category tags ee txt) (goto-char (point-min)) (while (re-search-forward regexp nil t) (goto-char (match-beginning 1)) (setq marker (org-agenda-new-marker (1+ (match-beginning 0))) category (org-get-category) - txt (org-format-agenda-item "" (match-string 1) category) + tags (org-get-tags-at (point)) + txt (org-format-agenda-item "" (match-string 1) category tags) priority (+ (org-get-priority txt) (if org-todo-kwd-priority-p @@ -5340,7 +5329,7 @@ (list 0 0 0 (nth 1 date) (car date) (nth 2 date)))) 0 11))) marker hdmarker deadlinep scheduledp donep tmp priority category - ee txt timestr) + ee txt timestr tags) (goto-char (point-min)) (while (re-search-forward regexp nil t) (if (not (save-match-data (org-at-date-range-p))) @@ -5362,13 +5351,14 @@ (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t) (progn (goto-char (match-end 1)) - (setq hdmarker (org-agenda-new-marker)) + (setq hdmarker (org-agenda-new-marker) + tags (org-get-tags-at)) (looking-at "\\*+[ \t]*\\([^\r\n]+\\)") (setq txt (org-format-agenda-item (format "%s%s" (if deadlinep "Deadline: " "") (if scheduledp "Scheduled: " "")) - (match-string 1) category timestr))) + (match-string 1) category tags timestr))) (setq txt org-agenda-no-heading-message)) (setq priority (org-get-priority txt)) (add-text-properties @@ -5417,7 +5407,7 @@ (apply 'encode-time ; DATE bound by calendar (list 0 0 0 (nth 1 date) (car date) (nth 2 date)))) 1 11)))) - marker hdmarker priority category + marker hdmarker priority category tags ee txt timestr) (goto-char (point-min)) (while (re-search-forward regexp nil t) @@ -5435,11 +5425,12 @@ (if (re-search-backward "\\(^\\|\r\\)\\*+" nil t) (progn (goto-char (match-end 1)) - (setq hdmarker (org-agenda-new-marker)) + (setq hdmarker (org-agenda-new-marker) + tags (org-get-tags-at)) (looking-at "\\*+[ \t]*\\([^\r\n]+\\)") (setq txt (org-format-agenda-item "Closed: " - (match-string 1) category timestr))) + (match-string 1) category tags timestr))) (setq txt org-agenda-no-heading-message)) (setq priority 100000) (add-text-properties @@ -5466,7 +5457,7 @@ (regexp org-deadline-time-regexp) (todayp (equal date (calendar-current-date))) ; DATE bound by calendar (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar - d2 diff pos pos1 category + d2 diff pos pos1 category tags ee txt head) (goto-char (point-min)) (while (re-search-forward regexp nil t) @@ -5484,6 +5475,7 @@ (progn (goto-char (match-end 0)) (setq pos1 (match-end 1)) + (setq tags (org-get-tags-at pos1)) (setq head (buffer-substring-no-properties (point) (progn (skip-chars-forward "^\r\n") @@ -5491,7 +5483,7 @@ (if (string-match org-looking-at-done-regexp head) (setq txt nil) (setq txt (org-format-agenda-item - (format "In %3d d.: " diff) head category)))) + (format "In %3d d.: " diff) head category tags)))) (setq txt org-agenda-no-heading-message)) (when txt (add-text-properties @@ -5527,7 +5519,7 @@ (regexp org-scheduled-time-regexp) (todayp (equal date (calendar-current-date))) ; DATE bound by calendar (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar - d2 diff pos pos1 category + d2 diff pos pos1 category tags ee txt head) (goto-char (point-min)) (while (re-search-forward regexp nil t) @@ -5544,6 +5536,7 @@ (progn (goto-char (match-end 0)) (setq pos1 (match-end 1)) + (setq tags (org-get-tags-at)) (setq head (buffer-substring-no-properties (point) (progn (skip-chars-forward "^\r\n") (point)))) @@ -5551,7 +5544,7 @@ (setq txt nil) (setq txt (org-format-agenda-item (format "Sched.%2dx: " (- 1 diff)) head - category)))) + category tags)))) (setq txt org-agenda-no-heading-message)) (when txt (add-text-properties @@ -5574,7 +5567,7 @@ (abbreviate-file-name (buffer-file-name))))) (regexp org-tr-regexp) (d0 (calendar-absolute-from-gregorian date)) - marker hdmarker ee txt d1 d2 s1 s2 timestr category) + marker hdmarker ee txt d1 d2 s1 s2 timestr category tags) (goto-char (point-min)) (while (re-search-forward regexp nil t) (setq timestr (match-string 0) @@ -5592,11 +5585,12 @@ (progn (setq hdmarker (org-agenda-new-marker (match-end 1))) (goto-char (match-end 1)) + (setq tags (org-get-tags-at)) (looking-at "\\*+[ \t]*\\([^\r\n]+\\)") (setq txt (org-format-agenda-item (format (if (= d1 d2) "" "(%d/%d): ") (1+ (- d0 d1)) (1+ (- d2 d1))) - (match-string 1) category + (match-string 1) category tags (if (= d0 d1) timestr)))) (setq txt org-agenda-no-heading-message)) (add-text-properties @@ -5643,7 +5637,7 @@ "A flag, set by `org-compile-prefix-format'. The flag is set if the currently compiled format contains a `%t'.") -(defun org-format-agenda-item (extra txt &optional category dotime noprefix) +(defun org-format-agenda-item (extra txt &optional category tags dotime noprefix) "Format TXT to be inserted into the agenda buffer. In particular, it adds the prefix and corresponding text properties. EXTRA must be a string and replaces the `%s' specifier in the prefix format. @@ -5654,7 +5648,7 @@ the `%t' specifier in the format. When DOTIME is a string, this string is searched for a time before TXT is. NOPREFIX is a flag and indicates that only the correctly processes TXT should be returned - this is used by -`org-agenda-change-all-lines'." +`org-agenda-change-all-lines'. TAG can be the tag of the headline." (save-match-data ;; Diary entries sometimes have extra whitespace at the beginning (if (string-match "^ +" txt) (setq txt (replace-match "" nil nil txt))) @@ -5664,6 +5658,7 @@ (file-name-sans-extension (file-name-nondirectory (buffer-file-name))) ""))) + (tag (or (nth (1- (length tags)) tags) "")) time ;; needed for the eval of the prefix format (ts (if dotime (concat (if (stringp dotime) dotime "") txt))) (time-of-day (and dotime (org-get-time-of-day ts))) @@ -5704,6 +5699,7 @@ ;; And finally add the text properties (add-text-properties 0 (length rtn) (list 'category (downcase category) + 'tags tags 'prefix-length (- (length rtn) (length txt)) 'time-of-day time-of-day 'dotime dotime) @@ -5732,7 +5728,7 @@ (unless (and remove (member time have)) (setq time (int-to-string time)) (push (org-format-agenda-item - nil string "" ;; FIXME: put a category for the grid? + nil string "" nil ;; FIXME: put a category for the grid? (concat (substring time 0 -2) ":" (substring time -2))) new) (put-text-property @@ -5746,11 +5742,12 @@ The resulting form is returned and stored in the variable `org-prefix-format-compiled'." (setq org-prefix-has-time nil) - (let ((start 0) varform vars var (s format) c f opt) + (let ((start 0) varform vars var (s format)e c f opt) (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ .;,:!?=|/<>]?\\)\\([cts]\\)" s start) (setq var (cdr (assoc (match-string 4 s) - '(("c" . category) ("t" . time) ("s" . extra)))) + '(("c" . category) ("t" . time) ("s" . extra) + ("T" . tag)))) c (or (match-string 3 s) "") opt (match-beginning 1) start (1+ (match-beginning 0))) @@ -5788,7 +5785,9 @@ (if (match-beginning 3) (string-to-number (match-string 3 s)) 0))) - (t1 (concat " " (int-to-string t0)))) + (t1 (concat " " + (if (< t0 100) "0" "") (if (< t0 10) "0" "") + (int-to-string t0)))) (if string (concat (substring t1 -4 -2) ":" (substring t1 -2)) t0))))) (defun org-finalize-agenda-entries (list) @@ -5842,6 +5841,14 @@ (let* ((pri (get-text-property (point-at-bol) 'priority))) (message "Priority is %d" (if pri pri -1000)))) +(defun org-agenda-show-tags () + "Show the tags applicable to the current item." + (interactive) + (let* ((tags (get-text-property (point-at-bol) 'tags))) + (if tags + (message "Tags are :%s:" (mapconcat 'identity tags ":")) + (message "No tags associated with this line")))) + (defun org-agenda-goto (&optional highlight) "Go to the Org-mode file which contains the item at point." (interactive) @@ -5954,7 +5961,7 @@ `equal' against all `org-hd-marker' text properties in the file. If FIXFACE is non-nil, the face of each item is modified acording to the new TODO state." - (let* (props m pl undone-face done-face finish new dotime cat) + (let* (props m pl undone-face done-face finish new dotime cat tags) ; (setq newhead (org-format-agenda-item "x" newhead "x" nil 'noprefix)) (save-excursion (goto-char (point-max)) @@ -5966,7 +5973,8 @@ (setq props (text-properties-at (point)) dotime (get-text-property (point) 'dotime) cat (get-text-property (point) 'category) - new (org-format-agenda-item "x" newhead cat dotime 'noprefix) + tags (get-text-property (point) 'tags) + new (org-format-agenda-item "x" newhead cat tags dotime 'noprefix) pl (get-text-property (point) 'prefix-length) undone-face (get-text-property (point) 'undone-face) done-face (get-text-property (point) 'done-face)) @@ -6294,7 +6302,7 @@ (if org-tags-match-list-sublevels (make-string (1- level) ?.) "") (org-get-heading)) - category)) + category tags-list)) (goto-char lspos) (setq marker (org-agenda-new-marker)) (add-text-properties @@ -6870,11 +6878,19 @@ (setq cmd 'emacs) (setq cmd (or (cdr (assoc ext apps)) (cdr (assoc t apps))))) + (when (eq cmd 'mailcap) + (require 'mailcap) + (mailcap-parse-mailcaps) + (let* ((mime-type (mailcap-extension-to-mime (or ext ""))) + (command (mailcap-mime-info mime-type))) + (if (stringp command) + (setq cmd command) + (setq cmd 'emacs)))) (cond ((and (stringp cmd) (not (string-match "^\\s-*$" cmd))) (setq cmd (format cmd (concat "\"" file "\""))) (save-window-excursion - (shell-command (concat cmd " & &")))) + (shell-command (concat cmd " &")))) ((or (stringp cmd) (eq cmd 'emacs)) (unless (equal (file-truename file) (file-truename (buffer-file-name))) @@ -7587,7 +7603,7 @@ (while (< (setq i (1+ i)) maxfields) ;; Loop over all columns (setq column (mapcar (lambda (x) (or (nth i x) "")) fields)) ;; maximum length - (push (apply 'max 1 (mapcar 'length column)) lengths) + (push (apply 'max 1 (mapcar 'string-width column)) lengths) ;; compute the fraction stepwise, ignoring empty fields (setq cnt 0 frac 0.0) (mapcar @@ -7843,7 +7859,7 @@ (if (looking-at "|[^|\n]+") (let* ((pos (match-beginning 0)) (match (match-string 0)) - (len (length match))) + (len (string-width match))) (replace-match (concat "|" (make-string (1- len) ?\ ))) (goto-char (+ 2 pos)) (substring match 1))))) @@ -8101,7 +8117,9 @@ (interactive "P") (if (not (org-at-table-p)) (error "Not at a table")) - (let* ((line (buffer-substring-no-properties (point-at-bol) (point-at-eol))) + (let* ((line + (org-expand-wide-chars + (buffer-substring-no-properties (point-at-bol) (point-at-eol)))) new) (if (string-match "^[ \t]*|-" line) (setq new (mapcar (lambda (x) (if (member x '(?| ?+)) ?| ?\ )) line)) @@ -8124,7 +8142,9 @@ (interactive "P") (if (not (org-at-table-p)) (error "Not at a table")) - (let ((line (buffer-substring-no-properties (point-at-bol) (point-at-eol))) + (let ((line + (org-expand-wide-chars + (buffer-substring-no-properties (point-at-bol) (point-at-eol)))) (col (current-column)) start) (if (string-match "^[ \t]*|-" line) @@ -8143,9 +8163,19 @@ (if (equal (char-before (point)) ?+) (progn (backward-delete-char 1) (insert "|"))) (insert "\n") - (beginning-of-line 0) + (beginning-of-line (if arg 1 -1)) (move-to-column col))) +(defun org-expand-wide-chars (s) + "Expand wide characters to spaces." + (let (w a) + (mapconcat + (lambda (x) + (if (> (setq w (string-width (setq a (char-to-string x)))) 1) + (make-string w ?\ ) + a)) + s ""))) + (defun org-table-kill-row () "Delete the current row or horizontal line from the table." (interactive) @@ -8300,8 +8330,9 @@ ;; insert a hline before first (goto-char beg) (org-table-insert-hline 'above) + (beginning-of-line -1) ;; insert a hline after each line - (while (progn (beginning-of-line 2) (< (point) end)) + (while (progn (beginning-of-line 3) (< (point) end)) (org-table-insert-hline)) (goto-char beg) (setq end (move-marker end (org-table-end))) @@ -8390,7 +8421,7 @@ many lines, whatever width that takes. The return value is a list of lines, without newlines at the end." (let* ((words (org-split-string string "[ \t\n]+")) - (maxword (apply 'max (mapcar 'length words))) + (maxword (apply 'max (mapcar 'string-width words))) w ll) (cond (width (org-do-wrap words (max maxword width))) @@ -11130,10 +11161,10 @@ ;; - Bindings in Org-mode map are currently ;; 0123456789abcdefghijklmnopqrstuvwxyz!?@#$%^&-+*/=()_{}[]:;"|,.<>~`'\t the alphabet -;; abcd fgh j lmnopqrstuvwxyz ? #$ -+*/= [] ; |,.<>~ \t necessary bindings +;; abcd fgh j lmnopqrstuvwxyz!? #$ -+*/= [] ; |,.<>~ \t necessary bindings ;; e (?) useful from outline-mode ;; i k @ expendable from outline-mode -;; 0123456789 ! %^& ()_{} " `' free +;; 0123456789 %^& ()_{} " `' free ;; Make `C-c C-x' a prefix key (define-key org-mode-map "\C-c\C-x" (make-sparse-keymap)) @@ -12116,3 +12147,25 @@ ;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd ;;; org.el ends here + +(defun org-get-tags-at (&optional pos) + "Get a list of all headline targs applicable at POS. +POS defaults to point. If tags are inherited, the list contains +the targets in the same sequence as the headlines appear, i.e. +the tags of the current headline come last." + (interactive) + (let (tags) + (save-excursion + (goto-char (or pos (point))) + (save-match-data + (org-back-to-heading t) + (condition-case nil + (while t + (if (looking-at "[^\r\n]+?:\\([a-zA-Z_:]+\\):[ \t]*\\([\n\r]\\|\\'\\)") + (setq tags (append (org-split-string (match-string 1) ":") tags))) + (or org-use-tag-inheritance (error "")) + (org-up-heading-all 1)) + (error nil)))) + (message "%s" tags) + tags)) + diff -r 8438f5473d99 -r de425e4eb0bc lisp/tooltip.el --- a/lisp/tooltip.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/tooltip.el Tue Jan 17 00:56:42 2006 +0000 @@ -48,7 +48,10 @@ (define-minor-mode tooltip-mode "Toggle Tooltip display. -With ARG, turn tooltip mode on if and only if ARG is positive." +With ARG, turn tooltip mode on if and only if ARG is positive. +When this minor mode is enabled, Emacs displays help text +in a pop-up window on mouse-over. When it is disabled, +Emacs displays the help text in the echo area instead." :global t :init-value (not (or noninteractive emacs-basic-display diff -r 8438f5473d99 -r de425e4eb0bc lisp/wdired.el --- a/lisp/wdired.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/wdired.el Tue Jan 17 00:56:42 2006 +0000 @@ -193,7 +193,8 @@ (define-key map [menu-bar wdired dashes] '("--")) (define-key map [menu-bar wdired wdired-abort-changes] - '("Abort Changes" . wdired-abort-changes)) + '(menu-item "Abort Changes" wdired-abort-changes + :help "Abort changes and return to dired mode")) (define-key map [menu-bar wdired wdired-finish-edit] '("Commit Changes" . wdired-finish-edit)) ;; FIXME: Use the new remap trick. diff -r 8438f5473d99 -r de425e4eb0bc lisp/wid-edit.el --- a/lisp/wid-edit.el Thu Jan 12 11:20:02 2006 +0000 +++ b/lisp/wid-edit.el Tue Jan 17 00:56:42 2006 +0000 @@ -1203,22 +1203,24 @@ ;; or if a special `boundary' field has been added after the widget ;; field. (if (overlayp overlay) - (if (and (not (eq (with-current-buffer - (widget-field-buffer widget) - (save-restriction - ;; `widget-narrow-to-field' can be - ;; active when this function is called - ;; from an change-functions hook. So - ;; temporarily remove field narrowing - ;; before to call `get-char-property'. - (widen) - (get-char-property (overlay-end overlay) - 'field))) - 'boundary)) - (or widget-field-add-space - (null (widget-get widget :size)))) - (1- (overlay-end overlay)) - (overlay-end overlay)) + ;; Don't proceed if overlay has been removed from buffer. + (when (overlay-buffer overlay) + (if (and (not (eq (with-current-buffer + (widget-field-buffer widget) + (save-restriction + ;; `widget-narrow-to-field' can be + ;; active when this function is called + ;; from an change-functions hook. So + ;; temporarily remove field narrowing + ;; before to call `get-char-property'. + (widen) + (get-char-property (overlay-end overlay) + 'field))) + 'boundary)) + (or widget-field-add-space + (null (widget-get widget :size)))) + (1- (overlay-end overlay)) + (overlay-end overlay))) (cdr overlay)))) (defun widget-field-find (pos) diff -r 8438f5473d99 -r de425e4eb0bc lispref/ChangeLog --- a/lispref/ChangeLog Thu Jan 12 11:20:02 2006 +0000 +++ b/lispref/ChangeLog Tue Jan 17 00:56:42 2006 +0000 @@ -1,3 +1,8 @@ +2006-01-14 Nick Roberts + + * advice.texi (Simple Advice): Update example to fit argument + change in previous-line. + 2006-01-05 Richard M. Stallman * markers.texi (The Mark): Fix in `mark'. diff -r 8438f5473d99 -r de425e4eb0bc lispref/advice.texi --- a/lispref/advice.texi Thu Jan 12 11:20:02 2006 +0000 +++ b/lispref/advice.texi Tue Jan 17 00:56:42 2006 +0000 @@ -74,7 +74,8 @@ this: @example -(defadvice previous-line (before next-line-at-end (arg)) +(defadvice previous-line (before next-line-at-end + (&optional arg try-vscroll)) "Insert an empty line when moving up from the top line." (if (and next-line-add-newlines (= arg 1) (save-excursion (beginning-of-line) (bobp))) @@ -87,8 +88,8 @@ @code{previous-line}. This piece of advice is named @code{next-line-at-end}, and the symbol @code{before} says that it is @dfn{before-advice} which should run before the regular definition of -@code{previous-line}. @code{(arg)} specifies how the advice code can -refer to the function's arguments. +@code{previous-line}. @code{(&optional arg try-vscroll)} specifies +how the advice code can refer to the function's arguments. When this piece of advice runs, it creates an additional line, in the situation where that is appropriate, but does not move point to that diff -r 8438f5473d99 -r de425e4eb0bc man/ChangeLog --- a/man/ChangeLog Thu Jan 12 11:20:02 2006 +0000 +++ b/man/ChangeLog Tue Jan 17 00:56:42 2006 +0000 @@ -1,3 +1,24 @@ +2006-01-13 Katsumi Yamaoka + + * gnus.texi (Article Washing): Additions. + +2006-01-08 Alex Schroeder + + * pgg.texi (Caching passphrase): Rewording. + +2006-01-14 Richard M. Stallman + + * basic.texi (Inserting Text): Minor cleanup. + +2006-01-13 Carsten Dominik + + * org.texi: (Agenda commands): Document tags command. + +2006-01-11 Luc Teirlinck + + * custom.texi (Changing a Variable, Face Customization): Update + for changes in Custom menus. + 2006-01-10 Katsumi Yamaoka * gnus.texi (RSS): Document nnrss-wash-html-in-text-plain-parts. @@ -40,7 +61,7 @@ 2006-01-05 Carsten Dominik - * org.texi: (Agenda Views): Chapter reorganized. + * org.texi (Agenda Views): Chapter reorganized. 2006-01-02 Chong Yidong diff -r 8438f5473d99 -r de425e4eb0bc man/basic.texi --- a/man/basic.texi Thu Jan 12 11:20:02 2006 +0000 +++ b/man/basic.texi Tue Jan 17 00:56:42 2006 +0000 @@ -63,7 +63,7 @@ @key{ENTER} key doesn't delete backwards, you need to do this. @xref{DEL Does Not Delete}, for an explanation of how. - Most PC keyboards have both a @key{BACKSPACE} key a short ways above + Most PC keyboards have both a @key{BACKSPACE} key not far above @key{RET} or @key{ENTER}, and a @key{DELETE} key elsewhere. On these keyboards, Emacs supports when possible the usual convention that the @key{BACKSPACE} key deletes backwards (it is @key{DEL}), while the diff -r 8438f5473d99 -r de425e4eb0bc man/cc-mode.texi --- a/man/cc-mode.texi Thu Jan 12 11:20:02 2006 +0000 +++ b/man/cc-mode.texi Tue Jan 17 00:56:42 2006 +0000 @@ -208,7 +208,7 @@ @vskip 0pt plus 1filll @insertcopying -This manual was generated from $Revision: 1.32 $ of $RCSfile: cc-mode.texi,v $, which can be +This manual was generated from $Revision$ of $RCSfile$, which can be downloaded from @url{http://cvs.sf.net/viewcvs.py/cc-mode/cc-mode/cc-mode.texi}. @end titlepage diff -r 8438f5473d99 -r de425e4eb0bc man/custom.texi --- a/man/custom.texi Thu Jan 12 11:20:02 2006 +0000 +++ b/man/custom.texi Tue Jan 17 00:56:42 2006 +0000 @@ -230,7 +230,7 @@ @smallexample /- Emacs group: ---------------------------------------------------\ - [State]: visible group members are all at standard settings. + [State]: visible group members are all at standard values. Customization of the One True Editor. See also [Manual]. @@ -446,7 +446,7 @@ There are actually four reset operations: @table @samp -@item Reset to Current +@item Undo Edits If you have made some modifications and not yet set the variable, this restores the text in the customization buffer to match the actual value. @@ -460,7 +460,7 @@ accordingly. This also eliminates any saved value for the variable, so that you will get the standard value in future Emacs sessions. -@item Use Backup Value +@item Set to Backup Value This sets the variable to a previous value that was set in the customization buffer in this session. If you customize a variable and then reset it, which discards the customized value, @@ -481,7 +481,7 @@ @smallexample [Set for Current Session] [Save for Future Sessions] - [Reset to Current] [Reset to Saved] [Erase Customization] [Finish] + [Undo Edits] [Reset to Saved] [Erase Customization] [Finish] @end smallexample @vindex custom-buffer-done-function @@ -591,8 +591,8 @@ A face can specify different appearances for different types of display. For example, a face can make text red on a color display, but use a bold font on a monochrome display. To specify multiple -appearances for a face, select @samp{Show all display specs} in the menu you -get from invoking @samp{[State]}. +appearances for a face, select @samp{For All Kinds of Displays} in the +menu you get from invoking @samp{[State]}. @findex modify-face Another more basic way to set the attributes of a specific face is diff -r 8438f5473d99 -r de425e4eb0bc man/gnus.texi --- a/man/gnus.texi Thu Jan 12 11:20:02 2006 +0000 +++ b/man/gnus.texi Tue Jan 17 00:56:42 2006 +0000 @@ -8571,7 +8571,9 @@ usually done automatically by Gnus if the message in question has a @code{Content-Type} header that says that the message is @acronym{HTML}. -If a prefix is given, a charset will be asked for. +If a prefix is given, a charset will be asked for. If it is a number, +the charset defined in @code{gnus-summary-show-article-charset-alist} +(@pxref{Paging the Article}) will be used. @vindex gnus-article-wash-function The default is to use the function specified by @@ -8582,12 +8584,15 @@ can use include: @table @code -@item W3 +@item w3 Use Emacs/W3. @item w3m Use @uref{http://emacs-w3m.namazu.org/, emacs-w3m}. +@item w3m-standalone +Use @uref{http://w3m.sourceforge.net/, w3m}. + @item links Use @uref{http://links.sf.net/, Links}. diff -r 8438f5473d99 -r de425e4eb0bc man/org.texi --- a/man/org.texi Thu Jan 12 11:20:02 2006 +0000 +++ b/man/org.texi Tue Jan 17 00:56:42 2006 +0000 @@ -4,7 +4,7 @@ @setfilename ../info/org @settitle Org Mode Manual -@set VERSION 4.02 +@set VERSION 4.03 @set DATE January 2006 @dircategory Emacs @@ -2509,6 +2509,11 @@ Change the TODO state of the item, both in the agenda and in the original org file. +@kindex T +@item T +Show all tags associated with the current item. Because of +inheritance, this may be more than the tags listed in the line itself. + @kindex : @item : Set tags for the current headline. diff -r 8438f5473d99 -r de425e4eb0bc src/ChangeLog --- a/src/ChangeLog Thu Jan 12 11:20:02 2006 +0000 +++ b/src/ChangeLog Tue Jan 17 00:56:42 2006 +0000 @@ -1,3 +1,25 @@ +2006-01-15 Andreas Schwab + + * search.c (Freplace_match): Use UPPERCASEP instead of !NOCASEP. + +2006-01-13 Richard M. Stallman + + * Makefile.in: Define new macro WINDOW_SUPPORT. + (lisp): Use it. + (SOME_MACHINE_LISP): Add conditionally loaded files. + +2006-01-12 YAMAMOTO Mitsuharu + + * macterm.c [USE_ATSUI] (atsu_get_text_layout_with_text_ptr) + [MAC_OS_X_VERSION_MAX_ALLOWED >= 1020]: Specify kATSLineUseQDRendering. + (XLoadQueryFont) [USE_ATSUI]: Display diacritical marks in + decomposed form. + + * process.c [HAVE_INTTYPES_H]: Include inttypes.h. + (ifflag_table): Fix typo (IFF_OACTIV -> IFF_OACTIVE). + (Fnetwork_interface_info): Use HAVE_STRUCT_IFREQ_IFR_NETMASK + macro. Also try member ifr_addr when getting netmask. + 2006-01-10 Stefan Monnier * fileio.c (Fexpand_file_name): Remove redundant tests. @@ -23,7 +45,7 @@ 2006-01-05 Kim F. Storm * process.c (Fmake_network_process): Use AF_INET instead of - AF_UNSPEC when AF_INET6 is not defined. + AF_UNSPEC when AF_INET6 is not defined. 2006-01-05 YAMAMOTO Mitsuharu diff -r 8438f5473d99 -r de425e4eb0bc src/Makefile.in --- a/src/Makefile.in Thu Jan 12 11:20:02 2006 +0000 +++ b/src/Makefile.in Tue Jan 17 00:56:42 2006 +0000 @@ -676,6 +676,20 @@ #define MSDOS_SUPPORT #endif +#ifdef HAVE_WINDOW_SYSTEM +#ifdef HAVE_X_WINDOWS +#define WINDOW_SUPPORT ${lispsource}image.elc \ + ${lispsource}international/fontset.elc ${lispsource}dnd.elc \ + ${lispsource}tool-bar.elc ${lispsource}mwheel.elc ${lispsource}x-dnd.elc +#else +#define WINDOW_SUPPORT ${lispsource}image.elc \ + ${lispsource}international/fontset.elc ${lispsource}dnd.elc \ + ${lispsource}tool-bar.elc ${lispsource}mwheel.elc +#endif +#else +#define WINDOW_SUPPORT +#endif + #ifdef WINDOWSNT #define WINNT_SUPPORT ${lispsource}ls-lisp.elc ${lispsource}disp-table.elc \ ${lispsource}dos-w32.elc ${lispsource}w32-vars.elc \ @@ -794,6 +808,7 @@ VMS_SUPPORT \ MSDOS_SUPPORT \ WINNT_SUPPORT \ + WINDOW_SUPPORT \ ${lispsource}widget.elc \ ${lispsource}window.elc \ ${lispsource}version.el @@ -904,11 +919,14 @@ ${dotdot}/lisp/ls-lisp.elc ${dotdot}/lisp/dos-fns.elc \ ${dotdot}/lisp/w32-fns.elc ${dotdot}/lisp/dos-w32.elc \ ${dotdot}/lisp/disp-table.elc ${dotdot}/lisp/dos-vars.elc \ - ${dotdot}/lisp/tooltip.elc \ + ${dotdot}/lisp/tooltip.elc ${dotdot}/lisp/image.elc \ + ${dotdot}/lisp/dnd.elc ${dotdot}/lisp/mwheel.elc \ + ${dotdot}/lisp/tool-bar.elc \ + ${dotdot}/lisp/x-dnd.elc \ ${dotdot}/lisp/international/ccl.elc \ ${dotdot}/lisp/international/codepage.elc \ - ${dotdot}/lisp/mouse.elc ${dotdot}/lisp/international/fontset.elc \ - ${dotdot}/lisp/dnd.elc ${dotdot}/lisp/x-dnd.elc \ + ${dotdot}/lisp/international/fontset.elc + ${dotdot}/lisp/mouse.elc \ ${dotdot}/lisp/term/x-win.elc /* Construct full set of libraries to be linked. diff -r 8438f5473d99 -r de425e4eb0bc src/macterm.c --- a/src/macterm.c Thu Jan 12 11:20:02 2006 +0000 +++ b/src/macterm.c Tue Jan 17 00:56:42 2006 +0000 @@ -626,6 +626,7 @@ static ATSLineLayoutOptions line_layout = #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics + | kATSLineUseQDRendering #else kATSLineIsDisplayOnly | kATSLineFractDisable #endif @@ -7507,8 +7508,10 @@ static Boolean bold_p, italic_p; ATSUAttributeValuePtr values[] = {&font_id, &size_fixed, &bold_p, &italic_p}; - ATSUFontFeatureType types[] = {kAllTypographicFeaturesType}; - ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector}; + ATSUFontFeatureType types[] = {kAllTypographicFeaturesType, + kDiacriticsType}; + ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector, + kDecomposeDiacriticsSelector}; Lisp_Object font_id_cons; font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)), diff -r 8438f5473d99 -r de425e4eb0bc src/process.c --- a/src/process.c Thu Jan 12 11:20:02 2006 +0000 +++ b/src/process.c Tue Jan 17 00:56:42 2006 +0000 @@ -40,6 +40,9 @@ #include /* some typedefs are used in sys/file.h */ #include #include +#ifdef HAVE_INTTYPES_H +#include +#endif #ifdef HAVE_UNISTD_H #include #endif @@ -3601,8 +3604,8 @@ #ifdef IFF_DYNAMIC { IFF_DYNAMIC, "dynamic" }, #endif -#ifdef IFF_OACTIV - { IFF_OACTIV, "oactiv" }, /* OpenBSD: transmission in progress */ +#ifdef IFF_OACTIVE + { IFF_OACTIVE, "oactive" }, /* OpenBSD: transmission in progress */ #endif #ifdef IFF_SIMPLEX { IFF_SIMPLEX, "simplex" }, /* OpenBSD: can't hear own transmissions */ @@ -3688,11 +3691,15 @@ res = Fcons (elt, res); elt = Qnil; -#if defined(SIOCGIFNETMASK) && defined(ifr_netmask) +#if defined(SIOCGIFNETMASK) && (defined(HAVE_STRUCT_IFREQ_IFR_NETMASK) || defined(HAVE_STRUCT_IFREQ_IFR_ADDR)) if (ioctl (s, SIOCGIFNETMASK, &rq) == 0) { any++; +#ifdef HAVE_STRUCT_IFREQ_IFR_NETMASK elt = conv_sockaddr_to_lisp (&rq.ifr_netmask, sizeof (rq.ifr_netmask)); +#else + elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr)); +#endif } #endif res = Fcons (elt, res); diff -r 8438f5473d99 -r de425e4eb0bc src/search.c --- a/src/search.c Thu Jan 12 11:20:02 2006 +0000 +++ b/src/search.c Tue Jan 17 00:56:42 2006 +0000 @@ -2376,7 +2376,7 @@ else some_multiletter_word = 1; } - else if (!NOCASEP (c)) + else if (UPPERCASEP (c)) { some_uppercase = 1; if (SYNTAX (prevc) != Sword)