summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/distro/ucslugc-packages.conf3
-rw-r--r--conf/machine/nokia770.conf14
-rw-r--r--packages/bwmon/bwmon_1.3.bb3
-rw-r--r--packages/ccxstream/ccxstream_1.0.15.bb4
-rw-r--r--packages/gpe-dm/files/Xserver-spitz.patch11
-rw-r--r--packages/gpe-dm/gpe-dm_0.47.bb5
-rw-r--r--packages/openntpd/openntpd_3.7p1.bb4
-rw-r--r--packages/perl/perl-5.8.7/config.sh-i386-linux1026
-rw-r--r--packages/perl/perl_5.8.7.bb6
-rw-r--r--packages/pine/pine-4.63/.mtn2git_empty0
-rw-r--r--packages/pine/pine-4.63/imap-2000-time.patch56
-rw-r--r--packages/pine/pine-4.63/pine-4.30-ldap.patch11
-rw-r--r--packages/pine/pine-4.63/pine-4.31-segfix.patch17
-rw-r--r--packages/pine/pine-4.63/pine-4.40-lockfile-perm.patch22
-rw-r--r--packages/pine/pine-4.63/pine-4.56-passfile.patch12
-rw-r--r--packages/pine/pine-4.63/pine-4.61-largeterminal.patch14
-rw-r--r--packages/pine/pine-4.63/pine-4.61-subjectlength.patch59
-rw-r--r--packages/pine/pine-4.63/pine-4.62-spooldir-permissions.patch12
-rw-r--r--packages/pine/pine-4.63/pine-4.63-r2-chappa-all.patch21900
-rw-r--r--packages/pine/pine-4.63/pine-ldap3.patch11
-rw-r--r--packages/pine/pine-4.63/transparency.patch14
-rw-r--r--packages/pine/pine_4.63.bb131
-rw-r--r--packages/tetex/tetex-native_3.0.bb11
23 files changed, 23274 insertions, 72 deletions
diff --git a/conf/distro/ucslugc-packages.conf b/conf/distro/ucslugc-packages.conf
index b76d352b8a..c6575241ba 100644
--- a/conf/distro/ucslugc-packages.conf
+++ b/conf/distro/ucslugc-packages.conf
@@ -14,7 +14,9 @@ ${PKGDIR}/packages/bluez-utils/*.bb \
${PKGDIR}/packages/boost/*.bb \
${PKGDIR}/packages/bridge-utils/*.bb \
${PKGDIR}/packages/busybox/*.bb \
+${PKGDIR}/packages/bwmon/*.bb \
${PKGDIR}/packages/bzip2/*.bb \
+${PKGDIR}/packages/ccxstream/*.bb \
${PKGDIR}/packages/coreutils/*.bb \
${PKGDIR}/packages/cpio/*.bb \
${PKGDIR}/packages/cron/*.bb \
@@ -129,6 +131,7 @@ ${PKGDIR}/packages/sudo/*.bb \
${PKGDIR}/packages/sysfsutils/*.bb \
${PKGDIR}/packages/sysvinit/*.bb \
${PKGDIR}/packages/thttpd/*.bb \
+${PKGDIR}/packages/timezones/*.bb \
${PKGDIR}/packages/tinylogin/*.bb \
${PKGDIR}/packages/uclibc/*.bb \
${PKGDIR}/packages/unionfs/*.bb \
diff --git a/conf/machine/nokia770.conf b/conf/machine/nokia770.conf
index 7a39104c63..c928093855 100644
--- a/conf/machine/nokia770.conf
+++ b/conf/machine/nokia770.conf
@@ -11,10 +11,8 @@ XSERVER = "xserver-kdrive-omap"
# 800x480 is big enough for me
GUI_MACHINE_CLASS = "bigscreen"
-GPE_EXTRA_DEPENDS += "gaim sylpheed"
-GPE_EXTRA_INSTALL += "gaim sylpheed"
-
-include conf/machine/handheld-common.conf
+GPE_EXTRA_DEPENDS += "gaim sylpheed gpe-mini-browser"
+GPE_EXTRA_INSTALL += "gaim sylpheed gpe-mini-browser"
# Use tune-arm926 per default. Machine independent feeds should be built with tune-strongarm.
include conf/machine/tune-arm926ejs.conf
@@ -32,10 +30,10 @@ SERIAL_CONSOLE = "115200 ttyS0"
#build omap1 till nokia releases the patches
PREFERRED_PROVIDER_virtual/kernel = "linux-omap1"
-BOOTSTRAP_EXTRA_DEPENDS = "virtual/kernel sysfsutils nokia770-init \
+BOOTSTRAP_EXTRA_DEPENDS += "virtual/kernel sysfsutils nokia770-init \
pcmcia-cs apmd ppp wireless-tools console-tools openswan wpa-supplicant-nossl lrzsz ppp-dialin"
-BOOTSTRAP_EXTRA_RDEPENDS = "sysfsutils nokia770-init \
+BOOTSTRAP_EXTRA_RDEPENDS += "sysfsutils nokia770-init \
pcmcia-cs apm ppp wireless-tools console-tools"
# NFS Modules
@@ -56,3 +54,7 @@ pcmcia-cs apm ppp wireless-tools console-tools"
#BOOTSTRAP_EXTRA_RDEPENDS += "kernel-module-gadgetfs kernel-module-g-file-storage kernel-module-g-serial \
# kernel-module-g-ether"
+include conf/machine/handheld-common.conf
+
+
+
diff --git a/packages/bwmon/bwmon_1.3.bb b/packages/bwmon/bwmon_1.3.bb
index 25271641e7..26c620e013 100644
--- a/packages/bwmon/bwmon_1.3.bb
+++ b/packages/bwmon/bwmon_1.3.bb
@@ -12,5 +12,6 @@ EXTRA_OEMAKE = "LDFLAGS=-L${STAGING_LIBDIR}"
inherit autotools
do_install () {
- install ${S}/bwmon ${D}/usr/bin/bwmon
+ install -d ${D}${bindir}
+ install ${S}/bwmon ${D}${bindir}/bwmon
}
diff --git a/packages/ccxstream/ccxstream_1.0.15.bb b/packages/ccxstream/ccxstream_1.0.15.bb
index 751e0412c5..cc42d895ca 100644
--- a/packages/ccxstream/ccxstream_1.0.15.bb
+++ b/packages/ccxstream/ccxstream_1.0.15.bb
@@ -1,7 +1,7 @@
DESCRIPTION = "XStream Server"
-
+DEPENDS = "readline"
LICENSE = "GPL-2"
-PR = "r1"
+PR = "r2"
SRC_URI = "http://surfnet.dl.sourceforge.net/sourceforge/xbplayer/${P}.tar.gz \
file://ccxstream-termcap.patch;patch=1 \
diff --git a/packages/gpe-dm/files/Xserver-spitz.patch b/packages/gpe-dm/files/Xserver-spitz.patch
new file mode 100644
index 0000000000..f30b705d13
--- /dev/null
+++ b/packages/gpe-dm/files/Xserver-spitz.patch
@@ -0,0 +1,11 @@
+--- gpe-dm-0.47/Xserver~ 2005-07-29 11:58:59.000000000 -0700
++++ gpe-dm-0.47/Xserver 2005-08-01 11:20:42.000000000 -0700
+@@ -62,6 +62,8 @@
+ ;;
+ "SHARP Shepherd" | "SHARP Husky" | "SHARP Corgi")
+ ARGS="$ARGS -rgba rgb" ;;
++ "SHARP Spitz")
++ ARGS="$ARGS -rgba rgb -screen 640x480@270" ;;
+ "Simpad")
+ ARGS="$ARGS -rgba rgb" ;;
+ "Generic OMAP1510/1610/1710")
diff --git a/packages/gpe-dm/gpe-dm_0.47.bb b/packages/gpe-dm/gpe-dm_0.47.bb
index a98220547e..5f87b3ce6a 100644
--- a/packages/gpe-dm/gpe-dm_0.47.bb
+++ b/packages/gpe-dm/gpe-dm_0.47.bb
@@ -6,9 +6,10 @@ SECTION = "gpe"
PRIORITY = "optional"
MAINTAINER = "Phil Blundell <pb@handhelds.org>"
DEPENDS = "glib-2.0"
-PR = "r1"
+PR = "r2"
INITSCRIPT_NAME = "gpe-dm"
INITSCRIPT_PARAMS = "start 99 5 2 . stop 20 0 1 6 ."
-SRC_URI += "file://collie-suspend-hack.patch;patch=1"
+SRC_URI += "file://collie-suspend-hack.patch;patch=1 \
+ file://Xserver-spitz.patch;patch=1"
diff --git a/packages/openntpd/openntpd_3.7p1.bb b/packages/openntpd/openntpd_3.7p1.bb
index 0c2091160f..fc355c7273 100644
--- a/packages/openntpd/openntpd_3.7p1.bb
+++ b/packages/openntpd/openntpd_3.7p1.bb
@@ -5,7 +5,8 @@ HOMEPAGE = "http://www.openntpd.org/"
LICENSE = "BSD"
SECTION = "console/network"
MAINTAINER = "Oyvind Repvik <nail@nslu2-linux.org>"
-PR="r2"
+DEPENDS = "timezones"
+PR="r3"
SRC_URI = "http://www.zip.com.au/~dtucker/openntpd/release/openntpd-${PV}.tar.gz \
file://autofoo.patch;patch=1 \
@@ -26,7 +27,6 @@ do_install_prepend() {
do_install_append() {
install -c -m 755 ${WORKDIR}/init ${D}${sysconfdir}/init.d/openntpd
- install -d ${D}${localstatedir}/shared/empty
}
pkg_postrm () {
diff --git a/packages/perl/perl-5.8.7/config.sh-i386-linux b/packages/perl/perl-5.8.7/config.sh-i386-linux
new file mode 100644
index 0000000000..fda13d0d9b
--- /dev/null
+++ b/packages/perl/perl-5.8.7/config.sh-i386-linux
@@ -0,0 +1,1026 @@
+#!/bin/sh
+#
+# This file was produced by running the Configure script. It holds all the
+# definitions figured out by Configure. Should you modify one of these values,
+# do not forget to propagate your changes by running "Configure -der". You may
+# instead choose to run each of the .SH files by yourself, or "Configure -S".
+#
+
+# Package name : perl5
+# Source directory : .
+# Configuration time: Wed Mar 9 04:09:49 CST 2005
+# Configured by : kergoth
+# Target system : linux hyperion 2.6.11-ck1 #1 wed mar 2 23:48:21 cst 2005 i386 gnulinux
+
+Author=''
+Date='$Date'
+Header=''
+Id='$Id'
+Locker=''
+Log='$Log'
+Mcc='Mcc'
+RCSfile='$RCSfile'
+Revision='$Revision'
+Source=''
+State=''
+_a='.a'
+_exe=''
+_o='.o'
+afs='false'
+afsroot='/afs'
+alignbytes='4'
+ansi2knr=''
+aphostname='/bin/hostname'
+api_revision='5'
+api_subversion='0'
+api_version='8'
+api_versionstring='5.8.0'
+ar='ar'
+archlib='/usr/lib/perl5/5.8.4/i386-linux'
+archlibexp='/usr/lib/perl5/5.8.4/i386-linux'
+archname64=''
+archname='i386-linux'
+archobjs=''
+asctime_r_proto='0'
+awk='awk'
+baserev='5.0'
+bash=''
+bin='/usr/bin'
+binexp='/usr/bin'
+bison='bison'
+byacc='byacc'
+byteorder='1234'
+c=''
+castflags='0'
+cat='cat'
+cc='cc'
+cccdlflags='-fpic'
+ccdlflags='-Wl,-E -Wl,-rpath,./install_me_here/usr/lib/perl5/5.8.4/i386-linux/CORE'
+ccflags='-fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
+ccflags_uselargefiles='-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
+ccname='gcc'
+ccsymbols='__GNUC_PATCHLEVEL__=5'
+ccversion=''
+cf_by='kergoth'
+cf_email='kergoth@hyperion.kergoth.com'
+cf_time='Wed Mar 9 04:09:49 CST 2005'
+charsize='1'
+chgrp=''
+chmod='chmod'
+chown=''
+clocktype='clock_t'
+comm='comm'
+compress=''
+contains='grep'
+cp='cp'
+cpio=''
+cpp='cpp'
+cpp_stuff='42'
+cppccsymbols='__GNUC__=3 __GNUC_MINOR__=3'
+cppflags='-fno-strict-aliasing -I/usr/local/include'
+cpplast='-'
+cppminus='-'
+cpprun='cc -E'
+cppstdin='cc -E'
+cppsymbols='__ELF__=1 _FILE_OFFSET_BITS=64 __GLIBC__=2 __GLIBC_MINOR__=3 __GNU_LIBRARY__=6 i386=1 __i386=1 __i386__=1 __i486=1 __i486__=1 _LARGEFILE_SOURCE=1 linux=1 __linux=1 __linux__=1 _POSIX_C_SOURCE=199506 _POSIX_SOURCE=1 __STDC__=1 unix=1 __unix=1 __unix__=1 __USE_BSD=1 __USE_FILE_OFFSET64=1 __USE_LARGEFILE=1 __USE_MISC=1 __USE_POSIX=1 __USE_POSIX199309=1 __USE_POSIX199506=1 __USE_POSIX2=1 __USE_SVID=1'
+crypt_r_proto='0'
+cryptlib=''
+csh='csh'
+ctermid_r_proto='0'
+ctime_r_proto='0'
+d_Gconvert='gcvt((x),(n),(b))'
+d_PRIEUldbl='define'
+d_PRIFUldbl='define'
+d_PRIGUldbl='define'
+d_PRIXU64='define'
+d_PRId64='define'
+d_PRIeldbl='define'
+d_PRIfldbl='define'
+d_PRIgldbl='define'
+d_PRIi64='define'
+d_PRIo64='define'
+d_PRIu64='define'
+d_PRIx64='define'
+d_SCNfldbl='define'
+d__fwalk='undef'
+d_access='define'
+d_accessx='undef'
+d_aintl='undef'
+d_alarm='define'
+d_archlib='define'
+d_asctime_r='undef'
+d_atolf='undef'
+d_atoll='define'
+d_attribut='define'
+d_bcmp='define'
+d_bcopy='define'
+d_bsd='undef'
+d_bsdgetpgrp='undef'
+d_bsdsetpgrp='undef'
+d_bzero='define'
+d_casti32='undef'
+d_castneg='define'
+d_charvspr='define'
+d_chown='define'
+d_chroot='define'
+d_chsize='undef'
+d_class='undef'
+d_closedir='define'
+d_cmsghdr_s='define'
+d_const='define'
+d_copysignl='define'
+d_crypt='define'
+d_crypt_r='undef'
+d_csh='undef'
+d_ctermid_r='undef'
+d_ctime_r='undef'
+d_cuserid='define'
+d_dbl_dig='define'
+d_dbminitproto='undef'
+d_difftime='define'
+d_dirfd='define'
+d_dirnamlen='undef'
+d_dlerror='define'
+d_dlopen='define'
+d_dlsymun='undef'
+d_dosuid='undef'
+d_drand48_r='undef'
+d_drand48proto='define'
+d_dup2='define'
+d_eaccess='undef'
+d_endgrent='define'
+d_endgrent_r='undef'
+d_endhent='define'
+d_endhostent_r='undef'
+d_endnent='define'
+d_endnetent_r='undef'
+d_endpent='define'
+d_endprotoent_r='undef'
+d_endpwent='define'
+d_endpwent_r='undef'
+d_endsent='define'
+d_endservent_r='undef'
+d_eofnblk='define'
+d_eunice='undef'
+d_faststdio='undef'
+d_fchdir='define'
+d_fchmod='define'
+d_fchown='define'
+d_fcntl='define'
+d_fcntl_can_lock='define'
+d_fd_macros='define'
+d_fd_set='define'
+d_fds_bits='undef'
+d_fgetpos='define'
+d_finite='define'
+d_finitel='define'
+d_flexfnam='define'
+d_flock='define'
+d_flockproto='define'
+d_fork='define'
+d_fp_class='undef'
+d_fpathconf='define'
+d_fpclass='undef'
+d_fpclassify='undef'
+d_fpclassl='undef'
+d_fpos64_t='undef'
+d_frexpl='define'
+d_fs_data_s='undef'
+d_fseeko='define'
+d_fsetpos='define'
+d_fstatfs='define'
+d_fstatvfs='define'
+d_fsync='define'
+d_ftello='define'
+d_ftime='undef'
+d_getcwd='define'
+d_getespwnam='undef'
+d_getfsstat='undef'
+d_getgrent='define'
+d_getgrent_r='undef'
+d_getgrgid_r='undef'
+d_getgrnam_r='undef'
+d_getgrps='define'
+d_gethbyaddr='define'
+d_gethbyname='define'
+d_gethent='define'
+d_gethname='define'
+d_gethostbyaddr_r='undef'
+d_gethostbyname_r='undef'
+d_gethostent_r='undef'
+d_gethostprotos='define'
+d_getitimer='define'
+d_getlogin='define'
+d_getlogin_r='undef'
+d_getmnt='undef'
+d_getmntent='define'
+d_getnbyaddr='define'
+d_getnbyname='define'
+d_getnent='define'
+d_getnetbyaddr_r='undef'
+d_getnetbyname_r='undef'
+d_getnetent_r='undef'
+d_getnetprotos='define'
+d_getpagsz='define'
+d_getpbyname='define'
+d_getpbynumber='define'
+d_getpent='define'
+d_getpgid='define'
+d_getpgrp2='undef'
+d_getpgrp='define'
+d_getppid='define'
+d_getprior='define'
+d_getprotobyname_r='undef'
+d_getprotobynumber_r='undef'
+d_getprotoent_r='undef'
+d_getprotoprotos='define'
+d_getprpwnam='undef'
+d_getpwent='define'
+d_getpwent_r='undef'
+d_getpwnam_r='undef'
+d_getpwuid_r='undef'
+d_getsbyname='define'
+d_getsbyport='define'
+d_getsent='define'
+d_getservbyname_r='undef'
+d_getservbyport_r='undef'
+d_getservent_r='undef'
+d_getservprotos='define'
+d_getspnam='define'
+d_getspnam_r='undef'
+d_gettimeod='define'
+d_gmtime_r='undef'
+d_gnulibc='define'
+d_grpasswd='define'
+d_hasmntopt='define'
+d_htonl='define'
+d_ilogbl='define'
+d_index='undef'
+d_inetaton='define'
+d_int64_t='define'
+d_isascii='define'
+d_isfinite='undef'
+d_isinf='define'
+d_isnan='define'
+d_isnanl='define'
+d_killpg='define'
+d_lchown='define'
+d_ldbl_dig='define'
+d_libm_lib_version='define'
+d_link='define'
+d_localtime_r='undef'
+d_locconv='define'
+d_lockf='define'
+d_longdbl='define'
+d_longlong='define'
+d_lseekproto='define'
+d_lstat='define'
+d_madvise='define'
+d_mblen='define'
+d_mbstowcs='define'
+d_mbtowc='define'
+d_memchr='define'
+d_memcmp='define'
+d_memcpy='define'
+d_memmove='define'
+d_memset='define'
+d_mkdir='define'
+d_mkdtemp='define'
+d_mkfifo='define'
+d_mkstemp='define'
+d_mkstemps='undef'
+d_mktime='define'
+d_mmap='define'
+d_modfl='define'
+d_modfl_pow32_bug='undef'
+d_modflproto='undef'
+d_mprotect='define'
+d_msg='define'
+d_msg_ctrunc='define'
+d_msg_dontroute='define'
+d_msg_oob='define'
+d_msg_peek='define'
+d_msg_proxy='define'
+d_msgctl='define'
+d_msgget='define'
+d_msghdr_s='define'
+d_msgrcv='define'
+d_msgsnd='define'
+d_msync='define'
+d_munmap='define'
+d_mymalloc='undef'
+d_nice='define'
+d_nl_langinfo='define'
+d_nv_preserves_uv='define'
+d_off64_t='undef'
+d_old_pthread_create_joinable='undef'
+d_oldpthreads='undef'
+d_oldsock='undef'
+d_open3='define'
+d_pathconf='define'
+d_pause='define'
+d_perl_otherlibdirs='undef'
+d_phostname='undef'
+d_pipe='define'
+d_poll='define'
+d_portable='define'
+d_procselfexe='define'
+d_pthread_atfork='undef'
+d_pthread_attr_setscope='define'
+d_pthread_yield='undef'
+d_pwage='undef'
+d_pwchange='undef'
+d_pwclass='undef'
+d_pwcomment='undef'
+d_pwexpire='undef'
+d_pwgecos='define'
+d_pwpasswd='define'
+d_pwquota='undef'
+d_qgcvt='define'
+d_quad='define'
+d_random_r='undef'
+d_readdir64_r='undef'
+d_readdir='define'
+d_readdir_r='undef'
+d_readlink='define'
+d_readv='define'
+d_recvmsg='define'
+d_rename='define'
+d_rewinddir='define'
+d_rmdir='define'
+d_safebcpy='undef'
+d_safemcpy='undef'
+d_sanemcmp='define'
+d_sbrkproto='define'
+d_scalbnl='define'
+d_sched_yield='define'
+d_scm_rights='define'
+d_seekdir='define'
+d_select='define'
+d_sem='define'
+d_semctl='define'
+d_semctl_semid_ds='define'
+d_semctl_semun='define'
+d_semget='define'
+d_semop='define'
+d_sendmsg='define'
+d_setegid='define'
+d_seteuid='define'
+d_setgrent='define'
+d_setgrent_r='undef'
+d_setgrps='define'
+d_sethent='define'
+d_sethostent_r='undef'
+d_setitimer='define'
+d_setlinebuf='define'
+d_setlocale='define'
+d_setlocale_r='undef'
+d_setnent='define'
+d_setnetent_r='undef'
+d_setpent='define'
+d_setpgid='define'
+d_setpgrp2='undef'
+d_setpgrp='define'
+d_setprior='define'
+d_setproctitle='undef'
+d_setprotoent_r='undef'
+d_setpwent='define'
+d_setpwent_r='undef'
+d_setregid='define'
+d_setresgid='define'
+d_setresuid='define'
+d_setreuid='define'
+d_setrgid='undef'
+d_setruid='undef'
+d_setsent='define'
+d_setservent_r='undef'
+d_setsid='define'
+d_setvbuf='define'
+d_sfio='undef'
+d_shm='define'
+d_shmat='define'
+d_shmatprototype='define'
+d_shmctl='define'
+d_shmdt='define'
+d_shmget='define'
+d_sigaction='define'
+d_sigprocmask='define'
+d_sigsetjmp='define'
+d_sockatmark='define'
+d_sockatmarkproto='undef'
+d_socket='define'
+d_socklen_t='define'
+d_sockpair='define'
+d_socks5_init='undef'
+d_sqrtl='define'
+d_srand48_r='undef'
+d_srandom_r='undef'
+d_sresgproto='undef'
+d_sresuproto='undef'
+d_statblks='define'
+d_statfs_f_flags='undef'
+d_statfs_s='define'
+d_statvfs='define'
+d_stdio_cnt_lval='undef'
+d_stdio_ptr_lval='undef'
+d_stdio_ptr_lval_nochange_cnt='undef'
+d_stdio_ptr_lval_sets_cnt='undef'
+d_stdio_stream_array='undef'
+d_stdiobase='undef'
+d_stdstdio='undef'
+d_strchr='define'
+d_strcoll='define'
+d_strctcpy='define'
+d_strerrm='strerror(e)'
+d_strerror='define'
+d_strerror_r='undef'
+d_strftime='define'
+d_strtod='define'
+d_strtol='define'
+d_strtold='define'
+d_strtoll='define'
+d_strtoq='define'
+d_strtoul='define'
+d_strtoull='define'
+d_strtouq='define'
+d_strxfrm='define'
+d_suidsafe='undef'
+d_symlink='define'
+d_syscall='define'
+d_syscallproto='define'
+d_sysconf='define'
+d_sysernlst=''
+d_syserrlst='define'
+d_system='define'
+d_tcgetpgrp='define'
+d_tcsetpgrp='define'
+d_telldir='define'
+d_telldirproto='define'
+d_time='define'
+d_times='define'
+d_tm_tm_gmtoff='define'
+d_tm_tm_zone='define'
+d_tmpnam_r='undef'
+d_truncate='define'
+d_ttyname_r='undef'
+d_tzname='define'
+d_u32align='undef'
+d_ualarm='define'
+d_umask='define'
+d_uname='define'
+d_union_semun='undef'
+d_unordered='undef'
+d_usleep='define'
+d_usleepproto='define'
+d_ustat='define'
+d_vendorarch='undef'
+d_vendorbin='undef'
+d_vendorlib='undef'
+d_vendorscript='undef'
+d_vfork='undef'
+d_void_closedir='undef'
+d_voidsig='define'
+d_voidtty=''
+d_volatile='define'
+d_vprintf='define'
+d_wait4='define'
+d_waitpid='define'
+d_wcstombs='define'
+d_wctomb='define'
+d_writev='define'
+d_xenix='undef'
+date='date'
+db_hashtype='u_int32_t'
+db_prefixtype='size_t'
+db_version_major=''
+db_version_minor=''
+db_version_patch=''
+defvoidused='15'
+direntrytype='struct dirent'
+dlext='so'
+dlsrc='dl_dlopen.xs'
+doublesize='8'
+drand01='drand48()'
+drand48_r_proto='0'
+dynamic_ext='attrs B ByteLoader Cwd Data/Dumper Devel/DProf Devel/Peek Devel/PPPort Digest/MD5 Encode Fcntl File/Glob Filter/Util/Call I18N/Langinfo IO IPC/SysV List/Util MIME/Base64 Opcode PerlIO/encoding PerlIO/scalar PerlIO/via POSIX re SDBM_File Socket Storable Sys/Hostname Sys/Syslog threads Time/HiRes Unicode/Normalize XS/APItest XS/Typemap threads/shared'
+eagain='EAGAIN'
+ebcdic='undef'
+echo='echo'
+egrep='egrep'
+emacs=''
+endgrent_r_proto='0'
+endhostent_r_proto='0'
+endnetent_r_proto='0'
+endprotoent_r_proto='0'
+endpwent_r_proto='0'
+endservent_r_proto='0'
+eunicefix=':'
+exe_ext=''
+expr='expr'
+extensions='attrs B ByteLoader Cwd Data/Dumper Devel/DProf Devel/Peek Devel/PPPort Digest/MD5 Encode Fcntl File/Glob Filter/Util/Call I18N/Langinfo IO IPC/SysV List/Util MIME/Base64 Opcode PerlIO/encoding PerlIO/scalar PerlIO/via POSIX re SDBM_File Socket Storable Sys/Hostname Sys/Syslog threads Time/HiRes Unicode/Normalize XS/APItest XS/Typemap threads/shared Errno'
+extras=''
+fflushNULL='define'
+fflushall='undef'
+find=''
+firstmakefile='makefile'
+flex=''
+fpossize='16'
+fpostype='fpos_t'
+freetype='void'
+from=':'
+full_ar='/usr/bin/ar'
+full_csh='csh'
+full_sed='/bin/sed'
+gccansipedantic=''
+gccosandvers=''
+gccversion='3.3.5 (Debian 1:3.3.5-6)'
+getgrent_r_proto='0'
+getgrgid_r_proto='0'
+getgrnam_r_proto='0'
+gethostbyaddr_r_proto='0'
+gethostbyname_r_proto='0'
+gethostent_r_proto='0'
+getlogin_r_proto='0'
+getnetbyaddr_r_proto='0'
+getnetbyname_r_proto='0'
+getnetent_r_proto='0'
+getprotobyname_r_proto='0'
+getprotobynumber_r_proto='0'
+getprotoent_r_proto='0'
+getpwent_r_proto='0'
+getpwnam_r_proto='0'
+getpwuid_r_proto='0'
+getservbyname_r_proto='0'
+getservbyport_r_proto='0'
+getservent_r_proto='0'
+getspnam_r_proto='0'
+gidformat='"lu"'
+gidsign='1'
+gidsize='4'
+gidtype='gid_t'
+glibpth='/usr/shlib /lib /usr/lib /usr/lib/386 /lib/386 /usr/ccs/lib /usr/ucblib /usr/local/lib '
+gmake='gmake'
+gmtime_r_proto='0'
+gnulibc_version='2.3.2'
+grep='grep'
+groupcat='cat /etc/group'
+groupstype='gid_t'
+gzip='gzip'
+h_fcntl='false'
+h_sysfile='true'
+hint='recommended'
+hostcat='cat /etc/hosts'
+html1dir=' '
+html1direxp=''
+html3dir=' '
+html3direxp=''
+i16size='2'
+i16type='short'
+i32size='4'
+i32type='long'
+i64size='8'
+i64type='long long'
+i8size='1'
+i8type='char'
+i_arpainet='define'
+i_bsdioctl=''
+i_crypt='define'
+i_db='undef'
+i_dbm='undef'
+i_dirent='define'
+i_dld='undef'
+i_dlfcn='define'
+i_fcntl='undef'
+i_float='define'
+i_fp='undef'
+i_fp_class='undef'
+i_gdbm='undef'
+i_grp='define'
+i_ieeefp='undef'
+i_inttypes='define'
+i_langinfo='define'
+i_libutil='undef'
+i_limits='define'
+i_locale='define'
+i_machcthr='undef'
+i_malloc='define'
+i_math='define'
+i_memory='undef'
+i_mntent='define'
+i_ndbm='undef'
+i_netdb='define'
+i_neterrno='undef'
+i_netinettcp='define'
+i_niin='define'
+i_poll='define'
+i_prot='undef'
+i_pthread='define'
+i_pwd='define'
+i_rpcsvcdbm='undef'
+i_sfio='undef'
+i_sgtty='undef'
+i_shadow='define'
+i_socks='undef'
+i_stdarg='define'
+i_stddef='define'
+i_stdlib='define'
+i_string='define'
+i_sunmath='undef'
+i_sysaccess='undef'
+i_sysdir='define'
+i_sysfile='define'
+i_sysfilio='undef'
+i_sysin='undef'
+i_sysioctl='define'
+i_syslog='define'
+i_sysmman='define'
+i_sysmode='undef'
+i_sysmount='define'
+i_sysndir='undef'
+i_sysparam='define'
+i_sysresrc='define'
+i_syssecrt='undef'
+i_sysselct='define'
+i_syssockio='undef'
+i_sysstat='define'
+i_sysstatfs='define'
+i_sysstatvfs='define'
+i_systime='define'
+i_systimek='undef'
+i_systimes='define'
+i_systypes='define'
+i_sysuio='define'
+i_sysun='define'
+i_sysutsname='define'
+i_sysvfs='define'
+i_syswait='define'
+i_termio='undef'
+i_termios='define'
+i_time='define'
+i_unistd='define'
+i_ustat='define'
+i_utime='define'
+i_values='define'
+i_varargs='undef'
+i_varhdr='stdarg.h'
+i_vfork='undef'
+ignore_versioned_solibs='y'
+inc_version_list=' '
+inc_version_list_init='0'
+incpath=''
+inews=''
+installarchlib='./install_me_here/usr/lib/perl5/5.8.4/i386-linux'
+installbin='./install_me_here/usr/bin'
+installhtml1dir=''
+installhtml3dir=''
+installman1dir='./install_me_here/usr/share/man/man1'
+installman3dir='./install_me_here/usr/share/man/man3'
+installprefix='./install_me_here/usr'
+installprefixexp='./install_me_here/usr'
+installprivlib='./install_me_here/usr/lib/perl5/5.8.4'
+installscript='./install_me_here/usr/bin'
+installsitearch='./install_me_here/usr/lib/perl5/site_perl/5.8.4/i386-linux'
+installsitebin='./install_me_here/usr/bin'
+installsitehtml1dir=''
+installsitehtml3dir=''
+installsitelib='./install_me_here/usr/lib/perl5/site_perl/5.8.4'
+installsiteman1dir='./install_me_here/usr/share/man/man1'
+installsiteman3dir='./install_me_here/usr/share/man/man3'
+installsitescript='./install_me_here/usr/bin'
+installstyle='./install_me_herelib/perl5'
+installusrbinperl='undef'
+installvendorarch=''
+installvendorbin=''
+installvendorhtml1dir=''
+installvendorhtml3dir=''
+installvendorlib=''
+installvendorman1dir=''
+installvendorman3dir=''
+installvendorscript=''
+intsize='4'
+issymlink='/usr/bin/test -h'
+ivdformat='"ld"'
+ivsize='4'
+ivtype='long'
+known_extensions='attrs B ByteLoader Cwd Data/Dumper DB_File Devel/DProf Devel/Peek Devel/PPPort Digest/MD5 Encode Fcntl File/Glob Filter/Util/Call GDBM_File I18N/Langinfo IO IPC/SysV List/Util MIME/Base64 NDBM_File ODBM_File Opcode PerlIO/encoding PerlIO/scalar PerlIO/via POSIX re SDBM_File Socket Storable Sys/Hostname Sys/Syslog Thread threads Time/HiRes Unicode/Normalize XS/APItest XS/Typemap threads/shared'
+ksh=''
+ld='cc'
+lddlflags='-shared -L/usr/local/lib'
+ldflags=' -L/usr/local/lib'
+ldflags_uselargefiles=''
+ldlibpthname='LD_LIBRARY_PATH'
+less='less'
+lib_ext='.a'
+libc='/lib/libc-2.3.2.so'
+libperl='libperl.so'
+libpth='/usr/local/lib /lib /usr/lib'
+libs='-ldl -lm -lc -lcrypt'
+libsdirs=' /usr/lib'
+libsfiles=' libdl.so libm.so libc.so libcrypt.so'
+libsfound=' /usr/lib/libdl.so /usr/lib/libm.so /usr/lib/libc.so /usr/lib/libcrypt.so'
+libspath=' /usr/local/lib /lib /usr/lib'
+libswanted='gdbm gdbm_compat db dl m c crypt'
+libswanted_uselargefiles=''
+line=''
+lint=''
+lkflags=''
+ln='ln'
+lns='/bin/ln -s'
+localtime_r_proto='0'
+locincpth='/usr/local/include /opt/local/include /usr/gnu/include /opt/gnu/include /usr/GNU/include /opt/GNU/include'
+loclibpth='/usr/local/lib /opt/local/lib /usr/gnu/lib /opt/gnu/lib /usr/GNU/lib /opt/GNU/lib'
+longdblsize='12'
+longlongsize='8'
+longsize='4'
+lp=''
+lpr=''
+ls='ls'
+lseeksize='8'
+lseektype='off_t'
+mail=''
+mailx=''
+make='make'
+make_set_make='#'
+mallocobj=''
+mallocsrc=''
+malloctype='void *'
+man1dir='/usr/share/man/man1'
+man1direxp='/usr/share/man/man1'
+man1ext='1'
+man3dir='/usr/share/man/man3'
+man3direxp='/usr/share/man/man3'
+man3ext='3'
+mips_type=''
+mistrustnm=''
+mkdir='mkdir'
+mmaptype='void *'
+modetype='mode_t'
+more='more'
+multiarch='undef'
+mv=''
+myarchname='i386-linux'
+mydomain='.kergoth.com'
+myhostname='hyperion'
+myuname='linux hyperion 2.6.11-ck1 #1 wed mar 2 23:48:21 cst 2005 i386 gnulinux '
+n='-n'
+need_va_copy='undef'
+netdb_hlen_type='size_t'
+netdb_host_type='const void *'
+netdb_name_type='const char *'
+netdb_net_type='in_addr_t'
+nm='nm'
+nm_opt=''
+nm_so_opt='--dynamic'
+nonxs_ext='Errno'
+nroff='nroff'
+nvEUformat='"E"'
+nvFUformat='"F"'
+nvGUformat='"G"'
+nv_preserves_uv_bits='32'
+nveformat='"e"'
+nvfformat='"f"'
+nvgformat='"g"'
+nvsize='8'
+nvtype='double'
+o_nonblock='O_NONBLOCK'
+obj_ext='.o'
+old_pthread_create_joinable=''
+optimize='-O2'
+orderlib='false'
+osname='linux'
+osvers='2.6.11-ck1'
+otherlibdirs=' '
+package='perl5'
+pager='/usr/bin/less'
+passcat='cat /etc/passwd'
+patchlevel='8'
+path_sep=':'
+perl5='hostperl'
+perl=''
+perl_patchlevel=''
+perladmin=''
+perllibs='-ldl -lm -lc -lcrypt'
+perlpath='hostperl'
+pg='pg'
+phostname='hostname'
+pidtype='pid_t'
+plibpth=''
+pmake=''
+pr=''
+prefix='/usr'
+prefixexp='/usr'
+privlib='/usr/lib/perl5/5.8.4'
+privlibexp='/usr/lib/perl5/5.8.4'
+procselfexe='"/proc/self/exe"'
+prototype='define'
+ptrsize='4'
+quadkind='3'
+quadtype='long long'
+randbits='48'
+randfunc='drand48'
+random_r_proto='0'
+randseedtype='long'
+ranlib=':'
+rd_nodata='-1'
+readdir64_r_proto='0'
+readdir_r_proto='0'
+revision='5'
+rm='rm'
+rmail=''
+run=''
+runnm='false'
+sPRIEUldbl='"LE"'
+sPRIFUldbl='"LF"'
+sPRIGUldbl='"LG"'
+sPRIXU64='"LX"'
+sPRId64='"Ld"'
+sPRIeldbl='"Le"'
+sPRIfldbl='"Lf"'
+sPRIgldbl='"Lg"'
+sPRIi64='"Li"'
+sPRIo64='"Lo"'
+sPRIu64='"Lu"'
+sPRIx64='"Lx"'
+sSCNfldbl='"Lf"'
+sched_yield='sched_yield()'
+scriptdir='/usr/bin'
+scriptdirexp='/usr/bin'
+sed='sed'
+seedfunc='srand48'
+selectminbits='32'
+selecttype='fd_set *'
+sendmail=''
+setgrent_r_proto='0'
+sethostent_r_proto='0'
+setlocale_r_proto='0'
+setnetent_r_proto='0'
+setprotoent_r_proto='0'
+setpwent_r_proto='0'
+setservent_r_proto='0'
+sh='/bin/sh'
+shar=''
+sharpbang='#!'
+shmattype='void *'
+shortsize='2'
+shrpenv=''
+shsharp='true'
+sig_count='65'
+sig_name='ZERO HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS NUM32 RTMIN NUM34 NUM35 NUM36 NUM37 NUM38 NUM39 NUM40 NUM41 NUM42 NUM43 NUM44 NUM45 NUM46 NUM47 NUM48 NUM49 NUM50 NUM51 NUM52 NUM53 NUM54 NUM55 NUM56 NUM57 NUM58 NUM59 NUM60 NUM61 NUM62 NUM63 RTMAX IOT CLD POLL UNUSED '
+sig_name_init='"ZERO", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS", "FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "URG", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "IO", "PWR", "SYS", "NUM32", "RTMIN", "NUM34", "NUM35", "NUM36", "NUM37", "NUM38", "NUM39", "NUM40", "NUM41", "NUM42", "NUM43", "NUM44", "NUM45", "NUM46", "NUM47", "NUM48", "NUM49", "NUM50", "NUM51", "NUM52", "NUM53", "NUM54", "NUM55", "NUM56", "NUM57", "NUM58", "NUM59", "NUM60", "NUM61", "NUM62", "NUM63", "RTMAX", "IOT", "CLD", "POLL", "UNUSED", 0'
+sig_num='0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 6 17 29 31 '
+sig_num_init='0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 6, 17, 29, 31, 0'
+sig_size='69'
+signal_t='void'
+sitearch='/usr/lib/perl5/site_perl/5.8.4/i386-linux'
+sitearchexp='/usr/lib/perl5/site_perl/5.8.4/i386-linux'
+sitebin='/usr/bin'
+sitebinexp='/usr/bin'
+sitehtml1dir=''
+sitehtml1direxp=''
+sitehtml3dir=''
+sitehtml3direxp=''
+sitelib='/usr/lib/perl5/site_perl/5.8.4'
+sitelib_stem='/usr/lib/perl5/site_perl'
+sitelibexp='/usr/lib/perl5/site_perl/5.8.4'
+siteman1dir='/usr/share/man/man1'
+siteman1direxp='/usr/share/man/man1'
+siteman3dir='/usr/share/man/man3'
+siteman3direxp='/usr/share/man/man3'
+siteprefix='/usr'
+siteprefixexp='/usr'
+sitescript='/usr/bin'
+sitescriptexp='/usr/bin'
+sizesize='4'
+sizetype='size_t'
+sleep=''
+smail=''
+so='so'
+sockethdr=''
+socketlib=''
+socksizetype='socklen_t'
+sort='sort'
+spackage='Perl5'
+spitshell='cat'
+srand48_r_proto='0'
+srandom_r_proto='0'
+src='.'
+ssizetype='ssize_t'
+startperl='#!/usr/bin/perl'
+startsh='#!/bin/sh'
+static_ext=' '
+stdchar='char'
+stdio_base='((fp)->_IO_read_base)'
+stdio_bufsiz='((fp)->_IO_read_end - (fp)->_IO_read_base)'
+stdio_cnt='((fp)->_IO_read_end - (fp)->_IO_read_ptr)'
+stdio_filbuf=''
+stdio_ptr='((fp)->_IO_read_ptr)'
+stdio_stream_array=''
+strerror_r_proto='0'
+strings='/usr/include/string.h'
+submit=''
+subversion='4'
+sysman='/usr/share/man/man1'
+tail=''
+tar=''
+targetarch=''
+tbl=''
+tee=''
+test='test'
+timeincl='/usr/include/sys/time.h /usr/include/time.h '
+timetype='time_t'
+tmpnam_r_proto='0'
+to=':'
+touch='touch'
+tr='tr'
+trnl='\n'
+troff=''
+ttyname_r_proto='0'
+u16size='2'
+u16type='unsigned short'
+u32size='4'
+u32type='unsigned long'
+u64size='8'
+u64type='unsigned long long'
+u8size='1'
+u8type='unsigned char'
+uidformat='"lu"'
+uidsign='1'
+uidsize='4'
+uidtype='uid_t'
+uname='uname'
+uniq='uniq'
+uquadtype='unsigned long long'
+use5005threads='undef'
+use64bitall='undef'
+use64bitint='undef'
+usecrosscompile='undef'
+usedl='define'
+usefaststdio='define'
+useithreads='undef'
+uselargefiles='define'
+uselongdouble='undef'
+usemallocwrap='define'
+usemorebits='undef'
+usemultiplicity='undef'
+usemymalloc='n'
+usenm='false'
+useopcode='true'
+useperlio='define'
+useposix='true'
+usereentrant='undef'
+usesfio='false'
+useshrplib='true'
+usesitecustomize='undef'
+usesocks='undef'
+usethreads='undef'
+usevendorprefix='undef'
+usevfork='false'
+usrinc='/usr/include'
+uuname=''
+uvXUformat='"lX"'
+uvoformat='"lo"'
+uvsize='4'
+uvtype='unsigned long'
+uvuformat='"lu"'
+uvxformat='"lx"'
+vendorarch=''
+vendorarchexp=''
+vendorbin=''
+vendorbinexp=''
+vendorhtml1dir=' '
+vendorhtml1direxp=''
+vendorhtml3dir=' '
+vendorhtml3direxp=''
+vendorlib=''
+vendorlib_stem=''
+vendorlibexp=''
+vendorman1dir=' '
+vendorman1direxp=''
+vendorman3dir=' '
+vendorman3direxp=''
+vendorprefix=''
+vendorprefixexp=''
+vendorscript=''
+vendorscriptexp=''
+version='5.8.4'
+version_patchlevel_string='version 8 subversion 4'
+versiononly='undef'
+vi=''
+voidflags='15'
+xlibpth='/usr/lib/386 /lib/386'
+yacc='yacc'
+yaccflags=''
+zcat=''
+zip='zip'
+# Configure command line arguments.
+config_arg0='./Configure'
+config_args=''
+config_argc=0
+PERL_REVISION=5
+PERL_VERSION=8
+PERL_SUBVERSION=4
+PERL_API_REVISION=5
+PERL_API_VERSION=8
+PERL_API_SUBVERSION=0
+PERL_PATCHLEVEL=
+PERL_CONFIG_SH=true
diff --git a/packages/perl/perl_5.8.7.bb b/packages/perl/perl_5.8.7.bb
index babeea3e9a..3500ca57bd 100644
--- a/packages/perl/perl_5.8.7.bb
+++ b/packages/perl/perl_5.8.7.bb
@@ -2,9 +2,10 @@ MAINTAINER="David Karlstrom <daka@thg.se>"
include perl.inc
-SRC_URI += "file://config.sh-armeb-linux"
+SRC_URI += "file://config.sh-armeb-linux \
+ file://config.sh-i386-linux"
-PR = "r9"
+PR = "r10"
do_configure() {
ln -sf ${HOSTPERL} ${STAGING_BINDIR}/hostperl
@@ -14,6 +15,7 @@ do_configure() {
cp ${WORKDIR}/Makefile.SH.patch .
cp ${WORKDIR}/config.sh-mipsel-linux .
cp ${WORKDIR}/config.sh-i686-linux .
+ cp ${WORKDIR}/config.sh-i386-linux .
cp ${WORKDIR}/config.sh-armeb-linux .
for i in config.sh-*-linux; do
a="`echo $i|sed -e 's,^config.sh-,,; s,-linux$,,'`"
diff --git a/packages/pine/pine-4.63/.mtn2git_empty b/packages/pine/pine-4.63/.mtn2git_empty
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/packages/pine/pine-4.63/.mtn2git_empty
diff --git a/packages/pine/pine-4.63/imap-2000-time.patch b/packages/pine/pine-4.63/imap-2000-time.patch
new file mode 100644
index 0000000000..751d1ff506
--- /dev/null
+++ b/packages/pine/pine-4.63/imap-2000-time.patch
@@ -0,0 +1,56 @@
+--- pine4.33/imap/src/osdep/unix/os_lnx.c.time Wed Feb 14 12:25:06 2001
++++ pine4.33/imap/src/osdep/unix/os_lnx.c Wed Feb 14 12:25:16 2001
+@@ -23,6 +23,7 @@
+ #include "osdep.h"
+ #include <stdio.h>
+ #include <sys/time.h>
++#include <time.h>
+ #include <sys/stat.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+--- pine4.33/imap/src/osdep/unix/news.c.time Thu Jan 18 21:28:33 2001
++++ pine4.33/imap/src/osdep/unix/news.c Wed Feb 14 12:24:34 2001
+@@ -21,7 +21,7 @@
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <errno.h>
+-extern int errno; /* just in case */
++#include <time.h>
+ #include "mail.h"
+ #include "osdep.h"
+ #include <sys/stat.h>
+--- pine4.33/imap/src/osdep/unix/phile.c.time Thu Jan 18 21:31:20 2001
++++ pine4.33/imap/src/osdep/unix/phile.c Wed Feb 14 12:24:34 2001
+@@ -21,8 +21,8 @@
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <errno.h>
+-extern int errno; /* just in case */
+ #include <signal.h>
++#include <time.h>
+ #include "mail.h"
+ #include "osdep.h"
+ #include <pwd.h>
+--- pine4.33/imap/src/osdep/unix/mh.c.time Thu Jan 18 21:27:37 2001
++++ pine4.33/imap/src/osdep/unix/mh.c Wed Feb 14 12:24:34 2001
+@@ -21,7 +21,8 @@
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <errno.h>
+-extern int errno; /* just in case */
++#include <time.h>
++
+ #include "mail.h"
+ #include "osdep.h"
+ #include <pwd.h>
+--- pine4.33/imap/src/osdep/unix/mx.c.time Thu Jan 18 21:28:09 2001
++++ pine4.33/imap/src/osdep/unix/mx.c Wed Feb 14 12:24:34 2001
+@@ -21,7 +21,7 @@
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <errno.h>
+-extern int errno; /* just in case */
++#include <time.h>
+ #include "mail.h"
+ #include "osdep.h"
+ #include <pwd.h>
diff --git a/packages/pine/pine-4.63/pine-4.30-ldap.patch b/packages/pine/pine-4.63/pine-4.30-ldap.patch
new file mode 100644
index 0000000000..6b920ade51
--- /dev/null
+++ b/packages/pine/pine-4.63/pine-4.30-ldap.patch
@@ -0,0 +1,11 @@
+--- pine4.30/build.ldap Fri Oct 27 12:48:05 2000
++++ pine4.30/build Fri Oct 27 12:49:00 2000
+@@ -249,7 +249,7 @@
+ case "$?" in
+ 1) if [ "$LLIBS" != "1" ]
+ then
+- L1="'LDAPLIBS=../ldap/libraries/libldap.a ../ldap/libraries/liblber.a'"
++ L1="'LDAPLIBS=../ldap/libraries/libldap.so ../ldap/libraries/liblber.so ../ldap/libraries/libresolv.so'"
+ fi
+ if [ "$LFLAGS" != "1" ]
+ then
diff --git a/packages/pine/pine-4.63/pine-4.31-segfix.patch b/packages/pine/pine-4.63/pine-4.31-segfix.patch
new file mode 100644
index 0000000000..f65aa60294
--- /dev/null
+++ b/packages/pine/pine-4.63/pine-4.31-segfix.patch
@@ -0,0 +1,17 @@
+diff -urN pine4.31.orig/pine/osdep/lstcmpnt pine4.31/pine/osdep/lstcmpnt
+--- pine4.31.orig/pine/osdep/lstcmpnt Mon Oct 30 17:45:08 2000
++++ pine4.31/pine/osdep/lstcmpnt Tue Dec 12 06:33:53 2000
+@@ -9,10 +9,10 @@
+ last_cmpnt(filename)
+ char *filename;
+ {
+- register char *p = NULL, *q = filename;
++ char *p = NULL, *q = filename;
+
+- if(!q)
+- return(q);
++ if(filename == 0)
++ return 0;
+
+ while(q = strchr(q, '/'))
+ if(*++q)
diff --git a/packages/pine/pine-4.63/pine-4.40-lockfile-perm.patch b/packages/pine/pine-4.63/pine-4.40-lockfile-perm.patch
new file mode 100644
index 0000000000..f2cb434de2
--- /dev/null
+++ b/packages/pine/pine-4.63/pine-4.40-lockfile-perm.patch
@@ -0,0 +1,22 @@
+--- pine4.40/imap/src/osdep/unix/env_unix.h.lock_protection_fix Thu Oct 4 05:26:33 2001
++++ pine4.40/imap/src/osdep/unix/env_unix.h Thu Oct 4 05:30:33 2001
+@@ -46,12 +46,15 @@
+
+
+ /*
+- * Attention: all sorcerer's apprentices who think that 0666 is a mistake.
+- * You are wrong. Read the FAQ. Do not meddle in the affairs of wizards,
+- * for they are subtle and quick to anger.
++ * Attention: all people who do not care about OS security, and think that
++ * mode 0666 is a correct. You are wrong. In modern multiuser systems,
++ * both remote and local security is critically important. Allowing 0666
++ * lockfiles, allows all sorts of security problems to occur. Feel free to
++ * meddle with it however, if you do not care about local security.
+ */
+
+-#define MANDATORYLOCKPROT 0666 /* don't change this */
++/* Change this only if you do not want a secure multiuser system */
++#define MANDATORYLOCKPROT 0600
+
+ /* Function prototypes */
+
diff --git a/packages/pine/pine-4.63/pine-4.56-passfile.patch b/packages/pine/pine-4.63/pine-4.56-passfile.patch
new file mode 100644
index 0000000000..bb9813f7c6
--- /dev/null
+++ b/packages/pine/pine-4.63/pine-4.56-passfile.patch
@@ -0,0 +1,12 @@
+--- pine4.56/pine/osdep/os-lnx.h.orig 2003-07-23 07:23:26.000000000 -0700
++++ pine4.56/pine/osdep/os-lnx.h 2003-07-23 07:23:30.000000000 -0700
+@@ -295,5 +295,9 @@
+ #define MAX_ADDR_EXPN (1000) /* Longest expanded addr */
+ #define MAX_ADDR_FIELD (10000) /* Longest fully-expanded addr field */
+
++/*----------------------------------------------------------------------
++ Allow for caching of passwords between connections.
++ ----*/
++#define PASSFILE ".pinepw"
+
+ #endif /* _OS_INCLUDED */
diff --git a/packages/pine/pine-4.63/pine-4.61-largeterminal.patch b/packages/pine/pine-4.63/pine-4.61-largeterminal.patch
new file mode 100644
index 0000000000..c046546dba
--- /dev/null
+++ b/packages/pine/pine-4.63/pine-4.61-largeterminal.patch
@@ -0,0 +1,14 @@
+diff -Nur pine4.61.orig/pine/osdep/os-lnx.h pine4.61/pine/osdep/os-lnx.h
+--- pine4.61.orig/pine/osdep/os-lnx.h 2004-12-18 00:33:46.162401405 +0100
++++ pine4.61/pine/osdep/os-lnx.h 2004-12-18 00:34:14.473012057 +0100
+@@ -247,8 +247,8 @@
+
+
+ /*-- Max screen pine will display on. Used to define some array sizes --*/
+-#define MAX_SCREEN_COLS (170)
+-#define MAX_SCREEN_ROWS (200)
++#define MAX_SCREEN_COLS (340)
++#define MAX_SCREEN_ROWS (400)
+
+
+ /*----------------------------------------------------------------------
diff --git a/packages/pine/pine-4.63/pine-4.61-subjectlength.patch b/packages/pine/pine-4.63/pine-4.61-subjectlength.patch
new file mode 100644
index 0000000000..b7a9cdf7b7
--- /dev/null
+++ b/packages/pine/pine-4.63/pine-4.61-subjectlength.patch
@@ -0,0 +1,59 @@
+--- pine4.61/pine/strings.c_orig 2004-03-12 10:48:17.783992528 +0100
++++ pine4.61/pine/strings.c 2004-03-12 11:01:37.929351944 +0100
+@@ -2912,7 +2912,7 @@ int rfc1522_token PROTO((char *,
+ char **));
+ int rfc1522_valtok PROTO((int));
+ int rfc1522_valenc PROTO((int));
+-int rfc1522_valid PROTO((char *, char **, char **, char **,
++int rfc1522_valid PROTO((char *, int, char **, char **, char **,
+ char **));
+ char *rfc1522_8bit PROTO((void *, int));
+ char *rfc1522_binary PROTO((void *, int));
+@@ -2949,7 +2949,7 @@ rfc1522_decode(d, len, s, charset)
+
+ while(s && (sw = strstr(s, RFC1522_INIT))){
+ /* validate the rest of the encoded-word */
+- if(rfc1522_valid(sw, &cset, &enc, &txt, &ew)){
++ if(rfc1522_valid(sw, 1, &cset, &enc, &txt, &ew)){
+ if(!rv)
+ rv = d; /* remember start of dest */
+
+@@ -3222,10 +3222,15 @@ rfc1522_valenc(c)
+
+ /*
+ * rfc1522_valid - validate the given string as to it's rfc1522-ness
++ * if relaxchk is true, double the maximum length of an encoded word.
++ * this is necessary to decode overlong encoded words generated by
++ * numerous incompliant implementations of RFC 2047 (1522).
++
+ */
+ int
+-rfc1522_valid(s, charset, enc, txt, endp)
++rfc1522_valid(s, relaxchk, charset, enc, txt, endp)
+ char *s;
++ int relaxchk;
+ char **charset;
+ char **enc;
+ char **txt;
+@@ -3237,7 +3242,11 @@ rfc1522_valid(s, charset, enc, txt, endp
+ rv = rfc1522_token(c = s+RFC1522_INIT_L, rfc1522_valtok, RFC1522_DLIM, &e)
+ && rfc1522_token(++e, rfc1522_valtok, RFC1522_DLIM, &t)
+ && rfc1522_token(++t, rfc1522_valenc, RFC1522_TERM, &p)
+- && p - s <= RFC1522_MAXW;
++ && p - s <= RFC1522_MAXW * (relaxchk ? 2 : 1);
++ /*
++ * relax the length condition by doubling the max length of an
++ * encoded word. It's is needed for some longer encoded words.
++ */
+
+ if(charset)
+ *charset = c;
+@@ -3288,7 +3297,7 @@ rfc1522_encode(d, len, s, charset)
+ }
+ else if(*p == RFC1522_INIT[0]
+ && !strncmp((char *) p, RFC1522_INIT, RFC1522_INIT_L)){
+- if(rfc1522_valid((char *) p, NULL, NULL, NULL, (char **) &q))
++ if(rfc1522_valid((char *) p, 0, NULL, NULL, NULL, (char **) &q))
+ p = q + RFC1522_TERM_L - 1; /* advance past encoded gunk */
+ }
+ else if(*p == ESCAPE && match_escapes((char *)(p+1))){
diff --git a/packages/pine/pine-4.63/pine-4.62-spooldir-permissions.patch b/packages/pine/pine-4.63/pine-4.62-spooldir-permissions.patch
new file mode 100644
index 0000000000..eb8c2f3eee
--- /dev/null
+++ b/packages/pine/pine-4.63/pine-4.62-spooldir-permissions.patch
@@ -0,0 +1,12 @@
+diff -bur pine4.62/imap/src/osdep/unix/env_unix.c pine4.62-gentoo/imap/src/osdep/unix/env_unix.c
+--- pine4.62/imap/src/osdep/unix/env_unix.c 2004-09-13 23:32:11.000000000 +0200
++++ pine4.62-gentoo/imap/src/osdep/unix/env_unix.c 2005-03-24 23:38:13.000000000 +0100
+@@ -106,7 +106,7 @@
+ * on the mail spool, or install mlock.
+ */
+ /* disable warning if can't make .lock file */
+-static short disableLockWarning = NIL;
++static short disableLockWarning = 1;
+
+ /* UNIX namespaces */
+
diff --git a/packages/pine/pine-4.63/pine-4.63-r2-chappa-all.patch b/packages/pine/pine-4.63/pine-4.63-r2-chappa-all.patch
new file mode 100644
index 0000000000..313d4544ef
--- /dev/null
+++ b/packages/pine/pine-4.63/pine-4.63-r2-chappa-all.patch
@@ -0,0 +1,21900 @@
+diff -rc pine4.63/README.maildir pine4.63.I.USE/README.maildir
+*** pine4.63/README.maildir Thu May 19 19:59:15 2005
+--- pine4.63.I.USE/README.maildir Thu May 19 19:57:24 2005
+***************
+*** 0 ****
+--- 1,244 ----
++ -------------------------------------------------------------------------------
++
++ Maildir Driver for Pine4.63
++ By Eduardo Chappa <chappa@math.washington.edu>
++ http://www.math.washington.edu/~chappa/pine/
++
++ -------------------------------------------------------------------------------
++ 1. General Information About This Patch
++ ---------------------------------------
++
++ This patch adds support for the maildir format to Pine. We take the
++ approach that this patch is one more driver among the number of formats
++ supported by Pine (more generally c-client). This approach differs from
++ older versions of similar patches, in that once a maildir patch was
++ applied, it was assumed that all your folders would be created in the
++ maildir format.
++
++ This patch does not assume that maildir is a preferred format, instead
++ puts maildir in equal footing with other formats (mbox, mbx, etc), and so
++ a maildir folder in the mail/ collection is treated in the same way as any
++ other folder in any other format. In another words, just by reading the
++ name of a folder, or opening it, or doing any operation with it, you can
++ not know in which format the folder is.
++
++ This implies that if you want to add a folder in the maildir format to the
++ mail/ collection, then you must add by pressing "A" in the folder list
++ collection and enter "#driver.md/mail/name_maildir_folder".
++
++ If you only want to use maildir, however, you can do so too. In this case,
++ you must create a maildir collection. In that collection, only maildir
++ folders will be listed. If there is any folder in any other format, that
++ folder will be ignored. In another words, any folder listed there is in
++ maildir format and can be accessed through that collection, conversely,
++ any folder not listed there is not in maildir format and there is no way
++ to access it using this collection.
++
++ In order to create a maildir collection, you could press M S L, and "A" to
++ add a collection. Fill in the required fields as follows:
++
++ Nickname : Anything
++ Server :
++ Path : #md/relative/path/to/maildir/collection/
++ View :
++
++ For example, if "path" is set to "#md/mail/", then Pine will look for your
++ maildir folders that are in ~/mail/.
++
++ The code in this patch is mostly based in code for the unix driver plus
++ some combinations of the mh, mbx and nntp drivers for the c-client
++ library. Those drivers were designed by Mark Crispin, and bugs in this
++ code are not his bugs, but my own.
++
++ I got all the specification for this patch from
++ http://cr.yp.to/proto/maildir.html. If you know of a place with a better
++ specification for maildir format please let me know. The method this patch
++ uses to create a unique filename for a message is one of the "old
++ fashioned" methods. I realize that this is old fashioned, but it is
++ portable, and portability is the main reason why I decided to use an old
++ fashioned method (most methods are not portable. See the word
++ "Unfortunately" in that document).
++
++ --------------
++ 2. Other Goals
++ --------------
++
++ It is intended that this code will work well with any application
++ written using the c-client library. Of paramount importance is to make the
++ associated imap server work well when the server accesses a folder in
++ Maildir format. The program mailutil should also work flawlessly with this
++ implemetation of the driver.
++
++ It is intended that this driver be fast and stable. We intend not to
++ patch Pine to make this driver do its work, unless such patching is for
++ fixing bugs in Pine or to pass parameters to the driver.
++
++ ----------------------------------------
++ 3. One sided comparison to other patches
++ ----------------------------------------
++
++ There are two other maildir patches that could be easily adapted for
++ version 4.63.
++
++ The first one is the patch distributed by SuSe which can be downloaded
++ from http://hico.fphil.uniba.sk/pine-patches.html. This patch was last
++ updated for version 4.58. Several hunks fail to be applied when you try to
++ apply it to Pine 4.63. Even if you apply those hunks manually there will
++ still be the following bugs:
++
++ * You can not save between any two storage systems. The old patch did
++ not do this well, because it had to modify the mailcmd.c file in order
++ to save messages to a unix style mailbox, and this is undesirable,
++ because the mailutil application associated to this patch would fail
++ to save messages.
++ * It corrupts messages when it saves them to a mbx format folder.
++ * It could not save messages to the INBOX folder.
++ * It crashes when two different clients are accessing the same mailbox:
++ For example, if a message is marked deleted in one session, then it
++ should be marked deleted in any other session too, but instead it
++ crashes the second session.
++ * Pine crashes when saving several messages to a maildir (not even the
++ prototype of the function is correctly defined).
++ * Pine crashes when checking for the STATUS of a maildir mailbox.
++ * Pine could not delete a maildir folder.
++ * Pine could not rename a maildir folder.
++
++ The other patch is available from Glue Logic (GL), was last updated for
++ version 4.61 and fails to apply a hunk in version 4.63, which must be
++ manually applied. There are, however, several problems and bugs. The patch
++ can be found at http://www.gluelogic.com/code/PINE-maildir/
++
++ * [Bug] It changes the default sort by arrival into sort by Date in
++ every folder. This makes Pine sort incorrectly any folder (no matter
++ in which format such folder is).
++
++ * [Missing Important Feature] Lacks support for dual folder use. You can
++ not create a directory with the same name than a given folder and use
++ it!
++
++ * [Bug] It confuses Unseen and Recent messages. Unseen messages are
++ reported as Recent. An Unseen message is a message that had not been
++ read the last time the folder was closed (or had been read but marked
++ Unseen in an earlier session). A Recent message is one which was not
++ in the folder the last time it was closed. Recent messages are your
++ real new messages, but Unseen are not. In GL patch, every Unseen
++ message is treated as Recent!.
++
++ * [Problem] Large folders take long time to be opened for the first
++ time.
++
++ * [Bug] Reported sizes are the number of bytes in the message and not
++ the "on the wire" size. If you were to manually edit a message and
++ either add or remove information from it, the size reported by Pine
++ would not be affected by this change.
++
++ * [Bug] Crashes when two sessions access the same mailbox and one
++ deletes and expunges a message while the other tries to read that
++ message. (explicitly, if session A uses the GL patch, and session B
++ uses my patch, then the following procedure crashes session A:
++
++ - In session B delete and expunge a message.
++ - Open that message in session A. Session A will notice it is gone
++ and will not crash.
++ - In session A delete and expunge a message.
++ - Open that message in session B. Session B will print a message
++ about no such message, then it will go back to the index screen
++ telling you that the message your were viewing was gone.
++ - Now in session B delete and expunge a message.
++ - Open that message in session A, Pine will crash).
++
++ * [Bug] The patch changes the name of a message-file by adding a place
++ for the size in the name of the message-file. By doing so it breaks
++ the maildir specification which only allows you to change the name by
++ changing flags. If there is another client reading that mailbox, there
++ is a chance that the other client will fail finding messages due to
++ changes made by the GL patch.
++
++ * [Bug] Any patch for Maildir support is NOT a patch for Pine (despite
++ the fact that you have read many times that the patch is for Pine),
++ but a patch for the C-Client library. As such it should work well with
++ any application that can be built with such library, like the UW-IMAP
++ server. The GL patch has a self proclaimed message stating not to use
++ the associated IMAP server to read Maildirs. This restriction does not
++ apply to my patch. I encourage you to use the server built with my
++ patch to access Maildirs.
++
++ ------------------------------------------------------------------------
++ 4. What are the known bugs of this implementation of the Maildir driver?
++ ------------------------------------------------------------------------
++
++ I don't know any at this time. There have been bugs before, though, but
++ I try to fix bugs as soon as they are reported. All bugs of the other
++ patches have been reported but not fixed, either because there was no one
++ maintaining the patch, or the maintainer has not fixed them yet (all these
++ reports were made as late as November 2004). A very complete list of
++ updates for this patch, which includes bug fixes, improvements and
++ addition of new features can be found at
++
++ http://www.math.washington.edu/~chappa/pine/updates/maildir.html
++
++ ----------
++ 5. On UIDs
++ ----------
++
++ This patch does not keep UIDs between sessions, but hopefully it does
++ keep consistent UIDs during one session. This is not a bug of the driver,
++ instead it is a shortcoming of the maildir specification. The main point
++ of the maildir configuration is that you should never (read my lips) ever
++ edit the message, but edit the filename associated to the message. Well, I
++ could not find any single place in the web where it was told how to save
++ the UID of a message, if there is one please let me know and I will add
++ UID support for this driver.
++
++ --------------------------------------------
++ 6. Configuring Pine and Setting up a Maildir
++ --------------------------------------------
++
++ Once this approach was chosen, it implied the following:
++
++ * This patch assumes that your INBOX is located at "$HOME/Maildir".
++ This is a directory which should have three subdirectories "cur",
++ "tmp" and "new". Mail is delivered to 'new' and read from 'cur'. I
++ have added a configuration option "maildir-location" which can be
++ used to tell Pine where your Maildir inbox is, in case your system
++ do not use the above directory (e.g. your system may use
++ "~/.maildir"). In this case define that variable to be the name of
++ the directory where your e-mail is being delivered (e.g.
++ ".maildir").
++
++ * If you want to use the above configuration as your inbox, you must
++ define your inbox-path as "#md/inbox" (no quotes). You can define
++ the inbox-path like above even if you have changed the
++ maildir-location variable. That's the whole point of that variable.
++
++ -----------------------------------
++ 7. What about Courier file systems?
++ -----------------------------------
++
++ In a courier file system all folders are subfolders of a root folder
++ called INBOX. Normally INBOX is located at ~/Maildir and subfolders are
++ "dot" directories in ~/Maildir. For example ~/Maildir/.Trash is a
++ subfolder of INBOX and is accessed with the nickname "INBOX.Trash".
++
++ You can not access folders in this way unless you preceed them with the
++ string "#mc/". The purpose of the string "#mc/" is to warn Pine that a
++ collection in the Courier format is going to be accessed, so you can
++ SELECT a folder like "#mc/INBOX.Trash", but not "INBOX.Trash"
++
++ You can access a collection through a server, but if you want to access a
++ collection of folders created using the Courier server, you MUST edit your
++ ".pinerc" file and enter the definition of the collection as follows:
++
++ folder-collections="Anything you want" #mc/INBOX.[]
++
++ You can replace the string "#mc/INBOX." by something different, for example
++ "#mc/Courier/." will make Pine search for your collection in ~/Courier.
++
++ You can not add this directly into Pine because Pine fails to accept this
++ value from its input, but it takes it correctly when it is added through
++ the ".pinerc" file.
++
++ You can access your inbox as "#mc/INBOX" or "#md/INBOX". Both definitions
++ point to the same place.
++
++ Last Updated April 29, 2005
+diff -rc pine4.63/imap/src/c-client/imap4r1.c pine4.63.I.USE/imap/src/c-client/imap4r1.c
+*** pine4.63/imap/src/c-client/imap4r1.c Fri Apr 8 16:44:01 2005
+--- pine4.63.I.USE/imap/src/c-client/imap4r1.c Thu May 19 19:57:33 2005
+***************
+*** 4396,4401 ****
+--- 4396,4402 ----
+ if (*env) { /* need to merge this header into envelope? */
+ if (!(*env)->newsgroups) { /* need Newsgroups? */
+ (*env)->newsgroups = nenv->newsgroups;
++ (*env)->ngpathexists = nenv->ngpathexists;
+ nenv->newsgroups = NIL;
+ }
+ if (!(*env)->followup_to) { /* need Followup-To? */
+***************
+*** 4450,4455 ****
+--- 4451,4457 ----
+ if (oenv) { /* need to merge old envelope? */
+ (*env)->newsgroups = oenv->newsgroups;
+ oenv->newsgroups = NIL;
++ (*env)->ngpathexists = oenv->ngpathexists;
+ (*env)->followup_to = oenv->followup_to;
+ oenv->followup_to = NIL;
+ (*env)->references = oenv->references;
+diff -rc pine4.63/imap/src/c-client/mail.c pine4.63.I.USE/imap/src/c-client/mail.c
+*** pine4.63/imap/src/c-client/mail.c Wed Mar 16 16:12:17 2005
+--- pine4.63.I.USE/imap/src/c-client/mail.c Thu May 19 19:57:24 2005
+***************
+*** 977,982 ****
+--- 977,983 ----
+ (((*mailbox == '{') || (*mailbox == '#')) &&
+ (stream = mail_open (NIL,mailbox,OP_PROTOTYPE | OP_SILENT))))
+ d = stream->dtb;
++ else if (maildir_valid_name(mailbox)) return maildir_create(stream, mailbox);
+ else if ((*mailbox != '{') && (ts = default_proto (NIL))) d = ts->dtb;
+ else { /* failed utterly */
+ sprintf (tmp,"Can't create mailbox %.80s: indeterminate format",mailbox);
+diff -rc pine4.63/imap/src/c-client/mail.h pine4.63.I.USE/imap/src/c-client/mail.h
+*** pine4.63/imap/src/c-client/mail.h Tue Feb 8 15:44:54 2005
+--- pine4.63.I.USE/imap/src/c-client/mail.h Thu May 19 19:57:33 2005
+***************
+*** 149,154 ****
+--- 149,156 ----
+ #define SET_LOGOUTHOOK (long) 226
+ #define GET_LOGOUTDATA (long) 227
+ #define SET_LOGOUTDATA (long) 228
++ #define SET_PASSWORDFILE 229
++ #define GET_PASSWORDFILE 230
+
+ /* 3xx: TCP/IP */
+ #define GET_OPENTIMEOUT (long) 300
+***************
+*** 311,316 ****
+--- 313,320 ----
+ #define SET_SNARFPRESERVE (long) 567
+ #define GET_INBOXPATH (long) 568
+ #define SET_INBOXPATH (long) 569
++ #define GET_COURIERSTYLE (long) 570
++ #define SET_COURIERSTYLE (long) 571
+
+ /* Driver flags */
+
+***************
+*** 622,627 ****
+--- 626,632 ----
+ /* Message envelope */
+
+ typedef struct mail_envelope {
++ unsigned int ngpathexists : 1; /* newsgroups may be bogus */
+ unsigned int incomplete : 1; /* envelope may be incomplete */
+ unsigned int imapenvonly : 1; /* envelope only has IMAP envelope */
+ char *remail; /* remail header if any */
+***************
+*** 790,795 ****
+--- 795,801 ----
+ unsigned int spare7 : 1; /* seventh spare bit */
+ unsigned int spare8 : 1; /* eighth spare bit */
+ void *sparep; /* spare pointer */
++ void *maildirp; /* for the Maildir driver, can't use sparep */
+ unsigned long user_flags; /* user-assignable flags */
+ } MESSAGECACHE;
+
+diff -rc pine4.63/imap/src/c-client/rfc822.c pine4.63.I.USE/imap/src/c-client/rfc822.c
+*** pine4.63/imap/src/c-client/rfc822.c Tue Jan 18 12:41:09 2005
+--- pine4.63.I.USE/imap/src/c-client/rfc822.c Thu May 19 19:57:33 2005
+***************
+*** 354,359 ****
+--- 354,360 ----
+ ENVELOPE *env = (*en = mail_newenvelope ());
+ BODY *body = bdy ? (*bdy = mail_newbody ()) : NIL;
+ long MIMEp = -1; /* flag that MIME semantics are in effect */
++ long PathP = NIL; /* flag that a Path: was seen */
+ parseline_t pl = (parseline_t) mail_parameters (NIL,GET_PARSELINE,NIL);
+ if (!host) host = BADHOST; /* make sure that host is non-null */
+ while (i && *s != '\n') { /* until end of header */
+***************
+*** 443,448 ****
+--- 444,452 ----
+ *t++ = '\0';
+ }
+ break;
++ case 'P': /* possible Path: */
++ if (!strcmp (tmp+1,"ATH")) env->ngpathexists = T;
++ break;
+ case 'R': /* possible Reply-To: */
+ if (!strcmp (tmp+1,"EPLY-TO"))
+ rfc822_parse_adrlist (&env->reply_to,d,host);
+diff -rc pine4.63/imap/src/mailutil/mailutil.c pine4.63.I.USE/imap/src/mailutil/mailutil.c
+*** pine4.63/imap/src/mailutil/mailutil.c Tue Feb 8 15:50:49 2005
+--- pine4.63.I.USE/imap/src/mailutil/mailutil.c Thu May 19 19:57:33 2005
+***************
+*** 29,34 ****
+--- 29,35 ----
+
+ /* Globals */
+
++ int passfile = NIL; /* password file supplied ? */
+ int debugp = NIL; /* flag saying debug */
+ int verbosep = NIL; /* flag saying verbose */
+ int rwcopyp = NIL; /* flag saying readwrite copy (for POP) */
+***************
+*** 159,164 ****
+--- 160,166 ----
+ for (nargs = argc ? argc - 1 : 0,args = argv + 1; nargs; args++,nargs--) {
+ if (*(s = *args) == '-') { /* parse switches */
+ if (!strcmp (s,"-debug") || !strcmp (s,"-d")) debugp = T;
++ else if (!strcmp (s,"-passfile")) passfile = T;
+ else if (!strcmp (s,"-verbose") || !strcmp (s,"-v")) verbosep = T;
+ else if (!strcmp (s,"-rwcopy") || !strcmp (s,"-rw")) rwcopyp = T;
+ else if ((nargs > 1) && (!strcmp (s,"-merge") || !strcmp (s,"-m"))) {
+***************
+*** 179,184 ****
+--- 181,190 ----
+ exit (ret);
+ }
+ }
++ else if (passfile) {
++ env_parameters(SET_PASSWORDFILE, (void *)s);
++ passfile = NIL;
++ }
+ else if (!cmd) cmd = s; /* first non-switch is command */
+ else if (!src) src = s; /* second non-switch is source */
+ else if (!dst) dst = s; /* third non-switch is destination */
+***************
+*** 665,671 ****
+ username[NETMAXUSER-1] = '\0';
+ if (s = strchr (username,'\n')) *s = '\0';
+ }
+! strcpy (password,getpass ("password: "));
+ }
+
+
+--- 671,679 ----
+ username[NETMAXUSER-1] = '\0';
+ if (s = strchr (username,'\n')) *s = '\0';
+ }
+! mm_userpwd(mb, &username, &password);
+! if (!password || !*password)
+! strcpy (password,getpass ("password: "));
+ }
+
+
+diff -rc pine4.63/imap/src/osdep/unix/Makefile pine4.63.I.USE/imap/src/osdep/unix/Makefile
+*** pine4.63/imap/src/osdep/unix/Makefile Wed Apr 20 17:49:08 2005
+--- pine4.63.I.USE/imap/src/osdep/unix/Makefile Thu May 19 19:57:24 2005
+***************
+*** 119,125 ****
+ # Standard distribution build parameters
+
+ DEFAULTAUTHENTICATORS=md5 pla log
+! DEFAULTDRIVERS=imap nntp pop3 mh mx mbx tenex mtx mmdf unix news phile
+
+
+ # Normally no need to change any of these
+--- 119,125 ----
+ # Standard distribution build parameters
+
+ DEFAULTAUTHENTICATORS=md5 pla log
+! DEFAULTDRIVERS=maildir courier imap nntp pop3 mh mx mbx tenex mtx mmdf unix news phile
+
+
+ # Normally no need to change any of these
+***************
+*** 128,134 ****
+ BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o siglocal.o \
+ dummy.o pseudo.o netmsg.o flstring.o fdstring.o \
+ rfc822.o nntp.o smtp.o imap4r1.o pop3.o \
+! unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o
+ CFLAGS=-g
+
+ CAT=cat
+--- 128,134 ----
+ BINARIES=osdep.o mail.o misc.o newsrc.o smanager.o utf8.o siglocal.o \
+ dummy.o pseudo.o netmsg.o flstring.o fdstring.o \
+ rfc822.o nntp.o smtp.o imap4r1.o pop3.o \
+! unix.o mbx.o mmdf.o tenex.o mtx.o news.o phile.o mh.o mx.o maildir.o
+ CFLAGS=-g
+
+ CAT=cat
+***************
+*** 257,263 ****
+
+ cyg: # Cygwin - note that most local file drivers don't work!!
+ $(BUILD) `$(CAT) SPECIALS` OS=$@ \
+! DEFAULTDRIVERS="imap nntp pop3 mbx unix phile" \
+ SIGTYPE=psx CHECKPW=cyg LOGINPW=cyg CRXTYPE=std \
+ SPOOLDIR=/var \
+ ACTIVEFILE=/usr/local/news/lib/active \
+--- 257,263 ----
+
+ cyg: # Cygwin - note that most local file drivers don't work!!
+ $(BUILD) `$(CAT) SPECIALS` OS=$@ \
+! DEFAULTDRIVERS="imap nntp pop3 mbx unix maildir phile" \
+ SIGTYPE=psx CHECKPW=cyg LOGINPW=cyg CRXTYPE=std \
+ SPOOLDIR=/var \
+ ACTIVEFILE=/usr/local/news/lib/active \
+***************
+*** 846,852 ****
+ tenex.o: mail.h misc.h osdep.h dummy.h
+ unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h
+ utf8.o: mail.h misc.h osdep.h utf8.h
+!
+
+ # OS-dependent
+
+--- 846,852 ----
+ tenex.o: mail.h misc.h osdep.h dummy.h
+ unix.o: mail.h misc.h osdep.h unix.h pseudo.h dummy.h
+ utf8.o: mail.h misc.h osdep.h utf8.h
+! maildir.o: mail.h misc.h osdep.h maildir.h dummy.h
+
+ # OS-dependent
+
+diff -rc pine4.63/imap/src/osdep/unix/dummy.c pine4.63.I.USE/imap/src/osdep/unix/dummy.c
+*** pine4.63/imap/src/osdep/unix/dummy.c Wed Nov 10 16:16:23 2004
+--- pine4.63.I.USE/imap/src/osdep/unix/dummy.c Thu May 19 19:57:24 2005
+***************
+*** 104,109 ****
+--- 104,110 ----
+ {
+ char *s,tmp[MAILTMPLEN];
+ struct stat sbuf;
++ maildir_remove_root(&name);
+ /* must be valid local mailbox */
+ if (name && *name && (*name != '{') && (s = mailboxfile (tmp,name))) {
+ /* indeterminate clearbox INBOX */
+***************
+*** 364,370 ****
+ char *s,tmp[MAILTMPLEN];
+ /* don't \NoSelect dir if it has a driver */
+ if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) &&
+! (d != &dummydriver)) attributes &= ~LATT_NOSELECT;
+ if (!contents || /* notify main program */
+ (!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) &&
+ (s = mailboxfile (tmp,name)) &&
+--- 365,374 ----
+ char *s,tmp[MAILTMPLEN];
+ /* don't \NoSelect dir if it has a driver */
+ if ((attributes & LATT_NOSELECT) && (d = mail_valid (NIL,name,NIL)) &&
+! (d != &dummydriver)){
+! attributes &= ~LATT_NOSELECT;
+! attributes |= LATT_NOINFERIORS;
+! }
+ if (!contents || /* notify main program */
+ (!(attributes & LATT_NOSELECT) && (csiz = strlen (contents)) &&
+ (s = mailboxfile (tmp,name)) &&
+***************
+*** 385,390 ****
+--- 389,396 ----
+ {
+ char *s,tmp[MAILTMPLEN];
+ long ret = NIL;
++ if(!strncmp(mailbox,"#md/",4) || !strncmp(mailbox,"#mc/", 4))
++ return maildir_create(stream, mailbox);
+ /* validate name */
+ if (!(compare_cstring (mailbox,"INBOX") && (s = dummy_file (tmp,mailbox)))) {
+ sprintf (tmp,"Can't create %.80s: invalid name",mailbox);
+***************
+*** 450,455 ****
+--- 456,469 ----
+ {
+ struct stat sbuf;
+ char *s,tmp[MAILTMPLEN];
++ if (!strncmp(mailbox,"#md/",4) || !strncmp(mailbox,"#mc/", 4)
++ || is_valid_maildir(&mailbox)){
++ char tmp[MAILTMPLEN] = {'\0'};
++ strcpy(tmp, mailbox);
++ if(tmp[strlen(tmp) - 1] != '/')
++ tmp[strlen(tmp)] = '/';
++ return maildir_delete(stream, tmp);
++ }
+ if (!(s = dummy_file (tmp,mailbox))) {
+ sprintf (tmp,"Can't delete - invalid name: %.80s",s);
+ MM_LOG (tmp,ERROR);
+***************
+*** 476,481 ****
+--- 490,498 ----
+ {
+ struct stat sbuf;
+ char c,*s,tmp[MAILTMPLEN],mbx[MAILTMPLEN],oldname[MAILTMPLEN];
++
++ maildir_remove_root(&old);
++ maildir_remove_root(&newname);
+ /* no trailing / allowed */
+ if (!dummy_file (oldname,old) || !(s = dummy_file (mbx,newname)) ||
+ ((s = strrchr (s,'/')) && !s[1])) {
+diff -rc pine4.63/imap/src/osdep/unix/env_unix.c pine4.63.I.USE/imap/src/osdep/unix/env_unix.c
+*** pine4.63/imap/src/osdep/unix/env_unix.c Mon Sep 13 14:31:19 2004
+--- pine4.63.I.USE/imap/src/osdep/unix/env_unix.c Thu May 19 19:57:33 2005
+***************
+*** 24,29 ****
+--- 24,30 ----
+
+ /* c-client environment parameters */
+
++ static char *pwdfile = NIL; /* password file */
+ static char *myUserName = NIL; /* user name */
+ static char *myHomeDir = NIL; /* home directory name */
+ static char *myMailboxDir = NIL;/* mailbox directory name */
+***************
+*** 41,46 ****
+--- 42,48 ----
+ static char *blackBoxDir = NIL; /* black box directory name */
+ /* black box default home directory */
+ static char *blackBoxDefaultHome = NIL;
++ static int xlate_key; /* for password file support */
+ static short anonymous = NIL; /* is anonymous */
+ static short blackBox = NIL; /* is a black box */
+ static short closedBox = NIL; /* is a closed box */
+***************
+*** 215,220 ****
+--- 217,229 ----
+ case GET_SHAREDHOME:
+ ret = (void *) sharedHome;
+ break;
++ case SET_PASSWORDFILE:
++ if (pwdfile) fs_give ((void **) &pwdfile);
++ pwdfile = cpystr ((char *) value);
++ break;
++ case GET_PASSWORDFILE:
++ ret = (void *) pwdfile;
++ break;
+ case SET_SYSINBOX:
+ if (sysInbox) fs_give ((void **) &sysInbox);
+ sysInbox = cpystr ((char *) value);
+***************
+*** 1638,1640 ****
+--- 1647,1723 ----
+ }
+ return ret;
+ }
++
++ /*
++ *
++ * Module to add support for password file to a c-client application
++ *
++ * Written by Eduardo Chappa, based on password file support for Pine
++ *
++ */
++ #ifndef PWDFILE
++ #define PWDFILE 1
++ #endif
++
++ #define FIRSTCH 0x20
++ #define LASTCH 0x7e
++ #define TABSZ (LASTCH - FIRSTCH + 1)
++
++ char mm_xlate_out (char c);
++ void mm_userpwd (NETMBX *mb, char **username, char **password);
++
++ /* function that decodes passwords */
++
++ char mm_xlate_out (char c)
++ {
++ register int dti;
++ register int xch;
++
++ if((c >= FIRSTCH) && (c <= LASTCH)){
++ xch = c - (dti = xlate_key);
++ xch += (xch < FIRSTCH-TABSZ) ? 2*TABSZ : (xch < FIRSTCH) ? TABSZ : 0;
++ dti = (xch - FIRSTCH) + dti;
++ dti -= (dti >= 2*TABSZ) ? 2*TABSZ : (dti >= TABSZ) ? TABSZ : 0;
++ xlate_key = dti;
++ return(xch);
++ }
++ else
++ return(c);
++ }
++
++ void mm_userpwd (NETMBX *mb, char **username, char **password)
++ {
++ char *s;
++ char tmp[MAILTMPLEN], *ui[5];
++ FILE *fp;
++ int i, j, n;
++
++ if (!(pwdfile = env_parameters(GET_PASSWORDFILE, NULL)))
++ return;
++
++ if (fp = fopen(pwdfile, "r")){
++ for(n = 0; fgets(tmp, sizeof(tmp), fp); n++){
++ xlate_key = n;
++ for(i = 0; tmp[i]; i++)
++ tmp[i] = mm_xlate_out(tmp[i]);
++
++ if(i && tmp[i-1] == '\n')
++ tmp[i-1] = '\0';
++
++ ui[0] = ui[1] = ui[2] = ui[3] = ui[4] = NULL;
++ for(i = 0, j = 0; tmp[i] && j < 5; j++){
++ for(ui[j] = &tmp[i]; tmp[i] && tmp[i] != '\t'; i++);
++
++ if(tmp[i])
++ tmp[i++] = '\0';
++ }
++ if (*username && ui[1] && !strcmp(*username, ui[1]) && mb->host
++ && ((ui[2] && !strcmp(mb->host, ui[2]))
++ || (ui[4] && !strcmp(mb->host,ui[4]))
++ || (ui[2] && !strcmp(mb->orighost, ui[2]))
++ || (ui[4] && !strcmp(mb->orighost,ui[4]))))
++ strcpy (*password,ui[0]);
++ }
++ fclose(fp);
++ }
++ }
+diff -rc pine4.63/imap/src/osdep/unix/maildir.c pine4.63.I.USE/imap/src/osdep/unix/maildir.c
+*** pine4.63/imap/src/osdep/unix/maildir.c Thu May 19 19:59:15 2005
+--- pine4.63.I.USE/imap/src/osdep/unix/maildir.c Thu May 19 19:57:24 2005
+***************
+*** 0 ****
+--- 1,2031 ----
++ /*
++ * Maildir driver for Pine4.63
++ *
++ * Written by Eduardo Chappa <chappa@math.washington.edu>
++ * Last Update: May 04, 2005
++ *
++ * The IMAP toolkit provided in this Distribution is
++ * Copyright 2004 University of Washington.
++ * The full text of our legal notices is contained in the file called
++ * CPYRIGHT, included with this Distribution.
++ */
++
++ #include <stdio.h>
++ #include <ctype.h>
++ #include <errno.h>
++ extern int errno; /* just in case */
++ #include "mail.h"
++ #include "osdep.h"
++ #include <pwd.h>
++ #include <sys/stat.h>
++ #include <sys/time.h>
++ #include "maildir.h"
++ #include "rfc822.h"
++ #include "fdstring.h"
++ #include "misc.h"
++ #include "dummy.h"
++
++ /* Driver dispatch used by MAIL */
++ DRIVER maildirdriver = {
++ "md", /* driver name, yes it's md, not maildir */
++ /* driver flags */
++ DR_MAIL|DR_LOCAL|DR_NAMESPACE|DR_NOSTICKY,
++ (DRIVER *) NIL, /* next driver */
++ maildir_valid, /* mailbox is valid for us */
++ maildir_parameters, /* manipulate parameters */
++ NIL, /* scan mailboxes */
++ maildir_list, /* find mailboxes */
++ maildir_lsub, /* find subscribed mailboxes */
++ maildir_sub, /* subscribe to mailbox */
++ maildir_unsub, /* unsubscribe from mailbox */
++ maildir_create, /* create mailbox */
++ maildir_delete, /* delete mailbox */
++ maildir_rename, /* rename mailbox */
++ mail_status_default, /* status of mailbox */
++ maildir_open, /* open mailbox */
++ maildir_close, /* close mailbox */
++ maildir_fast, /* fetch message "fast" attributes */
++ NIL, /* fetch message flags */
++ NIL, /* fetch overview */
++ NIL, /* fetch message structure */
++ maildir_header, /* fetch message header */
++ maildir_text, /* fetch message body */
++ NIL, /* fetch partial message text */
++ NIL, /* unique identifier */
++ NIL, /* message number */
++ NIL, /* modify flags */
++ maildir_flagmsg, /* per-message modify flags */
++ NIL, /* search for message based on criteria */
++ NIL, /* sort messages */
++ NIL, /* thread messages */
++ maildir_ping, /* ping mailbox to see if still alive */
++ maildir_check, /* check for new messages */
++ maildir_expunge, /* expunge deleted messages */
++ maildir_copy, /* copy messages to another mailbox */
++ maildir_append, /* append string message to mailbox */
++ NIL /* garbage collect stream */
++ };
++
++
++ DRIVER courierdriver = {
++ "mc", /* Why a separate driver? So that
++ createproto will work */
++ /* driver flags */
++ DR_MAIL|DR_LOCAL|DR_NAMESPACE|DR_NOSTICKY,
++ (DRIVER *) NIL, /* next driver */
++ maildir_valid, /* mailbox is valid for us */
++ maildir_parameters, /* manipulate parameters */
++ NIL, /* scan mailboxes */
++ courier_list, /* find mailboxes */
++ maildir_lsub, /* find subscribed mailboxes */
++ maildir_sub, /* subscribe to mailbox */
++ maildir_unsub, /* unsubscribe from mailbox */
++ maildir_create, /* create mailbox */
++ maildir_delete, /* delete mailbox */
++ maildir_rename, /* rename mailbox */
++ mail_status_default, /* status of mailbox */
++ maildir_open, /* open mailbox */
++ maildir_close, /* close mailbox */
++ maildir_fast, /* fetch message "fast" attributes */
++ NIL, /* fetch message flags */
++ NIL, /* fetch overview */
++ NIL, /* fetch message structure */
++ maildir_header, /* fetch message header */
++ maildir_text, /* fetch message body */
++ NIL, /* fetch partial message text */
++ NIL, /* unique identifier */
++ NIL, /* message number */
++ NIL, /* modify flags */
++ maildir_flagmsg, /* per-message modify flags */
++ NIL, /* search for message based on criteria */
++ NIL, /* sort messages */
++ NIL, /* thread messages */
++ maildir_ping, /* ping mailbox to see if still alive */
++ maildir_check, /* check for new messages */
++ maildir_expunge, /* expunge deleted messages */
++ maildir_copy, /* copy messages to another mailbox */
++ maildir_append, /* append string message to mailbox */
++ NIL /* garbage collect stream */
++ };
++
++ MAILSTREAM maildirproto = {&maildirdriver}; /* prototype stream */
++ MAILSTREAM courierproto = {&courierdriver}; /* prototype stream */
++
++ void
++ md_domain_name(void)
++ {
++ int i;
++
++ strcpy(mdlocaldomain,mylocalhost ());
++ for (i = 0; mdlocaldomain[i] ; i++)
++ if(mdlocaldomain[i] == '/')
++ mdlocaldomain[i] = '\057';
++ else if (mdlocaldomain[i] == ':')
++ mdlocaldomain[i] = '\072';
++ }
++
++ /* remove the "#md/" or "#mc/" part from a folder name */
++ void maildir_remove_root (char **name)
++ {
++ int courier = IS_COURIER(*name);
++ char realname[MAILTMPLEN], *p;
++
++ if (maildir_valid_name(*name)){
++ (*name) += 3;
++ if (**name == '/')
++ (*name)++;
++ }
++ if(courier)
++ courier_realname(*name, realname);
++ else
++ strcpy(realname, *name);
++ *name = cpystr(realname);
++ }
++
++
++ /* Check validity of the name, we accept:
++ * a) #md/directory/folder
++ * b) #md/inbox
++ * A few considerations: We can only accept as valid
++ * a) names that start with #md/ and the directory exists or
++ * b) names that do not start with #md/ but are maildir directories (have
++ * the /cur, /tmp and /new structure)
++ */
++ int maildir_valid_name (char *name)
++ {
++ char tmpname[MAILTMPLEN] = {'\0'};
++
++ if (mdfpath)
++ fs_give((void **)&mdfpath);
++ if (name && (name[0] != '#'))
++ sprintf(tmpname,"%s%s",MDPREFIX(CCLIENT), name);
++ mdfpath = cpystr(tmpname[0] ? tmpname : name);
++
++ return IS_CCLIENT(name) || IS_COURIER(name);
++ }
++
++ /* Check if the directory whose path is given by name is a valid maildir
++ * directory (contains /cur, /tmp and /new)
++ */
++ int maildir_valid_dir (char *name)
++ {
++ int len;
++ DirNamesType i;
++ struct stat sbuf;
++ char tmp[MAILTMPLEN];
++
++ if(name[strlen(name) - 1] == '/')
++ name[strlen(name) - 1] = '\0';
++ len = strlen(name);
++ for (i = Cur; i != EndDir; i++){
++ MDFLD(tmp, name, i);
++ if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode))
++ break;
++ }
++ name[len] = '\0';
++ return i == EndDir ? T : NIL;
++ }
++
++ void courier_realname(char *name, char *realname)
++ {
++ int i,j;
++
++ if(!name)
++ return;
++
++ for (i = 0, j = 0; i < MAILTMPLEN && j < strlen(name); j++, i++){
++ realname[i] = name[j];
++ if(name[j] == '/' && name[j+1] != '.' && name[j+1] != '%'
++ && name[j+1] != '*')
++ realname[++i] = '.';
++ }
++ if(realname[i-1] == '.')
++ i--;
++ realname[i] = '\0';
++ }
++
++
++ /* given a maildir folder, return its path. Memory freed by caller. Directory
++ * does not contain the trailing slash "/". On error NULL is returned.
++ */
++ int maildir_file_path (char *name, char *tmp)
++ {
++ char *maildirpath = maildir_parameters(GET_INBOXPATH,NIL);
++ char realname[MAILTMPLEN];
++ int courier = IS_COURIER(name);
++
++ /* There are several ways in which the path can come, so we will handle
++ them here. First we deal with #mc/ or #md/ prefix by removing the
++ prefix, if any */
++
++ maildir_remove_root(&name);
++ tmp[0] = '\0'; /* just in case something fails */
++
++ if (strlen(myhomedir()) +
++ max(strlen(name), strlen(maildirpath
++ ? maildirpath : "Maildir")) > MAILTMPLEN){
++ errno = ENAMETOOLONG;
++ sprintf(tmp,"Error opening \"%s\": %s", name, strerror (errno));
++ mm_log(tmp,ERROR);
++ return NIL;
++ }
++
++ /* There are two ways in which the name can come here, either as a
++ full path or not. If it is not a full path it can come in two ways,
++ either as a file system path (Maildir/.Drafts) or as a maildir path
++ (INBOX.Drafts)
++ */
++
++ if(*name == '/') /* full path */
++ strcpy(tmp, name); /* do nothing */
++ else{
++ sprintf (tmp,"%s/%s%s%s", myhomedir (),
++ strncmp (ucase (strcpy (tmp, name)), "INBOX", 5)
++ ? name : (maildirpath ? maildirpath : "Maildir"),
++ strncmp (ucase (strcpy (tmp, name)), "INBOX", 5)
++ ? "" : (courier ? "/" : ""),
++ strncmp (ucase (strcpy (tmp, name)), "INBOX", 5)
++ ? "" : *(name+5) == MDSEPARATOR(courier) ? name+5 : "");
++ }
++
++ return tmp[0] ? T : NIL;
++ }
++
++ /* This function is given a full path for a mailbox and returns
++ * if it is a valid maildir transformed to canonical notation
++ */
++ int
++ is_valid_maildir (char **name)
++ {
++ if (!strncmp(*name, myhomedir (), strlen(myhomedir()))){
++ (*name) += strlen(myhomedir());
++ if (**name == '/') (*name)++;
++ }
++ return maildir_valid(*name) ? T : NIL;
++ }
++
++ /* Check validity of mailbox. This routine does not send errors to log, other
++ * routines calling this one may do so, though
++ */
++
++ DRIVER *maildir_valid (char *name)
++ {
++ char tmpname[MAILTMPLEN];
++
++ maildir_file_path(name, tmpname);
++
++ return maildir_valid_dir(tmpname)
++ ? (IS_COURIER(name) ? &courierdriver : &maildirdriver) : NIL;
++ }
++ /*maildir fast */
++ void maildir_fast (MAILSTREAM *stream,char *sequence,long flags)
++ {
++ unsigned long i;
++ MESSAGECACHE *elt;
++ /* get sequence */
++ if (stream && LOCAL && ((flags & FT_UID) ?
++ mail_uid_sequence (stream,sequence) :
++ mail_sequence (stream,sequence)))
++ for (i = 1; i <= stream->nmsgs; i++) {
++ if ((elt = mail_elt (stream,i))->sequence && (elt->valid = T) &&
++ !(elt->day && elt->rfc822_size)) {
++ ENVELOPE **env = NIL;
++ ENVELOPE *e = NIL;
++ if (!stream->scache) env = &elt->private.msg.env;
++ else if (stream->msgno == i) env = &stream->env;
++ else env = &e;
++ if (!*env || !elt->rfc822_size) {
++ STRING bs;
++ unsigned long hs;
++ char *ht = (*stream->dtb->header) (stream,i,&hs,NIL);
++
++ if (!*env) rfc822_parse_msg (env,NIL,ht,hs,NIL,BADHOST,
++ stream->dtb->flags);
++ if (!elt->rfc822_size) {
++ (*stream->dtb->text) (stream,i,&bs,FT_PEEK);
++ elt->rfc822_size = hs + SIZE (&bs) - GETPOS (&bs);
++ }
++ }
++
++ if (!elt->day && *env && (*env)->date)
++ mail_parse_date (elt,(*env)->date);
++
++ if (!elt->day) elt->day = elt->month = 1;
++ mail_free_envelope (&e);
++ }
++ }
++ }
++
++
++ /*
++ * return all files in a given directory. This is a separate call
++ * so that if there are warnings during compilation this only appears once.
++ */
++ unsigned long
++ maildir_scandir (char *name, struct direct ***flist,
++ unsigned long *nfiles, int *scand, int flag)
++ {
++ struct stat sbuf;
++
++ if (scand)
++ *scand = -1; /* assume error for safety */
++ stat(name,&sbuf); /* stat the containing directory */
++ if (scand)
++ *scand = scandir(name, flist,
++ flag == CCLIENT ? maildir_select : courier_dir_select,
++ flag == CCLIENT ? maildir_namesort : courier_dir_sort);
++ *nfiles = (scand && (*scand > 0)) ? (unsigned long) *scand : 0L;
++
++ return sbuf.st_ctime;
++ }
++
++ /* Does a message with given name exists (or was it removed)?
++ * Returns: 1 - yes, such message exist,
++ * 0 - No, that message does not exist anymore
++ *
++ * Parameters: stream, name of mailbox, new name if his message does not
++ * exist.
++ */
++
++ int maildir_message_exists(MAILSTREAM *stream, char *name, char *newfile)
++ {
++ char tmp[MAILTMPLEN];
++ int gotit = NIL;
++ DIR *dir;
++ struct direct *d;
++ struct stat sbuf;
++
++ /* First check directly if it exists, if not there, look for it */
++ sprintf(tmp,"%s/%s", LOCAL->curdir, name);
++ if ((stat(tmp, &sbuf) == 0) && ((sbuf.st_mode & S_IFMT) == S_IFREG))
++ return T;
++
++ if (!(dir = opendir (LOCAL->curdir)))
++ return NIL;
++
++ while ((d = readdir(dir)) && gotit == NIL){
++ if (d->d_name[0] == '.')
++ continue;
++ if (same_maildir_file(d->d_name, name)){
++ gotit = T;
++ strcpy(newfile, d->d_name);
++ }
++ }
++ closedir(dir);
++ return gotit;
++ }
++
++ /* Maildir open */
++
++ MAILSTREAM *maildir_open (MAILSTREAM *stream)
++ {
++ char tmp[MAILTMPLEN];
++ struct stat sbuf;
++
++ if (!stream) return &maildirproto;
++ if (stream->local) fatal ("maildir recycle stream");
++ md_domain_name(); /* get domain name for maildir files in mdlocaldomain */
++ stream->uid_last = stream->uid_validity = 0;
++ if (!stream->rdonly){
++ stream->perm_seen = stream->perm_deleted = stream->perm_flagged =
++ stream->perm_answered = stream->perm_draft = T;
++ }
++ stream->uid_validity = time(0);
++ stream->local = (MAILDIRLOCAL *)fs_get (sizeof (MAILDIRLOCAL));
++ memset(LOCAL, 0, sizeof(MAILDIRLOCAL));
++ LOCAL->fd = -1;
++
++ LOCAL->courier = IS_COURIER(stream->mailbox);
++ strcpy(tmp, stream->mailbox);
++ if (maildir_file_path (stream->mailbox, tmp))
++ LOCAL->dir = cpystr (tmp);
++ if (LOCAL->dir){
++ MDFLD(tmp, LOCAL->dir, Cur);
++ LOCAL->curdir = cpystr (tmp);
++ if (stat (LOCAL->curdir,&sbuf) < 0) {
++ sprintf (tmp,"Can't open folder %s: %s",
++ stream->mailbox,strerror (errno));
++ mm_log (tmp,ERROR);
++ maildir_close(stream, 0);
++ return NIL;
++ }
++ }
++
++ if(maildir_file_path (stream->mailbox, tmp)){
++ fs_give ((void **) &stream->mailbox);
++ stream->mailbox = cpystr(tmp);
++ }
++
++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = MAXMESSAGESIZE) + 1);
++ stream->sequence++;
++ stream->nmsgs = stream->recent = 0;
++
++ maildir_parse_folder(stream, 1);
++
++ return stream;
++ }
++
++ /* Maildir initial parsing of the folder */
++ void
++ maildir_parse_folder (MAILSTREAM *stream, int full)
++ {
++ unsigned long total;
++
++ if (!stream) /* what??? */
++ return;
++
++ MM_CRITICAL(stream);
++
++ /* Scan old messages first, escoba! */
++ total = LOCAL ? maildir_parse_dir(stream, 0L, Cur, full)
++ : stream->nmsgs;
++ stream->nmsgs = LOCAL ? maildir_parse_dir(stream, total, New, full)
++ : stream->nmsgs;
++
++ MM_NOCRITICAL(stream);
++ }
++
++ /* Return the number of messages in the directory, while filling the
++ * elt structure.
++ */
++
++ unsigned long
++ maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs,
++ DirNamesType dirtype, int full)
++ {
++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], file[MAILTMPLEN],
++ newfile[MAILTMPLEN], *mdstr;
++ struct direct **names = NIL;
++ struct stat sbuf;
++ unsigned long i, j = 0L, nfiles, last_scan;
++ unsigned long recent = stream ? stream->recent : 0L;
++ int d = 0, f = 0, r = 0, s = 0, t = 0;
++ int k, we_compute, in_list, scan_err;
++ int silent = stream ? stream->silent : NIL;
++ MESSAGECACHE *elt;
++
++ MDFLD(tmp, LOCAL->dir, dirtype);
++ if (access (tmp, R_OK|W_OK|X_OK) != 0){
++ maildir_abort(stream);
++ return stream->nmsgs;
++ }
++
++ MDFLD(tmp, LOCAL->dir, Cur);
++ if (dirtype != New &&
++ (stat(tmp, &sbuf) < 0 || sbuf.st_ctime == LOCAL->scantime))
++ return stream->nmsgs;
++
++ MDFLD(tmp, LOCAL->dir, dirtype);
++ last_scan = maildir_scandir (tmp, &names, &nfiles, &scan_err, CCLIENT);
++ if (dirtype == Cur)
++ LOCAL->scantime = last_scan;
++
++ if (scan_err < 0){
++ maildir_abort(stream);
++ return nmsgs;
++ }
++
++ if (dirtype == Cur)
++ for (i = 1L; i <= stream->nmsgs;){
++ elt = mail_elt(stream, i);
++ in_list = elt && elt->maildirp && nfiles > 0L
++ ? (MDPOS(elt) < nfiles
++ ? same_maildir_file(MDFILE(elt), names[MDPOS(elt)]->d_name)
++ : NIL)
++ || maildir_message_in_list(MDFILE(elt), names, 0L,
++ nfiles - 1L, &MDPOS(elt))
++ : NIL;
++ if (!in_list){
++ if (elt->maildirp)
++ maildir_free_file ((void **) &elt->maildirp);
++
++ if (elt->recent) --recent;
++ mail_expunged(stream,i);
++ }
++ else i++;
++ }
++
++ stream->silent = T;
++ for (we_compute = 0, i = 1L; i <= nfiles; i++){
++ unsigned long pos, n;
++ mail_exists(stream, i + nmsgs);
++ elt = mail_elt(stream, i + nmsgs);
++ if (elt && elt->maildirp)
++ pos = MDPOS(elt); /* use data we found above */
++ else{
++ if (full)
++ pos = i - 1; /* first time, use sequence number */
++ else{
++ for (n = 0L ; (n < nfiles) && !names[n] ; n++);
++ pos = n; /* nfiles > stream->nmsgs!!, assign one */
++ }
++ }
++ if (dirtype == New) elt->recent = T;
++ if (!elt->private.uid){
++ elt->private.uid = stream->uid_last + 1;
++ stream->uid_validity = time(0);
++ }
++ if (stream->uid_last < elt->private.uid)
++ stream->uid_last = elt->private.uid;
++
++ maildir_getflag(names[pos]->d_name, &d, &f, &r ,&s, &t);
++ if (elt->maildirp)
++ maildir_free_file_only ((void **)&elt->maildirp);
++ else{
++ maildir_get_file((MAILDIRFILE **)&elt->maildirp);
++ we_compute++;
++ }
++ MDFILE(elt) = cpystr(names[pos]->d_name);
++ MDPOS(elt) = pos;
++
++ if (elt->draft != d || elt->flagged != f ||
++ elt->answered != r || elt->seen != s || elt->deleted != t){
++ elt->draft = d; elt->flagged = f; elt->answered = r;
++ elt->seen = s; elt->deleted = t;
++ if (!we_compute && !stream->rdonly)
++ MM_FLAGS(stream, i+nmsgs);
++ }
++ maildir_get_date(stream, i+nmsgs, dirtype);
++ elt->valid = T;
++ if (dirtype == New && !stream->rdonly){ /* move new messages to cur */
++ sprintf (file,"%s/%s", tmp, names[pos]->d_name);
++ if (stat (file,&sbuf) == 0 && S_ISREG (sbuf.st_mode)){
++ strcpy(tmp2,names[pos]->d_name);
++ if ((mdstr = strstr (names[pos]->d_name,MDSEP(3)))
++ || (mdstr = strstr (names[pos]->d_name,MDSEP(2)))){ /* Grrr */
++ *(mdstr+1) = '2';
++ sprintf (newfile,"%s/%s",LOCAL->curdir,names[pos]->d_name);
++ }
++ else{
++ sprintf (newfile,"%s/%s%s",LOCAL->curdir,names[pos]->d_name,MDSEP(2));
++ strcat(tmp2, MDSEP(2));
++ }
++ if (link (file,newfile) < 0){
++ mm_log("Unable to read new mail!",WARN);
++ }
++ else{
++ unlink (file);
++ j++; /* success!, count it! */
++ }
++ maildir_free_file_only((void **)&elt->maildirp);
++ MDFILE(elt) = cpystr(tmp2);
++ MDSIZE(elt) = sbuf.st_size;
++ MDMTIME(elt) = sbuf.st_mtime;
++ maildir_get_date(stream, i + nmsgs, New);
++ }
++ }
++ fs_give((void **)&names[pos]);
++ }
++ if(names)
++ fs_give((void **) &names);
++ stream->silent = silent;
++ if (dirtype == New && stream->rdonly)
++ j = nfiles;
++ mail_exists(stream, nmsgs + (dirtype == New ? j : nfiles));
++ mail_recent(stream, recent + (dirtype == New ? j : 0));
++
++ return (nmsgs + (dirtype == New ? j : nfiles));
++ }
++
++ long maildir_ping (MAILSTREAM *stream)
++ {
++ maildir_parse_folder(stream, 0);
++ return stream && LOCAL ? T : NIL;
++ }
++
++ int maildir_select (struct direct *name)
++ {
++ int rv = NIL, val;
++ val = name->d_name[0] - '0';
++ switch(val){
++ case 1: case 2: case 3: case 4: case 5:
++ case 6: case 7: case 8: case 9:
++ rv = T;
++ default: break;
++ }
++ return rv;
++ }
++
++ /*
++ * Unfortunately, there is no way to sort by arrival in this driver, this
++ * means that opening a folder in this driver using the scandir function
++ * will always make this driver slower than any driver that has a natural
++ * way of sorting by arrival (like a flat file format, "mbox", "mbx", etc).
++ */
++
++ int maildir_namesort (const void *d1,const void *d2)
++ {
++ const struct direct **e1, **e2;
++
++ e1 = (const struct direct **)d1;
++ e2 = (const struct direct **)d2;
++
++ return comp_maildir_file((char*)(*e1)->d_name, (char *)(*e2)->d_name);
++ }
++
++ /* Maildir close */
++
++ void maildir_close (MAILSTREAM *stream, long options)
++ {
++ MESSAGECACHE *elt;
++ unsigned long i;
++ int silent = stream ? stream->silent : 0;
++ mailcache_t mc = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL);
++
++ if (!stream) return;
++
++ for (i = 1; i <= stream->nmsgs; i++)
++ if ((elt = (MESSAGECACHE *) (*mc) (stream,i,CH_ELT)) && elt->maildirp)
++ maildir_free_file ((void **) &(elt->maildirp));
++ stream->silent = T;
++ if (options & CL_EXPUNGE) maildir_expunge (stream);
++ maildir_abort(stream);
++ if (mdfpath) fs_give((void **)&mdfpath);
++ stream->silent = silent;
++ }
++
++ void maildir_check (MAILSTREAM *stream)
++ {
++ if (maildir_ping (stream)) mm_log ("Check completed",(long) NIL);
++ }
++
++ long maildir_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs, long flags)
++ {
++ char tmp[MAILTMPLEN];
++ unsigned long i;
++ MESSAGECACHE *elt;
++ char *s;
++ /* UID call "impossible" */
++ if (flags & FT_UID || !LOCAL) return NIL;
++ elt = mail_elt (stream,msgno);
++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ if (LOCAL->fd < 0) /* if file closed ? */
++ LOCAL->fd = open(tmp,O_RDONLY,NIL);
++
++ if (LOCAL->fd < 0 && (errno == EACCES || errno == ENOENT)){
++ INIT (bs, mail_string, "", 0);
++ elt->rfc822_size = 0L;
++ return NIL;
++ }
++
++ if (LOCAL->dirty == 0)
++ MM_FLAGS(stream, elt->msgno);
++
++ s = maildir_text_work(stream, elt, &i, flags);
++ INIT (bs, mail_string, s, i);
++ return T;
++ }
++
++ char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt,
++ unsigned long *length,long flags)
++ {
++ FDDATA d;
++ STRING bs;
++ char *s,*t,*tl,tmp[CHUNK];
++ unsigned long msgno = elt->msgno;
++ static int try = 0;
++
++ if (length)
++ *length = 0L;
++ LOCAL->buf[0] = '\0';
++
++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ if (LOCAL->fd < 0) /* if file closed ? */
++ LOCAL->fd = open(tmp,O_RDONLY,NIL);
++
++ if (LOCAL->fd < 0){ /* flag change? */
++ if (try < 5){
++ try++;
++ if (maildir_update_elt_maildirp(stream, msgno) > 0)
++ try = 0;
++ return maildir_text_work(stream, mail_elt(stream, msgno),length, flags);
++ }
++ try = 0;
++ return NULL;
++ }
++
++ lseek (LOCAL->fd, elt->private.msg.text.offset,L_SET);
++
++ if (flags & FT_INTERNAL) { /* initial data OK? */
++ if (elt->private.msg.text.text.size > LOCAL->buflen) {
++ fs_give ((void **) &LOCAL->buf);
++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen =
++ elt->private.msg.text.text.size) + 1);
++ }
++ read (LOCAL->fd,LOCAL->buf,elt->private.msg.text.text.size);
++ LOCAL->buf[*length = elt->private.msg.text.text.size] = '\0';
++ }
++ else {
++ if (elt->rfc822_size > LOCAL->buflen) {
++ fs_give ((void **) &LOCAL->buf);
++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen = elt->rfc822_size) + 1);
++ }
++ d.fd = LOCAL->fd; /* yes, set up file descriptor */
++ d.pos = elt->private.msg.text.offset;
++ d.chunk = tmp; /* initial buffer chunk */
++ d.chunksize = CHUNK;
++ INIT (&bs,fd_string,&d,elt->private.msg.text.text.size);
++ for (s = LOCAL->buf; SIZE (&bs);) switch (CHR (&bs)) {
++ case '\r': /* carriage return seen */
++ *s++ = SNX (&bs); /* copy it and any succeeding LF */
++ if (SIZE (&bs) && (CHR (&bs) == '\n')) *s++ = SNX (&bs);
++ break;
++ case '\n':
++ *s++ = '\r'; /* insert a CR */
++ default:
++ *s++ = SNX (&bs); /* copy characters */
++ }
++ *s = '\0'; /* tie off buffer */
++ *length = s - (char *) LOCAL->buf; /* calculate length */
++ }
++ close(LOCAL->fd); LOCAL->fd = -1;
++ return LOCAL->buf;
++ }
++
++ /* maildir parse, fill the elt structure... well not all of it... */
++ unsigned long maildir_parse_message(MAILSTREAM *stream, unsigned long msgno,
++ DirNamesType dirtype)
++ {
++ char *b, *s, c;
++ char tmp[MAILTMPLEN];
++ struct stat sbuf;
++ unsigned long i, len;
++ int offset = 0, d, f, r, se, dt;
++ MESSAGECACHE *elt;
++
++ elt = mail_elt (stream,msgno);
++ MSGPATH(tmp, LOCAL->dir, MDFILE(elt), dirtype);
++ if(stat(tmp, &sbuf) == 0)
++ MDSIZE(elt) = sbuf.st_size;
++
++ maildir_get_date(stream, msgno, dirtype);
++ maildir_getflag(MDFILE(elt), &d, &f, &r ,&se, &dt);
++ elt->draft = d; elt->flagged = f; elt->answered = r; elt->seen = se;
++ elt->deleted = dt; elt->valid = T;
++ if (LOCAL->fd < 0) /* if file closed ? */
++ LOCAL->fd = open(tmp,O_RDONLY,NIL);
++
++ if (LOCAL->fd >= 0){
++ s = (char *) fs_get (MDSIZE(elt) + 1);
++ read (LOCAL->fd,s,MDSIZE(elt));
++ s[MDSIZE(elt)] = '\0';
++ for (i = 0, b = s; *b && !(i && (*b == '\n')); i = (*b++ == '\n'));
++ len = (*b ? ++b : b) - s;
++ elt->private.msg.header.text.size =
++ elt->private.msg.text.offset = len;
++ elt->private.msg.text.text.size = MDSIZE(elt) - len;
++ for (i = 0, b = s, c = *b; b && c &&
++ ((c < '\016') && (((c == '\012') && ++i) ||
++ ((c == '\015') && (*++b == '\012') && (i +=2)))
++ || c); i++, c= *++b);
++ elt->rfc822_size = i;
++ fs_give ((void **) &s);
++ close(LOCAL->fd); LOCAL->fd = -1;
++ }
++ return elt->rfc822_size;
++ }
++
++ int
++ maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno)
++ {
++ char tmp[MAILTMPLEN];
++ struct direct **names = NIL;
++ unsigned long i, nfiles, pos;
++ int d = 0, f = 0 , r = 0, s = 0, t = 0, in_list, scan_err;
++ MESSAGECACHE *elt;
++
++ MDFLD(tmp, LOCAL->dir, Cur);
++
++ maildir_scandir (tmp, &names, &nfiles, &scan_err, CCLIENT);
++
++ elt = mail_elt (stream,msgno);
++
++ in_list = nfiles > 0L
++ ? maildir_message_in_list(MDFILE(elt), names, 0L,
++ nfiles - 1L, &pos)
++ : NIL;
++
++ if (in_list && pos >= 0L && pos < nfiles
++ && !strcmp(MDFILE(elt), names[pos]->d_name)){
++ in_list = NIL;
++ maildir_abort(stream);
++ }
++
++ if (in_list && pos >= 0L && pos < nfiles){
++ maildir_free_file_only((void **)&elt->maildirp);
++ MDFILE(elt) = cpystr(names[pos]->d_name);
++ maildir_getflag(MDFILE(elt), &d, &f, &r ,&s, &t);
++ if (elt->draft != d || elt->flagged != f ||
++ elt->answered != r || elt->seen != s || elt->deleted != t){
++ elt->draft = d; elt->flagged = f; elt->answered = r;
++ elt->seen = s; elt->deleted = t;
++ MM_FLAGS(stream, msgno);
++ }
++ }
++ for (i = 0L; i < nfiles; i++)
++ fs_give((void **) &names[i]);
++ if (names)
++ fs_give((void **) &names);
++ return in_list ? 1 : -1;
++ }
++
++ /* Maildir fetch message header */
++
++ char *maildir_header (MAILSTREAM *stream,unsigned long msgno,
++ unsigned long *length, long flags)
++ {
++ char tmp[MAILTMPLEN], *s;
++ MESSAGECACHE *elt;
++ static int try = 0;
++
++ if (length)
++ *length = 0;
++ if (flags & FT_UID || !LOCAL) return ""; /* UID call "impossible" */
++ elt = mail_elt (stream,msgno);
++ if(elt->private.msg.header.text.size == 0)
++ maildir_parse_message(stream, msgno, Cur);
++
++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ if (LOCAL->fd < 0)
++ LOCAL->fd = open (tmp,O_RDONLY,NIL);
++
++ if (LOCAL->fd < 0 && errno == EACCES){
++ mm_log ("Message exists but can not be read. Envelope and body lost!",ERROR);
++ return NULL;
++ }
++
++ if (LOCAL->fd < 0){ /* flag change? */
++ if (try < 5){
++ try++;
++ if (maildir_update_elt_maildirp(stream, msgno) > 0)
++ try = 0;
++ return maildir_header(stream, msgno, length, flags);
++ }
++ try = 0;
++ return NULL;
++ }
++
++ if ((flags & FT_INTERNAL) &&
++ (elt->private.msg.header.text.size > LOCAL->buflen)){
++ fs_give ((void **) &LOCAL->buf);
++ LOCAL->buf = (char *) fs_get ((LOCAL->buflen =
++ elt->private.msg.header.text.size) + 1);
++ }
++ else
++ s = (char *) fs_get(elt->private.msg.header.text.size+1);
++ if (LOCAL->fd >= 0){
++ read (LOCAL->fd, flags & FT_INTERNAL ? (void *)LOCAL->buf : (void *)s,
++ elt->private.msg.header.text.size);
++ if (flags & FT_INTERNAL)
++ LOCAL->buf[*length = elt->private.msg.header.text.size] = '\0';
++ else{
++ s[*length = elt->private.msg.header.text.size] = '\0';
++ *length = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen,s,
++ elt->private.msg.header.text.size);
++ fs_give ((void **) &s);
++ }
++ }
++ elt->private.msg.text.offset = elt->private.msg.header.text.size;
++ elt->private.msg.text.text.size = MDSIZE(elt) - elt->private.msg.text.offset;
++ if(s)
++ fs_give((void **)&s);
++ close(LOCAL->fd); LOCAL->fd = -1;
++ return LOCAL->buf;
++ }
++
++ /* Maildir find list of subscribed mailboxes
++ * Accepts: mail stream
++ * pattern to search
++ */
++
++ void maildir_list (MAILSTREAM *stream,char *ref, char *pat)
++ {
++ char *s,test[MAILTMPLEN],file[MAILTMPLEN];
++ long i = 0;
++
++ if((!pat || !*pat) && (maildir_canonicalize (test,ref,"*"))
++ && maildir_valid_name(test)){ /* there is a #md/ leading here */
++ for (i = 3; test[i] && test[i] != '/'; i++);
++ if (s = strchr (test+i+1,'/')) *++s = '\0';
++ else test[0] = '\0';
++ mm_list (stream,'/',test, LATT_NOSELECT);
++ }
++ else if (maildir_canonicalize (test,ref,pat)) {
++ if (test[3] == '/') { /* looking down levels? */
++ /* yes, found any wildcards? */
++ if (s = strpbrk (test,"%*")) {
++ /* yes, copy name up to that point */
++ strncpy (file,test+4,i = s - (test+4));
++ file[i] = '\0'; /* tie off */
++ }
++ else strcpy (file,test+4);/* use just that name then */
++ /* find directory name */
++ if (s = strrchr (file,'/')) {
++ *s = '\0'; /* found, tie off at that point */
++ s = file;
++ }
++ /* do the work */
++ if(IS_COURIER(test))
++ courier_list_work (stream,s,test,0);
++ else
++ maildir_list_work (stream,s,test,0);
++ }
++ /* always an INBOX */
++ if (!compare_cstring (test,"#MD/INBOX"))
++ mm_list (stream,NIL,"#MD/INBOX",LATT_NOINFERIORS);
++ if (!compare_cstring (test,"#MC/INBOX"))
++ mm_list (stream,NIL,"#MC/INBOX",LATT_NOINFERIORS);
++ }
++ }
++
++ void courier_list (MAILSTREAM *stream,char *ref, char *pat)
++ {
++ /* I am too lazy to do anything. Do you care to ask maildir list, please?
++ The real reason why this is a dummy function is because we do not want to
++ see the same folder listed twice.
++ */
++ }
++
++ /* For those that want to hide things, we give them a chance to do so */
++ void *maildir_parameters (long function, void *value)
++ {
++ void *ret = NIL;
++ switch ((int) function) {
++ case SET_INBOXPATH:
++ if (myMdInboxDir) fs_give ((void **) &myMdInboxDir);
++ myMdInboxDir = cpystr ((char *) value);
++ case GET_INBOXPATH:
++ if (!myMdInboxDir) myMdInboxDir = cpystr("Maildir");
++ ret = (void *) myMdInboxDir;
++ break;
++ case SET_COURIERSTYLE:
++ CourierStyle = (long) value;
++ case GET_COURIERSTYLE:
++ ret = (void *) CourierStyle;
++ break;
++ default:
++ break;
++ }
++ return ret;
++ }
++
++ int maildir_create_folder(char *mailbox)
++ {
++ char tmp[MAILTMPLEN], err[MAILTMPLEN];
++ int i;
++
++ for (i = Cur; i != EndDir; i++){
++ MDFLD(tmp, mailbox, i);
++ if (mkdir(tmp, 0700) && errno != EEXIST){ /* try to make new dir */
++ sprintf (err, "Can't create %s: %s", tmp, strerror(errno));
++ mm_log (err,ERROR);
++ return NIL;
++ }
++ }
++ return T;
++ }
++
++ int maildir_create_work(char *mailbox, int loop)
++ {
++ char *s, c, err[MAILTMPLEN], tmp[MAILTMPLEN], tmp2[MAILTMPLEN], mbx[MAILTMPLEN];
++ int fnlen, i, create_dir = 0, courier, mv;
++ struct stat sbuf;
++ long style = (long) maildir_parameters(GET_COURIERSTYLE, NIL);
++
++ courier = IS_COURIER(mailbox);
++ strcpy(mbx, mailbox);
++ mv = maildir_valid(mbx) ? 1 : 0;
++ maildir_file_path(mailbox, tmp);
++ if (mailbox[strlen(mailbox) - 1] == MDSEPARATOR(courier)){
++ create_dir++;
++ mailbox[strlen(mailbox) - 1] = '\0';
++ }
++
++ if(!loop && courier){
++ if(mv){
++ if(create_dir){
++ if(style == CCLIENT)
++ strcpy (err,"Can not create directory: folder exists. Create subfolder");
++ else
++ strcpy(err,"Folder and Directory already exist");
++ }
++ else
++ strcpy (err, "Can't create mailbox: mailbox already exists");
++ }
++ else{
++ if(create_dir)
++ strcpy(err, "Can not create directory. Cread folder instead");
++ else
++ err[0] = '\0';
++ }
++ if(err[0]){
++ mm_log (err,ERROR);
++ return NIL;
++ }
++ }
++
++ fnlen = strlen(tmp);
++ if (s = strrchr(mailbox,MDSEPARATOR(courier))){
++ c = *++s;
++ *s = '\0';
++ if ((stat(tmp,&sbuf) || ((sbuf.st_mode & S_IFMT) != S_IFDIR)) &&
++ !maildir_create_work (mailbox, ++loop))
++ return NIL;
++ *s = c;
++ }
++ tmp[fnlen] = '\0';
++
++ if (mkdir(tmp,0700) && errno != EEXIST)
++ return NIL;
++
++ if (create_dir)
++ mailbox[fnlen] = '/';
++
++ if (create_dir){
++ if(style == CCLIENT){
++ if(!courier){
++ FILE *fp = NULL;
++ sprintf(tmp2,"%s%s", tmp, MDDIR);
++ if ((fp = fopen(tmp2,"w")) == NULL){
++ sprintf (err,"Problem creating %s: %s", tmp2, strerror(errno));
++ mm_log (err,ERROR);
++ return NIL;
++ }
++ fclose(fp);
++ }
++ }
++ return T;
++ }
++ else
++ return maildir_create_folder(tmp);
++ }
++
++ long maildir_create (MAILSTREAM *stream,char *mailbox)
++ {
++ char tmp[MAILTMPLEN], err[MAILTMPLEN];
++ long rv;
++ int create_dir;
++
++ create_dir = mailbox ?
++ (mailbox[strlen(mailbox) - 1] ==
++ MDSEPARATOR(IS_COURIER(mailbox))) : 0;
++ maildir_file_path(mailbox, tmp);
++ strcpy(tmp, mailbox);
++ rv = maildir_create_work(mailbox, 0);
++ strcpy(mailbox, tmp);
++ if (rv == 0){
++ sprintf (err,"Can't create %s %s",
++ create_dir ? "directory" : "mailbox", mailbox);
++ mm_log (err,ERROR);
++ }
++ return rv ? 1L : 0L;
++ }
++
++ #define MAXTRY 10000
++ void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt)
++ {
++ char oldfile[MAILTMPLEN],newfile[MAILTMPLEN],fn[MAILTMPLEN];
++ char tmp[MAILTMPLEN];
++ char *s;
++ int ren, try = 0;
++
++ LOCAL->dirty = 0;
++ if (elt->valid){
++ for (try = 1; try > 0 && try < MAXTRY; try++){
++ /* build the new filename */
++ sprintf (oldfile,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ fn[0] = '\0';
++ if ((ren = maildir_message_exists(stream, MDFILE(elt), fn)) == 0){
++ errno = ENOENT;
++ try = MAXTRY;
++ }
++ if (*fn) /* new oldfile! */
++ sprintf (oldfile,"%s/%s",LOCAL->curdir,fn);
++ if ((s = strchr (MDFILE(elt), FLAGSEP))) *s = '\0';
++ sprintf (fn,"%s%s%s%s%s%s%s", MDFILE(elt), MDSEP(2),
++ MDFLAG(Draft, elt->draft), MDFLAG(Flagged, elt->flagged),
++ MDFLAG(Replied, elt->answered), MDFLAG(Seen, elt->seen),
++ MDFLAG(Trashed, elt->deleted));
++ sprintf (newfile,"%s/%s",LOCAL->curdir,fn);
++ if (ren != 0 && rename (oldfile,newfile) >= 0)
++ try = -1;
++ }
++
++ if (try > 0){
++ sprintf(oldfile,"Unable to write flags to disk: %s",
++ errno == ENOENT ? "message is gone!" : strerror (errno));
++ mm_log(oldfile,ERROR);
++ LOCAL->dirty = 1;
++ return;
++ }
++ maildir_free_file_only ((void **) &elt->maildirp);
++ MDFILE(elt) = cpystr (fn);
++ }
++ }
++
++ void maildir_expunge (MAILSTREAM *stream)
++ {
++ MESSAGECACHE *elt;
++ unsigned long i;
++ unsigned long n = 0;
++ unsigned long nmsgs = stream->nmsgs;
++ unsigned long recent = stream->recent;
++ char tmp[MAILTMPLEN];
++
++ mm_critical (stream); /* go critical */
++ for (i = 1; i <= stream->nmsgs;)
++ if ((elt = mail_elt (stream,i))->deleted){
++ sprintf (tmp,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ if (unlink (tmp)) {/* try to delete the message */
++ sprintf (tmp,"Expunge of message %ld failed, aborted: %s",i,
++ strerror (errno));
++ if (!stream->silent)
++ mm_log (tmp,WARN);
++ break;
++ }
++ /* free the cached filename */
++ if (elt->maildirp)
++ maildir_free_file ((void **) &elt->maildirp);
++
++ if (elt->recent) --recent;/* if recent, note one less recent message */
++ mail_expunged (stream,i); /* notify upper levels */
++ n++; /* count up one more expunged message */
++ }
++ else i++;
++ if (n) { /* output the news if any expunged */
++ sprintf (tmp,"Expunged %ld messages",n);
++ if (!stream->silent)
++ mm_log (tmp,(long) NIL);
++ }
++ else
++ if (!stream->silent)
++ mm_log ("No messages deleted, so no update needed",(long) NIL);
++ mm_nocritical (stream); /* release critical */
++ /* notify upper level of new mailbox size */
++ mail_exists (stream,stream->nmsgs);
++ mail_recent (stream,recent);
++ }
++
++ long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
++ {
++ STRING st;
++ MESSAGECACHE *elt;
++ unsigned long len;
++ int fd;
++ long i, length;
++ struct stat sbuf;
++ char tmp[MAILTMPLEN], flags[MAILTMPLEN], path[MAILTMPLEN], *s, *b;
++ /* copy the messages */
++ if ((options & CP_UID) ? mail_uid_sequence (stream, sequence) :
++ mail_sequence (stream,sequence))
++ for (i = 1; i <= stream->nmsgs; i++)
++ if ((elt = mail_elt (stream,i))->sequence){
++ sprintf (path,"%s/%s",LOCAL->curdir, MDFILE(elt));
++ if (((fd = open (path,O_RDONLY,NIL)) < 0)
++ ||((!elt->rfc822_size &&
++ ((stat(path, &sbuf) < 0) || !S_ISREG (sbuf.st_mode)))))
++ return NIL;
++ if(!elt->rfc822_size)
++ MDSIZE(elt) = sbuf.st_size;
++ s = (char *) fs_get(MDSIZE(elt) + 1);
++ read (fd,s,MDSIZE(elt));
++ s[MDSIZE(elt)] = '\0';
++ close (fd);
++ len = strcrlfcpy (&LOCAL->buf,&LOCAL->buflen, s, MDSIZE(elt));
++ INIT (&st,mail_string, LOCAL->buf, len);
++ elt->rfc822_size = len;
++ fs_give ((void **)&s);
++
++ flags[0] = flags[1] = '\0';
++ if (elt->seen) strcat (flags," \\Seen");
++ if (elt->draft) strcat (flags," \\Draft");
++ if (elt->deleted) strcat (flags," \\Deleted");
++ if (elt->flagged) strcat (flags," \\Flagged");
++ if (elt->answered) strcat (flags," \\Answered");
++ flags[0] = '('; /* open list */
++ strcat (flags,")"); /* close list */
++ mail_date (tmp,elt); /* generate internal date */
++ if (!mail_append_full (NIL,mailbox,flags,tmp,&st))
++ return NIL;
++ if (options & CP_MOVE) elt->deleted = T;
++ }
++ return T; /* return success */
++ }
++
++ long maildir_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
++ {
++ int fd;
++ STRING *message;
++ char c,*s, *flags, *date;
++ char tmp[MAILTMPLEN],file[MAILTMPLEN],path1[MAILTMPLEN],path2[MAILTMPLEN];
++ MESSAGECACHE elt;
++ long i;
++ long size = 0;
++ long ret = LONGT;
++ unsigned long uf;
++ long f;
++ static unsigned int transact = 0;
++
++ if (!maildir_valid(mailbox)) {
++ sprintf (tmp,"Not a valid Maildir mailbox: %s",mailbox);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ if (!*mdlocaldomain)
++ md_domain_name(); /* get domain name for maildir files in mdlocaldomain now! */
++
++ if (!(*af) (stream,data,&flags,&date,&message)) return NIL;
++
++ mm_critical (stream); /* go critical */
++ do {
++ if (!SIZE (message)) { /* guard against zero-length */
++ mm_log ("Append of zero-length message",ERROR);
++ ret = NIL;
++ break;
++ }
++ if (date && !mail_parse_date(&elt,date)){
++ sprintf (tmp,"Bad date in append: %.80s",date);
++ mm_log (tmp,ERROR);
++ ret = NIL;
++ break;
++ }
++ f = mail_parse_flags (stream,flags,&uf);
++ /* build file name we will use */
++ sprintf (file,"%u.%d_%09u.%s%s%s%s%s%s",
++ time (0),getpid (),transact++,mdlocaldomain, f ? MDSEP(2) : "",
++ MDFLAG(Draft, f&fDRAFT), MDFLAG(Flagged, f&fFLAGGED),
++ MDFLAG(Replied, f&fANSWERED), MDFLAG(Seen, f&fSEEN));
++ /* build tmp file name */
++ if (maildir_file_path(mailbox, tmp))
++ MSGPATH(path1, tmp, file, Tmp);
++
++ if ((fd = open (path1,O_WRONLY|O_CREAT|O_EXCL,S_IREAD|S_IWRITE)) < 0) {
++ sprintf (tmp,"Can't open append mailbox: %s",strerror (errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ for (size = 0,i = SIZE (message),s = (char *) fs_get (i + 1); i; --i)
++ if ((c = SNX (message)) != '\015') s[size++] = c;
++ if ((write (fd,s,size) < 0) || fsync (fd)) {
++ unlink (path1); /* delete message */
++ sprintf (tmp,"Message append failed: %s",strerror (errno));
++ mm_log (tmp,ERROR);
++ ret = NIL;
++ }
++ fs_give ((void **) &s); /* flush the buffer */
++ close (fd); /* close the file */
++ /* build final filename to use */
++ if (maildir_file_path(mailbox, tmp))
++ MSGPATH(path2, tmp, file, New);
++ if (link (path1,path2) < 0) {
++ sprintf (tmp,"Message append failed: %s",strerror (errno));
++ mm_log (tmp,ERROR);
++ ret = NIL;
++ }
++ unlink (path1);
++
++ if (ret)
++ if (!(*af) (stream,data,&flags,&date,&message)) ret = NIL;
++
++ } while (ret && message); /* write the data */
++
++ mm_nocritical (stream); /* release critical */
++ return ret;
++ }
++
++ long maildir_delete (MAILSTREAM *stream,char *mailbox)
++ {
++ DIR *dirp;
++ struct direct *d;
++ int i, remove_dir = 0, mddir = 0, rv, error = 0;
++ char tmp[MAILTMPLEN],tmp2[MAILTMPLEN], realname[MAILTMPLEN];
++ struct stat sbuf;
++ char *mdpath = maildir_parameters(GET_INBOXPATH,NIL);
++ int courier = IS_COURIER(mailbox);
++
++ if (mailbox[strlen(mailbox) - 1] == MDSEPARATOR(courier)){
++ remove_dir++;
++ mailbox[strlen(mailbox) -1] = '\0';
++ }
++
++ if (!maildir_valid(mailbox)){
++ maildir_file_path(mailbox, tmp);
++ if (stat(tmp, &sbuf) < 0 || !S_ISDIR(sbuf.st_mode)){
++ sprintf(tmp,"Can not remove %s", mailbox);
++ error++;
++ }
++ }
++
++ if (!error && remove_dir && !maildir_dir_is_empty(mailbox)){
++ sprintf(tmp,"Can not remove directory %s/: directory not empty", mailbox);
++ error++;
++ }
++
++ if(error){
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ maildir_close(stream,0); /* even if stream was NULL */
++
++ maildir_file_path(mailbox, realname);
++
++ if (remove_dir){
++ sprintf(tmp,"%s/%s", realname, MDDIR);
++ if ((rv = stat (tmp,&sbuf)) == 0 && S_ISREG(sbuf.st_mode))
++ rv = unlink(tmp);
++ else if (errno == ENOENT)
++ rv = 0;
++ if (rv != 0){
++ sprintf(tmp,"Can not remove %s/%s: %s", tmp2, MDDIR, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ if (!maildir_valid(realname) && rmdir(realname) != 0){
++ sprintf(tmp,"Can not remove %s/: %s", mailbox, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ return T;
++ }
++ /* else remove just the folder. Remove all hidden files, except MDDIR */
++ for (i = Cur; i != EndDir; i++){
++ MDFLD(tmp, realname, i);
++
++ if (!(dirp = opendir (tmp))){
++ sprintf(tmp,"Can not read %s/: %s", mailbox, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ while (d = readdir(dirp)){
++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")){
++ sprintf(tmp2,"%s/%s", tmp, d->d_name);
++ if (unlink(tmp2) != 0){
++ sprintf(tmp2,"Can not remove %s: %s", mailbox, strerror(errno));
++ mm_log (tmp2,ERROR);
++ return NIL;
++ }
++ }
++ }
++ closedir(dirp);
++ if (rmdir(tmp) != 0){
++ sprintf(tmp,"Can not remove %s: %s", mailbox, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ }
++ /*
++ * ok we have removed all subdirectories of the folder mailbox, Remove the
++ * hidden files.
++ */
++
++ if (!(dirp = opendir (realname))){
++ sprintf(tmp,"Can not read %s/: %s", realname, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ while (d = readdir(dirp)){
++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")
++ && !strcmp(d->d_name, MDDIR)){
++ sprintf(tmp,"%s/%s", realname, d->d_name);
++ mddir++;
++ if (unlink(tmp) != 0)
++ error++;
++ }
++ }
++ closedir(dirp);
++ if (error ||
++ (maildir_dir_is_empty(mailbox) && mddir == 0 && rmdir(realname) < 0)){
++ sprintf(tmp,"Can not remove folder %s: %s", mailbox, strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ return T;
++ }
++
++ long maildir_rename (MAILSTREAM *stream, char *old, char *new)
++ {
++ struct direct **names = NIL;
++ struct stat sbuf;
++ char pathname[MAILTMPLEN], dir[MAILTMPLEN], curdir[MAILTMPLEN];
++ char tmp[MAILTMPLEN],tmpnew[MAILTMPLEN], realold[MAILTMPLEN];
++ char realnew[MAILTMPLEN],realpat[MAILTMPLEN], realname[MAILTMPLEN];
++ char *pat, *endold, c;
++ char *maildirpath = maildir_parameters(GET_INBOXPATH, NIL);
++ int courier = IS_COURIER(old) && IS_COURIER(new);
++ int scand, i, j, rv = T;
++ unsigned long ndir;
++ COURIER_S *cdir;
++
++ if((IS_COURIER(old) || IS_COURIER(new)) && !courier){
++ sprintf (tmp,"Can't rename mailbox %s to %s",old, new);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ if (!maildir_valid(old)){
++ sprintf (tmp,"Can't rename mailbox %s: folder not in maildir format",old);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ maildir_file_path(old, realold);
++ if (!maildir_valid_name(new) && new[0] == '#'){
++ sprintf (tmp,"Can't rename mailbox %s: folder not in maildir format",new);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ maildir_file_path(new, realnew);
++ if (access(tmpnew,F_OK) == 0){ /* new mailbox name must not exist */
++ sprintf (tmp,"Can't rename to mailbox %s: destination already exists",new);
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++
++ if(!courier){
++ if (rename (realold,realnew)){ /* try to rename the directory */
++ sprintf (tmp,"Can't rename mailbox %s to %s: %s",old, new,
++ strerror(errno));
++ mm_log (tmp,ERROR);
++ return NIL;
++ }
++ return T; /* return success */
++ }
++
++ cdir = courier_list_dir(old);
++ for (i = 0; cdir && i < cdir->total; i++){
++ if(strstr(cdir->data[i]->name, old)){
++ sprintf(tmp,"%s%s", new, cdir->data[i]->name+strlen(old));
++ maildir_file_path(cdir->data[i]->name, realold);
++ maildir_file_path(tmp, realnew);
++ if (rename (realold,realnew)){
++ sprintf (tmp,"Can't rename mailbox %s to %s: %s",old, new,
++ strerror(errno));
++ mm_log (tmp,ERROR);
++ rv = NIL;
++ }
++ }
++ }
++ courier_free_cdir(&cdir);
++ return rv;
++ }
++
++ long maildir_sub (MAILSTREAM *stream,char *mailbox)
++ {
++ return sm_subscribe (mailbox);
++ }
++
++ long maildir_unsub (MAILSTREAM *stream,char *mailbox)
++ {
++ return sm_unsubscribe (mailbox);
++ }
++
++ void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat)
++ {
++ void *sdb = NIL;
++ char *s, test[MAILTMPLEN];
++ /* get canonical form of name */
++ if (maildir_canonicalize (test,ref,pat) && (s = sm_read (&sdb))) {
++ do if (pmatch_full (s,test,'/')) mm_lsub (stream,'/',s,NIL);
++ while (s = sm_read (&sdb)); /* until no more subscriptions */
++ }
++ }
++
++ long maildir_canonicalize (char *pattern,char *ref,char *pat)
++ {
++ if (ref && *ref) { /* have a reference */
++ strcpy (pattern,ref); /* copy reference to pattern */
++ /* # overrides mailbox field in reference */
++ if (*pat == '#') strcpy (pattern,pat);
++ /* pattern starts, reference ends, with / */
++ else if ((*pat == '/') && (pattern[strlen (pattern) - 1] == '/'))
++ strcat (pattern,pat + 1); /* append, omitting one of the period */
++
++ else strcat (pattern,pat); /* anything else is just appended */
++ }
++ else strcpy (pattern,pat); /* just have basic name */
++ return (maildir_valid_name(pattern));
++ }
++
++ void maildir_list_work (MAILSTREAM *stream,char *dir,char *pat,long level)
++ {
++ DIR *dp;
++ struct direct *d;
++ struct stat sbuf;
++ char *cp,*np, curdir[MAILTMPLEN],name[MAILTMPLEN], tmp[MAILTMPLEN];
++ int i;
++ char *maildirpath = maildir_parameters(GET_INBOXPATH, NIL);
++
++ sprintf(curdir,"%s/%s/", myhomedir(), dir ? dir :
++ (maildirpath ? maildirpath : "Maildir"));
++ if (dp = opendir (curdir)){
++ if (dir) sprintf (name,"%s%s/",MDPREFIX(CCLIENT),dir);
++ else strcpy (name,MDPREFIX(CCLIENT));
++
++ if (level == 0 && name && pmatch_full (name, pat, '/'))
++ mm_list (stream,'/', name, LATT_NOSELECT);
++
++ while (d = readdir (dp))
++ if(strcmp(d->d_name, ".") && strcmp(d->d_name,"..")
++ && strcmp(d->d_name, MDNAME(Cur))
++ && strcmp(d->d_name, MDNAME(Tmp))
++ && strcmp(d->d_name, MDNAME(New))){
++
++ if (dir) sprintf (tmp,"%s%s", name,d->d_name);
++ else strcpy(tmp, d->d_name);
++
++ if(pmatch_full (tmp, pat,'/')){
++ sprintf(tmp,"%s/%s/%s", myhomedir(), dir ? dir :
++ (maildirpath ? maildirpath : "Maildir"), d->d_name);
++ if(stat (tmp,&sbuf) == 0
++ && ((sbuf.st_mode & S_IFMT) == S_IFDIR)){
++ if (dir) sprintf (tmp,"%s%s", name,d->d_name);
++ else strcpy(tmp, d->d_name);
++ i = maildir_valid(tmp)
++ ? (maildir_contains_folder(dir, d->d_name)
++ ? LATT_HASCHILDREN
++ : (maildir_is_dir(dir, d->d_name)
++ ? LATT_HASNOCHILDREN : LATT_NOINFERIORS))
++ : LATT_NOSELECT;
++ i += maildir_any_new_msgs(tmp)
++ ? LATT_MARKED : LATT_UNMARKED;
++ mm_list (stream,'/',tmp, i);
++ strcat (tmp, "/");
++ if(dmatch (tmp, pat,'/') &&
++ (level < (long) mail_parameters (NIL,GET_LISTMAXLEVEL,NIL))){
++ sprintf(tmp,"%s/%s",dir,d->d_name);
++ maildir_list_work (stream,tmp,pat,level+1);
++ }
++ }
++ }
++ }
++ }
++ closedir (dp);
++ }
++
++ void courier_list_work (MAILSTREAM *stream, char *dir, char *pat, long level)
++ {
++ unsigned long ndir;
++ struct direct **names = NIL;
++ struct stat sbuf;
++ char c, d, curdir[MAILTMPLEN],name[MAILTMPLEN], tmp[MAILTMPLEN];
++ char realname[MAILTMPLEN], realpat[MAILTMPLEN] = {'\0'}, pathname[MAILTMPLEN];
++ int i, j, scand;
++ long style = (long) maildir_parameters(GET_COURIERSTYLE, NIL);
++ char *maildirpath = maildir_parameters(GET_INBOXPATH, NIL);
++ COURIER_S *cdir;
++
++ j = strlen(pat) - 1;
++ maildir_file_path(pat, realpat);
++ c = pat[j];
++ pat[j] = '\0';
++ realname[0] = '\0';
++ if(dir)
++ maildir_file_path(dir, realname);
++ sprintf(curdir,"%s%s%s/%s", dir ? "" : myhomedir(), dir ? "" : "/",
++ dir ? realname : (maildirpath ? maildirpath : "Maildir"),
++ dir ? "" : ".");
++
++ sprintf(tmp, "%s%s/.", MDPREFIX(COURIER), dir ? dir :
++ (maildirpath ? maildirpath : "Maildir"));
++ if (level == 0 && tmp && pmatch_full (tmp, realpat, '.'))
++ mm_list (stream,'.', tmp, LATT_NOSELECT);
++
++ cdir = courier_list_dir(pat);
++ pat[j] = c;
++ for (i = 0; cdir && i < cdir->total; i++){
++ if(pmatch_full (cdir->data[i]->name, pat, '.')){
++ sprintf(tmp, "%s.", cdir->data[i]->name);
++ if(maildir_valid(cdir->data[i]->name)){
++ if(courier_search_list(cdir->data, tmp, 0, cdir->total - 1))
++ cdir->data[i]->attribute = LATT_HASCHILDREN;
++ else
++ cdir->data[i]->attribute = style == COURIER
++ ? LATT_HASNOCHILDREN : LATT_NOINFERIORS;
++ }
++ else
++ cdir->data[i]->attribute = LATT_NOSELECT;
++ cdir->data[i]->attribute += maildir_any_new_msgs(cdir->data[i]->name)
++ ? LATT_MARKED : LATT_UNMARKED;
++ mm_list (stream,'.',cdir->data[i]->name, cdir->data[i]->attribute);
++ }
++ }
++ courier_free_cdir(&cdir);
++ }
++
++ int
++ same_maildir_file(char *name1, char *name2)
++ {
++ char tmp1[MAILTMPLEN], tmp2[MAILTMPLEN];
++ char *s;
++
++ strcpy(tmp1, name1 ? name1 : "");
++ strcpy(tmp2, name2 ? name2 : "");
++ if (s = strchr(tmp1, FLAGSEP))
++ *s = '\0';
++ if (s = strchr(tmp1, SIZESEP))
++ *s = '\0';
++ if (s = strchr(tmp2, FLAGSEP))
++ *s = '\0';
++ if (s = strchr(tmp2, SIZESEP))
++ *s = '\0';
++
++ return !strcmp(tmp1, tmp2);
++ }
++
++
++ int comp_maildir_file(char *name1, char *name2)
++ {
++ unsigned long t1, t2;
++ int i;
++
++ if (!(name1 && *name1))
++ return name2 && *name2 ? (*name2 == FLAGSEP ? 0 : -1) : 0;
++
++ if (!(name2 && *name2))
++ return name1 && *name1 ? (*name1 == FLAGSEP ? 0 : 1) : 0;
++
++ if(!strcmp(name1,name2))
++ return 0;
++
++ t1 = strtoul(name1, NULL, 10);
++ t2 = strtoul(name2, NULL, 10);
++
++ if (t1 < t2)
++ return -1;
++
++ if (t1 > t2)
++ return 1;
++
++ i = strchr(name1,'.') - name1 + 1;
++ return (strcmp (name1 + i, name2 + i));
++ }
++
++ void
++ maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t)
++ {
++ char tmp[MAILTMPLEN], *b;
++ int offset = 0;
++
++ if(d && f && r && s && t)
++ *d = *f = *r = *s = *t = 0;
++ else
++ return; /* can not call this function with null arguments */
++
++ strcpy(tmp,name);
++ while (b = strchr(tmp+offset, FLAGSEP)){
++ char flag,last;
++ int i,k;
++ if (!++b) break;
++ switch (*b){
++ case '1':
++ case '2':
++ case '3': flag = *b; b += 2;
++ for (k = 0; b[k] && b[k] != FLAGSEP && b[k] != ','; k++);
++ last = b[k];
++ b[k] = '\0';
++ if (flag == '2' || flag == '3'){
++ *d = strchr (b, MDFLAGC(Draft)) ? T : NIL;
++ *f = strchr (b, MDFLAGC(Flagged)) ? T : NIL;
++ *r = strchr (b, MDFLAGC(Replied)) ? T : NIL;
++ *s = strchr (b, MDFLAGC(Seen)) ? T : NIL;
++ *t = strchr (b, MDFLAGC(Trashed)) ? T : NIL;
++ }
++ b[k] = last;
++ b += k;
++ for (; tmp[offset] && tmp[offset] != FLAGSEP; offset++);
++ offset++;
++ break;
++ default: break; /* Should we crash?... Nahhh */
++ }
++ }
++ }
++
++ int
++ maildir_message_in_list(char *msgname, struct direct **names,
++ unsigned long bottom, unsigned long top, unsigned long *pos)
++ {
++ unsigned long middle = (bottom + top)/2;
++ int test;
++
++ if (!msgname)
++ return NIL;
++
++ if (pos) *pos = middle;
++
++ if (same_maildir_file(msgname, names[middle]->d_name))
++ return T;
++
++ if (middle == bottom){ /* 0 <= 0 < 1 */
++ int rv = NIL;
++ if (same_maildir_file(msgname, names[middle]->d_name)){
++ rv = T;
++ if (pos) *pos = middle;
++ }
++ else
++ if (same_maildir_file(msgname, names[top]->d_name)){
++ rv = T;
++ if (pos) *pos = top;
++ }
++ return rv;
++ }
++
++ test = comp_maildir_file(msgname, names[middle]->d_name);
++
++ if (top <= bottom)
++ return test ? NIL : T;
++
++ if (test < 0 ) /* bottom < msgname < middle */
++ return maildir_message_in_list(msgname, names, bottom, middle, pos);
++ else if (test > 0) /* middle < msgname < top */
++ return maildir_message_in_list(msgname, names, middle, top, pos);
++ else return T;
++ }
++
++ void
++ maildir_abort(MAILSTREAM *stream)
++ {
++ if (LOCAL){
++ if (LOCAL->dir) fs_give ((void **) &LOCAL->dir);
++ if (LOCAL->curdir) fs_give ((void **) &LOCAL->curdir);
++ if (LOCAL->buf) fs_give ((void **) &LOCAL->buf);
++ fs_give ((void **) &stream->local);
++ }
++ if (mdfpath) fs_give((void **)&mdfpath);
++ stream->dtb = NIL;
++ }
++
++ int
++ maildir_contains_folder(char *dirname, char *name)
++ {
++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN];
++ int rv = 0;
++ DIR *dir;
++ struct direct *d;
++ struct stat sbuf;
++ char *maildirpath = maildir_parameters(GET_INBOXPATH, NIL);
++
++ sprintf(tmp2,"%s/%s/%s", myhomedir(), dirname ? dirname
++ : (maildirpath ? maildirpath : "Maildir"), name);
++
++ if (!(dir = opendir (tmp2)))
++ return NIL;
++
++ while (d = readdir(dir)){
++ if (strcmp(d->d_name, ".") && strcmp(d->d_name,"..")
++ && strcmp(d->d_name, MDNAME(Cur))
++ && strcmp(d->d_name, MDNAME(Tmp))
++ && strcmp(d->d_name, MDNAME(New))){
++
++ sprintf(tmp,"%s/%s", tmp2, d->d_name);
++ if(maildir_valid(tmp)){
++ rv++;
++ break;
++ }
++ }
++ }
++ closedir(dir);
++ return rv;
++ }
++
++ int
++ maildir_is_dir(char *dirname, char *name)
++ {
++ char tmp[MAILTMPLEN];
++ struct stat sbuf;
++ char *maildirpath = maildir_parameters(GET_INBOXPATH, NIL);
++
++ sprintf(tmp,"%s/%s/%s/%s", myhomedir(), dirname ? dirname
++ : (maildirpath ? maildirpath : "Maildir"), name, MDDIR);
++
++ return (stat(tmp, &sbuf) == 0 && S_ISREG (sbuf.st_mode)) ? 1 : 0;
++ }
++
++ int
++ maildir_dir_is_empty(char *mailbox)
++ {
++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN];
++ int rv = 1;
++ DIR *dir;
++ struct direct *d;
++ struct stat sbuf;
++
++ maildir_file_path(mailbox, tmp2);
++
++ if (!(dir = opendir (tmp2)))
++ return rv;
++
++ while (d = readdir(dir)){
++ sprintf(tmp,"%s/%s", tmp2, d->d_name);
++ if (strcmp(d->d_name, ".")
++ && strcmp(d->d_name,"..")
++ && strcmp(d->d_name, MDNAME(Cur))
++ && strcmp(d->d_name, MDNAME(Tmp))
++ && strcmp(d->d_name, MDNAME(New))
++ && strcmp(d->d_name, MDDIR)
++ && strcmp(d->d_name, MDUIDVALIDITY)
++ && !(d->d_name[0] == '.'
++ && stat (tmp,&sbuf) == 0
++ && S_ISREG(sbuf.st_mode))){
++ rv = 0;
++ break;
++ }
++ }
++ closedir(dir);
++ return rv;
++ }
++
++ void
++ maildir_get_file (MAILDIRFILE **mdfile)
++ {
++ MAILDIRFILE *md;
++
++ md = (MAILDIRFILE *) fs_get(sizeof(MAILDIRFILE));
++ memset(md, 0, sizeof(MAILDIRFILE));
++ *mdfile = md;
++ }
++
++ void
++ maildir_free_file (void **mdfile)
++ {
++ MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL;
++
++ if (md){
++ if (md->name) fs_give((void **)&md->name);
++ fs_give((void **)&md);
++ }
++ }
++
++ void
++ maildir_free_file_only (void **mdfile)
++ {
++ MAILDIRFILE *md = (mdfile && *mdfile) ? (MAILDIRFILE *) *mdfile : NULL;
++
++ if (md && md->name)
++ fs_give((void **)&md->name);
++ }
++
++ int
++ maildir_any_new_msgs(char *mailbox)
++ {
++ char tmp[MAILTMPLEN];
++ int rv = NIL;
++ DIR *dir;
++ struct direct *d;
++ struct stat sbuf;
++
++ MDFLD(tmp, mailbox, New);
++
++ if (!(dir = opendir (tmp)))
++ return rv;
++
++ while (d = readdir(dir)){
++ if (d->d_name[0] == '.')
++ continue;
++ rv = T;
++ break;
++ }
++ closedir(dir);
++ return rv;
++ }
++
++
++ void
++ maildir_get_date(MAILSTREAM *stream, unsigned long msgno, DirNamesType dirtype)
++ {
++ MESSAGECACHE *elt;
++ struct tm *tm;
++ unsigned long t1;
++
++ elt = mail_elt (stream,msgno);
++ if ((t1 = strtoul(MDFILE(elt), NULL, 10)) > 0){
++ tm = gmtime (&t1);
++ elt->day = tm->tm_mday; elt->month = tm->tm_mon + 1;
++ elt->year = tm->tm_year + 1900 - BASEYEAR;
++ elt->hours = tm->tm_hour; elt->minutes = tm->tm_min;
++ elt->seconds = tm->tm_sec;
++ elt->zhours = 0; elt->zminutes = 0;
++ }
++ }
++
++ /* Support for Courier Style directories
++
++ When this code is complete there will be two types of support, which
++ will be configurable. The problem is the following: In Courier style
++ folder structure, a "folder" may have a subfolder called
++ "folder.subfolder", which is not natural in the file system in the
++ sense that I can not stat for "folder.subfolder" wihtout knowing what
++ "subfolder" is. It needs to be guessed. Because of this I need to look
++ in the list of folders if there is a folder with a name
++ "folder.subfolder", before I can say if the folder is dual or not. One
++ can avoid this annoyance if one ignores the problem by declaring that
++ every folder is dual. I will however code as the default the more
++ complicated idea of scaning the containing directory each time it is
++ modified and search for subfolders, and list the entries it found.
++ */
++
++ int courier_dir_select (struct direct *name)
++ {
++ return name->d_name[0] == '.' && (strlen(name->d_name) > 2
++ || (strlen(name->d_name) == 2 && name->d_name[1] != '.'));
++ }
++
++ int courier_dir_sort (const void *d1, const void *d2)
++ {
++ const struct direct **e1, **e2;
++
++ e1 = (const struct direct **)d1;
++ e2 = (const struct direct **)d2;
++
++ return strcmp((char*)(*e1)->d_name, (char *)(*e2)->d_name);
++ }
++
++ void courier_free_cdir (COURIER_S **cdir)
++ {
++ int i;
++
++ if (!*cdir)
++ return;
++
++ if ((*cdir)->path) fs_give((void **)&((*cdir)->path));
++ for (i = 0; i < (*cdir)->total; i++)
++ if((*cdir)->data[i]->name) fs_give((void **)&((*cdir)->data[i]->name));
++ fs_give((void **)&((*cdir)->data));
++ fs_give((void **)&(*cdir));
++ }
++
++ COURIER_S *courier_get_cdir (int total)
++ {
++ COURIER_S *cdir;
++
++ cdir = (COURIER_S *)fs_get(sizeof(COURIER_S));
++ memset(cdir, 0, sizeof(COURIER_S));
++ cdir->data = (COURIERLOCAL **) fs_get(total*sizeof(COURIERLOCAL *));
++ cdir->total = total;
++ return cdir;
++ }
++
++ int courier_search_list(COURIERLOCAL **data, char *name, int first, int last)
++ {
++ int try = (first + last)/2;
++
++ if(!strstr(data[try]->name, name)){
++ if(first == try) /* first == last || first + 1 == last */
++ return strstr(data[last]->name, name) ? 1 : 0;
++ if(strcmp(data[try]->name, name) < 0) /*data[try] < name < data[end] */
++ return courier_search_list(data, name, try, last);
++ else /* data[begin] < name < data[try] */
++ return courier_search_list(data, name, first, try);
++ }
++ return 1;
++ }
++
++ /* Lists all directories that are subdirectories of a given directory */
++
++ COURIER_S *courier_list_dir(char *curdir)
++ {
++ struct direct **names = NIL;
++ struct stat sbuf;
++ unsigned long ndir;
++ COURIER_S *cdir;
++ char tmp[MAILTMPLEN], tmp2[MAILTMPLEN], pathname[MAILTMPLEN],
++ realname[MAILTMPLEN];
++ char *maildirpath = maildir_parameters(GET_INBOXPATH, NIL);
++ int i, j, scand;
++
++ /* There are two cases, either curdir is
++ #mc/INBOX. #mc/INBOX.foo
++ or
++ #mc/Maildir/. #mc/Maildir/.foo
++ */
++ strcpy(tmp,curdir + 4);
++ if(!strncmp(ucase(tmp), "INBOX", 5))
++ strcpy(tmp, "#mc/INBOX.");
++ else{
++ strcpy(tmp, curdir);
++ for (i = strlen(tmp) - 1; tmp[i] && tmp[i] != '/'; i--);
++ tmp[i+2] = '\0'; /* keep the last "." intact */
++ }
++ maildir_file_path(tmp, realname);
++ maildir_scandir (realname, &names, &ndir, &scand, COURIER);
++
++ if (scand > 0){
++ cdir = courier_get_cdir(ndir);
++ cdir->path = cpystr(realname);
++ for(i = 0, j = 0; i < ndir; i++){
++ sprintf(tmp2,"%s%s", tmp, names[i]->d_name+1);
++ sprintf(pathname,"%s%s", realname, names[i]->d_name);
++ if(stat(pathname, &sbuf) == 0 && S_ISDIR(sbuf.st_mode)){
++ cdir->data[j] = (COURIERLOCAL *) fs_get(sizeof(COURIERLOCAL));
++ cdir->data[j++]->name = cpystr(tmp2);
++ }
++ fs_give((void **)&names[i]);
++ }
++ if(names)
++ fs_give((void **) &names);
++ cdir->total = j;
++ }
++ return cdir;
++ }
+diff -rc pine4.63/imap/src/osdep/unix/maildir.h pine4.63.I.USE/imap/src/osdep/unix/maildir.h
+*** pine4.63/imap/src/osdep/unix/maildir.h Thu May 19 19:59:15 2005
+--- pine4.63.I.USE/imap/src/osdep/unix/maildir.h Thu May 19 19:57:24 2005
+***************
+*** 0 ****
+--- 1,185 ----
++ /*
++ * A few definitions that try to make this module portable to other
++ * platforms (e.g. Cygwin). This module is based on the information from
++ * http://cr.yp.to/proto/maildir.html
++ */
++
++ /* First we deal with the separator character */
++ #ifndef FLAGSEP
++ #define FLAGSEP ':'
++ #endif
++ #define SIZESEP ','
++
++ #define MDUIDVALIDITY ".uidvalidity" /* support for old maildirs */
++ #define MDDIR ".mdir" /* this folder is a directory */
++
++ const char sep1[] = {FLAGSEP, '1', ',', '\0'}; /* experimental semantics*/
++ const char sep2[] = {FLAGSEP, '2', ',', '\0'}; /* Flags Information */
++ const char sep3[] = {FLAGSEP, '3', ',', '\0'}; /* Grrrr.... */
++
++ const char *sep[] = { sep1, sep2, sep3, NULL};
++
++ #define MDSEP(i) sep[((i) - 1)]
++
++ /* Now we deal with flags. Woohoo! */
++ typedef enum {Draft, Flagged, Passed, Replied, Seen, Trashed,
++ EmptyFlag, EndFlags} MdFlagNamesType;
++ const int mdimapflags[] = {Draft, Flagged, Replied, Seen, Trashed, EmptyFlag, EndFlags};
++ const int mdkwdflags[] = {Passed, EmptyFlag, EndFlags};
++
++ /* this array lists the codes for mdflgnms (maildir flag names) above */
++ const char *mdflags[] = { "D", "F", "P", "R", "S", "T", "", NULL};
++ /* and as characters too */
++ const char cmdflags[] = { 'D', 'F', 'P', 'R', 'S', 'T', '0', '\0'};
++
++ /* MDFLAG(Seen, elt->seen) */
++ #define MDFLAG(i,j) mdflags[j ? (i) : EmptyFlag]
++ /* MDFLAGC(Seen) */
++ #define MDFLAGC(i) cmdflags[(i)]
++
++ /* Now we deal with the directory structure */
++ typedef enum {Cur, Tmp, New, EndDir} DirNamesType;
++ char *mdstruct[] = {"cur", "tmp", "new", NULL};
++ #define MDNAME(i) mdstruct[(i)]
++ #define MDFLD(tmp, dir, i) sprintf((tmp),"%s/%s", (dir), mdstruct[(i)])
++ #define MSGPATH(tmp, dir, msg,i) sprintf((tmp),"%s/%s/%s", (dir), mdstruct[(i)],(msg))
++
++ /* Support of Courier Structure */
++ #define CCLIENT 0
++ #define COURIER 1
++ #define IS_CCLIENT(t) \
++ (((t) && (t)[0] == '#' && ((t)[1] == 'm' || (t)[1] == 'M')\
++ && ((t)[2] == 'd' || (t)[2] == 'D')\
++ && (t)[3] == '/' && (t)[4] != '\0') ? 1 : 0)
++
++ #define IS_COURIER(t) \
++ (((t) && (t)[0] == '#' && ((t)[1] == 'm' || (t)[1] == 'M')\
++ && ((t)[2] == 'c' || (t)[2] == 'C')\
++ && (t)[3] == '/' && (t)[4] != '\0') ? 1 : 0)
++ #define MDPREFIX(s) ((s) ? "#mc/" : "#md/")
++ #define MDSEPARATOR(s) ((s) ? '.' : '/')
++
++
++ /* Now we deal with messages filenames */
++ char mdlocaldomain[MAILTMPLEN+1] = {'\0'};
++ static char *mdfpath = NULL;
++ static char *myMdInboxDir = NIL;/* Location of the Maildir INBOX */
++ static long CourierStyle = CCLIENT;
++
++ #define CHUNK 16384 /* from unix.h */
++
++ typedef struct courier_local {
++ char *name; /* name of directory/folder */
++ int attribute; /* attributes (children/marked/etc) */
++ } COURIERLOCAL;
++
++ typedef struct courier {
++ char *path; /* Path to collection */
++ time_t scantime; /* time at which information was generated */
++ int total; /* total number of elements in data */
++ COURIERLOCAL **data;
++ } COURIER_S;
++
++ /* In gdb this is the *(struct maildir_local *)stream->local structure */
++ typedef struct maildir_local {
++ unsigned int dirty : 1; /* diskcopy needs updating */
++ unsigned int courier : 1; /* It is Courier style file system */
++ int fd; /* fd of open message */
++ char *dir; /* mail directory name */
++ char *curdir; /* mail directory name/cur */
++ unsigned char *buf; /* temporary buffer */
++ unsigned long buflen; /* current size of temporary buffer */
++ time_t scantime; /* last time directory scanned */
++ } MAILDIRLOCAL;
++
++ /* Convenient access to local data */
++ #define LOCAL ((MAILDIRLOCAL *) stream->local)
++
++ typedef struct maildir_file_info {
++ char *name; /* name of the file */
++ unsigned long pos; /* place in list where this file is listed */
++ off_t size; /* size in bytes, on disk */
++ time_t atime; /* last access time */
++ time_t mtime; /* last modified time */
++ time_t ctime; /* last changed time */
++ } MAILDIRFILE;
++
++ #define MDFILE(F) (((MAILDIRFILE *)((F)->maildirp))->name)
++ #define MDPOS(F) (((MAILDIRFILE *)((F)->maildirp))->pos)
++ #define MDSIZE(F) (((MAILDIRFILE *)((F)->maildirp))->size)
++ #define MDATIME(F) (((MAILDIRFILE *)((F)->maildirp))->atime)
++ #define MDMTIME(F) (((MAILDIRFILE *)((F)->maildirp))->mtime)
++ #define MDCTIME(F) (((MAILDIRFILE *)((F)->maildirp))->ctime)
++
++ /* Function prototypes */
++
++ DRIVER *maildir_valid (char *name);
++ MAILSTREAM *maildir_open (MAILSTREAM *stream);
++ void maildir_close (MAILSTREAM *stream, long options);
++ long maildir_ping (MAILSTREAM *stream);
++ void maildir_check (MAILSTREAM *stream);
++ long maildir_text (MAILSTREAM *stream,unsigned long msgno,STRING *bs,long flags);
++ char *maildir_header (MAILSTREAM *stream,unsigned long msgno,
++ unsigned long *length, long flags);
++ void maildir_list (MAILSTREAM *stream,char *ref,char *pat);
++ void *maildir_parameters (long function,void *value);
++ int maildir_create_folder (char *mailbox);
++ long maildir_create (MAILSTREAM *stream,char *mailbox);
++ void maildir_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt); /*check */
++ void maildir_expunge (MAILSTREAM *stream);
++ long maildir_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options);
++ long maildir_append (MAILSTREAM *stream,char *mailbox, append_t af, void *data);
++ long maildir_delete (MAILSTREAM *stream,char *mailbox);
++ long maildir_rename (MAILSTREAM *stream,char *old,char *new);
++ long maildir_sub (MAILSTREAM *stream,char *mailbox);
++ long maildir_unsub (MAILSTREAM *stream,char *mailbox);
++ void maildir_lsub (MAILSTREAM *stream,char *ref,char *pat);
++ void courier_list (MAILSTREAM *stream,char *ref, char *pat);
++
++ /* utility functions */
++ void courier_realname (char *name, char *realname);
++ char *maildir_file (char *dst,char *name);
++ int maildir_select (struct direct *name);
++ int maildir_namesort (const void *d1, const void *d2);
++ int courier_dir_select (struct direct *name);
++ int courier_dir_sort (const void *d1, const void *d2);
++ long maildir_canonicalize (char *pattern,char *ref,char *pat);
++ void maildir_list_work (MAILSTREAM *stream,char *subdir,char *pat,long level);
++ void courier_list_work (MAILSTREAM *stream,char *subdir,char *pat,long level);
++ int maildir_file_path(char *name, char *tmp);
++ int maildir_valid_name (char *name);
++ int maildir_valid_dir (char *name);
++ int is_valid_maildir (char **name);
++ int maildir_message_exists(MAILSTREAM *stream,char *name, char *tmp);
++ void maildir_remove_root(char **name);
++ char *maildir_text_work (MAILSTREAM *stream,MESSAGECACHE *elt, unsigned long *length,long flags);
++ unsigned long maildir_parse_message(MAILSTREAM *stream, unsigned long msgno,
++ DirNamesType dirtype);
++ unsigned long maildir_scandir (char *name, struct direct ***flist,
++ unsigned long *nfiles, int *scand, int flag);
++ void maildir_parse_folder (MAILSTREAM *stream, int full);
++ void md_domain_name (void);
++ unsigned long maildir_parse_dir(MAILSTREAM *stream, unsigned long nmsgs,
++ DirNamesType dirtype, int full);
++ int same_maildir_file(char *name1, char *name2);
++ int comp_maildir_file(char *name1, char *name2);
++ int maildir_message_in_list(char *msgname, struct direct **names,
++ unsigned long bottom, unsigned long top, unsigned long *pos);
++ void maildir_getflag(char *name, int *d, int *f, int *r ,int *s, int *t);
++ int maildir_update_elt_maildirp(MAILSTREAM *stream, unsigned long msgno);
++ void maildir_abort (MAILSTREAM *stream);
++ int maildir_contains_folder(char *dirname, char *name);
++ int maildir_is_dir(char *dirname, char *name);
++ int maildir_dir_is_empty(char *mailbox);
++ int maildir_create_work (char *mailbox, int loop);
++ void maildir_get_file (MAILDIRFILE **mdfile);
++ void maildir_free_file (void **mdfile);
++ void maildir_free_file_only (void **mdfile);
++ int maildir_any_new_msgs(char *mailbox);
++ void maildir_get_date(MAILSTREAM *stream, unsigned long msgno, DirNamesType dirtype);
++ void maildir_fast (MAILSTREAM *stream,char *sequence,long flags);
++
++ void courier_free_cdir (COURIER_S **cdir);
++ COURIER_S *courier_get_cdir (int total);
++ int courier_search_list(COURIERLOCAL **data, char *name, int first, int last);
++ COURIER_S *courier_list_dir(char *curdir);
+diff -rc pine4.63/imap/src/osdep/unix/os_cyg.h pine4.63.I.USE/imap/src/osdep/unix/os_cyg.h
+*** pine4.63/imap/src/osdep/unix/os_cyg.h Mon Apr 19 08:22:07 2004
+--- pine4.63.I.USE/imap/src/osdep/unix/os_cyg.h Thu May 19 19:57:24 2005
+***************
+*** 39,44 ****
+--- 39,45 ----
+ #define setpgrp setpgid
+
+ #define SYSTEMUID 18 /* Cygwin returns this for SYSTEM */
++ #define FLAGSEP ';'
+ #define geteuid Geteuid
+ uid_t Geteuid (void);
+
+diff -rc pine4.63/pico/basic.c pine4.63.I.USE/pico/basic.c
+*** pine4.63/pico/basic.c Fri May 7 14:36:44 2004
+--- pine4.63.I.USE/pico/basic.c Thu May 19 19:57:33 2005
+***************
+*** 267,273 ****
+ int f, n; /* default Flag & Numeric argument */
+ {
+ int quoted, qlen;
+! char qstr[NLINE], qstr2[NLINE];
+
+ if (n < 0) /* the other way...*/
+ return(gotoeop(f, -n));
+--- 267,273 ----
+ int f, n; /* default Flag & Numeric argument */
+ {
+ int quoted, qlen;
+! char qstr[NLINE], qstr2[NLINE], ind_str[NLINE];
+
+ if (n < 0) /* the other way...*/
+ return(gotoeop(f, -n));
+***************
+*** 279,284 ****
+--- 279,295 ----
+ curwp->w_dotp = lback(curwp->w_dotp);
+ curwp->w_doto = 0;
+ }
++
++ if (indent_match((glo_quote_str || (Pmaster && Pmaster->quote_str))
++ ? (glo_quote_str ? glo_quote_str : Pmaster->quote_str)
++ : "",
++ curwp->w_dotp,ind_str, NLINE, 0)){
++ if (n){ /* look for another paragraph ? */
++ curwp->w_dotp = lback(curwp->w_dotp);
++ continue;
++ }
++ break;
++ }
+
+ /* scan line by line until we come to a line ending with
+ * a <NL><NL> or <NL><TAB> or <NL><SPACE>
+***************
+*** 288,294 ****
+ */
+ quoted = (glo_quote_str || (Pmaster && Pmaster->quote_str))
+ ? quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str,
+! curwp->w_dotp, qstr, NLINE) : 0;
+ qlen = quoted ? strlen(qstr) : 0;
+ while(lback(curwp->w_dotp) != curbp->b_linep
+ && llength(lback(curwp->w_dotp)) > qlen
+--- 299,305 ----
+ */
+ quoted = (glo_quote_str || (Pmaster && Pmaster->quote_str))
+ ? quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str,
+! curwp->w_dotp, qstr, NLINE, 0) : 0;
+ qlen = quoted ? strlen(qstr) : 0;
+ while(lback(curwp->w_dotp) != curbp->b_linep
+ && llength(lback(curwp->w_dotp)) > qlen
+***************
+*** 296,308 ****
+ ? (quoted == quote_match(glo_quote_str ? glo_quote_str
+ : Pmaster->quote_str,
+ lback(curwp->w_dotp),
+! qstr2, NLINE)
+ && !strcmp(qstr, qstr2))
+ : 1)
+ && lgetc(curwp->w_dotp, qlen).c != TAB
+ && lgetc(curwp->w_dotp, qlen).c != ' ')
+ curwp->w_dotp = lback(curwp->w_dotp);
+
+ if(n){
+ /* keep looking */
+ if(lback(curwp->w_dotp) == curbp->b_linep)
+--- 307,361 ----
+ ? (quoted == quote_match(glo_quote_str ? glo_quote_str
+ : Pmaster->quote_str,
+ lback(curwp->w_dotp),
+! qstr2, NLINE, 0)
+ && !strcmp(qstr, qstr2))
+ : 1)
++ && !indent_match((glo_quote_str
++ || (Pmaster && Pmaster->quote_str))
++ ? (glo_quote_str ? glo_quote_str : Pmaster->quote_str)
++ : "",
++ lback(curwp->w_dotp),ind_str, NLINE, 0)
+ && lgetc(curwp->w_dotp, qlen).c != TAB
+ && lgetc(curwp->w_dotp, qlen).c != ' ')
+ curwp->w_dotp = lback(curwp->w_dotp);
+
++ /*
++ * Ok, we made it here and we assume that we are at the begining
++ * of the paragraph. Let's double check this now. In order to do
++ * so we shell check if the first line was indented in a special
++ * way.
++ */
++ if(lback(curwp->w_dotp) == curbp->b_linep)
++ break;
++ else{
++ int indented, i, j;
++
++ /*
++ * for the following test we need to have the raw values,
++ * not the processed values
++ */
++ if (glo_quote_str || (Pmaster && Pmaster->quote_str)){
++ quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str,
++ curwp->w_dotp, qstr, NLINE, 1);
++ quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str,
++ lback(curwp->w_dotp), qstr2, NLINE, 1);
++ }
++ else
++ qstr[0] = qstr2[0] = '\0';
++ indented = indent_match((glo_quote_str || (Pmaster && Pmaster->quote_str))
++ ? (glo_quote_str ? glo_quote_str : Pmaster->quote_str)
++ : "",
++ lback(curwp->w_dotp),
++ ind_str, NLINE, 1);
++ if (strlenis(qstr2) + strlenis(ind_str) < strlenis(qstr))
++ indented = 0; /* Hack, so that it won't return one more line */
++ for (i= 0,j=0; qstr[i] && qstr2[i] && (qstr[i] == qstr2[i]);i++,j++);
++ for (; isspace(qstr2[i]); i++);
++ for (; isspace(qstr[j]); j++);
++ if (!qstr2[i] && !qstr[j] && indented)
++ curwp->w_dotp = lback(curwp->w_dotp);
++ }
++
+ if(n){
+ /* keep looking */
+ if(lback(curwp->w_dotp) == curbp->b_linep)
+***************
+*** 329,346 ****
+ return(TRUE);
+ }
+
+!
+ /*
+! * go forword to the end of the current paragraph
+ * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
+ * combination to delimit the begining of a paragraph
+ */
+ gotoeop(f, n)
+ int f, n; /* default Flag & Numeric argument */
+-
+ {
+! int quoted, qlen;
+! char qstr[NLINE], qstr2[NLINE];
+
+ if (n < 0) /* the other way...*/
+ return(gotobop(f, -n));
+--- 382,581 ----
+ return(TRUE);
+ }
+
+! GetAccent()
+! {
+! char c,d;
+! c = (char) GetKey();
+! if ((c == '?') || (c == '!')) {
+! d = c;
+! c = '\\';
+! }
+! else
+! if ((c == 's') || (c == 'S')){
+! c = d = 's';
+! }
+! else
+! if ((c == 'l') || (c == 'L')){
+! c = d = 'l';
+! }
+! else
+! d = (char) GetKey();
+! return (int) accent(c,d);
+! }
+!
+! pineaccent(f,n)
+! int f,n;
+! { int e;
+!
+! if (e = GetAccent())
+! execute(e,0,1);
+! return 1;
+! }
+!
+! unsigned char accent(f,n)
+! int f,n;
+! { char c,d;
+!
+! c = (char) f;
+! d = (char) n;
+! switch(c){
+! case '~' :
+! switch(d){
+! case 'a' : return '\343';
+! case 'n' : return '\361';
+! case 'o' : return '\365';
+! case 'A' : return '\303';
+! case 'N' : return '\321';
+! case 'O' : return '\325';
+! }
+! break;
+! case '\047' :
+! switch(d){
+! case 'a' : return '\341';
+! case 'e' : return '\351';
+! case 'i' : return '\355';
+! case 'o' : return '\363';
+! case 'u' : return '\372';
+! case 'y' : return '\375';
+! case 'A' : return '\301';
+! case 'E' : return '\311';
+! case 'I' : return '\315';
+! case 'O' : return '\323';
+! case 'U' : return '\332';
+! case 'Y' : return '\335';
+! }
+! break;
+! case '"' :
+! switch(d){
+! case 'a' : return '\344';
+! case 'e' : return '\353';
+! case 'i' : return '\357';
+! case 'o' : return '\366';
+! case 'u' : return '\374';
+! case 'y' : return '\377';
+! case 'A' : return '\304';
+! case 'E' : return '\313';
+! case 'I' : return '\317';
+! case 'O' : return '\326';
+! case 'U' : return '\334';
+! }
+! break;
+! case '^' :
+! switch(d){
+! case 'a' : return '\342';
+! case 'e' : return '\352';
+! case 'i' : return '\356';
+! case 'o' : return '\364';
+! case 'u' : return '\373';
+! case 'A' : return '\302';
+! case 'E' : return '\312';
+! case 'I' : return '\316';
+! case 'O' : return '\324';
+! case 'U' : return '\333';
+! case '0' : return '\260';
+! case '1' : return '\271';
+! case '2' : return '\262';
+! case '3' : return '\263';
+! }
+! break;
+! case '`' :
+! switch(d){
+! case 'a' : return '\340';
+! case 'e' : return '\350';
+! case 'i' : return '\354';
+! case 'o' : return '\362';
+! case 'u' : return '\371';
+! case 'A' : return '\300';
+! case 'E' : return '\310';
+! case 'I' : return '\314';
+! case 'O' : return '\322';
+! case 'U' : return '\331';
+! }
+! break;
+! case 'o' :
+! switch(d){
+! case 'a' : return '\345';
+! case 'A' : return '\305';
+! case '/' : return '\370';
+! case 'r' : return '\256';
+! case 'R' : return '\256';
+! case 'c' : return '\251';
+! case 'C' : return '\251';
+! }
+! break;
+! case '-' :
+! switch(d){
+! case 'o' : return '\272';
+! case 'O' : return '\272';
+! case '0' : return '\272';
+! case 'a' : return '\252';
+! case 'A' : return '\252';
+! case 'l' : return '\243';
+! case 'L' : return '\243';
+! }
+! break;
+! case 'O' :
+! switch(d){
+! case '/' : return '\330';
+! case 'r' : return '\256';
+! case 'R' : return '\256';
+! case 'c' : return '\251';
+! case 'C' : return '\251';
+! }
+! case '/' :
+! switch(d){
+! case 'o' : return '\370';
+! case 'O' : return '\330';
+! }
+! break;
+! case 'a' :
+! switch(d){
+! case 'e' : return '\346';
+! case 'E' : return '\346';
+! }
+! break;
+! case 'A' :
+! switch(d){
+! case 'E' : return '\306';
+! case 'e' : return '\306';
+! }
+! break;
+! case ',' :
+! switch(d){
+! case 'c' : return '\347';
+! case 'C' : return '\307';
+! }
+! break;
+! case '\\' :
+! switch(d){
+! case '?' : return '\277';
+! case '!' : return '\241';
+! }
+! break;
+! case 's' :
+! switch(d){
+! case 's' : return '\337';
+! }
+! break;
+! case 'l' :
+! switch(d){
+! case 'l' : return '\243';
+! }
+! break;
+! }
+! return '\0';
+! }
+!
+ /*
+! * go forward to the end of the current paragraph
+ * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
+ * combination to delimit the begining of a paragraph
+ */
+ gotoeop(f, n)
+ int f, n; /* default Flag & Numeric argument */
+ {
+! int quoted, qlen, indented;
+! char qstr[NLINE], qstr2[NLINE], ind_str[NLINE];
+
+ if (n < 0) /* the other way...*/
+ return(gotobop(f, -n));
+***************
+*** 353,358 ****
+--- 588,645 ----
+ break;
+ }
+
++ /*
++ * We need to figure out if this line is the first line of
++ * a paragraph that has been indented in a special way. If this
++ * is the case, we advance one more line before we use the
++ * algorithm below
++ */
++
++ if(curwp->w_dotp != curbp->b_linep){
++ int i,j;
++
++ if (glo_quote_str || (Pmaster && Pmaster->quote_str)){
++ quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str,
++ curwp->w_dotp, qstr, NLINE, 1);
++ quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str,
++ lforw(curwp->w_dotp), qstr2, NLINE, 1);
++ }
++ else
++ qstr[0] = qstr2[0] = '\0';
++ indented = indent_match((glo_quote_str || (Pmaster && Pmaster->quote_str))
++ ? (glo_quote_str ? glo_quote_str
++ : Pmaster->quote_str) : "", curwp->w_dotp,
++ ind_str, NLINE, 1);
++ if (strlenis(qstr) + strlenis(ind_str) < strlenis(qstr2)){
++ curwp->w_doto = 0;
++ if(n){ /* this line is a paragraph by itself */
++ curwp->w_dotp = lforw(curwp->w_dotp);
++ continue;
++ }
++ break;
++ }
++ for (i=0,j=0; qstr[i] && qstr2[i] && (qstr[i] == qstr2[i]);i++,j++);
++ for (; isspace(qstr[i]); i++);
++ for (; isspace(qstr2[j]); j++);
++ if (!qstr[i] && !qstr2[j] && indented){
++ if (indent_match((glo_quote_str
++ || (Pmaster && Pmaster->quote_str))
++ ? (glo_quote_str ? glo_quote_str
++ : Pmaster->quote_str) : "",
++ lforw(curwp->w_dotp),
++ ind_str, NLINE, 0)){
++ if (n){ /* look for another paragraph ? */
++ curwp->w_dotp = lforw(curwp->w_dotp);
++ continue;
++ }
++ }
++ else{
++ if (!lisblank(lforw(curwp->w_dotp)))
++ curwp->w_dotp = lforw(curwp->w_dotp);
++ }
++ }
++ }
++
+ /* scan line by line until we come to a line ending with
+ * a <NL><NL> or <NL><TAB> or <NL><SPACE>
+ *
+***************
+*** 361,367 ****
+ */
+ quoted = ((glo_quote_str || (Pmaster && Pmaster->quote_str))
+ ? quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str,
+! curwp->w_dotp, qstr, NLINE) : 0);
+ qlen = quoted ? strlen(qstr) : 0;
+
+ while(curwp->w_dotp != curbp->b_linep
+--- 648,654 ----
+ */
+ quoted = ((glo_quote_str || (Pmaster && Pmaster->quote_str))
+ ? quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str,
+! curwp->w_dotp, qstr, NLINE, 0) : 0);
+ qlen = quoted ? strlen(qstr) : 0;
+
+ while(curwp->w_dotp != curbp->b_linep
+***************
+*** 370,378 ****
+ ? (quoted == quote_match(glo_quote_str ? glo_quote_str
+ : Pmaster->quote_str,
+ lforw(curwp->w_dotp),
+! qstr2, NLINE)
+ && !strcmp(qstr, qstr2))
+ : 1)
+ && lgetc(lforw(curwp->w_dotp), qlen).c != TAB
+ && lgetc(lforw(curwp->w_dotp), qlen).c != ' ')
+ curwp->w_dotp = lforw(curwp->w_dotp);
+--- 657,671 ----
+ ? (quoted == quote_match(glo_quote_str ? glo_quote_str
+ : Pmaster->quote_str,
+ lforw(curwp->w_dotp),
+! qstr2, NLINE, 0)
+ && !strcmp(qstr, qstr2))
+ : 1)
++ && !indent_match((glo_quote_str
++ || (Pmaster && Pmaster->quote_str))
++ ? (glo_quote_str ? glo_quote_str
++ : Pmaster->quote_str) : "",
++ lforw(curwp->w_dotp),
++ ind_str, NLINE, 0)
+ && lgetc(lforw(curwp->w_dotp), qlen).c != TAB
+ && lgetc(lforw(curwp->w_dotp), qlen).c != ' ')
+ curwp->w_dotp = lforw(curwp->w_dotp);
+***************
+*** 653,659 ****
+--- 946,992 ----
+ return (scrollback (n, TRUE));
+ }
+
++ /* deltext deletes from the specified position until the end of the file
++ * or until the signature (when called from Pine), whichever comes first.
++ */
+
++ int
++ deltext (f,n)
++ int f,n;
++ {
++ LINE *currline = curwp->w_dotp;
++
++ if ((lastflag&CFKILL) == 0)
++ kdelete();
++
++ curwp->w_markp = curwp->w_dotp;
++ curwp->w_marko = curwp->w_doto;
++
++ while (curwp->w_dotp != curbp->b_linep){
++ if ((Pmaster)
++ && (llength(curwp->w_dotp) == 3)
++ && (lgetc(curwp->w_dotp, 0).c == '-')
++ && (lgetc(curwp->w_dotp, 1).c == '-')
++ && (lgetc(curwp->w_dotp, 2).c == ' ')){
++ if (curwp->w_dotp == currline){
++ if (curwp->w_doto)
++ curwp->w_dotp = lforw(curwp->w_dotp);
++ else
++ break;
++ }
++ else{
++ curwp->w_dotp = lback(curwp->w_dotp);
++ curwp->w_doto = llength(curwp->w_dotp);
++ break;
++ }
++ }
++ else
++ curwp->w_dotp = lforw(curwp->w_dotp);
++ }
++ killregion(FALSE,1);
++ lastflag |= CFKILL;
++ return TRUE;
++ }
+
+ scrollupline (f, n)
+ int f, n;
+diff -rc pine4.63/pico/composer.c pine4.63.I.USE/pico/composer.c
+*** pine4.63/pico/composer.c Thu Mar 17 11:08:37 2005
+--- pine4.63.I.USE/pico/composer.c Thu May 19 19:57:30 2005
+***************
+*** 1560,1565 ****
+--- 1560,1567 ----
+ }
+
+ UpdateHeader(0);
++ if(sendnow)
++ return(status !=0);
+ PaintHeader(COMPOSER_TOP_LINE, status != 0);
+ PaintBody(1);
+ return(status != 0);
+***************
+*** 1691,1697 ****
+ }
+
+ if(VALID_KEY(ch)){ /* char input */
+! /*
+ * if we are allowing editing, insert the new char
+ * end up leaving tbufp pointing to newly
+ * inserted character in string, and offset to the
+--- 1693,1699 ----
+ }
+
+ if(VALID_KEY(ch)){ /* char input */
+! insert_char:/*
+ * if we are allowing editing, insert the new char
+ * end up leaving tbufp pointing to newly
+ * inserted character in string, and offset to the
+***************
+*** 1775,1780 ****
+--- 1777,1789 ----
+ }
+ else { /* interpret ch as a command */
+ switch (ch = normalize_cmd(ch, ckm, 2)) {
++ case (CTRL|'\\') :
++ if (ch = GetAccent())
++ goto insert_char;
++ else
++ clearcursor();
++ break;
++
+ case (CTRL|'@') : /* word skip */
+ while(strng[ods.p_off]
+ && isalnum((unsigned char)strng[ods.p_off]))
+***************
+*** 2955,2960 ****
+--- 2964,2972 ----
+ {
+ register char *bufp;
+
++ if (sendnow)
++ return;
++
+ if(ComposerTopLine - 1 >= BOTTOM()) /* silently forget it */
+ return;
+
+***************
+*** 3004,3009 ****
+--- 3016,3024 ----
+ register char *bufp;
+ register int i;
+
++ if (sendnow)
++ return(TRUE);
++
+ bufp = headents[entry].prompt; /* fresh prompt paint */
+ if((i = entry_line(entry, FALSE)) == -1)
+ return(-1); /* silently forget it */
+***************
+*** 3884,3889 ****
+--- 3899,3907 ----
+ void
+ ShowPrompt()
+ {
++ if (sendnow)
++ return;
++
+ if(headents[ods.cur_e].key_label){
+ menu_header[TO_KEY].name = "^T";
+ menu_header[TO_KEY].label = headents[ods.cur_e].key_label;
+diff -rc pine4.63/pico/display.c pine4.63.I.USE/pico/display.c
+*** pine4.63/pico/display.c Fri May 7 14:38:24 2004
+--- pine4.63.I.USE/pico/display.c Thu May 19 19:57:32 2005
+***************
+*** 362,367 ****
+--- 362,370 ----
+ register int scroll = 0;
+ CELL c;
+
++ if (sendnow)
++ return;
++
+ #if TYPEAH
+ if (typahead())
+ return;
+***************
+*** 1400,1405 ****
+--- 1403,1409 ----
+
+ maxl = (nbuf-1 < term.t_ncol - plen - 1) ? nbuf-1 : term.t_ncol - plen - 1;
+
++ if (!sendnow)
+ pputs(buf, 1);
+ b = &buf[(flg & QBOBUF) ? 0 : strlen(buf)];
+
+***************
+*** 1460,1465 ****
+--- 1464,1482 ----
+ b++;
+ continue;
+
++ case (CTRL|'N'): /* Insert pattern */
++ if (pat[0] != '\0'){
++ strcat(buf,pat);
++ pputs(pat,1);
++ b += strlen(pat);
++ changed = TRUE;
++ }
++ else
++ (*term.t_beep)();
++ continue;
++
++
++
+ case (CTRL|'G') : /* CTRL-G help */
+ if(term.t_mrow == 0 && km_popped == 0){
+ movecursor(term.t_nrow-2, 0);
+***************
+*** 1515,1520 ****
+--- 1532,1542 ----
+ b--;
+ continue;
+
++ case (CTRL|'\\'):
++ if (c = GetAccent())
++ goto text;
++ continue;
++
+ case KEY_RIGHT:
+ if(*b != '\0')
+ b++;
+***************
+*** 1566,1571 ****
+--- 1588,1594 ----
+ #endif
+
+ default :
++ text:
+ if(strlen(buf) >= maxl){ /* contain the text */
+ (*term.t_beep)();
+ continue;
+***************
+*** 1604,1625 ****
+ b[i+1] = b[i];
+ while(i-- > 0);
+
+! pputc(*b++ = c, 0);
+ }
+ }
+
+! pputs(b, 1); /* show default */
+ i = term.t_ncol-1;
+ while(pscreen[ttrow]->v_text[i].c == ' '
+ && pscreen[ttrow]->v_text[i].a == 0)
+ i--;
+
+! while(ttcol <= i)
+ pputc(' ', 0);
+ }
+
+ ret:
+! if(km_popped){
+ term.t_mrow = 0;
+ movecursor(term.t_nrow, 0);
+ peeol();
+--- 1627,1652 ----
+ b[i+1] = b[i];
+ while(i-- > 0);
+
+! if(sendnow)
+! *b++ = c;
+! else
+! pputc(*b++ = c, 0);
+ }
+ }
+
+! if(!sendnow)
+! pputs(b, 1); /* show default */
+ i = term.t_ncol-1;
+ while(pscreen[ttrow]->v_text[i].c == ' '
+ && pscreen[ttrow]->v_text[i].a == 0)
+ i--;
+
+! while(!sendnow && ttcol <= i)
+ pputc(' ', 0);
+ }
+
+ ret:
+! if(!sendnow && km_popped){
+ term.t_mrow = 0;
+ movecursor(term.t_nrow, 0);
+ peeol();
+***************
+*** 1745,1750 ****
+--- 1772,1779 ----
+ register int c;
+ register char *ap;
+
++ if(sendnow)
++ return 0;
+ /*
+ * the idea is to only highlight if there is something to show
+ */
+***************
+*** 2472,2477 ****
+--- 2501,2509 ----
+ char nbuf[NLINE];
+ #endif
+
++ if(sendnow)
++ return;
++
+ #ifdef _WINDOWS
+ pico_config_menu_items (keymenu);
+ #endif
+diff -rc pine4.63/pico/ebind.h pine4.63.I.USE/pico/ebind.h
+*** pine4.63/pico/ebind.h Fri May 7 14:38:24 2004
+--- pine4.63.I.USE/pico/ebind.h Thu May 19 19:57:30 2005
+***************
+*** 105,111 ****
+ {CTRL|'^', setmark},
+ {CTRL|'_', alt_editor},
+ {0x7F, backdel},
+! {0, NULL}
+ };
+
+
+--- 105,113 ----
+ {CTRL|'^', setmark},
+ {CTRL|'_', alt_editor},
+ {0x7F, backdel},
+! {CTRL|'\\', pineaccent},
+! {0,
+! NULL}
+ };
+
+
+diff -rc pine4.63/pico/edef.h pine4.63.I.USE/pico/edef.h
+*** pine4.63/pico/edef.h Wed Oct 13 18:27:46 2004
+--- pine4.63.I.USE/pico/edef.h Thu May 19 19:57:27 2005
+***************
+*** 43,48 ****
+--- 43,49 ----
+
+ /* initialized global definitions */
+
++ int sendnow = 0; /* should we send now */
+ int fillcol = 72; /* Current fill column */
+ int userfillcol = -1; /* Fillcol set from cmd line */
+ char pat[NPAT]; /* Search pattern */
+***************
+*** 96,101 ****
+--- 97,103 ----
+
+ /* initialized global external declarations */
+
++ extern int sendnow; /* should we send now */
+ extern int fillcol; /* Fill column */
+ extern int userfillcol; /* Fillcol set from cmd line */
+ extern char pat[]; /* Search pattern */
+diff -rc pine4.63/pico/efunc.h pine4.63.I.USE/pico/efunc.h
+*** pine4.63/pico/efunc.h Tue Jun 15 15:22:58 2004
+--- pine4.63.I.USE/pico/efunc.h Thu May 19 19:57:33 2005
+***************
+*** 65,70 ****
+--- 65,71 ----
+ extern int gotoeop PROTO((int, int));
+ extern int forwpage PROTO((int, int));
+ extern int backpage PROTO((int, int));
++ extern int deltext PROTO((int, int));
+ extern int scrollupline PROTO((int, int));
+ extern int scrolldownline PROTO((int, int));
+ extern int scrollto PROTO((int, int));
+***************
+*** 73,78 ****
+--- 74,82 ----
+ extern int setimark PROTO((int, int));
+ extern int swapimark PROTO((int, int));
+ extern int mousepress PROTO((int, int));
++ extern unsigned char accent PROTO((int, int));
++ extern int pineaccent PROTO((int, int));
++ extern int GetAccent PROTO((void));
+
+ /* bind.c */
+ extern int whelp PROTO((int, int));
+***************
+*** 337,342 ****
+ extern int fillpara PROTO((int, int));
+ extern int fillbuf PROTO((int, int));
+ extern int inword PROTO((void));
+! extern int quote_match PROTO((char *, LINE *, char *, int));
+
+ #endif /* EFUNC_H */
+--- 341,350 ----
+ extern int fillpara PROTO((int, int));
+ extern int fillbuf PROTO((int, int));
+ extern int inword PROTO((void));
+! extern int quote_match PROTO((char *, LINE *, char *, int, int));
+! extern void flatten_qstring PROTO((QSTRING_S *, char *));
+! extern void free_qs PROTO((QSTRING_S **));
+! extern QSTRING_S *do_quote_match PROTO((char *, char *, char *, char *, int));
+! extern QSTRING_S *copy_qs PROTO((QSTRING_S *));
+
+ #endif /* EFUNC_H */
+diff -rc pine4.63/pico/line.c pine4.63.I.USE/pico/line.c
+*** pine4.63/pico/line.c Fri May 7 14:41:16 2004
+--- pine4.63.I.USE/pico/line.c Thu May 19 19:57:29 2005
+***************
+*** 635,641 ****
+
+ n = ((glo_quote_str || (Pmaster && Pmaster->quote_str))
+ && quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str,
+! line, qstr, NLINE))
+ ? strlen(qstr) : 0;
+
+ for(; n < llength(line); n++)
+--- 635,641 ----
+
+ n = ((glo_quote_str || (Pmaster && Pmaster->quote_str))
+ && quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str,
+! line, qstr, NLINE, 1))
+ ? strlen(qstr) : 0;
+
+ for(; n < llength(line); n++)
+diff -rc pine4.63/pico/main.c pine4.63.I.USE/pico/main.c
+*** pine4.63/pico/main.c Fri May 7 14:41:16 2004
+--- pine4.63.I.USE/pico/main.c Thu May 19 19:57:31 2005
+***************
+*** 149,154 ****
+--- 149,155 ----
+ int setlocale_ctype = 0;
+ char bname[NBUFN]; /* buffer name of file to read */
+ char *file_to_edit = NULL;
++ int line_information_on = FALSE;
+
+ timeo = 600;
+ Pmaster = NULL; /* turn OFF composer functionality */
+***************
+*** 306,311 ****
+--- 307,318 ----
+ emlwrite("You may possibly have new mail.", NULL);
+ }
+
++ if (c == (CTRL|'\\')){
++ c = GetAccent();
++ if (!c)
++ c = NODATA;
++ }
++
+ if(km_popped)
+ switch(c){
+ case NODATA:
+***************
+*** 327,340 ****
+ mlerase();
+ }
+
+! f = FALSE;
+ n = 1;
+
+ #ifdef MOUSE
+ clear_mfunc(mouse_in_content);
+ #endif
+ /* Do it. */
+ execute(normalize_cmd(c, fkm, 1), f, n);
+ }
+ }
+
+--- 334,363 ----
+ mlerase();
+ }
+
+! f = (c == (CTRL|'J'));
+ n = 1;
++ if (!line_information_on)
++ line_information_on = (c == (CTRL|'C'));
++ else
++ line_information_on = ((c == KEY_DOWN) || (c == KEY_UP) ||
++ (c == KEY_RIGHT) || (c == KEY_LEFT) ||
++ (c == (CTRL|'V')) || (c == (CTRL|'Y')) ||
++ (c == (CTRL|'K')) || (c == (CTRL|'D')) ||
++ (c == (CTRL|'F')) || (c == (CTRL|'B')) ||
++ (c == (CTRL|'N')) || (c == (CTRL|'P')) ||
++ (c == (CTRL|'A')) || (c == (CTRL|'E')) ||
++ (c == (CTRL|'U')) || (c == (CTRL|'^')))
++ && (c != (CTRL|'C'));
+
+ #ifdef MOUSE
+ clear_mfunc(mouse_in_content);
+ #endif
+ /* Do it. */
+ execute(normalize_cmd(c, fkm, 1), f, n);
++ if (line_information_on){
++ c = (CTRL|'C');
++ execute(normalize_cmd(c, fkm, 1), f, n);
++ }
+ }
+ }
+
+diff -rc pine4.63/pico/osdep/term.cap pine4.63.I.USE/pico/osdep/term.cap
+*** pine4.63/pico/osdep/term.cap Wed Jul 21 15:04:36 2004
+--- pine4.63.I.USE/pico/osdep/term.cap Thu May 19 19:57:27 2005
+***************
+*** 438,443 ****
+--- 438,449 ----
+ {
+ int row, col;
+
++ if (sendnow){
++ term.t_nrow = 23;
++ term.t_ncol = 80;
++ return 0;
++ }
++
+ /*
+ * determine the terminal's communication speed and decide
+ * if we need to do optimization ...
+diff -rc pine4.63/pico/osdep/unix pine4.63.I.USE/pico/osdep/unix
+*** pine4.63/pico/osdep/unix Tue Apr 19 14:28:56 2005
+--- pine4.63.I.USE/pico/osdep/unix Thu May 19 19:57:27 2005
+***************
+*** 363,368 ****
+--- 363,381 ----
+ {
+ int ch, status, cc;
+
++ if(sendnow){
++ ch = Pmaster && Pmaster->auto_cmds && *Pmaster->auto_cmds
++ ? *Pmaster->auto_cmds++ : NODATA;
++
++ if(ch & 0x80 && Pmaster && Pmaster->hibit_entered)
++ *Pmaster->hibit_entered = 1;
++
++ if (ch >= 0x00 && ch <= 0x1F)
++ ch = CTRL | (ch+'@');
++
++ return(ch);
++ }
++
+ if(!ReadyForKey(FUDGE-5))
+ return(NODATA);
+
+diff -rc pine4.63/pico/pico.c pine4.63.I.USE/pico/pico.c
+*** pine4.63/pico/pico.c Thu Mar 31 09:08:57 2005
+--- pine4.63.I.USE/pico/pico.c Thu May 19 19:57:27 2005
+***************
+*** 138,143 ****
+--- 138,152 ----
+ pico_all_done = 0;
+ km_popped = 0;
+
++ if (pm->auto_cmds){
++ int i;
++ #define CTRL_X 24
++ for (i = 0; pm->auto_cmds[i]; i++);
++ if ((i > 1) && (pm->auto_cmds[i - 2] == CTRL_X) &&
++ ((pm->auto_cmds[i - 1] == 'y') || (pm->auto_cmds[i-1] == 'Y')))
++ sendnow++;
++ }
++
+ if(!vtinit()) /* Init Displays. */
+ return(COMP_CANCEL);
+
+***************
+*** 686,691 ****
+--- 695,711 ----
+ return(FALSE);
+ }
+
++ /* When we send a message using the command line we are going to
++ ignore if the user wants to spell check, we assume she already
++ did */
++ if (sendnow){
++ result = (*Pmaster->exittest)(Pmaster->headents,
++ redraw_pico_for_callback, Pmaster->allow_flowed_text);
++ if (!result)
++ pico_all_done = COMP_EXIT;
++ return(result ? FALSE : TRUE);
++ }
++
+ #ifdef SPELLER
+ if(Pmaster->always_spell_check)
+ if(spell(0, 0) == -1)
+diff -rc pine4.63/pico/pico.h pine4.63.I.USE/pico/pico.h
+*** pine4.63/pico/pico.h Wed Mar 30 14:44:42 2005
+--- pine4.63.I.USE/pico/pico.h Thu May 19 19:57:29 2005
+***************
+*** 219,224 ****
+--- 219,225 ----
+ void (*resize)(); /* callback handling screen resize */
+ void (*winch_cleanup)(); /* callback handling screen resize */
+ int arm_winch_cleanup; /* do the winch_cleanup if resized */
++ int *auto_cmds; /* Initial keystroke commands */
+ HELP_T search_help;
+ HELP_T ins_help;
+ HELP_T ins_m_help;
+***************
+*** 342,347 ****
+--- 343,364 ----
+ struct KBSTREE *left;
+ } KBESC_T;
+
++ /*
++ * struct that will help us determine what the quote string of a line
++ * is. The "next" field indicates the presence of a possible continuation.
++ * The idea is that if a continuation fails, we free it and check for the
++ * remaining structure left
++ */
++
++ typedef enum {qsNormal, qsString, qsWord, qsChar} QStrType;
++
++ typedef struct QSTRING {
++ char *value; /* possible quote string */
++ QStrType qstype; /* type of quote string */
++ struct QSTRING *next; /* possible continuation */
++ } QSTRING_S;
++
++
+ /*
+ * Protos for functions used to manage keyboard escape sequences
+ * NOTE: these may ot actually get defined under some OS's (ie, DOS, WIN)
+diff -rc pine4.63/pico/random.c pine4.63.I.USE/pico/random.c
+*** pine4.63/pico/random.c Fri May 7 14:43:48 2004
+--- pine4.63.I.USE/pico/random.c Thu May 19 19:57:29 2005
+***************
+*** 364,370 ****
+ else{
+ backchar(FALSE, 1);
+ dotp = curwp->w_dotp;
+! gotobop(FALSE, 1); /* then go to the top of the para */
+ }
+
+ curwp->w_doto = 0;
+--- 364,371 ----
+ else{
+ backchar(FALSE, 1);
+ dotp = curwp->w_dotp;
+! swapimark(FALSE, 1); /* go back to the spot we marked before justify */
+! /* We assume that no imarks have been set between fillpara and now */
+ }
+
+ curwp->w_doto = 0;
+diff -rc pine4.63/pico/search.c pine4.63.I.USE/pico/search.c
+*** pine4.63/pico/search.c Thu Jul 1 14:36:36 2004
+--- pine4.63.I.USE/pico/search.c Thu May 19 19:57:34 2005
+***************
+*** 78,83 ****
+--- 78,87 ----
+ "\tbrackets. This string is the default search prompt.",
+ "~ Hitting only ~R~e~t~u~r~n or at the prompt will cause the",
+ "\tsearch to be made with the default value.",
++ " ",
++ "~ Hitting ~^~N will reinsert the last string you searched for",
++ "\tso that you can edit it (in case you made a mistake entering the",
++ "\tsearch pattern the first time).",
+ " ",
+ "\tThe text search is not case sensitive, and will examine the",
+ "\tentire message.",
+***************
+*** 235,244 ****
+--- 239,258 ----
+ mlerase();
+ FWS_RETURN(TRUE);
+
++ case (CTRL|'P'):
++ deletepara(0, 1);
++ mlerase();
++ FWS_RETURN(TRUE);
++
+ case (CTRL|'R'): /* toggle replacement option */
+ repl_mode = !repl_mode;
+ break;
+
++ case (CTRL|'X'):
++ deltext(f,n);
++ mlerase();
++ FWS_RETURN(TRUE);
++
+ default:
+ if(status == ABORT)
+ emlwrite("Search Cancelled", NULL);
+***************
+*** 275,281 ****
+ }
+
+ if(status + curwp->w_doto >= llength(curwp->w_dotp) ||
+! !eq(defpat[status],lgetc(curwp->w_dotp, curwp->w_doto + status).c))
+ break; /* do nothing! */
+ status++;
+ }
+--- 289,295 ----
+ }
+
+ if(status + curwp->w_doto >= llength(curwp->w_dotp) ||
+! !eq((unsigned char)defpat[status],lgetc(curwp->w_dotp, curwp->w_doto + status).c))
+ break; /* do nothing! */
+ status++;
+ }
+***************
+*** 499,505 ****
+ register int s;
+ int i = 0;
+ char tpat[NPAT+20];
+! EXTRAKEYS menu_pat[8];
+
+ menu_pat[i = 0].name = "^Y";
+ menu_pat[i].label = "FirstLine";
+--- 513,519 ----
+ register int s;
+ int i = 0;
+ char tpat[NPAT+20];
+! EXTRAKEYS menu_pat[10];
+
+ menu_pat[i = 0].name = "^Y";
+ menu_pat[i].label = "FirstLine";
+***************
+*** 517,522 ****
+--- 531,541 ----
+ KS_OSDATASET(&menu_pat[i], KS_NONE);
+
+ if(!repl_mode){
++ menu_pat[++i].name = "^X";
++ menu_pat[i].label = "EndText";
++ menu_pat[i].key = (CTRL|'X');
++ KS_OSDATASET(&menu_pat[i], KS_NONE);
++
+ menu_pat[++i].name = "^T";
+ menu_pat[i].label = "LineNumber";
+ menu_pat[i].key = (CTRL|'T');
+***************
+*** 532,537 ****
+--- 551,561 ----
+ menu_pat[i].key = (CTRL|'O');
+ KS_OSDATASET(&menu_pat[i], KS_NONE);
+
++ menu_pat[++i].name = "^P";
++ menu_pat[i].label = "Delete Para";
++ menu_pat[i].key = (CTRL|'P');
++ KS_OSDATASET(&menu_pat[i], KS_NONE);
++
+ menu_pat[++i].name = "^U";
+ menu_pat[i].label = "FullJustify";
+ menu_pat[i].key = (CTRL|'U');
+***************
+*** 630,636 ****
+ register int s;
+ int i;
+ char tpat[NPAT+20];
+! EXTRAKEYS menu_pat[7];
+
+ menu_pat[i = 0].name = "^Y";
+ menu_pat[i].label = "FirstLine";
+--- 654,660 ----
+ register int s;
+ int i;
+ char tpat[NPAT+20];
+! EXTRAKEYS menu_pat[9];
+
+ menu_pat[i = 0].name = "^Y";
+ menu_pat[i].label = "FirstLine";
+***************
+*** 643,648 ****
+--- 667,677 ----
+ KS_OSDATASET(&menu_pat[i], KS_NONE);
+
+ if(text_mode){
++ menu_pat[++i].name = "^X";
++ menu_pat[i].label = "EndText";
++ menu_pat[i].key = (CTRL|'X');
++ KS_OSDATASET(&menu_pat[i], KS_NONE);
++
+ menu_pat[++i].name = "^T";
+ menu_pat[i].label = "LineNumber";
+ menu_pat[i].key = (CTRL|'T');
+***************
+*** 658,663 ****
+--- 687,697 ----
+ menu_pat[i].key = (CTRL|'O');
+ KS_OSDATASET(&menu_pat[i], KS_NONE);
+
++ menu_pat[++i].name = "^P";
++ menu_pat[i].label = "Delete Para";
++ menu_pat[i].key = (CTRL|'P');
++ KS_OSDATASET(&menu_pat[i], KS_NONE);
++
+ menu_pat[++i].name = "^U";
+ menu_pat[i].label = "FullJustify";
+ menu_pat[i].key = (CTRL|'U');
+***************
+*** 760,766 ****
+ c = lgetc(curline, curoff++).c; /* get the char */
+
+ /* test it against first char in pattern */
+! if (eq(c, patrn[0]) != FALSE) { /* if we find it..*/
+ /* setup match pointers */
+ matchline = curline;
+ matchoff = curoff;
+--- 794,800 ----
+ c = lgetc(curline, curoff++).c; /* get the char */
+
+ /* test it against first char in pattern */
+! if (eq(c, (unsigned char)patrn[0]) != FALSE) { /* if we find it..*/
+ /* setup match pointers */
+ matchline = curline;
+ matchoff = curoff;
+***************
+*** 781,787 ****
+ return(FALSE);
+
+ /* and test it against the pattern */
+! if (eq(*patptr, c) == FALSE)
+ goto fail;
+ }
+
+--- 815,821 ----
+ return(FALSE);
+
+ /* and test it against the pattern */
+! if (eq((unsigned char) *patptr, c) == FALSE)
+ goto fail;
+ }
+
+***************
+*** 820,829 ****
+ int maxlength; /* maximum chars in destination */
+
+ {
+! char c; /* current char to translate */
+
+ /* scan through the string */
+! while ((c = *srcstr++) != 0) {
+ if (c == '\n') { /* its an EOL */
+ *deststr++ = '<';
+ *deststr++ = 'N';
+--- 854,863 ----
+ int maxlength; /* maximum chars in destination */
+
+ {
+! unsigned char c; /* current char to translate */
+
+ /* scan through the string */
+! while ((c = (unsigned char) *srcstr++) != 0) {
+ if (c == '\n') { /* its an EOL */
+ *deststr++ = '<';
+ *deststr++ = 'N';
+diff -rc pine4.63/pico/word.c pine4.63.I.USE/pico/word.c
+*** pine4.63/pico/word.c Fri May 7 14:45:24 2004
+--- pine4.63.I.USE/pico/word.c Thu May 19 19:57:29 2005
+***************
+*** 360,403 ****
+ && isalnum((unsigned char)lgetc(curwp->w_dotp, curwp->w_doto).c));
+ }
+
+
+ /*
+! * Return number of quotes if whatever starts the line matches the quote string
+ */
+! quote_match(q, l, buf, buflen)
+ char *q;
+ LINE *l;
+ char *buf;
+ int buflen;
+ {
+! register int i, n, j, qb;
+
+! *buf = '\0';
+! if(*q == '\0')
+! return(1);
+!
+! qb = (strlen(q) > 1 && q[strlen(q)-1] == ' ') ? 1 : 0;
+! for(n = 0, j = 0; ;){
+! for(i = 0; j <= llength(l) && qb ? q[i+1] : q[i]; i++, j++)
+! if(q[i] != lgetc(l, j).c)
+! return(n);
+!
+! n++;
+! if((!qb && q[i] == '\0') || (qb && q[i+1] == '\0')){
+! if(strlen(buf) + strlen(q) + 1 < buflen){
+! strcat(buf,q);
+! if(qb && (j > llength(l) || lgetc(l, j).c != ' '))
+! buf[strlen(buf)-1] = '\0';
+! }
+ }
+! if(j > llength(l))
+! return(n);
+! else if(qb && lgetc(l, j).c == ' ')
+! j++;
+ }
+! return(n); /* never reached */
+ }
+
+
+ /* Justify the entire buffer instead of just a paragraph */
+ fillbuf(f, n)
+--- 360,1419 ----
+ && isalnum((unsigned char)lgetc(curwp->w_dotp, curwp->w_doto).c));
+ }
+
++ /* Support of indentation of paragraphs */
++ #define NBSP ((unsigned char) '\240')
++ #define ISspace(c) ((c) == ' ' || (c) == TAB || ((unsigned char)(c)) == NBSP)
++ #define is_indent_char(c) (((c) == '.' || (c) == '}' || (c) == RPAREN || \
++ (c) == '*' || (c) == '+' || is_a_digit(c) || \
++ ISspace(c) || (c) == '-' || \
++ (c) == ']') ? 1 : 0)
++ #define allowed_after_digit(c,word,k) ((((c) == '.' && \
++ allowed_after_period(next((word),(k)))) ||\
++ (c) == RPAREN || (c) == '}' || (c) == ']' ||\
++ ISspace(c) || is_a_digit(c) || \
++ ((c) == '-' ) && \
++ allowed_after_dash(next((word),(k)))) \
++ ? 1 : 0)
++ #define allowed_after_period(c) (((c) == RPAREN || (c) == '}' || (c) == ']' ||\
++ ISspace(c) || (c) == '-' || \
++ is_a_digit(c)) ? 1 : 0)
++ #define allowed_after_parenth(c) (ISspace(c) ? 1 : 0)
++ #define allowed_after_space(c) (ISspace(c) ? 1 : 0)
++ #define allowed_after_braces(c) (ISspace(c) ? 1 : 0)
++ #define allowed_after_star(c) ((ISspace(c) || (c) == RPAREN ||\
++ (c) == ']' || (c) == '}') ? 1 : 0)
++ #define allowed_after_dash(c) ((ISspace(c) || is_a_digit(c)) ? 1 : 0)
++ #define EOLchar(c) (((c) == '.' || (c) == ':' || (c) == '?' ||\
++ (c) == '!') ? 1 : 0)
++
++ int is_indent PROTO((char *, int));
++ int indent_match PROTO(( char *, LINE *, char *, int, int));
++
++ /* Extended justification support */
++
++ #define is_cquote(c) ((c) == '>' || (c) == '|' || (c) == ']' || (c) == ':')
++ #define is_cword(c) ((((c) >= 'a') && ((c) <= 'z')) || \
++ (((c) >= 'A') && ((c) <= 'Z')) || \
++ (((c) >= '0') && ((c) <= '9')) || \
++ ((c) == ' ') || ((c) == '?') || \
++ ((c) == '@') || ((c) == '.') || \
++ ((c) == '!') || ((c) == '\'') || \
++ ((c) == ',') || ((c) == '\"') ? 1 : 0)
++ #define isaquote(c) ((c) == '\"' || (c) == '\'')
++ #define is8bit(c) ((((int) (c)) & 0x80) ? 1 : 0)
++ #define forbidden(c) (((c) == '\"') || ((c) == '\'') || ((c) == '$') ||\
++ ((c) == ',') || ((c) == '.') || ((c) == '-') ||\
++ ((c) == LPAREN) || ((c) == '/')|| ((c) == '`') ||\
++ ((c) == '{') || ((c) == '\\') || \
++ (((c) >= '0') && ((c) <= '9')))
++ #define is_cletter(c) ((((c) >= 'a') && ((c) <= 'z'))) ||\
++ ((((c) >= 'A') && ((c) <= 'Z'))||\
++ is8bit(c))
++ #define is_cnumber(c) ((c) >= '0' && (c) <= '9')
++ #define allwd_after_word(c) (((c) == ' ') || ((c) == '>') || is_cletter(c))
++ #define allwd_after_qsword(c) (((c) != '\\') && ((c) != RPAREN))
++ #define before(word,i) (((i) > 0) ? (word)[(i) - 1] : 0)
++ #define next(w,i) ((((w)[(i)]) != 0) ? ((w)[(i) + 1]) : 0)
++ #define now(w,i) ((w)[(i)])
++ #define is_qsword(c) (((c) == ':') || ((c) == RPAREN) ? 1 : 0)
++ #define is_colon(c) (((c) == ':') ? 1 : 0)
++ #define is_rarrow(c) (((c) == '>') ? 1 : 0)
++ #define is_tilde(c) (((c) == '~') ? 1 : 0)
++ #define is_dash(c) (((c) == '-') ? 1 : 0)
++ #define is_pound(c) (((c) == '#') ? 1 : 0)
++ #define is_space(c) (((c) == ' ') ? 1 : 0)
++ #define is_a_digit(c) ((((c) >= '0') && ((c) <= '9')) ? 1 : 0)
++ #define is_allowed(c) (is_cquote(c) || is_cword(c) || is_dash(c) || \
++ is_pound(c))
++
++ /* Internal justification functions */
++
++ QSTRING_S *is_quote PROTO((char *, char *, int));
++ QSTRING_S *copy_qs PROTO((QSTRING_S *));
++ QSTRING_S *qs_normal_part PROTO((QSTRING_S *));
++ QSTRING_S *qs_remove_trailing_spaces PROTO((QSTRING_S *));
++ QSTRING_S *trim_qs_from_cl PROTO((QSTRING_S *, QSTRING_S *, QSTRING_S *));
++ QSTRING_S *fix_qstring PROTO((QSTRING_S *, QSTRING_S *, QSTRING_S *));
++ QSTRING_S *qs_add PROTO((char *, char *, QStrType, int, int, int, int));
++ QSTRING_S *remove_qsword PROTO((QSTRING_S *));
++ int qstring_is_normal PROTO((QSTRING_S *));
++ int exists_good_part PROTO((QSTRING_S *));
++ int value_is_space PROTO((char *));
++ int strcmp_qs PROTO((char *, char *));
++ int count_levels_qstring PROTO((QSTRING_S *));
++ int same_qstring PROTO((QSTRING_S *, QSTRING_S *));
++ int advance_quote_string PROTO((char *, char *, int));
++ int strlenis PROTO((char *));
++ void flatten_qstring PROTO((QSTRING_S *, char *));
++ void linencpy PROTO((char *, LINE *, int));
++
++ /*
++ * This function creates a qstring pointer with the information that
++ * is_quote handles to it.
++ * Parameters:
++ * qs - User supplied quote string
++ * word - The line of text that the user is trying to read/justify
++ * beginw - Where we need to start copying from
++ * endw - Where we end copying
++ * offset - Any offset in endw that we need to account for
++ * typeqs - type of the string to be created
++ * neednext - boolean, indicating if we need to compute the next field
++ * of leave it NULL
++ *
++ * It is a mistake to call this function if beginw >= endw + offset.
++ * Please note the equality sign in the above inequality (this is because
++ * we always assume that qstring->value != "").
++ */
++
++ QSTRING_S *
++ qs_add(qs, word, typeqs, beginw, endw, offset, neednext)
++ char *qs;
++ char word[NSTRING];
++ QStrType typeqs;
++ int beginw;
++ int endw;
++ int offset;
++ int neednext;
++ {
++ QSTRING_S *qstring, *nextqs = (QSTRING_S *) NULL;
++ int i;
++
++ qstring = (QSTRING_S *) malloc (sizeof(QSTRING_S));
++ memset (qstring, 0, sizeof(QSTRING_S));
++ qstring->qstype = qsNormal;
++
++ if (beginw == 0){
++ beginw = endw + offset;
++ qstring->qstype = typeqs;
++ }
++
++ if (neednext)
++ nextqs = is_quote(qs, word+beginw, 1);
++
++ qstring->value = (char *) malloc((beginw+1)*sizeof(char));
++ strncpy(qstring->value, word, beginw);
++ qstring->value[beginw] = '\0';
++
++ qstring->next = nextqs;
++
++ return qstring;
++ }
++
++
++ int
++ qstring_is_normal(cl)
++ QSTRING_S *cl;
++ {
++ for (;cl && (cl->qstype == qsNormal); cl = cl->next);
++
++ return cl ? 0 : 1;
++ }
++
++ void
++ free_qs(cl)
++ QSTRING_S **cl;
++ {
++ if (!(*cl))
++ return;
++
++ if ((*cl)->next)
++ free_qs(&((*cl)->next));
++
++ (*cl)->next = (QSTRING_S *) NULL;
++
++ if ((*cl)->value)
++ free((void *)(*cl)->value);
++
++ (*cl)->value = (char *) NULL;
++
++ free((void *)(*cl));
++ *cl = (QSTRING_S *) NULL;
++ }
++
++ QSTRING_S *
++ copy_qs(cl)
++ QSTRING_S *cl;
++ {
++ QSTRING_S *qs;
++
++ if (!cl)
++ return (QSTRING_S *)NULL;
++
++ qs = (QSTRING_S *) malloc (sizeof(QSTRING_S));
++ memset (qs, 0, sizeof(QSTRING_S));
++
++ qs->value = (char *) malloc ((strlen(cl->value)+1)*sizeof(char));
++ strcpy(qs->value, cl->value);
++ qs->qstype = cl->qstype;
++ qs->next = copy_qs(cl->next);
++ return qs;
++ }
++
++ /*
++ * Given a quote string, this function returns the part that is the leading
++ * normal part of it. (the normal part is the part that is tagged qsNormal,
++ * that is to say, the one that is not controversial at all (like qsString
++ * for example).
++ */
++ QSTRING_S *
++ qs_normal_part(cl)
++ QSTRING_S *cl;
++ {
++
++ if (!cl) /* nothing in, nothing out */
++ return cl;
++
++ if (cl->qstype != qsNormal)
++ free_qs(&cl);
++
++ if (cl)
++ cl->next = qs_normal_part(cl->next);
++
++ return cl;
++ }
++
++ int
++ value_is_space(value)
++ char *value;
++ {
++ for (; value && *value && ISspace((unsigned char) *value); value++);
++
++ return value && *value ? 0 : 1;
++ }
++
++ /*
++ * this function removes trailing spaces from a quote string, but leaves the
++ * last one if there are trailing spaces
++ */
++ QSTRING_S *
++ qs_remove_trailing_spaces(cl)
++ QSTRING_S *cl;
++ {
++ QSTRING_S *rl = cl;
++
++ if (!cl) /* nothing in, nothing out */
++ return cl;
++
++ if (cl->next)
++ cl->next = qs_remove_trailing_spaces(cl->next);
++ else{
++ if (value_is_space(cl->value))
++ free_qs(&cl);
++ else{
++ int i, l;
++ i = l = strlen(cl->value) - 1;
++ while (cl->value && cl->value[i]
++ && ISspace((unsigned char) cl->value[i]))
++ i--;
++ i += (i < l) ? 2 : 1;
++ cl->value[i] = '\0';
++ }
++ }
++
++ return cl;
++ }
++
++ /*
++ * This function returns if two strings are the same quote string.
++ * The call is not symmetric. cl must preceed the line nl. This function
++ * should be called for comparing the last part of cl and nl.
++ */
++ int
++ strcmp_qs(valuecl, valuenl)
++ char *valuecl;
++ char *valuenl;
++ {
++ int j;
++
++ for (j = 0; valuecl[j] && (valuecl[j] == valuenl[j]); j++);
++ return !strcmp(valuecl, valuenl)
++ || (valuenl[j] && value_is_space(valuenl+j)
++ && value_is_space(valuecl+j)
++ && strlenis(valuecl+j) >= strlenis(valuenl+j))
++ || (!valuenl[j] && value_is_space(valuecl+j));
++ }
++
++ int
++ count_levels_qstring(cl)
++ QSTRING_S *cl;
++ {
++ int count;
++ for (count = 0; cl ; count++, cl = cl->next);
++
++ return count;
++ }
++
++ /*
++ * This function returns the number of agreements between
++ * cl and nl. The call is not symmetric. cl must be the line
++ * preceding nl.
++ */
++ int
++ same_qstring(cl,nl)
++ QSTRING_S *cl;
++ QSTRING_S *nl;
++ {
++ int same = 0, done = 0;
++
++ for (;cl && nl && !done; cl = cl->next, nl = nl->next)
++ if ((cl->qstype == nl->qstype) && (!strcmp(cl->value, nl->value)
++ || ((!cl->next) && strcmp_qs(cl->value, nl->value))))
++ same++;
++ else
++ done++;
++
++ return same;
++ }
++
++ QSTRING_S *
++ trim_qs_from_cl(cl, nl, pl)
++ QSTRING_S *cl;
++ QSTRING_S *nl;
++ QSTRING_S *pl;
++ {
++ QSTRING_S *cqstring = pl ? pl : nl;
++ QSTRING_S *tl = pl ? pl : nl;
++ int p, c;
++
++ if (qstring_is_normal(tl))
++ return tl;
++
++ p = same_qstring(pl ? pl : cl, pl ? cl : nl);
++
++ for (c = 1; c < p; c++, cl = cl->next, tl = tl->next);
++
++ /*
++ * cl->next and tl->next differ, it may be because cl->next does not
++ * exist or tl->next does not exist or simply both exist but are
++ * different. In this last case, it may be that cl->next->value is made
++ * of spaces. If this is the case, tl advances once more.
++ */
++
++ if (tl->next){
++ if (cl && cl->next && value_is_space(cl->next->value))
++ tl = tl->next;
++ if (tl->next)
++ free_qs(&(tl->next));
++ }
++
++ if (!p)
++ free_qs(&cqstring);
++
++ return cqstring;
++ }
++
++ /* This function trims cl so that it returns a real quote string based
++ * on information gathered from the previous and next lines. pl and cl are
++ * also trimmed, but that is done in another function, not here.
++ */
++ QSTRING_S *
++ fix_qstring(cl, nl, pl)
++ QSTRING_S *cl;
++ QSTRING_S *nl;
++ QSTRING_S *pl;
++ {
++ QSTRING_S *cqstring = cl, *nqstring = nl, *pqstring = pl;
++ int c, n;
++
++ if (qstring_is_normal(cl))
++ return cl;
++
++ c = count_levels_qstring(cl);
++ n = same_qstring(cl,nl);
++
++ if (!n){ /* no next line or no agreement with next line */
++ int p = same_qstring(pl, cl); /* number of agreements between pl and cl */
++ QSTRING_S *tl; /* test line */
++
++ /*
++ * Here p <= c, so either p < c or p == c. If p == c, we are done,
++ * and return cl. If not, there are two cases, either p == 0 or
++ * 0 < p < c. In the first case, we do not have enough evidence
++ * to return anything other than the normal part of cl, in the second
++ * case we can only return p levels of cl.
++ */
++
++ if (p == c)
++ tl = cqstring;
++ else{
++ if (p){
++ for (c = 1; c < p; c++)
++ cl = cl->next;
++ free_qs(&(cl->next));
++ tl = cqstring;
++ }
++ else{
++ int done = 0;
++ QSTRING_S *al = cl; /* another line */
++ /*
++ * Ok, we reaelly don't have enough evidence to return anything,
++ * different from the normal part of cl, but it could be possible
++ * that we may want to accept the not-normal part, so we better
++ * make an extra test to determine what needs to be freed
++ */
++ while (pl && cl && !strucmp(cl->value, pl->value)){
++ cl = cl->next;
++ pl = pl->next;
++ }
++ if (pl && cl && strcmp_qs(pl->value, cl->value))
++ cl = cl->next; /* next level differs only in spaces */
++ while (!done){
++ while (cl && cl->qstype == qsNormal)
++ cl = cl->next;
++ if (cl){
++ if ((cl->qstype == qsString)
++ && (cl->value[strlen(cl->value) - 1] == '>'))
++ cl = cl->next;
++ else done++;
++ }
++ else done++;
++ }
++ if (al == cl){
++ free_qs(&(cl));
++ tl = cl;
++ }
++ else {
++ while (al && (al->next != cl))
++ al = al->next;
++ cl = al;
++ if (cl && cl->next)
++ free_qs(&(cl->next));
++ tl = cqstring;
++ }
++ }
++ }
++ return tl;
++ }
++ if (n + 1 < c){ /* if there are not enough agreements */
++ int p = same_qstring(pl, cl); /* number of agreement between pl and cl */
++ QSTRING_S *tl; /* test line */
++
++ /*
++ * There's no way we can use cl in this case, but we can use
++ * part of cl, this is if pl does not have more agreements
++ * with cl.
++ */
++
++ if (p == c)
++ tl = cqstring;
++ else{
++ int m = p < n ? n : p;
++ for (c = 1; c < m; c++){
++ pl = pl ? pl->next : (QSTRING_S *) NULL;
++ nl = nl ? nl->next : (QSTRING_S *) NULL;
++ cl = cl->next;
++ }
++ if ((p == n) && pl && pl->next && nl && nl->next
++ && ((cl->next->qstype == pl->next->qstype)
++ || (cl->next->qstype == nl->next->qstype))
++ && (strcmp_qs(cl->next->value, pl->next->value)
++ || strcmp_qs(pl->next->value, cl->next->value)
++ || strcmp_qs(cl->next->value, nl->next->value)
++ || strcmp_qs(nl->next->value, cl->next->value)))
++ cl = cl->next; /* next level differs only in spaces */
++ if (cl->next)
++ free_qs(&(cl->next));
++ tl = cqstring;
++ }
++ return tl;
++ }
++ if (n + 1 == c){
++ int p = same_qstring(pl, cl);
++ QSTRING_S *tl; /* test line */
++
++ /*
++ * p <= c, so p <= n+1, which means p < n + 1 or p == n + 1.
++ * If p < n + 1, then p <= n.
++ * so we have three possibilities:
++ * p == n + 1 or p == n or p < n.
++ * In the first case we copy p == n + 1 == c levels, in the second
++ * and third case we copy n levels, and check if we can copy the
++ * n + 1 == c level.
++ */
++
++ if (p == n + 1) /* p == c, in the above sense of c */
++ tl = cl; /* use cl, this is enough evidence */
++ else{
++ for (c = 1; c < n; c++)
++ cl = cl->next;
++ /*
++ * Here c == n, we only have one more level of cl, and at least one
++ * more level of nl
++ */
++ if (cl->next->qstype == qsNormal)
++ cl = cl->next;
++ if (cl->next)
++ free_qs(&(cl->next));
++ tl = cqstring;
++ }
++ return tl;
++ }
++ if (n == c) /* Yeah!!! */
++ return cqstring;
++ }
++
++ /*
++ * This function flattens the quote string returned to us by is_quote. A
++ * crash in this function implies a bug elsewhere.
++ */
++ void
++ flatten_qstring(qs, buff)
++ QSTRING_S *qs;
++ char *buff;
++ {
++ int i = 0, j;
++
++ for (; qs; qs = qs->next)
++ for (j = 0; (qs->value[j]) && (buff[i++] = qs->value[j]); j++);
++ buff[i] = '\0';
++ }
++
++ /*
++ * Given a string, we return the position where the function thinks that
++ * the quote string is over, if you are ever thinking of fixing something,
++ * you got to the right place. Memory freed by caller. Experience shows
++ * that it only makes sense to initialize memory when we need it, not at
++ * the start of this function.
++ */
++ QSTRING_S *
++ is_quote (qs,word, been_here)
++ char *qs;
++ char word[NSTRING];
++ int been_here;
++ {
++ int i = 0, j, c, nxt, prev, finished = 0, offset;
++ QSTRING_S *qstring = (QSTRING_S *) NULL;
++
++ if (!word || !word[0])
++ return (QSTRING_S *) NULL;
++
++ while (!finished){
++ /*
++ * Before we apply our rules, let's advance past the quote string
++ * given by the user, this will avoid not recognition of the
++ * user's indent string and application of the arbitrary rules
++ * below. Notice that this step may bring bugs into this
++ * procedure, but these bugs will only appear if the indent string
++ * is really really strange and the text to be justified
++ * cooperates a lot too, so in general this will not be a problem.
++ * If you are concerned about this bug, simply remove the
++ * following lines after this comment and before the "switch"
++ * command below and use a more normal quote string!.
++ */
++ i += advance_quote_string(qs, word, i);
++ if (!word[i]) /* went too far? */
++ return qs_add(qs, word, qsNormal, 0, i, 0, 0);
++
++ switch (c = now(word,i)){
++ case NBSP:
++ case TAB :
++ case ' ' : { QSTRING_S *nextqs, *testqs = NULL;
++ int j;
++
++ for (; ISspace((unsigned char) word[i]); i++);
++ nextqs = is_quote(qs,word+i, 1);
++ /*
++ * Merge qstring and nextqs, since this is an artificial
++ * separation, unless nextqs is of different type.
++ * What this means in practice is that if
++ * qs->qstype == qsNormal and qs->next != NULL, then
++ * qs->next->qstype != qsNormal.
++ *
++ * Can't use qs_add to merge because it could lead
++ * to an infinite loop (e.g a line "^ ^").
++ */
++ if (nextqs){
++ if(nextqs->qstype == qsNormal){
++ i += strlen(nextqs->value);
++ testqs = copy_qs(nextqs->next);
++ }
++ else
++ testqs = copy_qs(nextqs);
++ free_qs(&nextqs);
++ }
++
++ qstring = (QSTRING_S *) malloc (sizeof(QSTRING_S));
++ memset (qstring, 0, sizeof(QSTRING_S));
++
++ qstring->value = (char *) malloc((i+1)*sizeof(char));
++ strncpy(qstring->value, word, i);
++ qstring->value[i] = '\0';
++ qstring->qstype = qsNormal;
++
++ qstring->next = testqs;
++
++ return qstring;
++ }
++ break;
++
++ case RPAREN: /* parenthesis ')' */
++ if ((i != 0) || ((i == 0) && been_here))
++ i++;
++ else
++ if (i == 0)
++ return qs_add(qs, word, qsChar, i, i, 1, 1);
++ else
++ finished++;
++ break;
++
++ case ';':
++ case ':': /* colon */
++ case '~': nxt = next(word,i);
++ if (is_tilde(c) && (nxt == '/'))
++ finished++;
++ else if (is_cquote(c)
++ || is_cquote(nxt)
++ || ((c != '~') && (nxt == RPAREN))
++ || ((i != 0) && is_space(nxt))
++ || is_cquote(prev = before(word,i))
++ || (is_space(prev) && !is_tilde(c))
++ || (is_tilde(c) && nxt != '/'))
++ i++;
++ else if (i == 0 && been_here)
++ return qs_add(qs, word, qsChar, i, i, 1, 1);
++ else
++ finished++;
++ break;
++
++ case '<' :
++ case '=' :
++ case '-' : offset = is_cquote(nxt = next(word,i)) ? 2
++ : ((nxt == c)
++ && is_cquote(next(word,i+1))) ? 3 : -1;
++
++ if (offset > 0)
++ return qs_add(qs, word, qsString, i, i, offset, 1);
++ else
++ finished++;
++ break;
++
++ case '[' :
++ case '+' : /* accept +>, *> */
++ case '*' : if (is_rarrow(nxt = next(word, i)) || /* stars */
++ (is_space(nxt) && is_rarrow(next(word,i+1))))
++ i++;
++ else
++ finished++;
++ break;
++
++ case '^' :
++ case '!' :
++ case '%' :
++ case '#' : if (next(word,i) != c)
++ return qs_add(qs, word, qsChar, i, i+1, 0, 1);
++ else
++ finished++;
++ break;
++
++ default:
++ if (is_cquote(c))
++ i++;
++ else if (is_cletter(c)){
++ for (j = i; (is_cletter(nxt = next(word,j)) || is_cnumber(nxt))
++ && !(is_space(nxt));j++);
++ /*
++ * The whole reason why we are splitting the quote
++ * string is so that we will be able to accept quote
++ * strings that are strange in some way. Here we got to
++ * a point in which a quote string might exist, but it
++ * could be strange, so we need to create a "next" field
++ * for the quote string to warn us that something
++ * strange is coming. We need to confirm if this is a
++ * good choice later. For now we will let it pass.
++ */
++ if (isaword(word,i,j) || isamailbox(word,i,j)){
++ int offset;
++ QStrType qstype;
++
++ offset = (is_cquote(c = next(word,j))
++ || (c == RPAREN)) ? 2
++ : ((is_space(c)
++ && is_cquote(next(word,j+1))) ? 3 : -1);
++
++ qstype = (is_cquote(c) || (c == RPAREN))
++ ? (is_qsword(c) ? qsWord : qsString)
++ : ((is_space(c) && is_cquote(next(word,j+1)))
++ ? (is_qsword(next(word,j+1))
++ ? qsWord : qsString)
++ : qsString);
++
++ /*
++ * qsWords are valid quote strings only when
++ * they are followed by text.
++ */
++ if ((offset > 0) && (qstype == qsWord) &&
++ !(allwd_after_qsword(now(word,j + offset))))
++ offset = -1;
++
++ if (offset > 0)
++ return qs_add(qs, word, qstype, i, j, offset, 1);
++ }
++ finished++;
++ }
++ else{
++ if(!forbidden(c))
++ return qs_add(qs, word, qsChar, 0, 1, 0, 1);
++ else /* chao pescao */
++ finished++;
++ }
++ break;
++ } /* End Switch */
++ } /* End while */
++
++ if (i > 0)
++ qstring = qs_add(qs, word, qsNormal, 0, i, 0, 0);
++
++ return qstring;
++ }
++
++ void
++ linencpy(word, l, buflen)
++ char word[NSTRING];
++ LINE *l;
++ int buflen;
++ {
++ int i = 0;
++ for (;(i < buflen) && (i < llength(l)) && (word[i] = (char)lgetc(l,i).c); i++);
++ word[buflen - 1] = '\0';
++ }
++
++
++
++ int
++ isaword(word,i,j)
++ char word[NSTRING];
++ int i;
++ int j;
++ {
++ return i <= j && is_cletter(word[i]) ?
++ (i < j ? isaword(word,i+1,j) : 1) : 0;
++ }
++
++ int
++ isamailbox(word,i,j)
++ char word[NSTRING];
++ int i;
++ int j;
++ {
++ return i <= j && (is_cletter(word[i]) || is_a_digit(word[i])
++ || word[i] == '.')
++ ? (i < j ? isamailbox(word,i+1,j) : 1) : 0;
++ }
++
++
++ /*
++ * This function returns the quote string as a structure. In this way we
++ have two ways to get the quote string: as a char * or as a QSTRING_S *
++ directly.
++ */
++ QSTRING_S *
++ qs_quote_match(q, l, buf, buflen, raw)
++ char *q;
++ LINE *l;
++ char *buf;
++ int buflen;
++ int raw;
++ {
++ char GLine[NSTRING] = {'\0'}, NLine[NSTRING] = {'\0'},
++ PLine[NSTRING] = {'\0'};
++ LINE *nl = l != curbp->b_linep ? lforw(l) : NULL;
++ LINE *pl = lback(l) != curbp->b_linep ? lback(l) : NULL;
++
++ if (nl)
++ linencpy(NLine, nl, NSTRING);
++
++ if (pl)
++ linencpy(PLine, pl, NSTRING);
++
++ linencpy(GLine, l, NSTRING);
++
++ return do_quote_match(q,GLine, NLine, PLine, raw);
++ }
+
+ /*
+! * Return number of quotes if whatever starts the line matches the quote
+! * string
+ */
+! quote_match(q, l, buf, buflen, raw)
+ char *q;
+ LINE *l;
+ char *buf;
+ int buflen;
++ int raw;
+ {
+! QSTRING_S *qs;
+
+! qs = qs_quote_match(q, l, buf, buflen, raw);
+! flatten_qstring(qs, buf);
+! if (qs)
+! free_qs(&qs);
+!
+! return buf && buf[0] ? strlen(buf) : 0;
+! }
+!
+! /*
+! This routine removes the last part that is qsword or qschar that is not
+! followed by a normal part. This means that if a qsword or qschar is
+! followed by a qsnormal (or qsstring), we accept the qsword (or qschar)
+! as part of a quote string.
+! */
+!
+! QSTRING_S *
+! remove_qsword(cl)
+! QSTRING_S *cl;
+! {
+! QSTRING_S *np = cl;
+! QSTRING_S *cp = np; /* this variable trails cl */
+!
+! while(1){
+! while (cl && cl->qstype == qsNormal)
+! cl = cl->next;
+!
+! if (cl){
+! if (((cl->qstype == qsWord) || (cl->qstype == qsChar))
+! && !exists_good_part(cl)){
+! if (np == cl) /* qsword or qschar at the beginning */
+! free_qs(&cp);
+! else{
+! while (np->next != cl)
+! np = np->next;
+! free_qs(&(np->next));
+! }
+! break;
+! }
+! else
+! cl = cl->next;
+! }
+! else
+! break;
+! }
+! return cp;
+! }
+!
+! int
+! exists_good_part (cl)
+! QSTRING_S *cl;
+! {
+! return (cl ? (((cl->qstype != qsWord) && (cl->qstype != qsChar)
+! && !value_is_space(cl->value))
+! ? 1
+! : exists_good_part(cl->next))
+! : 0);
+! }
+!
+!
+! QSTRING_S *
+! do_quote_match(q,GLine, NLine, PLine, raw)
+! char *q;
+! char GLine[NSTRING];
+! char NLine[NSTRING];
+! char PLine[NSTRING];
+! int raw;
+! {
+! QSTRING_S *cl, *nl = NULL, *pl = NULL;
+! int c, n, p,i, j, NewC, NewN, clength, same = 0;
+! char nbuf[NSTRING], pbuf[NSTRING], buf[NSTRING];
+! int emptynl = 0, emptypl = 0;
+!
+! cl = is_quote(q,GLine, 0); /* Current or Given line */
+!
+! if (!cl) /* if nothing in, nothing out */
+! return cl;
+!
+! if (NLine && NLine[0])
+! nl = is_quote(q,NLine, 0); /* Next Line */
+! if (PLine && PLine[0])
+! pl = is_quote(q,PLine, 0); /* Previous Line */
+!
+! /*
+! * If there's nothing in the preceeding or following line
+! * there is not enough information to accept it or discard it. In this
+! * case it's likely to be an isolated line, so we better accept it
+! * if it does not look like a word. */
+!
+! flatten_qstring(pl, pbuf);
+! emptypl = (!PLine || !PLine[0] ||
+! (pl && value_is_space(pbuf)) && !PLine[strlen(pbuf)]) ? 1 : 0;
+! if (emptypl){
+! flatten_qstring(nl, nbuf);
+! emptynl = (!NLine || !NLine[0] ||
+! (nl && value_is_space(nbuf) && !NLine[strlen(nbuf)])) ? 1 : 0;
+! if (emptynl){
+! cl = remove_qsword(cl);
+! cl = qs_remove_trailing_spaces(cl);
+! free_qs(&nl);
+! free_qs(&pl);
+!
+! return cl;
+! }
+! }
+!
+! /*
+! * If either cl, nl or pl contain suspicious characters that may make
+! * them (or not) be quote strings, we need to fix them, so that the
+! * next pass will be done correctly.
+! */
+!
+! cl = fix_qstring(cl, nl, pl);
+! nl = trim_qs_from_cl(cl, nl, NULL);
+! pl = trim_qs_from_cl(cl, NULL, pl);
+! flatten_qstring(cl, buf);
+! flatten_qstring(nl, nbuf);
+! flatten_qstring(pl, pbuf);
+!
+! if (raw){ /* if we are asked for the raw string */
+! free_qs(&nl);
+! free_qs(&pl);
+!
+! return cl; /* return now! */
+! }
+! /*
+! * Once upon a time, is_quote used to return the length of the quote
+! * string that it had found. One day, not long ago, black hand came
+! * and changed all that, and made is_quote return a quote string
+! * divided in several fields, making the algorithm much more
+! * complicated. Fortunately black hand left a few comments in the
+! * source code to make it more understandable. Because of this change
+! * we need to compute the lengths of the quote strings separately
+! */
+! c = buf && buf[0] ? strlen(buf) : 0;
+! n = nbuf && nbuf[0] ? strlen(nbuf) : 0;
+! p = pbuf && pbuf[0] ? strlen(pbuf) : 0;
+!
+! /*
+! * When quote strings contain only blank spaces (ascii code 32) the
+! * above count is equal to the length of the quote string, but if
+! * there are TABS, the length of the quote string as seen by the user
+! * is different than the number that was just computed. Because of
+! * this we demand a recount (hmm.. unless you are in Florida, where
+! * recounts are forbidden)
+! */
+!
+! NewC = strlenis(buf);
+! NewN = strlenis(nbuf);
+!
+! /*
+! * For paragraphs with spaces in the first line, but no space in the
+! * quote string of the second line, we make sure we choose the quote
+! * string without a space at the end of it.
+! */
+! if ((NLine && !NLine[0])
+! && ((PLine && !PLine[0])
+! || (((same = same_qstring(pl, cl)) != 0)
+! && (same != count_levels_qstring(cl)))))
+! cl = qs_remove_trailing_spaces(cl);
+! else
+! if (NewC > NewN){
+! for (j = 0; (j < n) && (GLine[j] == NLine[j]); j++);
+! clength = j;
+! if (j < n){ /* see if buf and nbuf are padded with spaces and tabs */
+! for (i = clength; i < n && ISspace((unsigned char)NLine[i]); i++);
+! if (i == n){
+! for (i = clength; i < c && ISspace((unsigned char)GLine[i]); i++);
+! if (i == c)
+! j = n;
+! }
+ }
+! if (j == n){
+! for (j = clength; j < c && ISspace((unsigned char)GLine[j]); j++);
+! if (j == c){
+!
+! /*
+! * If we get here, it means that the current line has the same
+! * quote string (visually) than the next line, but both of them
+! * are padded with different amount of TABS or spaces at the end.
+! * The current line (GLine) has more spaces/TABs than the next
+! * line. This is the typical situation that is found at the
+! * begining of a paragraph. We need to check this, however, by
+! * checking the previous line. This avoids that we confuse
+! * ourselves with being in the last line of a paragraph.
+! */
+!
+! for (j = 0; (j < p) && (GLine[j] == PLine[j]); j++);
+! if (((p == c) && ((j != p) && NLine[n]))
+! || ((p != c) && NLine[n])){
+! free_qs(&cl);
+! cl = copy_qs(nl);
+! }
+! }
+! }
+! }
+!
+! free_qs(&nl);
+! free_qs(&pl);
+!
+! return cl;
+! }
+!
+! /*
+! * Given a line, an initial position, and a quote string, we advance the
+! * current line past the quote string, including arbitraty spaces
+! * contained in the line, except that it removes trailing spaces. We do
+! * not handle TABs, if any, contained in the quote string. At least not
+! * yet.
+! *
+! * Arguments: q - quote string
+! * l - a line to process
+! * i - position in the line to start processing. i = 0 is the
+! * begining of that line.
+! */
+! int
+! advance_quote_string(q, l, i)
+! char *q;
+! char l[NSTRING];
+! int i;
+! {
+! int n = 0, j = 0, is = 0, es = 0;
+! int k, m, p, adv;
+! char qs[NSTRING] = {'\0'};
+!
+! if(!q || !*q)
+! return(0);
+!
+! for (p = strlen(q); (p > 0) && (q[p - 1] == ' '); p--, es++);
+! if (!p){ /* string contains only spaces */
+! for (k = 0; l[i + k] == ' '; k++);
+! k -= k % es;
+! return k;
+! }
+! for (is = 0; q[is] == ' '; is++); /* count initial spaces */
+! for (m = 0 ; is + m < p ; m++)
+! qs[m] = q[is + m]; /* qs = quote string without any space at the end */
+! /* advance as many spaces as there are at the begining */
+! for (k = 0; l[i + j] == ' '; k++, j++);
+! /* now find the visible string in the line */
+! for (m = 0; qs[m] && l[i + j] == qs[m]; m++, j++);
+! if (!qs[m]){ /* no match */
+! /*
+! * So far we have advanced at least "is" spaces, plus the visible
+! * string "qs". Now we need to advance the trailing number of
+! * spaces "es". If we can do that, we have found the quote string.
+! */
+! for (p = 0; l[i + j + p] == ' '; p++);
+! adv = advance_quote_string(q, l, i + j + ((p < es) ? p : es));
+! n = ((p < es) ? 0 : es) + k + m + adv;
+ }
+! return n;
+ }
+
++ /*
++ * This function returns the effective length in screen of the quote
++ * string. If the string contains a TAB character, it is added here, if
++ * not, the length returned is the length of the string
++ */
++
++ int
++ strlenis(qstr)
++ char *qstr;
++ {
++ int i, rv = 0;
++
++ if (qstr && *qstr){
++ for (i = 0; qstr[i]; i++)
++ rv += ((qstr[i] == TAB) ? (~rv & 0x07) + 1 : 1);
++ }
++ return rv;
++ }
+
+ /* Justify the entire buffer instead of just a paragraph */
+ fillbuf(f, n)
+***************
+*** 475,485 ****
+ int f, n; /* deFault flag and Numeric argument */
+
+ {
+! int i, j, c, qlen, word[NSTRING], same_word,
+! spaces, word_len, line_len, line_last, qn;
+! char *qstr, qstr2[NSTRING];
+ LINE *eopline;
+ REGION region;
+
+ if(curbp->b_mode&MDVIEW){ /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+--- 1491,1503 ----
+ int f, n; /* deFault flag and Numeric argument */
+
+ {
+! int i = 0, j, c, qlen, word[NSTRING], same_word, qlenis,
+! spaces, word_len, line_len, line_last, qn, indlen, qi, pqi;
+! char *qstr, qstr2[NSTRING], tbuf[NSTRING], ind_str[NSTRING],
+! *qstrfl, qstrfl2[NSTRING], quoid[NSTRING];
+ LINE *eopline;
+ REGION region;
++ QSTRING_S *tl;
+
+ if(curbp->b_mode&MDVIEW){ /* don't allow this command if */
+ return(rdonly()); /* we are in read only mode */
+***************
+*** 499,512 ****
+
+ /* and back to the beginning of the paragraph */
+ gotobop(FALSE, 1);
+
+! /* determine if we're justifying quoted text or not */
+ qstr = ((glo_quote_str || (Pmaster && Pmaster->quote_str))
+! && quote_match(glo_quote_str ? glo_quote_str
+! : Pmaster->quote_str,
+! curwp->w_dotp, qstr2, NSTRING)
+! && *qstr2) ? qstr2 : NULL;
+! qlen = qstr ? strlen(qstr) : 0;
+
+ /* let yank() know that it may be restoring a paragraph */
+ thisflag |= CFFILL;
+--- 1517,1602 ----
+
+ /* and back to the beginning of the paragraph */
+ gotobop(FALSE, 1);
++ setimark(FALSE, 1); /* Remember this spot in case we unjustify */
+
+! /*
+! * When a paragraph has special indentation, we will get two quote
+! * strings. One from the first line of the paragraph, and one from
+! * the last line of the paragraph. We will need to use both when
+! * we justify.
+! *
+! * Here's a model of what we will code:
+! *
+! * +-------+-------+-+-----+
+! * | qstrfl|ind_str|X| text|
+! * +-----+-+-------+-+-----+
+! * | qstr| *(space)|X| text|
+! * +-----+---------+-+-----+
+! *
+! * Here X represents 1 space if it exists after ind_str and
+! * "*(space)" represent a variable amount of space that is put there
+! * to pad text so that it will align correctly when justified.
+! */
+! indlen = indent_match((glo_quote_str || (Pmaster && Pmaster->quote_str))
+! ? (glo_quote_str ? glo_quote_str : Pmaster->quote_str)
+! : "", curwp->w_dotp, ind_str, NSTRING, 0);
+! qstrfl = (quote_match((glo_quote_str || (Pmaster && Pmaster->quote_str))
+! ? (glo_quote_str ? glo_quote_str : Pmaster->quote_str)
+! : ">", curwp->w_dotp, qstrfl2, NSTRING,0)
+! && *qstrfl2) ? qstrfl2 : NULL;
+! if (qstrfl){
+! if (glo_quote_str || (Pmaster && Pmaster->quote_str))
+! for (; (i < NSTRING) && (quoid[i] = qstrfl[i]); i++);
+! else{
+! for (; (i < NSTRING) && qstrfl[i] && (quoid[i] = ' '); i++);
+! qstrfl[0] = '\0';
+! }
+! }
+! if (indlen)
+! for (j = 0; ((i + j) < NSTRING) && (quoid[i] = ind_str[j]); i++,j++);
+! quoid[i] = '\0';
+! qi = quoid && quoid[0] ? strlen(quoid) : 0;
+! if (indlen) /* strip trailing spaces */
+! for (;ISspace((unsigned char) quoid[qi - 1]); qi--);
+! quoid[qi] = '\0'; /* we have closed quoid at "X" in the first line */
+!
+! if (strlenis(quoid) > fillcol)
+! return FALSE; /* Too wide, we can't justify this! */
+!
+! /* determine if we're justifying quoted text or not */
+ qstr = ((glo_quote_str || (Pmaster && Pmaster->quote_str))
+! && quote_match(glo_quote_str ? glo_quote_str :
+! Pmaster->quote_str,
+! curwp->w_dotp, qstr2, NSTRING, 0)
+! && *qstr2) ? qstr2 : NULL;
+! /* In some situations, like in the following paragraph, qstr can be non
+! * empty as returned above, when indeed it is empty. Fix it!.
+!
+! * Item #1
+! * Item #2
+! continuation of item #2
+! */
+! if (qstr && indlen){
+! for (i = strlen(qstr) - 1; ISspace((unsigned char) qstr[i]); i--);
+! qstr[i + 1] = '\0';
+! }
+!
+! qlen = qstr ? strlen(qstr) : 0;
+! qlenis = qstr ? strlenis(qstr) : 0;
+!
+! /*
+! * Compare effective lengths of quoid and qstr to decide how much space
+! * we need to use to pad with.
+! */
+! if (indlen && ((j = strlenis(quoid) - strlenis(qstr)) > 0)){
+! pqi = qstr ? strlen(qstr) : 0;
+! for (i = 0; (i < j) && (qstr2[pqi + i] = ' '); i++);
+! if (ISspace((unsigned char) ind_str[indlen - 1]))
+! qstr2[pqi + i++] = ' ';
+! qstr2[pqi + i] = '\0';
+! if (!qstr)
+! qstr = qstr2;
+! }
+
+ /* let yank() know that it may be restoring a paragraph */
+ thisflag |= CFFILL;
+***************
+*** 524,541 ****
+ return(FALSE);
+
+ /* Now insert it back wrapped */
+! spaces = word_len = line_len = same_word = 0;
+
+ /* Beginning with leading quoting... */
+! if(qstr){
+! while(qstr[line_len])
+! linsert(1, qstr[line_len++]);
+
+ line_last = ' '; /* no word-flush space! */
+ }
+
+ /* ...and leading white space */
+! for(i = qlen; (c = fremove(i)) == ' ' || c == TAB; i++){
+ linsert(1, line_last = c);
+ line_len += ((c == TAB) ? (~line_len & 0x07) + 1 : 1);
+ }
+--- 1614,1651 ----
+ return(FALSE);
+
+ /* Now insert it back wrapped */
+! spaces = word_len = line_len = same_word = i = 0;
+
+ /* Beginning with leading quoting... */
+! if(qstrfl){
+! while((tbuf[line_len] = qstrfl[line_len]) == fremove(line_len))
+! linsert(1, qstrfl[line_len++]);
+! /*
+! * The only way that at the end of the above loop we don't have
+! * line_len == qlen is that there are trailing spaces or TABS
+! * which could not be accounted in the qstr in is_quote or other
+! * functions before we got here. Now we enter the common part of
+! * the quote string in the first line and the rest is only spaces
+! * (or TABS) that need to be entered, which are left to the loop
+! * following this "if" statement
+! */
+! i = line_len; /* start next loop from here */
+! tbuf[line_len] = '\0'; /* closing tbuf... */
+! line_len = strlenis(tbuf); /* we demand a recount! */
+! line_last = ' '; /* no word-flush space! */
+! }
+
++ /* ...followed by the indent string, if any */
++ if (indlen){
++ for (i, j = 0; (c = fremove(i)) && ind_str[j]; i++, j++){
++ linsert(1, line_last = c);
++ line_len += ((c == TAB) ? (~line_len & 0x07) + 1 : 1);
++ }
+ line_last = ' '; /* no word-flush space! */
+ }
+
+ /* ...and leading white space */
+! for(i; (c = fremove(i)) == ' ' || c == TAB; i++){
+ linsert(1, line_last = c);
+ line_len += ((c == TAB) ? (~line_len & 0x07) + 1 : 1);
+ }
+***************
+*** 558,572 ****
+
+ default :
+ if(spaces){ /* flush word? */
+! if((line_len - qlen > 0)
+ && line_len + word_len + 1 > fillcol
+! && ((isspace((unsigned char)line_last))
+ || (linsert(1, ' ')))
+ && (line_len = fpnewline(qstr)))
+ line_last = ' '; /* no word-flush space! */
+
+ if(word_len){ /* word to write? */
+! if(line_len && !isspace((unsigned char) line_last)){
+ linsert(1, ' '); /* need padding? */
+ line_len++;
+ }
+--- 1668,1682 ----
+
+ default :
+ if(spaces){ /* flush word? */
+! if((line_len - qlenis > 0)
+ && line_len + word_len + 1 > fillcol
+! && ((ISspace((unsigned char)line_last))
+ || (linsert(1, ' ')))
+ && (line_len = fpnewline(qstr)))
+ line_last = ' '; /* no word-flush space! */
+
+ if(word_len){ /* word to write? */
+! if(line_len && !ISspace((unsigned char) line_last)){
+ linsert(1, ' '); /* need padding? */
+ line_len++;
+ }
+***************
+*** 588,595 ****
+
+ if(word_len + 1 >= NSTRING){
+ /* Magic! Fake that we output a wrapped word */
+! if((line_len - qlen > 0) && !same_word++){
+! if(!isspace((unsigned char) line_last))
+ linsert(1, ' ');
+ line_len = fpnewline(qstr);
+ }
+--- 1698,1705 ----
+
+ if(word_len + 1 >= NSTRING){
+ /* Magic! Fake that we output a wrapped word */
+! if((line_len - qlenis > 0) && !same_word++){
+! if(!ISspace((unsigned char) line_last))
+ linsert(1, ' ');
+ line_len = fpnewline(qstr);
+ }
+***************
+*** 608,619 ****
+ }
+
+ if(word_len){
+! if((line_len - qlen > 0) && (line_len + word_len + 1 > fillcol)){
+! if(!isspace((unsigned char) line_last))
+ linsert(1, ' ');
+! (void) fpnewline(qstr);
+ }
+! else if(line_len && !isspace((unsigned char) line_last))
+ linsert(1, ' ');
+
+ for(j = 0; j < word_len; j++)
+--- 1718,1730 ----
+ }
+
+ if(word_len){
+! if((line_len - qlenis > 0) && (line_len + word_len + 1 > fillcol)){
+! if(!ISspace((unsigned char) line_last))
+ linsert(1, ' ');
+! if (line_len && (line_len != qlenis))
+! (void) fpnewline(qstr);
+ }
+! else if(line_len && !ISspace((unsigned char) line_last))
+ linsert(1, ' ');
+
+ for(j = 0; j < word_len; j++)
+***************
+*** 640,644 ****
+--- 1751,1885 ----
+ for(len = 0; quote && *quote; quote++, len++)
+ linsert(1, *quote);
+
++ quote -= len; /* go back */
++ len = strlenis(quote); /* and recount */
+ return(len);
+ }
++
++ int
++ is_indent (word, plb)
++ char word[NSTRING];
++ int plb;
++ {
++ int i = 0, finished = 0, c, nxt, j, k, digit = 0, bdigits = -1;
++
++ if (!word || !word[0])
++ return i;
++
++ for (i = 0, j = 0; ISspace((unsigned char) word[i]); i++, j++);
++ while ((i < NSTRING - 2) && !finished){
++ switch (c = now(word,i)){
++ case NBSP:
++ case TAB :
++ case ' ' : for (; ISspace((unsigned char )word[i]); i++);
++ if (!is_indent_char(now(word,i)))
++ finished++;
++ break;
++
++ case '+' :
++ case '.' :
++ case ']' :
++ case '*' :
++ case '}' :
++ case '-' :
++ case RPAREN:
++ nxt = next(word,i);
++ if (((c == '.') && allowed_after_period(nxt))
++ || ((c == '*') && allowed_after_star(nxt))
++ || ((c == '}') && allowed_after_braces(nxt))
++ || ((c == '-') && allowed_after_dash(nxt))
++ || ((c == '+') && allowed_after_dash(nxt))
++ || ((c == RPAREN) && allowed_after_parenth(nxt))
++ || ((c == ']') && allowed_after_parenth(nxt)))
++ i++;
++ else
++ finished++;
++ break;
++
++ default : if (is_a_digit(c) && plb){
++ if (bdigits < 0)
++ bdigits = i; /* first digit */
++ for (k = i; is_a_digit(now(word,k)); k++);
++ if (k - bdigits > 2){ /* more than 2 digits? */
++ i = bdigits; /* too many! */
++ finished++;
++ }
++ else{
++ if(allowed_after_digit(now(word,k),word,k))
++ i = k;
++ else{
++ i = bdigits;
++ finished++;
++ }
++ }
++ }
++ else
++ finished++;
++ break;
++ }
++ }
++ if (i == j)
++ i = 0; /* there must be something more than spaces in an indent string */
++ return i;
++ }
++
++
++ /*
++ * If there is an indent string this function returns
++ * its length
++ */
++ int
++ indent_match(q, l, buf, buflen, raw)
++ char *q;
++ LINE *l;
++ char *buf;
++ int buflen;
++ int raw;
++ {
++ char GLine[NSTRING] = {0};
++ int i, j, k, plb;
++
++ k = quote_match(q,l, buf, buflen, raw);
++
++ linencpy(GLine, l, NSTRING);
++
++ plb = (lback(l) != curbp->b_linep) ? lisblank(lback(l)) : 1;
++ if (!plb){
++ i = llength(lback(l)) - 1;
++ for (; i >= 0 && ISspace((unsigned char)lgetc(lback(l), i).c); i--);
++ if (EOLchar(lgetc(lback(l), i).c))
++ plb++;
++ }
++
++ i = is_indent(GLine+k, plb);
++
++ for (j = 0; (j < i) && (buf[j] = GLine[j + k]); j++);
++ buf[j] = '\0';
++
++ return i;
++ }
++
++ deletepara(f, n) /* Delete the current paragraph */
++
++ int f, n; /* deFault flag and Numeric argument */
++
++ {
++ if(curbp->b_mode&MDVIEW){ /* don't allow this command if */
++ return(rdonly()); /* we are in read only mode */
++ }
++
++ if(!lisblank(curwp->w_dotp))
++ gotobop(FALSE, 1);
++
++ curwp->w_markp = curwp->w_dotp;
++ curwp->w_marko = curwp->w_doto;
++
++ gotoeop(FALSE, 1);
++ if (curwp->w_dotp != curbp->b_linep){ /* if we are not at the end of buffer */
++ curwp->w_dotp = lforw(curwp->w_dotp); /* get one more line */
++ curwp->w_doto = 0; /* but only the beginning */
++ }
++ killregion(f,n);
++
++ return(TRUE);
++ }
+diff -rc pine4.63/pine/addrbook.c pine4.63.I.USE/pine/addrbook.c
+*** pine4.63/pine/addrbook.c Tue Apr 26 15:15:46 2005
+--- pine4.63.I.USE/pine/addrbook.c Thu May 19 19:57:32 2005
+***************
+*** 6658,6667 ****
+ *warped;
+ {
+ int find_result, rc, flags;
+ static char search_string[MAX_SEARCH + 1] = { '\0' };
+ char prompt[MAX_SEARCH + 50], nsearch_string[MAX_SEARCH+1];
+ HelpType help;
+! ESCKEY_S ekey[4];
+ PerAddrBook *pab;
+ long nl;
+
+--- 6658,6668 ----
+ *warped;
+ {
+ int find_result, rc, flags;
++ static char last_search_string[MAX_SEARCH + 1] = { '\0' };
+ static char search_string[MAX_SEARCH + 1] = { '\0' };
+ char prompt[MAX_SEARCH + 50], nsearch_string[MAX_SEARCH+1];
+ HelpType help;
+! ESCKEY_S ekey[5];
+ PerAddrBook *pab;
+ long nl;
+
+***************
+*** 6676,6692 ****
+ ekey[0].name = "";
+ ekey[0].label = "";
+
+! ekey[1].ch = ctrl('Y');
+! ekey[1].rval = 10;
+! ekey[1].name = "^Y";
+! ekey[1].label = "First Adr";
+!
+! ekey[2].ch = ctrl('V');
+! ekey[2].rval = 11;
+! ekey[2].name = "^V";
+! ekey[2].label = "Last Adr";
+
+! ekey[3].ch = -1;
+
+ flags = OE_APPEND_CURRENT | OE_KEEP_TRAILING_SPACE;
+ while(1){
+--- 6677,6698 ----
+ ekey[0].name = "";
+ ekey[0].label = "";
+
+! ekey[1].ch = ctrl('N');
+! ekey[1].rval = 9;
+! ekey[1].name = "^N";
+! ekey[1].label = "Ins Pat";
+!
+! ekey[2].ch = ctrl('Y');
+! ekey[2].rval = 10;
+! ekey[2].name = "^Y";
+! ekey[2].label = "First Adr";
+!
+! ekey[3].ch = ctrl('V');
+! ekey[3].rval = 11;
+! ekey[3].name = "^V";
+! ekey[3].label = "Last Adr";
+
+! ekey[4].ch = -1;
+
+ flags = OE_APPEND_CURRENT | OE_KEEP_TRAILING_SPACE;
+ while(1){
+***************
+*** 6697,6702 ****
+--- 6703,6711 ----
+ help = help == NO_HELP ? h_oe_searchab : NO_HELP;
+ continue;
+ }
++ else if(rc == 9)
++ insert_pattern_in_string(nsearch_string, last_search_string
++ , MAX_SEARCH);
+ else if(rc == 10){
+ *warped = 1;
+ warp_to_beginning(); /* go to top of addrbooks */
+***************
+*** 6724,6730 ****
+ }
+ }
+
+! if(rc != 4)
+ break;
+ }
+
+--- 6733,6739 ----
+ }
+ }
+
+! if(rc != 4 && rc != 9)
+ break;
+ }
+
+***************
+*** 6737,6742 ****
+--- 6746,6754 ----
+ search_string[sizeof(search_string)-1] = '\0';
+ }
+
++ strncpy(last_search_string, nsearch_string, sizeof(last_search_string));
++ last_search_string[sizeof(last_search_string)-1] = '\0';
++
+ find_result = find_in_book(cur_line, search_string, new_line, wrapped);
+
+ if(*wrapped == 1)
+diff -rc pine4.63/pine/adrbkcmd.c pine4.63.I.USE/pine/adrbkcmd.c
+*** pine4.63/pine/adrbkcmd.c Thu Mar 31 09:29:09 2005
+--- pine4.63.I.USE/pine/adrbkcmd.c Thu May 19 19:57:26 2005
+***************
+*** 3866,3871 ****
+--- 3866,3873 ----
+ * won't do anything, but will cause compose_mail to think there's
+ * already a role so that it won't try to confirm the default.
+ */
++ if (ps_global->role)
++ fs_give((void **)&ps_global->role);
+ if(role)
+ role = copy_action(role);
+ else{
+***************
+*** 3873,3878 ****
+--- 3875,3881 ----
+ memset((void *)role, 0, sizeof(*role));
+ role->nick = cpystr("Default Role");
+ }
++ ps_global->role = cpystr(role->nick);
+ }
+
+ compose_mail(addr, fcc, role, NULL, NULL);
+diff -rc pine4.63/pine/args.c pine4.63.I.USE/pine/args.c
+*** pine4.63/pine/args.c Wed Mar 9 17:10:34 2005
+--- pine4.63.I.USE/pine/args.c Thu May 19 19:57:27 2005
+***************
+*** 74,79 ****
+--- 74,80 ----
+ char args_err_non_abs_passfile[] = "argument to \"-passfile\" should be fully-qualified";
+ char args_err_missing_lu[] = "missing argument for option \"-create_lu\"\nUsage: pine -create_lu <addrbook_file> <addrbook_sort_type>";
+ char args_err_missing_sort[] = "missing argument for option \"-sort\"";
++ char args_err_missing_thread_sort[] = "missing argument for option \"-threadsort\"";
+ char args_err_missing_flag_arg[] = "missing argument for flag \"%c\"";
+ char args_err_missing_flag_num[] = "Non numeric argument for flag \"%c\"";
+ char args_err_missing_debug_num[] = "Non numeric argument for \"%s\"";
+***************
+*** 117,122 ****
+--- 118,124 ----
+ " -z \t\tSuspend - allow use of ^Z suspension",
+ " -r \t\tRestricted - can only send mail to oneself",
+ " -sort <sort>\tSort - Specify sort order of folder:",
++ " -threadsort <sort>\tSort - Specify sort order of thread index screen:",
+ "\t\t subject, arrival, date, from, size, /reverse",
+ " -i\t\tIndex - Go directly to index, bypassing main menu",
+ " -I <keystroke_list> Initial keystrokes to be executed",
+***************
+*** 202,207 ****
+--- 204,210 ----
+ char *cmd_list = NULL;
+ char *debug_str = NULL;
+ char *sort = NULL;
++ char *threadsort = NULL;
+ char *pinerc_file = NULL;
+ char *addrbook_file = NULL;
+ char *ab_sort_descrip = NULL;
+***************
+*** 389,394 ****
+--- 392,409 ----
+
+ goto Loop;
+ }
++ else if(strcmp(*av, "threadsort") == 0){
++ if(--ac){
++ threadsort = *++av;
++ COM_THREAD_SORT_KEY = cpystr(threadsort);
++ }
++ else{
++ display_args_err(args_err_missing_thread_sort, NULL, 1);
++ ++usage;
++ }
++
++ goto Loop;
++ }
+ else if(strcmp(*av, "url") == 0){
+ if(args->action == aaFolder && !args->data.folder){
+ args->action = aaURL;
+***************
+*** 496,501 ****
+--- 511,522 ----
+ do_version = 1;
+ goto Loop;
+ }
++ else if(strcmp(*av, "subject") == 0){
++ if(--ac){
++ pine_state->subject = cpystr(*++av);
++ }
++ goto Loop;
++ }
+ #ifdef _WINDOWS
+ else if(strcmp(*av, "install") == 0){
+ ps_global->install_flag = 1;
+diff -rc pine4.63/pine/bldaddr.c pine4.63.I.USE/pine/bldaddr.c
+*** pine4.63/pine/bldaddr.c Fri Mar 25 15:33:27 2005
+--- pine4.63.I.USE/pine/bldaddr.c Thu May 19 19:57:26 2005
+***************
+*** 2306,2313 ****
+ if(as.cur >= as.how_many_personals)
+ pab->type |= GLOBAL;
+
+! pab->access = adrbk_access(pab);
+!
+ /* global address books are forced readonly */
+ if(pab->type & GLOBAL && pab->access != NoAccess)
+ pab->access = ReadOnly;
+--- 2306,2319 ----
+ if(as.cur >= as.how_many_personals)
+ pab->type |= GLOBAL;
+
+! if(ps_global->mail_stream &&
+! ps_global->mail_stream->lock && (pab->type & REMOTE_VIA_IMAP)){
+! as.initialized = 0;
+! pab->access = NoAccess;
+! }
+! else{
+! pab->access = adrbk_access(pab);
+! }
+ /* global address books are forced readonly */
+ if(pab->type & GLOBAL && pab->access != NoAccess)
+ pab->access = ReadOnly;
+diff -rc pine4.63/pine/filter.c pine4.63.I.USE/pine/filter.c
+*** pine4.63/pine/filter.c Thu Apr 7 11:00:56 2005
+--- pine4.63.I.USE/pine/filter.c Thu May 19 19:57:30 2005
+***************
+*** 204,209 ****
+--- 204,213 ----
+ error_description(errno)));
+ if(source == TmpFileStar)
+ (void)unlink(so->name);
++ if (ps_global->send_immediately){
++ printf("%s : %s\n", so->name, error_description(errno));
++ exit(1);
++ }
+
+ fs_give((void **)&so->name);
+ fs_give((void **)&so); /* so freed & set to NULL */
+***************
+*** 6764,6769 ****
+--- 6768,6778 ----
+ margin_r,
+ indent;
+ char special[256];
++ long curlinenum; /* current line number */
++ int curqstrpos; /* current position in quote string */
++ long linenum; /* line number */
++ long qstrlen; /* multiples of 100 */
++ char **qstrln; /* qstrln[i] = quote string line i - 1 */
+ } WRAP_S;
+
+ #define WRAP_MARG_L(F) (((WRAP_S *)(F)->opt)->margin_l)
+***************
+*** 6798,6803 ****
+--- 6807,6818 ----
+ #define WRAP_COLOR(F) (((WRAP_S *)(F)->opt)->color)
+ #define WRAP_COLOR_SET(F) ((WRAP_COLOR(F)) && (WRAP_COLOR(F)->fg[0]))
+ #define WRAP_SPACES(F) (((WRAP_S *)(F)->opt)->spaces)
++ #define WRAP_CURLINE(F) (((WRAP_S *)(F)->opt)->curlinenum)
++ #define WRAP_CURPOS(F) (((WRAP_S *)(F)->opt)->curqstrpos)
++ #define WRAP_LINENUM(F) (((WRAP_S *)(F)->opt)->linenum)
++ #define WRAP_QSTRLEN(F) (((WRAP_S *)(F)->opt)->qstrlen)
++ #define WRAP_QSTRN(F) (((WRAP_S *)(F)->opt)->qstrln)
++ #define WRAP_QSTR(F, N) (((WRAP_S *)(F)->opt)->qstrln[(N)])
+ #define WRAP_PUTC(F,C,V) { \
+ if((F)->linep == WRAP_LASTC(F)){ \
+ size_t offset = (F)->linep - (F)->line; \
+***************
+*** 6872,6877 ****
+--- 6887,6894 ----
+ case CCR : /* CRLF or CR in text ? */
+ state = BOL; /* either way, handle start */
+
++ WRAP_CURLINE(f)++;
++ WRAP_CURPOS(f) = 0;
+ if(WRAP_FLOW(f)){
+ if(f->f2 == 0 && WRAP_SPC_LEN(f)){ /* wrapped line */
+ /*
+***************
+*** 6963,6969 ****
+
+ case BOL :
+ if(WRAP_FLOW(f)){
+! if(c == '>'){
+ WRAP_FL_QC(f) = 1; /* init it */
+ state = FL_QLEV; /* go collect it */
+ }
+--- 6980,6989 ----
+
+ case BOL :
+ if(WRAP_FLOW(f)){
+! if(WRAP_QSTR(f, WRAP_CURLINE(f))
+! && WRAP_QSTR(f, WRAP_CURLINE(f))[WRAP_CURPOS(f)]
+! && WRAP_QSTR(f, WRAP_CURLINE(f))[WRAP_CURPOS(f)] == c){
+! WRAP_CURPOS(f)++;
+ WRAP_FL_QC(f) = 1; /* init it */
+ state = FL_QLEV; /* go collect it */
+ }
+***************
+*** 6977,6983 ****
+ }
+
+ /* quote level change implies new paragraph */
+! if(WRAP_FL_QD(f)){
+ WRAP_FL_QD(f) = 0;
+ if(WRAP_HARD(f) == 0){
+ WRAP_HARD(f) = 1;
+--- 6997,7012 ----
+ }
+
+ /* quote level change implies new paragraph */
+! if (WRAP_CURLINE(f) > 0
+! && WRAP_CURLINE(f) < WRAP_QSTRLEN(f)
+! && (WRAP_QSTR(f, WRAP_CURLINE(f)) != NULL
+! || WRAP_QSTR(f, WRAP_CURLINE(f) - 1) != NULL)
+! && ((WRAP_QSTR(f, WRAP_CURLINE(f)) != NULL &&
+! WRAP_QSTR(f, WRAP_CURLINE(f) - 1) == NULL)
+! || (WRAP_QSTR(f, WRAP_CURLINE(f)) == NULL &&
+! WRAP_QSTR(f, WRAP_CURLINE(f) - 1) != NULL)
+! || strcmp(WRAP_QSTR(f, WRAP_CURLINE(f)),
+! WRAP_QSTR(f, WRAP_CURLINE(f) - 1)))){
+ WRAP_FL_QD(f) = 0;
+ if(WRAP_HARD(f) == 0){
+ WRAP_HARD(f) = 1;
+***************
+*** 7029,7036 ****
+ break;
+
+ case FL_QLEV :
+! if(c == '>'){ /* another level */
+! WRAP_FL_QC(f)++;
+ }
+ else {
+ /* if EMBEDed, process it and return here */
+--- 7058,7068 ----
+ break;
+
+ case FL_QLEV :
+! if(WRAP_QSTR(f, WRAP_CURLINE(f))
+! && WRAP_QSTR(f, WRAP_CURLINE(f))[WRAP_CURPOS(f)]
+! && WRAP_QSTR(f, WRAP_CURLINE(f))[WRAP_CURPOS(f)] == c){
+! WRAP_CURPOS(f)++;
+! WRAP_FL_QC(f)++; /* another level */
+ }
+ else {
+ /* if EMBEDed, process it and return here */
+***************
+*** 7042,7048 ****
+ }
+
+ /* quote level change signals new paragraph */
+! if(WRAP_FL_QC(f) != WRAP_FL_QD(f)){
+ WRAP_FL_QD(f) = WRAP_FL_QC(f);
+ if(WRAP_HARD(f) == 0){ /* add hard newline */
+ WRAP_HARD(f) = 1; /* hard newline */
+--- 7074,7089 ----
+ }
+
+ /* quote level change signals new paragraph */
+! if (WRAP_CURLINE(f) > 0
+! && WRAP_CURLINE(f) < WRAP_QSTRLEN(f)
+! && (WRAP_QSTR(f, WRAP_CURLINE(f))
+! || WRAP_QSTR(f, WRAP_CURLINE(f) - 1))
+! && ((WRAP_QSTR(f, WRAP_CURLINE(f)) &&
+! !WRAP_QSTR(f, WRAP_CURLINE(f) - 1))
+! || (!WRAP_QSTR(f, WRAP_CURLINE(f)) &&
+! WRAP_QSTR(f, WRAP_CURLINE(f) - 1))
+! || strcmp(WRAP_QSTR(f, WRAP_CURLINE(f)),
+! WRAP_QSTR(f, WRAP_CURLINE(f) - 1)))){
+ WRAP_FL_QD(f) = WRAP_FL_QC(f);
+ if(WRAP_HARD(f) == 0){ /* add hard newline */
+ WRAP_HARD(f) = 1; /* hard newline */
+***************
+*** 7099,7104 ****
+--- 7140,7151 ----
+ state = FL_SIG;
+ break;
+
++ case ' ' : /* what? */
++ if (WRAP_QSTR(f, WRAP_CURLINE(f))){
++ WRAP_SPC_LEN(f)++;
++ so_writec(' ', WRAP_SPACES(f));
++ }
++
+ default : /* something else */
+ state = DFL;
+ goto case_dfl; /* handle c like DFL */
+***************
+*** 7115,7121 ****
+ &eob); /* note any embedded*/
+ wrap_eol(f, 1, &ip, &eib,
+ &op, &eob); /* plunk down newline */
+! wrap_bol(f, 1, 1, &ip, &eib,
+ &op, &eob); /* write any prefix */
+ }
+
+--- 7162,7168 ----
+ &eob); /* note any embedded*/
+ wrap_eol(f, 1, &ip, &eib,
+ &op, &eob); /* plunk down newline */
+! wrap_bol(f, 1, WRAP_FLOW(f), &ip, &eib,
+ &op, &eob); /* write any prefix */
+ }
+
+***************
+*** 7420,7426 ****
+ wrap_flush_embed(f, &ip, &eib, &op, &eob);
+ wrap_eol(f, 1, &ip, &eib, &op,
+ &eob); /* plunk down newline */
+! wrap_bol(f,1,1, &ip, &eib, &op,
+ &eob); /* write any prefix */
+ }
+
+--- 7467,7473 ----
+ wrap_flush_embed(f, &ip, &eib, &op, &eob);
+ wrap_eol(f, 1, &ip, &eib, &op,
+ &eob); /* plunk down newline */
+! wrap_bol(f,1,WRAP_FLOW(f), &ip, &eib, &op,
+ &eob); /* write any prefix */
+ }
+
+***************
+*** 7478,7483 ****
+--- 7525,7537 ----
+ if(WRAP_COLOR(f))
+ free_color_pair(&WRAP_COLOR(f));
+
++ { long i;
++ for (i = 0L; i < WRAP_QSTRLEN(f); i++)
++ if (WRAP_QSTR(f,i))
++ fs_give((void **) &(WRAP_QSTR(f,i)));
++ fs_give((void **)&WRAP_QSTRN(f));
++ }
++
+ fs_give((void **) &f->line); /* free temp line buffer */
+ so_give(&WRAP_SPACES(f));
+ fs_give((void **) &f->opt); /* free wrap widths struct */
+***************
+*** 7799,7805 ****
+ {
+ int j, i;
+ COLOR_PAIR *col = NULL;
+! char *prefix = NULL, *last_prefix = NULL;
+
+ if(ps_global->VAR_QUOTE_REPLACE_STRING){
+ get_pair(ps_global->VAR_QUOTE_REPLACE_STRING, &prefix, &last_prefix, 0, 0);
+--- 7853,7860 ----
+ {
+ int j, i;
+ COLOR_PAIR *col = NULL;
+! char *prefix = NULL, *last_prefix = NULL, *wrap_qstr = NULL;
+! int level = 0, oldj, len;
+
+ if(ps_global->VAR_QUOTE_REPLACE_STRING){
+ get_pair(ps_global->VAR_QUOTE_REPLACE_STRING, &prefix, &last_prefix, 0, 0);
+***************
+*** 7808,7817 ****
+ last_prefix = NULL;
+ }
+ }
+!
+! for(j = 0; j < WRAP_FL_QD(f); j++){
+ if(WRAP_USE_CLR(f)){
+! if((j % 3) == 0
+ && ps_global->VAR_QUOTE1_FORE_COLOR
+ && ps_global->VAR_QUOTE1_BACK_COLOR
+ && (col = new_color_pair(ps_global->VAR_QUOTE1_FORE_COLOR,
+--- 7863,7884 ----
+ last_prefix = NULL;
+ }
+ }
+!
+! if(WRAP_QSTR(f, WRAP_CURLINE(f)))
+! wrap_qstr = cpystr(WRAP_QSTR(f, WRAP_CURLINE(f)));
+! len = wrap_qstr ? strlen(wrap_qstr) : 0;
+!
+! for (j = wrap_qstr && *wrap_qstr == ' ' ? 1 : 0;
+! j < len && isspace((unsigned char)wrap_qstr[j]); j++){
+! GF_PUTC_GLO(f->next, wrap_qstr[j]);
+! f->n += ((wrap_qstr[j] == TAB) ? (~f->n & 0x07) + 1 : 1);
+! }
+!
+! for(; j < len && level < len; level++){
+! oldj = j;
+! j = next_level_quote(wrap_qstr, (char **)NULL, j, WRAP_FLOW(f));
+ if(WRAP_USE_CLR(f)){
+! if((level % 3) == 0
+ && ps_global->VAR_QUOTE1_FORE_COLOR
+ && ps_global->VAR_QUOTE1_BACK_COLOR
+ && (col = new_color_pair(ps_global->VAR_QUOTE1_FORE_COLOR,
+***************
+*** 7819,7825 ****
+ && pico_is_good_colorpair(col)){
+ GF_COLOR_PUTC(f, col);
+ }
+! else if((j % 3) == 1
+ && ps_global->VAR_QUOTE2_FORE_COLOR
+ && ps_global->VAR_QUOTE2_BACK_COLOR
+ && (col = new_color_pair(ps_global->VAR_QUOTE2_FORE_COLOR,
+--- 7886,7892 ----
+ && pico_is_good_colorpair(col)){
+ GF_COLOR_PUTC(f, col);
+ }
+! else if((level % 3) == 1
+ && ps_global->VAR_QUOTE2_FORE_COLOR
+ && ps_global->VAR_QUOTE2_BACK_COLOR
+ && (col = new_color_pair(ps_global->VAR_QUOTE2_FORE_COLOR,
+***************
+*** 7827,7833 ****
+ && pico_is_good_colorpair(col)){
+ GF_COLOR_PUTC(f, col);
+ }
+! else if((j % 3) == 2
+ && ps_global->VAR_QUOTE3_FORE_COLOR
+ && ps_global->VAR_QUOTE3_BACK_COLOR
+ && (col = new_color_pair(ps_global->VAR_QUOTE3_FORE_COLOR,
+--- 7894,7900 ----
+ && pico_is_good_colorpair(col)){
+ GF_COLOR_PUTC(f, col);
+ }
+! else if((level % 3) == 2
+ && ps_global->VAR_QUOTE3_FORE_COLOR
+ && ps_global->VAR_QUOTE3_BACK_COLOR
+ && (col = new_color_pair(ps_global->VAR_QUOTE3_FORE_COLOR,
+***************
+*** 7840,7884 ****
+ col = NULL;
+ }
+ }
+
+! if(!WRAP_LV_FLD(f)){
+! if(ps_global->VAR_QUOTE_REPLACE_STRING && prefix){
+! for(i = 0; prefix[i]; i++)
+! GF_PUTC_GLO(f->next, prefix[i]);
+! f->n += strlen(prefix);
+! }
+! else if(ps_global->VAR_REPLY_STRING
+! && (!strcmp(ps_global->VAR_REPLY_STRING, ">")
+! || !strcmp(ps_global->VAR_REPLY_STRING, "\">\""))){
+! GF_PUTC_GLO(f->next, '>');
+! f->n += 1;
+! }
+! else{
+! GF_PUTC_GLO(f->next, '>');
+! GF_PUTC_GLO(f->next, ' ');
+! f->n += 2;
+! }
+ }
+ else{
+! GF_PUTC_GLO(f->next, '>');
+! f->n += 1;
+ }
+ }
+ if(j && WRAP_LV_FLD(f)){
+ GF_PUTC_GLO(f->next, ' ');
+ f->n++;
+ }
+! else if(j && last_prefix){
+ for(i = 0; last_prefix[i]; i++)
+ GF_PUTC_GLO(f->next, last_prefix[i]);
+! f->n += strlen(last_prefix);
+ }
+
+ if(prefix)
+ fs_give((void **)&prefix);
+ if(last_prefix)
+ fs_give((void **)&last_prefix);
+!
+ return 0;
+ }
+
+--- 7907,7960 ----
+ col = NULL;
+ }
+ }
++ if (j > 1 && wrap_qstr[j-1] == ' ')
++ j -= 1;
+
+! if(!WRAP_LV_FLD(f) && ps_global->VAR_QUOTE_REPLACE_STRING && prefix){
+! for(i = 0; prefix[i]; i++)
+! GF_PUTC_GLO(f->next, prefix[i]);
+! f->n += strlenis(prefix);
+ }
+ else{
+! for (i = oldj; i < j; i++)
+! GF_PUTC_GLO(f->next, wrap_qstr[i]);
+! f->n += j - oldj;
+! }
+! for (i = j; isspace((unsigned char)wrap_qstr[i]); i++);
+! if(!wrap_qstr[i]){
+! f->n += i - j;
+! for (; j < i; j++)
+! GF_PUTC_GLO(f->next, ' ');
+ }
++ else{
++ if((WRAP_LV_FLD(f)
++ || !ps_global->VAR_QUOTE_REPLACE_STRING || !prefix)
++ || !ps_global->VAR_REPLY_STRING
++ || (strcmp(ps_global->VAR_REPLY_STRING, ">")
++ && strcmp(ps_global->VAR_REPLY_STRING, "\">\""))){
++ GF_PUTC_GLO(f->next, ' ');
++ f->n += 1;
++ }
++ }
++ for (; isspace((unsigned char)wrap_qstr[j]); j++);
+ }
+ if(j && WRAP_LV_FLD(f)){
+ GF_PUTC_GLO(f->next, ' ');
+ f->n++;
+ }
+! else if(j && !value_is_space(wrap_qstr) && last_prefix){
+ for(i = 0; last_prefix[i]; i++)
+ GF_PUTC_GLO(f->next, last_prefix[i]);
+! f->n += strlenis(last_prefix);
+ }
+
+ if(prefix)
+ fs_give((void **)&prefix);
+ if(last_prefix)
+ fs_give((void **)&last_prefix);
+! if (wrap_qstr)
+! fs_give((void **)&wrap_qstr);
+!
+ return 0;
+ }
+
+***************
+*** 7909,7914 ****
+--- 7985,7996 ----
+ wrap->leave_flowed = (GFW_FLOW_RESULT & flags) == GFW_FLOW_RESULT;
+ wrap->delsp = (GFW_DELSP & flags) == GFW_DELSP;
+ wrap->use_color = (GFW_USECOLOR & flags) == GFW_USECOLOR;
++ wrap->curlinenum = 0L;
++ wrap->curqstrpos = 0;
++ wrap->linenum = 0L;
++ wrap->qstrlen = 100L;
++ wrap->qstrln = (char **) fs_get(100*sizeof(char *));
++ memset(wrap->qstrln, 0, 100*sizeof(char *));
+
+ return((void *) wrap);
+ }
+***************
+*** 8330,8336 ****
+--- 8412,8595 ----
+ } \
+ }
+
++ #define ADD_QUOTE_STRING(F) { \
++ int len = tmp_20k_buf[0] ? strlen(tmp_20k_buf) + 1 : 0; \
++ FILTER_S *fltr; \
++ \
++ for(fltr = (F); fltr && fltr->f != gf_wrap; fltr = fltr->next);\
++ if (fltr){ \
++ if (WRAP_LINENUM(fltr) >= WRAP_QSTRLEN(fltr)){ \
++ fs_resize((void **)&WRAP_QSTRN(fltr), \
++ (WRAP_QSTRLEN(fltr) + 100) * sizeof(char *)); \
++ memset(WRAP_QSTRN(fltr)+WRAP_QSTRLEN(fltr), 0, \
++ 100*sizeof(char*)); \
++ WRAP_QSTRLEN(fltr) += 100L; \
++ } \
++ if (len){ \
++ WRAP_QSTR(fltr, WRAP_LINENUM(fltr)) = \
++ (char *) fs_get(len*sizeof(char)); \
++ WRAP_QSTR(fltr, WRAP_LINENUM(fltr)) = cpystr(tmp_20k_buf);\
++ } \
++ WRAP_LINENUM(fltr)++; \
++ } \
++ }
++
++ #define GF_ADD_QUOTED_LINE(F, line) \
++ { \
++ LT_INS_S *ins = NULL, *insp; \
++ int done;\
++ unsigned char ch;\
++ register char *cp;\
++ register int l;\
++ \
++ if (line){\
++ done = (*((LINETEST_S *) (F)->opt)->f)((F)->n++,\
++ line, &ins,\
++ ((LINETEST_S *) (F)->opt)->local);\
++ if (done < 2){ \
++ ADD_QUOTE_STRING((F));\
++ for(insp = ins, cp = line; *cp ; ){\
++ while(insp && cp == insp->where){\
++ for(l = 0; l < insp->len; l++){\
++ ch = (unsigned char) insp->text[l];\
++ GF_PUTC((F)->next, ch);\
++ }\
++ insp = insp->next;\
++ }\
++ GF_PUTC((F)->next, *cp);\
++ cp++;\
++ }\
++ while(insp){\
++ for(l = 0; l < insp->len; l++){\
++ ch = (unsigned char) insp->text[l];\
++ GF_PUTC((F)->next, ch);\
++ }\
++ insp = insp->next;\
++ }\
++ gf_line_test_free_ins(&ins);\
++ GF_PUTC((F)->next, '\015');\
++ GF_PUTC((F)->next, '\012');\
++ }\
++ }\
++ }
++ /* test second line of old line first */
++ #define SECOND_LINE_QUOTE_TEST(line, F) \
++ {\
++ *p = '\0';\
++ for (i = 0; ((F)->oldline)[i] && ((F)->oldline)[i] != '\015'; i++);\
++ if (((F)->oldline)[i]){\
++ i += (((F)->oldline)[i+1] == '\012') ? 2 : 1;\
++ line = (F)->oldline + i;\
++ }\
++ for (i = 0; ((F)->line) \
++ && (i < LINE_TEST_BLOCK) \
++ && (i < SIZEOF_20KBUF)\
++ && ((F)->line)[i] \
++ && (((F)->line)[i] != '\015')\
++ && (((F)->line)[i] != '\012')\
++ && (tmp_20k_buf[i] = ((F)->line)[i]); i++);\
++ tmp_20k_buf[i] = '\0';\
++ GF_ADD_QUOTED_LINE((F), line);\
++ }
++
++ #define FIRST_LINE_QUOTE_TEST(line, F)\
++ {\
++ *p = '\0';\
++ line = (F)->line;\
++ (F)->oldline = cpystr(line);\
++ for (i = 0; line[i] && line[i] != '\015' && line[i] != '\012'; i++); \
++ if (line[i]){\
++ (line[i]) = '\0'; \
++ i+= (line[i+1] == '\012') ? 2 : 1;\
++ }\
++ for (j = 0; ((F)->line) \
++ && ((i + j) < LINE_TEST_BLOCK) \
++ && (j < SIZEOF_20KBUF) \
++ && ((F)->line)[i + j] \
++ && (((F)->line)[i + j] != '\015')\
++ && (((F)->line)[i + j] != '\012')\
++ && (tmp_20k_buf[j] = ((F)->line)[i + j]); j++);\
++ tmp_20k_buf[j] = '\0';\
++ GF_ADD_QUOTED_LINE((F), line);\
++ }
++
++
++ void
++ gf_quote_test(f, flg)
++ FILTER_S *f;
++ int flg;
++ {
++ register char *p = f->linep;
++ register char *eobuf = GF_LINE_TEST_EOB(f);
++ char *line = NULL;
++ int i, j;
++ GF_INIT(f, f->next);
++
++ if(flg == GF_DATA){
++ register unsigned char c;
++ register int state = f->f1;
++
++ while(GF_GETC(f, c)){
++
++ if(state == 2){ /* two full lines read */
++ state = 0;
++
++ /* first process the second line of an old line */
++ if (f->oldline && f->oldline[0])
++ SECOND_LINE_QUOTE_TEST(line, f);
++
++ /* now we process the first line */
++ FIRST_LINE_QUOTE_TEST(line, f);
+
++ p = f->line;
++ continue;
++ }
++ if(c == '\015'){
++ state++;
++ if (state == 1)
++ GF_LINE_TEST_ADD(f, c);
++ }
++ else
++ GF_LINE_TEST_ADD(f, c);
++ }
++
++ f->f1 = state;
++ GF_END(f, f->next);
++ }
++ else if(flg == GF_EOD){
++ /* first process the second line of an old line */
++ if (f->oldline && f->oldline[0])
++ SECOND_LINE_QUOTE_TEST(line, f);
++
++ /* now we process the first line */
++ FIRST_LINE_QUOTE_TEST(line, f);
++
++ /* We are out of data. In this case we have processed the second
++ * line of an oldline, then the first line of a line, but we need
++ * to process the second line of the given line. We do this by
++ * processing it now!.
++ */
++ if (line[i]){
++ tmp_20k_buf[0] = '\0'; /* No next line */
++ GF_ADD_QUOTED_LINE(f, line+i);
++ }
++
++ fs_give((void **) &f->oldline); /* free old line buffer */
++ fs_give((void **) &f->line); /* free line buffer */
++ fs_give((void **) &f->opt); /* free test struct */
++ GF_FLUSH(f->next);
++ (*f->next->f)(f->next, GF_EOD);
++ }
++ else if(flg == GF_RESET){
++ dprint(9, (debugfile, "-- gf_reset line_test\n"));
++ f->f1 = 0; /* state */
++ f->n = 0L; /* line number */
++ f->f2 = LINE_TEST_BLOCK; /* size of alloc'd line */
++ f->line = p = (char *) fs_get(f->f2 * sizeof(char));
++ }
++
++ f->linep = p;
++ }
+
+ /*
+ * this simple filter accumulates characters until a newline, offers it
+***************
+*** 8355,8361 ****
+ if(state){
+ state = 0;
+ if(c == '\012'){
+! int done;
+
+ GF_LINE_TEST_TEST(f, done);
+
+--- 8614,8625 ----
+ if(state){
+ state = 0;
+ if(c == '\012'){
+! int done, i, j = 0;
+!
+! for (i = 0; op && op[i] && (i < LINE_TEST_BLOCK) &&
+! (i < SIZEOF_20KBUF) && (op[i] != '\015') &&
+! (tmp_20k_buf[i] = op[i]); i++);
+! tmp_20k_buf[i] = '\0';
+
+ GF_LINE_TEST_TEST(f, done);
+
+***************
+*** 8417,8422 ****
+--- 8681,8687 ----
+ else if(flg == GF_EOD){
+ int i;
+
++ tmp_20k_buf[0] = '\0';
+ GF_LINE_TEST_TEST(f, i); /* examine remaining data */
+ fs_give((void **) &f->line); /* free line buffer */
+ fs_give((void **) &f->opt); /* free test struct */
+diff -rc pine4.63/pine/folder.c pine4.63.I.USE/pine/folder.c
+*** pine4.63/pine/folder.c Mon Apr 4 11:42:52 2005
+--- pine4.63.I.USE/pine/folder.c Thu May 19 19:57:31 2005
+***************
+*** 94,100 ****
+ #define FLW_SLCT 0x02
+ #define FLW_LIST 0x04
+
+!
+
+
+ /*----------------------------------------------------------------------
+--- 94,100 ----
+ #define FLW_SLCT 0x02
+ #define FLW_LIST 0x04
+
+! static int max_slot_size = 0;
+
+
+ /*----------------------------------------------------------------------
+***************
+*** 224,229 ****
+--- 224,230 ----
+ gf_io_t, HANDLE_S **, int));
+ int folder_list_write_folder PROTO((gf_io_t, CONTEXT_S *,
+ int, char *, int));
++ int folder_list_write_count PROTO((FOLDER_S *, CONTEXT_S *, gf_io_t, int));
+ int folder_list_write_prefix PROTO((FOLDER_S *, int, gf_io_t));
+ int folder_list_ith PROTO((int, CONTEXT_S *));
+ char *folder_list_center_space PROTO((char *, int));
+***************
+*** 469,475 ****
+
+ HELP_MENU,
+ OTHER_MENU,
+! NULL_MENU,
+ NULL_MENU,
+ NULL_MENU,
+ NULL_MENU,
+--- 470,476 ----
+
+ HELP_MENU,
+ OTHER_MENU,
+! {"^H","ChkIncFld",{MC_FORCECHECK,1,ctrl('H')}, KS_NONE},
+ NULL_MENU,
+ NULL_MENU,
+ NULL_MENU,
+***************
+*** 1708,1713 ****
+--- 1709,1715 ----
+ gf_io_t pc;
+
+ dprint(1, (debugfile, "\n\n ---- FOLDER LISTER ----\n"));
++ ps->in_fld_list = 1;
+
+ memset(&folder_proc_data, 0, sizeof(FPROC_S));
+ folder_proc_data.fs = fs;
+***************
+*** 1842,1847 ****
+--- 1844,1850 ----
+ *fs->cache_streamp = NULL;
+ }
+
++ ps->in_fld_list = 0;
+ return(folder_proc_data.rv);
+ }
+
+***************
+*** 1955,1960 ****
+--- 1958,1975 ----
+ gf_puts("\n", pc);
+ }
+
++ if (c_list->use & CNTXT_INCMNG &&
++ F_ON(F_ENABLE_INCOMING_CHECK,ps_global) &&
++ F_ON(F_ENABLE_INCOMING,ps_global) &&
++ F_OFF(F_ENABLE_FAST_RECENT, ps_global)){
++ sprintf(tmp_20k_buf,
++ "Format: Folder-name [Total New Messages/Total Messages]");
++ gf_puts(folder_list_center_space(tmp_20k_buf, cols), pc);
++ gf_puts(tmp_20k_buf, pc);
++ gf_puts("\n", pc);
++ }
++
++
+ gf_puts(repeat_char(cols, '-'), pc);
+ gf_puts("\n\n", pc);
+ }
+***************
+*** 1992,1999 ****
+--- 2007,2027 ----
+ else if(c_list == fp->fs->list_cntxt)
+ len += 4; /* "[X] " */
+
++ if (c_list->use & CNTXT_INCMNG &&
++ F_ON(F_ENABLE_INCOMING_CHECK,ps_global) &&
++ F_ON(F_ENABLE_INCOMING,ps_global) &&
++ F_OFF(F_ENABLE_FAST_RECENT, ps_global))
++ if (need_folder_report(FLDR_NAME(f))){
++ len += 5; /* "[/]" + " " */
++ len += strlen(comatose(f->countrecent));
++ len += strlen(comatose(f->messages));
++ }
++ else
++ len += 1;
++
+ if(slot_size < len)
+ slot_size = len;
++ max_slot_size = slot_size;
+ }
+
+ if(F_ON(F_SINGLE_FOLDER_LIST, ps_global)){
+***************
+*** 2098,2104 ****
+ int flags;
+ {
+ char buf[256];
+! int l = 0;
+ FOLDER_S *fp;
+ HANDLE_S *h;
+
+--- 2126,2132 ----
+ int flags;
+ {
+ char buf[256];
+! int l = 0, s = 0;
+ FOLDER_S *fp;
+ HANDLE_S *h;
+
+***************
+*** 2121,2126 ****
+--- 2149,2155 ----
+ && (*pc)(strlen(buf)) && gf_puts(buf, pc)) : 1)
+ && (fp ? ((l = folder_list_write_prefix(fp, flags, pc)) >= 0
+ && gf_puts(FLDR_NAME(fp), pc)
++ && (s = folder_list_write_count(fp, ctxt, pc, l)) >= 0
+ && ((fp->isdir && fp->isfolder) ? (*pc)('[') : 1)
+ && ((fp->isdir) ? (*pc)(ctxt->dir->delim) : 1)
+ && ((fp->isdir && fp->isfolder) ? (*pc)(']') : 1))
+***************
+*** 2128,2134 ****
+ && (h ? ((*pc)(TAG_EMBED) && (*pc)(TAG_BOLDOFF)
+ && (*pc)(TAG_EMBED) && (*pc)(TAG_INVOFF)) : 1)){
+ if(fp){
+! l += strlen(FLDR_NAME(fp));
+ if(fp->isdir)
+ l += (fp->isfolder) ? 3 : 1;
+ }
+--- 2157,2163 ----
+ && (h ? ((*pc)(TAG_EMBED) && (*pc)(TAG_BOLDOFF)
+ && (*pc)(TAG_EMBED) && (*pc)(TAG_INVOFF)) : 1)){
+ if(fp){
+! l += strlen(FLDR_NAME(fp)) + s;
+ if(fp->isdir)
+ l += (fp->isfolder) ? 3 : 1;
+ }
+***************
+*** 2139,2144 ****
+--- 2168,2203 ----
+ return(l);
+ }
+
++ int
++ folder_list_write_count(f, ctxt, pc, l)
++ FOLDER_S *f;
++ CONTEXT_S *ctxt;
++ gf_io_t pc;
++ int l;
++ {
++ int rv = 0, i;
++ int offset = 1;
++
++ if (ctxt->use & CNTXT_INCMNG &&
++ F_ON(F_ENABLE_INCOMING_CHECK,ps_global) &&
++ F_ON(F_ENABLE_INCOMING,ps_global) &&
++ F_OFF(F_ENABLE_FAST_RECENT, ps_global) &&
++ need_folder_report(FLDR_NAME(f))){
++ rv = max_slot_size - strlen(FLDR_NAME(f)) - l;
++ rv -= strlen(comatose(f->countrecent));
++ rv -= strlen(comatose(f->messages));
++ rv -= 5 + offset;
++ for (i = 0; i <= rv; i++) gf_puts(" ", pc);
++ gf_puts("[", pc);
++ gf_puts(comatose(f->countrecent), pc);
++ gf_puts("/", pc);
++ gf_puts(comatose(f->messages), pc);
++ gf_puts("]", pc);
++ rv = max_slot_size - strlen(FLDR_NAME(f)) - l - offset -1;
++ }
++ return rv;
++ }
++
+
+ int
+ folder_list_write_prefix(f, flags, pc)
+***************
+*** 2224,2229 ****
+--- 2283,2301 ----
+ p = strchr(p, fs->context->dir->delim))
+ name = ++p;
+
++ if(fs->context->use & CNTXT_INCMNG){
++ FOLDER_S *f;
++ int total = folder_total(FOLDERS(fs->context)), index;
++ for(index = folder_index(ps_global->inbox_name, fs->context, FI_FOLDER);
++ index >= 0 && index < total
++ && (f = folder_entry(index, FOLDERS(fs->context)))
++ && !f->isdir; index++)
++ if(!strcmp(fs->first_folder, f->name)){
++ name = FLDR_NAME(f);
++ break;
++ }
++ }
++
+ for(h = handles; h; h = h->next)
+ if(h->h.f.context == fs->context){
+ if(!h_found) /* match at least given context */
+***************
+*** 2462,2468 ****
+ "Empty folder collection. No folder to rename!");
+
+ break;
+!
+
+ /*-------------- Delete --------------------*/
+ case MC_DELETE :
+--- 2534,2549 ----
+ "Empty folder collection. No folder to rename!");
+
+ break;
+!
+!
+! /*------- Check incoming forlders -------*/
+! case MC_FORCECHECK:
+! ps_global->force_check_now = 1;
+! rv = (new_mail_incfolder(ps_global,MC_FORCECHECK) &&
+! ps_global->refresh_list > 0) ? 1 : 0;
+! ps_global->refresh_list = 0;
+! break;
+!
+
+ /*-------------- Delete --------------------*/
+ case MC_DELETE :
+***************
+*** 2783,2792 ****
+ if(we_cancel)
+ cancel_busy_alarm(-1);
+
+! if(gotit)
+ sprintf(tmp_output,
+ "%lu total message%.2s, %lu of them recent",
+ tot, plural(tot), rec);
+ }
+ }else
+ strncpy(tmp_output, "No folder to check! Can't get recent info",
+--- 2864,2880 ----
+ if(we_cancel)
+ cancel_busy_alarm(-1);
+
+! if(gotit){
+ sprintf(tmp_output,
+ "%lu total message%.2s, %lu of them recent",
+ tot, plural(tot), rec);
++ folder->countrecent = rec;
++ folder->messages = tot;
++ if (rec > 0L)
++ folder->notified = 1;
++ folder->selected = rec > 0L ? 1 : folder->user_selected;
++ ps_global->refresh_list++;
++ }
+ }
+ }else
+ strncpy(tmp_output, "No folder to check! Can't get recent info",
+***************
+*** 3323,3330 ****
+ case 'f' : /* flip selection */
+ n = folder_total(FOLDERS(context));
+ for(total = i = 0; i < n; i++)
+! if(f = folder_entry(i, FOLDERS(context)))
+ f->selected = !f->selected;
+
+ return(1); /* repaint */
+
+--- 3411,3420 ----
+ case 'f' : /* flip selection */
+ n = folder_total(FOLDERS(context));
+ for(total = i = 0; i < n; i++)
+! if(f = folder_entry(i, FOLDERS(context))){
+ f->selected = !f->selected;
++ f->user_selected = f->selected;
++ }
+
+ return(1); /* repaint */
+
+***************
+*** 3467,3481 ****
+ CONTEXT_S *context;
+ {
+ int i, n, total;
+
+ n = folder_total(FOLDERS(context));
+! for(total = i = 0; i < n; i++)
+! if(folder_entry(i, FOLDERS(context))->selected)
+ total++;
+
+ return(total);
+ }
+
+
+ SELECTED_S *
+ new_selected()
+--- 3557,3620 ----
+ CONTEXT_S *context;
+ {
+ int i, n, total;
++ FOLDER_S *f;
+
+ n = folder_total(FOLDERS(context));
+! for(total = i = 0; i < n; i++){
+! f = folder_entry(i, FOLDERS(context));
+! if(f->selected)
+ total++;
++ }
+
+ return(total);
+ }
+
++ void
++ update_incoming_folder_data(stream, context)
++ MAILSTREAM *stream;
++ CONTEXT_S *context;
++ {
++ FOLDER_S *f = incoming_folder_data(stream, context);
++
++ if(f){
++ f->origrecent = f->recent = stream->recent;
++ f->messages = stream->nmsgs;
++ }
++ }
++
++
++ FOLDER_S *
++ incoming_folder_data(stream, cntxt)
++ MAILSTREAM *stream;
++ CONTEXT_S *cntxt;
++ {
++ long index, total, done = 0;
++ FOLDER_S *f = NULL;
++
++ if (cntxt && cntxt->use & CNTXT_INCMNG){
++ total = folder_total(FOLDERS(cntxt));
++ for (index = 0L; index < total ; index++){
++ f = folder_entry(index, FOLDERS(cntxt));
++ if (!strcmp(STREAMNAME(stream), FLDR_NAME(f))){
++ done++;
++ break;
++ }
++ }
++ }
++ if (!done)
++ f = NULL;
++ return f;
++ }
++
++ int
++ need_folder_report(folder)
++ char *folder;
++ {
++ return (ps_global->VAR_INCOMING_FOLDERS_CHECK &&
++ ((ps_global->VAR_INCOMING_FOLDERS_CHECK[0] == '*') ||
++ strstr(ps_global->VAR_INCOMING_FOLDERS_CHECK, folder)));
++ }
++
+
+ SELECTED_S *
+ new_selected()
+***************
+*** 4204,4209 ****
+--- 4343,4349 ----
+
+ if(f = folder_entry(index, FOLDERS(context))){
+ f->selected = !f->selected;
++ f->user_selected = f->selected;
+ return((*func)(context, index));
+ }
+ return 1;
+***************
+*** 7223,7228 ****
+--- 7363,7371 ----
+ FOLDERS(context) = init_folder_entries();
+ init_incoming_folder_list(ps_global, context);
+ init_inbox_mapping(ps_global->VAR_INBOX_PATH, context);
++ ps_global->force_check_now = 1; /* sorry about this */
++ new_mail_incfolder(ps_global,MC_FORCECHECK);
++ ps_global->refresh_list += 1;
+ }
+
+
+***************
+*** 8406,8416 ****
+ long *find_recent;
+ int *did_cancel;
+ {
+! int index, recent = 0, failed_status = 0, try_fast;
+ char prompt[128];
+ FOLDER_S *f = NULL;
+ char tmp[MAILTMPLEN];
+!
+
+ /* note: find_folders may assign "stream" */
+ build_folder_list(streamp, cntxt, NULL, NULL,
+--- 8549,8565 ----
+ long *find_recent;
+ int *did_cancel;
+ {
+! int index, recent = 0, failed_status = 0, try_fast, done = 0;
+ char prompt[128];
+ FOLDER_S *f = NULL;
+ char tmp[MAILTMPLEN];
+! char *test_current = cpystr(current);
+! int cur_indx = folder_index(ps_global->cur_folder, cntxt, FI_FOLDER);
+! int loop = !strcmp(next, ps_global->cur_folder) ? 0 :
+! (folder_index(test_current, cntxt, FI_FOLDER) <= cur_indx
+! ? 1 : 0);
+! int last = !strcmp(ps_global->cur_folder, ps_global->inbox_name)
+! ? 1 : cur_indx;
+
+ /* note: find_folders may assign "stream" */
+ build_folder_list(streamp, cntxt, NULL, NULL,
+***************
+*** 8421,8427 ****
+ if(find_recent)
+ *find_recent = 0L;
+
+! for(index = folder_index(current, cntxt, FI_FOLDER) + 1;
+ index > 0
+ && index < folder_total(FOLDERS(cntxt))
+ && (f = folder_entry(index, FOLDERS(cntxt)))
+--- 8570,8578 ----
+ if(find_recent)
+ *find_recent = 0L;
+
+!
+! find_new_message:
+! for(index = folder_index(test_current, cntxt, FI_FOLDER) + 1;
+ index > 0
+ && index < folder_total(FOLDERS(cntxt))
+ && (f = folder_entry(index, FOLDERS(cntxt)))
+***************
+*** 8432,8437 ****
+--- 8583,8593 ----
+ int rv, we_cancel = 0, mlen, match;
+ char msg_buf[MAX_BM+1], mbuf[MAX_BM+1];
+
++ if (loop && (index == last)){
++ done++;
++ break;
++ }
++
+ /* must be a folder and it can't be the current one */
+ if(ps_global->context_current == ps_global->context_list
+ && !strcmp(ps_global->cur_folder, FLDR_NAME(f)))
+***************
+*** 8583,8601 ****
+ }
+ }
+
+! if(f && (!find_recent || recent))
+ strcpy(next, FLDR_NAME(f));
+ else
+ *next = '\0';
+
+ /* BUG: how can this be made smarter so we cache the list? */
+ free_folder_list(cntxt);
+ return((*next) ? next : NULL);
+ }
+
+
+
+ /*
+ * folder_is_nick - check to see if the given name is a nickname
+ * for some folder in the given context...
+ *
+--- 8739,8906 ----
+ }
+ }
+
+! if(f && (!find_recent || recent)){
+ strcpy(next, FLDR_NAME(f));
++ done++;
++ }
+ else
+ *next = '\0';
+
++ if (!done && F_ON(F_AUTO_CIRCULAR_TAB,ps_global)
++ && strcmp(test_current,ps_global->inbox_name)){
++ done++; loop++;
++ if (test_current)
++ fs_give((void **)&test_current);
++ test_current = cpystr(ps_global->inbox_name);
++ goto find_new_message;
++ }
++
+ /* BUG: how can this be made smarter so we cache the list? */
+ free_folder_list(cntxt);
++ if (test_current)
++ fs_give((void **)&test_current);
+ return((*next) ? next : NULL);
+ }
+
+
+
+ /*
++ * next_folder - given a current folder in a context, return the next in
++ * the list, or NULL if no more or there's a problem.
++ */
++ int
++ next_folder_check(streamp, cntxt, find_recent, find_messages, f, opstrm)
++ MAILSTREAM **streamp;
++ CONTEXT_S *cntxt;
++ long *find_recent, *find_messages;
++ FOLDER_S *f;
++ int *opstrm;
++ {
++ char *next;
++ int index, failed_status = 0;
++
++ /* note: find_folders may assign "stream" */
++ build_folder_list(streamp, cntxt, NULL, NULL, BFL_NONE);
++
++ if(find_recent && find_messages && opstrm){
++ MAILSTREAM *stream = NULL;
++ int rv, we_cancel = 0;
++ char msg_buf[MAX_SCREEN_COLS+1] = {'\0'};
++ char tmp[MAILTMPLEN];
++
++ *opstrm = 0; /* default value */
++ *find_recent = f->recent; /* default value. Return this if */
++ *find_messages = f->messages; /* not requested */
++
++ if((stream = sp_stream_get(context_apply(tmp, cntxt, f->name,sizeof(tmp)),
++ SP_MATCH)) != NULL){
++ *opstrm = 1;
++ (void) pine_mail_ping(stream);
++ next = new_mail_in_open_stream(stream, find_recent, find_messages);
++ free_folder_list(cntxt);
++ return next ? 1 : 0;
++ }
++ else if ((F_ON(F_ENABLE_FAST_RECENT, ps_global) &&
++ F_OFF(F_ENABLE_INCOMING_RECHECK,ps_global) &&
++ (f->notified || f->selected))
++ || (f->selected && f->user_selected)){
++
++ next = f->notified ? FLDR_NAME(f) : NULL;
++ free_folder_list(cntxt);
++ return next ? 1 : 0;
++ }
++ else if (need_folder_report(FLDR_NAME(f))
++ && (strcmp(ps_global->cur_folder, FLDR_NAME(f)) || !stream)){
++
++ we_cancel = busy_alarm(1, msg_buf, NULL, 1);
++
++ /* First, get a stream for the test */
++ if(streamp && *streamp){
++ if(context_same_stream(cntxt, f->name, *streamp))
++ stream = *streamp;
++ else{
++ mail_close(*streamp);
++ *streamp = NULL;
++ }
++ }
++
++ if(!stream)
++ stream = sp_stream_get(context_apply(tmp, cntxt, f->name,
++ sizeof(tmp)), SP_SAME);
++
++ if(!stream){
++ if(!(stream = sp_stream_status_get(
++ context_apply(tmp, cntxt, f->name,
++ sizeof(tmp))))){
++ stream = (*f->name == '{')
++ ? mail_open (NIL,f->name,OP_HALFOPEN) : NIL;
++ sp_add_status(stream);
++ }
++ }
++
++ if(F_OFF(F_ENABLE_FAST_RECENT, ps_global)
++ || !((rv = folder_exists(cntxt,f->name))
++ & (FEX_ISMARKED | FEX_UNMARKED))){
++ extern MAILSTATUS mm_status_result;
++
++ if((F_ON(F_ENABLE_FAST_RECENT, ps_global) &&
++ (rv == 0 || rv & FEX_ERROR))){
++ failed_status = 1;
++ mm_status_result.flags = 0L;
++ }
++ else{
++ if(stream){
++ if(!context_status_full(cntxt, stream,
++ f->name, SA_RECENT | SA_MESSAGES,
++ &f->uidvalidity,
++ &f->uidnext)){
++ failed_status = 1;
++ mm_status_result.flags = 0L;
++ }
++ }
++ else{
++ if(!context_status_streamp_full(cntxt, streamp, f->name,
++ SA_RECENT | SA_MESSAGES,
++ &f->uidvalidity,
++ &f->uidnext)){
++ failed_status = 1;
++ mm_status_result.flags = 0L;
++ }
++ }
++ }
++
++ if (!failed_status){
++ *find_messages = mm_status_result.messages;
++ *find_recent = mm_status_result.recent;
++ }
++ else{
++ *find_recent = *find_messages = 0;
++ }
++ rv = (((mm_status_result.flags & SA_RECENT) ||
++ (F_OFF(F_ENABLE_FAST_RECENT,ps_global)
++ && (mm_status_result.recent != f->recent)))
++ && (*find_recent = mm_status_result.recent))
++ ? FEX_ISMARKED : 0;
++ }
++
++ if(we_cancel)
++ cancel_busy_alarm(0);
++
++ failed_status = 0;
++
++ if(rv & FEX_ISMARKED){
++ next = f ? FLDR_NAME(f) : NULL;
++ free_folder_list(cntxt);
++ return next ? 1 : 0;
++ }
++ }
++ return 0;
++ }
++ }
++
++
++
++ /*
+ * folder_is_nick - check to see if the given name is a nickname
+ * for some folder in the given context...
+ *
+diff -rc pine4.63/pine/imap.c pine4.63.I.USE/pine/imap.c
+*** pine4.63/pine/imap.c Fri Jan 21 17:31:32 2005
+--- pine4.63.I.USE/pine/imap.c Thu May 19 19:57:33 2005
+***************
+*** 704,710 ****
+ q_line = -(ps_global->ttyo ? ps_global->ttyo->footer_rows : 3);
+
+ /* make sure errors are seen */
+! if(ps_global->ttyo)
+ flush_status_messages(0);
+
+ /*
+--- 704,710 ----
+ q_line = -(ps_global->ttyo ? ps_global->ttyo->footer_rows : 3);
+
+ /* make sure errors are seen */
+! if(ps_global->ttyo && !ps_global->checking_incfld)
+ flush_status_messages(0);
+
+ /*
+***************
+*** 1949,1959 ****
+--- 1949,1963 ----
+ #endif
+
+ if(elapsed >= (long)ps_global->tcp_query_timeout){
++ if(!ps_global->checking_incfld){
+ sprintf(pmt,
+ "Waited %s seconds for server reply. Break connection to server",
+ long2string(elapsed));
+ if(want_to(pmt, 'n', 'n', NO_HELP, WT_FLUSH_IN) == 'y')
+ return(0L);
++ }
++ else
++ rv = 0L;
+ }
+
+ return(rv);
+***************
+*** 1995,2000 ****
+--- 1999,2005 ----
+ if(elapsed >= (long)ps_global->tcp_query_timeout){
+ int clear_inverse;
+
++ if(!ps_global->checking_incfld){
+ ClearLine(ps_global->ttyo->screen_rows - FOOTER_ROWS(ps_global));
+ if(clear_inverse = !InverseState())
+ StartInverse();
+***************
+*** 2015,2020 ****
+--- 2020,2028 ----
+ EndInverse();
+
+ ClearLine(ps_global->ttyo->screen_rows - FOOTER_ROWS(ps_global));
++ }
++ else
++ rv = 0L;
+ }
+
+ if(rv == 1L){ /* just warn 'em something's up */
+***************
+*** 2031,2036 ****
+--- 2039,2074 ----
+ return(rv);
+ }
+
++ QUOTALIST *pine_quotalist_copy (pquota)
++ QUOTALIST *pquota;
++ {
++ QUOTALIST *cquota = NULL;
++
++ if(pquota){
++ cquota = mail_newquotalist();
++ if (pquota->name && *pquota->name){
++ cquota->name = (char *) fs_get((strlen(pquota->name) + 1)*sizeof(char));
++ cquota->name = cpystr(pquota->name);
++ }
++ cquota->usage = pquota->usage;
++ cquota->limit = pquota->limit;
++ if (pquota->next)
++ cquota->next = pine_quotalist_copy(pquota->next);
++ }
++ return cquota;
++ }
++
++
++ /* C-client callback to handle quota */
++
++ void
++ pine_parse_quota (stream, msg, pquota)
++ MAILSTREAM *stream;
++ unsigned char *msg;
++ QUOTALIST *pquota;
++ {
++ ps_global->quota = pine_quotalist_copy (pquota);
++ }
+
+ /*
+ * C-client callback to handle SSL/TLS certificate validation failures
+diff -rc pine4.63/pine/init.c pine4.63.I.USE/pine/init.c
+*** pine4.63/pine/init.c Thu Apr 7 11:01:42 2005
+--- pine4.63.I.USE/pine/init.c Thu May 19 19:57:32 2005
+***************
+*** 71,76 ****
+--- 71,77 ----
+ typedef enum {Sapling, Seedling, Seasoned} FeatureLevel;
+
+ #define TO_BAIL_THRESHOLD 60
++ #define INCFLD_THRESHOLD 5
+
+ #define METASTR "\nremote-abook-metafile="
+ static char meta_prefix[] = ".ab";
+***************
+*** 158,163 ****
+--- 159,166 ----
+
+ CONF_TXT_T cf_text_incoming_folders[] = "List of incoming msg folders besides INBOX, e.g. ={host2}inbox, {host3}inbox\n# Syntax: optnl-label {optnl-imap-host-name}folder-path";
+
++ CONF_TXT_T cf_incoming_folders_check[] = "List of incoming folders to be checked for new mail";
++
+ CONF_TXT_T cf_text_folder_collections[] = "List of directories where saved-message folders may be. First one is\n# the default for Saves. Example: Main {host1}mail/[], Desktop mail\\[]\n# Syntax: optnl-label {optnl-imap-hostname}optnl-directory-path[]";
+
+ CONF_TXT_T cf_text_news_collections[] = "List, only needed if nntp-server not set, or news is on a different host\n# than used for NNTP posting. Examples: News *[] or News *{host3/nntp}[]\n# Syntax: optnl-label *{news-host/protocol}[]";
+***************
+*** 214,223 ****
+--- 217,256 ----
+
+ CONF_TXT_T cf_text_sort_key[] = "Sets presentation order of messages in Index. Choices:\n# Subject, From, Arrival, Date, Size, To, Cc, OrderedSubj, Score, and Thread.\n# Order may be reversed by appending /Reverse. Default: \"Arrival\".";
+
++ CONF_TXT_T cf_text_thread_sort_key[] = "#Sets presentation order of threads in thread index. Choices:\n#arrival, and thread.";
++
+ CONF_TXT_T cf_text_addrbook_sort_rule[] = "Sets presentation order of address book entries. Choices: dont-sort,\n# fullname-with-lists-last, fullname, nickname-with-lists-last, nickname\n# Default: \"fullname-with-lists-last\".";
+
+ CONF_TXT_T cf_text_folder_sort_rule[] = "Sets presentation order of folder list entries. Choices: alphabetical,\n# alpha-with-dirs-last, alpha-with-dirs-first.\n# Default: \"alpha-with-directories-last\".";
+
++ CONF_TXT_T cf_text_compose_rules[] = "Allows a user to set rules when composing messages.";
++
++ CONF_TXT_T cf_text_forward_rules[] = "Allows a user to set rules when forwarding messages.";
++
++ CONF_TXT_T cf_text_reply_rules[] = "Allows a user to set rules when replying messages.";
++
++ CONF_TXT_T cf_text_index_rules[] = "Allows a user to supercede global index format variable in designated folders.";
++
++ CONF_TXT_T cf_text_replace_rules[] = "Allows a user to change the form a specify field in the index-format is \n# displayed.";
++
++ CONF_TXT_T cf_text_reply_indent_rules[] = "Allows a user to change the form a specify a reply-indent-string\n# based of rules.";
++
++ CONF_TXT_T cf_text_reply_leadin_rules[] = "Allows a user to replace the reply-leadin message based on different parameters.";
++
++ CONF_TXT_T cf_text_reply_subject_rules[] = "Allows a user to replace the subject of a message in a customs based way";
++
++ CONF_TXT_T cf_text_thread_displaystyle_rule[] = "Allows a user to specify the threading style of specific folders";
++
++ CONF_TXT_T cf_text_thread_indexstyle_rule[] = "Allows a user to specify the threading index style of specific folders";
++
++ CONF_TXT_T cf_text_save_rules[] = "Allows a user to specify a save folder message for specific senders or folders.";
++
++ CONF_TXT_T cf_text_smtp_rules[] = "Allows a user to specify a smtp server to be used when sending e-mail,\n# according to the rules specified here.";
++
++ CONF_TXT_T cf_text_sort_rules[] = "Allows a user to specify the sort default order of a specific folder.";
++
++ CONF_TXT_T cf_text_startup_rules[] = "Allows a user to specify the position of a highlighted message when opening a \n# folder.";
++
+ CONF_TXT_T cf_text_character_set[] = "Reflects capabilities of the display you have. Default: US-ASCII.\n# Typical alternatives include ISO-8859-x, (x is a number between 1 and 9).";
+
+ CONF_TXT_T cf_text_editor[] = "Specifies the program invoked by ^_ in the Composer,\n# or the \"enable-alternate-editor-implicitly\" feature.";
+***************
+*** 228,233 ****
+--- 261,268 ----
+
+ CONF_TXT_T cf_text_fillcol[] = "Specifies the column of the screen where the composer should wrap.";
+
++ CONF_TXT_T cf_special_text_color[] = "Specifies a comma separated list of text and regular expresions that Pine\n# will highlight";
++
+ CONF_TXT_T cf_text_replystr[] = "Specifies the string to insert when replying to a message.";
+
+ CONF_TXT_T cf_text_quotereplstr[] = "Specifies the string to replace quotes with when viewing a message.";
+***************
+*** 242,247 ****
+--- 277,284 ----
+
+ CONF_TXT_T cf_text_inc_startup[] = "Sets message which cursor begins on. Choices: first-unseen, first-recent,\n# first-important, first-important-or-unseen, first-important-or-recent,\n# first, last. Default: \"first-unseen\".";
+
++ CONF_TXT_T cf_text_inc_check[] = "Sets how and when checks for new mail should happen. Choices: automatic,\n# automatic-after-first-manual-check, manual-only, Default: automatic";
++
+ CONF_TXT_T cf_pruning_rule[] = "Allows a default answer for the prune folder questions. Choices: yes-ask,\n# yes-no, no-ask, no-no, ask-ask, ask-no. Default: \"ask-ask\".";
+
+ CONF_TXT_T cf_reopen_rule[] = "Controls behavior when reopening an already open folder.";
+***************
+*** 378,383 ****
+--- 415,422 ----
+
+ CONF_TXT_T cf_text_tcp_query_timeo[] = "If this much time has elapsed at the time of a tcp read or write\n# timeout, pine will ask if you want to break the connection.\n# Default is 60 seconds, minimum is 5, maximum is 1000.";
+
++ CONF_TXT_T cf_text_inc_fld_timeout[] = "If this much time has elapsed at the time of a tcp read or write\n# timeout while checking for new mail in an incoming folder, pine will break the connection.\n# Default is 5 seconds, minimum is 2, maximum is 60.";
++
+ CONF_TXT_T cf_text_rsh_open_timeo[] = "Sets the time in seconds that Pine will attempt to open a UNIX remote\n# shell connection. The default is 15, min is 5, and max is unlimited.\n# Zero disables rsh altogether.";
+
+ CONF_TXT_T cf_text_rsh_path[] = "Sets the name of the command used to open a UNIX remote shell connection.\n# The default is typically /usr/ucb/rsh.";
+***************
+*** 418,423 ****
+--- 457,465 ----
+
+ CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file";
+
++ CONF_TXT_T cf_text_maildir_location[] = "Location relative to your HOME directory of the directory where your INBOX\n# for the maildir format is located. Default value is \"Maildir\". If your\n# inbox is located at \"~/Maildir\" you do not need to change this value.\n# A common value is also \".maildir\"";
++
++
+ /* these are used to report folder directory creation problems */
+ CONF_TXT_T init_md_exists[] = "The \"%s\" subdirectory already exists, but it is not writable by Pine so Pine cannot run. Please correct the permissions and restart Pine.";
+
+***************
+*** 471,476 ****
+--- 513,520 ----
+ cf_text_nntp_server},
+ {"inbox-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+ cf_text_inbox_path},
++ {"incoming-folders-to-check", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0,
++ cf_incoming_folders_check},
+ {"incoming-archive-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0,
+ cf_text_archived_folders},
+ {"pruned-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
+***************
+*** 511,516 ****
+--- 555,562 ----
+ cf_text_fcc_name_rule},
+ {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+ cf_text_sort_key},
++ {"thread-sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
++ cf_text_thread_sort_key},
+ {"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+ cf_text_addrbook_sort_rule},
+ {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+***************
+*** 519,524 ****
+--- 565,572 ----
+ cf_text_goto_default},
+ {"incoming-startup-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+ cf_text_inc_startup},
++ {"incoming-check-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
++ cf_text_inc_check},
+ {"pruning-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+ cf_pruning_rule},
+ {"folder-reopen-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+***************
+*** 533,538 ****
+--- 581,612 ----
+ cf_text_thread_exp_char},
+ {"threading-lastreply-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+ cf_text_thread_lastreply_char},
++ {"threading-display-style-rule", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_thread_displaystyle_rule},
++ {"threading-index-style-rule", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_thread_indexstyle_rule},
++ {"compose-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_compose_rules},
++ {"forward-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_forward_rules},
++ {"index-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_index_rules},
++ {"replace-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_replace_rules},
++ {"reply-indent-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_reply_indent_rules},
++ {"reply-leadin-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_reply_leadin_rules},
++ {"reply-subject-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_reply_subject_rules},
++ {"save-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_save_rules},
++ {"smtp-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_smtp_rules},
++ {"sort-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_sort_rules},
++ {"startup-rules", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_text_startup_rules},
+ {"character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+ cf_text_character_set},
+ {"editor", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
+***************
+*** 541,546 ****
+--- 615,622 ----
+ cf_text_speller},
+ {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+ cf_text_fillcol},
++ {"special-text-color", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
++ cf_special_text_color},
+ {"reply-indent-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0,
+ cf_text_replystr},
+ {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+***************
+*** 605,610 ****
+--- 681,688 ----
+ cf_text_news_active},
+ {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+ cf_text_news_spooldir},
++ {"maildir-location", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
++ cf_text_maildir_location},
+ {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+ cf_text_upload_cmd},
+ {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+***************
+*** 673,678 ****
+--- 751,758 ----
+ cf_text_tcp_write_timeo},
+ {"tcp-query-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+ cf_text_tcp_query_timeo},
++ {"inc-fld-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
++ cf_text_inc_fld_timeout},
+ {"rsh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+ cf_text_rsh_command},
+ {"rsh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
+***************
+*** 772,777 ****
+--- 852,859 ----
+ {"quote3-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, NULL},
+ {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, NULL},
+ {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, NULL},
++ {"special-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, NULL},
++ {"special-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, NULL},
+ {"prompt-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, NULL},
+ {"prompt-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, NULL},
+ {"index-to-me-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, NULL},
+***************
+*** 1475,1481 ****
+ register struct variable *vars = ps->vars;
+ int obs_header_in_reply, /* the obs_ variables are to */
+ obs_old_style_reply, /* support backwards compatibility */
+! obs_save_by_sender, i, def_sort_rev;
+ long rvl;
+ PINERC_S *fixedprc = NULL;
+ FeatureLevel obs_feature_level;
+--- 1557,1563 ----
+ register struct variable *vars = ps->vars;
+ int obs_header_in_reply, /* the obs_ variables are to */
+ obs_old_style_reply, /* support backwards compatibility */
+! obs_save_by_sender, i, def_sort_rev, thread_def_sort_rev;
+ long rvl;
+ PINERC_S *fixedprc = NULL;
+ FeatureLevel obs_feature_level;
+***************
+*** 1497,1502 ****
+--- 1579,1585 ----
+ GLO_FEATURE_LEVEL = cpystr(DF_FEATURE_LEVEL);
+ GLO_OLD_STYLE_REPLY = cpystr(DF_OLD_STYLE_REPLY);
+ GLO_SORT_KEY = cpystr(DF_SORT_KEY);
++ GLO_THREAD_SORT_KEY = cpystr(DF_THREAD_SORT_KEY);
+ GLO_SAVED_MSG_NAME_RULE = cpystr(DF_SAVED_MSG_NAME_RULE);
+ GLO_FCC_RULE = cpystr(DF_FCC_RULE);
+ GLO_AB_SORT_RULE = cpystr(DF_AB_SORT_RULE);
+***************
+*** 1507,1512 ****
+--- 1590,1596 ----
+ GLO_REMOTE_ABOOK_VALIDITY = cpystr(DF_REMOTE_ABOOK_VALIDITY);
+ GLO_GOTO_DEFAULT_RULE = cpystr(DF_GOTO_DEFAULT_RULE);
+ GLO_INCOMING_STARTUP = cpystr(DF_INCOMING_STARTUP);
++ GLO_INCOMING_RULE = cpystr(DF_INCOMING_RULE);
+ GLO_PRUNING_RULE = cpystr(DF_PRUNING_RULE);
+ GLO_REOPEN_RULE = cpystr(DF_REOPEN_RULE);
+ GLO_THREAD_DISP_STYLE = cpystr(DF_THREAD_DISP_STYLE);
+***************
+*** 1856,1863 ****
+--- 1940,1959 ----
+ set_current_val(&vars[V_POSTPONED_FOLDER], TRUE, TRUE);
+ set_current_val(&vars[V_READ_MESSAGE_FOLDER], TRUE, TRUE);
+ set_current_val(&vars[V_FORM_FOLDER], TRUE, TRUE);
++ set_current_val(&vars[V_COMPOSE_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_FORWARD_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_INDEX_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_REPLACE_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_REPLY_INDENT_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_REPLY_LEADIN_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_RESUB_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_SAVE_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_SMTP_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_SORT_RULES], TRUE, TRUE);
++ set_current_val(&vars[V_STARTUP_RULES], TRUE, TRUE);
+ set_current_val(&vars[V_EDITOR], TRUE, TRUE);
+ set_current_val(&vars[V_SPELLER], TRUE, TRUE);
++ set_current_val(&vars[V_SPECIAL_TEXT], TRUE, TRUE);
+ set_current_val(&vars[V_IMAGE_VIEWER], TRUE, TRUE);
+ set_current_val(&vars[V_BROWSER], TRUE, TRUE);
+ set_current_val(&vars[V_SMTP_SERVER], TRUE, TRUE);
+***************
+*** 2076,2081 ****
+--- 2172,2184 ----
+ else
+ ps->tcp_query_timeout = i;
+
++ set_current_val(&vars[V_INCFLDTIMEO], TRUE, TRUE);
++ ps->incfld_timeout = i = INCFLD_THRESHOLD;
++ if(VAR_INCFLDTIMEO && SVAR_INCFLDQUERY(ps, i, tmp_20k_buf))
++ init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
++ else
++ ps->incfld_timeout = i;
++
+ set_current_val(&vars[V_NEWSRC_PATH], TRUE, TRUE);
+ if(VAR_NEWSRC_PATH && VAR_NEWSRC_PATH[0])
+ mail_parameters(NULL, SET_NEWSRC, (void *)VAR_NEWSRC_PATH);
+***************
+*** 2090,2095 ****
+--- 2193,2202 ----
+ mail_parameters(NULL, SET_NEWSSPOOL,
+ (void *)VAR_NEWS_SPOOL_DIR);
+
++ set_current_val(&vars[V_MAILDIR_LOCATION], TRUE, TRUE);
++ if(VAR_MAILDIR_LOCATION && VAR_MAILDIR_LOCATION[0])
++ maildir_parameters(SET_INBOXPATH, (void *)VAR_MAILDIR_LOCATION);
++
+ /* guarantee a save default */
+ set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE);
+ if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0])
+***************
+*** 2323,2330 ****
+ set_current_val(&vars[V_PRUNED_FOLDERS], TRUE, TRUE);
+ set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
+ set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
+ set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
+! if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev) == -1){
+ sprintf(tmp_20k_buf, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
+ init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
+ ps->def_sort = SortArrival;
+--- 2430,2438 ----
+ set_current_val(&vars[V_PRUNED_FOLDERS], TRUE, TRUE);
+ set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
+ set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
++ set_current_val(&vars[V_INCOMING_FOLDERS_CHECK], TRUE, TRUE);
+ set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
+! if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev,0) == -1){
+ sprintf(tmp_20k_buf, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
+ init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
+ ps->def_sort = SortArrival;
+***************
+*** 2333,2338 ****
+--- 2441,2457 ----
+ else
+ ps->def_sort_rev = def_sort_rev;
+
++ set_current_val(&vars[V_THREAD_SORT_KEY], TRUE, TRUE);
++ if(decode_sort(VAR_THREAD_SORT_KEY, &ps->thread_def_sort,
++ &thread_def_sort_rev, 1) == -1){
++ sprintf(tmp_20k_buf, "Sort type \"%s\" is invalid", VAR_THREAD_SORT_KEY);
++ init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
++ ps->thread_def_sort = SortThread;
++ ps->thread_def_sort_rev = 0;
++ }
++ else
++ ps->thread_def_sort_rev = thread_def_sort_rev;
++
+ cur_rule_value(&vars[V_SAVED_MSG_NAME_RULE], TRUE, TRUE);
+ {NAMEVAL_S *v; int i;
+ for(i = 0; v = save_msg_rules(i); i++)
+***************
+*** 2360,2370 ****
+--- 2479,2492 ----
+ cur_rule_value(&vars[V_TITLEBAR_COLOR_STYLE], TRUE, TRUE);
+ cur_rule_value(&vars[V_FLD_SORT_RULE], TRUE, TRUE);
+ cur_rule_value(&vars[V_INCOMING_STARTUP], TRUE, TRUE);
++ cur_rule_value(&vars[V_INCOMING_RULE], TRUE, TRUE);
+ cur_rule_value(&vars[V_PRUNING_RULE], TRUE, TRUE);
+ cur_rule_value(&vars[V_REOPEN_RULE], TRUE, TRUE);
+ cur_rule_value(&vars[V_GOTO_DEFAULT_RULE], TRUE, TRUE);
+ cur_rule_value(&vars[V_THREAD_DISP_STYLE], TRUE, TRUE);
+ cur_rule_value(&vars[V_THREAD_INDEX_STYLE], TRUE, TRUE);
++ cur_rule_value(&vars[V_THREAD_DISP_STYLE_RULES], TRUE, TRUE);
++ cur_rule_value(&vars[V_THREAD_INDEX_STYLE_RULES], TRUE, TRUE);
+
+ set_current_val(&vars[V_THREAD_MORE_CHAR], TRUE, TRUE);
+ if(VAR_THREAD_MORE_CHAR[0] && VAR_THREAD_MORE_CHAR[1]){
+***************
+*** 2418,2423 ****
+--- 2540,2546 ----
+ if(VAR_INIT_CMD_LIST && VAR_INIT_CMD_LIST[0] && VAR_INIT_CMD_LIST[0][0])
+ process_init_cmds(ps, VAR_INIT_CMD_LIST);
+
++ create_rule_list();
+ #ifdef _WINDOWS
+ mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
+ if(ps_global->update_registry != UREG_NEVER_SET){
+***************
+*** 2607,2612 ****
+--- 2730,2737 ----
+ F_STRIP_WS_BEFORE_SEND, h_config_strip_ws_before_send, PREF_COMP},
+
+ /* Reply Prefs */
++ {"alternate-reply-menu",
++ F_ALT_REPLY_MENU, h_config_alt_reply_menu, PREF_RPLY},
+ {"enable-reply-indent-string-editing",
+ F_ENABLE_EDIT_REPLY_INDENT, h_config_prefix_editing, PREF_RPLY},
+ {"include-attachments-in-reply",
+***************
+*** 2641,2646 ****
+--- 2766,2773 ----
+ F_AUTO_FCC_ONLY, h_config_auto_fcc_only, PREF_SEND},
+ {"fcc-without-attachments",
+ F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND},
++ {"return-path-uses-domain-name",
++ F_USE_DOMAIN_NAME, h_config_use_domain, PREF_SEND},
+ {"mark-fcc-seen",
+ F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND},
+ {"send-without-confirm",
+***************
+*** 2661,2666 ****
+--- 2788,2797 ----
+ F_ENABLE_DOT_FOLDERS, h_config_enable_dot_folders, PREF_FLDR},
+ {"enable-incoming-folders",
+ F_ENABLE_INCOMING, h_config_enable_incoming, PREF_FLDR},
++ {"enable-check-incoming-folders",
++ F_ENABLE_INCOMING_CHECK, h_config_enable_check_incoming, PREF_FLDR},
++ {"recheck-all-incoming-folders",
++ F_ENABLE_INCOMING_RECHECK, h_config_enable_recheck_incoming,PREF_FLDR},
+ {"enable-lame-list-mode",
+ F_FIX_BROKEN_LIST, h_config_lame_list_mode, PREF_FLDR},
+ {"expanded-view-of-folders",
+***************
+*** 2677,2682 ****
+--- 2808,2815 ----
+ F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR},
+ {"vertical-folder-list",
+ F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR},
++ {"use-courier-folder-list",
++ F_COURIER_FOLDER_LIST, h_config_courier_list, PREF_FLDR},
+
+ /* Addr book */
+ {"combined-addrbook-display",
+***************
+*** 2693,2698 ****
+--- 2826,2833 ----
+ /* Index prefs */
+ {"auto-open-next-unread",
+ F_AUTO_OPEN_NEXT_UNREAD, h_config_auto_open_unread, PREF_INDX},
++ {"enable-circular-tab",
++ F_AUTO_CIRCULAR_TAB, h_config_circular_tab, PREF_INDX},
+ {"continue-tab-without-confirm",
+ F_TAB_NO_CONFIRM, h_config_tab_no_prompt, PREF_INDX},
+ {"delete-skips-deleted",
+***************
+*** 2715,2720 ****
+--- 2850,2857 ----
+ F_TAB_TO_NEW, h_config_tab_new_only, PREF_INDX},
+ {"thread-index-shows-important-color",
+ F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX},
++ {"enhanced-fancy-thread-support",
++ F_ENHANCED_THREAD, h_config_enhanced_thread, PREF_INDX},
+
+ /* Viewer prefs */
+ {"enable-msg-view-addresses",
+***************
+*** 2820,2825 ****
+--- 2957,2964 ----
+ F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD},
+ {"auto-move-read-msgs",
+ F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC},
++ {"auto-move-read-msgs-using-rules",
++ F_AUTO_READ_MSGS_RULES, h_config_auto_read_msgs_rules, PREF_MISC},
+ {"auto-unzoom-after-apply",
+ F_AUTO_UNZOOM, h_config_auto_unzoom, PREF_MISC},
+ {"auto-zoom-after-select",
+***************
+*** 3767,3772 ****
+--- 3906,3928 ----
+ ? &is_rules[index] : NULL);
+ }
+
++ /*
++ * Standard way to get incoming check rules...
++ */
++ NAMEVAL_S *
++ incoming_check_rules(index)
++ int index;
++ {
++ static NAMEVAL_S is_rules[] = {
++ {"automatic", NULL, IC_AUTO},
++ {"automatic-after-first-manual-check", NULL, IC_MAN_AUTO},
++ {"manual-only", NULL, IC_MAN}
++ };
++
++ return((index >= 0 && index < (sizeof(is_rules)/sizeof(is_rules[0])))
++ ? &is_rules[index] : NULL);
++ }
++
+
+ NAMEVAL_S *
+ startup_rules(index)
+***************
+*** 4201,4210 ****
+ if(i > 0){
+ ps->initial_cmds = (int *)fs_get((i+1) * sizeof(int));
+ ps->free_initial_cmds = ps->initial_cmds;
+ for(j = 0; j < i; j++)
+! ps->initial_cmds[j] = i_cmds[j];
+!
+! ps->initial_cmds[i] = 0;
+ ps->in_init_seq = ps->save_in_init_seq = 1;
+ }
+ }
+--- 4357,4371 ----
+ if(i > 0){
+ ps->initial_cmds = (int *)fs_get((i+1) * sizeof(int));
+ ps->free_initial_cmds = ps->initial_cmds;
++ ps->initial_cmds_backup = (int *)fs_get((i+1) * sizeof(int));
++ ps->free_initial_cmds_backup = ps->initial_cmds_backup;
+ for(j = 0; j < i; j++)
+! ps->initial_cmds[j] = ps->initial_cmds_backup[j] = i_cmds[j];
+! #define ctrl_x 24
+! if (i > 1)
+! ps->send_immediately = i_cmds[i - 2] == ctrl_x
+! && ((i_cmds[i - 1] == 'y') || (i_cmds[i-1] == 'Y'));
+! ps->initial_cmds[i] = ps->initial_cmds_backup[i] = 0;
+ ps->in_init_seq = ps->save_in_init_seq = 1;
+ }
+ }
+***************
+*** 6442,6464 ****
+ * argument also means arrival/reverse.
+ */
+ int
+! decode_sort(sort_spec, def_sort, def_sort_rev)
+ char *sort_spec;
+ SortOrder *def_sort;
+ int *def_sort_rev;
+ {
+ char *sep;
+ char *fix_this = NULL;
+! int x, reverse;
+
+ if(!sort_spec || !*sort_spec){
+! *def_sort = SortArrival;
+ *def_sort_rev = 0;
+ return(0);
+ }
+
+ if(struncmp(sort_spec, "reverse", strlen(sort_spec)) == 0){
+! *def_sort = SortArrival;
+ *def_sort_rev = 1;
+ return(0);
+ }
+--- 6603,6626 ----
+ * argument also means arrival/reverse.
+ */
+ int
+! decode_sort(sort_spec, def_sort, def_sort_rev, thread)
+ char *sort_spec;
+ SortOrder *def_sort;
+ int *def_sort_rev;
++ int thread;
+ {
+ char *sep;
+ char *fix_this = NULL;
+! int x = 0, reverse;
+
+ if(!sort_spec || !*sort_spec){
+! *def_sort = thread ? SortThread : SortArrival;
+ *def_sort_rev = 0;
+ return(0);
+ }
+
+ if(struncmp(sort_spec, "reverse", strlen(sort_spec)) == 0){
+! *def_sort = thread ? SortThread : SortArrival;
+ *def_sort_rev = 1;
+ return(0);
+ }
+***************
+*** 6481,6493 ****
+ sort_spec, strlen(sort_spec)) == 0)
+ break;
+
+ if(fix_this)
+ *fix_this = '/';
+
+ if(ps_global->sort_types[x] == EndofList)
+ return(-1);
+
+! *def_sort = ps_global->sort_types[x];
+ *def_sort_rev = reverse;
+ return(0);
+ }
+--- 6643,6661 ----
+ sort_spec, strlen(sort_spec)) == 0)
+ break;
+
++ if (thread && ps_global->sort_types[x] != SortArrival
++ && ps_global->sort_types[x] != SortDate
++ && ps_global->sort_types[x] != SortThread)
++ for(x = 0; ps_global->sort_types[x] != EndofList; x++);
++
+ if(fix_this)
+ *fix_this = '/';
+
+ if(ps_global->sort_types[x] == EndofList)
+ return(-1);
+
+! *def_sort = (thread && ps_global->sort_types[x] == SortDate)
+! ? SortThread : ps_global->sort_types[x];
+ *def_sort_rev = reverse;
+ return(0);
+ }
+***************
+*** 11038,11043 ****
+--- 11206,11219 ----
+ break;
+ }
+ }
++ else if(var == &ps_global->vars[V_INCOMING_RULE]){
++ if(ps_global->VAR_INCOMING_RULE)
++ for(i = 0; v = incoming_check_rules(i); i++)
++ if(!strucmp(ps_global->VAR_INCOMING_RULE, S_OR_L(v))){
++ ps_global->inc_check_rule = v->value;
++ break;
++ }
++ }
+ else if(var == &ps_global->vars[V_PRUNING_RULE]){
+ if(ps_global->VAR_PRUNING_RULE)
+ for(i = 0; v = pruning_rules(i); i++)
+diff -rc pine4.63/pine/mailcmd.c pine4.63.I.USE/pine/mailcmd.c
+*** pine4.63/pine/mailcmd.c Wed Apr 27 11:54:59 2005
+--- pine4.63.I.USE/pine/mailcmd.c Thu May 19 19:57:34 2005
+***************
+*** 58,63 ****
+--- 58,64 ----
+ /*
+ * Internal Prototypes
+ */
++ void cmd_quota PROTO((struct pine *));
+ void cmd_delete PROTO((struct pine *, MSGNO_S *, int, CmdWhere));
+ void cmd_undelete PROTO((struct pine *, MSGNO_S *, int));
+ void cmd_reply PROTO((struct pine *, MSGNO_S *, int));
+***************
+*** 89,99 ****
+ int save_ex_explain_body PROTO((BODY *, unsigned long *, gf_io_t));
+ int save_ex_explain_parts PROTO((BODY *, int, unsigned long *, gf_io_t));
+ int save_ex_output_line PROTO((char *, unsigned long *, gf_io_t));
+ int create_for_save PROTO((MAILSTREAM *, CONTEXT_S *, char *));
+ void set_keywords_in_msgid_msg PROTO((MAILSTREAM *, MESSAGECACHE *,
+ MAILSTREAM *, char *, long));
+ long get_msgno_by_msg_id PROTO((MAILSTREAM *, char *, MSGNO_S *));
+! int select_sort PROTO((struct pine *, int, SortOrder *, int *));
+ void aggregate_select PROTO((struct pine *, MSGNO_S *, int, CmdWhere,int));
+ int select_number PROTO((MAILSTREAM *, MSGNO_S *, SEARCHSET **));
+ int select_thrd_number PROTO((MAILSTREAM *, MSGNO_S *, SEARCHSET **));
+--- 90,103 ----
+ int save_ex_explain_body PROTO((BODY *, unsigned long *, gf_io_t));
+ int save_ex_explain_parts PROTO((BODY *, int, unsigned long *, gf_io_t));
+ int save_ex_output_line PROTO((char *, unsigned long *, gf_io_t));
++ void total_messages_status PROTO ((MAILSTREAM *, int, unsigned long *,
++ unsigned long *));
++ char *any_report_message PROTO ((MAILSTREAM *));
+ int create_for_save PROTO((MAILSTREAM *, CONTEXT_S *, char *));
+ void set_keywords_in_msgid_msg PROTO((MAILSTREAM *, MESSAGECACHE *,
+ MAILSTREAM *, char *, long));
+ long get_msgno_by_msg_id PROTO((MAILSTREAM *, char *, MSGNO_S *));
+! int select_sort PROTO((struct pine *, int, SortOrder *, int *, int));
+ void aggregate_select PROTO((struct pine *, MSGNO_S *, int, CmdWhere,int));
+ int select_number PROTO((MAILSTREAM *, MSGNO_S *, SEARCHSET **));
+ int select_thrd_number PROTO((MAILSTREAM *, MSGNO_S *, SEARCHSET **));
+***************
+*** 109,114 ****
+--- 113,139 ----
+ char *currentf_sequence PROTO((MAILSTREAM *, MSGNO_S *, long, long *,
+ int, char **, char **));
+ char *invalid_elt_sequence PROTO((MAILSTREAM *, MSGNO_S *));
++ long top_thread PROTO((MAILSTREAM *, long));
++ void move_top_thread PROTO((MAILSTREAM *, MSGNO_S *, long));
++ long top_this_thread PROTO((MAILSTREAM *, long));
++ void move_top_this_thread PROTO((MAILSTREAM *, MSGNO_S *, long));
++ void cmd_delete_this_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *));
++ void cmd_delete_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *));
++ void cmd_undelete_this_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *));
++ void cmd_undelete_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *));
++ void cmd_select_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *));
++ void kolapse_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, char, int));
++ int count_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, long));
++ int count_this_thread PROTO((MAILSTREAM *, unsigned long));
++ int this_thread_is_kolapsed PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, long));
++ int thread_is_kolapsed PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, long));
++ int collapse_this_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int, int));
++ void collapse_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int));
++ int expand_this_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int, int));
++ void expand_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int));
++ int move_next_this_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int));
++ int move_next_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int));
++ int move_prev_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int));
+ char *selected_sequence PROTO((MAILSTREAM *, MSGNO_S *, long *, int));
+ int any_messages PROTO((MSGNO_S *, char *, char *));
+ int can_set_flag PROTO((struct pine *, char *, int));
+***************
+*** 119,124 ****
+--- 144,155 ----
+ int read_msg_prompt PROTO((long, char *));
+ char *move_read_incoming PROTO((MAILSTREAM *, CONTEXT_S *, char *,
+ char **, char *));
++ char *move_read_msgs_using_rules PROTO((MAILSTREAM *, char *, char *));
++ unsigned get_perfolder_startup_rule PROTO((MAILSTREAM *, int, char *));
++ void setup_threading_index_style PROTO(());
++ int find_startup_position PROTO((int, MAILSTREAM *, long));
++ char *get_rule_result PROTO((int, char *, int));
++ char *get_folder_to_save PROTO((MAILSTREAM *, long, char *));
+ void cross_delete_crossposts PROTO((MAILSTREAM *));
+ void menu_clear_cmd_binding PROTO((struct key_menu *, int));
+ int update_folder_spec PROTO((char *, char *));
+***************
+*** 141,146 ****
+--- 172,180 ----
+ #define SV_FOR_FILT 0x2
+ #define SV_FIX_DELS 0x4
+
++ static MAILSTREAM *saved_stream;
++ static unsigned long rule_curpos = 0L;
++
+ typedef struct append_package {
+ MAILSTREAM *stream;
+ char *flags;
+***************
+*** 267,272 ****
+--- 301,307 ----
+ {'r', 'r', "R", "Recipient"},
+ {'p', 'p', "P", "Participant"},
+ {'b', 'b', "B", "Body"},
++ {'h', 'h', "H", "Header"},
+ {-1, 0, NULL, NULL}
+ };
+
+***************
+*** 936,942 ****
+ state->context_current, &recent_cnt,
+ F_ON(F_TAB_NO_CONFIRM,state)
+ ? NULL : &did_cancel))){
+! if(!in_inbox){
+ static ESCKEY_S inbox_opt[] = {
+ {'y', 'y', "Y", "Yes"},
+ {'n', 'n', "N", "No"},
+--- 971,977 ----
+ state->context_current, &recent_cnt,
+ F_ON(F_TAB_NO_CONFIRM,state)
+ ? NULL : &did_cancel))){
+! if(!in_inbox && F_OFF(F_AUTO_CIRCULAR_TAB,state)){
+ static ESCKEY_S inbox_opt[] = {
+ {'y', 'y', "Y", "Yes"},
+ {'n', 'n', "N", "No"},
+***************
+*** 1186,1191 ****
+--- 1221,1230 ----
+ if(SORT_IS_THREADED(msgmap))
+ refresh_sort(stream, msgmap, SRT_NON);
+
++ if (msgmap->nmsgs
++ && F_ON(F_ENHANCED_THREAD, state) && COLL_THRDS())
++ kolapse_thread(state, stream, msgmap, '[', 0);
++
+ state->mangled_body = 1;
+ state->mangled_header = 1;
+ q_status_message2(SM_ORDER, 0, 4,
+***************
+*** 1256,1261 ****
+--- 1295,1301 ----
+ ps_global->expunge_in_progress = 0;
+ if(we_cancel)
+ cancel_busy_alarm((sp_expunge_count(stream) > 0) ? 0 : -1);
++ update_incoming_folder_data(stream, state->context_current);
+
+ dprint(2,(debugfile,"expunge complete cur:%ld max:%ld\n",
+ mn_get_cur(msgmap), mn_get_total(msgmap)));
+***************
+*** 1298,1303 ****
+--- 1338,1346 ----
+ */
+ if(SORT_IS_THREADED(msgmap))
+ refresh_sort(stream, msgmap, SRT_NON);
++ if (msgmap->nmsgs
++ && F_ON(F_ENHANCED_THREAD, state) && COLL_THRDS())
++ kolapse_thread(state, stream, msgmap, '[', 0);
+ }
+ else{
+ if(del_count)
+***************
+*** 1434,1440 ****
+ if(any_messages(msgmap, NULL, NULL)){
+ if(any_lflagged(msgmap, MN_SLCT) > 0L){
+ if(apply_command(state, stream, msgmap, 0,
+! AC_NONE, question_line)
+ && F_ON(F_AUTO_UNZOOM, state))
+ unzoom_index(state, stream, msgmap);
+ }
+--- 1477,1483 ----
+ if(any_messages(msgmap, NULL, NULL)){
+ if(any_lflagged(msgmap, MN_SLCT) > 0L){
+ if(apply_command(state, stream, msgmap, 0,
+! AC_NONE, question_line, 1)
+ && F_ON(F_AUTO_UNZOOM, state))
+ unzoom_index(state, stream, msgmap);
+ }
+***************
+*** 1447,1464 ****
+
+ /*-------- Sort command -------*/
+ case MC_SORT :
+ {
+ int were_threading = THREADING();
+ SortOrder sort = mn_get_sort(msgmap);
+ int rev = mn_get_revsort(msgmap);
+
+ dprint(1, (debugfile,"MAIL_CMD: sort\n"));
+! if(select_sort(state, question_line, &sort, &rev)){
+ /* $ command reinitializes threading collapsed/expanded info */
+ if(SORT_IS_THREADED(msgmap) && !SEP_THRDINDX())
+ erase_threading_info(stream, msgmap);
+
+! sort_folder(stream, msgmap, sort, rev, SRT_VRB|SRT_MAN);
+ }
+
+ state->mangled_footer = 1;
+--- 1490,1514 ----
+
+ /*-------- Sort command -------*/
+ case MC_SORT :
++ case MC_SORTHREAD :
+ {
+ int were_threading = THREADING();
+ SortOrder sort = mn_get_sort(msgmap);
+ int rev = mn_get_revsort(msgmap);
++ int thread = (command == MC_SORT) ? 0 : 1;
+
++ if (sort == SortThread)
++ sort = ps_global->thread_cur_sort;
+ dprint(1, (debugfile,"MAIL_CMD: sort\n"));
+! if(select_sort(state, question_line, &sort, &rev, thread)){
+ /* $ command reinitializes threading collapsed/expanded info */
+ if(SORT_IS_THREADED(msgmap) && !SEP_THRDINDX())
+ erase_threading_info(stream, msgmap);
+
+! if (command == MC_SORTHREAD)
+! ps_global->thread_cur_sort = sort;
+! sort = (command == MC_SORT) ? sort : SortThread;
+! sort_folder(stream, msgmap, sort, rev, SRT_VRB|SRT_MAN, 1);
+ }
+
+ state->mangled_footer = 1;
+***************
+*** 1533,1538 ****
+--- 1583,1594 ----
+ break;
+
+
++ /*--------Incoming Folders Auto Check --------*/
++ case MC_FORCECHECK:
++ state->force_check_now = 1;
++ new_mail_incfolder(state,command);
++ break;
++
+ /*--------- Default, unknown command ----------*/
+ default:
+ panic("Unexpected command case");
+***************
+*** 1940,1945 ****
+--- 1996,2163 ----
+ }
+
+
++ static struct key quota_keys[] =
++ {HELP_MENU,
++ NULL_MENU,
++ {"E","Exit",{MC_EXIT,3,{'e','i',ctrl('C')}},KS_EXITMODE},
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU,
++ NULL_MENU};
++ INST_KEY_MENU(pine_quota_keymenu, quota_keys);
++
++ int process_quota_cmd(cmd, msgmap, sparms)
++ int cmd;
++ MSGNO_S *msgmap;
++ SCROLL_S *sparms;
++ {
++ return cmd;
++ }
++
++
++ void cmd_quota (state)
++ struct pine *state;
++ {
++ QUOTALIST *imapquota;
++ NETMBX mb;
++ unsigned long len, storageuse, storagelim, messageuse, messagelim;
++ STORE_S *store;
++ SCROLL_S sargs;
++ char *linedata;
++ char *storageq = NULL, *messageq = NULL;
++ int storage=0, message=0, other=0, storagelen = 0, messagelen = 0;
++
++ if(!state->mail_stream || !is_imap_stream(state->mail_stream)){
++ q_status_message(SM_ORDER, 1, 5, "Quota only available for IMAP folders");
++ return;
++ }
++
++ if (state->mail_stream
++ && !sp_dead_stream(state->mail_stream)
++ && state->mail_stream->mailbox
++ && *state->mail_stream->mailbox
++ && mail_valid_net_parse(state->mail_stream->mailbox, &mb))
++ imap_getquotaroot(state->mail_stream, mb.mailbox);
++
++ if(!state->quota) /* failed ? */
++ return; /* go back... */
++
++ if(!(store = so_get(CharStar, NULL, EDIT_ACCESS))){
++ q_status_message(SM_ORDER | SM_DING, 3, 3, "Error allocating space.");
++ return;
++ }
++
++ if (state->mail_stream && state->mail_stream->original_mailbox){
++ len = strlen(state->mail_stream->original_mailbox) + 18;
++ linedata = (char *) fs_get(len*sizeof(char));
++ sprintf(linedata,"Quota Report for %s\n",
++ state->mail_stream->original_mailbox);
++ so_puts(store,linedata);
++ if (linedata)
++ fs_give((void **)&linedata);
++ }
++ else
++ so_puts(store,"Quota Report:\n");
++ so_puts(store,"\n");
++
++ for (imapquota = state->quota; imapquota; imapquota = imapquota->next){
++ if(!strucmp(imapquota->name,"STORAGE")){
++ storage++;
++ storagelen = strlen(long2string(imapquota->limit)) + 1;
++ storageuse = imapquota->usage;
++ storagelim = imapquota->limit;
++ }
++ if(!strucmp(imapquota->name,"MESSAGE")){
++ message++;
++ messagelen = strlen(long2string(imapquota->limit)) + 1;
++ messageuse = imapquota->usage;
++ messagelim = imapquota->limit;
++ }
++ other += strucmp(imapquota->name,"STORAGE") &&
++ strucmp(imapquota->name,"MESSAGE") ? 0 : 1;
++ }
++
++ storageq = (char *) fs_get(storagelen*sizeof(char));
++ if (storage)
++ sprintf(storageq, "%lu KB", storageuse);
++ messageq = (char *) fs_get(messagelen*sizeof(char));
++ if (message)
++ sprintf(messageq, "%lu message%s", messageuse, plural(messageuse));
++ len = strlen("Usage: ") + storagelen + messagelen + 20;
++ linedata = (char *) fs_get(len*sizeof(char));
++ sprintf(linedata,"Usage: %s%s%s%s\n", storage ? storageq : "",
++ message ? (storage ? " (" : "") : "",
++ message ? messageq : "",
++ message ? (storage ? ")" : "") : "");
++ so_puts(store, linedata);
++ if (storageq)
++ fs_give((void **)&storageq);
++ if (messageq)
++ fs_give((void **)&messageq);
++ if (linedata)
++ fs_give((void **)&linedata);
++
++ storageq = (char *) fs_get(storagelen*sizeof(char));
++ if (storage)
++ sprintf(storageq, "%lu KB", storagelim);
++ messageq = (char *) fs_get(messagelen*sizeof(char));
++ if (message)
++ sprintf(messageq, "%lu message%s", messagelim, plural(messagelim));
++ len = strlen("Limit: ") + storagelen + messagelen + 20;
++ linedata = (char *) fs_get(len*sizeof(char));
++ sprintf(linedata,"Limit: %s%s%s%s", storage ? storageq : "",
++ message ? (storage ? " (" : "") : "",
++ message ? messageq : "",
++ message ? (storage ? ")" : "") : "");
++ so_puts(store, linedata);
++ if (storageq)
++ fs_give((void **)&storageq);
++ if (messageq)
++ fs_give((void **)&messageq);
++ if (linedata)
++ fs_give((void **)&linedata);
++
++ for (imapquota = state->quota; other && imapquota;
++ imapquota = imapquota->next){
++ if (strucmp(imapquota->name,"STORAGE") &&
++ strucmp(imapquota->name,"MESSAGE")){
++ len = (imapquota->name ? strlen(imapquota->name) : strlen("No Name"))
++ + 2*strlen(long2string(imapquota->limit)) + 46;
++ linedata = (char *) fs_get(len*sizeof(char));
++ sprintf(linedata,
++ "Resource : %s\nUsage : %lu (%lu%%)\nLimit : %lu\n\n",
++ imapquota->name ? imapquota->name : "No Name",
++ imapquota->usage, 100*imapquota->usage/imapquota->limit,
++ imapquota->limit);
++ so_puts(store,linedata);
++ if (linedata)
++ fs_give((void **)&linedata);
++ }
++ }
++
++ memset(&sargs, 0, sizeof(SCROLL_S));
++ sargs.text.text = so_text(store);
++ sargs.text.src = CharStar;
++ sargs.text.desc = "Quota Resources Summary";
++ sargs.bar.title = cpystr("QUOTA SUMMARY");
++ sargs.proc.tool = process_quota_cmd;
++ sargs.help.text = NO_HELP;
++ sargs.help.title = NULL;
++ sargs.keys.menu = &pine_quota_keymenu;
++ setbitmap(sargs.keys.bitmap);
++
++ scrolltool(&sargs);
++ so_give(&store);
++
++ if (state->quota)
++ mail_free_quotalist(&(state->quota));
++ }
++
+ /*----------------------------------------------------------------------
+ Execute DELETE message command
+
+***************
+*** 2928,2933 ****
+--- 3146,3152 ----
+
+ dprint(4, (debugfile, "\n - saving message -\n"));
+
++ saved_stream = stream; /* ugly hack! */
+ state->ugly_consider_advancing_bit = 0;
+ if(F_OFF(F_SAVE_PARTIAL_WO_CONFIRM, state)
+ && msgno_any_deletedparts(stream, msgmap)
+***************
+*** 3175,3181 ****
+ {
+ static char folder[MAILTMPLEN+1] = {'\0'};
+ static CONTEXT_S *last_context = NULL;
+! int rc, n, flags, last_rc = 0, saveable_count = 0, done = 0;
+ int context_was_set, delindex;
+ char prompt[MAX_SCREEN_COLS+1], *p, expanded[MAILTMPLEN];
+ char *buf = tmp_20k_buf;
+--- 3394,3400 ----
+ {
+ static char folder[MAILTMPLEN+1] = {'\0'};
+ static CONTEXT_S *last_context = NULL;
+! int rc, n=0, flags, last_rc = 0, saveable_count = 0, done = 0;
+ int context_was_set, delindex;
+ char prompt[MAX_SCREEN_COLS+1], *p, expanded[MAILTMPLEN];
+ char *buf = tmp_20k_buf;
+***************
+*** 3184,3189 ****
+--- 3403,3411 ----
+ char *deltext = NULL;
+ CONTEXT_S *tc;
+ ESCKEY_S ekey[9];
++ RULE_RESULT *rule;
++
++ saved_stream = state->mail_stream;
+
+ if(!cntxt)
+ panic("no context ptr in save_prompt");
+***************
+*** 3214,3219 ****
+--- 3436,3448 ----
+ return(0);
+ }
+
++ if (rule = get_result_rule(V_SAVE_RULES, FOR_RULE | FOR_SAVE, env)){
++ strncpy(folder,rule->result,sizeof(folder)-1);
++ folder[sizeof(folder)-1] = '\0';
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
+
+ /* how many context's can be saved to... */
+ for(tc = state->context_list; tc; tc = tc->next)
+***************
+*** 4134,4140 ****
+ *date = '\0';
+
+ rv = save_fetch_append(stream, mn_m2raw(msgmap, i),
+! NULL, save_stream, save_folder, context,
+ mc ? mc->rfc822_size : 0L, flags, date, so);
+
+ if(sp_expunge_count(stream))
+--- 4363,4369 ----
+ *date = '\0';
+
+ rv = save_fetch_append(stream, mn_m2raw(msgmap, i),
+! NULL, save_stream, folder, context,
+ mc ? mc->rfc822_size : 0L, flags, date, so);
+
+ if(sp_expunge_count(stream))
+***************
+*** 7265,7270 ****
+--- 7494,7558 ----
+ return(newfolder);
+ }
+
++ char *
++ any_report_message (stream)
++ MAILSTREAM *stream;
++ {
++ char message[40] = {'\0'}, *report;
++ unsigned long new, unseen;
++ int i, imapstatus = 0;
++
++ for (i = 0; ps_global->index_disp_format[i].ctype != iNothing
++ && ps_global->index_disp_format[i].ctype != iIStatus; i++);
++ imapstatus = ps_global->index_disp_format[i].ctype == iIStatus;
++
++ report = (char *) fs_get(41*sizeof(char));
++ total_messages_status(stream, imapstatus, &new, &unseen);
++
++ if (new > 0L || (unseen > 0L && imapstatus)){
++ sprintf(message," - %s%s%s%s%s", new > 0L ? comatose(new) : "",
++ new > 0L ? " new" : "",
++ new > 0L && unseen > 0L && imapstatus ? ", " : "",
++ unseen > 0L && imapstatus ? comatose(unseen) : "",
++ unseen > 0L && imapstatus ? " unseen" : "");
++ }
++ report = *message ? cpystr(message) : cpystr("");
++
++ return report;
++ }
++
++ void
++ total_messages_status (stream, imapstatus, new, unseen)
++ MAILSTREAM *stream;
++ int imapstatus;
++ unsigned long *new, *unseen;
++ {
++ MESSAGECACHE *mc;
++ unsigned long i;
++ int *searched;
++
++ if (new) *new = imapstatus ? count_flagged(stream, F_RECENT | F_UNDEL)
++ : count_flagged(stream, F_UNSEEN | F_UNDEL);
++ if (unseen) *unseen = 0L;
++
++ if (!imapstatus || !unseen)
++ return;
++
++ searched = (int *) fs_get(stream->nmsgs*sizeof(int));
++ memset(searched, 0, stream->nmsgs*sizeof(searched));
++ for (i = 1L; stream && i <= stream->nmsgs && (mc = mail_elt(stream, i)); i++)
++ if (mc->searched
++ || (mc->valid && !get_lflag(stream, NULL, i, MN_EXLD)
++ && mc->recent && !mc->deleted))
++ searched[i-1] = 1;
++ count_flagged(stream, F_UNSEEN | F_UNDEL);
++ for (i = 1L; stream && i <= stream->nmsgs && (mc = mail_elt(stream, i)); i++)
++ if (!searched[i-1] && (mc->searched
++ || (mc->valid && !get_lflag(stream, NULL, i, MN_EXLD)
++ && !mc->seen && !mc->recent && !mc->deleted)))
++ (*unseen)++;
++ fs_give((void **)&searched);
++ }
+
+ /*----------------------------------------------------------------------
+ Check to see if user input is in form of old c-client mailbox speck
+***************
+*** 7322,7327 ****
+--- 7610,7821 ----
+ return(FALSE);
+ }
+
++ void
++ setup_threading_index_style()
++ {
++ RULE_RESULT *rule;
++ NAMEVAL_S *v;
++ int i;
++
++ rule = get_result_rule(V_THREAD_INDEX_STYLE_RULES,
++ FOR_RULE | FOR_THREAD, (ENVELOPE *) NULL);
++ if (rule || ps_global->VAR_THREAD_INDEX_STYLE){
++ for(i = 0; v = thread_index_styles(i); i++)
++ if(!strucmp(rule ? rule->result : ps_global->VAR_THREAD_INDEX_STYLE,
++ rule ? (v ? v->name : "" ) : S_OR_L(v))){
++ ps_global->thread_index_style = v->value;
++ break;
++ }
++ if (rule){
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ }
++ }
++
++
++ char *get_rule_result(rule_context, newfolder, code)
++ int rule_context;
++ char *newfolder;
++ int code;
++ { char *rule_result = NULL;
++ ENVELOPE *news_envelope;
++ RULE_RESULT *rule;
++
++ if (IS_NEWS(ps_global->mail_stream)){
++ news_envelope = mail_newenvelope();
++ news_envelope->newsgroups = cpystr(newfolder);
++ }
++ else
++ news_envelope = (ENVELOPE *) NULL;
++
++ rule = get_result_rule(code, rule_context, news_envelope);
++
++ if (news_envelope)
++ mail_free_envelope (&news_envelope);
++
++ if (rule){
++ rule_result = cpystr(rule->result);
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++
++ return rule_result;
++ }
++
++ find_startup_position(rule, m, pc)
++ int rule;
++ MAILSTREAM *m;
++ long pc;
++ {
++ long n;
++ switch(rule){
++ /*
++ * For news in incoming collection we're doing the same thing
++ * for first-unseen and first-recent. In both those cases you
++ * get first-unseen if FAKE_NEW is off and first-recent if
++ * FAKE_NEW is on. If FAKE_NEW is on, first unseen is the
++ * same as first recent because all recent msgs are unseen
++ * and all unrecent msgs are seen (see pine_mail_open).
++ */
++ case IS_FIRST_UNSEEN:
++ first_unseen:
++ mn_set_cur(ps_global->msgmap,
++ (sp_first_unseen(m)
++ && mn_get_sort(ps_global->msgmap) == SortArrival
++ && !mn_get_revsort(ps_global->msgmap)
++ && !get_lflag(ps_global->mail_stream, NULL,
++ sp_first_unseen(m), MN_EXLD)
++ && (n = mn_raw2m(ps_global->msgmap,
++ sp_first_unseen(m))))
++ ? n
++ : first_sorted_flagged(F_UNSEEN | F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID));
++ break;
++
++ case IS_FIRST_RECENT:
++ first_recent:
++ /*
++ * We could really use recent for news but this is the way
++ * it has always worked, so we'll leave it. That is, if
++ * the FAKE_NEW feature is on, recent and unseen are
++ * equivalent, so it doesn't matter. If the feature isn't
++ * on, all the undeleted messages are unseen and we start
++ * at the first one. User controls with the FAKE_NEW feature.
++ */
++ if(IS_NEWS(ps_global->mail_stream)){
++ mn_set_cur(ps_global->msgmap,
++ first_sorted_flagged(F_UNSEEN|F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID));
++ }
++ else{
++ mn_set_cur(ps_global->msgmap,
++ first_sorted_flagged(F_RECENT | F_UNSEEN
++ | F_UNDEL,
++ m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID));
++ }
++ break;
++
++ case IS_FIRST_IMPORTANT:
++ mn_set_cur(ps_global->msgmap,
++ first_sorted_flagged(F_FLAG|F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID));
++ break;
++
++ case IS_FIRST_IMPORTANT_OR_UNSEEN:
++
++ if(IS_NEWS(ps_global->mail_stream))
++ goto first_unseen;
++
++ {
++ MsgNo flagged, first_unseen;
++
++ flagged = first_sorted_flagged(F_FLAG|F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID);
++ first_unseen = (sp_first_unseen(m)
++ && mn_get_sort(ps_global->msgmap) == SortArrival
++ && !mn_get_revsort(ps_global->msgmap)
++ && !get_lflag(ps_global->mail_stream, NULL,
++ sp_first_unseen(m), MN_EXLD)
++ && (n = mn_raw2m(ps_global->msgmap,
++ sp_first_unseen(m))))
++ ? n
++ : first_sorted_flagged(F_UNSEEN|F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID);
++ mn_set_cur(ps_global->msgmap,
++ (MsgNo) min((int) flagged, (int) first_unseen));
++
++ }
++
++ break;
++
++ case IS_FIRST_IMPORTANT_OR_RECENT:
++
++ if(IS_NEWS(ps_global->mail_stream))
++ goto first_recent;
++
++ {
++ MsgNo flagged, first_recent;
++
++ flagged = first_sorted_flagged(F_FLAG|F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID);
++ first_recent = first_sorted_flagged(F_RECENT | F_UNSEEN
++ | F_UNDEL,
++ m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID);
++ mn_set_cur(ps_global->msgmap,
++ (MsgNo) min((int) flagged, (int) first_recent));
++ }
++
++ break;
++
++ case IS_FIRST:
++ mn_set_cur(ps_global->msgmap,
++ first_sorted_flagged(F_UNDEL, m, pc,
++ THREADING() ? 0 : FSF_SKIP_CHID));
++ break;
++
++ case IS_LAST:
++ mn_set_cur(ps_global->msgmap,
++ first_sorted_flagged(F_UNDEL, m, pc,
++ FSF_LAST | (THREADING() ? 0 : FSF_SKIP_CHID)));
++ break;
++
++ default:
++ panic("Unexpected incoming startup case");
++ break;
++
++ }
++ }
++
++ unsigned
++ get_perfolder_startup_rule(stream, rule_type, folder)
++ MAILSTREAM *stream;
++ int rule_type;
++ char *folder;
++ {
++ unsigned startup_rule;
++ char *rule_result;
++
++ startup_rule = reset_startup_rule(stream);
++ rule_result = get_rule_result(FOR_RULE | FOR_STARTUP, folder, rule_type);
++ if (rule_result && *rule_result){
++ int i;
++ NAMEVAL_S *v;
++
++ for(i = 0; v = incoming_startup_rules(i); i++)
++ if(!strucmp(rule_result, v->name)){
++ startup_rule = v->value;
++ break;
++ }
++ fs_give((void **)&rule_result);
++ }
++ return startup_rule;
++ }
++
+
+ /*----------------------------------------------------------------------
+ Actually attempt to open given folder
+***************
+*** 7356,7362 ****
+ int open_inbox, rv, old_tros, we_cancel = 0,
+ do_reopen = 0, n, was_dead = 0, cur_already_set = 0;
+ char expanded_file[max(MAXPATH,MAILTMPLEN)+1],
+! *old_folder, *old_path, *p;
+ long openmode, rflags = 0L, pc = 0L, cur, raw;
+ ENVELOPE *env = NULL;
+ char status_msg[81];
+--- 7850,7856 ----
+ int open_inbox, rv, old_tros, we_cancel = 0,
+ do_reopen = 0, n, was_dead = 0, cur_already_set = 0;
+ char expanded_file[max(MAXPATH,MAILTMPLEN)+1],
+! *old_folder, *old_path, *p, *report;
+ long openmode, rflags = 0L, pc = 0L, cur, raw;
+ ENVELOPE *env = NULL;
+ char status_msg[81];
+***************
+*** 7690,7704 ****
+ sizeof(ps_global->cur_folder)-1);
+ ps_global->cur_folder[sizeof(ps_global->cur_folder)-1] = '\0';
+ ps_global->context_current = ps_global->context_list;
+ reset_index_format();
+ clear_index_cache();
+ /* MUST sort before restoring msgno! */
+ refresh_sort(ps_global->mail_stream, ps_global->msgmap, SRT_NON);
+! q_status_message3(SM_ORDER, 0, 3,
+! "Opened folder \"%.200s\" with %.200s message%.200s",
+! ps_global->inbox_name,
+! long2string(mn_get_total(ps_global->msgmap)),
+! plural(mn_get_total(ps_global->msgmap)));
+ #ifdef _WINDOWS
+ mswin_settitle(ps_global->inbox_name);
+ #endif
+--- 8184,8203 ----
+ sizeof(ps_global->cur_folder)-1);
+ ps_global->cur_folder[sizeof(ps_global->cur_folder)-1] = '\0';
+ ps_global->context_current = ps_global->context_list;
++ setup_threading_index_style();
+ reset_index_format();
+ clear_index_cache();
+ /* MUST sort before restoring msgno! */
+ refresh_sort(ps_global->mail_stream, ps_global->msgmap, SRT_NON);
+! report = any_report_message(ps_global->mail_stream);
+! q_status_message4(SM_ORDER, 0, 3,
+! "Opened folder \"%.200s\" with %.200s message%.200s%.200s",
+! ps_global->inbox_name,
+! long2string(mn_get_total(ps_global->msgmap)),
+! plural(mn_get_total(ps_global->msgmap)),
+! report);
+! if (report)
+! fs_give((void **)&report);
+ #ifdef _WINDOWS
+ mswin_settitle(ps_global->inbox_name);
+ #endif
+***************
+*** 7999,8004 ****
+--- 8498,8504 ----
+
+ clear_index_cache();
+ reset_index_format();
++ setup_threading_index_style();
+
+ /*
+ * Start news reading with messages the user's marked deleted
+***************
+*** 8018,8025 ****
+ if(!sp_flagged(ps_global->mail_stream, SP_FILTERED))
+ process_filter_patterns(ps_global->mail_stream, ps_global->msgmap, 0L);
+
+! q_status_message6(SM_ORDER, 0, 4,
+! "%.20s \"%.200s\" opened with %.20s message%.20s%.20s%.20s",
+ IS_NEWS(ps_global->mail_stream)
+ ? "News group" : "Folder",
+ pretty_fn(newfolder),
+--- 8518,8533 ----
+ if(!sp_flagged(ps_global->mail_stream, SP_FILTERED))
+ process_filter_patterns(ps_global->mail_stream, ps_global->msgmap, 0L);
+
+! if(!(rflags & SP_MATCH) || !(rflags & SP_LOCKED))
+! reset_sort_order(SRT_VRB);
+! else if(sp_new_mail_count(ps_global->mail_stream) > 0L
+! || sp_unsorted_newmail(ps_global->mail_stream)
+! || sp_need_to_rethread(ps_global->mail_stream))
+! refresh_sort(ps_global->mail_stream, ps_global->msgmap, SRT_NON);
+!
+! report = any_report_message(ps_global->mail_stream);
+! q_status_message7(SM_ORDER, 0, 4,
+! "%.20s \"%.200s\" opened with %.20s message%.20s%.20s%.20s%.20s",
+ IS_NEWS(ps_global->mail_stream)
+ ? "News group" : "Folder",
+ pretty_fn(newfolder),
+***************
+*** 8029,8048 ****
+ && sp_flagged(ps_global->mail_stream, SP_PERMLOCKED))
+ ? " (StayOpen)" : "",
+ READONLY_FOLDER(ps_global->mail_stream)
+! ? " READONLY" : "");
+
+ #ifdef _WINDOWS
+ mswin_settitle(pretty_fn(newfolder));
+ #endif
+
+- if(!(rflags & SP_MATCH) || !(rflags & SP_LOCKED))
+- reset_sort_order(SRT_VRB);
+- else if(sp_new_mail_count(ps_global->mail_stream) > 0L
+- || sp_unsorted_newmail(ps_global->mail_stream)
+- || sp_need_to_rethread(ps_global->mail_stream))
+- refresh_sort(ps_global->mail_stream, ps_global->msgmap, SRT_NON);
+-
+-
+ /*
+ * Set current message number when re-opening Stay-Open or
+ * cached folders.
+--- 8537,8551 ----
+ && sp_flagged(ps_global->mail_stream, SP_PERMLOCKED))
+ ? " (StayOpen)" : "",
+ READONLY_FOLDER(ps_global->mail_stream)
+! ? " READONLY" : "",
+! report);
+! if (report)
+! fs_give((void **)&report);
+
+ #ifdef _WINDOWS
+ mswin_settitle(pretty_fn(newfolder));
+ #endif
+
+ /*
+ * Set current message number when re-opening Stay-Open or
+ * cached folders.
+***************
+*** 8106,8112 ****
+
+ if(!cur_already_set && mn_get_total(ps_global->msgmap) > 0L){
+
+! perfolder_startup_rule = reset_startup_rule(ps_global->mail_stream);
+
+ if(ps_global->start_entry > 0){
+ mn_set_cur(ps_global->msgmap, mn_get_revsort(ps_global->msgmap)
+--- 8609,8618 ----
+
+ if(!cur_already_set && mn_get_total(ps_global->msgmap) > 0L){
+
+! perfolder_startup_rule = get_perfolder_startup_rule(ps_global->mail_stream,
+! V_STARTUP_RULES, newfolder);
+!
+! reset_startup_rule(ps_global->mail_stream);
+
+ if(ps_global->start_entry > 0){
+ mn_set_cur(ps_global->msgmap, mn_get_revsort(ps_global->msgmap)
+***************
+*** 8128,8267 ****
+ else
+ use_this_startup_rule = ps_global->inc_startup_rule;
+
+! switch(use_this_startup_rule){
+! /*
+! * For news in incoming collection we're doing the same thing
+! * for first-unseen and first-recent. In both those cases you
+! * get first-unseen if FAKE_NEW is off and first-recent if
+! * FAKE_NEW is on. If FAKE_NEW is on, first unseen is the
+! * same as first recent because all recent msgs are unseen
+! * and all unrecent msgs are seen (see pine_mail_open).
+! */
+! case IS_FIRST_UNSEEN:
+! first_unseen:
+! mn_set_cur(ps_global->msgmap,
+! (sp_first_unseen(m)
+! && mn_get_sort(ps_global->msgmap) == SortArrival
+! && !mn_get_revsort(ps_global->msgmap)
+! && !get_lflag(ps_global->mail_stream, NULL,
+! sp_first_unseen(m), MN_EXLD)
+! && (n = mn_raw2m(ps_global->msgmap,
+! sp_first_unseen(m))))
+! ? n
+! : first_sorted_flagged(F_UNSEEN | F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID));
+! break;
+
+! case IS_FIRST_RECENT:
+! first_recent:
+! /*
+! * We could really use recent for news but this is the way
+! * it has always worked, so we'll leave it. That is, if
+! * the FAKE_NEW feature is on, recent and unseen are
+! * equivalent, so it doesn't matter. If the feature isn't
+! * on, all the undeleted messages are unseen and we start
+! * at the first one. User controls with the FAKE_NEW feature.
+! */
+! if(IS_NEWS(ps_global->mail_stream)){
+! mn_set_cur(ps_global->msgmap,
+! first_sorted_flagged(F_UNSEEN|F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID));
+! }
+! else{
+! mn_set_cur(ps_global->msgmap,
+! first_sorted_flagged(F_RECENT | F_UNSEEN
+! | F_UNDEL,
+! m, pc,
+ THREADING() ? 0 : FSF_SKIP_CHID));
+! }
+! break;
+!
+! case IS_FIRST_IMPORTANT:
+! mn_set_cur(ps_global->msgmap,
+! first_sorted_flagged(F_FLAG|F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID));
+! break;
+!
+! case IS_FIRST_IMPORTANT_OR_UNSEEN:
+!
+! if(IS_NEWS(ps_global->mail_stream))
+! goto first_unseen;
+!
+! {
+! MsgNo flagged, first_unseen;
+!
+! flagged = first_sorted_flagged(F_FLAG|F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID);
+! first_unseen = (sp_first_unseen(m)
+! && mn_get_sort(ps_global->msgmap) == SortArrival
+! && !mn_get_revsort(ps_global->msgmap)
+! && !get_lflag(ps_global->mail_stream, NULL,
+! sp_first_unseen(m), MN_EXLD)
+! && (n = mn_raw2m(ps_global->msgmap,
+! sp_first_unseen(m))))
+! ? n
+! : first_sorted_flagged(F_UNSEEN|F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID);
+! mn_set_cur(ps_global->msgmap,
+! (MsgNo) min((int) flagged, (int) first_unseen));
+!
+! }
+!
+! break;
+!
+! case IS_FIRST_IMPORTANT_OR_RECENT:
+!
+! if(IS_NEWS(ps_global->mail_stream))
+! goto first_recent;
+!
+! {
+! MsgNo flagged, first_recent;
+!
+! flagged = first_sorted_flagged(F_FLAG|F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID);
+! first_recent = first_sorted_flagged(F_RECENT | F_UNSEEN
+! | F_UNDEL,
+! m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID);
+! mn_set_cur(ps_global->msgmap,
+! (MsgNo) min((int) flagged, (int) first_recent));
+! }
+!
+! break;
+!
+! case IS_FIRST:
+! mn_set_cur(ps_global->msgmap,
+! first_sorted_flagged(F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID));
+! break;
+!
+! case IS_LAST:
+! mn_set_cur(ps_global->msgmap,
+! first_sorted_flagged(F_UNDEL, m, pc,
+! FSF_LAST | (THREADING() ? 0 : FSF_SKIP_CHID)));
+! break;
+!
+! default:
+! panic("Unexpected incoming startup case");
+! break;
+!
+! }
+! }
+! else if(IS_NEWS(ps_global->mail_stream)){
+! /*
+! * This will go to two different places depending on the FAKE_NEW
+! * feature (see pine_mail_open).
+! */
+! mn_set_cur(ps_global->msgmap,
+! first_sorted_flagged(F_UNSEEN|F_UNDEL, m, pc,
+! THREADING() ? 0 : FSF_SKIP_CHID));
+! }
+! else{
+! mn_set_cur(ps_global->msgmap,
+! mn_get_revsort(ps_global->msgmap)
+! ? 1L
+! : mn_get_total(ps_global->msgmap));
+! }
+
+ adjust_cur_to_visible(ps_global->mail_stream, ps_global->msgmap);
+ }
+--- 8634,8657 ----
+ else
+ use_this_startup_rule = ps_global->inc_startup_rule;
+
+! find_startup_position(use_this_startup_rule, m, pc);
+
+! }
+! else if(IS_NEWS(ps_global->mail_stream)){
+! /*
+! * This will go to two different places depending on the FAKE_NEW
+! * feature (see pine_mail_open).
+! */
+! mn_set_cur(ps_global->msgmap,
+! first_sorted_flagged(F_UNSEEN|F_UNDEL, m, pc,
+ THREADING() ? 0 : FSF_SKIP_CHID));
+! }
+! else{
+! mn_set_cur(ps_global->msgmap,
+! mn_get_revsort(ps_global->msgmap)
+! ? 1L
+! : mn_get_total(ps_global->msgmap));
+! }
+
+ adjust_cur_to_visible(ps_global->mail_stream, ps_global->msgmap);
+ }
+***************
+*** 8284,8290 ****
+ PAT_S *pat;
+ int we_set_it = 0;
+
+! if(ps_global->mail_stream && nonempty_patterns(rflags, &pstate)){
+ for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
+ if(match_pattern(pat->patgrp, ps_global->mail_stream, NULL,
+ NULL, NULL, SO_NOSERVER|SE_NOPREFETCH))
+--- 8674,8683 ----
+ PAT_S *pat;
+ int we_set_it = 0;
+
+! if(find_index_rule())
+! return;
+!
+! if(ps_global->mail_stream && nonempty_patterns(rflags, &pstate)){
+ for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
+ if(match_pattern(pat->patgrp, ps_global->mail_stream, NULL,
+ NULL, NULL, SO_NOSERVER|SE_NOPREFETCH))
+***************
+*** 8314,8323 ****
+ PAT_S *pat;
+ SortOrder the_sort_order;
+ int sort_is_rev;
+!
+ /* set default order */
+ the_sort_order = ps_global->def_sort;
+! sort_is_rev = ps_global->def_sort_rev;
+
+ if(ps_global->mail_stream && nonempty_patterns(rflags, &pstate)){
+ for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
+--- 8707,8733 ----
+ PAT_S *pat;
+ SortOrder the_sort_order;
+ int sort_is_rev;
+! char *rule_result;
+! SortOrder new_sort = EndofList;
+! int is_rev;
+!
+! rule_result = get_rule_result(FOR_RULE | FOR_SORT, ps_global->cur_folder,
+! V_SORT_RULES);
+! if (rule_result && *rule_result){
+! new_sort = (SortOrder) translate(rule_result, 1);
+! is_rev = (SortOrder) translate(rule_result, 0) == EndofList ? 0 : 1;
+! fs_give((void **)&rule_result);
+! }
+! if (new_sort != EndofList){
+! the_sort_order = new_sort;
+! sort_is_rev = is_rev;
+! }
+! else{
+ /* set default order */
+ the_sort_order = ps_global->def_sort;
+! sort_is_rev = the_sort_order == SortThread
+! ? (ps_global->thread_def_sort_rev + ps_global->def_sort_rev) % 2
+! : ps_global->def_sort_rev;
+
+ if(ps_global->mail_stream && nonempty_patterns(rflags, &pstate)){
+ for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
+***************
+*** 8329,8340 ****
+ if(pat && pat->action && !pat->action->bogus
+ && pat->action->sort_is_set){
+ the_sort_order = pat->action->sortorder;
+! sort_is_rev = pat->action->revsort;
+ }
+ }
+
+ sort_folder(ps_global->mail_stream, ps_global->msgmap,
+! the_sort_order, sort_is_rev, flags);
+ }
+
+
+--- 8739,8756 ----
+ if(pat && pat->action && !pat->action->bogus
+ && pat->action->sort_is_set){
+ the_sort_order = pat->action->sortorder;
+! sort_is_rev = the_sort_order == SortThread
+! ? (ps_global->thread_def_sort_rev + pat->action->revsort) % 2
+! : pat->action->revsort;
+ }
+ }
++ }
++ if (ps_global->thread_cur_sort != SortArrival
++ && ps_global->thread_cur_sort != SortThread)
++ ps_global->thread_cur_sort = ps_global->thread_def_sort;
+
+ sort_folder(ps_global->mail_stream, ps_global->msgmap,
+! the_sort_order, sort_is_rev, flags, 1);
+ }
+
+
+***************
+*** 8420,8425 ****
+--- 8836,8842 ----
+ temp[MAILTMPLEN+1], buff1[MAX_SCREEN_COLS+1], *moved_msg = NULL,
+ buff2[MAX_SCREEN_COLS+1], *folder;
+ CONTEXT_S *context;
++ FOLDER_S *f;
+ struct variable *vars = ps_global->vars;
+ int ret, expunge = FALSE, no_close = 0;
+ char ing[4];
+***************
+*** 8436,8442 ****
+ }
+
+ if(stream != NULL){
+! context = sp_context(stream);
+ folder = STREAMNAME(stream);
+
+ dprint(2, (debugfile, "expunge_and_close: \"%s\"%s\n",
+--- 8853,8859 ----
+ }
+
+ if(stream != NULL){
+! context = ps_global->context_current;
+ folder = STREAMNAME(stream);
+
+ dprint(2, (debugfile, "expunge_and_close: \"%s\"%s\n",
+***************
+*** 8449,8454 ****
+--- 8866,8879 ----
+ buff1[0] = '\0';
+ buff2[0] = '\0';
+
++ if(F_OFF(F_ENABLE_FAST_RECENT,ps_global) &&
++ (f = incoming_folder_data(stream, context))){
++ new_mail_in_open_stream(stream, &(f->recent), &(f->messages));
++ f->notified = 0;
++ f->countrecent = 0L;
++ f->selected = f->user_selected;
++ }
++
+ if(!stream->rdonly){
+
+ if(!no_close){
+***************
+*** 8476,8484 ****
+ /* Save read messages? */
+ if(VAR_READ_MESSAGE_FOLDER && VAR_READ_MESSAGE_FOLDER[0]
+ && sp_flagged(stream, SP_INBOX)
+! && (seen_not_del = count_flagged(stream, F_SEEN | F_UNDEL))){
+
+ if(F_ON(F_AUTO_READ_MSGS,ps_global)
+ || read_msg_prompt(seen_not_del, VAR_READ_MESSAGE_FOLDER))
+ /* move inbox's read messages */
+ moved_msg = move_read_msgs(stream, VAR_READ_MESSAGE_FOLDER,
+--- 8901,8911 ----
+ /* Save read messages? */
+ if(VAR_READ_MESSAGE_FOLDER && VAR_READ_MESSAGE_FOLDER[0]
+ && sp_flagged(stream, SP_INBOX)
+! && (F_ON(F_AUTO_READ_MSGS_RULES, ps_global) ||
+! (seen_not_del = count_flagged(stream, F_SEEN | F_UNDEL)))){
+
+ if(F_ON(F_AUTO_READ_MSGS,ps_global)
++ || F_ON(F_AUTO_READ_MSGS_RULES, ps_global)
+ || read_msg_prompt(seen_not_del, VAR_READ_MESSAGE_FOLDER))
+ /* move inbox's read messages */
+ moved_msg = move_read_msgs(stream, VAR_READ_MESSAGE_FOLDER,
+***************
+*** 10133,10138 ****
+--- 10560,10568 ----
+ char *bufp = NULL;
+ MESSAGECACHE *mc;
+
++ if (F_ON(F_AUTO_READ_MSGS_RULES, ps_global))
++ return move_read_msgs_using_rules(stream, dstfldr, buf);
++
+ if(!is_absolute_path(dstfldr)
+ && !(save_context = default_save_context(ps_global->context_list)))
+ save_context = ps_global->context_list;
+***************
+*** 10174,10181 ****
+ sprintf(buf, "Moving %s read message%s to \"%.45s\"",
+ comatose(searched), plural(searched), dstfldr);
+ we_cancel = busy_alarm(1, buf, NULL, 1);
+! if(save(ps_global, stream, save_context, dstfldr, msgmap,
+! SV_DELETE | SV_FIX_DELS) == searched)
+ strncpy(bufp = buf + 1, "Moved", 5); /* change Moving to Moved */
+
+ mn_give(&msgmap);
+--- 10604,10612 ----
+ sprintf(buf, "Moving %s read message%s to \"%.45s\"",
+ comatose(searched), plural(searched), dstfldr);
+ we_cancel = busy_alarm(1, buf, NULL, 1);
+! ps_global->exiting = 1;
+! if((save(ps_global, stream, save_context, dstfldr, msgmap,
+! SV_DELETE | SV_FIX_DELS) == searched))
+ strncpy(bufp = buf + 1, "Moved", 5); /* change Moving to Moved */
+
+ mn_give(&msgmap);
+***************
+*** 10186,10191 ****
+--- 10617,10759 ----
+ return(bufp);
+ }
+
++ char *
++ move_read_msgs_using_rules(stream, dstfldr,buf)
++ MAILSTREAM *stream;
++ char *dstfldr;
++ char *buf;
++ {
++ CONTEXT_S *save_context = NULL;
++ char **folder_to_save = NULL;
++ int num, we_cancel;
++ long i, j, success, nmsgs = 0L;
++ MSGNO_S *msgmap = NULL;
++
++ saved_stream = stream; /* horrible hack! */
++ if(!is_absolute_path(dstfldr)
++ && !(save_context = default_save_context(ps_global->context_list)))
++ save_context = ps_global->context_list;
++
++ folder_to_save = (char **)fs_get((stream->nmsgs + 1)*sizeof(char *));
++ folder_to_save[0] = NULL;
++ mn_init(&msgmap, stream->nmsgs);
++ for (i = 1L; i <= stream->nmsgs ; i++){
++ set_lflag(stream, msgmap, i, MN_SLCT, 0);
++ folder_to_save[i] = get_lflag(stream, NULL, i, MN_EXLD)
++ ? NULL : get_folder_to_save(stream, i, dstfldr);
++ }
++ for (i = 1L; i <= stream->nmsgs; i++){
++ num = 0;
++ if (folder_to_save[i]){
++ mn_init(&msgmap, stream->nmsgs);
++ for (j = i; j <= stream->nmsgs ; j++){
++ if (folder_to_save[j]){
++ if (!strcmp(folder_to_save[i], folder_to_save[j])){
++ set_lflag(stream, msgmap, j, MN_SLCT, 1);
++ num++;
++ if (j != i)
++ fs_give((void **)&folder_to_save[j]);
++ }
++ }
++ }
++ pseudo_selected(msgmap);
++ sprintf(buf, "Moving %s read message%s to \"%.45s\"",
++ comatose(num), plural(num), folder_to_save[i]);
++ we_cancel = busy_alarm(1, buf, NULL, 1);
++ ps_global->exiting = 1;
++ if(success = save(ps_global, stream,save_context, folder_to_save[i],
++ msgmap, SV_DELETE | SV_FIX_DELS))
++ nmsgs += success;
++ if(we_cancel)
++ cancel_busy_alarm(success ? 0 : -1);
++ for (j = i; j <= stream->nmsgs ; j++)
++ set_lflag(stream, msgmap, j, MN_SLCT, 0);
++ fs_give((void **)&folder_to_save[i]);
++ mn_give(&msgmap);
++ }
++ }
++ ps_global->exiting = 0; /* useful if we call from aggregate operations */
++ sprintf(buf, "Moved automatically %s message%s",
++ comatose(nmsgs), plural(nmsgs));
++ if (folder_to_save)
++ fs_give((void **)folder_to_save);
++ rule_curpos = 0L;
++ return buf;
++ }
++
++ unsigned long
++ rules_cursor_pos(stream)
++ MAILSTREAM *stream;
++ {
++ MSGNO_S *msgmap = sp_msgmap(stream);
++ return rule_curpos != 0L ? rule_curpos : mn_m2raw(msgmap,mn_get_cur(msgmap));
++ }
++
++
++ MAILSTREAM *
++ find_open_stream()
++ {
++ return saved_stream;
++ }
++
++ char *
++ get_folder_to_save(stream, i, dstfldr)
++ MAILSTREAM *stream;
++ long i;
++ char *dstfldr;
++ {
++ MESSAGECACHE *mc = NULL;
++ RULE_RESULT *rule;
++ MSGNO_S *msgmap = NULL;
++ char *folder_to_save = NULL, *save_folder = NULL;
++ int n;
++ long msgno;
++
++ /* The plan is as follows: Select each message of the folder. We
++ * need to set the cursor correctly so that iFlag gets the value
++ * correctly too, otherwise iFlag will get the value of the position
++ * of the cursor. After that we need to look for a rule that applies
++ * to the message and get the saving folder. If we get a saving folder,
++ * and we used the _FLAG_ token, use that folder, if no
++ * _FLAG_ token was used, move only if seen and not deleted, to the
++ * folder specified in the saving rule. If we did not get a saving
++ * folder from the rule, just save in the default folder.
++ */
++
++ mn_init(&msgmap, stream->nmsgs);
++ rule_curpos = i;
++ msgno = mn_m2raw(msgmap, i);
++ if (msgno > 0L){
++ mc = mail_elt(stream, msgno);
++ rule = (RULE_RESULT *)
++ get_result_rule(V_SAVE_RULES, FOR_RULE | FOR_SAVE,
++ (ENVELOPE *) mc->private.msg.env);
++ if (rule){
++ folder_to_save = cpystr(rule->result);
++ n = rule->number;
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ }
++
++ if (folder_to_save && *folder_to_save){
++ RULELIST *list = get_rulelist_from_code(V_SAVE_RULES,
++ ps_global->rule_list);
++ RULE_S *prule = get_rule(list, n);
++ if (condition_contains_token(prule->condition, "_FLAG_")
++ || (mc->valid && mc->seen && !mc->deleted)
++ || (!mc->valid && mc->searched))
++ save_folder = cpystr(folder_to_save);
++ else
++ save_folder = NULL;
++ }
++ else
++ if (!mc || (mc->seen && !mc->deleted))
++ save_folder = cpystr(dstfldr);
++ mn_give(&msgmap);
++ rule_curpos = 0L;
++ return save_folder;
++ }
+
+
+ /*----------------------------------------------------------------------
+***************
+*** 10232,10238 ****
+ && ((context_isambig(folder)
+ && folder_is_nick(folder, FOLDERS(context), 0))
+ || folder_index(folder, context, FI_FOLDER) > 0)
+! && (seen_undel = count_flagged(stream, F_SEEN | F_UNDEL))){
+
+ for(; f && *archive; archive++){
+ char *p;
+--- 10800,10808 ----
+ && ((context_isambig(folder)
+ && folder_is_nick(folder, FOLDERS(context), 0))
+ || folder_index(folder, context, FI_FOLDER) > 0)
+! && ((seen_undel = count_flagged(stream, F_SEEN | F_UNDEL))
+! || (F_ON(F_AUTO_READ_MSGS,ps_global) &&
+! F_ON(F_AUTO_READ_MSGS_RULES, ps_global)))){
+
+ for(; f && *archive; archive++){
+ char *p;
+***************
+*** 11514,11526 ****
+
+ ----*/
+ int
+! apply_command(state, stream, msgmap, preloadkeystroke, flags, q_line)
+ struct pine *state;
+ MAILSTREAM *stream;
+ MSGNO_S *msgmap;
+ int preloadkeystroke;
+ int flags;
+ int q_line;
+ {
+ int i = 8, /* number of static entries in sel_opts3 */
+ rv = 1,
+--- 12084,12097 ----
+
+ ----*/
+ int
+! apply_command(state, stream, msgmap, preloadkeystroke, flags, q_line, display)
+ struct pine *state;
+ MAILSTREAM *stream;
+ MSGNO_S *msgmap;
+ int preloadkeystroke;
+ int flags;
+ int q_line;
++ int display;
+ {
+ int i = 8, /* number of static entries in sel_opts3 */
+ rv = 1,
+***************
+*** 11647,11655 ****
+ collapse_or_expand(state, stream, msgmap,
+ F_ON(F_SLASH_COLL_ENTIRE, ps_global)
+ ? 0L
+! : mn_get_cur(msgmap));
+ break;
+
+ case ':' :
+ select_thread_stmp(state, stream, msgmap);
+ break;
+--- 12218,12236 ----
+ collapse_or_expand(state, stream, msgmap,
+ F_ON(F_SLASH_COLL_ENTIRE, ps_global)
+ ? 0L
+! : mn_get_cur(msgmap),
+! display);
+ break;
+
++ case '[' :
++ collapse_this_thread(state, stream, msgmap, display, 0);
++ break;
++
++ case ']' :
++ expand_this_thread(state, stream, msgmap, display, 0);
++ break;
++
++
+ case ':' :
+ select_thread_stmp(state, stream, msgmap);
+ break;
+***************
+*** 12167,12172 ****
+--- 12748,12754 ----
+ SEARCHSET **msgset;
+ {
+ PINETHRD_S *nthrd, *bthrd;
++ unsigned long next, branch;
+
+ if(!(stream && thrd))
+ return;
+***************
+*** 12175,12188 ****
+ && (!(msgset && *msgset) || in_searchset(*msgset, thrd->rawno)))
+ mm_searched(stream, thrd->rawno);
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ set_search_bit_for_thread(stream, nthrd, msgset);
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ set_search_bit_for_thread(stream, bthrd, msgset);
+ }
+--- 12757,12770 ----
+ && (!(msgset && *msgset) || in_searchset(*msgset, thrd->rawno)))
+ mm_searched(stream, thrd->rawno);
+
+! if(next= get_next(stream, thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ set_search_bit_for_thread(stream, nthrd, msgset);
+ }
+
+! if(branch = get_branch(stream, thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ set_search_bit_for_thread(stream, bthrd, msgset);
+ }
+***************
+*** 12390,12396 ****
+ {
+ int r, type, we_cancel = 0, not = 0, flags, old_imap;
+ char sstring[80], savedsstring[80], origcharset[16], tmp[128];
+! char *sval = NULL, *cset = NULL, *charset = NULL;
+ char buftmp[MAILTMPLEN];
+ ESCKEY_S ekey[4];
+ ENVELOPE *env = NULL;
+--- 12972,12978 ----
+ {
+ int r, type, we_cancel = 0, not = 0, flags, old_imap;
+ char sstring[80], savedsstring[80], origcharset[16], tmp[128];
+! char namehdr[80], *sval = NULL, *cset = NULL, *charset = NULL;
+ char buftmp[MAILTMPLEN];
+ ESCKEY_S ekey[4];
+ ENVELOPE *env = NULL;
+***************
+*** 12464,12469 ****
+--- 13046,13085 ----
+ sval = "BODYTEXT";
+ break;
+
++ case 'h' :
++ sprintf(tmp, "Name of HEADER to match : ");
++ flags = OE_APPEND_CURRENT;
++ namehdr[0] = '\0';
++ r = 'x';
++ while (r == 'x'){
++ int done = 0;
++
++ r = optionally_enter(namehdr, -FOOTER_ROWS(ps_global), 0,
++ sizeof(namehdr), tmp, ekey, NO_HELP, &flags);
++ if (r == 1){
++ cmd_cancelled("Selection by text");
++ return(1);
++ }
++ removing_leading_white_space(namehdr);
++ while(!done){
++ while ((namehdr[0] != '\0') && /* remove trailing ":" */
++ (namehdr[strlen(namehdr) - 1] == ':'))
++ namehdr[strlen(namehdr) - 1] = '\0';
++ if ((namehdr[0] != '\0')
++ && isspace((unsigned char) namehdr[strlen(namehdr) - 1]))
++ removing_trailing_white_space(namehdr);
++ else
++ done++;
++ }
++ if (strchr(namehdr,' ') || strchr(namehdr,'\t') ||
++ strchr(namehdr,':'))
++ namehdr[0] = '\0';
++ if (namehdr[0] == '\0')
++ r = 'x';
++ }
++ sval = namehdr;
++ break;
++
+ case 'x':
+ break;
+
+***************
+*** 12587,12592 ****
+--- 13203,13211 ----
+ }
+
+ switch(type){
++ case 'h' : /* Any header */
++ pgm->header = mail_newsearchheader (namehdr,sstring);
++ break;
+ case 'r' : /* TO or CC */
+ if(old_imap){
+ /* No OR on old servers */
+***************
+*** 13764,13777 ****
+ Returns 0 if it was cancelled, 1 otherwise.
+ ----*/
+ int
+! select_sort(state, ql, sort, rev)
+ struct pine *state;
+ int ql;
+ SortOrder *sort;
+ int *rev;
+ {
+ char prompt[200], tmp[3], *p;
+! int s, i;
+ int deefault = 'a', retval = 1;
+ HelpType help;
+ ESCKEY_S sorts[14];
+--- 14383,14397 ----
+ Returns 0 if it was cancelled, 1 otherwise.
+ ----*/
+ int
+! select_sort(state, ql, sort, rev, thread)
+ struct pine *state;
+ int ql;
+ SortOrder *sort;
+ int *rev;
++ int thread;
+ {
+ char prompt[200], tmp[3], *p;
+! int s, i, j;
+ int deefault = 'a', retval = 1;
+ HelpType help;
+ ESCKEY_S sorts[14];
+***************
+*** 13805,13821 ****
+ strncpy(prompt, "Choose type of sort, or 'R' to reverse current sort : ",
+ sizeof(prompt));
+
+! for(i = 0; state->sort_types[i] != EndofList; i++) {
+! sorts[i].rval = i;
+! p = sorts[i].label = sort_name(state->sort_types[i]);
+! while(*(p+1) && islower((unsigned char)*p))
+! p++;
+!
+! sorts[i].ch = tolower((unsigned char)(tmp[0] = *p));
+! sorts[i].name = cpystr(tmp);
+!
+! if(mn_get_sort(state->msgmap) == state->sort_types[i])
+! deefault = sorts[i].rval;
+ }
+
+ sorts[i].ch = 'r';
+--- 14425,14451 ----
+ strncpy(prompt, "Choose type of sort, or 'R' to reverse current sort : ",
+ sizeof(prompt));
+
+! for(i = 0, j = 0; state->sort_types[i] != EndofList; i++) {
+! sorts[i].rval = i;
+! sorts[i].name = cpystr("");
+! sorts[i].label = "";
+! sorts[i].ch = -2;
+! if (!thread || state->sort_types[i] == SortArrival
+! || state->sort_types[i] == SortThread){
+! p = sorts[j].label = sort_name(state->sort_types[i]);
+! while(*(p+1) && islower((unsigned char)*p))
+! p++;
+! sorts[j].ch = tolower((unsigned char)(tmp[0] = *p));
+! sorts[j++].name = cpystr(tmp);
+! }
+!
+! if (thread){
+! if (state->thread_def_sort == state->sort_types[i])
+! deefault = sorts[j-1].rval;
+! }
+! else
+! if(mn_get_sort(state->msgmap) == state->sort_types[i])
+! deefault = sorts[i].rval;
+ }
+
+ sorts[i].ch = 'r';
+***************
+*** 13840,13846 ****
+ if(s == 'r')
+ *rev = !mn_get_revsort(state->msgmap);
+ else
+! *sort = state->sort_types[s];
+
+ if(F_ON(F_SHOW_SORT, ps_global))
+ ps_global->mangled_header = 1;
+--- 14470,14476 ----
+ if(s == 'r')
+ *rev = !mn_get_revsort(state->msgmap);
+ else
+! *sort = state->sort_types[thread ? (s == 0 ? 1 : 9) : s];
+
+ if(F_ON(F_SHOW_SORT, ps_global))
+ ps_global->mangled_header = 1;
+***************
+*** 13854,13859 ****
+--- 14484,14492 ----
+ fs_give((void **)&sorts[i].name);
+
+ blank_keymenu(ps_global->ttyo->screen_rows - 2, 0);
++ if(*sort == SortScore)
++ scores_are_used(SCOREUSE_INVALID);
++
+ return(retval);
+ }
+
+***************
+*** 14524,14526 ****
+--- 15157,15855 ----
+ return(flag_submenu);
+ }
+ #endif /* _WINDOWS */
++
++ /* Extra Fancy Thread support */
++
++ long
++ top_thread(stream, rawmsgno)
++ MAILSTREAM *stream;
++ long rawmsgno;
++ {
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno;
++
++ if(!stream)
++ return -1L;
++
++ if(rawmsgno)
++ thrd = fetch_thread(stream, rawmsgno);
++
++ if(!thrd)
++ return -1L;
++
++ return F_ON(F_ENHANCED_THREAD, ps_global)
++ ? (thrd->toploose ? thrd->toploose : thrd->top)
++ : thrd->top;
++ }
++
++ void
++ move_top_thread(stream, msgmap, rawmsgno)
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ long rawmsgno;
++ {
++ mn_set_cur(msgmap,mn_raw2m(msgmap, top_thread(stream, rawmsgno)));
++ }
++
++ long
++ top_this_thread(stream, rawmsgno)
++ MAILSTREAM *stream;
++ long rawmsgno;
++ {
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno;
++
++ if(!stream)
++ return -1L;
++
++ if(rawmsgno)
++ thrd = fetch_thread(stream, rawmsgno);
++
++ if(!thrd)
++ return -1L;
++
++ return thrd->top;
++ }
++
++ void
++ move_top_this_thread(stream, msgmap, rawmsgno)
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ long rawmsgno;
++ {
++ mn_set_cur(msgmap,mn_raw2m(msgmap, top_this_thread(stream, rawmsgno)));
++ }
++
++
++ void
++ cmd_delete_this_thread(state, stream, msgmap)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ {
++ unsigned long rawno, top, save_kolapsed;
++ PINETHRD_S *thrd = NULL, *nxthrd;
++
++ if(!stream)
++ return;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_this_thread(stream, msgmap, rawno);
++ top = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return;
++
++ save_kolapsed = this_thread_is_kolapsed(state, stream, msgmap, top);
++ collapse_this_thread(state, stream, msgmap, 0, 0);
++ thread_command(state, stream, msgmap, 'd', -FOOTER_ROWS(state), 1);
++ if (!save_kolapsed)
++ expand_this_thread(state, stream, msgmap, 0, 0);
++ }
++
++ void
++ cmd_delete_thread(state, stream, msgmap)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ {
++ unsigned long rawno, top, orig_top, topnxt, save_kolapsed;
++ PINETHRD_S *thrd = NULL, *nxthrd;
++ int done = 0, count;
++
++ if(!stream)
++ return;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_thread(stream, msgmap, rawno);
++ top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return;
++
++ while (!done){
++ cmd_delete_this_thread(state, stream, msgmap);
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
++ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_top != top_thread(stream, top)))
++ done++;
++ }
++ mn_set_cur(msgmap,mn_raw2m(msgmap, rawno));
++ cmd_delete(state, msgmap, 0, MsgIndx);
++ count = count_thread(state, stream, msgmap, rawno);
++ q_status_message2(SM_ORDER, 0, 1, "%s message%s marked deleted",
++ int2string(count), plural(count));
++ }
++
++
++
++ int
++ thread_is_kolapsed(state, stream, msgmap, rawmsgno)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ long rawmsgno;
++ {
++ int collapsed;
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno, orig, orig_rawno;
++
++ if(!stream)
++ return -1;
++
++ orig = mn_get_cur(msgmap);
++ move_top_thread(stream, msgmap, rawmsgno);
++ rawno = orig_rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return -1;
++
++ while(collapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno))
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
++ || !(rawno = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_rawno != top_thread(stream, rawno)))
++ break;
++
++ mn_set_cur(msgmap,orig); /* return home */
++
++ return collapsed;
++ }
++
++ /* this function tells us if the thread (or branch in the case of loose threads)
++ * is collapsed
++ */
++
++ int
++ this_thread_is_kolapsed(state, stream, msgmap, rawmsgno)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ long rawmsgno;
++ {
++ int collapsed;
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno, orig;
++
++ if(!stream)
++ return -1;
++
++ rawno = rawmsgno;
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return -1;
++
++ collapsed = get_lflag(stream, NULL, rawno, MN_COLL | MN_CHID);
++
++ if (!thrd->next){
++ if (thrd->rawno != top_thread(stream, thrd->rawno))
++ collapsed = get_lflag(stream, NULL, rawno, MN_CHID);
++ else
++ collapsed = get_lflag(stream, NULL, rawno, MN_COLL);
++ }
++
++ return collapsed;
++ }
++
++ int
++ collapse_this_thread(state, stream, msgmap, display, special)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int display;
++ int special;
++ {
++ int collapsed, rv = 1, done = 0;
++ PINETHRD_S *thrd = NULL, *nthrd;
++ unsigned long rawno, orig, msgno;
++
++ if(!stream)
++ return 0;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return rv;
++
++ collapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno);
++
++ if (special && collapsed){
++ expand_this_thread(state, stream, msgmap, 0, 0);
++ collapsed = 0;
++ }
++
++ clear_index_cache_ent(mn_raw2m(msgmap,rawno));
++
++ if (!collapsed && thrd->next){
++ if (thrd->rawno == top_thread(stream, thrd->rawno))
++ collapse_or_expand(state, stream, msgmap, mn_get_cur(msgmap), display);
++ else{
++ set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno), MN_COLL, 1);
++ set_thread_subtree(stream, thrd, msgmap, 1, MN_CHID);
++ }
++ }
++ else{
++ if (!collapsed && special
++ && ((F_OFF(F_ENHANCED_THREAD, state) && !thrd->next)
++ || F_ON(F_ENHANCED_THREAD, state))){
++ if (thrd->toploose){
++ if (thrd->rawno != thrd->toploose)
++ set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_CHID,
++ 1);
++ else
++ set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_COLL,
++ 1);
++ }
++ }
++ else{
++ rv = 0;
++ if (display)
++ q_status_message(SM_ORDER, 0, 1, "Thread already collapsed");
++ }
++ }
++ return rv;
++ }
++
++ void
++ collapse_thread(state, stream, msgmap, display)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int display;
++ {
++ int collapsed, rv = 1, done = 0;
++ PINETHRD_S *thrd = NULL;
++ unsigned long orig, orig_top, top;
++
++ if(!stream)
++ return;
++
++ expand_this_thread(state, stream, msgmap, display, 1);
++ orig = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_thread(stream, msgmap,orig);
++ top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap));
++
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return;
++
++ while (!done){
++ collapse_this_thread(state, stream, msgmap, display, 1);
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
++ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_top != top_thread(stream, top)))
++ done++;
++ }
++ mn_set_cur(msgmap,mn_raw2m(msgmap, orig_top));
++ }
++
++ int
++ expand_this_thread(state, stream, msgmap, display, special)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int display;
++ int special;
++ {
++ int collapsed, rv = 1, done = 0;
++ PINETHRD_S *thrd = NULL, *nthrd;
++ unsigned long rawno, orig, msgno;
++
++ if(!stream)
++ return 0;
++
++ orig = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_this_thread(stream, msgmap,orig);
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return rv;
++
++ collapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno);
++
++ if (special && !collapsed){
++ collapse_this_thread(state, stream, msgmap, 0, 0);
++ collapsed = 1;
++ }
++
++ clear_index_cache_ent(mn_raw2m(msgmap,rawno));
++
++ if (collapsed && thrd->next){
++ if (thrd->rawno == top_thread(stream, thrd->rawno))
++ collapse_or_expand(state, stream, msgmap, mn_get_cur(msgmap), display);
++ else{
++ set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno), MN_COLL, 0);
++ set_thread_subtree(stream, thrd, msgmap, 0, MN_CHID);
++ }
++ }
++ else{
++ if (collapsed && special
++ && ((F_OFF(F_ENHANCED_THREAD, state) && !thrd->next)
++ || F_ON(F_ENHANCED_THREAD, state))){
++ if (thrd->toploose)
++ if (thrd->rawno != thrd->toploose)
++ set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_CHID, 0);
++ else
++ set_lflag(stream, msgmap, mn_raw2m(msgmap,thrd->rawno),MN_COLL, 0);
++ }
++ else{
++ rv = 0;
++ if (display)
++ q_status_message(SM_ORDER, 0, 1, "Thread already expanded");
++ }
++ }
++ return rv;
++ }
++
++ void
++ expand_thread(state, stream, msgmap, display)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int display;
++ {
++ int collapsed, rv = 1, done = 0;
++ PINETHRD_S *thrd = NULL;
++ unsigned long orig, orig_top, top;
++
++ if(!stream)
++ return;
++
++ orig = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap));
++
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return;
++
++ while (!done){
++ expand_this_thread(state, stream, msgmap, display, 1);
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
++ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_top != top_thread(stream, top)))
++ done++;
++ }
++ mn_set_cur(msgmap,mn_raw2m(msgmap, orig_top));
++ }
++
++
++ void
++ cmd_undelete_this_thread(state, stream, msgmap)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ {
++ unsigned long rawno;
++ int save_kolapsed;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ save_kolapsed = this_thread_is_kolapsed(state, stream, msgmap, rawno);
++ collapse_this_thread(state, stream, msgmap, 0, 0);
++ thread_command(state, stream, msgmap, 'u', -FOOTER_ROWS(state), 1);
++ if (!save_kolapsed)
++ expand_this_thread(state, stream, msgmap, 0, 0);
++ }
++
++ void
++ cmd_undelete_thread(state, stream, msgmap)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ {
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno, top, orig_top;
++ int done = 0, count;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_thread(stream, msgmap, rawno);
++ top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return;
++
++ while (!done){
++ cmd_undelete_this_thread(state, stream, msgmap);
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
++ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_top != top_thread(stream, top)))
++ done++;
++ }
++ mn_set_cur(msgmap,mn_raw2m(msgmap, rawno));
++ count = count_thread(state, stream, msgmap, rawno);
++ q_status_message2(SM_ORDER, 0, 1, "Deletion mark removed from %s message%s",
++ int2string(count), plural(count));
++ }
++
++ void
++ kolapse_thread(state, stream, msgmap, ch, display)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ char ch;
++ int display;
++ {
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno;
++ int rv = 1, done = 0;
++
++ if(!stream)
++ return;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return;
++
++ clear_index_cache();
++ mn_set_cur(msgmap,1); /* go to the first message */
++ while (!done){
++ if (ch == '[')
++ collapse_thread(state, stream, msgmap, display);
++ else
++ expand_thread(state, stream, msgmap, display);
++ if ((rv = move_next_thread(state, stream, msgmap, 0)) <= 0)
++ done++;
++ }
++
++ if (rv < 0){
++ if (display)
++ q_status_message(SM_ORDER, 0, 1, (ch == '[')
++ ? "Error while collapsing thread"
++ : "Error while expanding thread");
++ }
++ else
++ if(display)
++ q_status_message(SM_ORDER, 0, 1, (ch == '[')
++ ? "All threads collapsed. Use \"}\" to expand them"
++ : "All threads expanded. Use \"{\" to collapse them");
++
++ mn_set_cur(msgmap,mn_raw2m(msgmap, top_thread(stream,rawno)));
++ }
++
++ int
++ move_next_this_thread(state, stream, msgmap, display)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int display;
++ {
++ PINETHRD_S *thrd = NULL, *thrdnxt;
++ unsigned long rawno, top;
++ int rv = 1;
++
++ if(!stream)
++ return -1;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return -1;
++
++ top = top_thread(stream, rawno);
++
++ thrdnxt = (top == rawno) ? fetch_thread(stream, top) : thrd;
++ if (thrdnxt->nextthd)
++ mn_set_cur(msgmap,mn_raw2m(msgmap, thrdnxt->nextthd));
++ else{
++ rv = 0;
++ if (display)
++ q_status_message(SM_ORDER, 0, 1, "No more Threads to advance");
++ }
++ return rv;
++ }
++
++ int
++ move_next_thread(state, stream, msgmap, display)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int display;
++ {
++ int collapsed, rv = 1, done = 0;
++ PINETHRD_S *thrd = NULL;
++ unsigned long orig, orig_top, top;
++
++ if(!stream)
++ return 0;
++
++ orig = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_thread(stream, msgmap,orig);
++ top = orig_top = mn_m2raw(msgmap, mn_get_cur(msgmap));
++
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return 0;
++
++ while (rv > 0 && !done){
++ rv = move_next_this_thread(state, stream, msgmap, display);
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_top != top_thread(stream, top)))
++ done++;
++ }
++ if (display){
++ if (rv > 0 && SEP_THRDINDX())
++ q_status_message(SM_ORDER, 0, 2, "Viewing next thread");
++ if (!rv)
++ q_status_message(SM_ORDER, 0, 2, "No more threads to advance");
++ }
++ if(rv <= 0){
++ rv = 0;
++ mn_set_cur(msgmap, mn_raw2m(msgmap, orig));
++ }
++
++ return rv;
++ }
++
++ int
++ move_prev_thread(state, stream, msgmap, display)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int display;
++ {
++ PINETHRD_S *thrd = NULL;
++ unsigned long rawno, top;
++ int rv = 1;
++
++ if(!stream)
++ return -1;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return -1;
++
++ top = top_thread(stream, rawno);
++
++ if (top != rawno)
++ mn_set_cur(msgmap,mn_raw2m(msgmap, top));
++ else if (thrd->prevthd)
++ mn_set_cur(msgmap,mn_raw2m(msgmap, top_thread(stream,thrd->prevthd)));
++ else
++ rv = 0;
++ if (display){
++ if (rv && SEP_THRDINDX())
++ q_status_message(SM_ORDER, 0, 2, "Viewing previous thread");
++ if (!rv)
++ q_status_message(SM_ORDER, 0, 2, "No more threads to go back");
++ }
++
++ return rv;
++ }
++
++ void
++ cmd_select_thread(state, stream, msgmap)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ {
++ unsigned long rawno;
++ int save_kolapsed;
++
++ rawno = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ save_kolapsed = thread_is_kolapsed(state, stream, msgmap, rawno);
++ collapse_thread(state, stream, msgmap, 0);
++ thread_command(state, stream, msgmap, ':', -FOOTER_ROWS(state), 1);
++ if (!save_kolapsed)
++ expand_thread(state, stream, msgmap, 0);
++ }
++
++ /*
++ * This function assumes that it is called at a top of a thread in its
++ * first call
++ */
++
++ int
++ count_this_thread(stream, rawno)
++ MAILSTREAM *stream;
++ unsigned long rawno;
++ {
++ unsigned long top, orig_top, topnxt;
++ PINETHRD_S *thrd = NULL;
++ int count = 1;
++
++ if(!stream)
++ return 0;
++
++ if(rawno)
++ thrd = fetch_thread(stream, rawno);
++
++ if(!thrd)
++ return 0;
++
++ if (thrd->next)
++ count += count_this_thread(stream, thrd->next);
++
++ if (thrd->branch)
++ count += count_this_thread(stream, thrd->branch);
++
++ return count;
++ }
++
++ int
++ count_thread(state, stream, msgmap, rawno)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ long rawno;
++ {
++ unsigned long top, orig, orig_top;
++ PINETHRD_S *thrd = NULL;
++ int done = 0, count = 0;
++
++ if(!stream)
++ return 0;
++
++ orig = mn_m2raw(msgmap, mn_get_cur(msgmap));
++ move_top_thread(stream, msgmap,rawno);
++ top = orig_top = top_thread(stream, rawno);
++ if(top)
++ thrd = fetch_thread(stream, top);
++
++ if(!thrd)
++ return 0;
++
++ while (!done){
++ count += count_this_thread(stream, top);
++ if (F_OFF(F_ENHANCED_THREAD, state)
++ || (move_next_this_thread(state, stream, msgmap, 0) <= 0)
++ || !(top = mn_m2raw(msgmap, mn_get_cur(msgmap)))
++ || (orig_top != top_thread(stream, top)))
++ done++;
++ }
++ mn_set_cur(msgmap,mn_raw2m(msgmap, orig));
++ return count;
++ }
+diff -rc pine4.63/pine/mailindx.c pine4.63.I.USE/pine/mailindx.c
+*** pine4.63/pine/mailindx.c Wed Apr 27 11:55:00 2005
+--- pine4.63.I.USE/pine/mailindx.c Thu May 19 19:57:34 2005
+***************
+*** 112,120 ****
+ RCOMPOSE_MENU,
+ HOMEKEY_MENU,
+ ENDKEY_MENU,
+! NULL_MENU,
+ {"/","Collapse/Expand",{MC_COLLAPSE,1,{'/'}},KS_NONE},
+! NULL_MENU,
+ NULL_MENU};
+ INST_KEY_MENU(index_keymenu, index_keys);
+ #define BACK_KEY 2
+--- 112,133 ----
+ RCOMPOSE_MENU,
+ HOMEKEY_MENU,
+ ENDKEY_MENU,
+! {"K","Sort Thread",{MC_SORTHREAD,1,{'k'}},KS_NONE},
+ {"/","Collapse/Expand",{MC_COLLAPSE,1,{'/'}},KS_NONE},
+! {"{","Collapse All",{MC_KOLAPSE,1,{'{'}},KS_NONE},
+! {"}","Expand All", {MC_EXPTHREAD,1,{'}'}},KS_NONE},
+!
+! HELP_MENU,
+! OTHER_MENU,
+! {")","Next Threa",{MC_NEXTHREAD,1,{')'}},KS_NONE},
+! {"(","Prev Threa",{MC_PRETHREAD,1,{'('}},KS_NONE},
+! {"^D","Delete Thr",{MC_DELTHREAD,1,{ctrl('D')}},KS_NONE},
+! {"^U","Undel Thre",{MC_UNDTHREAD,1,{ctrl('U')}},KS_NONE},
+! {"^T","Select Thr",{MC_SELTHREAD,1,{ctrl('T')}},KS_NONE},
+! {"^H","ChkIncFl",{MC_FORCECHECK,1,{ctrl('H')}},KS_NONE},
+! {"[","Close Thre",{MC_CTHREAD,1,{'['}},KS_NONE},
+! {"]","Open Threa",{MC_OTHREAD,1,{']'}},KS_NONE},
+! QUOTA_MENU,
+ NULL_MENU};
+ INST_KEY_MENU(index_keymenu, index_keys);
+ #define BACK_KEY 2
+***************
+*** 197,205 ****
+ RCOMPOSE_MENU,
+ HOMEKEY_MENU,
+ ENDKEY_MENU,
+! NULL_MENU,
+ {"/","Collapse/Expand",{MC_COLLAPSE,1,{'/'}},KS_NONE},
+ NULL_MENU,
+ NULL_MENU};
+ INST_KEY_MENU(thread_keymenu, thread_keys);
+
+--- 210,231 ----
+ RCOMPOSE_MENU,
+ HOMEKEY_MENU,
+ ENDKEY_MENU,
+! {"]","Open Threa",{MC_OTHREAD,1,{']'}},KS_NONE},
+ {"/","Collapse/Expand",{MC_COLLAPSE,1,{'/'}},KS_NONE},
++ {")","Next Threa",{MC_NEXTHREAD,1,{')'}},KS_NONE},
++ {"(","Prev Threa",{MC_PRETHREAD,1,{'('}},KS_NONE},
++
++ HELP_MENU,
++ OTHER_MENU,
+ NULL_MENU,
++ NULL_MENU,
++ {"^D","Delete Thr",{MC_DELTHREAD,1,{ctrl('D')}},KS_NONE},
++ {"^U","Undel Thre",{MC_UNDTHREAD,1,{ctrl('U')}},KS_NONE},
++ {"^T","Select Thr",{MC_SELTHREAD,1,{ctrl('T')}},KS_NONE},
++ NULL_MENU,
++ {"^H","ChkIncFl",{MC_FORCECHECK,1,{ctrl('H')}},KS_NONE},
++ QUOTA_MENU,
++ {"K","Sort Thread",{MC_SORTHREAD,1,{'k'}},KS_NONE},
+ NULL_MENU};
+ INST_KEY_MENU(thread_keymenu, thread_keys);
+
+***************
+*** 315,326 ****
+
+ HLINE_S *(*format_index_line) PROTO((INDEXDATA_S *));
+ void (*setup_header_widths) PROTO((void));
+!
+
+
+ /*
+ * Internal prototypes
+ */
+ void index_index_screen PROTO((struct pine *));
+ void thread_index_screen PROTO((struct pine *));
+ void setup_for_index_index_screen PROTO((void));
+--- 341,357 ----
+
+ HLINE_S *(*format_index_line) PROTO((INDEXDATA_S *));
+ void (*setup_header_widths) PROTO((void));
+! static int erase_thread_info = 1;
+
+
+ /*
+ * Internal prototypes
+ */
++ SortOrder translate PROTO ((char *, int));
++ ENVELOPE *make_envelope PROTO ((INDEXDATA_S *, int));
++ char *find_value PROTO ((char *,char *, int, char *, int, char *, int, INDEXDATA_S *, int));
++ int find_index_rule PROTO((void));
++ void setup_threading_display_style PROTO((void));
+ void index_index_screen PROTO((struct pine *));
+ void thread_index_screen PROTO((struct pine *));
+ void setup_for_index_index_screen PROTO((void));
+***************
+*** 346,351 ****
+--- 377,390 ----
+ void index_data_env PROTO((INDEXDATA_S *, ENVELOPE *));
+ int set_index_addr PROTO((INDEXDATA_S *, char *, ADDRESS *,
+ char *, int, char *));
++ unsigned long get_next PROTO((MAILSTREAM *,PINETHRD_S *));
++ unsigned long get_branch PROTO((MAILSTREAM *,PINETHRD_S *));
++ long get_length_branch PROTO((MAILSTREAM *, long));
++ THREADNODE *copy_tree PROTO((THREADNODE *));
++ void find_msgmap PROTO((MAILSTREAM *, MSGNO_S *, int, SortOrder,
++ unsigned));
++ void move_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int));
++ void relink_threads PROTO((MAILSTREAM *, MSGNO_S *, long *));
+ int i_cache_size PROTO((long));
+ int i_cache_width PROTO(());
+ int ctype_is_fixed_length PROTO((IndexColType));
+***************
+*** 390,406 ****
+ struct pass_along
+ *sort_thread_flatten PROTO((THREADNODE *, MAILSTREAM *,
+ struct pass_along *,
+! PINETHRD_S *, unsigned));
+ void make_thrdflags_consistent PROTO((MAILSTREAM *, MSGNO_S *,
+ PINETHRD_S *, int));
+ THREADNODE *collapse_threadnode_tree PROTO((THREADNODE *));
+ PINETHRD_S *msgno_thread_info PROTO((MAILSTREAM *, unsigned long,
+ PINETHRD_S *, unsigned));
+ long calculate_visible_threads PROTO((MAILSTREAM *));
+ void set_thread_subtree PROTO((MAILSTREAM *, PINETHRD_S *,
+ MSGNO_S *, int, int));
+ void thread_command PROTO((struct pine *, MAILSTREAM *, MSGNO_S *,
+! int, int));
+ void set_flags_for_thread PROTO((MAILSTREAM *, MSGNO_S *, int,
+ PINETHRD_S *, int));
+ unsigned long count_flags_in_thread PROTO((MAILSTREAM *, PINETHRD_S *, long));
+--- 429,447 ----
+ struct pass_along
+ *sort_thread_flatten PROTO((THREADNODE *, MAILSTREAM *,
+ struct pass_along *,
+! PINETHRD_S *, unsigned, int,
+! long,long));
+ void make_thrdflags_consistent PROTO((MAILSTREAM *, MSGNO_S *,
+ PINETHRD_S *, int));
+ THREADNODE *collapse_threadnode_tree PROTO((THREADNODE *));
++ THREADNODE *copy_tree PROTO((THREADNODE *));
+ PINETHRD_S *msgno_thread_info PROTO((MAILSTREAM *, unsigned long,
+ PINETHRD_S *, unsigned));
+ long calculate_visible_threads PROTO((MAILSTREAM *));
+ void set_thread_subtree PROTO((MAILSTREAM *, PINETHRD_S *,
+ MSGNO_S *, int, int));
+ void thread_command PROTO((struct pine *, MAILSTREAM *, MSGNO_S *,
+! int, int, int));
+ void set_flags_for_thread PROTO((MAILSTREAM *, MSGNO_S *, int,
+ PINETHRD_S *, int));
+ unsigned long count_flags_in_thread PROTO((MAILSTREAM *, PINETHRD_S *, long));
+***************
+*** 592,600 ****
+--- 633,644 ----
+ return;
+ }
+
++ state->redrawer = redraw_index_body;
+ state->prev_screen = mail_index_screen;
+ state->next_screen = SCREEN_FUN_NULL;
+
++ setup_threading_display_style();
++
+ if(THRD_AUTO_VIEW() && sp_viewing_a_thread(state->mail_stream)
+ && state->view_skipped_index)
+ unview_thread(state, state->mail_stream, state->msgmap);
+***************
+*** 702,720 ****
+ MAILSTREAM *stream;
+ MSGNO_S *msgmap;
+ {
+! int ch, cmd, which_keys, force,
+ cur_row, cur_col, km_popped, paint_status;
+ int old_day = -1;
+! long i, j, k, old_max_msgno;
+ IndexType style, old_style = MsgIndex;
+ struct index_state id;
+ struct key_menu *km = NULL;
+ #if defined(DOS) || defined(OS2)
+ extern void (*while_waiting)();
+ #endif
+
+ dprint(1, (debugfile, "\n\n ---- INDEX MANAGER ----\n"));
+!
+ ch = 'x'; /* For displaying msg 1st time thru */
+ force = 0;
+ km_popped = 0;
+--- 746,770 ----
+ MAILSTREAM *stream;
+ MSGNO_S *msgmap;
+ {
+! int ch, cmd, which_keys, force, skip = 0,
+ cur_row, cur_col, km_popped, paint_status;
+ int old_day = -1;
+! long i, j, k, old_max_msgno, nm;
+ IndexType style, old_style = MsgIndex;
+ struct index_state id;
+ struct key_menu *km = NULL;
++ FOLDER_S *f;
+ #if defined(DOS) || defined(OS2)
+ extern void (*while_waiting)();
+ #endif
+
+ dprint(1, (debugfile, "\n\n ---- INDEX MANAGER ----\n"));
+! if (f = incoming_folder_data(stream, cntxt)){
+! f->selected = f->user_selected; /* unselect this folder now */
+! f->origrecent = stream->recent; /* more accurate than f->recent */
+! f->notified = 1; /* no updates in this screen */
+! f->countrecent = 0;
+! }
+ ch = 'x'; /* For displaying msg 1st time thru */
+ force = 0;
+ km_popped = 0;
+***************
+*** 749,757 ****
+ }
+
+ /*------- Check for new mail -------*/
+! new_mail(force, NM_TIMING(ch), NM_STATUS_MSG);
+! force = 0; /* may not need to next time around */
+!
+ /*
+ * If the width of the message number field in the display changes
+ * we need to flush the cache and redraw. When the cache is cleared
+--- 799,822 ----
+ }
+
+ /*------- Check for new mail -------*/
+! nm = new_mail(force, NM_TIMING(ch), NM_STATUS_MSG);
+! if (!skip || nm > 0L){
+! if(nm > 0L)
+! state->force_check_now = 1;
+! if(f)
+! f->notified = 1;
+! new_mail_incfolder(state, MC_IFAUTOCHECK);
+! }
+! if (f){
+! long rec, tot;
+! new_mail_in_open_stream(stream, &rec, &tot);
+! f->countrecent = rec > f->recent ? rec - f->countrecent : 0;
+! f->selected = f->user_selected;
+! f->recent = rec;
+! f->messages = tot;
+! }
+! ps_global->refresh_list = 0; /* reset refresh_list */
+! force = skip = 0; /* may not need to next time around */
+ /*
+ * If the width of the message number field in the display changes
+ * we need to flush the cache and redraw. When the cache is cleared
+***************
+*** 943,948 ****
+--- 1008,1016 ----
+ break;
+ }
+
++ if ((cmd != MC_NONE) && (cmd != MC_FORCECHECK))
++ state->force_check_now = 0;
++
+ /*----------- Execute the command ------------------*/
+ switch(cmd){
+
+***************
+*** 958,963 ****
+--- 1026,1032 ----
+
+ /*---------- Scroll line up ----------*/
+ case MC_CHARUP :
++ previtem:
+ (void) process_cmd(state, stream, msgmap, MC_PREVITEM,
+ (style == MsgIndex
+ || style == MultiMsgIndex
+***************
+*** 975,980 ****
+--- 1044,1050 ----
+
+ /*---------- Scroll line down ----------*/
+ case MC_CHARDOWN :
++ nextitem:
+ /*
+ * Special Page framing handling here. If we
+ * did something that should scroll-by-a-line, frame
+***************
+*** 1192,1197 ****
+--- 1262,1268 ----
+
+
+ case MC_THRDINDX :
++ mc_thrdindx:
+ msgmap->top = msgmap->top_after_thrd;
+ if(unview_thread(state, stream, msgmap)){
+ ps_global->redrawer = NULL;
+***************
+*** 1239,1245 ****
+ && mp.col == id.plus_col
+ && style != ThreadIndex){
+ collapse_or_expand(state, stream, msgmap,
+! mn_get_cur(msgmap));
+ }
+ else if (mp.doubleclick){
+ if(mp.button == M_BUTTON_LEFT){
+--- 1310,1316 ----
+ && mp.col == id.plus_col
+ && style != ThreadIndex){
+ collapse_or_expand(state, stream, msgmap,
+! mn_get_cur(msgmap), 1);
+ }
+ else if (mp.doubleclick){
+ if(mp.button == M_BUTTON_LEFT){
+***************
+*** 1309,1314 ****
+--- 1380,1387 ----
+ reset_index_border();
+ break;
+
++ case MC_QUOTA:
++ cmd_quota(state);
+
+ /*---------- Redraw ----------*/
+ case MC_REPAINT :
+***************
+*** 1333,1341 ****
+
+
+ case MC_COLLAPSE :
+! thread_command(state, stream, msgmap, ch, -FOOTER_ROWS(state));
+ break;
+
+ case MC_DELETE :
+ case MC_UNDELETE :
+ case MC_REPLY :
+--- 1406,1511 ----
+
+
+ case MC_COLLAPSE :
+! thread_command(state, stream, msgmap, ch, -FOOTER_ROWS(state), 1);
+ break;
+
++ case MC_CTHREAD :
++ if (SEP_THRDINDX())
++ goto mc_thrdindx;
++ else
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL,
++ "to collapse a thread"))
++ collapse_thread(state, stream,msgmap, 1);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_OTHREAD :
++ if (SEP_THRDINDX())
++ goto view_a_thread;
++ else
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to expand a thread"))
++ expand_thread(state, stream,msgmap, 1);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_NEXTHREAD:
++ case MC_PRETHREAD:
++ if (THRD_INDX()){
++ if (cmd == MC_NEXTHREAD)
++ goto nextitem;
++ else
++ goto previtem;
++ }
++ else
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL,
++ "to move to other thread"))
++ move_thread(state, stream, msgmap,
++ cmd == MC_NEXTHREAD ? 1 : -1);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_KOLAPSE:
++ case MC_EXPTHREAD:
++ if (SEP_THRDINDX()){
++ q_status_message(SM_ORDER, 0, 1,
++ "Command not available in this screen");
++ }
++ else{
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL,
++ cmd == MC_KOLAPSE ? "to collapse" : "to expand"))
++ kolapse_thread(state, stream, msgmap,
++ (cmd == MC_KOLAPSE) ? '[' : ']', 1);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ }
++ break;
++
++ case MC_DELTHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to delete"))
++ cmd_delete_thread(state, stream, msgmap);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_UNDTHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to undelete"))
++ cmd_undelete_thread(state, stream, msgmap);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++
++ case MC_SELTHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to undelete"))
++ cmd_select_thread(state, stream, msgmap);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
+ case MC_DELETE :
+ case MC_UNDELETE :
+ case MC_REPLY :
+***************
+*** 1356,1368 ****
+ if(rawno)
+ thrd = fetch_thread(stream, rawno);
+
+! collapsed = thrd && thrd->next
+! && get_lflag(stream, NULL, rawno, MN_COLL);
+ }
+
+ if(collapsed){
+ thread_command(state, stream, msgmap,
+! ch, -FOOTER_ROWS(state));
+ /* increment current */
+ if(cmd == MC_DELETE){
+ advance_cur_after_delete(state, stream, msgmap,
+--- 1526,1537 ----
+ if(rawno)
+ thrd = fetch_thread(stream, rawno);
+
+! collapsed = thread_is_kolapsed(ps_global, stream, msgmap, rawno);
+ }
+
+ if(collapsed){
+ thread_command(state, stream, msgmap,
+! ch, -FOOTER_ROWS(state),1);
+ /* increment current */
+ if(cmd == MC_DELETE){
+ advance_cur_after_delete(state, stream, msgmap,
+***************
+*** 1401,1407 ****
+ }
+ /* else fall thru to normal default */
+
+!
+ /*---------- Default -- all other command ----------*/
+ default:
+ do_the_default:
+--- 1570,1579 ----
+ }
+ /* else fall thru to normal default */
+
+! case MC_TAB:
+! skip++;
+! /* do not check for new mail in inc fldrs and fall through */
+!
+ /*---------- Default -- all other command ----------*/
+ default:
+ do_the_default:
+***************
+*** 2772,2777 ****
+--- 2944,2950 ----
+ n = mn_raw2m(msgs, thrd->rawno);
+
+ while(thrd){
++ unsigned long branch;
+ if(!msgline_hidden(stream, msgs, n, 0)
+ && (++m % lines_per_page) == 1L)
+ t = n;
+***************
+*** 2840,2850 ****
+
+ /* n is the end of this thread */
+ while(thrd){
+ n = mn_raw2m(msgs, thrd->rawno);
+! if(thrd->branch)
+! thrd = fetch_thread(stream, thrd->branch);
+! else if(thrd->next)
+! thrd = fetch_thread(stream, thrd->next);
+ else
+ thrd = NULL;
+ }
+--- 3013,3024 ----
+
+ /* n is the end of this thread */
+ while(thrd){
++ unsigned long next = 0L, branch = 0L;
+ n = mn_raw2m(msgs, thrd->rawno);
+! if(branch = get_branch(stream,thrd))
+! thrd = fetch_thread(stream, branch);
+! else if(next = get_next(stream,thrd))
+! thrd = fetch_thread(stream, next);
+ else
+ thrd = NULL;
+ }
+***************
+*** 2998,3003 ****
+--- 3172,3178 ----
+ case iSTime:
+ case iKSize:
+ case iSize:
++ case iSizeThread:
+ (*answer)[column].req_width = 7;
+ break;
+ case iS1Date:
+***************
+*** 3034,3047 ****
+ static INDEX_PARSE_T itokens[] = {
+ {"STATUS", iStatus, FOR_INDEX},
+ {"MSGNO", iMessNo, FOR_INDEX},
+! {"DATE", iDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"FROMORTO", iFromTo, FOR_INDEX},
+ {"FROMORTONOTNEWS", iFromToNotNews, FOR_INDEX},
+ {"SIZE", iSize, FOR_INDEX},
+ {"SIZECOMMA", iSizeComma, FOR_INDEX},
+ {"SIZENARROW", iSizeNarrow, FOR_INDEX},
+ {"KSIZE", iKSize, FOR_INDEX},
+! {"SUBJECT", iSubject, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"FULLSTATUS", iFStatus, FOR_INDEX},
+ {"IMAPSTATUS", iIStatus, FOR_INDEX},
+ {"SUBJKEY", iSubjKey, FOR_INDEX},
+--- 3209,3223 ----
+ static INDEX_PARSE_T itokens[] = {
+ {"STATUS", iStatus, FOR_INDEX},
+ {"MSGNO", iMessNo, FOR_INDEX},
+! {"DATE", iDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+ {"FROMORTO", iFromTo, FOR_INDEX},
+ {"FROMORTONOTNEWS", iFromToNotNews, FOR_INDEX},
+ {"SIZE", iSize, FOR_INDEX},
+ {"SIZECOMMA", iSizeComma, FOR_INDEX},
++ {"SIZETHREAD", iSizeThread, FOR_INDEX},
+ {"SIZENARROW", iSizeNarrow, FOR_INDEX},
+ {"KSIZE", iKSize, FOR_INDEX},
+! {"SUBJECT", iSubject, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_TRIM},
+ {"FULLSTATUS", iFStatus, FOR_INDEX},
+ {"IMAPSTATUS", iIStatus, FOR_INDEX},
+ {"SUBJKEY", iSubjKey, FOR_INDEX},
+***************
+*** 3051,3076 ****
+ {"DESCRIPSIZE", iDescripSize, FOR_INDEX},
+ {"ATT", iAtt, FOR_INDEX},
+ {"SCORE", iScore, FOR_INDEX},
+! {"LONGDATE", iLDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SHORTDATE1", iS1Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SHORTDATE2", iS2Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SHORTDATE3", iS3Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SHORTDATE4", iS4Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DATEISO", iDateIso, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SHORTDATEISO", iDateIsoS, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATE", iSDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTTIME", iSTime, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SMARTDATETIME", iSDateTime, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"TIME24", iTime24, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"TIME12", iTime12, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"TIMEZONE", iTimezone, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"MONTHABBREV", iMonAbb, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAYOFWEEKABBREV", iDayOfWeekAbb, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAYOFWEEK", iDayOfWeek, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"FROM", iFrom, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"TO", iTo, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"SENDER", iSender, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"CC", iCc, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"RECIPS", iRecips, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"NEWS", iNews, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"TOANDNEWS", iToAndNews, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+--- 3227,3255 ----
+ {"DESCRIPSIZE", iDescripSize, FOR_INDEX},
+ {"ATT", iAtt, FOR_INDEX},
+ {"SCORE", iScore, FOR_INDEX},
+! {"LONGDATE", iLDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SHORTDATE1", iS1Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SHORTDATE2", iS2Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SHORTDATE3", iS3Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SHORTDATE4", iS4Date, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"DATEISO", iDateIso, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SHORTDATEISO", iDateIsoS, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATE", iSDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTTIME", iSTime, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"SMARTDATETIME", iSDateTime, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"TIME24", iTime24, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"TIME12", iTime12, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"TIMEZONE", iTimezone, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"MONTHABBREV", iMonAbb, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"DAYOFWEEKABBREV", iDayOfWeekAbb, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"DAYOFWEEK", iDayOfWeek, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"FROM", iFrom, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_SAVE|FOR_RULE|FOR_COMPOSE},
+! {"TO", iTo, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_SAVE|FOR_RULE|FOR_COMPOSE},
+! {"SENDER", iSender, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_SAVE|FOR_RULE},
+! {"CC", iCc, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_SAVE|FOR_RULE},
+! {"ADDRESSTO", iAddressTo, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_SAVE|FOR_RULE},
+! {"ADDRESSCC", iAddressCc, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_SAVE|FOR_RULE},
+! {"ADDRESSRECIPS", iAddressRecip, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_SAVE|FOR_RULE},
+ {"RECIPS", iRecips, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"NEWS", iNews, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"TOANDNEWS", iToAndNews, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+***************
+*** 3079,3124 ****
+ {"NEWSANDRECIPS", iNewsAndRecips, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"MSGID", iMsgID, FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"CURNEWS", iCurNews, FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAYDATE", iRDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAY", iDay, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAYORDINAL", iDayOrdinal, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAY2DIGIT", iDay2Digit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"MONTHLONG", iMonLong, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"MONTH", iMon, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"MONTH2DIGIT", iMon2Digit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"YEAR", iYear, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"YEAR2DIGIT", iYear2Digit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"ADDRESS", iAddress, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"MAILBOX", iMailbox, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"ROLENICK", iRoleNick, FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"INIT", iInit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"CURDATE", iCurDate, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURDATEISO", iCurDateIso, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURDATEISOS", iCurDateIsoS, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURTIME24", iCurTime24, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURTIME12", iCurTime12, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURDAY", iCurDay, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURDAY2DIGIT", iCurDay2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURDAYOFWEEK", iCurDayOfWeek, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+ {"CURDAYOFWEEKABBREV", iCurDayOfWeekAbb,
+! FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURMONTH", iCurMon, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURMONTH2DIGIT", iCurMon2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURMONTHLONG", iCurMonLong, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURMONTHABBREV", iCurMonAbb, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURYEAR", iCurYear, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"CURYEAR2DIGIT", iCurYear2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTMONTH", iLstMon, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTMONTH2DIGIT", iLstMon2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTMONTHLONG", iLstMonLong, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTMONTHABBREV", iLstMonAbb, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTMONTHYEAR", iLstMonYear, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+ {"LASTMONTHYEAR2DIGIT", iLstMonYear2Digit,
+! FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTYEAR", iLstYear, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+! {"LASTYEAR2DIGIT", iLstYear2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_FILT},
+ {"ARROW", iArrow, FOR_INDEX},
+ {"CURSORPOS", iCursorPos, FOR_TEMPLATE},
+ {NULL, iNothing, FOR_NOTHING}
+ };
+
+--- 3258,3312 ----
+ {"NEWSANDRECIPS", iNewsAndRecips, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"MSGID", iMsgID, FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"CURNEWS", iCurNews, FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"DAYDATE", iRDate, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"DAY", iDay, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"DAYORDINAL", iDayOrdinal, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"DAY2DIGIT", iDay2Digit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"MONTHLONG", iMonLong, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"MONTH", iMon, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"MONTH2DIGIT", iMon2Digit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"YEAR", iYear, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"YEAR2DIGIT", iYear2Digit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE},
+! {"ADDRESS", iAddress, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE},
+ {"MAILBOX", iMailbox, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"ROLENICK", iRoleNick, FOR_REPLY_INTRO|FOR_TEMPLATE},
+ {"INIT", iInit, FOR_INDEX|FOR_REPLY_INTRO|FOR_TEMPLATE},
+! {"CURDATE", iCurDate, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURDATEISO", iCurDateIso, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURDATEISOS", iCurDateIsoS, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURTIME24", iCurTime24, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURTIME12", iCurTime12, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURDAY", iCurDay, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURDAY2DIGIT", iCurDay2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURDAYOFWEEK", iCurDayOfWeek, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+ {"CURDAYOFWEEKABBREV", iCurDayOfWeekAbb,
+! FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURMONTH", iCurMon, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURMONTH2DIGIT", iCurMon2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURMONTHLONG", iCurMonLong, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURMONTHABBREV", iCurMonAbb, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURYEAR", iCurYear, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"CURYEAR2DIGIT", iCurYear2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"LASTMONTH", iLstMon, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"LASTMONTH2DIGIT", iLstMon2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"LASTMONTHLONG", iLstMonLong, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"LASTMONTHABBREV", iLstMonAbb, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"LASTMONTHYEAR", iLstMonYear, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+ {"LASTMONTHYEAR2DIGIT", iLstMonYear2Digit,
+! FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"LASTYEAR", iLstYear, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+! {"LASTYEAR2DIGIT", iLstYear2Digit, FOR_REPLY_INTRO|FOR_TEMPLATE|FOR_RULE|FOR_SAVE|FOR_FILT},
+ {"ARROW", iArrow, FOR_INDEX},
+ {"CURSORPOS", iCursorPos, FOR_TEMPLATE},
++ {"NICK", iNick, FOR_RULE|FOR_SAVE},
++ {"FOLDER", iFolder, FOR_RULE|FOR_SAVE|FOR_FOLDER},
++ {"ROLE", iRole, FOR_RULE|FOR_RESUB|FOR_TRIM|FOR_TEMPLATE},
++ {"FLAG", iFlag, FOR_RULE|FOR_SAVE|FOR_FLAG},
++ {"COLLECTION", iCollection, FOR_RULE|FOR_SAVE|FOR_COMPOSE|FOR_FOLDER},
++ {"BCC", iBcc, FOR_COMPOSE|FOR_RULE},
++ {"LCC", iLcc, FOR_COMPOSE|FOR_RULE},
++ {"FORWARDFROM", iFfrom, FOR_COMPOSE|FOR_RULE},
++ {"FORWARDADDRESS", iFadd, FOR_COMPOSE|FOR_RULE},
+ {NULL, iNothing, FOR_NOTHING}
+ };
+
+***************
+*** 3286,3292 ****
+ */
+ static IndexColType fixed_ctypes[] = {
+ iArrow, iMessNo, iStatus, iFStatus, iIStatus, iDate, iSDate, iSDateTime,
+! iSTime, iLDate,
+ iS1Date, iS2Date, iS3Date, iS4Date, iDateIso, iDateIsoS,
+ iSize, iSizeComma, iSizeNarrow, iKSize, iDescripSize,
+ iAtt, iTime24, iTime12, iTimezone, iMonAbb, iYear, iYear2Digit,
+--- 3474,3480 ----
+ */
+ static IndexColType fixed_ctypes[] = {
+ iArrow, iMessNo, iStatus, iFStatus, iIStatus, iDate, iSDate, iSDateTime,
+! iSTime, iLDate, iSizeThread,
+ iS1Date, iS2Date, iS3Date, iS4Date, iDateIso, iDateIsoS,
+ iSize, iSizeComma, iSizeNarrow, iKSize, iDescripSize,
+ iAtt, iTime24, iTime12, iTimezone, iMonAbb, iYear, iYear2Digit,
+***************
+*** 3457,3462 ****
+--- 3645,3651 ----
+ case iTime12:
+ case iSize:
+ case iKSize:
++ case iSizeThread:
+ cdesc->actual_length = 7;
+ cdesc->adjustment = Right;
+ break;
+***************
+*** 3521,3527 ****
+ cdesc->ctype != iNothing;
+ cdesc++)
+ if(cdesc->ctype == iSize || cdesc->ctype == iKSize ||
+! cdesc->ctype == iSizeNarrow ||
+ cdesc->ctype == iSizeComma || cdesc->ctype == iDescripSize){
+ if(cdesc->actual_length == 0){
+ if((fix=cdesc->width) > 0){ /* had this reserved */
+--- 3710,3716 ----
+ cdesc->ctype != iNothing;
+ cdesc++)
+ if(cdesc->ctype == iSize || cdesc->ctype == iKSize ||
+! cdesc->ctype == iSizeNarrow || cdesc->ctype == iSizeThread ||
+ cdesc->ctype == iSizeComma || cdesc->ctype == iDescripSize){
+ if(cdesc->actual_length == 0){
+ if((fix=cdesc->width) > 0){ /* had this reserved */
+***************
+*** 3813,3818 ****
+--- 4002,4081 ----
+ }
+ }
+
++ ENVELOPE *make_envelope(idata, index)
++ INDEXDATA_S *idata;
++ int index;
++ {
++ ENVELOPE *result;
++
++ result = mail_newenvelope();
++
++ result->from = rfc822_cpy_adr(idata->from);
++ result->to = rfc822_cpy_adr(idata->to);
++ result->cc = rfc822_cpy_adr(idata->cc);
++ result->sender = rfc822_cpy_adr(idata->sender);
++ result->subject = cpystr(idata->subject);
++ result->newsgroups = index ? cpystr(idata->newsgroups) :
++ IS_NEWS(idata->stream) ? cpystr(ps_global->cur_folder)
++ : NULL;
++ return result;
++ }
++
++ /*---------------------------------
++
++ -----------*/
++
++ char *find_value(token,function1, context1, function2, context2, function3, context3, idata, code)
++ char *token;
++ char *function1;
++ int context1;
++ char *function2;
++ int context2;
++ char *function3;
++ int context3;
++ INDEXDATA_S *idata;
++ int code;
++ { int n = 0, done = 0, next_step = 0;
++ char *rule_result;
++ int rule_context;
++ RULELIST *rule = get_rulelist_from_code(code, ps_global->rule_list);
++ RULE_S *prule;
++
++ if (rule){
++ rule_context = FOR_RULE;
++ while (!done && (prule = get_rule(rule,n++))){
++ if (context1 && prule->action->token &&
++ !strcmp(prule->action->token, token)
++ && !strcmp(prule->action->function, function1)){
++ rule_context |= context1;
++ next_step++;
++ }
++ if (context2 && prule->action->token &&
++ !strcmp(prule->action->token, token)
++ && !strcmp(prule->action->function, function2)){
++ rule_context |= context2;
++ next_step++;
++ }
++ if (context3 && prule->action->token &&
++ !strcmp(prule->action->token, token)
++ && !strcmp(prule->action->function, function3)){
++ rule_context |= context3;
++ next_step++;
++ }
++ if (next_step){
++ ENVELOPE *local_env = make_envelope(idata,1);
++ next_step = FALSE;
++ rule_result = process_rule(prule, rule_context, local_env);
++ if (local_env)
++ mail_free_envelope(&local_env);
++ if (rule_result)
++ done++;
++ }
++ }
++ }
++ return done ? rule_result : NULL;
++ }
++
+
+ /*----------------------------------------------------------------------
+ Create a string summarizing the message header for index on screen
+***************
+*** 3945,3954 ****
+
+ /* find next thread which is visible */
+ do{
+ if(mn_get_revsort(msgmap) && thrd->prevthd)
+ thrd = fetch_thread(stream, thrd->prevthd);
+! else if(!mn_get_revsort(msgmap) && thrd->nextthd)
+! thrd = fetch_thread(stream, thrd->nextthd);
+ else
+ thrd = NULL;
+ } while(thrd
+--- 4208,4218 ----
+
+ /* find next thread which is visible */
+ do{
++ unsigned long branch;
+ if(mn_get_revsort(msgmap) && thrd->prevthd)
+ thrd = fetch_thread(stream, thrd->prevthd);
+! else if(!mn_get_revsort(msgmap) && thrd->branch)
+! thrd = fetch_thread(stream, thrd->branch);
+ else
+ thrd = NULL;
+ } while(thrd
+***************
+*** 4404,4414 ****
+ }
+
+ /* is this a collapsed thread index line? */
+ if(!idata->bogus && THREADING()){
+! thrd = fetch_thread(idata->stream, idata->rawno);
+! collapsed = thrd && thrd->next
+! && get_lflag(idata->stream, NULL,
+! idata->rawno, MN_COLL);
+ }
+
+ /* calculate contents of the required fields */
+--- 4668,4676 ----
+ }
+
+ /* is this a collapsed thread index line? */
++ thrd = fetch_thread(idata->stream, idata->rawno);
+ if(!idata->bogus && THREADING()){
+! collapsed = thrd && thread_is_kolapsed(ps_global, idata->stream, ps_global->msgmap, idata->rawno);
+ }
+
+ /* calculate contents of the required fields */
+***************
+*** 4940,4946 ****
+--- 5202,5232 ----
+
+ break;
+
++ case iSizeThread:
++ if (!THREADING()){
++ goto getsize;
++ } else if (collapsed){
++ l = count_flags_in_thread(idata->stream, thrd, F_NONE);
++ sprintf(str, "(%lu)", l);
++ }
++ else{
++ thrd = fetch_thread(idata->stream, idata->rawno);
++ if(!thrd)
++ sprintf(str,"Error");
++ else{
++ long lengthb;
++ lengthb = get_length_branch(idata->stream, idata->rawno);
++
++ if (lengthb > 0L)
++ sprintf(str,"(%lu)", lengthb);
++ else
++ sprintf(str," ");
++ }
++ }
++ break;
++
+ case iSize:
++ getsize:
+ /* 0 ... 9999 */
+ if((l = fetch_size(idata)) < 10*1000L)
+ sprintf(str, "(%lu)", l);
+***************
+*** 7031,7041 ****
+ unsigned long rawno;
+ unsigned char buf[MAILTMPLEN];
+ OFFCOLOR_S myoffs[OFFS];
+! int mynoff = 0;
+
+ memset(str, 0, (width+1) * sizeof(*str));
+ origstr = str;
+! origsubj = fetch_subject(idata);
+ if(!origsubj)
+ origsubj = "";
+
+--- 7317,7335 ----
+ unsigned long rawno;
+ unsigned char buf[MAILTMPLEN];
+ OFFCOLOR_S myoffs[OFFS];
+! int mynoff = 0, we_clear = 0;
+! char *rule_result;
+
+ memset(str, 0, (width+1) * sizeof(*str));
+ origstr = str;
+! rule_result = find_value("_SUBJECT_", "_REPLACE_", FOR_REPLACE, "_TRIM_", FOR_TRIM, "_REXTRIM_", FOR_TRIM, idata, V_REPLACE_RULES);
+! if (rule_result){
+! we_clear++;
+! origsubj = cpystr(rule_result);
+! fs_give((void **)&rule_result);
+! }
+! else
+! origsubj = fetch_subject(idata);
+ if(!origsubj)
+ origsubj = "";
+
+***************
+*** 7060,7067 ****
+ thdorig = thd = fetch_thread(idata->stream, idata->rawno);
+ border = str + width;
+ if(current_index_state->plus_col >= 0 && !THRD_INDX()){
+! collapsed = thd && thd->next &&
+! get_lflag(idata->stream, NULL, idata->rawno, MN_COLL);
+ hline = get_index_cache(idata->msgno);
+ hline->plus = collapsed ? ps_global->VAR_THREAD_MORE_CHAR[0]
+ : (thd && thd->next)
+--- 7354,7361 ----
+ thdorig = thd = fetch_thread(idata->stream, idata->rawno);
+ border = str + width;
+ if(current_index_state->plus_col >= 0 && !THRD_INDX()){
+! collapsed = this_thread_is_kolapsed(ps_global, idata->stream, ps_global->msgmap, idata->rawno);
+! collapsed = collapsed && (count_thread(ps_global,idata->stream, ps_global->msgmap, idata->rawno) != 1);
+ hline = get_index_cache(idata->msgno);
+ hline->plus = collapsed ? ps_global->VAR_THREAD_MORE_CHAR[0]
+ : (thd && thd->next)
+***************
+*** 7316,7321 ****
+--- 7610,7617 ----
+
+ if(free_subj)
+ fs_give((void **) &free_subj);
++ if (we_clear && origsubj)
++ fs_give((void **)&origsubj);
+
+ /* adjust offsets for indents and subject truncation */
+ if(offs && noff && *noff < OFFS && mynoff && pico_usingcolor()){
+***************
+*** 7543,7550 ****
+ thdorig = thd = fetch_thread(idata->stream, idata->rawno);
+ border = str + width;
+ if(current_index_state->plus_col >= 0 && !THRD_INDX()){
+! collapsed = thd && thd->next &&
+! get_lflag(idata->stream, NULL, idata->rawno, MN_COLL);
+ hline = get_index_cache(idata->msgno);
+ hline->plus = collapsed ? ps_global->VAR_THREAD_MORE_CHAR[0]
+ : (thd && thd->next)
+--- 7839,7846 ----
+ thdorig = thd = fetch_thread(idata->stream, idata->rawno);
+ border = str + width;
+ if(current_index_state->plus_col >= 0 && !THRD_INDX()){
+! collapsed = this_thread_is_kolapsed(ps_global, idata->stream, ps_global->msgmap, idata->rawno);
+! collapsed = collapsed && (count_thread (ps_global,idata->stream, ps_global->msgmap, idata->rawno) != 1);
+ hline = get_index_cache(idata->msgno);
+ hline->plus = collapsed ? ps_global->VAR_THREAD_MORE_CHAR[0]
+ : (thd && thd->next)
+***************
+*** 7635,7650 ****
+ ? "To"
+ : (addr = fetch_cc(idata))
+ ? "Cc"
+! : NULL))
+! && set_index_addr(idata, field, addr, "To: ",
+! width, fptr))
+! break;
+!
+ if(ctype == iFromTo &&
+ (newsgroups = fetch_newsgroups(idata)) &&
+ *newsgroups){
+! sprintf(fptr, "To: %-*.*s", width-4, width-4,
+! newsgroups);
+ break;
+ }
+
+--- 7931,7960 ----
+ ? "To"
+ : (addr = fetch_cc(idata))
+ ? "Cc"
+! : NULL))){
+! char *rule_result;
+! rule_result = find_value("_FROM_","_REPLACE_",FOR_REPLACE, NULL,0,NULL,0, idata,V_REPLACE_RULES);
+! if (!rule_result)
+! set_index_addr(idata, field, addr, "To: ",
+! width, str);
+! else{
+! sprintf(str, "%-*.*s", width, width, rule_result);
+! fs_give((void **)&rule_result);
+! }
+! break;
+! }
+ if(ctype == iFromTo &&
+ (newsgroups = fetch_newsgroups(idata)) &&
+ *newsgroups){
+! char *rule_result;
+! rule_result = find_value("_FROM_","_REPLACE_",FOR_REPLACE, NULL,0,NULL, 0, idata, V_REPLACE_RULES);
+! if (!rule_result)
+! sprintf(str, "To: %-*.*s", width-4, width-4,
+! newsgroups);
+! else{
+! sprintf(str, "%-*.*s", width, width, rule_result);
+! fs_give((void **)&rule_result);
+! }
+ break;
+ }
+
+***************
+*** 7657,7664 ****
+ break;
+
+ case iFrom:
+! set_index_addr(idata, "From", fetch_from(idata),
+! NULL, width, fptr);
+ break;
+
+ case iAddress:
+--- 7967,7983 ----
+ break;
+
+ case iFrom:
+! { char *rule_result;
+! rule_result = find_value("_FROM_","_REPLACE_", FOR_REPLACE, "_TRIM_", FOR_TRIM, "_REXTRIM_", FOR_TRIM, idata, V_REPLACE_RULES);
+! if (!rule_result)
+! set_index_addr(idata, "From", fetch_from(idata),
+! NULL, width, str);
+! else{
+! sprintf(str, "%-*.*s", width, width, rule_result);
+! fs_give((void **)&rule_result);
+! }
+! }
+!
+ break;
+
+ case iAddress:
+***************
+*** 7741,7746 ****
+--- 8060,8083 ----
+ return(1);
+ }
+
++ void
++ insert_pattern_in_string(buf, last, maxbuf)
++ char *buf;
++ char *last;
++ int maxbuf;
++ {
++ if (last[0] != '\0'){
++ int lenlast, lenbuf;
++ lenlast = strlen(last);
++ lenbuf = buf[0] == '\0' ? 0 : strlen(buf);
++ if (lenlast + lenbuf <= maxbuf){
++ if (buf[0] == '\0')
++ strcpy(buf, last);
++ else
++ strcat(buf, last);
++ }
++ }
++ }
+
+
+ /*----------------------------------------------------------------------
+***************
+*** 7765,7773 ****
+--- 8102,8112 ----
+ long i, sorted_msg, selected = 0L;
+ char prompt[MAX_SEARCH+50], new_string[MAX_SEARCH+1];
+ HelpType help;
++ static char last_search_pat[MAX_SEARCH+1] = {'\0'};
+ static char search_string[MAX_SEARCH+1] = { '\0' };
+ HLINE_S *hl;
+ static ESCKEY_S header_search_key[] = { {0, 0, NULL, NULL },
++ {ctrl('N'), 9, "^N","Ins Pat"},
+ {ctrl('Y'), 10, "^Y", "First Msg"},
+ {ctrl('V'), 11, "^V", "Last Msg"},
+ {-1, 0, NULL, NULL} };
+***************
+*** 7814,7819 ****
+--- 8153,8160 ----
+ : h_os_index_whereis;
+ continue;
+ }
++ else if(rc == 9)
++ insert_pattern_in_string(new_string, last_search_pat, MAX_SEARCH);
+ else if(rc == 10){
+ q_status_message(SM_ORDER, 0, 3, "Searched to First Message.");
+ if(any_lflagged(msgmap, MN_HIDE | MN_CHID)){
+***************
+*** 7851,7857 ****
+ break;
+ }
+
+! if(rc != 4) /* redraw */
+ break; /* redraw */
+ }
+
+--- 8192,8198 ----
+ break;
+ }
+
+! if(rc != 4 && rc != 9) /* redraw */
+ break; /* redraw */
+ }
+
+***************
+*** 7868,7873 ****
+--- 8209,8217 ----
+ strncpy(search_string, new_string, sizeof(search_string));
+ search_string[sizeof(search_string)-1] = '\0';
+
++ strncpy(last_search_pat, new_string, sizeof(last_search_pat));
++ last_search_pat[sizeof(last_search_pat)-1] = '\0';
++
+ #ifndef DOS
+ intr_handling_on();
+ #endif
+***************
+*** 8054,8059 ****
+--- 8398,8440 ----
+ : ((mdiff = *mess_a - *mess_b) ? ((mdiff > 0) ? 1 : -1) : 0));
+ }
+
++ SortOrder translate(order, is_rev)
++ char *order;
++ int is_rev;
++ {
++ int rev = 0;
++ if (!strncmp(order,"tHread", 6)
++ || (rev = !strncmp(order,"Reverse tHread", 14)))
++ return is_rev || rev ? SortThread : EndofList;
++ if (!strncmp(order,"OrderedSubj", 11)
++ || (rev = !strncmp(order,"Reverse OrderedSubj", 19)))
++ return is_rev || rev ? SortSubject2 : EndofList;
++ if (!strncmp(order,"Subject", 7)
++ || (rev = !strncmp(order,"Reverse SortSubject", 15)))
++ return is_rev || rev ? SortSubject : EndofList;
++ if (!strncmp(order,"Arrival", 7)
++ || (rev = !strncmp(order,"Reverse Arrival", 15)))
++ return is_rev || rev ? SortArrival : EndofList;
++ if (!strncmp(order,"From", 4)
++ || (rev = !strncmp(order,"Reverse From", 12)))
++ return is_rev || rev ? SortFrom : EndofList;
++ if (!strncmp(order,"To", 2)
++ || (rev = !strncmp(order,"Reverse To", 10)))
++ return is_rev || rev ? SortTo : EndofList;
++ if (!strncmp(order,"Cc", 2)
++ || (rev = !strncmp(order,"Reverse Cc", 10)))
++ return is_rev || rev ? SortCc : EndofList;
++ if (!strncmp(order,"Date", 4)
++ || (rev = !strncmp(order,"Reverse Date", 12)))
++ return is_rev || rev ? SortDate : EndofList;
++ if (!strncmp(order,"siZe", 4)
++ || (rev = !strncmp(order,"Reverse siZe", 12)))
++ return is_rev || rev ? SortSize : EndofList;
++ if (!strncmp(order,"scorE", 5)
++ || (rev = !strncmp(order,"Reverse scorE", 13)))
++ return is_rev || rev ? SortScore : EndofList;
++ return EndofList;
++ }
+
+ /*----------------------------------------------------------------------
+ Sort the current folder into the order set in the msgmap
+***************
+*** 8069,8080 ****
+ causes the sort to happen if it is still needed.
+ ----*/
+ void
+! sort_folder(stream, msgmap, new_sort, new_rev, flags)
+ MAILSTREAM *stream;
+ MSGNO_S *msgmap;
+ SortOrder new_sort;
+ int new_rev;
+ unsigned flags;
+ {
+ long raw_current, i, j;
+ unsigned long *sort = NULL;
+--- 8450,8462 ----
+ causes the sort to happen if it is still needed.
+ ----*/
+ void
+! sort_folder(stream, msgmap, new_sort, new_rev, flags, first)
+ MAILSTREAM *stream;
+ MSGNO_S *msgmap;
+ SortOrder new_sort;
+ int new_rev;
+ unsigned flags;
++ int first;
+ {
+ long raw_current, i, j;
+ unsigned long *sort = NULL;
+***************
+*** 8084,8089 ****
+--- 8466,8480 ----
+ int current_rev;
+ MESSAGECACHE *mc;
+
++ if (first){
++ if (new_sort == SortThread)
++ find_msgmap(stream, msgmap, flags,
++ ps_global->thread_cur_sort, new_rev);
++ else
++ sort_folder(stream, msgmap, new_sort, new_rev, flags, 0);
++ return;
++ }
++
+ dprint(2, (debugfile, "Sorting by %s%s\n",
+ sort_name(new_sort), new_rev ? "/reverse" : ""));
+
+***************
+*** 8446,8451 ****
+--- 8837,8843 ----
+
+ thrd = fetch_head_thread(stream);
+ for(j = msgmap->max_thrdno; thrd && j >= 1L; j--){
++ unsigned long branch;
+ thrd->thrdno = j;
+
+ if(thrd->nextthd)
+***************
+*** 8512,8518 ****
+ MESSAGECACHE *mc;
+ PINELT_S *peltp;
+
+! if(!(stream && stream->spare))
+ return;
+
+ ps_global->view_skipped_index = 0;
+--- 8904,8910 ----
+ MESSAGECACHE *mc;
+ PINELT_S *peltp;
+
+! if(!(stream && stream->spare) || !erase_thread_info)
+ return;
+
+ ps_global->view_skipped_index = 0;
+***************
+*** 8574,8580 ****
+ unsigned long msgno, rawno, set_in_thread, in_thread;
+ int bail, this_is_vis;
+ int un_view_thread = 0;
+! long raw_current;
+
+
+ dprint(2, (debugfile, "sort_thread_callback\n"));
+--- 8966,8972 ----
+ unsigned long msgno, rawno, set_in_thread, in_thread;
+ int bail, this_is_vis;
+ int un_view_thread = 0;
+! long raw_current, branch;
+
+
+ dprint(2, (debugfile, "sort_thread_callback\n"));
+***************
+*** 8593,8601 ****
+ * way. If the dummy node is at the top-level, then its children are
+ * promoted to the top-level as separate threads.
+ */
+! collapsed_tree = collapse_threadnode_tree(tree);
+! (void) sort_thread_flatten(collapsed_tree, stream, thrd_flatten_array,
+! NULL, THD_TOP);
+ mail_free_threadnode(&collapsed_tree);
+
+ if(any_lflagged(g_sort.msgmap, MN_HIDE))
+--- 8985,8995 ----
+ * way. If the dummy node is at the top-level, then its children are
+ * promoted to the top-level as separate threads.
+ */
+! collapsed_tree = F_ON(F_ENHANCED_THREAD, ps_global) ?
+! copy_tree(tree) : collapse_threadnode_tree(tree);
+! (void) sort_thread_flatten(collapsed_tree,
+! stream, thrd_flatten_array,
+! NULL, THD_TOP, 0, 1L, 0L);
+ mail_free_threadnode(&collapsed_tree);
+
+ if(any_lflagged(g_sort.msgmap, MN_HIDE))
+***************
+*** 8760,8771 ****
+ else{
+ thrd = fetch_head_thread(stream);
+ while(thrd){
+ /*
+ * The top-level threads aren't hidden by collapse.
+ */
+ msgno = mn_raw2m(g_sort.msgmap, thrd->rawno);
+! if(msgno)
+! set_lflag(stream, g_sort.msgmap, msgno, MN_CHID, 0);
+
+ if(thrd->next){
+ PINETHRD_S *nthrd;
+--- 9154,9167 ----
+ else{
+ thrd = fetch_head_thread(stream);
+ while(thrd){
++ unsigned long raw = thrd->rawno;
++ unsigned long top = top_thread(stream, raw);
+ /*
+ * The top-level threads aren't hidden by collapse.
+ */
+ msgno = mn_raw2m(g_sort.msgmap, thrd->rawno);
+! if(msgno && !get_lflag(stream, NULL,thrd->rawno, MN_COLL))
+! set_lflag(stream, g_sort.msgmap, msgno, MN_CHID, 0);
+
+ if(thrd->next){
+ PINETHRD_S *nthrd;
+***************
+*** 8779,8787 ****
+ MN_COLL));
+ }
+
+! if(thrd->nextthd)
+ thrd = fetch_thread(stream, thrd->nextthd);
+! else
+ thrd = NULL;
+ }
+ }
+--- 9175,9184 ----
+ MN_COLL));
+ }
+
+! while (thrd && top_thread(stream, thrd->rawno) == top
+! && thrd->nextthd)
+ thrd = fetch_thread(stream, thrd->nextthd);
+! if (!(thrd && thrd->nextthd))
+ thrd = NULL;
+ }
+ }
+***************
+*** 8802,8811 ****
+ PINETHRD_S *not_this_thread;
+ {
+ PINETHRD_S *thrd = NULL, *nthrd;
+! unsigned long msgno;
+
+ dprint(9, (debugfile, "collapse_threads\n"));
+
+ thrd = fetch_head_thread(stream);
+ while(thrd){
+ if(thrd != not_this_thread){
+--- 9199,9215 ----
+ PINETHRD_S *not_this_thread;
+ {
+ PINETHRD_S *thrd = NULL, *nthrd;
+! unsigned long msgno, branch;
+
+ dprint(9, (debugfile, "collapse_threads\n"));
+
++ /* if(F_ON(F_ENHANCED_THREAD, ps_global)){*/
++ kolapse_thread(ps_global, stream, msgmap, '[', 0);
++ if (not_this_thread)
++ expand_thread(ps_global, stream, msgmap, 0);
++ return;
++ /* }*/
++
+ thrd = fetch_head_thread(stream);
+ while(thrd){
+ if(thrd != not_this_thread){
+***************
+*** 8840,8846 ****
+ int a_parent_is_collapsed;
+ {
+ PINETHRD_S *nthrd, *bthrd;
+! unsigned long msgno;
+
+ if(!thrd)
+ return;
+--- 9244,9250 ----
+ int a_parent_is_collapsed;
+ {
+ PINETHRD_S *nthrd, *bthrd;
+! unsigned long msgno, next, branch;
+
+ if(!thrd)
+ return;
+***************
+*** 8858,8865 ****
+ set_lflag(stream, msgmap, msgno, MN_CHID, 0);
+ }
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ make_thrdflags_consistent(stream, msgmap, nthrd,
+ a_parent_is_collapsed
+--- 9262,9269 ----
+ set_lflag(stream, msgmap, msgno, MN_CHID, 0);
+ }
+
+! if(next = get_next(stream, thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ make_thrdflags_consistent(stream, msgmap, nthrd,
+ a_parent_is_collapsed
+***************
+*** 8868,8875 ****
+ MN_COLL));
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ make_thrdflags_consistent(stream, msgmap, bthrd,
+ a_parent_is_collapsed);
+--- 9272,9279 ----
+ MN_COLL));
+ }
+
+! if(branch = get_branch(stream, thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ make_thrdflags_consistent(stream, msgmap, bthrd,
+ a_parent_is_collapsed);
+***************
+*** 8882,8888 ****
+ MAILSTREAM *stream;
+ {
+ PINETHRD_S *thrd = NULL;
+! long vis = 0L;
+
+ thrd = fetch_head_thread(stream);
+ while(thrd){
+--- 9286,9292 ----
+ MAILSTREAM *stream;
+ {
+ PINETHRD_S *thrd = NULL;
+! long vis = 0L, branch;
+
+ thrd = fetch_head_thread(stream);
+ while(thrd){
+***************
+*** 8899,8945 ****
+
+
+ struct pass_along *
+! sort_thread_flatten(node, stream, entry, thrd, flags)
+ THREADNODE *node;
+ MAILSTREAM *stream;
+ struct pass_along *entry;
+ PINETHRD_S *thrd;
+ unsigned flags;
+ {
+ long n = 0L;
+! PINETHRD_S *newthrd = NULL;
+
+ if(node){
+! if(node->num){ /* holes happen */
+ n = (long) (entry - thrd_flatten_array);
+
+ for(; n > 0; n--)
+ if(thrd_flatten_array[n].rawno == node->num)
+ break; /* duplicate */
+
+! if(!n)
+! entry->rawno = node->num;
+! }
+!
+! /*
+! * Build a richer threading structure that will help us paint
+! * and operate on threads and subthreads.
+! */
+! if(!n && node->num){
+! newthrd = msgno_thread_info(stream, node->num, thrd, flags);
+! if(newthrd){
+! entry->thrd = newthrd;
+! entry++;
+!
+! if(node->next)
+ entry = sort_thread_flatten(node->next, stream, entry,
+! newthrd, THD_NEXT);
+!
+ if(node->branch)
+ entry = sort_thread_flatten(node->branch, stream, entry,
+! newthrd,
+! (flags == THD_TOP) ? THD_TOP
+! : THD_BRANCH);
+ }
+ }
+ }
+--- 9303,9388 ----
+
+
+ struct pass_along *
+! sort_thread_flatten(node, stream, entry, thrd, flags, adopted, top, threadno)
+ THREADNODE *node;
+ MAILSTREAM *stream;
+ struct pass_along *entry;
+ PINETHRD_S *thrd;
+ unsigned flags;
++ int adopted;
++ long top;
++ long threadno;
+ {
+ long n = 0L;
+! PINETHRD_S *newthrd = NULL, *save_thread = NULL;
+
+ if(node){
+! if(node->num){
+ n = (long) (entry - thrd_flatten_array);
+
++ if (adopted == 2)
++ top = node->num;
++
+ for(; n > 0; n--)
+ if(thrd_flatten_array[n].rawno == node->num)
+ break; /* duplicate */
+
+! if(!n){
+! entry->rawno = node->num;
+! newthrd = msgno_thread_info(stream, node->num, thrd, flags);
+! if(newthrd){
+! if (adopted == 2)
+! threadno = newthrd->thrdno;
+! if (adopted){
+! newthrd->toploose = top;
+! newthrd->thrdno = threadno;
+! }
+! entry->thrd = newthrd;
+! entry++;
+! }
+! adopted = adopted ? 1 : 0;
+! if (node->next)
+ entry = sort_thread_flatten(node->next, stream, entry,
+! newthrd, THD_NEXT, adopted, top,
+! threadno);
+ if(node->branch)
+ entry = sort_thread_flatten(node->branch, stream, entry,
+! newthrd,
+! (flags == THD_TOP) ? THD_TOP: THD_BRANCH,
+! adopted, top, threadno);
+! }
+! }
+! else{
+! adopted = 2;
+! if(node->next)
+! entry = sort_thread_flatten(node->next, stream, entry,
+! thrd, THD_TOP, adopted, top, threadno);
+! adopted = 0;
+! if(node->branch){
+! if(entry){
+! struct pass_along *last_entry = entry;
+! int i = 0;
+!
+! /*
+! * Next moved up to replace "tree" in the tree.
+! * If next has no branches, then we want to branch off
+! * of next. If next has branches, we want to branch off
+! * of the last of those branches instead.
+! */
+! last_entry--;
+! while(last_entry->thrd->parent)
+! last_entry--;
+! save_thread = last_entry->thrd;
+! last_entry += i+1;
+!
+! last_entry = sort_thread_flatten(node->branch, stream, entry,
+! save_thread,
+! (flags == THD_TOP) ? THD_TOP: THD_BRANCH,
+! adopted, top, threadno);
+! }
+! else
+! entry = sort_thread_flatten(node->branch, stream, entry,
+! NULL, THD_TOP, adopted, top, threadno);
+ }
+ }
+ }
+***************
+*** 8947,8952 ****
+--- 9390,9415 ----
+ return(entry);
+ }
+
++ /*
++ * Make a copy of c-client's THREAD tree
++ */
++ THREADNODE *
++ copy_tree(tree)
++ THREADNODE *tree;
++ {
++ THREADNODE *newtree = NULL;
++
++ if(tree){
++ newtree = mail_newthreadnode(NULL);
++ newtree->num = tree->num;
++ if(tree->next)
++ newtree->next = copy_tree(tree->next);
++
++ if(tree->branch)
++ newtree->branch = copy_tree(tree->branch);
++ }
++ return(newtree);
++ }
+
+ /*
+ * Make a copy of c-client's THREAD tree while eliminating dummy nodes.
+***************
+*** 10694,10705 ****
+
+
+ void
+! thread_command(state, stream, msgmap, preloadkeystroke, q_line)
+ struct pine *state;
+ MAILSTREAM *stream;
+ MSGNO_S *msgmap;
+ int preloadkeystroke;
+ int q_line;
+ {
+ PINETHRD_S *thrd = NULL;
+ unsigned long rawno, save_branch;
+--- 11157,11169 ----
+
+
+ void
+! thread_command(state, stream, msgmap, preloadkeystroke, q_line, display)
+ struct pine *state;
+ MAILSTREAM *stream;
+ MSGNO_S *msgmap;
+ int preloadkeystroke;
+ int q_line;
++ int display;
+ {
+ PINETHRD_S *thrd = NULL;
+ unsigned long rawno, save_branch;
+***************
+*** 10748,10754 ****
+ cancel_busy_alarm(0);
+
+ (void ) apply_command(state, stream, msgmap, preloadkeystroke, flags,
+! q_line);
+
+ /* restore the original flags */
+ copy_lflags(stream, msgmap, MN_STMP, MN_SLCT);
+--- 11212,11218 ----
+ cancel_busy_alarm(0);
+
+ (void ) apply_command(state, stream, msgmap, preloadkeystroke, flags,
+! q_line, display);
+
+ /* restore the original flags */
+ copy_lflags(stream, msgmap, MN_STMP, MN_SLCT);
+***************
+*** 10786,10805 ****
+ int v;
+ {
+ PINETHRD_S *nthrd, *bthrd;
+
+ if(!(stream && thrd && msgmap))
+ return;
+
+ set_lflag(stream, msgmap, mn_raw2m(msgmap, thrd->rawno), f, v);
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ set_flags_for_thread(stream, msgmap, f, nthrd, v);
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ set_flags_for_thread(stream, msgmap, f, bthrd, v);
+ }
+--- 11250,11270 ----
+ int v;
+ {
+ PINETHRD_S *nthrd, *bthrd;
++ unsigned long next = 0L, branch = 0L;
+
+ if(!(stream && thrd && msgmap))
+ return;
+
+ set_lflag(stream, msgmap, mn_raw2m(msgmap, thrd->rawno), f, v);
+
+! if(next = get_next(stream,thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ set_flags_for_thread(stream, msgmap, f, nthrd, v);
+ }
+
+! if(branch = get_branch(stream, thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ set_flags_for_thread(stream, msgmap, f, bthrd, v);
+ }
+***************
+*** 10854,10864 ****
+ * index.
+ */
+ void
+! collapse_or_expand(state, stream, msgmap, msgno)
+ struct pine *state;
+ MAILSTREAM *stream;
+ MSGNO_S *msgmap;
+ unsigned long msgno;
+ {
+ int collapsed, adjust_current = 0;
+ PINETHRD_S *thrd = NULL, *nthrd;
+--- 11319,11330 ----
+ * index.
+ */
+ void
+! collapse_or_expand(state, stream, msgmap, msgno, display)
+ struct pine *state;
+ MAILSTREAM *stream;
+ MSGNO_S *msgmap;
+ unsigned long msgno;
++ int display;
+ {
+ int collapsed, adjust_current = 0;
+ PINETHRD_S *thrd = NULL, *nthrd;
+***************
+*** 10912,10918 ****
+ if(!thrd)
+ return;
+
+! collapsed = get_lflag(stream, NULL, thrd->rawno, MN_COLL) && thrd->next;
+
+ if(collapsed){
+ msgno = mn_raw2m(msgmap, thrd->rawno);
+--- 11378,11384 ----
+ if(!thrd)
+ return;
+
+! collapsed = this_thread_is_kolapsed(ps_global, stream, msgmap, thrd->rawno);
+
+ if(collapsed){
+ msgno = mn_raw2m(msgmap, thrd->rawno);
+***************
+*** 10930,10942 ****
+ msgno = mn_raw2m(msgmap, thrd->rawno);
+ if(msgno > 0L && msgno <= mn_get_total(msgmap)){
+ set_lflag(stream, msgmap, msgno, MN_COLL, 1);
+! if(nthrd = fetch_thread(stream, thrd->next))
+ set_thread_subtree(stream, nthrd, msgmap, 1, MN_CHID);
+
+ clear_index_cache_ent(msgno);
+ }
+ }
+! else
+ q_status_message(SM_ORDER, 0, 1,
+ "No thread to collapse or expand on this line");
+
+--- 11396,11408 ----
+ msgno = mn_raw2m(msgmap, thrd->rawno);
+ if(msgno > 0L && msgno <= mn_get_total(msgmap)){
+ set_lflag(stream, msgmap, msgno, MN_COLL, 1);
+! if((thrd->next) && (nthrd = fetch_thread(stream, thrd->next)))
+ set_thread_subtree(stream, nthrd, msgmap, 1, MN_CHID);
+
+ clear_index_cache_ent(msgno);
+ }
+ }
+! else if (display)
+ q_status_message(SM_ORDER, 0, 1,
+ "No thread to collapse or expand on this line");
+
+***************
+*** 11018,11035 ****
+ unsigned long rawno, count = 0;
+ PINETHRD_S *nthrd, *bthrd;
+ MESSAGECACHE *mc;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return count;
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ count += count_flags_in_thread(stream, nthrd, flags);
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ count += count_flags_in_thread(stream, bthrd, flags);
+ }
+--- 11484,11502 ----
+ unsigned long rawno, count = 0;
+ PINETHRD_S *nthrd, *bthrd;
+ MESSAGECACHE *mc;
++ unsigned long next = 0L, branch = 0L;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return count;
+
+! if(next = get_next(stream, thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ count += count_flags_in_thread(stream, nthrd, flags);
+ }
+
+! if(branch = get_branch(stream, thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ count += count_flags_in_thread(stream, bthrd, flags);
+ }
+***************
+*** 11060,11079 ****
+ MSGNO_S *msgmap;
+ int flags; /* flag to count */
+ {
+! unsigned long rawno, count = 0;
+ PINETHRD_S *nthrd, *bthrd;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return count;
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ count += count_lflags_in_thread(stream, nthrd, msgmap, flags);
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ count += count_lflags_in_thread(stream, bthrd, msgmap,flags);
+ }
+--- 11527,11546 ----
+ MSGNO_S *msgmap;
+ int flags; /* flag to count */
+ {
+! unsigned long rawno, count = 0, next, branch;
+ PINETHRD_S *nthrd, *bthrd;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return count;
+
+! if(next = get_next(stream, thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ count += count_lflags_in_thread(stream, nthrd, msgmap, flags);
+ }
+
+! if(branch = get_branch(stream, thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ count += count_lflags_in_thread(stream, bthrd, msgmap,flags);
+ }
+***************
+*** 11095,11101 ****
+ MAILSTREAM *stream;
+ PINETHRD_S *thrd;
+ {
+! unsigned long rawno, count = 0;
+ PINETHRD_S *nthrd, *bthrd;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+--- 11562,11568 ----
+ MAILSTREAM *stream;
+ PINETHRD_S *thrd;
+ {
+! unsigned long rawno, count = 0, next, branch;
+ PINETHRD_S *nthrd, *bthrd;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+***************
+*** 11104,11117 ****
+ if(get_lflag(stream, NULL, thrd->rawno, MN_HIDE) == 0)
+ return 1;
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd && thread_has_some_visible(stream, nthrd))
+ return 1;
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd && thread_has_some_visible(stream, bthrd))
+ return 1;
+ }
+--- 11571,11584 ----
+ if(get_lflag(stream, NULL, thrd->rawno, MN_HIDE) == 0)
+ return 1;
+
+! if(next = get_next(stream, thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd && thread_has_some_visible(stream, nthrd))
+ return 1;
+ }
+
+! if(branch = get_branch(stream, thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd && thread_has_some_visible(stream, bthrd))
+ return 1;
+ }
+***************
+*** 11186,11205 ****
+ MSGNO_S *msgmap;
+ {
+ int count = 0;
+ PINETHRD_S *nthrd, *bthrd;
+ MESSAGECACHE *mc;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return count;
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ count += mark_msgs_in_thread(stream, nthrd, msgmap);
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ count += mark_msgs_in_thread(stream, bthrd, msgmap);
+ }
+--- 11653,11673 ----
+ MSGNO_S *msgmap;
+ {
+ int count = 0;
++ long next, branch;
+ PINETHRD_S *nthrd, *bthrd;
+ MESSAGECACHE *mc;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return count;
+
+! if(next = get_next(stream, thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ count += mark_msgs_in_thread(stream, nthrd, msgmap);
+ }
+
+! if(branch = get_branch(stream, thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ count += mark_msgs_in_thread(stream, bthrd, msgmap);
+ }
+***************
+*** 11233,11239 ****
+ int flags; /* flags to set or clear */
+ int v; /* set or clear? */
+ {
+! unsigned long rawno, msgno;
+ PINETHRD_S *nthrd, *bthrd;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+--- 11701,11707 ----
+ int flags; /* flags to set or clear */
+ int v; /* set or clear? */
+ {
+! unsigned long rawno, msgno, next, branch;
+ PINETHRD_S *nthrd, *bthrd;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+***************
+*** 11259,11272 ****
+ && v == 1 && get_index_cache(msgno)->line[0])
+ clear_index_cache_ent(msgno);
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ set_thread_lflags(stream, nthrd, msgmap, flags, v);
+ }
+
+! if(thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ set_thread_lflags(stream, bthrd, msgmap, flags, v);
+ }
+--- 11727,11740 ----
+ && v == 1 && get_index_cache(msgno)->line[0])
+ clear_index_cache_ent(msgno);
+
+! if(next = get_next(stream, thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ set_thread_lflags(stream, nthrd, msgmap, flags, v);
+ }
+
+! if(branch = get_branch(stream,thrd)){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ set_thread_lflags(stream, bthrd, msgmap, flags, v);
+ }
+***************
+*** 11353,11371 ****
+ {
+ char to_us = ' ';
+ PINETHRD_S *nthrd, *bthrd;
+ MESSAGECACHE *mc;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return to_us;
+
+! if(thrd->next){
+! nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ to_us = to_us_symbol_for_thread(stream, nthrd, consider_flagged);
+ }
+
+! if(to_us == ' ' && thrd->branch){
+! bthrd = fetch_thread(stream, thrd->branch);
+ if(bthrd)
+ to_us = to_us_symbol_for_thread(stream, bthrd, consider_flagged);
+ }
+--- 11821,11840 ----
+ {
+ char to_us = ' ';
+ PINETHRD_S *nthrd, *bthrd;
++ unsigned long next = 0L, branch = 0L;
+ MESSAGECACHE *mc;
+
+ if(!thrd || !stream || thrd->rawno < 1L || thrd->rawno > stream->nmsgs)
+ return to_us;
+
+! if(next = get_next(stream,thrd)){
+! nthrd = fetch_thread(stream, next);
+ if(nthrd)
+ to_us = to_us_symbol_for_thread(stream, nthrd, consider_flagged);
+ }
+
+! if(to_us == ' ' && (branch = get_branch(stream, thrd))){
+! bthrd = fetch_thread(stream, branch);
+ if(bthrd)
+ to_us = to_us_symbol_for_thread(stream, bthrd, consider_flagged);
+ }
+***************
+*** 11400,11406 ****
+ break;
+ }
+
+! if(to_us != '+' && resent_to_us(&idata))
+ to_us = '+';
+
+ if(to_us == ' ' && F_ON(F_MARK_FOR_CC,ps_global))
+--- 11869,11875 ----
+ break;
+ }
+
+! if(to_us != '+' && !idata.bogus && resent_to_us(&idata))
+ to_us = '+';
+
+ if(to_us == ' ' && F_ON(F_MARK_FOR_CC,ps_global))
+***************
+*** 11436,11442 ****
+ int flags; /* flags to set or clear */
+ {
+ int hiding;
+! unsigned long rawno, msgno;
+ PINETHRD_S *nthrd, *bthrd;
+
+ hiding = (flags == MN_CHID) && v;
+--- 11905,11911 ----
+ int flags; /* flags to set or clear */
+ {
+ int hiding;
+! unsigned long rawno, msgno, next, branch;
+ PINETHRD_S *nthrd, *bthrd;
+
+ hiding = (flags == MN_CHID) && v;
+***************
+*** 11448,11454 ****
+
+ set_lflag(stream, msgmap, msgno, flags, v);
+
+! if(thrd->next && (hiding || !get_lflag(stream,NULL,thrd->rawno,MN_COLL))){
+ nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ set_thread_subtree(stream, nthrd, msgmap, v, flags);
+--- 11917,11924 ----
+
+ set_lflag(stream, msgmap, msgno, flags, v);
+
+! if(thrd->next
+! && (hiding || !get_lflag(stream,NULL,thrd->rawno,MN_COLL))){
+ nthrd = fetch_thread(stream, thrd->next);
+ if(nthrd)
+ set_thread_subtree(stream, nthrd, msgmap, v, flags);
+***************
+*** 11492,11499 ****
+ if(rawno)
+ thrd = fetch_thread(stream, rawno);
+
+! if(thrd && thrd->top && thrd->top != thrd->rawno)
+! thrd = fetch_thread(stream, thrd->top);
+
+ if(!thrd)
+ return 0;
+--- 11962,11969 ----
+ if(rawno)
+ thrd = fetch_thread(stream, rawno);
+
+! if(thrd && thrd->top && top_thread(stream,thrd->top) != thrd->rawno)
+! thrd = fetch_thread(stream, top_thread(stream,thrd->top));
+
+ if(!thrd)
+ return 0;
+***************
+*** 11509,11516 ****
+ set_thread_lflags(stream, thrd, msgmap, MN_CHID2, 1);
+ }
+
+! if(current_index_state)
+! msgmap->top_after_thrd = current_index_state->msg_at_top;
+
+ /*
+ * If this is one of those wacky users who like to sort backwards
+--- 11979,11987 ----
+ set_thread_lflags(stream, thrd, msgmap, MN_CHID2, 1);
+ }
+
+! /* if(current_index_state)
+! msgmap->top_after_thrd = current_index_state->msg_at_top;*/
+! msgmap->top_after_thrd = mn_raw2m(msgmap, thrd->top);
+
+ /*
+ * If this is one of those wacky users who like to sort backwards
+***************
+*** 11563,11569 ****
+ thrd = fetch_thread(stream, rawno);
+
+ if(thrd && thrd->top)
+! topthrd = fetch_thread(stream, thrd->top);
+
+ if(!topthrd)
+ return 0;
+--- 12034,12040 ----
+ thrd = fetch_thread(stream, rawno);
+
+ if(thrd && thrd->top)
+! topthrd = fetch_thread(stream, top_thread(stream,thrd->top));
+
+ if(!topthrd)
+ return 0;
+***************
+*** 11700,11702 ****
+--- 12171,12508 ----
+ }
+ }
+ }
++
++ unsigned long
++ get_branch(stream,thrd)
++ MAILSTREAM *stream;
++ PINETHRD_S *thrd;
++ {
++ PINETHRD_S *nthrd = NULL;
++ unsigned long top;
++
++ if (thrd->toploose && thrd->nextthd)
++ nthrd = fetch_thread(stream, thrd->nextthd);
++ if (!nthrd)
++ return thrd->branch;
++ top = top_thread(stream, thrd->rawno);
++ return thrd->branch
++ ? thrd->branch
++ : (F_ON(F_ENHANCED_THREAD, ps_global)
++ ? (top == top_thread(stream, nthrd->rawno) ? thrd->nextthd : 0L)
++ : 0L);
++ }
++
++ unsigned long
++ get_next(stream,thrd)
++ MAILSTREAM *stream;
++ PINETHRD_S *thrd;
++ {
++ return thrd->next;
++ }
++
++ long
++ get_length_branch(stream, rawno)
++ MAILSTREAM *stream;
++ long rawno;
++ {
++ int branchp = 0, done = 0;
++ long top, count = 1L, raw;
++ PINETHRD_S *thrd, *pthrd = NULL, *nthrd;
++
++ thrd = fetch_thread(stream, rawno);
++
++ if (!thrd)
++ return -1L;
++
++ top = thrd->top;
++
++ if (thrd->parent)
++ pthrd = fetch_thread(stream, thrd->parent);
++
++ if (thrd->rawno == top)
++ branchp++;
++
++ if (!branchp && !pthrd){ /* what!!?? */
++ raw = top;
++ while (!done){
++ pthrd = fetch_thread(stream, raw);
++ if ((pthrd->next == rawno) || (pthrd->branch == rawno))
++ done++;
++ else{
++ if (pthrd->next)
++ raw = pthrd->next;
++ else if (pthrd->branch)
++ raw = pthrd->branch;
++ }
++ }
++ }
++
++ if (pthrd && pthrd->next == thrd->rawno && thrd->branch)
++ branchp++;
++
++ if (pthrd && pthrd->next && pthrd->next != thrd->rawno){
++ nthrd = fetch_thread(stream, pthrd->next);
++ while (nthrd && nthrd->branch && nthrd->branch != thrd->rawno)
++ nthrd = fetch_thread(stream, nthrd->branch);
++ if(nthrd && nthrd->branch && nthrd->branch == thrd->rawno)
++ branchp++;
++ }
++
++ if(branchp){
++ int entry = 0;
++ while(thrd && thrd->next){
++ entry = 1;
++ count++;
++ thrd = fetch_thread(stream, thrd->next);
++ if (thrd->branch)
++ break;
++ }
++ if (entry && thrd->branch)
++ count--;
++ }
++ return branchp ? (count ? count : 1L) : 0L;
++ }
++
++ void
++ find_msgmap(stream, msgmap, flags, ordersort, is_rev)
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int flags;
++ SortOrder ordersort;
++ unsigned is_rev;
++ {
++ int we_cancel;
++ long *old_arrival,*new_arrival;
++ long init_thread, end_thread, current;
++ long k = 1L, j, last_thread = 0L;
++ long i, tmsg, ntmsg, nthreads;
++ int nflags = (SRT_VRB | SRT_MAN);
++ char sort_msg[MAX_SCREEN_COLS+1] = {'\0'};
++ PINETHRD_S *thrd, *tthrd, *nthrd;
++
++ erase_thread_info = 0;
++ current = mn_m2raw(msgmap, mn_get_cur(msgmap));
++
++ /* now sort by arrival */
++ sort_folder(stream, msgmap, ordersort, 0, nflags, 0);
++
++ tmsg = mn_get_total(msgmap) + 1;
++
++ if (tmsg <= 1)
++ return;
++
++ old_arrival = (long *) fs_get(tmsg * sizeof(long));
++ memset(old_arrival, 0, tmsg*sizeof(long));
++ for (i= 1L;(i <= mn_get_total(msgmap)) && (old_arrival[i] = msgmap->sort[i]); i++);
++
++ /* now sort by thread */
++ sort_folder(stream, msgmap, SortThread, 0, nflags, 0);
++ ntmsg = mn_get_total(msgmap) + 1;
++
++ if (tmsg != ntmsg){ /* oh oh, something happened,we better try again */
++ fs_give((void **)&old_arrival);
++ find_msgmap(stream, msgmap, flags, ordersort, is_rev);
++ return;
++ }
++
++ /* reconstruct the msgmap */
++
++ new_arrival = (long *) fs_get(tmsg * sizeof(long));
++ memset(new_arrival, 0, tmsg*sizeof(long));
++ i = mn_get_total(msgmap);
++ while (new_arrival[1] == 0){ /* think of this as (tmsg > 0) */
++ int done = 0;
++ long n = mn_get_total(msgmap);
++
++ init_thread = top_thread(stream, old_arrival[i]);
++ thrd = fetch_thread(stream, init_thread);
++ while ((new_arrival[n] != 0) && !done){ /* compare raw numbers */
++ done = (new_arrival[n] == init_thread);
++ n--;
++ }
++ if (!done){
++ k = 1L;
++ mn_set_cur(msgmap, mn_raw2m(msgmap, init_thread));
++ if (move_next_thread(ps_global, stream, msgmap, 0) <= 0)
++ j = mn_get_total(msgmap) - mn_raw2m(msgmap, init_thread) + 1;
++ else
++ j = mn_get_cur(msgmap) - mn_raw2m(msgmap, init_thread);
++ end_thread = mn_raw2m(msgmap, init_thread) + j;
++ while (k <= j){
++ new_arrival[tmsg - k] = msgmap->sort[end_thread - k];
++ k++;
++ }
++ tmsg -= j;
++ }
++ i--;
++ }
++ relink_threads(stream, msgmap, new_arrival);
++ for (i = 1; (i <= mn_get_total(msgmap))
++ && (msgmap->sort[i] = new_arrival[i]); i++);
++ msgno_reset_isort(msgmap);
++
++ fs_give((void **)&new_arrival);
++ fs_give((void **)&old_arrival);
++
++
++ if(is_rev && (mn_get_total(msgmap) > 1L)){
++ long *rev_sort;
++ long i = 1L, l = mn_get_total(msgmap);
++
++ rev_sort = (long *) fs_get((mn_get_total(msgmap)+1L) * sizeof(long));
++ memset(rev_sort, 0, (mn_get_total(msgmap)+1L)*sizeof(long));
++ while (l > 0L){
++ if (top_thread(stream, msgmap->sort[l]) == msgmap->sort[l]){
++ long init_thread = msgmap->sort[l];
++ long j, k;
++
++ mn_set_cur(msgmap, mn_raw2m(msgmap, init_thread));
++ if (move_next_thread(ps_global, stream, msgmap, 0) <= 0)
++ j = mn_get_total(msgmap) - mn_raw2m(msgmap, init_thread) + 1;
++ else
++ j = mn_get_cur(msgmap) - mn_raw2m(msgmap, init_thread);
++ for (k = 0L; (k < j) && (rev_sort[i+k] = msgmap->sort[l+k]); k++);
++ i += j;
++ }
++ l--;
++ }
++ relink_threads(stream, msgmap, rev_sort);
++ for (i = 1L; i <= mn_get_total(msgmap); i++)
++ msgmap->sort[i] = rev_sort[i];
++ msgno_reset_isort(msgmap);
++ fs_give((void **)&rev_sort);
++ }
++ mn_reset_cur(msgmap, first_sorted_flagged(is_rev ? F_NONE : F_SRCHBACK,
++ stream, mn_raw2m(msgmap, current), FSF_SKIP_CHID));
++ msgmap->top = -1L;
++
++ sp_set_unsorted_newmail(ps_global->mail_stream, 0);
++
++ for(i = 1L; i <= ps_global->mail_stream->nmsgs; i++)
++ mail_elt(ps_global->mail_stream, i)->spare7 = 0;
++
++ mn_set_sort(msgmap, SortThread);
++ mn_set_revsort(msgmap, is_rev);
++ erase_thread_info = 1;
++ clear_index_cache();
++ }
++
++ void
++ move_thread(state, stream, msgmap, direction)
++ struct pine *state;
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ int direction;
++ {
++ long new_cursor, old_cursor = mn_get_cur(msgmap);
++ int rv;
++ PINETHRD_S *thrd;
++
++ rv = direction > 0 ? move_next_thread(state, stream, msgmap, 1):
++ move_prev_thread(state, stream, msgmap, 1);
++ if (rv > 0 && THRD_INDX_ENABLED()){
++ new_cursor = mn_get_cur(msgmap);
++ mn_set_cur(msgmap, old_cursor);
++ unview_thread(state, stream, msgmap);
++ thrd = fetch_thread(stream,mn_m2raw(msgmap, new_cursor));
++ mn_set_cur(msgmap, new_cursor);
++ view_thread(state, stream, msgmap, 1);
++ state->next_screen = SCREEN_FUN_NULL;
++ }
++ }
++
++ void
++ relink_threads(stream, msgmap, new_arrival)
++ MAILSTREAM *stream;
++ MSGNO_S *msgmap;
++ long *new_arrival;
++ {
++ long last_thread = 0L;
++ long i = 0L, j = 1L, k;
++ PINETHRD_S *thrd, *nthrd;
++
++ while (j <= mn_get_total(msgmap)){
++ i++;
++ thrd = fetch_thread(stream, new_arrival[j]);
++ if (!thrd) /* sort failed!, better leave from here now!!! */
++ break;
++ thrd->prevthd = last_thread;
++ thrd->thrdno = i;
++ thrd->head = new_arrival[1];
++ last_thread = thrd->rawno;
++ mn_set_cur(msgmap, mn_raw2m(msgmap,thrd->top));
++ k = mn_get_cur(msgmap);
++ if (move_next_thread(ps_global, stream, msgmap, 0) <= 0)
++ j += mn_get_total(msgmap) + 1 - k;
++ else
++ j += mn_get_cur(msgmap) - k;
++ if (!thrd->toploose)
++ thrd->nextthd = (j <= mn_get_total(msgmap)) ? new_arrival[j] : 0L;
++ else{
++ int done = 0;
++ while(thrd->nextthd && !done){
++ thrd->thrdno = i;
++ thrd->head = new_arrival[1];
++ if (thrd->nextthd)
++ nthrd = fetch_thread(stream, thrd->nextthd);
++ else
++ done++;
++ if(top_thread(stream, thrd->rawno) == top_thread(stream, nthrd->rawno))
++ thrd = nthrd;
++ else
++ done++;
++ }
++ thrd->nextthd = (j <= mn_get_total(msgmap)) ? new_arrival[j] : 0L;
++ last_thread = thrd->rawno;
++ }
++ }
++ }
++
++
++ int
++ find_index_rule()
++ {
++ int found = 0;
++ RULE_RESULT *rule;
++ INDEXDATA_S idata;
++ ENVELOPE *local_env;
++
++ memset(&idata, 0, sizeof(INDEXDATA_S));
++ idata.stream = ps_global->mail_stream;
++ local_env = (ENVELOPE *)make_envelope(&idata, 0);
++ rule = get_result_rule(V_INDEX_RULES, FOR_RULE | FOR_INDEX, local_env);
++ if (local_env)
++ mail_free_envelope(&local_env);
++ if (rule){
++ init_index_format(rule->result, &ps_global->index_disp_format);
++ found = 1;
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ return found;
++ }
++
++ void
++ setup_threading_display_style()
++ {
++ RULE_RESULT *rule;
++ NAMEVAL_S *v;
++ int i;
++
++ rule = get_result_rule(V_THREAD_DISP_STYLE_RULES,
++ FOR_RULE | FOR_THREAD, (ENVELOPE *) NULL);
++ if (rule || ps_global->VAR_THREAD_DISP_STYLE){
++ for(i = 0; v = thread_disp_styles(i); i++)
++ if(!strucmp(rule ? rule->result : ps_global->VAR_THREAD_DISP_STYLE,
++ rule ? (v ? v->name : "" ) : S_OR_L(v))){
++ ps_global->thread_disp_style = v->value;
++ break;
++ }
++ if (rule){
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ }
++ }
+diff -rc pine4.63/pine/mailpart.c pine4.63.I.USE/pine/mailpart.c
+*** pine4.63/pine/mailpart.c Wed Apr 27 11:55:01 2005
+--- pine4.63.I.USE/pine/mailpart.c Thu May 19 19:57:32 2005
+***************
+*** 815,822 ****
+--- 815,828 ----
+ /*--- get string ---*/
+ {int rc, found = 0;
+ char *result = NULL, buf[64];
++ static char last_pat[64] = {'\0'};
+ static char last[64], tmp[64];
+ HelpType help;
++ static ESCKEY_S ekey[] = {
++ {0, 0, "", ""},
++ {ctrl('N'), 9, "^N", "Ins Pat"},
++ {-1, 0, NULL, NULL}};
++
+
+ ps->mangled_footer = 1;
+ buf[0] = '\0';
+***************
+*** 829,846 ****
+ int flags = OE_APPEND_CURRENT | OE_SEQ_SENSITIVE;
+
+ rc = optionally_enter(buf,-FOOTER_ROWS(ps),0,sizeof(buf),
+! tmp,NULL,help,&flags);
+ if(rc == 3)
+ help = help == NO_HELP ? h_attach_index_whereis : NO_HELP;
+! else if(rc == 0 || rc == 1 || !buf[0]){
+ if(rc == 0 && !buf[0] && last[0])
+ strcpy(buf, last);
+!
+! break;
+ }
+ }
+
+ if(rc == 0 && buf[0]){
+ ctmp = current;
+ while(ctmp = next_attline(ctmp))
+ if(srchstr(ctmp->dstring, buf)){
+--- 835,857 ----
+ int flags = OE_APPEND_CURRENT | OE_SEQ_SENSITIVE;
+
+ rc = optionally_enter(buf,-FOOTER_ROWS(ps),0,sizeof(buf),
+! tmp,ekey,help,&flags);
+ if(rc == 3)
+ help = help == NO_HELP ? h_attach_index_whereis : NO_HELP;
+! else if(rc == 0 || rc == 1 || rc == 9 || !buf[0]){
+ if(rc == 0 && !buf[0] && last[0])
+ strcpy(buf, last);
+! if (rc == 9)
+! insert_pattern_in_string(buf, last_pat, 63);
+! else
+! break;
+ }
+ }
+
+ if(rc == 0 && buf[0]){
++ strncpy(last_pat, buf, sizeof(last_pat));
++ last_pat[sizeof(last_pat)-1] = '\0';
++
+ ctmp = current;
+ while(ctmp = next_attline(ctmp))
+ if(srchstr(ctmp->dstring, buf)){
+***************
+*** 3463,3469 ****
+ /*
+ * For consistency, the first question is always "include text?"
+ */
+! if((include_text = reply_text_query(ps_global, 1, &prefix)) >= 0
+ && reply_news_test(a->body->nested.msg->env, outgoing) > 0
+ && reply_harvest(ps_global, msgno, a->number,
+ a->body->nested.msg->env, &saved_from,
+--- 3474,3480 ----
+ /*
+ * For consistency, the first question is always "include text?"
+ */
+! if((include_text = reply_text_query(ps_global, 1, NULL, &prefix)) >= 0
+ && reply_news_test(a->body->nested.msg->env, outgoing) > 0
+ && reply_harvest(ps_global, msgno, a->number,
+ a->body->nested.msg->env, &saved_from,
+diff -rc pine4.63/pine/mailview.c pine4.63.I.USE/pine/mailview.c
+*** pine4.63/pine/mailview.c Wed Apr 27 11:55:02 2005
+--- pine4.63.I.USE/pine/mailview.c Thu May 19 19:57:34 2005
+***************
+*** 75,80 ****
+--- 75,89 ----
+ int len;
+ } SCRLFILE_S;
+
++ #include <regex.h>
++
++ #define REGERROR 128
++
++ typedef struct IVAL {
++ int start;
++ int end;
++ struct IVAL *next;
++ } IVAL_S;
+
+ /*
+ * Struct to help write lines do display as they're decoded
+***************
+*** 152,157 ****
+--- 161,167 ----
+ #define SS_CUR 2
+ #define SS_FREE 3
+
++ static ACTION_S *role_chosen = NULL;
+
+ /*
+ * Def's to help page reframing based on handles
+***************
+*** 235,246 ****
+ HOMEKEY_MENU,
+ ENDKEY_MENU,
+ RCOMPOSE_MENU,
+! NULL_MENU,
+! NULL_MENU,
+! NULL_MENU,
+! NULL_MENU,
+! NULL_MENU,
+! NULL_MENU,
+ NULL_MENU};
+ INST_KEY_MENU(view_keymenu, view_keys);
+ #define VIEW_ATT_KEY 3
+--- 245,256 ----
+ HOMEKEY_MENU,
+ ENDKEY_MENU,
+ RCOMPOSE_MENU,
+! {"(","Prev Threa",{MC_PRETHREAD,1,{'('}},KS_NONE},
+! {")","Next Threa",{MC_NEXTHREAD,1,{')'}},KS_NONE},
+! {"^D","Delete Thr",{MC_DELTHREAD,1,{ctrl('D')}},KS_NONE},
+! {"^U","Undel Thre",{MC_UNDTHREAD,1,{ctrl('U')}},KS_NONE},
+! {"^T","selcT Thre",{MC_SELTHREAD,1,{ctrl('T')}},KS_NONE},
+! {"^H","ChkIncFl",{MC_FORCECHECK,1,{ctrl('H')}},KS_NONE},
+ NULL_MENU};
+ INST_KEY_MENU(view_keymenu, view_keys);
+ #define VIEW_ATT_KEY 3
+***************
+*** 268,274 ****
+ {"S", "Save", {MC_SAVETEXT,1,{'s'}}, KS_SAVE}};
+ INST_KEY_MENU(simple_text_keymenu, simple_text_keys);
+
+!
+
+
+ /*
+--- 278,289 ----
+ {"S", "Save", {MC_SAVETEXT,1,{'s'}}, KS_SAVE}};
+ INST_KEY_MENU(simple_text_keymenu, simple_text_keys);
+
+! static char *prefix;
+! #define NO_FLOWED 0x0000
+! #define IS_FLOWED 0x0001
+! #define DELETEQUO 0x0010
+! #define COLORAQUO 0x0100
+! #define RAWSTRING 0x1000
+
+
+ /*
+***************
+*** 362,367 ****
+--- 377,392 ----
+ void embed_color PROTO((COLOR_PAIR *, gf_io_t));
+ int color_a_quote PROTO((long, char *, LT_INS_S **, void *));
+ int color_signature PROTO((long, char *, LT_INS_S **, void *));
++ IVAL_S *copy_ival PROTO((IVAL_S *));
++ IVAL_S * compute_interval PROTO((char *, char *, int));
++ void remove_spaces_ival PROTO((IVAL_S **, char *));
++ void interval_free PROTO((IVAL_S **));
++ char * regex_pattern PROTO((char **));
++ LT_INS_S ** insert_color_special_text PROTO((LT_INS_S **, char **, IVAL_S *,
++ int, COLOR_PAIR *));
++ int any_color_in_string PROTO((char *));
++ int length_color PROTO((char *, int));
++ int color_this_text PROTO((long, char *, LT_INS_S **, void *));
+ int color_headers PROTO((long, char *, LT_INS_S **, void *));
+ int url_hilite_hdr PROTO((long, char *, LT_INS_S **, void *));
+ int url_launch PROTO((HANDLE_S *));
+***************
+*** 386,391 ****
+--- 411,418 ----
+ int pcpine_resize_scroll PROTO((void));
+ int pcpine_view_cursor PROTO((int, long));
+ #endif
++ int is_word PROTO((char [], int, int));
++ int is_mailbox PROTO((char [], int, int));
+
+
+
+***************
+*** 420,425 ****
+--- 447,453 ----
+ HANDLE_S *handles = NULL;
+ SCROLL_S scrollargs;
+ SourceType src = CharStar;
++ FOLDER_S *f = NULL;
+
+ dprint(1, (debugfile, "\n\n ----- MAIL VIEW -----\n"));
+
+***************
+*** 473,478 ****
+--- 501,517 ----
+ else
+ ps->unseen_in_view = !mc->seen;
+
++ prefix = reply_quote_str(env);
++ /* Make sure the prefix is not only made of spaces, so that we do not
++ * paint the screen incorrectly
++ */
++ if (prefix && *prefix){
++ int i;
++ for (i = 0; isspace((unsigned char) prefix[i]); i++);
++ if (i == strlen(prefix))
++ fs_give((void **)&prefix);
++ }
++
+ #if defined(DOS) && !defined(WIN32)
+ /*
+ * Handle big text for DOS here.
+***************
+*** 634,639 ****
+--- 673,680 ----
+ }
+ while(ps->next_screen == SCREEN_FUN_NULL);
+
++ if (prefix && *prefix)
++ fs_give((void **)&prefix);
+ if(we_cancel)
+ cancel_busy_alarm(-1);
+
+***************
+*** 1590,1595 ****
+--- 1631,1644 ----
+ if((flgs & FM_DISPLAY)
+ && !(flgs & FM_NOCOLOR)
+ && pico_usingcolor()
++ && ps_global->VAR_SPECIAL_TEXT_FORE_COLOR
++ && ps_global->VAR_SPECIAL_TEXT_BACK_COLOR){
++ gf_link_filter(gf_line_test, gf_line_test_opt(color_this_text, NULL));
++ }
++
++ if((flgs & FM_DISPLAY)
++ && !(flgs & FM_NOCOLOR)
++ && pico_usingcolor()
+ && ps_global->VAR_SIGNATURE_FORE_COLOR
+ && ps_global->VAR_SIGNATURE_BACK_COLOR){
+ gf_link_filter(gf_line_test, gf_line_test_opt(color_signature, &is_in_sig));
+***************
+*** 1600,1607 ****
+ && pico_usingcolor()
+ && ps_global->VAR_QUOTE1_FORE_COLOR
+ && ps_global->VAR_QUOTE1_BACK_COLOR){
+! gf_link_filter(gf_line_test, gf_line_test_opt(color_a_quote, NULL));
+ }
+
+ wrapflags = (flgs & FM_DISPLAY) ? GFW_HANDLES : 0;
+ if(flgs & FM_DISPLAY
+--- 1649,1658 ----
+ && pico_usingcolor()
+ && ps_global->VAR_QUOTE1_FORE_COLOR
+ && ps_global->VAR_QUOTE1_BACK_COLOR){
+! gf_link_filter(gf_quote_test,gf_line_test_opt(color_a_quote, NULL));
+ }
++ else
++ gf_link_filter(gf_quote_test,gf_line_test_opt(select_quote, NULL));
+
+ wrapflags = (flgs & FM_DISPLAY) ? GFW_HANDLES : 0;
+ if(flgs & FM_DISPLAY
+***************
+*** 2691,2696 ****
+--- 2742,2749 ----
+ {0, 'a', "A", "editApp"},
+ {-1, 0, NULL, NULL}};
+
++ if (role_chosen)
++ free_action(&role_chosen);
+ if(handle->type == URL){
+ launch_opts[4].ch = 'u';
+
+***************
+*** 2801,2811 ****
+ * sense if you just say View selected URL ...
+ */
+ if(handle->type == URL &&
+! !struncmp(handle->h.url.path, "mailto:", 7))
+! sprintf(prompt, "Compose mail to \"%.*s%s\" ? ",
+! min(max(0,sc - 25), sizeof(prompt)-50), handle->h.url.path+7,
+! (strlen(handle->h.url.path+7) > max(0,sc-25)) ? "..." : "");
+! else
+ sprintf(prompt, "View selected %s %s%.*s%s ? ",
+ (handle->type == URL) ? "URL" : "Attachment",
+ (handle->type == URL) ? "\"" : "",
+--- 2854,2894 ----
+ * sense if you just say View selected URL ...
+ */
+ if(handle->type == URL &&
+! !struncmp(handle->h.url.path, "mailto:", 7)){
+! int rolenick = role_chosen ? strlen(role_chosen->nick) : 0;
+! int offset = 25 + (role_chosen ? 20 : 0);
+! int offset2 = max(0, sc - offset) - strlen(handle->h.url.path+7);
+! int offset3 = sc - strlen(handle->h.url.path+7) - rolenick - offset;
+! int laddress = min(max(0,sc - offset), sizeof(prompt)-50);
+! int lrole = rolenick;
+!
+! if (offset3 < 0){
+! lrole = rolenick;
+! laddress = sc - offset - lrole;
+! offset3 = laddress - 20; /* redefine offset3 */
+! if (offset3 < 0){
+! laddress = 20;
+! lrole = sc - offset - laddress;
+! }
+! }
+! launch_opts[2].ch = 'r';
+! launch_opts[2].rval = 'r';
+! launch_opts[2].name = "R";
+! launch_opts[2].label = "Set Role";
+! sprintf(prompt, "Compose mail to \"%.*s%s\" %s%.*s%s%s? ",
+! laddress, handle->h.url.path+7,
+! offset2 < 0 ? "..." : "",
+! role_chosen ? "using role \"" : "",
+! role_chosen ? lrole : 0,
+! role_chosen ? role_chosen->nick : "",
+! role_chosen ? (rolenick > lrole ? "..." : "") : "",
+! role_chosen ? "\" " : "");
+! }
+! else{
+! launch_opts[2].ch = -2;
+! launch_opts[2].rval = 0;
+! launch_opts[2].name = NULL;
+! launch_opts[2].label = NULL;
+ sprintf(prompt, "View selected %s %s%.*s%s ? ",
+ (handle->type == URL) ? "URL" : "Attachment",
+ (handle->type == URL) ? "\"" : "",
+***************
+*** 2814,2825 ****
+--- 2897,2931 ----
+ (handle->type == URL)
+ ? ((strlen(handle->h.url.path) > max(0,sc-27))
+ ? "...\"" : "\"") : "");
++ }
+
+ switch(radio_buttons(prompt, -FOOTER_ROWS(ps_global),
+ launch_opts, 'y', 'n', NO_HELP, RB_SEQ_SENSITIVE)){
+ case 'y' :
+ return(1);
+
++ case 'r':
++ {
++ void (*prev_screen)() = ps_global->prev_screen,
++ (*redraw)() = ps_global->redrawer;
++ ps_global->redrawer = NULL;
++ ps_global->next_screen = SCREEN_FUN_NULL;
++ if(role_select_screen(ps_global, &role_chosen, 1) < 0){
++ cmd_cancelled("Compose");
++ ps_global->next_screen = prev_screen;
++ ps_global->redrawer = redraw;
++ if(ps_global->redrawer)
++ (*ps_global->redrawer)();
++ return 0;
++ }
++ ps_global->next_screen = prev_screen;
++ ps_global->redrawer = redraw;
++ if(role_chosen)
++ role_chosen = combine_inherited_role(role_chosen);
++ if(ps_global->redrawer)
++ (*ps_global->redrawer)();
++ }
++
+ case 'u' :
+ strncpy(tmp, handle->h.url.path, sizeof(tmp)-1);
+ tmp[sizeof(tmp)-1] = '\0';
+***************
+*** 3481,3486 ****
+--- 3587,3621 ----
+ return(buf);
+ }
+
++ #define is_digit(c) ((((c) >= '0') && ((c) <= '9')) ? 1 : 0)
++
++ #define is_letter(c) (((c) >= 'a' && (c) <= 'z') || \
++ ((c) >= 'A' && (c) <= 'Z'))
++
++ #define next(w,i) ((((w)[(i)]) != 0) ? ((w)[(i) + 1]) : 0)
++
++ #define single_level(c) (((c) == '>') || ((c) == '|') || ((c) == '~') || \
++ ((c) == ']'))
++
++ int
++ is_word (buf, i, j)
++ char buf[NSTRING];
++ int i;
++ int j;
++ {
++ return i <= j && is_letter(buf[i]) ?
++ (i < j ? is_word(buf,i+1,j) : 1) : 0;
++ }
++
++ int
++ is_mailbox(buf,i,j)
++ char buf[NSTRING];
++ int i;
++ int j;
++ {
++ return i <= j && (is_letter(buf[i]) || is_digit(buf[i]) || buf[i] == '.')
++ ? (i < j ? is_mailbox(buf,i+1,j) : 1) : 0;
++ }
+
+ int
+ colorcmp(color1, color2)
+***************
+*** 3503,3508 ****
+--- 3638,3710 ----
+ struct quote_colors *next;
+ };
+
++
++ int
++ next_level_quote(buf, line, i, is_flowed)
++ char *buf;
++ char **line;
++ int i;
++ int is_flowed;
++ {
++ int j;
++
++ if (!single_level(buf[i])){
++ if(is_mailbox(buf,i,i)){
++ for (j = i; buf[j] && !isspace(buf[j]); j++);
++ if (is_word(buf,i,j-1) || is_mailbox(buf,i,j-1))
++ j += isspace(buf[j]) ? 2 : 1;
++ }
++ else{
++ switch(buf[i]){
++ case ':' :
++ if (next(buf,i) != RPAREN)
++ j = i + 1;
++ else
++ j = i + 2;
++ break;
++
++ case '-' :
++ if (next(buf,i) != '-')
++ j = i + 2;
++ else
++ j = i + 3;
++ break;
++
++ case '+' :
++ case '*' :
++ if (next(buf,i) != ' ')
++ j = i + 2;
++ else
++ j = i + 3;
++ break;
++
++ default :
++ for (j = i; buf[j] && !isspace(buf[j])
++ && (!single_level(buf[i]) && !is_letter(buf[j])); j++);
++ j += isspace(buf[j]) ? 1 : 0;
++ break;
++ }
++ }
++ if (line && *line)
++ (*line) += j - i;
++ }
++ else{
++ j = i+1;
++ if (line && *line)
++ (*line)++;
++ }
++ if(!is_flowed){
++ if(line && *line)
++ for(; isspace((unsigned char)*(*line)); (*line)++);
++ for (i = j; isspace((unsigned char) buf[i]); i++);
++ }
++ else i = j;
++ if (is_flowed && i != j)
++ buf[i] = '\0';
++ return i;
++ }
++
++
+ int
+ color_a_quote(linenum, line, ins, is_flowed_msg)
+ long linenum;
+***************
+*** 3510,3528 ****
+ LT_INS_S **ins;
+ void *is_flowed_msg;
+ {
+! int countem = 0;
+ struct variable *vars = ps_global->vars;
+ char *p;
+ struct quote_colors *colors = NULL, *cp, *next;
+ COLOR_PAIR *col = NULL;
+ int is_flowed = is_flowed_msg ? *((int *)is_flowed_msg) : 0;
+
+ p = line;
+! if(!is_flowed)
+! while(isspace((unsigned char)*p))
+! p++;
+
+! if(p[0] == '>'){
+ struct quote_colors *c;
+
+ /*
+--- 3712,3736 ----
+ LT_INS_S **ins;
+ void *is_flowed_msg;
+ {
+! int countem = 0, i, j = 0;
+ struct variable *vars = ps_global->vars;
+ char *p;
++ char buf[NSTRING] = {'\0'};
+ struct quote_colors *colors = NULL, *cp, *next;
+ COLOR_PAIR *col = NULL;
++ int code;
+ int is_flowed = is_flowed_msg ? *((int *)is_flowed_msg) : 0;
+
++ code = (is_flowed ? IS_FLOWED : NO_FLOWED) | COLORAQUO;
++ select_quote(linenum, line, ins, (void *)code);
++ for (i = 0; tmp_20k_buf[i] && (buf[i] = tmp_20k_buf[i]); i++);
++ buf[i] = '\0';
++
+ p = line;
+! for(i = 0; isspace((unsigned char)buf[i]); i++)
+! p++; /*(i = is_flowed ? (buf[j] ? j : 0): j);*/
+
+! if(buf[i]){
+ struct quote_colors *c;
+
+ /*
+***************
+*** 3571,3577 ****
+ free_color_pair(&col);
+
+ cp = NULL;
+! while(*p == '>'){
+ cp = (cp && cp->next) ? cp->next : colors;
+
+ if(countem > 0)
+--- 3779,3785 ----
+ free_color_pair(&col);
+
+ cp = NULL;
+! while(buf[i]){
+ cp = (cp && cp->next) ? cp->next : colors;
+
+ if(countem > 0)
+***************
+*** 3581,3590 ****
+
+ countem = (countem == 1) ? 0 : countem;
+
+! p++;
+! if(!is_flowed)
+! for(; isspace((unsigned char)*p); p++)
+! ;
+ }
+
+ if(colors){
+--- 3789,3797 ----
+
+ countem = (countem == 1) ? 0 : countem;
+
+! i = next_level_quote(buf, &p, i, is_flowed);
+! for (; isspace((unsigned char)*p); p++);
+! for (; isspace((unsigned char)buf[i]); i++);
+ }
+
+ if(colors){
+***************
+*** 3648,3653 ****
+--- 3855,3919 ----
+ return(0);
+ }
+
++ /* This filter gives a quote string of a line. It sends its reply back to the
++ calling filter in the tmp_20k_buf variable. This filter replies with
++ the full quote string including tailing spaces if any. It is the
++ responsibility of the calling filter to figure out if thos spaces are
++ useful for that filter or if they should be removed before doing any
++ useful work. For example, color_a_quote does not require the trailing
++ spaces, but gf_wrap does.
++ */
++ int
++ select_quote(linenum, line, ins, code)
++ long linenum;
++ char *line;
++ LT_INS_S **ins;
++ void *code;
++ {
++ int i;
++ char buf[NSTRING] = {'\0'};
++ char GLine[NSTRING] = {'\0'};
++ char PLine[NSTRING] = {'\0'};
++ char NLine[NSTRING] = {'\0'};
++ static char GLine1[NSTRING] = {'\0'};
++ static char PLine1[NSTRING] = {'\0'};
++ static char GLine2[NSTRING] = {'\0'};
++ static char PLine2[NSTRING] = {'\0'};
++ QSTRING_S *qs;
++ int buflen = NSTRING < SIZEOF_20KBUF ? NSTRING - 1: SIZEOF_20KBUF - 1;
++ int who = ((int) code) & COLORAQUO; /* may I ask who is calling? */
++ int raw = ((int) code) & RAWSTRING; /* return raw string */
++
++ strncpy(GLine, who ? GLine1 : GLine2, buflen);
++ strncpy(PLine, who ? PLine1 : PLine2, buflen);
++
++ if (linenum != 0)
++ strncpy(PLine, GLine, buflen);
++
++ strncpy(NLine, tmp_20k_buf, buflen);
++
++ if (line)
++ strncpy(GLine, line, buflen);
++ else
++ GLine[0] = '\0';
++
++ qs = do_quote_match(prefix && *prefix ? prefix : ">",
++ GLine, NLine, PLine, raw);
++ flatten_qstring(qs, buf);
++ free_qs(&qs);
++ /* do not paint an extra level for a line with a >From string at the
++ * begining of it
++ */
++ if (buf[0]){
++ i = strlen(buf);
++ if (strlen(line) >= i + 6 && !strncmp(line+i-1,">From ", 6))
++ buf[i - 1] = '\0';
++ }
++ strncpy(tmp_20k_buf, buf, buflen);
++ strncpy((who ? GLine1 : GLine2), GLine, buflen);
++ strncpy((who ? PLine1 : PLine2), PLine, buflen);
++ return -1;
++ }
+
+ /*
+ * Paint the signature.
+***************
+*** 3660,3686 ****
+ void *is_in_sig;
+ {
+ struct variable *vars = ps_global->vars;
+! int *in_sig_block;
+ COLOR_PAIR *col = NULL;
+
+ if(is_in_sig == NULL)
+ return 0;
+
+ in_sig_block = (int *) is_in_sig;
+!
+! if(!strcmp(line, SIGDASHES))
+! *in_sig_block = START_SIG_BLOCK;
+! else if(*line == '\0')
+ /*
+ * Suggested by Eduardo: allow for a blank line right after
+ * the sigdashes.
+ */
+ *in_sig_block = (*in_sig_block == START_SIG_BLOCK)
+ ? IN_SIG_BLOCK : OUT_SIG_BLOCK;
+ else
+! *in_sig_block = (*in_sig_block != OUT_SIG_BLOCK)
+ ? IN_SIG_BLOCK : OUT_SIG_BLOCK;
+
+ if(*in_sig_block != OUT_SIG_BLOCK
+ && VAR_SIGNATURE_FORE_COLOR && VAR_SIGNATURE_BACK_COLOR
+ && (col = new_color_pair(VAR_SIGNATURE_FORE_COLOR,
+--- 3926,4005 ----
+ void *is_in_sig;
+ {
+ struct variable *vars = ps_global->vars;
+! int *in_sig_block, i, j,same_qstr = 0;
+ COLOR_PAIR *col = NULL;
++ static char GLine[NSTRING] = {'\0'};
++ static char PLine[NSTRING] = {'\0'};
++ char NLine[NSTRING] = {'\0'};
++ static char *buf, buf2[NSTRING] = {'\0'};
++ QSTRING_S *qs;
++ static qstrlen = 0;
+
+ if(is_in_sig == NULL)
+ return 0;
+
++ if (linenum != 0){
++ for (i = 0; GLine[i] && (PLine[i] = GLine[i]); i++);
++ PLine[i] = '\0';
++ }
++
++ for (i = 0; tmp_20k_buf[i] && (tmp_20k_buf[i] != '\015') && (i < NSTRING)
++ && (i < SIZEOF_20KBUF)
++ && (NLine[i] = tmp_20k_buf[i]); i++);
++ NLine[i] = '\0';
++
++ for (i = 0; (i < NSTRING) && ((GLine[i] = line[i]) != 0); i++);
++ GLine[NSTRING - 1] = '\0';
++ qs = do_quote_match(prefix && *prefix ? prefix : ">",
++ GLine, NLine, PLine, 1);
++ flatten_qstring(qs, buf2);
++ i = buf2 && buf2[0] ? strlen(buf2) : 0;
++ free_qs(&qs);
++
++ /* determine if buf and buf2 are the same quote string */
++ if (!struncmp(buf, buf2, qstrlen)){
++ for (j = qstrlen; buf2[j] && isspace((unsigned char)buf2[j]); j++);
++ if (!buf2[j] || buf2[j] == '|' || (buf2[j] == '*' && buf2[j+1] != '>'))
++ same_qstr++;
++ }
++
+ in_sig_block = (int *) is_in_sig;
+!
+! if (*in_sig_block != OUT_SIG_BLOCK){
+! if (line && *line && (strlen(line) >= qstrlen) && same_qstr)
+! line += qstrlen;
+! else if (strlen(line) < qstrlen)
+! line += i;
+! else if (!same_qstr)
+! *in_sig_block = OUT_SIG_BLOCK;
+! }
+! else
+! line += i;
+!
+! if(!strcmp(line, SIGDASHES) || !strcmp(line, "--")){
+! *in_sig_block = START_SIG_BLOCK;
+! buf = (char *) fs_get((i + 1)*sizeof(char));
+! buf = cpystr(buf2);
+! qstrlen = i;
+! }
+! else if(*line == '\0'){
+ /*
+ * Suggested by Eduardo: allow for a blank line right after
+ * the sigdashes.
+ */
+ *in_sig_block = (*in_sig_block == START_SIG_BLOCK)
+ ? IN_SIG_BLOCK : OUT_SIG_BLOCK;
++ }
+ else
+! *in_sig_block = (*in_sig_block != OUT_SIG_BLOCK)
+ ? IN_SIG_BLOCK : OUT_SIG_BLOCK;
+
++ if (*in_sig_block == OUT_SIG_BLOCK){
++ qstrlen = 0; /* reset back in case there's another paragraph */
++ if (buf)
++ fs_give((void **)&buf);
++ }
++
+ if(*in_sig_block != OUT_SIG_BLOCK
+ && VAR_SIGNATURE_FORE_COLOR && VAR_SIGNATURE_BACK_COLOR
+ && (col = new_color_pair(VAR_SIGNATURE_FORE_COLOR,
+***************
+*** 3751,3756 ****
+--- 4070,4316 ----
+ return 0;
+ }
+
++ IVAL_S *
++ copy_ival(ival)
++ IVAL_S *ival;
++ {
++ IVAL_S *cp;
++
++ if (!ival)
++ return (IVAL_S *)NULL;
++
++ cp = (IVAL_S *) malloc (sizeof(IVAL_S));
++ memset (cp, 0, sizeof(IVAL_S));
++
++ cp->start = ival->start;
++ cp->end = ival->end;
++ cp->next = copy_ival(ival->next);
++ return cp;
++ }
++
++ void
++ interval_free(ival)
++ IVAL_S **ival;
++ {
++ if (!(*ival))
++ return;
++
++ if ((*ival)->next)
++ interval_free(&((*ival)->next));
++
++ (*ival)->next = (IVAL_S *) NULL;
++
++ free((void *)(*ival));
++ *ival = (IVAL_S *) NULL;
++ }
++
++ IVAL_S *
++ compute_interval (string, pattern, endm)
++ char *string;
++ char *pattern;
++ int endm;
++ {
++ IVAL_S *ival = NULL, *nextival= NULL;
++ int error, sizerror;
++ regex_t preg;
++ regmatch_t pmatch;
++
++ if (error = regcomp(&preg, pattern, REG_EXTENDED)){
++ /* char message[REGERROR];
++ sizerror = regerror(error, &preg, message, REGERROR);
++ printf("%s\n", message);*/
++ regfree(&preg);
++ return (IVAL_S *) NULL;
++ }
++ else{
++ if (((error = regexec(&preg, string, 1, &pmatch, 0)) != REG_NOMATCH)
++ && !error){
++ ival = (IVAL_S *) malloc(sizeof(IVAL_S));
++ memset (ival, 0, sizeof(IVAL_S));
++ ival->start = endm + pmatch.rm_so;
++ ival->end = endm + pmatch.rm_eo;
++ nextival = compute_interval(string+pmatch.rm_so+1, pattern, ival->start+1);
++ if (nextival){
++ if (nextival->start <= ival->end){
++ ival->end = nextival->end;
++ ival->next = copy_ival(nextival->next);
++ interval_free(&nextival);
++ }
++ else
++ ival->next = nextival;
++ }
++ }
++ }
++ regfree(&preg);
++ return ival;
++ }
++
++ char *
++ regex_pattern(plist)
++ char **plist;
++ {
++ int i = 0, j = 0, k = 0, n = 0, len = 0;
++ char *pattern = NULL;
++
++ if(plist && plist[0] && plist[0][0]){
++ for (i = 0; plist[i] && plist[i][0]; i++)
++ len += strlen(plist[i]) + 1;
++ pattern = (char *) fs_get(len * sizeof(char));
++ for (j = 0; j < i; j++){
++ for(k = 0; plist[j][k]; k++)
++ pattern[n++] = plist[j][k];
++ pattern[n++] = (j == i - 1) ? '\0' : '|';
++ }
++ }
++ return pattern;
++ }
++
++ LT_INS_S **
++ insert_color_special_text(ins, p, ival, last_end, col)
++ LT_INS_S **ins;
++ char **p;
++ IVAL_S *ival;
++ int last_end;
++ COLOR_PAIR *col;
++ {
++ struct variable *vars = ps_global->vars;
++
++ if (ival){
++ *p += ival->start - last_end;
++ ins = gf_line_test_new_ins(ins, *p, color_embed(col->fg, col->bg),
++ (2 * RGBLEN) + 4);
++ *p += ival->end - ival->start;
++ ins = gf_line_test_new_ins(ins, *p, color_embed(VAR_NORM_FORE_COLOR,
++ VAR_NORM_BACK_COLOR), (2 * RGBLEN) + 4);
++ ins = insert_color_special_text(ins, p, ival->next, ival->end, col);
++ }
++ return ins;
++ }
++
++ int
++ length_color(p, begin_color)
++ char *p;
++ int begin_color;
++ {
++ int len = 0, done = begin_color ? 0 : -1;
++ char *orig = p;
++
++ while (*p && done <= 0){
++ switch(*p++){
++ case TAG_HANDLE :
++ p += *p + 1;
++ done++;
++ break;
++
++ case TAG_FGCOLOR :
++ case TAG_BGCOLOR :
++ p += RGBLEN;
++ if (!begin_color)
++ done++;
++ break;
++
++ default :
++ break;
++ }
++ }
++ len = p - orig;
++ return len;
++ }
++
++ int
++ any_color_in_string(p)
++ char *p;
++ {
++ int rv = 0;
++ char *orig = p;
++ while (*p && !rv)
++ if (*p++ == TAG_EMBED)
++ rv = p - orig;
++ return rv;
++ }
++
++ void
++ remove_spaces_ival(ivalp, p)
++ IVAL_S **ivalp;
++ char *p;
++ {
++ IVAL_S *ival;
++ int i;
++ if (!ivalp || !*ivalp)
++ return;
++ ival = *ivalp;
++ for (i = 0; isspace((unsigned char) p[ival->start + i]); i++);
++ if (ival->start + i < ival->end) /* do not do this if match only spaces */
++ ival->start += i;
++ else
++ return;
++ for (i = 0; isspace((unsigned char) p[ival->end - i - 1]); i++);
++ ival->end -= i;
++ if (ival->next)
++ remove_spaces_ival(&(ival->next), p);
++ }
++
++ int
++ color_this_text(linenum, line, ins, local)
++ long linenum;
++ char *line;
++ LT_INS_S **ins;
++ void *local;
++ {
++ struct variable *vars = ps_global->vars;
++ COLOR_PAIR *col = NULL;
++ char *p;
++ int i;
++ static char *pattern = NULL;
++
++ select_quote(linenum, line, ins, NULL);
++ p = line + strlen(tmp_20k_buf);
++
++ if(VAR_SPECIAL_TEXT_FORE_COLOR && VAR_SPECIAL_TEXT_BACK_COLOR
++ && (col = new_color_pair(VAR_SPECIAL_TEXT_FORE_COLOR,
++ VAR_SPECIAL_TEXT_BACK_COLOR))
++ && !pico_is_good_colorpair(col))
++ free_color_pair(&col);
++
++ if (linenum == 0){
++ if (pattern)
++ fs_give((void **)&pattern);
++ pattern = regex_pattern(ps_global->VAR_SPECIAL_TEXT);
++ }
++
++ if(pattern && col){
++ IVAL_S *ival;
++ int done = 0, begin_color = 0;
++
++ while (!done){
++ if (i = any_color_in_string(p)){
++ begin_color = (begin_color + 1) % 2;
++ if (begin_color){
++ p[i - 1] = '\0';
++ ival = compute_interval(p, pattern, 0);
++ remove_spaces_ival(&ival, p);
++ p[i - 1] = TAG_EMBED;
++ ins = insert_color_special_text(ins, &p, ival, 0, col);
++ }
++ for (;*p++ != TAG_EMBED; );
++ p += length_color(p, begin_color);
++ }
++ else{
++ ival = compute_interval(p, pattern, 0);
++ remove_spaces_ival(&ival, p);
++ ins = insert_color_special_text(ins, &p, ival, 0, col);
++ done++;
++ }
++ interval_free(&ival);
++ if (!*p)
++ done++;
++ }
++ free_color_pair(&col);
++ }
++
++ return 0;
++ }
++
+
+ /*
+ * Replace quotes of nonflowed messages. This needs to happen
+***************
+*** 3843,3849 ****
+ {
+ DELQ_S *dq;
+ char *lp;
+! int i, lines, not_a_quote = 0;
+ size_t len;
+
+ dq = (DELQ_S *) local;
+--- 4403,4409 ----
+ {
+ DELQ_S *dq;
+ char *lp;
+! int i, lines, not_a_quote = 0, code, feedback;
+ size_t len;
+
+ dq = (DELQ_S *) local;
+***************
+*** 3853,3858 ****
+--- 4413,4419 ----
+ if(dq->lines > 0 || dq->lines == Q_DEL_ALL){
+
+ lines = (dq->lines == Q_DEL_ALL) ? 0 : dq->lines;
++ feedback = (dq->lines == Q_DEL_ALL) ? 0 : 1;
+
+ /*
+ * First determine if this line is part of a quote.
+***************
+*** 3863,3868 ****
+--- 4424,4432 ----
+ for(i = dq->indent_length; i > 0 && !not_a_quote && *lp; i--)
+ if(*lp++ != SPACE)
+ not_a_quote++;
++
++ while(isspace((unsigned char) *lp))
++ lp++;
+
+ /* skip over leading tags */
+ while(!not_a_quote
+***************
+*** 3902,3918 ****
+ }
+ }
+
+! /* skip over whitespace */
+! if(!dq->is_flowed)
+! while(isspace((unsigned char) *lp))
+! lp++;
+!
+! /* check first character to see if it is a quote */
+! if(!not_a_quote && *lp != '>')
+! not_a_quote++;
+
+ if(not_a_quote){
+! if(dq->in_quote > lines+1){
+ char tmp[500];
+
+ /*
+--- 4466,4481 ----
+ }
+ }
+
+! code = (dq->is_flowed ? IS_FLOWED : NO_FLOWED) | DELETEQUO;
+! len = lp - line;
+! if(strlen(tmp_20k_buf) > len)
+! strcpy(tmp_20k_buf, tmp_20k_buf+len);
+! select_quote(linenum, lp, ins, (void *) code);
+! if (!not_a_quote && !tmp_20k_buf[0])
+! not_a_quote++;
+
+ if(not_a_quote){
+! if(dq->in_quote > lines+1 && feedback){
+ char tmp[500];
+
+ /*
+***************
+*** 5017,5023 ****
+ fs_give((void **) &urlp);
+
+ rflags = ROLE_COMPOSE;
+! if(nonempty_patterns(rflags, &dummy)){
+ role = set_role_from_msg(ps_global, rflags, -1L, NULL);
+ if(confirm_role(rflags, &role))
+ role = combine_inherited_role(role);
+--- 5580,5586 ----
+ fs_give((void **) &urlp);
+
+ rflags = ROLE_COMPOSE;
+! if(!(role = copy_action(role_chosen)) && nonempty_patterns(rflags, &dummy)){
+ role = set_role_from_msg(ps_global, rflags, -1L, NULL);
+ if(confirm_role(rflags, &role))
+ role = combine_inherited_role(role);
+***************
+*** 5093,5098 ****
+--- 5656,5662 ----
+
+ free_redraft_pos(&redraft_pos);
+ free_action(&role);
++ free_action(&role_chosen);
+
+ return(rv);
+ }
+***************
+*** 5665,5671 ****
+ char *err, *charset;
+ int filtcnt = 0, error_found = 0, column, wrapit;
+ int is_in_sig = OUT_SIG_BLOCK;
+! int is_flowed_msg = 0;
+ int is_delsp_yes = 0;
+ int filt_only_c0 = 0;
+ char *parmval;
+--- 6229,6235 ----
+ char *err, *charset;
+ int filtcnt = 0, error_found = 0, column, wrapit;
+ int is_in_sig = OUT_SIG_BLOCK;
+! int is_flowed_msg = 0, add_me = 1;
+ int is_delsp_yes = 0;
+ int filt_only_c0 = 0;
+ char *parmval;
+***************
+*** 5767,5772 ****
+--- 6331,6345 ----
+ filters[filtcnt++].data = gf_line_test_opt(url_hilite, handlesp);
+ }
+
++ if((flags & FM_DISPLAY)
++ && !(flags & FM_NOCOLOR)
++ && pico_usingcolor()
++ && VAR_SPECIAL_TEXT_FORE_COLOR
++ && VAR_SPECIAL_TEXT_BACK_COLOR){
++ filters[filtcnt].filter = gf_line_test;
++ filters[filtcnt++].data = gf_line_test_opt(color_this_text, NULL);
++ }
++
+ /*
+ * First, paint the signature.
+ * Disclaimers noted below for coloring quotes apply here as well.
+***************
+*** 5794,5802 ****
+ && pico_usingcolor()
+ && VAR_QUOTE1_FORE_COLOR
+ && VAR_QUOTE1_BACK_COLOR){
+! filters[filtcnt].filter = gf_line_test;
+! filters[filtcnt++].data = gf_line_test_opt(color_a_quote,
+! &is_flowed_msg);
+ }
+ }
+ else if(!strucmp(att->body->subtype, "richtext")){
+--- 6367,6375 ----
+ && pico_usingcolor()
+ && VAR_QUOTE1_FORE_COLOR
+ && VAR_QUOTE1_BACK_COLOR){
+! add_me = 0;
+! filters[filtcnt].filter = gf_quote_test;
+! filters[filtcnt++].data = gf_line_test_opt(color_a_quote, &is_flowed_msg);
+ }
+ }
+ else if(!strucmp(att->body->subtype, "richtext")){
+***************
+*** 5866,5871 ****
+--- 6439,6450 ----
+ }
+ }
+
++ if (add_me){
++ filters[filtcnt].filter = gf_quote_test;
++ filters[filtcnt++].data = gf_line_test_opt(select_quote,
++ (void *) RAWSTRING);
++ }
++
+ if(wrapit && !(flags & FM_NOWRAP)){
+ int margin = 0, wrapflags = (flags & FM_DISPLAY) ? GFW_HANDLES : 0;
+
+***************
+*** 5913,5919 ****
+ dq.saved_line = &free_this;
+ dq.handlesp = handlesp;
+
+! filters[filtcnt].filter = gf_line_test;
+ filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
+ }
+
+--- 6492,6498 ----
+ dq.saved_line = &free_this;
+ dq.handlesp = handlesp;
+
+! filters[filtcnt].filter = gf_quote_test;
+ filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
+ }
+
+***************
+*** 6453,6460 ****
+ format_addr_string(s, n, sect, "Return-Path: ", e->return_path,
+ flags, pc);
+
+! if((which & FE_NEWSGROUPS) && e->newsgroups)
+ format_newsgroup_string("Newsgroups: ", e->newsgroups, flags, pc);
+
+ if((which & FE_FOLLOWUPTO) && e->followup_to)
+ format_newsgroup_string("Followup-To: ", e->followup_to, flags, pc);
+--- 7032,7051 ----
+ format_addr_string(s, n, sect, "Return-Path: ", e->return_path,
+ flags, pc);
+
+! if((which & FE_NEWSGROUPS) && e->newsgroups){
+! int bogus = NIL;
+ format_newsgroup_string("Newsgroups: ", e->newsgroups, flags, pc);
++ if (!e->ngpathexists && e->message_id &&
++ strncmp (e->message_id,"<Pine.",6) &&
++ strncmp (e->message_id,"<MS-C.",6) &&
++ strncmp (e->message_id,"<MailManager.",13) &&
++ strncmp (e->message_id,"<EasyMail.",11) &&
++ strncmp (e->message_id,"<ML-",4)) bogus = T;
++
++ if(bogus)
++ q_status_message(SM_ORDER, 0, 3,
++ "Unverified Newsgroup header -- Message MAY or MAY NOT have been posted");
++ }
+
+ if((which & FE_FOLLOWUPTO) && e->followup_to)
+ format_newsgroup_string("Followup-To: ", e->followup_to, flags, pc);
+***************
+*** 7189,7196 ****
+ {
+ register long cur_top_line, num_display_lines;
+ int result, done, ch, cmd, found_on, found_on_col,
+! first_view, force, scroll_lines, km_size,
+! cursor_row, cursor_col, km_popped;
+ long jn;
+ struct key_menu *km;
+ HANDLE_S *next_handle;
+--- 7780,7787 ----
+ {
+ register long cur_top_line, num_display_lines;
+ int result, done, ch, cmd, found_on, found_on_col,
+! first_view, force, scroll_lines, km_size, skip = 0,
+! cursor_row, cursor_col, km_popped, nm;
+ long jn;
+ struct key_menu *km;
+ HANDLE_S *next_handle;
+***************
+*** 7397,7403 ****
+
+ /*============ Check for New Mail and CheckPoint ============*/
+ if(!sparms->quell_newmail &&
+! new_mail(force, NM_TIMING(ch), NM_STATUS_MSG) >= 0){
+ update_scroll_titlebar(cur_top_line, 1);
+ if(ps_global->mangled_footer)
+ draw_keymenu(km, bitmap, ps_global->ttyo->screen_cols,
+--- 7988,7996 ----
+
+ /*============ Check for New Mail and CheckPoint ============*/
+ if(!sparms->quell_newmail &&
+! (nm = new_mail(force, NM_TIMING(ch), NM_STATUS_MSG)) >= 0){
+! skip = 0;
+! ps_global->force_check_now = nm > 0 ? 1 : 0;
+ update_scroll_titlebar(cur_top_line, 1);
+ if(ps_global->mangled_footer)
+ draw_keymenu(km, bitmap, ps_global->ttyo->screen_cols,
+***************
+*** 7405,7410 ****
+--- 7998,8015 ----
+
+ ps_global->mangled_footer = 0;
+ }
++ ps_global->in_pico = 0;
++
++ if (!skip)
++ new_mail_incfolder(ps_global, MC_IFAUTOCHECK);
++ skip = 0;
++ if (ps_global->refresh_list > 0){
++ ps_global->refresh_list = 0;
++ if (ps_global->in_fld_list){
++ cmd = MC_RESIZE;
++ goto end;
++ }
++ }
+
+ /*
+ * If an expunge of the current message happened during the
+***************
+*** 7539,7544 ****
+--- 8144,8150 ----
+ break;
+ }
+
++ ps_global->force_check_now = (((cmd == MC_NONE) || (cmd == MC_FORCECHECK)) ? 1 : 0);
+
+ /*============= Execute command =======================*/
+ switch(cmd){
+***************
+*** 8251,8256 ****
+--- 8857,8908 ----
+ print_to_printer(sparms);
+ break;
+
++ case MC_NEXTHREAD:
++ case MC_PRETHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL,
++ "to move to other thread"))
++ move_thread(ps_global, ps_global->mail_stream, ps_global->msgmap,
++ cmd == MC_NEXTHREAD ? 1 : -1);
++ done = 1;
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_DELTHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to delete"))
++ cmd_delete_thread(ps_global, ps_global->mail_stream, ps_global->msgmap);
++ done = 1;
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_UNDTHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to undelete"))
++ cmd_undelete_thread(ps_global, ps_global->mail_stream, ps_global->msgmap);
++ done = 1;
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
++
++ case MC_SELTHREAD:
++ if (THREADING()){
++ if (any_messages(ps_global->msgmap, NULL, "to undelete"))
++ cmd_select_thread(ps_global, ps_global->mail_stream, ps_global->msgmap);
++ done = 1;
++ }
++ else
++ q_status_message(SM_ORDER, 0, 1,
++ "Command available in threaded mode only");
++ break;
+
+ /* ------- First handle on Line ------ */
+ case MC_GOTOBOL :
+***************
+*** 8283,8289 ****
+--- 8935,8957 ----
+
+ break;
+
++ /*------- Check incoming folders -------*/
++ case MC_FORCECHECK:
++ ps_global->force_check_now = 1;
++ if (new_mail_incfolder(ps_global,MC_FORCECHECK) &&
++ ps_global->refresh_list > 0){
++ ps_global->refresh_list = 0;
++ if (ps_global->in_fld_list){
++ cmd = MC_RESIZE;
++ goto end;
++ }
++ }
++ break;
+
++ case MC_TAB:
++ skip++;
++ /* do not check for new mail in inc fldrs and fall through */
++
+ /*------- Standard commands ------*/
+ default:
+ whereis_pos.row = 0;
+***************
+*** 8355,8360 ****
+--- 9023,9029 ----
+
+ } /* End of while() -- loop executing commands */
+
++ end:
+ ps_global->redrawer = NULL; /* next statement makes this invalid! */
+ zero_scroll_text(); /* very important to zero out on return!!! */
+ scroll_state(SS_FREE);
+***************
+*** 8463,8470 ****
+--- 9132,9141 ----
+ char prompt[MAX_SEARCH+50], nsearch_string[MAX_SEARCH+1];
+ HelpType help;
+ int rc, flags;
++ static char last_search_string[MAX_SEARCH+1] = { '\0' };
+ static char search_string[MAX_SEARCH+1] = { '\0' };
+ static ESCKEY_S word_search_key[] = { { 0, 0, "", "" },
++ {ctrl('N'), 9, "^N", "Ins Pat"},
+ {ctrl('Y'), 10, "^Y", "First Line"},
+ {ctrl('V'), 11, "^V", "Last Line"},
+ {-1, 0, NULL, NULL}
+***************
+*** 8486,8491 ****
+--- 9157,9165 ----
+ help = help == NO_HELP ? h_oe_searchview : NO_HELP;
+ continue;
+ }
++ else if(rc == 9)
++ insert_pattern_in_string(nsearch_string, last_search_string,
++ MAX_SEARCH);
+ else if(rc == 10){
+ strcpy(report, "Searched to First Line.");
+ return(-4);
+***************
+*** 8495,8501 ****
+ return(-5);
+ }
+
+! if(rc != 4)
+ break;
+ }
+
+--- 9169,9175 ----
+ return(-5);
+ }
+
+! if(rc != 4 && rc != 9)
+ break;
+ }
+
+***************
+*** 8507,8512 ****
+--- 9181,9189 ----
+ search_string[sizeof(search_string)-1] = '\0';
+ }
+
++ strncpy(last_search_string, nsearch_string, sizeof(last_search_string));
++ last_search_string[sizeof(last_search_string)-1] = '\0';
++
+ rc = search_scroll_text(start_line, start_col, search_string, cursor_pos,
+ offset_in_line);
+ return(rc);
+diff -rc pine4.63/pine/newmail.c pine4.63.I.USE/pine/newmail.c
+*** pine4.63/pine/newmail.c Thu Jan 13 16:44:30 2005
+--- pine4.63.I.USE/pine/newmail.c Thu May 19 19:57:28 2005
+***************
+*** 48,53 ****
+--- 48,55 ----
+
+ #include "headers.h"
+
++ static long incoming_folders_new_mail = 0L;
++
+
+ /*
+ * Internal prototypes
+***************
+*** 701,706 ****
+--- 703,709 ----
+ "subject:"
+ };
+
++ ps_global->refresh_list += 1; /* Force update in folder screen */
+ if(stream)
+ e = pine_mail_fetchstructure(stream, max_num, NULL);
+
+***************
+*** 1095,1100 ****
+--- 1098,1108 ----
+ if(m && sp_flagged(m, SP_LOCKED))
+ sp_set_mail_since_cmd(m, 0L);
+ }
++
++ if (incoming_folders_new_mail > 0L){
++ icon_text(NULL, IT_NEWMAIL);
++ incoming_folders_new_mail = 0L;
++ }
+ }
+
+
+***************
+*** 1299,1301 ****
+--- 1307,1545 ----
+ }
+ }
+ #endif
++
++ #define ADD_FLD_MSG(m, F, j) \
++ {\
++ strcat((m),"\"");\
++ strcat((m),FLDR_NAME((F)));\
++ strcat((m),"\"");\
++ (F)->notified = 1;\
++ if (j)\
++ strcat((m),", ");\
++ }
++ #define MSG(n) (((n) + 30 > SIZEOF_20KBUF) ? message : tmp_20k_buf)
++ #define CODE() ((command == MC_FORCECHECK) ? 1 : ((newflds > 0) ? -1 : 1))
++ #define NMVAR() ((command == MC_FORCECHECK) ? nflds : \
++ newflds > 0 ? newflds : nflds)
++
++ /* Check for new mail in incoming folders */
++ int
++ new_mail_incfolder(state,command)
++ struct pine *state;
++ int command;
++ {
++ char *message = NULL;
++ int index = 0, i, nflds = 0, tflds, tlflds = 0, newflds = 0, save_state;
++ static time_t now, old = 0;
++ static int check_started = 0;
++ int tcp_query_timeout = state->tcp_query_timeout;
++ int tcp_open_timeout = 30;
++ int offset = !F_OFF(F_ENABLE_FAST_RECENT, state);
++ FOLDER_S *f;
++
++ if (F_OFF(F_ENABLE_INCOMING,ps_global)
++ || F_OFF(F_ENABLE_INCOMING_CHECK,ps_global)
++ || (state->inc_check_rule == IC_MAN
++ && command != MC_FORCECHECK)
++ || (state->inc_check_rule == IC_MAN_AUTO
++ && check_started == 0 && command != MC_FORCECHECK))
++ return -1;
++
++ if ((!state->force_check_now) || (state->checking_incfld)){
++ state->force_check_now = 1; /* I'll be back, but wait a moment */
++ return -1;
++ }
++
++ now = time(0);
++ if ((old != 0) && (command != MC_FORCECHECK) &&
++ (state->refresh_list == 0) &&
++ (now - old < timeo*state->delay))
++ return -1;
++
++ state->checking_incfld = 1; /* point of no return */
++ check_started = 1; /* checks have already started */
++ ps_global->mm_log_error = 0; /* turn off display of errors */
++ ps_global->noshow_error = 1;
++
++ if(state->VAR_TCPOPENTIMEO)
++ (void)SVAR_TCP_OPEN(state, tcp_open_timeout, tmp_20k_buf);
++ mail_parameters(NULL, SET_OPENTIMEOUT, (void *)(long)state->incfld_timeout);
++
++ save_state = ps_global->in_init_seq;
++ state->in_init_seq = 0; /* force output of cue during check */
++ check_cue_display("+"); /* Show something to indicate delay */
++ MoveCursor(state->ttyo->screen_rows -FOOTER_ROWS(state),0);
++ fflush(stdout);
++ state->tcp_query_timeout = state->incfld_timeout;
++
++ if(state->context_current){
++ MAILSTREAM *nxtstrm = NULL;
++ long rec, tot, fslctd;
++ int opstrm, updated;
++ CONTEXT_S *ctxt = sp_context(sp_inbox_stream());
++
++ /* Look for the Incoming folder collections, Normally the incoming folders
++ * collection is the first collection, but just to be sure, we back up to
++ * the beginning and go forward from there to try to find it.
++ */
++
++ if (!ctxt){
++ ctxt = state->context_current;
++ while (1){
++ if (ctxt->prev)
++ ctxt = ctxt->prev;
++ else
++ break;
++ }
++ while (1){
++ if (ctxt->use & CNTXT_INCMNG)
++ break;
++ else
++ ctxt = ctxt->next;
++ }
++ }
++
++ tflds = folder_total(FOLDERS(ctxt));
++ for(index = folder_index(state->inbox_name, ctxt, FI_FOLDER) + offset;
++ index >= offset && index < tflds
++ && (f = folder_entry(index, FOLDERS(ctxt)))
++ && !f->isdir; index++){
++
++ rec = tot = fslctd = 0L;
++
++ fslctd = next_folder_check(&nxtstrm, ctxt, &rec, &tot, f, &opstrm);
++
++ if(fslctd && !strcmp(FLDR_NAME(f), state->cur_folder)
++ && !state->in_fld_list)
++ fslctd = 0L;
++
++ updated = (rec != f->recent || tot != f->messages);
++ if ((f->recent + f->messages == 0L && updated)
++ || (((!opstrm && updated) || (!f->notified && opstrm && updated))
++ && fslctd))
++ state->refresh_list++;
++
++ f->countrecent = rec > f->origrecent ? rec - f->origrecent : 0;
++ f->messages = tot;
++ f->recent = rec;
++
++ if (!offset && f->countrecent == 0L && fslctd)
++ fslctd = 0L;
++
++ if (fslctd){ /* this folder contains new mail */
++ state->refresh_list += f->selected ? 0 : 1;
++ f->selected = 1;
++ if (strcmp(FLDR_NAME(f), state->inbox_name)){
++ tlflds += strlen(FLDR_NAME(f)) + 4;
++ f->new_mail = 1;
++ if(!f->notified){
++ newflds++;
++ f->new_mail = (command == MC_FORCECHECK) ? 1 : -1;
++ }
++ nflds++;
++ }
++ }
++ else{
++ if (f->selected)
++ state->refresh_list += f->user_selected ? 0 : 1;
++ if (f->notified)
++ f->selected = f->user_selected ? 1 : 0;
++ f->notified = f->new_mail = 0; /* reset */
++ }
++ }
++
++ if(nxtstrm)
++ pine_mail_close(nxtstrm);
++
++ state->mm_log_error = 1; /* turn display of errors back on */
++ state->noshow_error = 0;
++
++ if(nflds == 0){
++ if (command == MC_FORCECHECK && state->VAR_INCOMING_FOLDERS_CHECK)
++ q_status_message(SM_ORDER, 0, 2,
++ "There are NO new messages in your Incoming Folders");
++ }
++ else{ /* nflds > 0 */
++ if (tlflds + 30 > SIZEOF_20KBUF)
++ message = (char *) fs_get((tlflds + 30)*sizeof(char));
++ if(newflds > 0)
++ state->refresh_list += 1;
++ strcpy(MSG(tlflds),"New message in folder");
++ strcat(MSG(tlflds),(NMVAR() > 1) ? "s " : " ");
++ for(i = 0, index = folder_index(state->inbox_name, ctxt, FI_FOLDER)
++ + offset;
++ index >= offset && index < tflds
++ && (f = folder_entry(index, FOLDERS(ctxt))); index++)
++ if(f->new_mail == CODE()){
++ if(NMVAR() > 1){
++ ADD_FLD_MSG(MSG(tlflds), f, (i < (NMVAR() - 2)) ? 1 : 0);
++ if(i == NMVAR() - 2)
++ strcat(MSG(tlflds)," and ");
++ }
++ else
++ ADD_FLD_MSG(MSG(tlflds), f, 0);
++ f->new_mail = 1;
++ if(++i == NMVAR())
++ break;
++ }
++ if (newflds > 0 || command == MC_FORCECHECK){
++ if(strlen(MSG(tlflds)) < state->ttyo->screen_cols - 2){
++ if (command != MC_FORCECHECK){
++ q_status_message(SM_ASYNC | SM_DING, 0, 60, MSG(tlflds));
++ icon_text(MSG(tlflds), IT_NEWMAIL);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 2, MSG(tlflds));
++ }
++ else{
++ strcpy(tmp_20k_buf,
++ "You have NEW messages in your Incoming Folders");
++ if (command != MC_FORCECHECK){
++ q_status_message(SM_ASYNC | SM_DING, 0, 60, tmp_20k_buf);
++ icon_text(tmp_20k_buf, IT_NEWMAIL);
++ }
++ else
++ q_status_message(SM_ORDER, 0, 2, tmp_20k_buf);
++ }
++ }
++ if (message)
++ fs_give((void **)&message);
++ } /* end of nflds > 0 */
++ }
++ state->checking_incfld = 0;
++ check_cue_display(" "); /* Erase the "+" added before */
++ state->in_init_seq = save_state; /* restore original value */
++ MoveCursor(state->ttyo->screen_rows -FOOTER_ROWS(state),0);
++ incoming_folders_new_mail = nflds;
++
++ old = time(0);
++ state->delay = time(0) - now + 1;
++ state->tcp_query_timeout = tcp_query_timeout;
++ mail_parameters(NULL, SET_OPENTIMEOUT, (void *)(long)tcp_open_timeout);
++
++ return nflds;
++ }
++
++
++ char *
++ new_mail_in_open_stream(stream, rec, tot)
++ MAILSTREAM *stream;
++ long *rec;
++ long *tot;
++ {
++ long excluded;
++
++ if((excluded = any_lflagged(sp_msgmap(stream), MN_EXLD))){
++ *tot = stream->nmsgs - excluded;
++ if(tot)
++ *rec = count_flagged(stream, F_RECENT);
++ else
++ *rec = 0L;
++ }
++ else{
++ *tot = stream->nmsgs;
++ *rec = sp_recent_since_visited(stream);
++ }
++
++ return *rec ? STREAMNAME(stream) : NULL;
++ }
+diff -rc pine4.63/pine/osdep/termin.gen pine4.63.I.USE/pine/osdep/termin.gen
+*** pine4.63/pine/osdep/termin.gen Wed Dec 1 10:56:39 2004
+--- pine4.63.I.USE/pine/osdep/termin.gen Thu May 19 19:57:28 2005
+***************
+*** 6,11 ****
+--- 6,28 ----
+ int pcpine_oe_cursor PROTO((int, long));
+ #endif
+
++ void
++ fake_config_screen(tt)
++ struct ttyo **tt;
++ {
++ struct ttyo *ttyo;
++
++ ttyo = (struct ttyo *)fs_get(sizeof (struct ttyo));
++
++ ttyo->header_rows = 2;
++ ttyo->footer_rows = 3;
++ ttyo->screen_rows = 24;
++ ttyo->screen_cols = 80;
++
++ *tt = ttyo;
++
++ }
++
+
+ /*
+ * Generic tty input routines
+***************
+*** 227,233 ****
+ (escape_list && escape_list[0].ch != -1)
+ ? escape_list[0].label: ""));
+
+! if(!ps_global->ttyo)
+ return(pre_screen_config_opt_enter(string, field_len, prompt,
+ escape_list, help, flags));
+
+--- 244,250 ----
+ (escape_list && escape_list[0].ch != -1)
+ ? escape_list[0].label: ""));
+
+! if((!ps_global->ttyo) || (ps_global->send_immediately))
+ return(pre_screen_config_opt_enter(string, field_len, prompt,
+ escape_list, help, flags));
+
+***************
+*** 1030,1035 ****
+--- 1047,1053 ----
+ return(0);
+
+ *ch = *ps_global->initial_cmds++;
++ ps_global->initial_cmds_offset++;
+ if(!*ps_global->initial_cmds && ps_global->free_initial_cmds){
+ fs_give((void **)&(ps_global->free_initial_cmds));
+ ps_global->initial_cmds = 0;
+***************
+*** 1039,1045 ****
+ }
+
+ if(firsttime) {
+! firsttime = 0;
+ if(ps_global->in_init_seq) {
+ ps_global->in_init_seq = 0;
+ ps_global->save_in_init_seq = 0;
+--- 1057,1063 ----
+ }
+
+ if(firsttime) {
+! firsttime = ps_global->checking_incfld ? (char) 1 : 0;
+ if(ps_global->in_init_seq) {
+ ps_global->in_init_seq = 0;
+ ps_global->save_in_init_seq = 0;
+diff -rc pine4.63/pine/osdep/termin.unx pine4.63.I.USE/pine/osdep/termin.unx
+*** pine4.63/pine/osdep/termin.unx Tue Aug 3 14:46:44 2004
+--- pine4.63.I.USE/pine/osdep/termin.unx Thu May 19 19:57:27 2005
+***************
+*** 46,51 ****
+--- 46,53 ----
+ init_tty_driver(ps)
+ struct pine *ps;
+ {
++ if(ps->send_immediately)
++ return 0;
+ #ifdef MOUSE
+ if(F_ON(F_ENABLE_MOUSE, ps_global))
+ init_mouse();
+***************
+*** 573,578 ****
+--- 575,583 ----
+ init_keyboard(use_fkeys)
+ int use_fkeys;
+ {
++ if (ps_global->send_immediately)
++ return;
++
+ if(use_fkeys && (!strucmp(term_name,"vt102")
+ || !strucmp(term_name,"vt100")))
+ printf("\033\133\071\071\150");
+***************
+*** 591,596 ****
+--- 596,604 ----
+ end_keyboard(use_fkeys)
+ int use_fkeys;
+ {
++ if(ps_global->send_immediately)
++ return;
++
+ if(use_fkeys && (!strcmp(term_name, "vt102")
+ || !strcmp(term_name, "vt100"))){
+ printf("\033\133\071\071\154");
+diff -rc pine4.63/pine/osdep/termout.unx pine4.63.I.USE/pine/osdep/termout.unx
+*** pine4.63/pine/osdep/termout.unx Tue Nov 30 09:53:57 2004
+--- pine4.63.I.USE/pine/osdep/termout.unx Thu May 19 19:57:27 2005
+***************
+*** 160,165 ****
+--- 160,168 ----
+ void
+ init_screen()
+ {
++ if(ps_global->send_immediately)
++ return;
++
+ if(_termcap_init) /* init using termcap's rule */
+ tputs(_termcap_init, 1, outchar);
+
+***************
+*** 267,272 ****
+--- 270,278 ----
+ {
+ int footer_rows_was_one = 0;
+
++ if(ps_global->send_immediately)
++ return;
++
+ if(!panicking){
+
+ dprint(9, (debugfile, "end_screen called\n"));
+***************
+*** 321,327 ****
+ _line = 0; /* clear leaves us at top... */
+ _col = 0;
+
+! if(ps_global->in_init_seq)
+ return;
+
+ mark_status_unknown();
+--- 327,333 ----
+ _line = 0; /* clear leaves us at top... */
+ _col = 0;
+
+! if(ps_global->in_init_seq || ps_global->send_immediately)
+ return;
+
+ mark_status_unknown();
+diff -rc pine4.63/pine/other.c pine4.63.I.USE/pine/other.c
+*** pine4.63/pine/other.c Fri Apr 15 15:07:11 2005
+--- pine4.63.I.USE/pine/other.c Thu May 19 19:57:32 2005
+***************
+*** 362,369 ****
+ char *checkbox_pretty_value PROTO((struct pine *, CONF_S *));
+ char *color_pretty_value PROTO((struct pine *, CONF_S *));
+ char *radio_pretty_value PROTO((struct pine *, CONF_S *));
+! char *sort_pretty_value PROTO((struct pine *, CONF_S *));
+! char *generalized_sort_pretty_value PROTO((struct pine *, CONF_S *, int));
+ char *yesno_pretty_value PROTO((struct pine *, CONF_S *));
+ char *sigfile_pretty_value PROTO((struct pine *, CONF_S *));
+ void set_radio_pretty_vals PROTO((struct pine *, CONF_S **));
+--- 362,369 ----
+ char *checkbox_pretty_value PROTO((struct pine *, CONF_S *));
+ char *color_pretty_value PROTO((struct pine *, CONF_S *));
+ char *radio_pretty_value PROTO((struct pine *, CONF_S *));
+! char *sort_pretty_value PROTO((struct pine *, CONF_S *, int));
+! char *generalized_sort_pretty_value PROTO((struct pine *, CONF_S *, int, int));
+ char *yesno_pretty_value PROTO((struct pine *, CONF_S *));
+ char *sigfile_pretty_value PROTO((struct pine *, CONF_S *));
+ void set_radio_pretty_vals PROTO((struct pine *, CONF_S **));
+***************
+*** 1608,1614 ****
+ if(lv < (j = strlen(sort_name(ps->sort_types[i]))))
+ lv = j;
+
+! decode_sort(pval, &def_sort, &def_sort_rev);
+
+ for(j = 0; j < 2; j++){
+ for(i = 0; ps->sort_types[i] != EndofList; i++){
+--- 1608,1614 ----
+ if(lv < (j = strlen(sort_name(ps->sort_types[i]))))
+ lv = j;
+
+! decode_sort(pval, &def_sort, &def_sort_rev, 0);
+
+ for(j = 0; j < 2; j++){
+ for(i = 0; ps->sort_types[i] != EndofList; i++){
+***************
+*** 1623,1628 ****
+--- 1623,1678 ----
+ }
+ }
+ }
++ else if(vtmp == &ps->vars[V_THREAD_SORT_KEY]){ /* radio case */
++ SortOrder thread_def_sort;
++ int thread_def_sort_rev;
++
++ ctmpa->flags |= CF_NOSELECT;
++ ctmpa->keymenu = &config_radiobutton_keymenu;
++ ctmpa->tool = NULL;
++
++ /* put a nice delimiter before list */
++ new_confline(&ctmpa)->var = NULL;
++ ctmpa->varnamep = ctmpb;
++ ctmpa->keymenu = &config_radiobutton_keymenu;
++ ctmpa->help = NO_HELP;
++ ctmpa->tool = radiobutton_tool;
++ ctmpa->valoffset = 12;
++ ctmpa->flags |= CF_NOSELECT;
++ ctmpa->value = cpystr("Set Thread Sort Options");
++
++ new_confline(&ctmpa)->var = NULL;
++ ctmpa->varnamep = ctmpb;
++ ctmpa->keymenu = &config_radiobutton_keymenu;
++ ctmpa->help = NO_HELP;
++ ctmpa->tool = radiobutton_tool;
++ ctmpa->valoffset = 12;
++ ctmpa->flags |= CF_NOSELECT;
++ ctmpa->value = cpystr("--- ----------------------");
++
++ /* find longest value's name */
++ for(lv = 0, i = 0; ps->sort_types[i] != EndofList; i++)
++ if(lv < (j = strlen(sort_name(ps->sort_types[i]))))
++ lv = j;
++
++ decode_sort(pval, &thread_def_sort, &thread_def_sort_rev, 1);
++
++ for(j = 0; j < 2; j++){
++ for(i = 0; ps->sort_types[i] != EndofList; i++){
++ if (ps->sort_types[i] == SortArrival
++ || ps->sort_types[i] == SortThread){
++ new_confline(&ctmpa)->var = vtmp;
++ ctmpa->varnamep = ctmpb;
++ ctmpa->keymenu = &config_radiobutton_keymenu;
++ ctmpa->help = config_help(vtmp - ps->vars, 0);
++ ctmpa->tool = radiobutton_tool;
++ ctmpa->valoffset = 12;
++ ctmpa->varmem = i + (j * EndofList);
++ ctmpa->value = pretty_value(ps, ctmpa);
++ }
++ }
++ }
++ }
+ else if(vtmp == &ps->vars[V_USE_ONLY_DOMAIN_NAME]){ /* yesno case */
+ ctmpa->keymenu = &config_yesno_keymenu;
+ ctmpa->tool = yesno_tool;
+***************
+*** 1674,1679 ****
+--- 1724,1730 ----
+ || vtmp == &ps->vars[V_TCPREADWARNTIMEO]
+ || vtmp == &ps->vars[V_TCPWRITEWARNTIMEO]
+ || vtmp == &ps->vars[V_TCPQUERYTIMEO]
++ || vtmp == &ps->vars[V_INCFLDTIMEO]
+ || vtmp == &ps->vars[V_RSHOPENTIMEO]
+ || vtmp == &ps->vars[V_SSHOPENTIMEO]
+ || vtmp == &ps->vars[V_USERINPUTTIMEO]
+***************
+*** 1779,1784 ****
+--- 1830,1844 ----
+ }
+ }
+
++ pval = PVAL(&ps->vars[V_THREAD_SORT_KEY], ew);
++ if(vsave[V_THREAD_SORT_KEY].saved_user_val.p && pval
++ && strcmp(vsave[V_THREAD_SORT_KEY].saved_user_val.p, pval)){
++ if(!mn_get_mansort(ps_global->msgmap)){
++ clear_index_cache();
++ reset_sort_order(SRT_VRB);
++ }
++ }
++
+ treat_color_vars_as_text = 0;
+ free_saved_config(ps, &vsave, expose_hidden_config);
+ #ifdef _WINDOWS
+***************
+*** 1799,1804 ****
+--- 1859,1865 ----
+ v == &ps->vars[V_FCC_RULE] ||
+ v == &ps->vars[V_GOTO_DEFAULT_RULE] ||
+ v == &ps->vars[V_INCOMING_STARTUP] ||
++ v == &ps->vars[V_INCOMING_RULE] ||
+ v == &ps->vars[V_PRUNING_RULE] ||
+ v == &ps->vars[V_REOPEN_RULE] ||
+ v == &ps->vars[V_THREAD_DISP_STYLE] ||
+***************
+*** 1828,1833 ****
+--- 1889,1896 ----
+ rulefunc = goto_rules;
+ else if(v == &ps->vars[V_INCOMING_STARTUP])
+ rulefunc = incoming_startup_rules;
++ else if(v == &ps->vars[V_INCOMING_RULE])
++ rulefunc = incoming_check_rules;
+ else if(v == startup_ptr)
+ rulefunc = startup_rules;
+ else if(v == &ps->vars[V_PRUNING_RULE])
+***************
+*** 1933,1939 ****
+ CONF_S *ctmp;
+
+ if(!(cl && *cl &&
+! ((*cl)->var == &ps->vars[V_SORT_KEY] ||
+ standard_radio_var(ps, (*cl)->var) ||
+ (*cl)->var == startup_ptr)))
+ return;
+--- 1996,2003 ----
+ CONF_S *ctmp;
+
+ if(!(cl && *cl &&
+! (((*cl)->var == &ps->vars[V_SORT_KEY]) ||
+! ((*cl)->var == &ps->vars[V_THREAD_SORT_KEY]) ||
+ standard_radio_var(ps, (*cl)->var) ||
+ (*cl)->var == startup_ptr)))
+ return;
+***************
+*** 1999,2004 ****
+--- 2063,2069 ----
+ case V_TCPREADWARNTIMEO :
+ case V_TCPWRITEWARNTIMEO :
+ case V_TCPQUERYTIMEO :
++ case V_INCFLDTIMEO :
+ case V_RSHCMD :
+ case V_RSHPATH :
+ case V_RSHOPENTIMEO :
+***************
+*** 6460,6466 ****
+ int multicol;
+ {
+ char tmp[MAXPATH+1];
+! int cmd, i, j, ch = 'x', done = 0, changes = 0;
+ int retval = 0;
+ int km_popped = 0, stay_in_col = 0;
+ struct key_menu *km = NULL;
+--- 6525,6531 ----
+ int multicol;
+ {
+ char tmp[MAXPATH+1];
+! int cmd, i, j, k = 1, ch = 'x', done = 0, changes = 0;
+ int retval = 0;
+ int km_popped = 0, stay_in_col = 0;
+ struct key_menu *km = NULL;
+***************
+*** 6507,6512 ****
+--- 6572,6578 ----
+ }
+
+ /*----------- Check for new mail -----------*/
++ if (!ps->send_immediately){
+ if(new_mail(0, NM_TIMING(ch), NM_STATUS_MSG | NM_DEFER_SORT) >= 0)
+ ps->mangled_header = 1;
+
+***************
+*** 6536,6541 ****
+--- 6602,6608 ----
+ mark_status_unknown();
+ }
+
++ } /* send_immediately */
+ if(ps->mangled_footer || km != screen->current->keymenu){
+ bitmap_t bitmap;
+
+***************
+*** 6607,6612 ****
+--- 6674,6680 ----
+ }
+ }
+
++ if(!ps_global->send_immediately){
+ MoveCursor(cursor_pos.row, cursor_pos.col);
+ #ifdef MOUSE
+ mouse_in_content(KEY_MOUSE, -1, -1, 0, 0); /* prime the handler */
+***************
+*** 6625,6630 ****
+--- 6693,6706 ----
+ #ifdef _WINDOWS
+ mswin_setscrollcallback(NULL);
+ #endif
++ } /* send_immediately */
++
++ if (ps->send_immediately){
++ ps_global->dont_use_init_cmds = 0;
++ process_config_input(&ch);
++ if (ch == '\030') /* ^X, bye */
++ goto end;
++ }
+
+ cmd = menu_command(ch, km);
+
+***************
+*** 7046,7055 ****
+--- 7122,7133 ----
+ #define FOUND_NOSELECT 0x08
+ #define FOUND_ABOVE 0x10
+ char *result = NULL, buf[64];
++ static char last_pat[64] = {'\0'};
+ static char last[64];
+ HelpType help;
+ static ESCKEY_S ekey[] = {
+ {0, 0, "", ""},
++ {ctrl('N'), 9, "^N", "Ins Pat"},
+ {ctrl('Y'), 10, "^Y", "Top"},
+ {ctrl('V'), 11, "^V", "Bottom"},
+ {-1, 0, NULL, NULL}};
+***************
+*** 7068,7080 ****
+ tmp,ekey,help,&flags);
+ if(rc == 3)
+ help = help == NO_HELP ? h_config_whereis : NO_HELP;
+! else if(rc == 0 || rc == 1 || rc == 10 || rc == 11 || !buf[0]){
+ if(rc == 0 && !buf[0] && last[0])
+ strncpy(buf, last, 64);
+
+! break;
+ }
+ }
+
+ screen->current->flags &= ~CF_VAR2;
+ if(rc == 0 && buf[0]){
+--- 7146,7167 ----
+ tmp,ekey,help,&flags);
+ if(rc == 3)
+ help = help == NO_HELP ? h_config_whereis : NO_HELP;
+! else if(rc == 0 || rc == 1 || rc == 9 || rc == 10
+! || rc == 11 || !buf[0]){
+ if(rc == 0 && !buf[0] && last[0])
+ strncpy(buf, last, 64);
+
+! if(rc == 9)
+! insert_pattern_in_string(buf, last_pat, 63);
+! else
+! break;
+ }
+ }
++
++ if (buf[0] != '\0'){
++ strncpy(last_pat, buf, sizeof(last_pat));
++ last_pat[sizeof(buf) - 1] = '\0';
++ }
+
+ screen->current->flags &= ~CF_VAR2;
+ if(rc == 0 && buf[0]){
+***************
+*** 7286,7292 ****
+ break;
+ }
+ }
+!
+ screen->current = first_confline(screen->current);
+ free_conflines(&screen->current);
+ return(retval);
+--- 7373,7379 ----
+ break;
+ }
+ }
+! end:
+ screen->current = first_confline(screen->current);
+ free_conflines(&screen->current);
+ return(retval);
+***************
+*** 7429,7434 ****
+--- 7516,7523 ----
+ return(h_config_nntp_server);
+ case V_INBOX_PATH :
+ return(h_config_inbox_path);
++ case V_INCOMING_FOLDERS_CHECK :
++ return(h_config_check_inc_fld);
+ case V_PRUNED_FOLDERS :
+ return(h_config_pruned_folders);
+ case V_DEFAULT_FCC :
+***************
+*** 7467,7476 ****
+--- 7556,7593 ----
+ return(h_config_fcc_rule);
+ case V_SORT_KEY :
+ return(h_config_sort_key);
++ case V_THREAD_SORT_KEY :
++ return(h_config_thread_sort_key);
+ case V_AB_SORT_RULE :
+ return(h_config_ab_sort_rule);
+ case V_FLD_SORT_RULE :
+ return(h_config_fld_sort_rule);
++ case V_THREAD_DISP_STYLE_RULES:
++ return(h_config_thread_display_style_rule);
++ case V_THREAD_INDEX_STYLE_RULES:
++ return(h_config_thread_index_style_rule);
++ case V_COMPOSE_RULES:
++ return(h_config_compose_rules);
++ case V_FORWARD_RULES:
++ return(h_config_forward_rules);
++ case V_INDEX_RULES:
++ return(h_config_index_rules);
++ case V_REPLACE_RULES:
++ return(h_config_replace_rules);
++ case V_REPLY_INDENT_RULES:
++ return(h_config_reply_indent_rules);
++ case V_REPLY_LEADIN_RULES:
++ return(h_config_reply_leadin_rules);
++ case V_RESUB_RULES:
++ return(h_config_resub_rules);
++ case V_SAVE_RULES:
++ return(h_config_save_rules);
++ case V_SMTP_RULES:
++ return(h_config_smtp_rules);
++ case V_SORT_RULES:
++ return(h_config_sort_rules);
++ case V_STARTUP_RULES:
++ return(h_config_startup_rules);
+ case V_CHAR_SET :
+ return(h_config_char_set);
+ case V_EDITOR :
+***************
+*** 7503,7508 ****
+--- 7620,7627 ----
+ return(h_config_scroll_margin);
+ case V_DEADLETS :
+ return(h_config_deadlets);
++ case V_SPECIAL_TEXT :
++ return(h_config_special_text_to_color);
+ case V_FILLCOL :
+ return(h_config_composer_wrap_column);
+ case V_TCPOPENTIMEO :
+***************
+*** 7513,7518 ****
+--- 7632,7639 ----
+ return(h_config_tcp_writewarn_timeo);
+ case V_TCPQUERYTIMEO :
+ return(h_config_tcp_query_timeo);
++ case V_INCFLDTIMEO :
++ return(h_config_inc_fld_timeo);
+ case V_RSHOPENTIMEO :
+ return(h_config_rsh_open_timeo);
+ case V_SSHOPENTIMEO :
+***************
+*** 7595,7600 ****
+--- 7716,7723 ----
+ return(h_config_goto_default);
+ case V_INCOMING_STARTUP:
+ return(h_config_inc_startup);
++ case V_INCOMING_RULE:
++ return(h_config_inc_rule);
+ case V_PRUNING_RULE:
+ return(h_config_pruning_rule);
+ case V_REOPEN_RULE:
+***************
+*** 7621,7626 ****
+--- 7744,7751 ----
+ return(h_config_newmailwidth);
+ case V_NEWSRC_PATH :
+ return(h_config_newsrc_path);
++ case V_MAILDIR_LOCATION :
++ return(h_config_maildir_location);
+ case V_BROWSER :
+ return(h_config_browser);
+ #if defined(DOS) || defined(OS2)
+***************
+*** 7652,7657 ****
+--- 7777,7785 ----
+ case V_SIGNATURE_FORE_COLOR :
+ case V_SIGNATURE_BACK_COLOR :
+ return(h_config_signature_color);
++ case V_SPECIAL_TEXT_FORE_COLOR :
++ case V_SPECIAL_TEXT_BACK_COLOR :
++ return(h_config_special_text_color);
+ case V_PROMPT_FORE_COLOR :
+ case V_PROMPT_BACK_COLOR :
+ return(h_config_prompt_color);
+***************
+*** 8045,8050 ****
+--- 8173,8182 ----
+ lowrange = 5;
+ hirange = 1000;
+ }
++ else if((*cl)->var == &ps->vars[V_INCFLDTIMEO]){
++ lowrange = 2;
++ hirange = 60;
++ }
+ else if((*cl)->var == &ps->vars[V_TCPWRITEWARNTIMEO] ||
+ (*cl)->var == &ps->vars[V_RSHOPENTIMEO] ||
+ (*cl)->var == &ps->vars[V_SSHOPENTIMEO] ||
+***************
+*** 9371,9377 ****
+ }
+
+ set_current_val((*cl)->var, TRUE, TRUE);
+! if(decode_sort(ps->VAR_SORT_KEY, &def_sort, &def_sort_rev) != -1){
+ ps->def_sort = def_sort;
+ ps->def_sort_rev = def_sort_rev;
+ }
+--- 9503,9509 ----
+ }
+
+ set_current_val((*cl)->var, TRUE, TRUE);
+! if(decode_sort(ps->VAR_SORT_KEY, &def_sort, &def_sort_rev,0) != -1){
+ ps->def_sort = def_sort;
+ ps->def_sort_rev = def_sort_rev;
+ }
+***************
+*** 9380,9385 ****
+--- 9512,9548 ----
+ ps->mangled_body = 1; /* BUG: redraw it all for now? */
+ rv = 1;
+ }
++ else if((*cl)->var == &ps->vars[V_THREAD_SORT_KEY]){
++ SortOrder thread_def_sort;
++ int thread_def_sort_rev;
++
++ thread_def_sort_rev = (*cl)->varmem >= (short) EndofList;
++ thread_def_sort = (SortOrder) ((*cl)->varmem - (thread_def_sort_rev
++ * EndofList));
++ sprintf(tmp_20k_buf, "%s%s", sort_name(thread_def_sort),
++ (thread_def_sort_rev) ? "/Reverse" : "");
++
++ if((*cl)->var->cmdline_val.p)
++ fs_give((void **)&(*cl)->var->cmdline_val.p);
++
++ if(apval){
++ if(*apval)
++ fs_give((void **)apval);
++
++ *apval = cpystr(tmp_20k_buf);
++ }
++
++ set_current_val((*cl)->var, TRUE, TRUE);
++ if(decode_sort(ps->VAR_THREAD_SORT_KEY, &thread_def_sort,
++ &thread_def_sort_rev, 1) != -1){
++ ps->thread_def_sort = thread_def_sort;
++ ps->thread_def_sort_rev = thread_def_sort_rev;
++ }
++
++ set_radio_pretty_vals(ps, cl);
++ ps->mangled_body = 1; /* BUG: redraw it all for now? */
++ rv = 1;
++ }
+ else
+ q_status_message(SM_ORDER | SM_DING, 3, 6,
+ "Programmer botch! Unknown radiobutton type.");
+***************
+*** 10903,10909 ****
+ else if(standard_radio_var(ps, v) || v == startup_ptr)
+ return(radio_pretty_value(ps, cl));
+ else if(v == &ps->vars[V_SORT_KEY])
+! return(sort_pretty_value(ps, cl));
+ else if(v == &ps->vars[V_SIGNATURE_FILE])
+ return(sigfile_pretty_value(ps, cl));
+ else if(v == &ps->vars[V_USE_ONLY_DOMAIN_NAME])
+--- 11066,11074 ----
+ else if(standard_radio_var(ps, v) || v == startup_ptr)
+ return(radio_pretty_value(ps, cl));
+ else if(v == &ps->vars[V_SORT_KEY])
+! return(sort_pretty_value(ps, cl, 0));
+! else if(v == &ps->vars[V_THREAD_SORT_KEY])
+! return(sort_pretty_value(ps, cl, 1));
+ else if(v == &ps->vars[V_SIGNATURE_FILE])
+ return(sigfile_pretty_value(ps, cl));
+ else if(v == &ps->vars[V_USE_ONLY_DOMAIN_NAME])
+***************
+*** 11572,11590 ****
+
+
+ char *
+! sort_pretty_value(ps, cl)
+ struct pine *ps;
+ CONF_S *cl;
+ {
+! return(generalized_sort_pretty_value(ps, cl, 1));
+ }
+
+
+ char *
+! generalized_sort_pretty_value(ps, cl, default_ok)
+ struct pine *ps;
+ CONF_S *cl;
+ int default_ok;
+ {
+ char tmp[MAXPATH];
+ char *pvalnorm, *pvalexc, *pval;
+--- 11737,11757 ----
+
+
+ char *
+! sort_pretty_value(ps, cl, thread)
+ struct pine *ps;
+ CONF_S *cl;
++ int thread;
+ {
+! return(generalized_sort_pretty_value(ps, cl, 1, thread));
+ }
+
+
+ char *
+! generalized_sort_pretty_value(ps, cl, default_ok, thread)
+ struct pine *ps;
+ CONF_S *cl;
+ int default_ok;
++ int thread;
+ {
+ char tmp[MAXPATH];
+ char *pvalnorm, *pvalexc, *pval;
+***************
+*** 11634,11640 ****
+ }
+ else if(fixed){
+ pval = v->fixed_val.p;
+! decode_sort(pval, &var_sort, &var_sort_rev);
+ is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort);
+
+ sprintf(tmp, "(%c) %s%-*s%*s%s",
+--- 11801,11807 ----
+ }
+ else if(fixed){
+ pval = v->fixed_val.p;
+! decode_sort(pval, &var_sort, &var_sort_rev, thread);
+ is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort);
+
+ sprintf(tmp, "(%c) %s%-*s%*s%s",
+***************
+*** 11645,11653 ****
+ is_the_one ? " (value is fixed)" : "");
+ }
+ else if(is_set_for_this_level){
+! decode_sort(pval, &var_sort, &var_sort_rev);
+ is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort);
+! decode_sort(pvalexc, &exc_sort, &exc_sort_rev);
+ the_exc_one = (editing_normal_which_isnt_except && pvalexc &&
+ exc_sort_rev == line_sort_rev && exc_sort == line_sort);
+ sprintf(tmp, "(%c) %s%-*s%*s%s",
+--- 11812,11820 ----
+ is_the_one ? " (value is fixed)" : "");
+ }
+ else if(is_set_for_this_level){
+! decode_sort(pval, &var_sort, &var_sort_rev, thread);
+ is_the_one = (var_sort_rev == line_sort_rev && var_sort == line_sort);
+! decode_sort(pvalexc, &exc_sort, &exc_sort_rev, thread);
+ the_exc_one = (editing_normal_which_isnt_except && pvalexc &&
+ exc_sort_rev == line_sort_rev && exc_sort == line_sort);
+ sprintf(tmp, "(%c) %s%-*s%*s%s",
+***************
+*** 11665,11671 ****
+ }
+ else{
+ if(pvalexc){
+! decode_sort(pvalexc, &exc_sort, &exc_sort_rev);
+ is_the_one = (exc_sort_rev == line_sort_rev &&
+ exc_sort == line_sort);
+ sprintf(tmp, "( ) %s%-*s%*s%s",
+--- 11832,11838 ----
+ }
+ else{
+ if(pvalexc){
+! decode_sort(pvalexc, &exc_sort, &exc_sort_rev, thread);
+ is_the_one = (exc_sort_rev == line_sort_rev &&
+ exc_sort == line_sort);
+ sprintf(tmp, "( ) %s%-*s%*s%s",
+***************
+*** 11676,11682 ****
+ }
+ else{
+ pval = v->current_val.p;
+! decode_sort(pval, &var_sort, &var_sort_rev);
+ is_the_one = ((pval || default_ok) &&
+ var_sort_rev == line_sort_rev &&
+ var_sort == line_sort);
+--- 11843,11849 ----
+ }
+ else{
+ pval = v->current_val.p;
+! decode_sort(pval, &var_sort, &var_sort_rev, thread);
+ is_the_one = ((pval || default_ok) &&
+ var_sort_rev == line_sort_rev &&
+ var_sort == line_sort);
+***************
+*** 11874,11879 ****
+--- 12041,12059 ----
+
+ cl->value = pretty_value(ps, cl);
+ }
++ if (f->id == F_ENHANCED_THREAD && ps->mail_stream
++ && SORT_IS_THREADED(ps->msgmap)){
++ refresh_sort(ps->mail_stream, ps->msgmap, SRT_NON);
++ if (COLL_THRDS()) /* sortring by thread destroys collapsed info */
++ kolapse_thread(ps, ps->mail_stream, ps->msgmap,'[', 0);
++ if(SEP_THRDINDX() && SORT_IS_THREADED(ps->msgmap)
++ && sp_viewing_a_thread(ps->mail_stream)){
++ unview_thread(ps, ps->mail_stream, ps->msgmap);
++ view_thread(ps, ps->mail_stream, ps->msgmap, 0);
++ ps_global->next_screen = SCREEN_FUN_NULL;
++ }
++ }
++
+
+ /*
+ * Handle any features that need special attention here...
+***************
+*** 11884,11889 ****
+--- 12064,12073 ----
+ mail_parameters(NULL,SET_FROMWIDGET,(void *)(F_ON(f->id ,ps) ? 1 : 0));
+ break;
+
++ case F_COURIER_FOLDER_LIST:
++ mail_parameters(NULL,SET_COURIERSTYLE,(void *)(F_ON(f->id ,ps)? 1 : 0));
++ break; /* COURIER == 1, CCLIENT == 0, see maildir.h */
++
+ case F_CMBND_ABOOK_DISP :
+ addrbook_reset();
+ break;
+***************
+*** 12683,12688 ****
+--- 12867,12893 ----
+ var == &ps->vars[V_ABOOK_FORMATS]){
+ addrbook_reset();
+ }
++ else if(var == &ps->vars[V_COMPOSE_RULES] ||
++ var == &ps->vars[V_FORWARD_RULES] ||
++ var == &ps->vars[V_INDEX_RULES] ||
++ var == &ps->vars[V_REPLACE_RULES] ||
++ var == &ps->vars[V_REPLY_INDENT_RULES] ||
++ var == &ps->vars[V_REPLY_LEADIN_RULES] ||
++ var == &ps->vars[V_RESUB_RULES] ||
++ var == &ps->vars[V_SAVE_RULES] ||
++ var == &ps->vars[V_SMTP_RULES] ||
++ var == &ps->vars[V_SORT_RULES] ||
++ var == &ps->vars[V_STARTUP_RULES] ||
++ var == &ps->vars[V_THREAD_DISP_STYLE_RULES] ||
++ var == &ps->vars[V_THREAD_INDEX_STYLE_RULES]){
++ if(ps_global->rule_list)
++ free_parsed_rule_list(&ps_global->rule_list);
++ create_rule_list();
++ if(var == &ps->vars[V_INDEX_RULES]){
++ reset_index_format();
++ clear_iindex_cache();
++ }
++ }
+ else if(var == &ps->vars[V_INDEX_FORMAT]){
+ reset_index_format();
+ clear_iindex_cache();
+***************
+*** 12849,12854 ****
+--- 13054,13065 ----
+ if(ps->VAR_TCPQUERYTIMEO && SVAR_TCP_QUERY(ps, val, tmp_20k_buf))
+ q_status_message(SM_ORDER, 3, 5, tmp_20k_buf);
+ }
++ else if(var == &ps->vars[V_INCFLDTIMEO]){
++ val = 5;
++ if(!revert)
++ if(ps->VAR_INCFLDTIMEO && SVAR_TCP_QUERY(ps, val, tmp_20k_buf))
++ q_status_message(SM_ORDER, 3, 5, tmp_20k_buf);
++ }
+ else if(var == &ps->vars[V_RSHOPENTIMEO]){
+ val = 15;
+ if(!revert)
+***************
+*** 12890,12895 ****
+--- 13101,13111 ----
+ fs_give((void **)&ps->vars[V_OPER_DIR].main_user_val.p);
+ }
+ }
++ else if(var == &ps->vars[V_INCOMING_FOLDERS_CHECK] &&
++ F_OFF(F_ENABLE_FAST_RECENT, ps)){
++ ps->force_check_now = 1;
++ new_mail_incfolder(ps, MC_FORCECHECK); /* yes, update it now */
++ }
+ else if(var == &ps->vars[V_MAILCHECK]){
+ timeo = 15;
+ if(SVAR_MAILCHK(ps, timeo, tmp_20k_buf)){
+***************
+*** 12955,12960 ****
+--- 13171,13180 ----
+ (void *)var->current_val.p);
+ }
+ #endif
++ else if(var == &ps->vars[V_MAILDIR_LOCATION]){
++ if(var->current_val.p && var->current_val.p[0])
++ maildir_parameters(SET_INBOXPATH, (void *)var->current_val.p);
++ }
+ else if(revert && standard_radio_var(ps, var)){
+
+ cur_rule_value(var, TRUE, FALSE);
+***************
+*** 13001,13009 ****
+ else if(revert && var == &ps->vars[V_SORT_KEY]){
+ int def_sort_rev;
+
+! decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev);
+ ps->def_sort_rev = def_sort_rev;
+ }
+ else if(var == &ps->vars[V_THREAD_MORE_CHAR] ||
+ var == &ps->vars[V_THREAD_EXP_CHAR] ||
+ var == &ps->vars[V_THREAD_LASTREPLY_CHAR]){
+--- 13221,13235 ----
+ else if(revert && var == &ps->vars[V_SORT_KEY]){
+ int def_sort_rev;
+
+! decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev, 0);
+ ps->def_sort_rev = def_sort_rev;
+ }
++ else if(revert && var == &ps->vars[V_THREAD_SORT_KEY]){
++ int thread_def_sort_rev;
++
++ decode_sort(VAR_THREAD_SORT_KEY, &ps->thread_def_sort, &thread_def_sort_rev, 1);
++ ps->thread_def_sort_rev = thread_def_sort_rev;
++ }
+ else if(var == &ps->vars[V_THREAD_MORE_CHAR] ||
+ var == &ps->vars[V_THREAD_EXP_CHAR] ||
+ var == &ps->vars[V_THREAD_LASTREPLY_CHAR]){
+***************
+*** 13760,13771 ****
+
+ if(!(nonempty_patterns(rflags, &pstate) &&
+ first_pattern(&pstate))){
+! q_status_message(SM_ORDER, 0, 3,
+ "No roles available. Use Setup/Rules to add roles.");
+ return(ret);
+ }
+
+-
+ if(alt_compose){
+ menu_init_binding(&role_select_km,
+ alt_compose == MC_FORWARD ? 'F' : alt_compose == MC_REPLY ? 'R' : 'C',
+--- 13986,14001 ----
+
+ if(!(nonempty_patterns(rflags, &pstate) &&
+ first_pattern(&pstate))){
+! if (!ps->send_immediately)
+! q_status_message(SM_ORDER, 0, 3,
+ "No roles available. Use Setup/Rules to add roles.");
++ else{
++ printf("No roles available. Use Setup/Rules to add roles.");
++ exit(-1);
++ }
+ return(ret);
+ }
+
+ if(alt_compose){
+ menu_init_binding(&role_select_km,
+ alt_compose == MC_FORWARD ? 'F' : alt_compose == MC_REPLY ? 'R' : 'C',
+***************
+*** 17979,17985 ****
+
+ pval = PVAL(&sort_act_var, ew);
+ if(pval)
+! decode_sort(pval, &def_sort, &def_sort_rev);
+
+ /* allow user to set their default sort order */
+ new_confline(&ctmp)->var = &sort_act_var;
+--- 18209,18215 ----
+
+ pval = PVAL(&sort_act_var, ew);
+ if(pval)
+! decode_sort(pval, &def_sort, &def_sort_rev, 0);
+
+ /* allow user to set their default sort order */
+ new_confline(&ctmp)->var = &sort_act_var;
+***************
+*** 17989,17995 ****
+ ctmp->tool = role_sort_tool;
+ ctmp->valoffset = 12;
+ ctmp->varmem = -1;
+! ctmp->value = generalized_sort_pretty_value(ps, ctmp, 0);
+
+ for(j = 0; j < 2; j++){
+ for(i = 0; ps->sort_types[i] != EndofList; i++){
+--- 18219,18225 ----
+ ctmp->tool = role_sort_tool;
+ ctmp->valoffset = 12;
+ ctmp->varmem = -1;
+! ctmp->value = generalized_sort_pretty_value(ps, ctmp, 0, 0);
+
+ for(j = 0; j < 2; j++){
+ for(i = 0; ps->sort_types[i] != EndofList; i++){
+***************
+*** 18001,18007 ****
+ ctmp->valoffset = 12;
+ ctmp->varmem = i + (j * EndofList);
+ ctmp->value = generalized_sort_pretty_value(ps, ctmp,
+! 0);
+ }
+ }
+
+--- 18231,18237 ----
+ ctmp->valoffset = 12;
+ ctmp->varmem = i + (j * EndofList);
+ ctmp->value = generalized_sort_pretty_value(ps, ctmp,
+! 0, 0);
+ }
+ }
+
+***************
+*** 18906,18912 ****
+ (*result)->patgrp->stat_boy = PAT_STAT_EITHER;
+
+ if(sort_act){
+! decode_sort(sort_act, &def_sort, &def_sort_rev);
+ (*result)->action->sort_is_set = 1;
+ (*result)->action->sortorder = def_sort;
+ (*result)->action->revsort = (def_sort_rev ? 1 : 0);
+--- 19136,19142 ----
+ (*result)->patgrp->stat_boy = PAT_STAT_EITHER;
+
+ if(sort_act){
+! decode_sort(sort_act, &def_sort, &def_sort_rev, 0);
+ (*result)->action->sort_is_set = 1;
+ (*result)->action->sortorder = def_sort;
+ (*result)->action->revsort = (def_sort_rev ? 1 : 0);
+***************
+*** 21330,21335 ****
+--- 21560,21570 ----
+ if(apval)
+ *apval = (role && role->nick) ? cpystr(role->nick) : NULL;
+
++ if (ps_global->role)
++ fs_give((void **)&ps_global->role);
++ if (role && role->nick)
++ ps_global->role = cpystr(role->nick);
++
+ if((*cl)->value)
+ fs_give((void **)&((*cl)->value));
+
+***************
+*** 24130,24135 ****
+--- 24365,24371 ----
+ set_color_val(&vars[V_IND_UNS_FORE_COLOR], 0);
+ set_color_val(&vars[V_IND_ARR_FORE_COLOR], 0);
+ set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0);
++ set_color_val(&vars[V_SPECIAL_TEXT_FORE_COLOR], 0);
+
+ set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE);
+ set_current_val(&ps->vars[V_KW_COLORS], TRUE, TRUE);
+***************
+*** 24680,24682 ****
+--- 24916,24920 ----
+ return(TRUE);
+ }
+ #endif /* _WINDOWS */
++
++ #include "rules.c"
+diff -rc pine4.63/pine/pine.c pine4.63.I.USE/pine/pine.c
+*** pine4.63/pine/pine.c Wed Apr 27 11:55:02 2005
+--- pine4.63.I.USE/pine/pine.c Thu May 19 19:57:34 2005
+***************
+*** 87,92 ****
+--- 87,93 ----
+ /*
+ * Internal prototypes
+ */
++ int sp_add_status PROTO((MAILSTREAM *));
+ int sp_add PROTO((MAILSTREAM *, int));
+ int sp_nusepool_notperm PROTO((void));
+ void sp_delete PROTO((MAILSTREAM *));
+***************
+*** 252,257 ****
+--- 253,259 ----
+ pine_state = (struct pine *)fs_get(sizeof (struct pine));
+ memset((void *)pine_state, 0, sizeof(struct pine));
+ ps_global = pine_state;
++ ps_global->thread_def_sort = SortDate;
+ ps_global->def_sort = SortArrival;
+ ps_global->sort_types[0] = SortSubject;
+ ps_global->sort_types[1] = SortArrival;
+***************
+*** 264,269 ****
+--- 266,273 ----
+ ps_global->sort_types[8] = SortScore;
+ ps_global->sort_types[9] = SortThread;
+ ps_global->sort_types[10] = EndofList;
++ ps_global->force_check_now = 1;
++ ps_global->delay = 1;
+ ps_global->atmts = (ATTACH_S *) fs_get(sizeof(ATTACH_S));
+ ps_global->atmts_allocated = 1;
+ ps_global->atmts->description = NULL;
+***************
+*** 342,348 ****
+ pine_args(pine_state, argc, argv, &args);
+
+ #ifndef _WINDOWS
+! if(!isatty(0)){
+ /*
+ * monkey with descriptors so our normal tty i/o routines don't
+ * choke...
+--- 346,352 ----
+ pine_args(pine_state, argc, argv, &args);
+
+ #ifndef _WINDOWS
+! if((!pine_state->send_immediately) && !isatty(0)){
+ /*
+ * monkey with descriptors so our normal tty i/o routines don't
+ * choke...
+***************
+*** 366,377 ****
+--- 370,384 ----
+ exit(-1);
+ }
+
++ mail_parameters(NULL, SET_QUOTA, (void *) pine_parse_quota);
++
+ /* set some default timeouts in case pinerc is remote */
+ mail_parameters(NULL, SET_OPENTIMEOUT, (void *)(long)30);
+ mail_parameters(NULL, SET_READTIMEOUT, (void *)(long)15);
+ mail_parameters(NULL, SET_TIMEOUT, (void *) pine_tcptimeout);
+ /* could be TO_BAIL_THRESHOLD, 15 seems more appropriate for now */
+ pine_state->tcp_query_timeout = 15;
++ pine_state->incfld_timeout = 5;
+
+ mail_parameters(NULL, SET_SENDCOMMAND, (void *) pine_imap_cmd_happened);
+ mail_parameters(NULL, SET_FREESTREAMSPAREP, (void *) sp_free_callback);
+***************
+*** 506,517 ****
+--- 513,532 ----
+ ps_global->s_pool.max_remstream));
+
+ init_vars(pine_state);
++ if (args.action == aaFolder && !args.data.folder &&
++ ps_global->send_immediately){
++ printf("No value for To: field specified\n");
++ exit(-1);
++ }
+
+ if(args.action == aaFolder){
+ pine_state->beginning_of_month = first_run_of_month();
+ pine_state->beginning_of_year = first_run_of_year();
+ }
+
++ mail_parameters(NULL,SET_COURIERSTYLE,
++ (void *)(F_ON(F_COURIER_FOLDER_LIST, ps_global) ? 1 : 0));
++
+ set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps_global),
+ F_ON(F_ENABLE_SETLOCALE_CTYPE, ps_global));
+
+***************
+*** 559,565 ****
+ rv = 0;
+ if(pine_state->VAR_TCPWRITEWARNTIMEO){
+ if(!SVAR_TCP_WRITEWARN(pine_state, rv, tmp_20k_buf))
+! if(rv == 0 || rv > 4) /* making sure */
+ mail_parameters(NULL, SET_WRITETIMEOUT, (void *)(long)rv);
+ }
+
+--- 574,580 ----
+ rv = 0;
+ if(pine_state->VAR_TCPWRITEWARNTIMEO){
+ if(!SVAR_TCP_WRITEWARN(pine_state, rv, tmp_20k_buf))
+! if(rv == 0 || rv > 4) /* making sure */
+ mail_parameters(NULL, SET_WRITETIMEOUT, (void *)(long)rv);
+ }
+
+***************
+*** 717,722 ****
+--- 732,738 ----
+
+
+ /*--- output side ---*/
++ if (!ps_global->send_immediately){
+ rv = config_screen(&(pine_state->ttyo));
+ #if !defined(DOS) && !defined(OS2) /* always succeeds under DOS! */
+ if(rv){
+***************
+*** 741,746 ****
+--- 757,765 ----
+ exit(-1);
+ }
+ #endif
++ }
++ else
++ fake_config_screen(&(pine_state->ttyo));
+
+ if(F_ON(F_BLANK_KEYMENU,ps_global))
+ FOOTER_ROWS(ps_global) = 1;
+***************
+*** 787,793 ****
+ goodnight_gracey(pine_state, exit_val);
+ }
+
+! if(args.action == aaFolder
+ && (pine_state->first_time_user || pine_state->show_new_version)){
+ pine_state->mangled_header = 1;
+ show_main_screen(pine_state, 0, FirstMenu, &main_keymenu, 0,
+--- 806,812 ----
+ goodnight_gracey(pine_state, exit_val);
+ }
+
+! if(!pine_state->send_immediately && args.action == aaFolder
+ && (pine_state->first_time_user || pine_state->show_new_version)){
+ pine_state->mangled_header = 1;
+ show_main_screen(pine_state, 0, FirstMenu, &main_keymenu, 0,
+***************
+*** 941,946 ****
+--- 960,971 ----
+ int len, good_addr = 1;
+ int exit_val = 0;
+ BUILDER_ARG fcc;
++ ACTION_S *role = NULL;
++
++ if (pine_state->in_init_seq && pine_state->send_immediately
++ && (char) *pine_state->initial_cmds++ == '#'
++ && ++pine_state->initial_cmds_offset)
++ role_select_screen(pine_state, &role, 1);
+
+ if(pine_state->in_init_seq){
+ pine_state->in_init_seq = pine_state->save_in_init_seq = 0;
+***************
+*** 976,982 ****
+ memset(&fcc, 0, sizeof(fcc));
+
+ if(good_addr){
+! compose_mail(addr, fcc.tptr, NULL,
+ args.data.mail.attachlist, stdin_getc);
+ }
+ else{
+--- 1001,1007 ----
+ memset(&fcc, 0, sizeof(fcc));
+
+ if(good_addr){
+! compose_mail(addr, fcc.tptr, role,
+ args.data.mail.attachlist, stdin_getc);
+ }
+ else{
+***************
+*** 1009,1014 ****
+--- 1034,1040 ----
+
+ pine_state->mail_stream = NULL;
+ pine_state->mangled_screen = 1;
++ pine_state->subject = NULL;
+
+ if(args.action == aaURL){
+ url_tool_t f;
+***************
+*** 1098,1103 ****
+--- 1124,1130 ----
+ "mail folder");
+ }
+
++ if (!pine_state->send_immediately)
+ fflush(stdout);
+
+ #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
+***************
+*** 3164,3170 ****
+ {
+ int quit = 0;
+
+! dprint(1, (debugfile, "\n\n ---- QUIT SCREEN ----\n"));
+
+ if(F_ON(F_CHECK_MAIL_ONQUIT,ps_global)
+ && new_mail(1, VeryBadTime, NM_STATUS_MSG | NM_DEFER_SORT) > 0
+--- 3191,3198 ----
+ {
+ int quit = 0;
+
+! dprint(1, (debugfile, "\n\n ---- QUIT SCREEN ----\n"));
+! ps_global->in_pico = 1; /* we are leaving anyway */
+
+ if(F_ON(F_CHECK_MAIL_ONQUIT,ps_global)
+ && new_mail(1, VeryBadTime, NM_STATUS_MSG | NM_DEFER_SORT) > 0
+***************
+*** 3209,3214 ****
+--- 3237,3243 ----
+ extern KBESC_T *kbesc;
+
+ dprint(2, (debugfile, "goodnight_gracey:\n"));
++ sprintf(pine_state->cur_folder, pine_state->inbox_name);
+
+ /* We want to do this here before we close up the streams */
+ trim_remote_adrbks();
+***************
+*** 3311,3316 ****
+--- 3340,3346 ----
+ dprint(7, (debugfile, "goodnight_gracey: sp_end\n"));
+ ps_global->noshow_error = 1;
+ sp_end();
++ sp_status_end();
+
+ /* after sp_end, which might call a filter */
+ completely_done_with_adrbks();
+***************
+*** 3348,3353 ****
+--- 3378,3385 ----
+ free_saved_query_parameters();
+ #endif
+
++ if(pine_state->subject != NULL)
++ fs_give((void **)&pine_state->subject);
+ if(pine_state->hostname != NULL)
+ fs_give((void **)&pine_state->hostname);
+ if(pine_state->localdomain != NULL)
+***************
+*** 3409,3414 ****
+--- 3441,3449 ----
+
+ fs_give((void **)&ps_global->atmts);
+ }
++
++ if(ps_global->rule_list)
++ free_parsed_rule_list(&ps_global->rule_list);
+
+ dprint(7, (debugfile, "goodnight_gracey: free_vars\n"));
+ free_vars(pine_state);
+***************
+*** 3956,3969 ****
+
+ was_invisible = (mc->spare || mc->spare4) ? 1 : 0;
+
+ if(chk_thrd_cnt = ((msgs->visible_threads >= 0L)
+ && THRD_INDX_ENABLED() && (f & MN_HIDE) && (mc->spare != v))){
+- thrd = fetch_thread(stream, rawno);
+ if(thrd && thrd->top){
+! if(thrd->top == thrd->rawno)
+ topthrd = thrd;
+ else
+! topthrd = fetch_thread(stream, thrd->top);
+ }
+
+ if(topthrd){
+--- 3991,4005 ----
+
+ was_invisible = (mc->spare || mc->spare4) ? 1 : 0;
+
++ thrd = fetch_thread(stream, rawno);
++
+ if(chk_thrd_cnt = ((msgs->visible_threads >= 0L)
+ && THRD_INDX_ENABLED() && (f & MN_HIDE) && (mc->spare != v))){
+ if(thrd && thrd->top){
+! if(top_thread(stream,thrd->top) == thrd->rawno)
+ topthrd = thrd;
+ else
+! topthrd = fetch_thread(stream, top_thread(stream,thrd->top));
+ }
+
+ if(topthrd){
+***************
+*** 6320,6325 ****
+--- 6356,6446 ----
+ return(NULL);
+ }
+
++ MAILSTREAM *
++ sp_stream_status_get(mailbox)
++ char *mailbox;
++ {
++ int i;
++ MAILSTREAM *m = NULL;
++
++ for(i = 0; i < ps_global->s_pool_status.nstream; i++){
++ m = ps_global->s_pool_status.streams[i];
++ if(m && same_stream(mailbox, m) && pine_mail_ping(m))
++ return m;
++ }
++ return NULL;
++ }
++
++ void
++ sp_status_end()
++ {
++ int i;
++ MAILSTREAM *m;
++
++ for(i = 0; i < ps_global->s_pool_status.nstream; i++){
++ m = ps_global->s_pool_status.streams[i];
++ if(m)
++ pine_mail_actually_close(m);
++ }
++
++ if(ps_global->s_pool_status.streams)
++ fs_give((void **) &ps_global->s_pool_status.streams);
++
++ ps_global->s_pool_status.nstream = 0;
++ }
++
++ int
++ sp_add_status(stream)
++ MAILSTREAM *stream;
++ {
++ int i, slot = -1;
++ MAILSTREAM *m;
++
++ if(!stream)
++ return -1;
++
++ for(i = 0; i < ps_global->s_pool_status.nstream; i++){
++ m = ps_global->s_pool_status.streams[i];
++ if(m == stream){
++ slot = i;
++ return 0;
++ }
++ }
++
++ for(i = 0; i < ps_global->s_pool_status.nstream; i++){
++ m = ps_global->s_pool_status.streams[i];
++ if(!m){
++ slot = i;
++ break;
++ }
++ }
++
++ if(slot < 0){
++ slot = ps_global->s_pool_status.nstream++;
++ if(ps_global->s_pool_status.streams){
++ fs_resize((void **) &ps_global->s_pool_status.streams,
++ ps_global->s_pool_status.nstream *
++ sizeof(*ps_global->s_pool_status.streams));
++ ps_global->s_pool_status.streams[slot] = NULL;
++ }
++ else{
++ ps_global->s_pool_status.streams =
++ (MAILSTREAM **) fs_get(ps_global->s_pool_status.nstream *
++ sizeof(*ps_global->s_pool_status.streams));
++ memset(ps_global->s_pool_status.streams, 0,
++ ps_global->s_pool_status.nstream *
++ sizeof(*ps_global->s_pool_status.streams));
++ }
++ }
++
++ if(slot >= 0 && slot < ps_global->s_pool_status.nstream){
++ ps_global->s_pool_status.streams[slot] = stream;
++ return 0;
++ }
++ else
++ return -1;
++ }
++
+
+ void
+ sp_end()
+diff -rc pine4.63/pine/pine.h pine4.63.I.USE/pine/pine.h
+*** pine4.63/pine/pine.h Fri Apr 15 15:07:15 2005
+--- pine4.63.I.USE/pine/pine.h Thu May 19 19:57:34 2005
+***************
+*** 231,236 ****
+--- 231,239 ----
+ #ifndef DF_INCOMING_STARTUP
+ #define DF_INCOMING_STARTUP "first-unseen"
+ #endif
++ #ifndef DF_INCOMING_RULE
++ #define DF_INCOMING_RULE "automatic"
++ #endif
+ #ifndef DF_PRUNING_RULE
+ #define DF_PRUNING_RULE "ask-ask"
+ #endif
+***************
+*** 622,627 ****
+--- 625,631 ----
+ , V_SMTP_SERVER
+ , V_NNTP_SERVER
+ , V_INBOX_PATH
++ , V_INCOMING_FOLDERS_CHECK
+ , V_ARCHIVED_FOLDERS
+ , V_PRUNED_FOLDERS
+ , V_DEFAULT_FCC
+***************
+*** 642,651 ****
+--- 646,657 ----
+ , V_SAVED_MSG_NAME_RULE
+ , V_FCC_RULE
+ , V_SORT_KEY
++ , V_THREAD_SORT_KEY
+ , V_AB_SORT_RULE
+ , V_FLD_SORT_RULE
+ , V_GOTO_DEFAULT_RULE
+ , V_INCOMING_STARTUP
++ , V_INCOMING_RULE
+ , V_PRUNING_RULE
+ , V_REOPEN_RULE
+ , V_THREAD_DISP_STYLE
+***************
+*** 653,662 ****
+--- 659,682 ----
+ , V_THREAD_MORE_CHAR
+ , V_THREAD_EXP_CHAR
+ , V_THREAD_LASTREPLY_CHAR
++ , V_THREAD_DISP_STYLE_RULES
++ , V_THREAD_INDEX_STYLE_RULES
++ , V_COMPOSE_RULES
++ , V_FORWARD_RULES
++ , V_INDEX_RULES
++ , V_REPLACE_RULES
++ , V_REPLY_INDENT_RULES
++ , V_REPLY_LEADIN_RULES
++ , V_RESUB_RULES
++ , V_SAVE_RULES
++ , V_SMTP_RULES
++ , V_SORT_RULES
++ , V_STARTUP_RULES
+ , V_CHAR_SET
+ , V_EDITOR
+ , V_SPELLER
+ , V_FILLCOL
++ , V_SPECIAL_TEXT
+ , V_REPLY_STRING
+ , V_REPLY_INTRO
+ , V_QUOTE_REPLACE_STRING
+***************
+*** 689,694 ****
+--- 709,715 ----
+ , V_NEWSRC_PATH
+ , V_NEWS_ACTIVE_PATH
+ , V_NEWS_SPOOL_DIR
++ , V_MAILDIR_LOCATION
+ , V_UPLOAD_CMD
+ , V_UPLOAD_CMD_PREFIX
+ , V_DOWNLOAD_CMD
+***************
+*** 726,731 ****
+--- 747,753 ----
+ , V_TCPREADWARNTIMEO
+ , V_TCPWRITEWARNTIMEO
+ , V_TCPQUERYTIMEO
++ , V_INCFLDTIMEO
+ , V_RSHCMD
+ , V_RSHPATH
+ , V_RSHOPENTIMEO
+***************
+*** 787,792 ****
+--- 809,816 ----
+ , V_QUOTE3_BACK_COLOR
+ , V_SIGNATURE_FORE_COLOR
+ , V_SIGNATURE_BACK_COLOR
++ , V_SPECIAL_TEXT_FORE_COLOR
++ , V_SPECIAL_TEXT_BACK_COLOR
+ , V_PROMPT_FORE_COLOR
+ , V_PROMPT_BACK_COLOR
+ , V_IND_PLUS_FORE_COLOR
+***************
+*** 843,848 ****
+--- 867,874 ----
+ #define VAR_INBOX_PATH vars[V_INBOX_PATH].current_val.p
+ #define GLO_INBOX_PATH vars[V_INBOX_PATH].global_val.p
+ #define VAR_INCOMING_FOLDERS vars[V_INCOMING_FOLDERS].current_val.l
++ #define VAR_INCOMING_FOLDERS_CHECK vars[V_INCOMING_FOLDERS_CHECK].current_val.p
++ #define GLO_INCOMING_FOLDERS_CHECK vars[V_INCOMING_FOLDERS_CHECK].global_val.p
+ #define VAR_FOLDER_SPEC vars[V_FOLDER_SPEC].current_val.l
+ #define GLO_FOLDER_SPEC vars[V_FOLDER_SPEC].global_val.l
+ #define VAR_NEWS_SPEC vars[V_NEWS_SPEC].current_val.l
+***************
+*** 897,912 ****
+--- 923,980 ----
+ #define VAR_SORT_KEY vars[V_SORT_KEY].current_val.p
+ #define GLO_SORT_KEY vars[V_SORT_KEY].global_val.p
+ #define COM_SORT_KEY vars[V_SORT_KEY].cmdline_val.p
++ #define VAR_THREAD_SORT_KEY vars[V_THREAD_SORT_KEY].current_val.p
++ #define GLO_THREAD_SORT_KEY vars[V_THREAD_SORT_KEY].global_val.p
++ #define COM_THREAD_SORT_KEY vars[V_THREAD_SORT_KEY].cmdline_val.p
+ #define VAR_AB_SORT_RULE vars[V_AB_SORT_RULE].current_val.p
+ #define GLO_AB_SORT_RULE vars[V_AB_SORT_RULE].global_val.p
+ #define VAR_FLD_SORT_RULE vars[V_FLD_SORT_RULE].current_val.p
+ #define GLO_FLD_SORT_RULE vars[V_FLD_SORT_RULE].global_val.p
++ #define VAR_COMPOSE_RULES vars[V_COMPOSE_RULES].current_val.l
++ #define GLO_COMPOSE_RULES vars[V_COMPOSE_RULES].global_val.l
++ #define USR_COMPOSE_RULES vars[V_COMPOSE_RULES].user_val.l
++ #define VAR_FORWARD_RULES vars[V_FORWARD_RULES].current_val.l
++ #define GLO_FORWARD_RULES vars[V_FORWARD_RULES].global_val.l
++ #define USR_FORWARD_RULES vars[V_FORWARD_RULES].user_val.l
++ #define VAR_INDEX_RULES vars[V_INDEX_RULES].current_val.l
++ #define GLO_INDEX_RULES vars[V_INDEX_RULES].global_val.l
++ #define USR_INDEX_RULES vars[V_INDEX_RULES].user_val.l
++ #define VAR_REPLACE_RULES vars[V_REPLACE_RULES].current_val.l
++ #define GLO_REPLACE_RULES vars[V_REPLACE_RULES].global_val.l
++ #define USR_REPLACE_RULES vars[V_REPLACE_RULES].user_val.l
++ #define VAR_REPLY_INDENT_RULES vars[V_REPLY_INDENT_RULES].current_val.l
++ #define GLO_REPLY_INDENT_RULES vars[V_REPLY_INDENT_RULES].global_val.l
++ #define USR_REPLY_INDENT_RULES vars[V_REPLY_INDENT_RULES].user_val.l
++ #define VAR_REPLY_LEADIN_RULES vars[V_REPLY_LEADIN_RULES].current_val.l
++ #define GLO_REPLY_LEADIN_RULES vars[V_REPLY_LEADIN_RULES].global_val.l
++ #define USR_REPLY_LEADIN_RULES vars[V_REPLY_LEADIN_RULES].user_val.l
++ #define VAR_RESUB_RULES vars[V_RESUB_RULES].current_val.l
++ #define GLO_RESUB_RULES vars[V_RESUB_RULES].global_val.l
++ #define USR_RESUB_RULES vars[V_RESUB_RULES].user_val.l
++ #define VAR_THREAD_DISP_STYLE_RULES vars[V_THREAD_DISP_STYLE_RULES].current_val.l
++ #define GLO_THREAD_DISP_STYLE_RULES vars[V_THREAD_DISP_STYLE_RULES].global_val.l
++ #define VAR_THREAD_INDEX_STYLE_RULES vars[V_THREAD_INDEX_STYLE_RULES].current_val.l
++ #define GLO_THREAD_INDEX_STYLE_RULES vars[V_THREAD_INDEX_STYLE_RULES].global_val.l
++ #define VAR_SAVE_RULES vars[V_SAVE_RULES].current_val.l
++ #define GLO_SAVE_RULES vars[V_SAVE_RULES].global_val.l
++ #define USR_SAVE_RULES vars[V_SAVE_RULES].user_val.l
++ #define VAR_SMTP_RULES vars[V_SMTP_RULES].current_val.l
++ #define GLO_SMTP_RULES vars[V_SMTP_RULES].global_val.l
++ #define USR_SMTP_RULES vars[V_SMTP_RULES].user_val.l
++ #define VAR_SORT_RULES vars[V_SORT_RULES].current_val.l
++ #define GLO_SORT_RULES vars[V_SORT_RULES].global_val.l
++ #define USR_SORT_RULES vars[V_SORT_RULES].user_val.l
++ #define VAR_STARTUP_RULES vars[V_STARTUP_RULES].current_val.l
++ #define GLO_STARTUP_RULES vars[V_STARTUP_RULES].global_val.l
++ #define USR_STARTUP_RULES vars[V_STARTUP_RULES].user_val.l
+ #define VAR_CHAR_SET vars[V_CHAR_SET].current_val.p
+ #define GLO_CHAR_SET vars[V_CHAR_SET].global_val.p
+ #define VAR_EDITOR vars[V_EDITOR].current_val.l
+ #define GLO_EDITOR vars[V_EDITOR].global_val.l
+ #define VAR_SPELLER vars[V_SPELLER].current_val.p
+ #define GLO_SPELLER vars[V_SPELLER].global_val.p
++ #define VAR_SPECIAL_TEXT vars[V_SPECIAL_TEXT].current_val.l
++ #define GLO_SPECIAL_TEXT vars[V_SPECIAL_TEXT].global_val.l
+ #define VAR_FILLCOL vars[V_FILLCOL].current_val.p
+ #define GLO_FILLCOL vars[V_FILLCOL].global_val.p
+ #define VAR_DEADLETS vars[V_DEADLETS].current_val.p
+***************
+*** 991,996 ****
+--- 1059,1066 ----
+ #define GLO_NEWS_ACTIVE_PATH vars[V_NEWS_ACTIVE_PATH].global_val.p
+ #define VAR_NEWS_SPOOL_DIR vars[V_NEWS_SPOOL_DIR].current_val.p
+ #define GLO_NEWS_SPOOL_DIR vars[V_NEWS_SPOOL_DIR].global_val.p
++ #define VAR_MAILDIR_LOCATION vars[V_MAILDIR_LOCATION].current_val.p
++ #define GLO_MAILDIR_LOCATION vars[V_MAILDIR_LOCATION].global_val.p
+ #define VAR_DISABLE_DRIVERS vars[V_DISABLE_DRIVERS].current_val.l
+ #define VAR_DISABLE_AUTHS vars[V_DISABLE_AUTHS].current_val.l
+ #define VAR_REMOTE_ABOOK_METADATA vars[V_REMOTE_ABOOK_METADATA].current_val.p
+***************
+*** 1035,1040 ****
+--- 1105,1111 ----
+ #define VAR_TCPREADWARNTIMEO vars[V_TCPREADWARNTIMEO].current_val.p
+ #define VAR_TCPWRITEWARNTIMEO vars[V_TCPWRITEWARNTIMEO].current_val.p
+ #define VAR_TCPQUERYTIMEO vars[V_TCPQUERYTIMEO].current_val.p
++ #define VAR_INCFLDTIMEO vars[V_INCFLDTIMEO].current_val.p
+ #define VAR_RSHOPENTIMEO vars[V_RSHOPENTIMEO].current_val.p
+ #define VAR_RSHPATH vars[V_RSHPATH].current_val.p
+ #define VAR_RSHCMD vars[V_RSHCMD].current_val.p
+***************
+*** 1045,1050 ****
+--- 1116,1123 ----
+ #define VAR_BROWSER vars[V_BROWSER].current_val.l
+ #define VAR_INCOMING_STARTUP vars[V_INCOMING_STARTUP].current_val.p
+ #define GLO_INCOMING_STARTUP vars[V_INCOMING_STARTUP].global_val.p
++ #define VAR_INCOMING_RULE vars[V_INCOMING_RULE].current_val.p
++ #define GLO_INCOMING_RULE vars[V_INCOMING_RULE].global_val.p
+ #define VAR_PRUNING_RULE vars[V_PRUNING_RULE].current_val.p
+ #define GLO_PRUNING_RULE vars[V_PRUNING_RULE].global_val.p
+ #define VAR_REOPEN_RULE vars[V_REOPEN_RULE].current_val.p
+***************
+*** 1122,1127 ****
+--- 1195,1202 ----
+ #define VAR_QUOTE3_BACK_COLOR vars[V_QUOTE3_BACK_COLOR].current_val.p
+ #define VAR_SIGNATURE_FORE_COLOR vars[V_SIGNATURE_FORE_COLOR].current_val.p
+ #define VAR_SIGNATURE_BACK_COLOR vars[V_SIGNATURE_BACK_COLOR].current_val.p
++ #define VAR_SPECIAL_TEXT_FORE_COLOR vars[V_SPECIAL_TEXT_FORE_COLOR].current_val.p
++ #define VAR_SPECIAL_TEXT_BACK_COLOR vars[V_SPECIAL_TEXT_BACK_COLOR].current_val.p
+ #define VAR_PROMPT_FORE_COLOR vars[V_PROMPT_FORE_COLOR].current_val.p
+ #define VAR_PROMPT_BACK_COLOR vars[V_PROMPT_BACK_COLOR].current_val.p
+ #define VAR_VIEW_HDR_COLORS vars[V_VIEW_HDR_COLORS].current_val.l
+***************
+*** 1151,1156 ****
+--- 1226,1232 ----
+ F_FULL_AUTO_EXPUNGE,
+ F_EXPUNGE_MANUALLY,
+ F_AUTO_READ_MSGS,
++ F_AUTO_READ_MSGS_RULES,
+ F_AUTO_FCC_ONLY,
+ F_READ_IN_NEWSRC_ORDER,
+ F_SELECT_WO_CONFIRM,
+***************
+*** 1168,1173 ****
+--- 1244,1250 ----
+ F_SHOW_DELAY_CUE,
+ F_CANCEL_CONFIRM,
+ F_AUTO_OPEN_NEXT_UNREAD,
++ F_AUTO_CIRCULAR_TAB,
+ F_SELECTED_SHOWN_BOLD,
+ F_QUOTE_ALL_FROMS,
+ F_AUTO_INCLUDE_IN_REPLY,
+***************
+*** 1184,1189 ****
+--- 1261,1268 ----
+ F_DISABLE_PIPES_IN_TEMPLATES,
+ F_ATTACHMENTS_IN_REPLY,
+ F_ENABLE_INCOMING,
++ F_ENABLE_INCOMING_CHECK,
++ F_ENABLE_INCOMING_RECHECK,
+ F_NO_NEWS_VALIDATION,
+ F_QUELL_EXTRA_POST_PROMPT,
+ F_DISABLE_TAKE_LASTFIRST,
+***************
+*** 1206,1215 ****
+--- 1285,1296 ----
+ F_PASS_C1_CONTROL_CHARS,
+ F_SINGLE_FOLDER_LIST,
+ F_VERTICAL_FOLDER_LIST,
++ F_COURIER_FOLDER_LIST,
+ F_TAB_CHK_RECENT,
+ F_AUTO_REPLY_TO,
+ F_VERBOSE_POST,
+ F_FCC_ON_BOUNCE,
++ F_USE_DOMAIN_NAME,
+ F_SEND_WO_CONFIRM,
+ F_USE_SENDER_NOT_X,
+ F_BLANK_KEYMENU,
+***************
+*** 1314,1323 ****
+--- 1395,1406 ----
+ F_MAILDROPS_PRESERVE_STATE,
+ F_EXPOSE_HIDDEN_CONFIG,
+ F_ALT_COMPOSE_MENU,
++ F_ALT_REPLY_MENU,
+ F_ALT_ROLE_MENU,
+ F_ALWAYS_SPELL_CHECK,
+ F_QUELL_TIMEZONE,
+ F_COLOR_LINE_IMPORTANT,
++ F_ENHANCED_THREAD,
+ F_SLASH_COLL_ENTIRE,
+ F_ENABLE_FULL_HDR_AND_TEXT,
+ F_QUELL_FULL_HDR_RESET,
+***************
+*** 1547,1552 ****
+--- 1630,1642 ----
+ #define IS_NOTSET 7 /* for reset version */
+
+ /*
++ * Incoming check rules
++ */
++ #define IC_AUTO 0
++ #define IC_MAN_AUTO 1
++ #define IC_MAN 2
++
++ /*
+ * Pruning rules. If these grow, widen pruning_rule.
+ */
+ #define PRUNE_ASK_AND_ASK 0
+***************
+*** 1830,1835 ****
+--- 1920,1929 ----
+ #define SVAR_TCP_QUERY(ps, n, e) strtoval((ps)->VAR_TCPQUERYTIMEO, \
+ &(n), 5, 30000, 0, (e), \
+ "Tcp-Query-Timeout")
++ #define SVAR_INCFLDQUERY(ps, n, e) strtoval((ps)->VAR_INCFLDTIMEO, \
++ &(n), 2, 60, 0, (e), \
++ "Inc-fld-timeout")
++
+ #define SVAR_RSH_OPEN(ps, n, e) strtoval((ps)->VAR_RSHOPENTIMEO, \
+ &(n), 5, 30000, 0, (e), \
+ "Rsh-Open-Timeout")
+***************
+*** 1930,1936 ****
+ SortSubject2, SortScore, SortThread, EndofList} SortOrder;
+
+ #define refresh_sort(S,M,F) sort_folder((S), (M), mn_get_sort(M), \
+! mn_get_revsort(M), (F))
+
+ /*
+ * The two structs below hold all knowledge regarding
+--- 2024,2030 ----
+ SortSubject2, SortScore, SortThread, EndofList} SortOrder;
+
+ #define refresh_sort(S,M,F) sort_folder((S), (M), mn_get_sort(M), \
+! mn_get_revsort(M), (F), 1)
+
+ /*
+ * The two structs below hold all knowledge regarding
+***************
+*** 1974,1986 ****
+ typedef struct pine_thrd {
+ unsigned long rawno; /* raw msgno of this message */
+ unsigned long thrdno; /* thread number */
+- unsigned long flags;
+ unsigned long next; /* msgno of first reply to us */
+ unsigned long branch; /* like THREADNODE branch, next replier */
+ unsigned long parent; /* message that this is a reply to */
+ unsigned long nextthd; /* next thread, only tops have this */
+ unsigned long prevthd; /* previous thread, only tops have this */
+ unsigned long top; /* top of this thread */
+ unsigned long head; /* head of the whole thread list */
+ } PINETHRD_S;
+
+--- 2068,2080 ----
+ typedef struct pine_thrd {
+ unsigned long rawno; /* raw msgno of this message */
+ unsigned long thrdno; /* thread number */
+ unsigned long next; /* msgno of first reply to us */
+ unsigned long branch; /* like THREADNODE branch, next replier */
+ unsigned long parent; /* message that this is a reply to */
+ unsigned long nextthd; /* next thread, only tops have this */
+ unsigned long prevthd; /* previous thread, only tops have this */
+ unsigned long top; /* top of this thread */
++ unsigned long toploose; /* top of this thread, if is loose */
+ unsigned long head; /* head of the whole thread list */
+ } PINETHRD_S;
+
+***************
+*** 2571,2580 ****
+--- 2665,2681 ----
+ unsigned hasnochildren:1; /* known not to have children */
+ unsigned scanned:1; /* scanned by c-client */
+ unsigned selected:1; /* selected by user */
++ unsigned user_selected:1; /* selected by user (not Pine)*/
+ unsigned subscribed:1; /* selected by user */
+ unsigned long varhash; /* hash of var for incoming */
+ unsigned long uidvalidity; /* only for #move folder */
+ unsigned long uidnext; /* only for #move folder */
++ int notified; /* notified the change? */
++ int new_mail; /* folder has new mail */
++ long origrecent; /* # recent messages in stream*/
++ long countrecent; /* # recent messages displayed*/
++ long recent; /* # recent messages adjusted */
++ long messages; /* # messages */
+ char *nickname; /* folder's short name */
+ char name[1]; /* folder's name */
+ } FOLDER_S;
+***************
+*** 2600,2611 ****
+ iLstYear, iLstYear2Digit,
+ iMessNo, iAtt, iMsgID, iSubject,
+ iSubjKey, iSubjKeyInit, iKey, iKeyInit,
+! iSize, iSizeComma, iSizeNarrow, iDescripSize,
+ iNewsAndTo, iToAndNews, iNewsAndRecips, iRecipsAndNews,
+ iFromTo, iFromToNotNews, iFrom, iTo, iSender, iCc, iNews, iRecips,
+ iCurNews, iArrow,
+ iMailbox, iAddress, iInit, iCursorPos,
+ iDay2Digit, iMon2Digit, iYear2Digit,
+ iSTime, iKSize,
+ iRoleNick,
+ iScore, iDayOfWeekAbb, iDayOfWeek,
+--- 2701,2715 ----
+ iLstYear, iLstYear2Digit,
+ iMessNo, iAtt, iMsgID, iSubject,
+ iSubjKey, iSubjKeyInit, iKey, iKeyInit,
+! iSize, iSizeComma, iSizeNarrow, iDescripSize, iSizeThread,
+ iNewsAndTo, iToAndNews, iNewsAndRecips, iRecipsAndNews,
+ iFromTo, iFromToNotNews, iFrom, iTo, iSender, iCc, iNews, iRecips,
+ iCurNews, iArrow,
+ iMailbox, iAddress, iInit, iCursorPos,
+ iDay2Digit, iMon2Digit, iYear2Digit,
++ iFolder, iFlag, iCollection, iRole,
++ iNick, iAddressTo, iAddressCc, iAddressRecip, iBcc, iLcc,
++ iFfrom, iFadd,
+ iSTime, iKSize,
+ iRoleNick,
+ iScore, iDayOfWeekAbb, iDayOfWeek,
+***************
+*** 2622,2634 ****
+ } INDEX_PARSE_T;
+
+ /* these are flags for the what_for field in INDEX_PARSE_T */
+! #define FOR_NOTHING 0x00
+! #define FOR_INDEX 0x01
+! #define FOR_REPLY_INTRO 0x02
+! #define FOR_TEMPLATE 0x04 /* or for signature */
+! #define FOR_FILT 0x08
+! #define DELIM_USCORE 0x10
+! #define DELIM_PAREN 0x20
+
+ #define DEFAULT_REPLY_INTRO "default"
+
+--- 2726,2749 ----
+ } INDEX_PARSE_T;
+
+ /* these are flags for the what_for field in INDEX_PARSE_T */
+! #define FOR_NOTHING 0x00000
+! #define FOR_INDEX 0x00001
+! #define FOR_REPLY_INTRO 0x00002
+! #define FOR_TEMPLATE 0x00004 /* or for signature */
+! #define FOR_FILT 0x00008
+! #define DELIM_USCORE 0x00010
+! #define DELIM_PAREN 0x00020
+! #define FOR_SAVE 0x00040 /* for rules */
+! #define FOR_FOLDER 0x00080 /* for rules */
+! #define FOR_RULE 0x00100 /* for rules */
+! #define FOR_TRIM 0x00200 /* for rules */
+! #define FOR_RESUB 0x00400 /* for rules */
+! #define FOR_REPLACE 0x00800 /* for rules */
+! #define FOR_SORT 0x01000 /* for rules */
+! #define FOR_FLAG 0x02000 /* for rules */
+! #define FOR_COMPOSE 0x04000 /* for rules */
+! #define FOR_THREAD 0x08000 /* for rules */
+! #define FOR_STARTUP 0x10000 /* for rules */
+
+ #define DEFAULT_REPLY_INTRO "default"
+
+***************
+*** 2992,3002 ****
+ #define MC_NOT 799
+ #define MC_COLLAPSE 800
+ #define MC_CHK_RECENT 801
+!
+
+ /*
+ * Some standard Key/Command Bindings
+ */
+ #define NULL_MENU {NULL, NULL, {MC_NONE}, KS_NONE}
+ #define HELP_MENU {"?", "Help", \
+ {MC_HELP, 2, {'?',ctrl('G')}}, \
+--- 3107,3132 ----
+ #define MC_NOT 799
+ #define MC_COLLAPSE 800
+ #define MC_CHK_RECENT 801
+! #define MC_PRETHREAD 802
+! #define MC_CTHREAD 803
+! #define MC_OTHREAD 804
+! #define MC_DELTHREAD 805
+! #define MC_UNDTHREAD 806
+! #define MC_SELTHREAD 807
+! #define MC_SSUTHREAD 808
+! #define MC_DSUTHREAD 809
+! #define MC_USUTHREAD 810
+! #define MC_SORTHREAD 811
+! #define MC_NEXTHREAD 812
+! #define MC_KOLAPSE 813
+! #define MC_EXPTHREAD 814
+! #define MC_QUOTA 815
+
+ /*
+ * Some standard Key/Command Bindings
+ */
++ #define MC_IFAUTOCHECK 820
++ #define MC_FORCECHECK 821
+ #define NULL_MENU {NULL, NULL, {MC_NONE}, KS_NONE}
+ #define HELP_MENU {"?", "Help", \
+ {MC_HELP, 2, {'?',ctrl('G')}}, \
+***************
+*** 3094,3100 ****
+ #define TAB_MENU {"Tab", "NextNew", \
+ {MC_TAB,1,{TAB}}, \
+ KS_NONE}
+!
+
+ #define USER_INPUT_TIMEOUT(ps) ((ps->hours_to_timeout > 0) && \
+ ((time(0) - time_of_last_input) > 60*60*(ps->hours_to_timeout)))
+--- 3224,3232 ----
+ #define TAB_MENU {"Tab", "NextNew", \
+ {MC_TAB,1,{TAB}}, \
+ KS_NONE}
+! #define QUOTA_MENU {"@", "Quota", \
+! {MC_QUOTA,1,{'@'}}, \
+! KS_NONE}
+
+ #define USER_INPUT_TIMEOUT(ps) ((ps->hours_to_timeout > 0) && \
+ ((time(0) - time_of_last_input) > 60*60*(ps->hours_to_timeout)))
+***************
+*** 3681,3688 ****
+--- 3813,3872 ----
+ #define HEX_CHAR1(C) HEX_ARRAY[((C) & 0xf0) >> 4]
+ #define HEX_CHAR2(C) HEX_ARRAY[(C) & 0xf]
+
++ typedef struct rule {
++ char *result; /* The result of the rule */
++ int number; /* The number of the rule that succeded, -1 if not */
++ } RULE_RESULT;
++
++ #define TOKEN_VALUE struct tokenvalue_s
++ #define CONDITION_S struct condition_s
++ #define RULEACTION_S struct ruleaction_s
++ #define RULE_S struct rule_s
++ #define RULELIST struct rulelist_s
++ #define PRULELIST_S struct parsedrulelist_s
++
++ TOKEN_VALUE {
++ char *testxt;
++ TOKEN_VALUE *next;
++ };
++
++ typedef enum {Equal, Subset, Includes,
++ NotEqual, NotSubset, NotIncludes,
++ EndTypes} TestType;
++
++ CONDITION_S {
++ char *tname; /* tname ttype {value} */
++ TestType ttype; /* tname ttype {value} */
++ TOKEN_VALUE *value; /* value to check against */
++ CONDITION_S *next; /* next condition to test */
++ };
++
++ RULEACTION_S {
++ char *token; /* token := function{value} or token = null */
++ char *function; /* token := function{value} or simply function{value}*/
++ TOKEN_VALUE *value; /* token := function{value} or simply function{value}*/
++ int context; /* context in which this rule can be used */
++ char* (*exec)();
++ unsigned int is_trim:1;
++ unsigned int is_rextrim:1;
++ unsigned int is_replace:1;
++ };
+
++ RULE_S {
++ CONDITION_S *condition;
++ RULEACTION_S *action;
++ };
+
++ RULELIST {
++ RULE_S *prule;
++ RULELIST *next;
++ };
++
++ PRULELIST_S {
++ int varnum; /* number associated to the variable */
++ RULELIST *rlist;
++ PRULELIST_S *next;
++ };
+
+ /*------------------------------
+ Structure to pass optionally_enter to tell it what keystrokes
+***************
+*** 3830,3835 ****
+--- 4014,4020 ----
+ PrivateAffector *affector;
+ } PrivateTop;
+
++ #define DF_THREAD_SORT_KEY "thread"
+
+ typedef enum {OpenFolder, SaveMessage, FolderMaint, GetFcc,
+ Subscribe, PostNews} FolderFun;
+***************
+*** 3954,3959 ****
+--- 4139,4146 ----
+ unsigned char t; /* temporary char */
+ char *line; /* place for temporary storage */
+ char *linep; /* pointer into storage space */
++ char *oldline; /* the previous line to "line" */
++ char *oldlinep; /* the previous line to "line" */
+ void *opt; /* optional per instance data */
+ void *data; /* misc internal data pointer */
+ unsigned char queue[1 + GF_MAXBUF];
+***************
+*** 4221,4226 ****
+--- 4408,4414 ----
+ CONTEXT_S *context_last; /* most recently open context */
+
+ SP_S s_pool; /* stream pool */
++ SP_S s_pool_status; /* stream pool */
+
+ char inbox_name[MAXFOLDER+1];
+ char pine_pre_vers[10]; /* highest version previously run */
+***************
+*** 4228,4237 ****
+--- 4416,4436 ----
+ MAILSTREAM *mail_stream; /* ptr to current folder stream */
+ MSGNO_S *msgmap; /* ptr to current message map */
+
++ char *role; /* role used when composing */
++ int exiting;
++
+ unsigned read_predicted:1;
+
+ char cur_folder[MAXPATH+1];
++ QUOTALIST *quota;
+ char last_unambig_folder[MAXPATH+1];
++ int refresh_list;
++ int in_pico;
++ int in_fld_list;
++ int force_check_now;
++ int checking_incfld;
++ int incfld_timeout;
++ int delay;
+ ATTACH_S *atmts;
+ int atmts_allocated;
+ int remote_abook_validity; /* minutes, -1=never, 0=only on opens */
+***************
+*** 4255,4260 ****
+--- 4454,4461 ----
+ unsigned unseen_in_view:1;
+ unsigned start_in_context:1; /* start fldr_scrn in current cntxt */
+ unsigned def_sort_rev:1; /* true if reverse sort is default */
++ unsigned thread_def_sort_rev:1; /* true if reverse sort is default in thread screen */
++ unsigned msgmap_thread_def_sort_rev:1; /* true if reverse sort is being used in thread screen */
+ unsigned restricted:1;
+
+ unsigned save_msg_rule:5;
+***************
+*** 4265,4270 ****
+--- 4466,4472 ----
+ unsigned titlebar_color_style:3;
+ unsigned fld_sort_rule:3;
+ unsigned inc_startup_rule:3;
++ unsigned inc_check_rule:2;
+ unsigned pruning_rule:3;
+ unsigned reopen_rule:4;
+ unsigned goto_default_rule:3;
+***************
+*** 4356,4361 ****
+--- 4558,4566 ----
+
+ int *initial_cmds; /* cmds to execute on startup */
+ int *free_initial_cmds; /* used to free when done */
++ int *initial_cmds_backup; /* keep a copy in case they are freed */
++ int *free_initial_cmds_backup; /* free the copy */
++ int initial_cmds_offset; /* how many commands we have executed */
+
+ char c_client_error[300]; /* when nowhow_error is set and PARSE */
+
+***************
+*** 4392,4397 ****
+--- 4597,4605 ----
+ EditWhich ew_for_other_take;
+
+ SortOrder def_sort, /* Default sort type */
++ thread_def_sort, /* Default Sort Type in Thread Screen */
++ thread_cur_sort, /* current sort style for threads */
++ msgmap_thread_sort,
+ sort_types[22];
+
+ int last_expire_year, last_expire_month;
+***************
+*** 4404,4409 ****
+--- 4612,4620 ----
+
+ int nmw_width;
+
++ char *subject;
++ int send_immediately;
++
+ int hours_to_timeout;
+
+ int tcp_query_timeout;
+***************
+*** 4425,4430 ****
+--- 4636,4642 ----
+ INIT_ERR_S *init_errs;
+
+ PRINT_S *print;
++ PRULELIST_S *rule_list;
+
+ struct variable *vars;
+ };
+***************
+*** 4552,4557 ****
+--- 4764,4770 ----
+ void gf_busy PROTO((FILTER_S *, int));
+ void gf_nvtnl_local PROTO((FILTER_S *, int));
+ void gf_local_nvtnl PROTO((FILTER_S *, int));
++ void gf_quote_test PROTO((FILTER_S *, int));
+ void gf_line_test PROTO((FILTER_S *, int));
+ void *gf_line_test_opt PROTO((linetest_t, void *));
+ LT_INS_S **gf_line_test_new_ins PROTO((LT_INS_S **, char *, char *, int));
+***************
+*** 4588,4599 ****
+--- 4801,4817 ----
+ char *folder_is_nick PROTO((char *, void *, int));
+ char *next_folder PROTO((MAILSTREAM **, char *, char *,CONTEXT_S *,
+ long *, int *));
++ int next_folder_check PROTO((MAILSTREAM **, CONTEXT_S *, long *, long *,
++ FOLDER_S *, int *));
+ void init_inbox_mapping PROTO((char *, CONTEXT_S *));
+ int news_build PROTO((char *, char **, char **, BUILDER_ARG *, int *));
+ char *news_group_selector PROTO((char **));
+ void free_newsgrp_cache PROTO(());
+ char *context_edit_screen PROTO((struct pine *, char *, char *,
+ char *, char *, char *));
++ void update_incoming_folder_data PROTO((MAILSTREAM *, CONTEXT_S *));
++ FOLDER_S *incoming_folder_data PROTO((MAILSTREAM *, CONTEXT_S *));
++ int need_folder_report PROTO ((char *));
+ SELECTED_S *new_selected PROTO((void));
+ void free_selected PROTO((SELECTED_S **));
+ int add_new_folder PROTO((CONTEXT_S *, EditWhich, int, char *, size_t,
+***************
+*** 4615,4620 ****
+--- 4833,4839 ----
+ #endif
+
+ /*-- imap.c --*/
++ void pine_parse_quota PROTO((MAILSTREAM *, unsigned char *msg,QUOTALIST *));
+ char *cached_user_name PROTO((char *));
+ void imap_flush_passwd_cache PROTO(());
+ long pine_tcptimeout PROTO((long, long));
+***************
+*** 4647,4653 ****
+ int write_pinerc PROTO((struct pine *, EditWhich, int));
+ int var_in_pinerc PROTO((char *));
+ void free_pinerc_lines PROTO((PINERC_LINE **));
+! int decode_sort PROTO((char *, SortOrder *, int *));
+ void dump_global_conf PROTO((void));
+ void dump_new_pinerc PROTO((char *));
+ int set_variable PROTO((int, char *, int, int, EditWhich));
+--- 4866,4872 ----
+ int write_pinerc PROTO((struct pine *, EditWhich, int));
+ int var_in_pinerc PROTO((char *));
+ void free_pinerc_lines PROTO((PINERC_LINE **));
+! int decode_sort PROTO((char *, SortOrder *, int *, int));
+ void dump_global_conf PROTO((void));
+ void dump_new_pinerc PROTO((char *));
+ int set_variable PROTO((int, char *, int, int, EditWhich));
+***************
+*** 4678,4683 ****
+--- 4897,4903 ----
+ NAMEVAL_S *titlebar_col_style PROTO((int));
+ NAMEVAL_S *fld_sort_rules PROTO((int));
+ NAMEVAL_S *incoming_startup_rules PROTO((int));
++ NAMEVAL_S *incoming_check_rules PROTO((int));
+ NAMEVAL_S *startup_rules PROTO((int));
+ NAMEVAL_S *pruning_rules PROTO((int));
+ NAMEVAL_S *reopen_rules PROTO((int));
+***************
+*** 4720,4729 ****
+ int set_mime_extension_by_type PROTO((char *, char *));
+
+ /*---- mailcmd.c ----*/
+ int process_cmd PROTO((struct pine *, MAILSTREAM *, MSGNO_S *,
+ int, CmdWhere, int *));
+ int apply_command PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int,
+! int, int));
+ int menu_command PROTO((int, struct key_menu *));
+ void menu_init_binding PROTO((struct key_menu *, int, int,
+ char *, char *, int));
+--- 4940,4950 ----
+ int set_mime_extension_by_type PROTO((char *, char *));
+
+ /*---- mailcmd.c ----*/
++ MAILSTREAM *find_open_stream PROTO((void));
+ int process_cmd PROTO((struct pine *, MAILSTREAM *, MSGNO_S *,
+ int, CmdWhere, int *));
+ int apply_command PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int,
+! int, int, int));
+ int menu_command PROTO((int, struct key_menu *));
+ void menu_init_binding PROTO((struct key_menu *, int, int,
+ char *, char *, int));
+***************
+*** 4766,4771 ****
+--- 4987,4993 ----
+ char *get_uname PROTO((char *, char *, int));
+ char *build_updown_cmd PROTO((char *, char *, char *, char*));
+ int file_lister PROTO((char *, char *, int, char *, int, int, int));
++ unsigned long rules_cursor_pos PROTO((MAILSTREAM *));
+ int display_folder_list PROTO((CONTEXT_S **, char *, int,
+ int (*) PROTO((struct pine *,
+ CONTEXT_S **,
+***************
+*** 4790,4795 ****
+--- 5012,5018 ----
+ #endif
+
+ /*--- mailindx.c ---*/
++ void insert_pattern_in_string PROTO((char *, char *, int));
+ void mail_index_screen PROTO((struct pine *));
+ int index_lister PROTO((struct pine *, CONTEXT_S *, char *,
+ MAILSTREAM *, MSGNO_S *));
+***************
+*** 4820,4826 ****
+ MSGNO_S *, IndexType, int *, int));
+ char *sort_name PROTO((SortOrder));
+ void sort_folder PROTO((MAILSTREAM *, MSGNO_S *,
+! SortOrder, int, unsigned));
+ int percent_sorted PROTO((void));
+ void msgno_init PROTO((MSGNO_S **, long));
+ void msgno_give PROTO((MSGNO_S **));
+--- 5043,5049 ----
+ MSGNO_S *, IndexType, int *, int));
+ char *sort_name PROTO((SortOrder));
+ void sort_folder PROTO((MAILSTREAM *, MSGNO_S *,
+! SortOrder, int, unsigned, int));
+ int percent_sorted PROTO((void));
+ void msgno_init PROTO((MSGNO_S **, long));
+ void msgno_give PROTO((MSGNO_S **));
+***************
+*** 4843,4849 ****
+ void free_pine_elt PROTO((void **));
+ SEARCHSET *build_searchset PROTO((MAILSTREAM *));
+ void collapse_or_expand PROTO((struct pine *, MAILSTREAM *, MSGNO_S *,
+! unsigned long));
+ PINETHRD_S *fetch_thread PROTO((MAILSTREAM *, unsigned long));
+ PINETHRD_S *fetch_head_thread PROTO((MAILSTREAM *));
+ int view_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int));
+--- 5066,5072 ----
+ void free_pine_elt PROTO((void **));
+ SEARCHSET *build_searchset PROTO((MAILSTREAM *));
+ void collapse_or_expand PROTO((struct pine *, MAILSTREAM *, MSGNO_S *,
+! unsigned long, int));
+ PINETHRD_S *fetch_thread PROTO((MAILSTREAM *, unsigned long));
+ PINETHRD_S *fetch_head_thread PROTO((MAILSTREAM *));
+ int view_thread PROTO((struct pine *, MAILSTREAM *, MSGNO_S *, int));
+***************
+*** 4891,4896 ****
+--- 5114,5121 ----
+ int, char *));
+
+ /*--- mailview.c ---*/
++ int select_quote PROTO((long, char *, LT_INS_S **, void *));
++ int next_level_quote PROTO((char *, char **, int, int));
+ void mail_view_screen PROTO((struct pine *));
+ int scrolltool PROTO((SCROLL_S *));
+ char *body_type_names PROTO((int));
+***************
+*** 4937,4942 ****
+--- 5162,5169 ----
+ void check_point_change PROTO((MAILSTREAM *));
+ void reset_check_point PROTO((MAILSTREAM *));
+ void zero_new_mail_count PROTO((void));
++ int new_mail_incfolder PROTO((struct pine *, int));
++ char *new_mail_in_open_stream PROTO((MAILSTREAM *, long *, long *));
+ int changes_to_checkpoint PROTO((MAILSTREAM *));
+ void close_newmailfifo PROTO((void));
+ void init_newmailfifo PROTO((char *));
+***************
+*** 5122,5133 ****
+--- 5349,5362 ----
+ int sp_flagged PROTO((MAILSTREAM *, unsigned long));
+ void sp_mark_stream_dead PROTO((MAILSTREAM *));
+ MAILSTREAM *sp_stream_get PROTO((char *, unsigned long));
++ MAILSTREAM *sp_stream_status_get PROTO((char *));
+ int sp_a_locked_stream_is_dead PROTO((void));
+ int sp_a_locked_stream_changed PROTO((void));
+ MAILSTREAM *sp_inbox_stream PROTO((void));
+ void sp_cleanup_dead_streams PROTO((void));
+ int sp_nremote_permlocked PROTO((void));
+ void sp_end PROTO((void));
++ void sp_status_end PROTO((void));
+
+ /*-- reply.c --*/
+ void reply PROTO((struct pine *, ACTION_S *));
+***************
+*** 5138,5144 ****
+ ENVELOPE *, ADDRESS **, ADDRESS **,
+ ADDRESS **, ADDRESS **,int *));
+ int reply_news_test PROTO((ENVELOPE *, ENVELOPE *));
+! int reply_text_query PROTO((struct pine *, long, char **));
+ BODY *reply_body PROTO((MAILSTREAM *, ENVELOPE *, BODY *, long,
+ char *, void *, char *, int, ACTION_S *, int,
+ REDRAFT_POS_S **));
+--- 5367,5373 ----
+ ENVELOPE *, ADDRESS **, ADDRESS **,
+ ADDRESS **, ADDRESS **,int *));
+ int reply_news_test PROTO((ENVELOPE *, ENVELOPE *));
+! int reply_text_query PROTO((struct pine *, long, ENVELOPE *, char **));
+ BODY *reply_body PROTO((MAILSTREAM *, ENVELOPE *, BODY *, long,
+ char *, void *, char *, int, ACTION_S *, int,
+ REDRAFT_POS_S **));
+***************
+*** 5185,5190 ****
+--- 5414,5459 ----
+ void standard_picobuf_setup PROTO((PICO *));
+ void standard_picobuf_teardown PROTO((PICO *));
+
++ /* -- rules.c -- */
++ RULE_RESULT *get_result_rule PROTO ((int, int, ENVELOPE *));
++ char *test_rule PROTO ((RULELIST *, int, ENVELOPE *, int *));
++ char *process_rule PROTO ((RULE_S *, int, ENVELOPE *));
++ int test_condition PROTO ((CONDITION_S *, int, ENVELOPE *));
++ int test_in PROTO ((CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int));
++ int test_ni PROTO ((CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int));
++ int test_not_in PROTO ((CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int));
++ int test_not_ni PROTO ((CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int));
++ int test_eq PROTO ((CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int));
++ int test_not_eq PROTO ((CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int));
++ int isolate_condition PROTO ((char *, char **, int *));
++ int condition_contains_token PROTO((CONDITION_S *, char *));
++ char *trim PROTO ((RULEACTION_S *, int, ENVELOPE *));
++ char *rextrim PROTO ((RULEACTION_S *, int, ENVELOPE *));
++ char *raw_value PROTO ((RULEACTION_S *, int, ENVELOPE *));
++ char *extended_value PROTO ((RULEACTION_S *, int, ENVELOPE *));
++ char *expand PROTO ((char *, char *));
++ char *get_name_token PROTO ((char *));
++ char *advance_to_char PROTO ((char *, char, int, int *));
++ void free_token_value PROTO ((TOKEN_VALUE **));
++ void free_condition PROTO ((CONDITION_S **));
++ void free_ruleaction PROTO ((RULEACTION_S **));
++ void free_rule PROTO ((RULE_S **));
++ void free_rule_list PROTO ((RULELIST **));
++ void free_parsed_rule_list PROTO((PRULELIST_S **));
++ void *alloc_mem PROTO ((size_t));
++ void add_rule PROTO ((int, int));
++ void create_rule_list PROTO ((void));
++ RULE_S *parse_rule PROTO ((char *, int));
++ RULE_S *get_rule PROTO ((RULELIST *, int));
++ RULELIST *get_rule_list PROTO ((char **, int, int));
++ RULELIST *get_rulelist_from_code PROTO((int, PRULELIST_S *));
++ TOKEN_VALUE *parse_group_data PROTO ((char *,int *));
++ TOKEN_VALUE *copy_parsed_value PROTO((TOKEN_VALUE *, int, ENVELOPE *));
++ CONDITION_S *fill_condition PROTO ((char *));
++ CONDITION_S *parse_condition PROTO ((char *, int *));
++ PRULELIST_S *add_prule PROTO ((PRULELIST_S *, PRULELIST_S *));
++ RULEACTION_S *parse_action PROTO ((char *, int));
++
+ /*-- screen.c --*/
+ void draw_keymenu PROTO((struct key_menu *, bitmap_t, int, int,
+ int, OtherMenu));
+***************
+*** 5309,5314 ****
+--- 5578,5584 ----
+ void removing_leading_white_space PROTO((char *));
+ void removing_leading_and_trailing_white_space PROTO((char *));
+ int removing_double_quotes PROTO((char *));
++ void removing_extra_stuff PROTO((char *));
+ char *skip_white_space PROTO((char *));
+ char *skip_to_white_space PROTO((char *));
+ char *removing_quotes PROTO((char *));
+***************
+*** 5490,5495 ****
+--- 5760,5766 ----
+ void MoveCursor PROTO((int, int));
+ void NewLine PROTO((void));
+ int config_screen PROTO((struct ttyo **));
++ void fake_config_screen PROTO((struct ttyo **));
+ void init_screen PROTO((void));
+ void end_screen PROTO((char *, int));
+ void outchar PROTO((int));
+diff -rc pine4.63/pine/pine.hlp pine4.63.I.USE/pine/pine.hlp
+*** pine4.63/pine/pine.hlp Thu Apr 28 10:22:02 2005
+--- pine4.63.I.USE/pine/pine.hlp Thu May 19 19:59:15 2005
+***************
+*** 457,462 ****
+--- 457,463 ----
+ <P>
+ Some topics of current interest include:
+ <UL>
++ <P><LI> Information on <A HREF="h_patches">patches for this release</A>
+ <P><LI> <A HREF="h_maildrop">Mail Drops</A>
+ <P><LI> Information on <A HREF="h_info_on_locking">Folder Locking</A>
+ <P><LI> Information on <A HREF="h_info_on_mbox">Missing mail and the mbox driver</A>
+***************
+*** 1081,1086 ****
+--- 1082,1143 ----
+ &lt;End of Configuration Notes&gt;
+ </BODY>
+ </HTML>
++ ====== h_patches ======
++ <html>
++ <head>
++ <TITLE>Information on patches added to this release</TITLE>
++ </head>
++ <body>
++ <H1>Information on patches added to this release</H1>
++ <P>
++ This version of Pine has been modified by including patches from
++ <A HREF="http://www.math.washington.edu/~chappa/pine/">
++ http://www.math.washington.edu/~chappa/pine/</A>. These patches include
++ new features and bug fixes. More complete information on each patch
++ included in this version can be found in the web.
++
++ <P>If you have any problems with this release of Pine, please contact
++ Eduardo Chappa &lt;chappa@math.washington.edu&gt;. Include the word
++ &quot;Pine&quot; in the subject of the message to bypass spam filters.
++
++ <P>The list of patches included in this release are:
++
++ <P>New Features:
++
++ <UL>
++ <LI> Maildir Patch. <A HREF="h_config_maildir">(more...)</A>
++ <LI> Enhanced fancy thread interface.
++ <A HREF="h_config_enhanced_thread">(more...)</A>
++ <LI> Pine justifies paragraphs with more than one level of indentation.
++ <A HREF="h_compose_justify">(more...)</A>
++ <LI> Rules patch, to make Pine flexible.
++ <A HREF="h_config_new_rules">(more...)</A>
++ <LI> Send mail from the command line.
++ <LI> Automatic check of new mail in incoming folders.
++ <A HREF="h_config_enable_check_incoming">(more...)</A>
++ <LI> Write accents like &aacute;&eacute; or other foreing characters: &ntilde; etc.
++ <LI> Tab check folders on cycles.
++ <A HREF="h_config_circular_tab">(more...)</A>
++ <LI> Get the number of new messages when opening a folder.
++ <LI> Reinsert the pattern you searched for last.
++ <LI> New Reply command menu.
++ <A HREF="h_config_alt_reply_menu">(more...)</A>
++ <LI> Change your From header without any effort!
++ <LI> Choose a role when composing a message from a mailto: link.
++ <LI> Paint special text in the body of the message in any custom color.
++ <A HREF="h_config_special_text_to_color">(more...)</A>
++ <LI> Select messages by the content of an arbitrary header.
++ <LI> Delete until the the end of a file, or message (press ^W^X).
++ <LI> Get the QUOTA information from an IMAP server (if such server supports
++ the QUOTA command).
++ </UL>
++ <P> Bug Fixes:
++ <UL>
++ <LI> Fix a bug which could make the sort by score be computed incorrectly.
++ </UL>
++
++ </body>
++ </html>
+ ====== h_news_legal ======
+ <html>
+ <head>
+***************
+*** 3091,3097 ****
+--- 3148,3156 ----
+ <li><a href="h_config_alt_role_menu">FEATURE: Alternate-Role-Menu</a>
+ <li><a href="h_config_force_low_speed">FEATURE: Assume-Slow-Link</a>
+ <li><a href="h_config_auto_read_msgs">FEATURE: Auto-Move-Read-Msgs</a>
++ <li><a href="h_config_auto_read_msgs_rules">FEATURE: auto-move-read-msgs-using-rules</a>
+ <li><a href="h_config_auto_open_unread">FEATURE: Auto-Open-Next-Unread</a>
++ <li><a href="h_config_circular_tab">FEATURE: enable-circular-tab</a>
+ <li><a href="h_config_auto_unzoom">FEATURE: Auto-Unzoom-After-Apply</a>
+ <li><a href="h_config_auto_zoom">FEATURE: Auto-Zoom-After-Select</a>
+ <li><a href="h_config_check_mail_onquit">FEATURE: Check-Newmail-When-Quitting</a>
+***************
+*** 3349,3354 ****
+--- 3408,3414 ----
+ <li><a href="h_config_abook_formats">OPTION: Addressbook-Formats</a>
+ <li><a href="h_config_alt_addresses">OPTION: Alt-Addresses</a>
+ <li><a href="h_config_char_set">OPTION: Character-Set</a>
++ <li><a href="h_config_special_text_to_color">OPTION: Special Text to Color</a>
+ <li><a href="h_config_color_style">OPTION: Color-Style</a>
+ <li><a href="h_config_composer_wrap_column">OPTION: Composer-Wrap-Column</a>
+ <li><a href="h_config_index_color_style">OPTION: Current-Indexline-Style</a>
+***************
+*** 3449,3457 ****
+--- 3509,3519 ----
+ <li><a href="h_config_sending_filter">OPTION: Sending-Filters</a>
+ <li><a href="h_config_sendmail_path">OPTION: Sendmail-Path</a>
+ <li><a href="h_config_signature_color">OPTION: Signature Color</a>
++ <li><a href="h_config_special_text_color">OPTION: Special Text Color</a>
+ <li><a href="h_config_signature_file">OPTION: Signature-File</a>
+ <li><a href="h_config_smtp_server">OPTION: SMTP-Server</a>
+ <li><a href="h_config_sort_key">OPTION: Sort-Key</a>
++ <li><a href="h_config_thread_sort_key">OPTION: Thread-Sort-Key</a>
+ <li><a href="h_config_speller">OPTION: Speller</a>
+ <li><a href="h_config_sshcmd">OPTION: Ssh-Command</a>
+ <li><a href="h_config_ssh_open_timeo">OPTION: Ssh-Open-Timeout</a>
+***************
+*** 5297,5302 ****
+--- 5359,5517 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ======= h_thread_index_sort_arrival =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Arrival</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Arrival</H1>
++
++ The <EM>Arrival</EM> sort option arranges threads according to the last
++ time that a message was added to it. In this order the last thread
++ contains the most recent message in the folder.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_date =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Date</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Date</H1>
++
++ The <EM>Date</EM> sort option in the THREAD&nbsp;INDEX screen is the same
++ as sorting by thread, the most likely thing is that you won't see Pine
++ sorting the folder, because it's already sorted.
++
++ <P>
++ On a folder like INBOX, sorting by &quot;Date&quot; should be almost
++ identical to sorting by &quot;Arrival&quot;.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_subj =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Subject</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Subject</H1>
++
++ The <EM>Subject</EM> sort option has not been defined yet.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_ordsubj =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: OrderedSubject</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: OrderedSubject</H1>
++
++ The <EM>OrderedSubject</EM> sort option in the THREAD&nbsp;INDEX screen is
++ the same as sorting by <A HREF="h_thread_index_sort_subj">Subject</A>.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_thread =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Thread</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Thread</H1>
++
++ The <EM>Thread</EM> sort option in the THREAD&nbsp;INDEX screen sorts all
++ messages by the proposed algorithm by Crispin and Murchison. In this
++ method of sorting once threads have been isolated they are sorted by the
++ date of their parents, or if that is missing, the first message in that
++ thread.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_from =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: From</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: From</H1>
++
++ The <EM>From</EM> sort option has not been defined yet.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_size =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Size</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Size</H1>
++
++ The <EM>Size</EM> sort option has not been defined yet.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_score =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Score</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Score</H1>
++
++ The <EM>Score</EM> sort option has not been defined yet.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_to =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: To</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: To</H1>
++
++ The <EM>To</EM> sort option has not been defined yet.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ======= h_thread_index_sort_cc =======
++ <HTML>
++ <HEAD>
++ <TITLE>SORT OPTION: Cc</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>SORT OPTION: Cc</H1>
++
++ The <EM>Cc</EM> sort option has not been defined yet.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ======= h_index_cmd_whereis =======
+ <HTML>
+ <HEAD>
+***************
+*** 6515,6520 ****
+--- 6730,6775 ----
+ not preserved.
+
+ <P>
++ This version of Pine contains an enhanced algorithm for justification,
++ which allows you to justify text that contains more complicated quote
++ strings. This algorithm is based on pragmatics, rather than on a theory,
++ and seems to work well with most messages. Below you will find technical
++ information on how this algorithm works.
++
++ <P>
++ When justifying, Pine goes through each line of the text and tries to
++ determine for each line what the quote string of that line is. The quote
++ string you provided is always recognized. Among other characters
++ recognized is &quot;&gt;&quot;.
++
++ <P>
++ Some other constructions of quote strings are recognized only if they
++ appear enough in the text. For example &quot;Peter :&quot; is only
++ recognized if it appears in two consecutive lines.
++
++ <P>
++ Additionaly, Pine recognizes indent-strings and justifies text in a
++ paragraph to the right of indent-string, padding with spaces if necessary.
++ An indent string is one which you use to delimit elements of a list. For
++ example, if you were to write a list of groceries, one may write:
++
++ <UL>
++ <LI> Fruit
++ <LI> Bread
++ <LI> Eggs
++ </UL>
++
++ <P>
++ In this case the character &quot;*&quot; is the indent-string. Pine
++ recognizes numbers (0, 1, 2.5, etc) also as indent-strings, and certain
++ combinations of spaces, periods, and parenthesis. In any case, numbers are
++ recognized <B>ONLY</B> if the line preceeding the given line is empty or
++ ends in one of the characters &quot;.&quot; or &quot;:&quot;.
++ In addition to the explanation of what constitutes a paragraph above, a
++ new paragraph is recognized when an indent-string is found in it (and
++ validated according to the above stated rules).
++
++ <P>
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
+***************
+*** 17318,17323 ****
+--- 17573,17579 ----
+ <A HREF="h_config_index_format">&quot;Index-Format&quot;</A> option,
+ in the <A HREF="h_config_reply_intro">&quot;Reply-Leadin&quot;</A> option,
+ in signature files,
++ in the <A HREF="h_config_reply_leadin_rules">&quot;new-rules&quot; option</A>,
+ in template files used in
+ <A HREF="h_rules_roles">&quot;roles&quot;</A>, and in the folder name
+ that is the target of a Filter Rule.
+***************
+*** 17330,17336 ****
+ <P>
+ <P>
+
+! <H1><EM>Tokens Available for all Cases (except Filter Rules)</EM></H1>
+
+ <DL>
+ <DT>SUBJECT</DT>
+--- 17586,17592 ----
+ <P>
+ <P>
+
+! <H1><EM>Tokens Available for all Cases (except Filter Rules or in some cases for new-rules)</EM></H1>
+
+ <DL>
+ <DT>SUBJECT</DT>
+***************
+*** 17352,17357 ****
+--- 17608,17622 ----
+ For example, &quot;mailbox@domain&quot;.
+ </DD>
+
++ <DT>ADDRESSTO</DT>
++ <DD>
++ This is similar to the &quot;TO&quot; token, only it is always the
++ email address of all people listed in the TO: field of the messages. Addresses
++ are separated by a blank space. Example, &quot;mailbox@domain&quot; when
++ the e-mail message contains only one person in the To: field, or
++ &quot;peter@flintstones.com president@world.com&quot;.
++ </DD>
++
+ <DT>MAILBOX</DT>
+ <DD>
+ This is the same as the &quot;ADDRESS&quot; except that the
+***************
+*** 17399,17404 ****
+--- 17664,17678 ----
+ message's &quot;Cc:&quot; header field.
+ </DD>
+
++ <DT>ADDRESSCC</DT>
++ <DD>
++ This is similar to the &quot;CC&quot; token, only it is always the
++ email address of all people listed in the Cc: field of the messages. Addresses
++ are separated by a blank space. Example: &quot;mailbox@domain&quot; when
++ the e-mail message contains only one person in the Cc: field, or
++ &quot;peter@flintstones.com president@world.com&quot;.
++ </DD>
++
+ <DT>RECIPS</DT>
+ <DD>
+ This token represents the personal names (or email addresses if the names
+***************
+*** 17407,17412 ****
+--- 17681,17694 ----
+ the message's &quot;Cc:&quot; header field.
+ </DD>
+
++ <DT>ADDRESSRECIPS</DT>
++ <DD>
++ This token represent the e-mail addresses of the people in the To: and
++ Cc: fields, exactly in that order separated by a space. It is almost obtained
++ by concatenating the ADDRESSTO and ADDRESSCC tokens.
++ </DD>
++
++
+ <DT>NEWSANDRECIPS</DT>
+ <DD>
+ This token represents the newsgroups from the
+***************
+*** 17779,17784 ****
+--- 18061,18074 ----
+ <P>
+ </DD>
+
++ <DT>SIZETHREAD</DT>
++ <DD>
++ This token represents the total size of the thread for a collapsed thread
++ or the size of the branch for an expanded thread. The field is omitted for
++ messages that are not top of threads nor branches and it defaults to
++ the SIZE token when your folders is not sorted by thread.
++ </DD>
++
+ <DT>SIZENARROW</DT>
+ <DD>
+ This token represents the total size, in bytes, of the message.
+***************
+*** 18134,18139 ****
+--- 18424,18501 ----
+ </DL>
+
+ <P>
++ <H1><EM>Tokens Available Only for New-Rules</EM></H1>
++
++ <DL>
++ <DT>FOLDER</DT>
++ <DD>
++ Name of the folder where the rule will be applied
++ </DD>
++ </DL>
++
++ <DL>
++ <DT>COLLECTION</DT>
++ <DD>
++ Name of the collection list where the rule will be applied.
++ </DD>
++ </DL>
++
++ <DL>
++ <DT>ROLE</DT>
++ <DD>
++ Name of the Role used to reply a message.
++ </DD>
++ </DL>
++
++ <DL>
++ <DT>BCC</DT>
++ <DD>
++ Not implemented yet, but it will be implemented in future versions. It will
++ be used for <A HREF="h_config_compose_rules">compose</A>
++ <A HREF="h_config_reply_rules">reply</A>
++ <A HREF="h_config_forward_rules">forward</A>
++ rules.
++ </DD>
++ </DL>
++
++ <DL>
++ <DT>LCC</DT>
++ <DD>
++ This is the value of the Lcc: field at the moment that you start the composition.
++ </DD>
++ </DL>
++
++ <DL>
++ <DT>FORWARDFROM</DT>
++ <DD>
++ This corresponds to the personal name (or address if there's no personal
++ name) of the person who sent the message that you are forwarding.
++ </DD>
++ </DL>
++
++ <DL>
++ <DT>FORWARDADDRESS</DT>
++ <DD>
++ This is the address of the person that sent the message that you
++ are forwarding.
++ </DD>
++ </DL>
++
++
++
++
++ <DL>
++ <DT>FLAG</DT>
++ <DD>
++ A string containing the value of all the flags associated to a specific
++ message. The possible values of allowed flags are "*" for Important, "N"
++ for recent or new, "U" for unseen or unread, "R" for seen or read, "A" for
++ answered and "D" for deleted. See an example of its use in the
++ <A HREF="h_config_new_rules">new rules</A> explanation and example help.
++ </DD>
++ </DL>
++
++ <P>
+ <H1><EM>Token Available Only for Templates and Signatures</EM></H1>
+
+ <DL>
+***************
+*** 18866,18871 ****
+--- 19228,19250 ----
+ be combined with the other fields if you'd like.
+
+ <End of help on this topic>
++ ====== h_config_check_inc_fld ======
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: incoming-folders-to-check</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: incoming-folders-to-check</H1>
++ <P>
++ if you set this option and <A HREF="h_config_enable_check_incoming">
++ enable-check-incoming-folders</A> then you can use this option to write a space
++ separate list of incoming folders where you want new mail to be
++ checked. If you want all your incoming folders to be checked just write a
++ "*" as the value for this option.
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ======= h_address_format =======
+ <HTML>
+ <HEAD>
+***************
+*** 19988,20048 ****
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
+! ====== h_config_literal_sig =====
+ <HTML>
+ <HEAD>
+! <TITLE>OPTION: Literal-Signature</TITLE>
+ </HEAD>
+ <BODY>
+! <H1>OPTION: Literal-Signature</H1>
+
+- With this option your actual signature, as opposed to
+- the name of a file containing your signature,
+- is stored in the Pine configuration file.
+- If this is defined it takes precedence over the Signature-File option.
+ <P>
+
+- This is simply a different way to store the signature.
+- The signature is stored inside your Pine configuration file instead of in
+- a separate file.
+- Tokens work the same way they do with the
+- <A HREF="h_config_signature_file">Signature-File</A> so look there for
+- help.
+ <P>
+
+- The Setup/Signature command on Pine's Main Menu will edit
+- the &quot;Literal-Signature&quot; by default. However, if no
+- &quot;Literal-Signature&quot; is defined and the file named in the
+- &quot;Signature-File&quot; option exists, then the latter will be used
+- instead.
+ <P>
+!
+! The two character sequence &#92;n (backslash followed by
+! the character n) will be used to signify a line-break in your signature.
+! You don't have to enter the &#92;n, but it will be visible in the
+! SETUP CONFIGURATION window after you are done editing the signature.
+
+ <P>
+! <UL>
+ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
+! </UL><P>
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
+! ====== h_config_signature_file =====
+ <HTML>
+ <HEAD>
+! <TITLE>OPTION: Signature-File</TITLE>
+ </HEAD>
+ <BODY>
+! <H1>OPTION: Signature-File</H1>
+
+! If a <A HREF="h_config_literal_sig">Literal-Signature</A> option is defined,
+! then this &quot;Signature-File&quot; option will be ignored.
+! You can tell that that is the case because the value of the
+! &quot;Signature-File&quot; will show up as
+ <P>
+! <CENTER><SAMP>&lt;Ignored: using Literal-Signature instead&gt;</SAMP></CENTER>
+ <P>
+ You may either use all Literal Signatures (signatures stored in your
+ configuration file) throughout Pine, or all signature files.
+--- 20367,20523 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
+! ====== h_config_maildir_location ======
+ <HTML>
+ <HEAD>
+! <TITLE>OPTION: maildir-location</TITLE>
+ </HEAD>
+ <BODY>
+! <H1>OPTION: maildir-location</H1>
+
+ <P>
++ This option should be used only if you have a Maildir folder which you
++ want to use as your INBOX. If this is not your case (or don't know what
++ this is), you can safely ignore this option.
+
+ <P>
++ This option overrides the default directory Pine uses to find the location of
++ your INBOX, in case this is in Maildir format. The default value of this
++ option is "Maildir", but in some systems, this directory could have been
++ renamed (e.g. to ".maildir"). If this is your case use this option to change
++ the default.
+
+ <P>
+! The value of this option is prefixed with the "~/" string to determine the
+! full path to your INBOX.
+
+ <P>
+! You should probably <A HREF="h_config_maildir">read</A> a few tips that
+! teach you how to configure your maildir for optimal performance. This
+! version also has <A HREF="h_config_courier_list">support</A> for the
+! Courier style file system when a maildir collection is accessed locally.
+!
+! <P><UL>
+ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
+! </UL>
+! <P>
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
+! ====== h_config_maildir =====
+ <HTML>
+ <HEAD>
+! <TITLE>Maildir Support</TITLE>
+ </HEAD>
+ <BODY>
+! <H1>Maildir Support</H1>
+
+! This version of Pine has been enhanced with Maildir support. This text is
+! intended to be a reference on its support.
+ <P>
+!
+! A Maildir folder is a directory that contains three directories called
+! cur, tmp and new. A program that delivers mail (e.g. postfix) will put new
+! mail in the new directory. A program that reads mail will look for for old
+! messages in the cur directory, while it will look for new mail in the new
+! directory.
+! <P>
+!
+! In order to use maildir support it is better to set your inbox-path to the
+! value &quot;#md/inbox&quot; (without quotes). This assumes that your mail
+! delivery agent is delivering new mail to ~/Maildir/new. If the directory
+! where new mail is being delivered is not called "Maildir", you can set the
+! name of the subdirectory of home where it is being delivered in the <A
+! HREF="h_config_maildir_location">maildir-location</A> configuration
+! variable. Most of the time you will not have to worry about the
+! maildir-location variable, because it will probably be set by your
+! administrator in the pine.conf configuration file.
+! <P>
+!
+! One of the advantages of the Maildir support of this version of Pine is
+! that you do not have to stop using folders in another styles (mbox, mbx,
+! etc.). This is desirable since the usage of a specific mail storage system
+! is a personal decision. Folders in the maildir format that are part of the
+! Mail collection will be recognized without any extra configuration of your
+! part. If your mail/ collection is located under the mail/ directory, then
+! creating a new maildir folder in this collection is done by pressing "A"
+! and entering the string "#driver.md/mail/newfolder". Observe that adding a
+! new folder as "newfolder" may not create such folder in maildir format.
+!
+! <P>
+! If you would like to have all folders created in the maildir format by
+! default, you do so by adding a Maildir Collection. In order to convert
+! your current mail/ collection into a maildir collection, edit the
+! collection and change the path variable from &quot;mail/&quot; to
+! &quot;#md/mail&quot;. In a maildir collection folders of any other format
+! are ignored.
+!
+! <P> Finally, This version also has
+! <A HREF="h_config_courier_list">support</A> for the Courier style file system
+! when a maildir collection is accessed locally.
+!
+! <P>
+! <UL>
+! <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
+! </UL><P>
+! &lt;End of help on this topic&gt;
+! </BODY>
+! </HTML>
+! ====== h_config_literal_sig =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: Literal-Signature</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: Literal-Signature</H1>
+!
+! With this option your actual signature, as opposed to
+! the name of a file containing your signature,
+! is stored in the Pine configuration file.
+! If this is defined it takes precedence over the Signature-File option.
+! <P>
+!
+! This is simply a different way to store the signature.
+! The signature is stored inside your Pine configuration file instead of in
+! a separate file.
+! Tokens work the same way they do with the
+! <A HREF="h_config_signature_file">Signature-File</A> so look there for
+! help.
+! <P>
+!
+! The Setup/Signature command on Pine's Main Menu will edit
+! the &quot;Literal-Signature&quot; by default. However, if no
+! &quot;Literal-Signature&quot; is defined and the file named in the
+! &quot;Signature-File&quot; option exists, then the latter will be used
+! instead.
+! <P>
+!
+! The two character sequence &#92;n (backslash followed by
+! the character n) will be used to signify a line-break in your signature.
+! You don't have to enter the &#92;n, but it will be visible in the
+! SETUP CONFIGURATION window after you are done editing the signature.
+!
+! <P>
+! <UL>
+! <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
+! </UL><P>
+! &lt;End of help on this topic&gt;
+! </BODY>
+! </HTML>
+! ====== h_config_signature_file =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: Signature-File</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: Signature-File</H1>
+!
+! If a <A HREF="h_config_literal_sig">Literal-Signature</A> option is defined,
+! then this &quot;Signature-File&quot; option will be ignored.
+! You can tell that that is the case because the value of the
+! &quot;Signature-File&quot; will show up as
+! <P>
+! <CENTER><SAMP>&lt;Ignored: using Literal-Signature instead&gt;</SAMP></CENTER>
+ <P>
+ You may either use all Literal Signatures (signatures stored in your
+ configuration file) throughout Pine, or all signature files.
+***************
+*** 20750,20755 ****
+--- 21225,21265 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_thread_sort_key =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: Thread-Sort-Key</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: Thread-Sort-Key</H1>
++
++ This option determines the order in which threads will be displayed. You
++ can choose from the following options.
++
++ <P>
++ <UL>
++ <LI> <A HREF="h_thread_index_sort_arrival">Arrival</A>
++ <!-- <LI> <A HREF="h_thread_index_sort_date">Date</A>
++ <LI> <A HREF="h_thread_index_sort_subj">Subject</A>
++ <LI> <A HREF="h_thread_index_sort_ordsubj">OrderedSubj</A>-->
++ <LI> <A HREF="h_thread_index_sort_thread">Thread</A>
++ <!-- <LI> <A HREF="h_thread_index_sort_from">From</A>
++ <LI> <A HREF="h_thread_index_sort_size">Size</A>
++ <LI> <A HREF="h_thread_index_sort_score">Score</A>
++ <LI> <A HREF="h_thread_index_sort_to">To</A>
++ <LI> <A HREF="h_thread_index_sort_cc">Cc</A>-->
++ </UL>
++
++ <P> Each type of sort may also be reversed. Normal default is by
++ &quot;Thread&quot;.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_other_startup =====
+ <HTML>
+ <HEAD>
+***************
+*** 20866,20898 ****
+ This option controls the order in which address book entries will be
+ presented. Choose one of the following:
+
+! <DL>
+! <DT>fullname</DT>
+! <DD>use fullname field, lists mixed in
+! </DD>
+
+! <DT>fullname-with-lists-last</DT>
+! <DD>use fullname field, but put lists at end
+! </DD>
+
+! <DT>nickname</DT>
+! <DD>use nickname field, lists mixed in
+! </DD>
+
+! <DT>nickname-with-lists-last</DT>
+! <DD>use nickname field, but put lists at end
+! </DD>
+
+! <DT>dont-sort</DT>
+! <DD>don't change order of file
+! </DD>
+! </DL>
+
+ <P>
+! The normal default is &quot;fullname-with-lists-last&quot;.
+
+ <P>
+! <UL>
+ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
+ </UL><P>
+ &lt;End of help on this topic&gt;
+--- 21376,22052 ----
+ This option controls the order in which address book entries will be
+ presented. Choose one of the following:
+
+! <DL>
+! <DT>fullname</DT>
+! <DD>use fullname field, lists mixed in
+! </DD>
+!
+! <DT>fullname-with-lists-last</DT>
+! <DD>use fullname field, but put lists at end
+! </DD>
+!
+! <DT>nickname</DT>
+! <DD>use nickname field, lists mixed in
+! </DD>
+!
+! <DT>nickname-with-lists-last</DT>
+! <DD>use nickname field, but put lists at end
+! </DD>
+!
+! <DT>dont-sort</DT>
+! <DD>don't change order of file
+! </DD>
+! </DL>
+!
+! <P>
+! The normal default is &quot;fullname-with-lists-last&quot;.
+!
+! <P>
+! <UL>
+! <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
+! </UL><P>
+! &lt;End of help on this topic&gt;
+! </BODY>
+! </HTML>
+! ====== h_config_compose_rules =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: Compose-Rule</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: Compose-Rule</H1>
+!
+! <P> At this time, this option is used to generate values for signature
+! files that is not possible to do with the use of
+! <A HREF="h_rules_roles">roles</A>.
+!
+! <P> For example, you can have a rule like:<BR>
+! _TO_ >> {Peter Flinstones} => _SIGNATURE_{~/.petersignature}
+!
+! <P> This configuration option is just one of many that allow you to
+! override the value of some global configurations within Pine. There is a
+! help text explaining how to define all of them, which you can read by
+! following this <A HREF="h_config_new_rules">link</A>.
+!
+! <P>&lt;End of help on this topic&gt;
+! </BODY>
+! </HTML>
+! ====== h_config_forward_rules =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: Forward-Rule</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: Forward-Rule</H1>
+!
+! <P> At this time this option can be used to trim values of some fields,
+! for example it can be used in the following way:
+!
+! <P>
+! _ROLE_ == {work} => _LCC_ := _TRIM_{_FORWARDFROM_ <_FORWARDADDRESS_>}
+!
+! <P> This configuration option is just one of many that allow you to
+! override the value of some global configurations within Pine. There is a
+! help text explaining how to define all of them, which you can read by
+! following this <A HREF="h_config_new_rules">link</A>.
+!
+! <P>&lt;End of help on this topic&gt;
+! </BODY>
+! </HTML>
+! ====== h_config_index_rules =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: Index-Rule</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: Index-Rule</H1>
+!
+! <P> This option is used to supercede the value of the option <A
+! HREF="h_config_index_format">index-format</A> for specific folders. In
+! this form you can have different index-formats for different folders. For
+! example an entry here may be:
+!
+! <P>
+! _FOLDER_ == {INBOX} => _INDEX_{IMAPSTATUS DATE FROM(33%) SIZE SUBJECT(67%)}
+!
+! <P> This configuration option is just one of many that allow you to
+! override the value of some global configurations within Pine. There is a
+! help text explaining how to define all of them, which you can read by
+! following this <A HREF="h_config_new_rules">link</A>.
+!
+! <P>&lt;End of help on this topic&gt;
+! </BODY>
+! </HTML>
+! ====== h_config_replace_rules =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: Replace-Rule</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: Replace-Rule</H1>
+!
+! <P> This option is used to have Pine print different values for specific
+! tokens in the <A HREF="h_config_index_format">index-format</A>. For example you
+! can replace strings like "To: newsgroup" by your name.
+!
+! <P> Here are examples of possible rules:<BR>
+! _FOLDER_ != {sent-mail} && _NICK_ != {} => _FROM_ := _REPLACE_{_FROM_ (_NICK_)}
+!
+! <P> or if you receive messages with tags that contain arbitrary numbers, and
+! you want them removed from the index (but not from the subject), use a rule
+! like the following<BR>
+! _FOLDER_ == {INBOX} => _SUBJECT_ := _REXTRIM_{&#92;[some-tag-here #[0-9].*&#92;]}
+!
+! <P> You can also use this configuration option to remove specific strings of
+! the index display screen, so that you can trim unnecessary information in
+! your index.
+!
+! <P> This configuration option is just one of many that allow you to
+! override the value of some global configurations within Pine. There is a
+! help text explaining how to define all of them, which you can read by
+! following this <A HREF="h_config_new_rules">link</A>.
+!
+! <P>&lt;End of help on this topic&gt;
+! </BODY>
+! </HTML>
+! ====== h_config_reply_leadin_rules =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: Reply-Leadin-Rule</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: Reply-Leadin-Rule</H1>
+!
+! <P> This option is used to have Pine generate a different
+! <A HREF="h_config_reply_intro">reply-leadin</A> string dependent either on
+! the person you are replying to, or the folder where the message is being
+! replied is in, or both.
+!
+! <P> Here there are examples of how this can be used. One can use the definition
+! below to post to newsgroups and the pine-info mailing list, say:
+! <P>
+! _FOLDER_ << {pine-info;_NEWS_} => _REPLY_{*** _FROM_ _ADDRESS_("_FROM_" "" "(_ADDRESS_) ")wrote in_NEWS_("" " the" "") _FOLDER_ _NEWS_("" "list " "")_SMARTDATE_("Today" "today" "on _LONGDATE_"):}
+!
+! <P> Here there is an example that one can use to change the reply indent string
+! to reply people that speak spanish.
+! <P>
+! _FROM_{Condorito;Quico} => _REPLY_{*** _FROM_ (_ADDRESS_) escribi&oacute; _SMARTDATE_("Today" "hoy" "en _LONGDATE_"):}
+!
+! <P> This configuration option is just one of many that allow you to
+! override the value of some global configurations within Pine. There is a
+! help text explaining how to define all of them, which you can read by
+! following this <A HREF="h_config_new_rules">link</A>.
+!
+! <P>&lt;End of help on this topic&gt;
+! </BODY>
+! </HTML>
+! ====== h_config_resub_rules =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: Replace-Subject-Rule</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: Replace-Subject-Rule</H1>
+!
+! <P> This option is used to have Pine generate a different subject when
+! replying rather than the one Pine would generate automatically.
+!
+! <P> Here there are a couple of examples about how to use this
+! configuration option:
+!
+! <P> In order to have messages with empty subject to be replied with the message
+! "your message" use the rule<BR>
+! <center>_SUBJECT_ == {} => _RESUB_{Re: your message}</center>
+!
+! <P> If you want to trim some parts of the subject when you reply use the
+! rule<BR>
+! <center>_SUBJECT_ >> {[one];two} => _SUBJECT_ := _TRIM_{[;];two}</center>
+!
+! <P>this rule removes the brackets "[" and "]" whenever the string "[one]"
+! appears in it, it also removes the word "two" from it.
+!
+! <P>Another example where you may want to use this rule is when you
+! correspond with people that change the reply string from &quot;Re:&quot;
+! to &quot;AW:&quot; or &quot;Sv:&quot;. In this case a rule like<BR>
+! <center>_SUBJECT_ >> {Sv: ;AW: } => _SUBJECT_ := _TRIM_{Sv: ;AW: }</center>
+! <P>
+! would eliminate undesired strings in replies.
+!
+! <P> You can also use this configuration option to customize reply subjects
+! according to the sender of the message.
+!
+! <P> This configuration option is just one of many that allow you to
+! override the value of some global configurations within Pine. There is a
+! help text explaining how to define all of them, which you can read by
+! following this <A HREF="h_config_new_rules">link</A>.
+!
+! <P>&lt;End of help on this topic&gt;
+! </BODY>
+! </HTML>
+! ====== h_config_sort_rules =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: Sort-Rule</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: Sort-Rule</H1>
+!
+! <P> This option is used to have Pine sort different folders in different orders
+! and thus override the value already set in the
+! <A HREF="h_config_sort_key">sort-key</A> configuration option.
+!
+! <P> Here's an example of the way it can be used. In this case all incoming
+! folders are mailing lists, except for INBOX, so we sort INBOX by arrival
+! (which is the default type of sort), but we want all the rest of mailing
+! lists and newsgroups to be sorted by thread.
+!
+! <P>
+! _COLLECTION_ >> {Incoming-Folders;News} && _FOLDER_ != {INBOX} => _SORT_{tHread}
+!
+! <P> Another example could be<BR>
+! _FOLDER_ == {Mailing List} => _SORT_{Reverse tHread}
+!
+! <P> This configuration option is just one of many that allow you to
+! override the value of some global configurations within Pine. There is a
+! help text explaining how to define all of them, which you can read by
+! following this <A HREF="h_config_new_rules">link</A>.
+!
+! <P>&lt;End of help on this topic&gt;
+!
+! </BODY>
+! </HTML>
+! ====== h_config_save_rules =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: Save-Rules</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: Save-Rules</H1>
+!
+! <P> This option is used to specify which folder should be used to save a
+! message depending either on the folder the message is in, who the message
+! is from, or text that the message contains in specific headers (Cc:,
+! Subject:, etc).
+!
+! <P> If this option is set and the
+! <A HREF="h_config_auto_read_msgs">auto-move-read-msgs</A> configuration
+! option is also set then these definitions will be used to move messages
+! from your INBOX when exiting Pine.
+!
+! <P>Here there are some examples<BR>
+! _FLAG_ >> {D} -> Trash<BR>
+! _FROM_ == {U2} -> Bono<BR>
+! _FOLDER_ == {comp.mail.pine} -> pine-stuff<BR>
+! _NICK_ != {} -> _NICK_/_NICK_<BR>
+! _DATEISO_ >> {02-10;02-11} -> archive-oct-nov-2002
+!
+! <P> This configuration option is just one of many that allow you to
+! override the value of some global configurations within Pine. There is a
+! help text explaining how to define all of them, which you can read by
+! following this <A HREF="h_config_new_rules">link</A>.
+!
+! <P>&lt;End of help on this topic&gt;
+!
+! </BODY>
+! </HTML>
+! ====== h_config_reply_indent_rules =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: Reply-indent-Rule</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: Reply-indent-Rule</H1>
+!
+! <P> This option is used to specify which reply-indent-string is to be used
+! when replying to an e-mail. If none of the rules are successful, the result in
+! the variable <a href="h_config_reply_indent_string">reply-indent-string</a>
+! is used.
+!
+! <P> The associated function to this configuration option is called "RESTR" (for
+! REply STRing). Some examples of its use are:<BR>
+! _FROM_ == {Your Boss} => _RESTR_{"> "}<BR>
+! _FROM_ == {My Wife} => _RESTR_{":* "}<BR>
+! _FROM_ == {Perter Flinstone;Wilma Flinstone} => _RESTR_{"_INIT_ > "}<BR>
+!
+! <P> This configuration option is just one of many that allow you to
+! override the value of some global configurations within Pine. There is a
+! help text explaining how to define all of them, which you can read by
+! following this <A HREF="h_config_new_rules">link</A>.
+!
+! <P>&lt;End of help on this topic&gt;
+!
+! </BODY>
+! </HTML>
+! ====== h_config_smtp_rules =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: SMTP-Rule</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: SMTP-Rule</H1>
+!
+! <P> This option is used to specify which SMTP server should be used when
+! sending a message, if this rule is not defined, or the execution of the rule
+! results in no server selected, then Pine will look for
+! the value from the role that is being used to compose the message. If no smtp
+! server is defined in that role or you are not using a role, then Pine will get
+! the name of the server from the
+! <A HREF="h_config_smtp_server">&quot;smtp-server&quot;</A> configuration
+! option according to the rules used in that variable.
+!
+! <P> The function associated to this configuration option is _SMTP_, an example
+! of the use of this function is<BR>
+! _ADDRESSTO_ == {peter@bedrock.com} => _SMTP_{smtp.bedrock.com}
+!
+! <P> This configuration option is just one of many that allow you to
+! override the value of some global configurations within Pine. There is a
+! help text explaining how to define all of them, which you can read by
+! following this <A HREF="h_config_new_rules">link</A>.
+!
+! <P>&lt;End of help on this topic&gt;
+!
+! </BODY>
+! </HTML>
+! ====== h_config_startup_rules =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: Startup-Rule</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: Startup-Rule</H1>
+!
+! <P> This option is used when a folder is being opened. You can use it to
+! specify its <A HREF="h_config_inc_startup">incoming-startup-rule</A> and override
+! Pine's global value set for all folders.
+!
+! <P> An example of the usage of this option is:<BR>
+! _FOLDER_ == {Lynx;pine-info;_NEWS_} => _STARTUP_{first-unseen}
+!
+! <P> This configuration option is just one of many that allow you to
+! override the value of some global configurations within Pine. There is a
+! help text explaining how to define all of them, which you can read by
+! following this <A HREF="h_config_new_rules">link</A>.
+!
+! <P>&lt;End of help on this topic&gt;
+!
+! </BODY>
+! </HTML>
+! ====== h_config_new_rules =====
+! <HTML>
+! <HEAD>
+! <TITLE>OPTION: New Rules Explained</TITLE>
+! </HEAD>
+! <BODY>
+! <H1>OPTION: New Rules Explained</H1>
+!
+! This is a quite powerful option. Here you can define rules that override
+! the values of any other global rule you have globally set in pine.
+!
+! <P>
+! For example, you can set your folders to be sorted in a certain way when
+! you open them (say by Arrival). You may not want to be this the behavior
+! of, say, a Newsgroup, maybe you would like there to have your folder to be
+! automatically ordered by Ordered Subject. The purpose of this feature is
+! to accomplish exactly that. You can use this option for defining such
+! exception and make Pine automatically sort your favorite Newsgroup by
+! Ordered Subject.
+!
+! <P>
+! On the other hand you may be suscribed to a mailing list, and maybe you
+! don't care to see in the index the size of the messages, however in other
+! lists you may want to see the size of the messages. You can use this
+! configuration for changing the way the index is displayed in a folder.
+!
+! <P>
+! Also there may be a mailing list that identifies itself by adding a
+! certain string to its subject which makes difficult to read the total
+! subject, so you may want to delete that string from the subject whenever
+! it appears. You can do that also with this configuration.
+!
+! <P>
+! You may also want to make your reply-leadin-string person or folder
+! dependent. You can do this with this feature (part of this feature can be
+! accomplised with the roles definitions, but roles are not the right tool
+! to do this as you will see).
+!
+! <P>
+! Every rule has three parts, a condition, a separator and an action. The
+! action is what will happen if the condition of the rule is satisified.
+!
+! <P>
+! Here is an example:
+!
+! <P>
+! _FROM_ == {Fred Flinstone} =&gt; _SAVE_{Fred}
+!
+! <P>
+! Here the separator is "=&gt;". Whatever is to the left of the separator
+! is the condition (that is to say _FROM_ == {Fred Flinstone}) and to the
+! right is the action (_SAVE_{Fred}). The condition means that the rule will
+! be applied only if the message that you are reading is from "Fred
+! Flinstone", and the action will be that you will be offered to save it in
+! the folder "Fred", whenever you press the letter "S" to save a message.
+!
+! <P>
+! The separator is always "=&gt;", with one exception to be seen later.
+! But for the most part this will be the only one you'll ever need.
+!
+! <P>
+! Now let us see how to do it. There are 12 functions already defined for
+! you. These are: _INDEX_, _REPLACE_, _REPLY_, _RESUB_, _SAVE_, _SIGNATURE_,
+! _SORT_, _STARTUP_, _TRIM_, _REXTRIM_, _THREADSTYLE and _THREADINDEX_. The
+! parameter of a function has to be enclosed between "{" and "}", so for
+! example you can specify _SAVE_{saved-messages} as a valid sentence.
+!
+! <P>
+! At the end of the document you will find more examples.Here is a short
+! description of what each function does:
+!
+! <P>
+! <UL>
+! <LI> _INDEX_ : This function takes as an argument an index-format, and
+! makes that the index-format for the specified folder.
+! <LI> _REPLACE_ : This function replaces the subject/from of the given e-mail by
+! another subject/from only when displaying the index.
+! <LI> _REPLY_ : This function takes as an argument a definition of a
+! reply-leadin-string and makes this the reply-leading-string of the
+! specified folder or person.
+! <LI> _RESTR_ : This function takes as an argument the value of the
+! reply-indent-string to be used to answer the message being replied to.
+! <LI> _RESUB_ : This function replaces the subject of the given e-mail by
+! another subject only when replying to a message.
+! <LI> _SAVE_ : The save function takes as an argument the name of a
+! possibly non existing folder, whenever you want to save a message, that
+! folder will be offered for you to save.
+! <LI> _SIGNATURE_ : This function takes as an argument a signature file and
+! uses that file as the signature for the message you are about to
+! compose/reply/forward.
+! <LI> _SMTP_ : This function takes as an argument the definition of a
+! SMTP server.
+! <LI> _SORT_ : This function takes as an argument a Sort Style, and sorts a
+! specified folder in that sort order.
+! <LI> _TRIM_ : This function takes as an argument a list of strings that
+! you want removed from another string. At this time this only works for
+! _FROM_ and _SUBJECT_.
+! <LI> _REXTRIM_ : Same as _TRIM_ but its argument is one and
+! only one extended regular expression.
+! <LI> _STARTUP_ : This function takes as an argument an
+! incoming-startup-rule, and open an specified folder using that rule.
+! <LI> _THREADSTYLE_ : This function takes as an argument a
+! threading-display-style and uses it to display threads in a folder.
+! <LI> _THREADINDEX_ : This function takes as an argument a
+! threading-index-style and uses it to display threads in a folder.
+! </UL>
+!
+! <P>
+! You must me wondering how to define the person/folder over who to apply
+! the action. This is done in the condition. When you specify a rule, the
+! rule is only executed if the condition is satisfied. In another words for
+! the rule:
+!
+! <P>
+! _FROM_ == {Fred Flinstone} =&gt; _SAVE_{Fred}
+!
+! <P>
+! it will only be applied if the from is "Fred Flinstone", if the From is
+! "Wilma Flinstone" the rule will be skipped.
+!
+! <P> In order to test a condition you can use the following tokens (in
+! alphabetical order): _ADDRESS_,_CC_, _FOLDER_, _FROM_,_NICK_, _ROLE,
+! _SENDER_, _SUBJECT_ and _TO_. The token will always be tested against what
+! it is between "{" and "}" in the condition, this part of the condition is
+! called the "condition set". The definition of each token can be found
+! <A HREF="h_index_tokens">here</A>.
+!
+! <P>
+! You can also test in different ways, you can
+! use the following "test operands": &lt;&lt;, !&lt;, &gt;&gt;, !&gt;, ==
+! and !=. All of them are two strings long. Here is the meaning of them:
+!
+! <P>
+! <UL>
+! <LI> &lt;&lt; : It tests if the value of the token is contained in
+! the condition set. Here for example if the condition set were equal to
+! "Freddy", then the condition: _NICK_ &lt;&lt; {Freddy}, would be true if
+! the value of _NICK_ were "Fred", "red" or "Freddy". You are just looking
+! for substrings here.
+! <LI> &gt;&gt; : It tests if the value of the token contains the value of
+! the condition set. Here for example if the condittion set were equal to
+! "Fred", then the condition: _FROM_ &gt;&gt; {Fred}, would be true if
+! the value of _FROM_ were "Fred Flinstone" or "Fred P. Flinstone" or "Freddy".
+! <LI> == : It tests if the value of the token is exactly equal to the value
+! of the set condition. For example _NICK_ == {Fred} will be false if the value
+! of _NICK_ is "Freddy" or "red".
+! <LI> !&lt; : This is true only when &lt;&lt; is false and viceversa.
+! <LI> !&gt; : This is true only when &gt;&gt; is false and viceversa.
+! <LI> != : This is true only when == is false and viceversa.
+! </UL>
+!
+! <P>
+! Now let us say that you want the same action to be applied to more than
+! one person or folder, say you want "folder1" and "folder2" to be sorted by
+! Ordered Subject upon entering. Then you can list them all of them in the
+! condition part separting them by a ";". Here is the way to do it.
+!
+! <P>
+! _FOLDER_ &lt;&lt; {folder1; folder2} =&gt; _SORT_{OrderedSubj}
+!
+! <P>
+! Here is the first subtelty about these definitions. Notice that the
+! following rule:
+!
+! <P>
+! _FOLDER_ == {folder1; folder2} =&gt; _SORT_{Reverse OrderedSubj}
+!
+! <P> works only for "folder1" but not for "folder2". This is because the
+! comparison of the name of the folder is done with whatever is in between
+! "{", ";" or "}", so in the above rule you would be testing <BR>
+! "folder2" == " folder2". The extra space makes the difference.
+! The reason why the first rule does not fail is because
+! "folder2" &lt;&lt; " folder2" is actually
+! true. If something ever fails this may be something to look into.
+!
+! <P>
+! Here are a few examples of what we have talked about before.
+!
+! <P>
+! _NICK_ == {lisa;kika} =&gt; _SAVE_{_NICK_/_NICK_} <BR>
+! This means that if the nick is lisa, it will
+! save the message in the folder "lisa/lisa", and if the nick
+! is "kika", it will save the message in the folder "kika/kika"
+!
+! <P>
+! _FOLDER_ == {Lynx} -&gt; lynx <BR>
+! This, is an abreviation of the following rule:<BR>
+! _FOLDER_ == {Lynx} =&gt; _SAVE_{lynx} <BR>
+! (note the change in separator from "=&gt;" to "-&gt;"). In the future
+! I will use that abreviation.
+!
+! <P> _FOLDER_ &lt;&lt; {comp.mail.pine; pine-info; pine-alpha} -&gt; pine <BR>
+! Any message in the folders "comp.mail.pine", "pine-info" or "pine-alpha"
+! will be saved to the folder "pine".
+!
+! <P> _FROM_ &lt;&lt; {Pine Master} -&gt; pine <BR>
+! Any message whose From field contains
+! "Pine Master" will be saved in the folder pine.
+!
+! <P> _FOLDER_ &lt;&lt; {Lynx; pine-info; comp.mail.pine} =&gt;
+! _INDEX_{IMAPSTATUS MSGNO DATE FROMORTO(33%) SUBJECT(66%)} <BR> Use a
+! different index-format for the folders "Lynx", "pine-info" and
+! "comp.mail.pine", where the size is not present.
+!
+! <P> _FOLDER_ == {Lynx;pine-info} =&gt; _REPLY_{*** _FROM_ (_ADDRESS_)
+! wrote in the _FOLDER_ list _SMARTDATE_("Today" "today" "on
+! _LONGDATE_"):}<BR> If a message is in one of the incoming folders "Lynx"
+! or "pine-info", create a reply-leadin-string that acknowledges that. Note
+! the absence of "," in the function _SMARTDATE_. For example answering to a
+! message in the pine-info list would look like:
+!
+! <P>
+! *** Steve Hubert (hubert@cac.washington.edu) wrote in the pine-info list today:
+!
+! <P>
+! However replying for a message in the Lynx list would look:
+!
+! <P>
+! *** mattack@area.com (mattack@area.com) wrote in the Lynx list today:
+!
+! <P>
+! If you write in more than one language you can use this feature to create
+! Reply-leadin-strings in different languages.
+!
+! <P> Note that at least for people you can create particular
+! reply-leadin-string using the role features, but it does not work as this
+! one does. This seems to be the right way to do it.
+!
+! <P> _FOLDER_ &lt;&lt; {Lynx; comp.mail.pine; pine_info; pine-alpha} =&gt;
+! _SORT_{OrderedSubj}<BR> This means upon opening, sort the folders "Lynx",
+! "comp.mail.pine", etc in ordered subject. All the others use the default
+! sort order. You can not sort in reverse in this form. The possible
+! arguments of this function are listed in the definition of the
+! default-sort-rule (Arrival, scorE, siZe, etc).
+!
+! <P> The last examples use the function _TRIM_ which has a special form.
+! This function can only be used in the index list.
+!
+! <P> _FOLDER_ &lt;&lt; {Lynx} =&gt; _SUBJECT_ := _TRIM_{lynx-dev }<BR> In
+! the folder "Lynx" eliminate from the subject the string "lynx-dev " (with
+! the space at the end). For example a message whose subject is "Re:
+! lynx-dev unvisited Visited Links", would be shown in the index with
+! subject: "Re: unvisited Visited Links", making the subject shorter and
+! giving the same information.
+!
+! <P> _FROM_ &gt;&gt; {Name (Comment)} =&gt; _FROM_ :=
+! _TRIM_{ (Comment)}<BR> Remove the part " (Comment)"
+! from the _FROM_, so when displaying in the index the real From "Name"
+! will appear.
+!
+! <P> _SUBJECT_ == {} =&gt; _RESUB_{Re: your mail without subject}
+! If there is no subject in the message, use the subject "Re: your mail
+! wiyhout subject" as a subject for the reply message.
+!
+! <P> You can add more complexity to your rules by checking more than one
+! conditions before a rule is executed. For example: Assume that you want to
+! answer every email that contains the string "bug report", with the subject
+! "Re: About your bug report", you could make
+!
+! <P>
+! _SUBJECT_ == {bug report} =&gt; _RESUB_{Re: About your _SUBJECT_}
+!
+! <P> The problem with this construction is that if the person emails you
+! back, then the next time you answer the message the subject will be: "Re:
+! About your Re: About your bug report", so it grew. You may want to avoid
+! this growth by using the following rule:
+!
+! <P>
+! _SUBJECT_ &gt;&gt; {bug report} && _SUBJECT_ !&gt; {Re: } =&gt; _RESUB_{Re: About your _SUBJECT_}<BR>
+
+! <P>
+! which will only add the string "Re: About your" only the first time the
+! message is replied.
+
+! <P>
+! Say your personal name is "Fred Flinstones", and assume that you don't
+! like to see "To: comp.mail.pine" in every post you make to this newsgroup,
+! but instead would like to see it as everyone else sees it. <BR>
+! _FOLDER_ == {comp.mail.pine} && _FROM_ == {Fred Flinstones} => _FROM_ := _REPLACE_{_FROM_}
+
+! <P>
+! You can also list your index by nick, in the following way:<BR>
+! _NICK_ != {} => _FROM_ := _REPLACE_{_NICK_}
+
+! <P>
+! If you want to open the folder "pine-info" in the first non-read message
+! use the rule:<BR>
+! _FOLDER_ == {pine-info} => _STARTUP_{first-unseen}
+
+ <P>
+! If you want to move your deleted messages to a folder, called "Trash", use
+! the following rule:<BR>
+! _FLAG_ >> {D} -> Trash
+
+ <P>
+! The reason why the above test is not "_FLAG_ == {D}" is because that would mean
+! that this is the only flag set in the message. It's better to test by containment in this case.
+!
+! <P> If you want to use a specific signature when you are in a specific collection
+! use the following rule:<BR>
+! _COLLECTION_ == {Mail} => _SIGNATURE_{/full/path/to/.signature}
+!
+! <P> Finally about the question of which rule will be executed. Only the
+! first rule that matches will be executed. It is important to notice though
+! that "saving" rules do not compete with "sorting" rules. So the first
+! "saving" rule that matches will be executed in the case of saving and so
+! on.
+!
+! <P> Here are some things to do still:
+! <UL>
+! <LI> To make _TRIM_ compatible with more tokens (_TO_, _SENDER_, etc)
+! <LI> To make this list dissapear!
+! </UL>
+!
+! <P>
+! <UL>
+ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
+ </UL><P>
+ &lt;End of help on this topic&gt;
+***************
+*** 21032,21037 ****
+--- 22186,22227 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_special_text_to_color =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: Special Text to Color</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: Specil Text to Color</H1>
++
++ Use this option to enter patterns (text or regular expressions) that Pine
++ will highlight in the body of the text that is not part of a handle (and
++ internal or external link that Pine paints in a different color).
++
++ <P>
++ Enter each pattern in a different line. Pine will internally merge these
++ patterns (by adding a "|" character), or you can add them all in one line
++ by separating them by a "|" character.
++
++ <P>
++ Pine will use the colors defined in the
++ <A HREF="h_config_special_text_color"> Special Text Color</A> variable.
++ to paint any match.
++
++ <P>
++ If the Special Text Color is not set, setting this variable will not
++ cause that special text to be indicated in any special way. It will look
++ like any normal text. You must set those colors in order to make Pine
++ paint the screen differently when it finds the patterns specified in this
++ variable.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_display_filters =====
+ <HTML>
+ <HEAD>
+***************
+*** 21850,21855 ****
+--- 23040,23077 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_inc_fld_timeo =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: inc-fld-timeout</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: inc-fld-timeout</H1>
++
++ When Pine is checking for new mail in an external incoming folder, and the
++ amount of time specified in this variable has elapsed without Pine being
++ able to connect to the server holding that mailbox, Pine will drop the
++ connection to that server and continue checking for new mail in other
++ incoming folders, if any.
++
++ <P>
++ Observe that Pine will not print an error message in this case, but it
++ will silently drop the connection. If your connections are fast setting
++ this to a large value will not cause you any problem, but if your
++ connections are slow setting this to a small value will make Pine speed
++ checking for new mail, although it is possible that not all of your
++ incoming folders will be checked for new mail.
++
++ <P>
++ The default is 5 seconds, which is also the minimum and the maximum is 60.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_incoming_folders =====
+ <HTML>
+ <HEAD>
+***************
+*** 24123,24128 ****
+--- 25345,25420 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_thread_display_style_rule =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: Threading-Display-Style-Rule</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: Threading-Display-Style-Rule</H1>
++
++ This option is very similar to <A HREF="h_config_thread_disp_style">
++ threading-display-style</A>, but it is a rule which specifies the
++ display styles for a thread that you want displayed in a specific
++ folder or collection.
++ <P>
++ The token to be used in this function is _THREADSTYLE_. Here there is
++ an example of its use
++ <P>
++ _FOLDER_ == {pine-info} => _THREADSTYLE_{mutt-like}
++ <P>
++ The values that can be given for the _THREADSTYLE_ function are the
++ values of the threading-display-style function, which can be found
++ listed in the <A HREF="h_config_thread_disp_style">threading-display-style</A>
++ configuration option.
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Pine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
++ ====== h_config_thread_index_style_rule =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: Threading-Index-Style-Rule</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: Threading-Index-Style-Rule</H1>
++
++ This option is very similar to <A HREF="h_config_thread_index_style">
++ threading-index-style</A>, but it is a rule which specifies the
++ index styles for a thread that you want displayed in a specific
++ folder or collection.
++ <P>
++ The token to be used in this function is _THREADINDEX_. Here there is
++ an example of its use
++ <P>
++ _FOLDER_ == {pine-info} => _THREADINDEX_{regular-index-with-expanded-threads}
++ <P>
++ The values that can be given for the _THREADINDEX_ function are the
++ values of the threading-index-display function, which can be found
++ listed in the <A HREF="h_config_thread_index_style">threading-index-display</A>
++ configuration option.
++
++ <P> This configuration option is just one of many that allow you to
++ override the value of some global configurations within Pine. There is a
++ help text explaining how to define all of them, which you can read by
++ following this <A HREF="h_config_new_rules">link</A>.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_pruning_rule =====
+ <HTML>
+ <HEAD>
+***************
+*** 24416,24421 ****
+--- 25708,25758 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_inc_rule =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: Incoming-Check-Rule</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: Incoming-Check-Rule</H1>
++
++ This value affects Pine's behavior when starting Pine. It determines
++ how and when Pine will check for new mail in your incoming folders. The
++ default value is &quot;automatic&quot;.
++
++ <P>
++ The three possible values for this option are:
++
++ <DL>
++ <DT>automatic</DT>
++ <DD>This is the default. When this is selected the first check for new
++ mail will be done when Pine is starting up and you either go to the
++ INDEX or FOLDER LIST screens.
++ </DD>
++
++ <DT>automatic-after-first-manual-check</DT>
++ <DD>Similar to the default, but no check is done until you force the first
++ one by pressing CTRL-H. All checks are automatic after the first one. Observe
++ that this feature does not work once an automatic check has been done.
++ </DD>
++
++ <DT>manual-only</DT>
++ <DD>This forces Pine to do only manual checks. This will probably speed
++ Pine, since checks will only happen when they are forced by pressing CTRL-H.
++ </DD>
++ </DL>
++
++ <P>
++ If you just want to stop Pine from checking in one folder, then simply
++ select that folder. Checks on that folder will be skipped.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_browser =====
+ <HTML>
+ <HEAD>
+***************
+*** 25490,25495 ****
+--- 26827,26909 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_enable_check_incoming ======
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: enable-check-incoming-folders</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: enable-check-incoming-folders</H1>
++ If you have enabled <A HREF="h_config_enable_incoming">incoming
++ folders</A> then setting this feature allows you to check for new mail in
++ these. A message stating that new mail was received and in which folders
++ will be written in the screen. You can decide which incoming folders you
++ want to check for new mail, and the list of them has to be entered in the
++ setting <A HREF="h_config_check_inc_fld">incoming-folders-to-check</A>.
++
++ <P> If you have the option
++ <A HREF="h_config_fast_recent">enable-fast-recent-test</A>
++ <B>disabled</B>, but have this feature enabled, then a full report on the
++ total number of messages, and the number of new messages in the folder is
++ printed in the <A HREF="h_folder_maint">FOLDER LIST</A> screen
++ for each folder listed in the variable
++ <A HREF="h_config_check_inc_fld">incoming-folders-to-check</A>. The report for each
++ folder is made in the format
++
++ <P>
++ folder-name [Number of new messages/Number of messages in the folder]
++
++ <P>
++ If an incoming folder is not listed in the variable
++ <A HREF="h_config_check_inc_fld">incoming-folders-to-check</A>, then only
++ the name of the folder and no other report is made about that folder.
++
++ <P>
++ Other important features related to this feature are:
++ <OL>
++ <LI><A HREF="h_config_enable_recheck_incoming">recheck-all-incoming-folders</A>,
++ which allows you to decide if you want to check all folders every check,
++ <LI><A HREF="h_config_inc_rule">incoming-check-rule</A>, which determines
++ how and when Pine will check for new mail in your incoming folders.
++ </OL>
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL>
++ </BODY>
++ </HTML>
++ ====== h_config_enable_recheck_incoming ======
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: recheck-all-incoming-folders</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: recheck-all-incoming-folders</H1>
++ If you have enabled <A HREF="h_config_enable_incoming">incoming folders</A>
++ and <A HREF="h_config_enable_check_incoming">enable-check-incoming-folder</A>
++ then setting this feature will force Pine to recheck all incoming folders
++ for new mail. The normal behavior (that is to say, when this feature
++ is not enabled) is that Pine will skip checking for new mail in folders
++ where it already found. This is done to speed checking for new mail.
++
++ <P>
++ The default behavior, however, can cause problems if you use two clients
++ to access the same incoming folders, because Pine will not realize that
++ new mail does not exist in one folder where it already reported new mail,
++ but was opened with the other client. Setting this feature will cause Pine
++ to recheck all folders all the time. In this way Pine will know for sure
++ which folders DO contain new mail.
++
++ <P> If you only use Pine to access your incoming folders, then DO NOT
++ enable this feature.
++
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL>
++ </BODY>
++ </HTML>
+ ====== h_config_attach_in_reply ======
+ <HTML>
+ <HEAD>
+***************
+*** 25788,25793 ****
+--- 27202,27223 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_use_domain =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: return-path-uses-domain-name </TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: return-path-uses-domain-name</H1>
++
++ If you enable this configuration option Pine will use your domain name and your
++ username in that domain name to construct your Return-Path header, if not Pine
++ will use the address that you have set in the From: field to construct it.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_use_sender_not_x =====
+ <HTML>
+ <HEAD>
+***************
+*** 25954,25959 ****
+--- 27384,27416 ----
+ successes. You will usually receive the full message back when there is
+ a failure.
+
++ <P> When this feature is <B>disabled</B>, and the feature
++ <A HREF="h_config_enable_check_incoming">enable-check-incoming-folders</A>
++ is enabled, then a full report of the number of messages and number of
++ new messages in each incoming folder listed in the option
++ <A HREF="h_config_check_inc_fld">incoming-folders-to-check</A> is made. This
++ report is printed in the <A HREF="h_folder_maint">FOLDER LIST</A> screen. The
++ report is given in the form
++
++ <P>
++ folder-name [Number of New Messages/Number of messages in the folder]
++
++ <P> If an incoming-folder is not listed in the variable
++ <A HREF="h_config_check_inc_fld">incoming-folders-to-check</A>, no check for
++ that folder is made, so only the folder name, and no other information is
++ printed about that folder.
++
++ <P> If this feature is enabled and the feature
++ <A HREF="h_config_enable_recheck_incoming">recheck-all-incoming-folders</A>
++ is disabled, then selecting a folder will cancel further checks on that
++ folder. This is useful if checks to a particular incoming folder are slow
++ and want to be avoided (until the folder is unselected and a new cycle of
++ checks is done) without changing the list of folders to be checked.
++ Selecting a folder in order to avoid checks for new mail does not work in
++ other cases, since it is either explicitly requested this way or because
++ it is necessary to update the count of new and total number of messages of
++ every requested folder.
++
+ <P>
+ If you turn on the DSNOpts the default is to return as much information as
+ possible to you. That is, by default, the Success and Delay options are
+***************
+*** 26332,26337 ****
+--- 27789,27846 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_alt_reply_menu =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: alternate-reply-menu</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: alternate-reply-menu</H1>
++
++ This feature controls the menu that is displayed when Reply is selected.
++ If set, a list of options will be presented, with each option representing
++ the type of composition that could be used. This feature is most useful
++ for users who want to avoid being prompted with each option separately, or
++ would like to override some defaults set in your configuration for the
++ message that you are replying (e.g. you may have set the option to strip
++ signatures, but for the message you are answering you would like not to do
++ that)
++
++ <P>
++ The way this feature works is as follows. Initially you get the question
++ if you want to include the message, and in the menu you will see several
++ options, each option is accompanied by some text explaining what will
++ happen if you press the associated command. For example, if you read the
++ text &quot;S Strip Sig&quot;, it means that if you press the letter
++ &quot;S&quot; the signature will be stripped off the message you are
++ replying. Observer that the menu will change to
++ &quot;S No Strip&quot;, which means that if you press &quot;S&quot;, the
++ signature will not be stripped off from the message. Your choices are
++ activated when you press RETURN.
++
++ <P>
++ Another way to remember what Pine will do, is that what will be done is
++ exactly the opposite of what you read in the menu.
++
++ <P>
++ The possible options are:
++
++ <OL>
++ <LI> F: To decide if you want to send flowed text or not. This option appears
++ unless you have quelled sending flowed text.
++
++ <LI> S: To strip the signature from a message, only available is the feature
++ <a href="h_config_sigdashes">enable-sigdashes</a> or the
++ <a href="h_config_strip_sigdashes">strip-from-sigdashes-on-reply</a> option are
++ enabled.
++
++ <LI> R: To set a role, if you do not want Pine to set one automatically for you
++ or would like to set one when you can not select any.
++ </OL>
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_del_from_dot =====
+ <HTML>
+ <HEAD>
+***************
+*** 27077,27082 ****
+--- 28586,28634 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_courier_list =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: Courier-Folder-List</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: Courier-Folder-List</H1>
++
++ In a maildir collection, a folder could be used as a directory to store
++ folders. In the Courier server if you create a folder, then a directory
++ with the same name is created. If you use this patch to access a
++ collection created by the Courier server, then the display of such
++ collection will look confusing. The best way to access a maildir
++ collection created by the Courier server is by using the &quot;#mc/&quot;
++ prefix instead of the &quot;#md/&quot; prefix. If you use this alternate
++ prefix, then this feature applies to you, otherwise you can safely ignore
++ the text that follows.
++ <P>
++ Depending on if you have enabled the option
++ <a href="h_config_separate_yold_dir_view">separate-folder-and-firectory-entries</a>
++ a folder may be listed as &quot;folder[.]&quot;, or as two entries in the
++ list by &quot;folder&quot; and &quot;folder.&quot;.
++ <P>
++ If this option is disabled, Pine will list local folders that are in Courier
++ style format, as &quot;folder&quot;, and those that are also directories as
++ &quot;folder[.]&quot;. This makes the default display cleaner.
++ <P>
++ If this feature is enabled then creating folders in a maildir collection
++ will create a directory with the same name. If this feature is disabled, then
++ a folder is considered a directory only if it contains subfolders, so you can
++ not create a directory with the same name as an exisiting folder unless
++ you create a subfolder of that folder first (e.g. if you have a folder
++ called &quot;foo&quot; simply add &quot;foo.bar&quot; directly. This will
++ create the directory &quot;foo&quot; and the subfolder &quot;bar&quot; of it).
++ <P>
++ Observe that this feature works only for maildir collections that are accessed
++ locally. If a collection is accessed remotely then this feature has no value,
++ as the report is created in a server, and Pine only reports what received
++ from the server in this case.
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_verbose_post =====
+ <HTML>
+ <HEAD>
+***************
+*** 27228,27233 ****
+--- 28780,28808 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_auto_read_msgs_rules =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: auto-move-read-msgs-using-rules</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: auto-move-read-msgs-using-rules</H1>
++ This feature controls an aspect of Pine's behavior upon quitting. If set,
++ and the
++ <A HREF="h_config_read_message_folder">&quot;read-message-folder&quot;</A>
++ option is also set, then Pine will automatically transfer all read
++ messages to the designated folder using the rules that you have defined in
++ your
++ <A HREF="h_config_save_rules">&quot;save-rules&quot;</A> and mark
++ them as deleted in the INBOX. Messages in the INBOX marked with an
++ &quot;N&quot; (meaning New, or unseen) are not affected.
++ <P>
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_auto_fcc_only =====
+ <HTML>
+ <HEAD>
+***************
+*** 27616,27621 ****
+--- 29191,29213 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_enhanced_thread =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: enhanced-fancy-thread-support</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: enhanced-fancy-thread-support</H1>
++
++ If this option is set certain commands in Pine will operate in loose
++ threads too. For example, the command ^D marks a thread deleted, but if
++ this feature is set, it will remove all threads that share the same missing
++ parent with this thread.
++
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_news_cross_deletes =====
+ <HTML>
+ <HEAD>
+***************
+*** 28224,28229 ****
+--- 29816,29842 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_circular_tab =====
++ <HTML>
++ <HEAD>
++ <TITLE>FEATURE: enable-circular-tab</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>FEATURE: enable-circular-tab</H1>
++
++ <P>
++ This Feature is like
++ <A HREF="h_config_auto_open_unread">&quot;auto-open-next-unread&quot;</A>,
++ in the sense that you can use TAB to browse through all of your Incoming
++ Folders checking for new mail. Once it gets to the last folder of the
++ collection it goes back to check again until it returns to the original
++ folder where it started.
++ <UL>
++ <LI><A HREF="h_finding_help">Finding more information and requesting help</A>
++ </UL><P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_auto_include_reply =====
+ <HTML>
+ <HEAD>
+***************
+*** 28715,28720 ****
+--- 30328,30357 ----
+ &lt;End of help on this topic&gt;
+ </BODY>
+ </HTML>
++ ====== h_config_special_text_color =====
++ <HTML>
++ <HEAD>
++ <TITLE>OPTION: Special Text Color</TITLE>
++ </HEAD>
++ <BODY>
++ <H1>OPTION: Special Text Color</H1>
++
++ Sets the color Pine uses for coloring any text in the body of the message
++ that is not part of a handle (and internal or external link that Pine
++ paints in a different color). By default, this variable is not defined,
++ which means that text that matches the pattern is not painted in any
++ particular way. This variable must be set in a special form if you
++ want text to be painted.
++
++ <P>
++ <A HREF="h_color_setup">Descriptions of the available commands</A>
++ <P>
++ Look <A HREF="h_edit_nav_cmds">here</A>
++ to see the available Editing and Navigation commands.
++ <P>
++ &lt;End of help on this topic&gt;
++ </BODY>
++ </HTML>
+ ====== h_config_prompt_color =====
+ <HTML>
+ <HEAD>
+diff -rc pine4.63/pine/reply.c pine4.63.I.USE/pine/reply.c
+*** pine4.63/pine/reply.c Thu Apr 28 10:22:03 2005
+--- pine4.63.I.USE/pine/reply.c Thu May 19 19:57:34 2005
+***************
+*** 62,67 ****
+--- 62,69 ----
+
+ #include "headers.h"
+
++ static ACTION_S *role_chosen;
++ static int strip, send_flowed = 1;
+
+
+ /*
+***************
+*** 276,282 ****
+ if(!times){ /* only first time */
+ char *p = cpystr(prefix);
+
+! if((include_text=reply_text_query(pine_state,totalm,&prefix)) < 0)
+ goto done_early;
+
+ /* edited prefix? */
+--- 278,284 ----
+ if(!times){ /* only first time */
+ char *p = cpystr(prefix);
+
+! if((include_text=reply_text_query(pine_state,totalm,env,&prefix)) < 0)
+ goto done_early;
+
+ /* edited prefix? */
+***************
+*** 307,312 ****
+--- 309,355 ----
+ else if(i == 0)
+ goto done_early;
+
++ if (ps_global->role)
++ fs_give((void **)&ps_global->role);
++
++ /* Setup possible role */
++ if (role_chosen)
++ role = role_chosen;
++ else if(role_arg)
++ role = copy_action(role_arg);
++
++ if(!role){
++ rflags = ROLE_REPLY;
++ if(!role_chosen && nonempty_patterns(rflags, &dummy)){
++ /* setup default role */
++ nrole = NULL;
++ j = mn_first_cur(pine_state->msgmap);
++ do {
++ role = nrole;
++ nrole = set_role_from_msg(pine_state, rflags,
++ mn_m2raw(pine_state->msgmap, j),
++ NULL);
++ } while(nrole && (!role || nrole == role)
++ && (j=mn_next_cur(pine_state->msgmap)) > 0L);
++
++ if(!role || nrole == role)
++ role = nrole;
++ else
++ role = NULL;
++
++ if(confirm_role(rflags, &role))
++ role = combine_inherited_role(role);
++ else{ /* cancel reply */
++ role = NULL;
++ cmd_cancelled("Reply");
++ goto done_early;
++ }
++ }
++ }
++
++ if (role)
++ ps_global->role = cpystr(role->nick); /* remember the role */
++
+ /*------------ Format the subject line ---------------*/
+ if(outgoing->subject){
+ /*
+***************
+*** 319,326 ****
+ outgoing->subject = cpystr("Re: several messages");
+ }
+ }
+! else
+! outgoing->subject = reply_subject(env->subject, NULL, 0);
+ }
+
+
+--- 362,380 ----
+ outgoing->subject = cpystr("Re: several messages");
+ }
+ }
+! else{
+! RULE_RESULT *rule;
+! rule = get_result_rule(V_RESUB_RULES,
+! FOR_RULE|FOR_RESUB|FOR_TRIM , env);
+! if (rule){
+! outgoing->subject = reply_subject(rule->result, NULL, 0);
+! if (rule->result)
+! fs_give((void **)&rule->result);
+! fs_give((void **)&rule);
+! }
+! else
+! outgoing->subject = reply_subject(env->subject, NULL, 0);
+! }
+ }
+
+
+***************
+*** 331,369 ****
+ if(sp_expunge_count(pine_state->mail_stream)) /* cur msg expunged */
+ goto done_early;
+
+- /* Setup possible role */
+- if(role_arg)
+- role = copy_action(role_arg);
+-
+- if(!role){
+- rflags = ROLE_REPLY;
+- if(nonempty_patterns(rflags, &dummy)){
+- /* setup default role */
+- nrole = NULL;
+- j = mn_first_cur(pine_state->msgmap);
+- do {
+- role = nrole;
+- nrole = set_role_from_msg(pine_state, rflags,
+- mn_m2raw(pine_state->msgmap, j),
+- NULL);
+- } while(nrole && (!role || nrole == role)
+- && (j=mn_next_cur(pine_state->msgmap)) > 0L);
+-
+- if(!role || nrole == role)
+- role = nrole;
+- else
+- role = NULL;
+-
+- if(confirm_role(rflags, &role))
+- role = combine_inherited_role(role);
+- else{ /* cancel reply */
+- role = NULL;
+- cmd_cancelled("Reply");
+- goto done_early;
+- }
+- }
+- }
+-
+ /*
+ * Reply_seed may call c-client in get_fcc_based_on_to, so env may
+ * no longer be valid. Get it again.
+--- 385,390 ----
+***************
+*** 995,1001 ****
+ prompt_fodder);
+ }
+
+! cmd = radio_buttons(prompt, -FOOTER_ROWS(ps_global), ekey,
+ 'y', 'x', help, RB_NORM);
+
+ switch(cmd){
+--- 1016,1023 ----
+ prompt_fodder);
+ }
+
+! cmd = ps_global->send_immediately ? 'n' :
+! radio_buttons(prompt, -FOOTER_ROWS(ps_global), ekey,
+ 'y', 'x', help, RB_NORM);
+
+ switch(cmd){
+***************
+*** 1623,1630 ****
+ ENVELOPE *env;
+ {
+ char *prefix, *repl, *p, buf[MAX_PREFIX+1], pbf[MAX_SUBSTITUTION+1];
+
+! strncpy(buf, ps_global->VAR_REPLY_STRING, sizeof(buf)-1);
+ buf[sizeof(buf)-1] = '\0';
+
+ /* set up the prefix to quote included text */
+--- 1645,1671 ----
+ ENVELOPE *env;
+ {
+ char *prefix, *repl, *p, buf[MAX_PREFIX+1], pbf[MAX_SUBSTITUTION+1];
++ char reply_string[MAX_PREFIX+1];
++
++ { RULE_RESULT *rule;
++ rule = get_result_rule(V_REPLY_INDENT_RULES, FOR_RULE|FOR_COMPOSE , env);
++ if (rule){
++ strncpy(reply_string,rule->result,sizeof(reply_string));
++ reply_string[sizeof(reply_string)-1] = '\0';
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ else
++ if ((ps_global->VAR_REPLY_STRING) && (ps_global->VAR_REPLY_STRING[0])){
++ strncpy(reply_string,ps_global->VAR_REPLY_STRING, sizeof(reply_string)-1);
++ reply_string[sizeof(reply_string)-1] = '\0';
++ }
++ else
++ strncpy(reply_string,"> ",sizeof("> "));
++ }
+
+! strncpy(buf, reply_string, sizeof(buf)-1);
+ buf[sizeof(buf)-1] = '\0';
+
+ /* set up the prefix to quote included text */
+***************
+*** 1680,1689 ****
+ int
+ reply_quote_str_contains_tokens()
+ {
+! return(ps_global->VAR_REPLY_STRING && ps_global->VAR_REPLY_STRING[0] &&
+! (strstr(ps_global->VAR_REPLY_STRING, from_token) ||
+! strstr(ps_global->VAR_REPLY_STRING, nick_token) ||
+! strstr(ps_global->VAR_REPLY_STRING, init_token)));
+ }
+
+ /*
+--- 1721,1750 ----
+ int
+ reply_quote_str_contains_tokens()
+ {
+! char *reply_string;
+!
+! reply_string = (char *) malloc( 80*sizeof(char));
+! { RULE_RESULT *rule;
+! rule = get_result_rule(V_REPLY_INDENT_RULES,
+! FOR_RULE | FOR_COMPOSE, (ENVELOPE *)NULL);
+! if (rule){
+! reply_string = cpystr(rule->result);
+! if (rule->result)
+! fs_give((void **)&rule->result);
+! fs_give((void **)&rule);
+! }
+! else
+! if ((ps_global->VAR_REPLY_STRING) && (ps_global->VAR_REPLY_STRING[0])){
+! strncpy(reply_string,ps_global->VAR_REPLY_STRING, sizeof(reply_string)-1);
+! reply_string[sizeof(reply_string)-1] = '\0';
+! }
+! else
+! reply_string = cpystr("> ");
+! }
+! return(reply_string && reply_string[0] &&
+! (strstr(reply_string, from_token) ||
+! strstr(reply_string, nick_token) ||
+! strstr(reply_string, init_token)));
+ }
+
+ /*
+***************
+*** 1693,1738 ****
+ * 0 if we're NOT to include the text
+ * -1 on cancel or error
+ */
+ int
+! reply_text_query(ps, many, prefix)
+ struct pine *ps;
+ long many;
+ char **prefix;
+ {
+ int ret, edited = 0;
+! static ESCKEY_S rtq_opts[] = {
+! {'y', 'y', "Y", "Yes"},
+! {'n', 'n', "N", "No"},
+! {-1, 0, NULL, NULL}, /* may be overridden below */
+! {-1, 0, NULL, NULL}
+! };
+
+ if(F_ON(F_AUTO_INCLUDE_IN_REPLY, ps)
+! && F_OFF(F_ENABLE_EDIT_REPLY_INDENT, ps))
+ return(1);
+
+ while(1){
+! sprintf(tmp_20k_buf, "Include %s%soriginal message%s in Reply%s%s%s? ",
+ (many > 1L) ? comatose(many) : "",
+ (many > 1L) ? " " : "",
+ (many > 1L) ? "s" : "",
+ F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? " (using \"" : "",
+ F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? *prefix : "",
+ F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? "\")" : "");
+
+! if(F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps)){
+! rtq_opts[2].ch = ctrl('R');
+! rtq_opts[2].rval = 'r';
+! rtq_opts[2].name = "^R";
+! rtq_opts[2].label = "Edit Indent String";
+! }
+! else
+! rtq_opts[2].ch = -1;
+
+ switch(ret = radio_buttons(tmp_20k_buf,
+ ps->ttyo->screen_rows > 4
+ ? -FOOTER_ROWS(ps_global) : -1,
+! rtq_opts,
+ (edited || F_ON(F_AUTO_INCLUDE_IN_REPLY, ps))
+ ? 'y' : 'n',
+ 'x', NO_HELP, RB_SEQ_SENSITIVE)){
+--- 1754,1854 ----
+ * 0 if we're NOT to include the text
+ * -1 on cancel or error
+ */
++
++ #define MAX_REPLY_OPTIONS 8
++
+ int
+! reply_text_query(ps, many, env, prefix)
+ struct pine *ps;
+ long many;
++ ENVELOPE *env;
+ char **prefix;
+ {
+ int ret, edited = 0;
+! static ESCKEY_S compose_style[MAX_REPLY_OPTIONS];
+! int ekey_num;
+! int orig_sf;
+!
+! orig_sf = send_flowed = *prefix && **prefix ? (F_OFF(F_QUELL_FLOWED_TEXT, ps)
+! && F_OFF(F_STRIP_WS_BEFORE_SEND, ps)
+! && (strcmp(*prefix, "> ") == 0
+! || strcmp(*prefix, ">") == 0)) : 0;
+!
+! role_chosen = NULL;
+! strip = F_ON(F_ENABLE_STRIP_SIGDASHES, ps) || F_ON(F_ENABLE_SIGDASHES, ps);
+
+ if(F_ON(F_AUTO_INCLUDE_IN_REPLY, ps)
+! && F_OFF(F_ENABLE_EDIT_REPLY_INDENT, ps) && F_OFF(F_ALT_REPLY_MENU,ps))
+ return(1);
+
+ while(1){
+! sprintf(tmp_20k_buf,"Include %s%soriginal message%s in Reply%s%s%s%s%s? ",
+ (many > 1L) ? comatose(many) : "",
+ (many > 1L) ? " " : "",
+ (many > 1L) ? "s" : "",
+ F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? " (using \"" : "",
+ F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? *prefix : "",
++ role_chosen ? "\" and role \"" : "",
++ role_chosen ? role_chosen->nick : "",
+ F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps) ? "\")" : "");
+
+! ekey_num = 0;
+! compose_style[ekey_num].ch = 'y';
+! compose_style[ekey_num].rval = 'y';
+! compose_style[ekey_num].name = "Y";
+! compose_style[ekey_num++].label = "Yes";
+!
+! compose_style[ekey_num].ch = 'n';
+! compose_style[ekey_num].rval = 'n';
+! compose_style[ekey_num].name = "N";
+! compose_style[ekey_num++].label = "No";
+!
+! if (F_ON(F_ENABLE_EDIT_REPLY_INDENT, ps)){
+! compose_style[ekey_num].ch = ctrl('R');
+! compose_style[ekey_num].rval = 'r';
+! compose_style[ekey_num].name = "^R";
+! compose_style[ekey_num++].label = "Indent Str" ;
+! }
+!
+! /***** Alternate Reply Menu ********/
+!
+! if (F_ON(F_ALT_REPLY_MENU, ps)){
+! unsigned which_help;
+!
+! if (F_ON(F_ENABLE_STRIP_SIGDASHES, ps) ||
+! F_ON(F_ENABLE_SIGDASHES, ps)){
+! compose_style[ekey_num].ch = 's';
+! compose_style[ekey_num].rval = 's';
+! compose_style[ekey_num].name = "S";
+! compose_style[ekey_num++].label = strip ? "No Strip"
+! : "Strip Sig";
+! }
+!
+! compose_style[ekey_num].ch = 'r';
+! compose_style[ekey_num].rval = 'R';
+! compose_style[ekey_num].name = "R";
+! compose_style[ekey_num++].label = "Set Role";
+!
+! if(orig_sf){
+! compose_style[ekey_num].ch = 'f';
+! compose_style[ekey_num].rval = 'F';
+! compose_style[ekey_num].name = "F";
+! compose_style[ekey_num++].label = send_flowed ? "Quell Flowed"
+! : "Send Flowed";
+! }
+!
+! }
+! compose_style[ekey_num].ch = -1;
+! compose_style[ekey_num].name = NULL;
+! compose_style[ekey_num].label = NULL;
+!
+!
+! /***** End Alt Reply Menu *********/
+
+ switch(ret = radio_buttons(tmp_20k_buf,
+ ps->ttyo->screen_rows > 4
+ ? -FOOTER_ROWS(ps_global) : -1,
+! compose_style,
+ (edited || F_ON(F_AUTO_INCLUDE_IN_REPLY, ps))
+ ? 'y' : 'n',
+ 'x', NO_HELP, RB_SEQ_SENSITIVE)){
+***************
+*** 1740,1745 ****
+--- 1856,1892 ----
+ cmd_cancelled("Reply");
+ return(-1);
+
++ case 'F':
++ send_flowed = (send_flowed + 1) % 2;
++ break;
++
++ case 's':
++ strip = (strip + 1) % 2;
++ break;
++
++ case 'R':
++ {
++ void (*prev_screen)() = ps->prev_screen,
++ (*redraw)() = ps->redrawer;
++ ps->redrawer = NULL;
++ ps->next_screen = SCREEN_FUN_NULL;
++ if(role_select_screen(ps, &role_chosen, 1) < 0){
++ cmd_cancelled("Reply");
++ ps->next_screen = prev_screen;
++ ps->redrawer = redraw;
++ if (ps->redrawer)
++ (*ps->redrawer)();
++ continue;
++ }
++ ps->next_screen = prev_screen;
++ ps->redrawer = redraw;
++ if(role_chosen)
++ role_chosen = combine_inherited_role(role_chosen);
++ }
++ if (ps->redrawer)
++ (*ps->redrawer)();
++ break;
++
+ case 'r':
+ if(prefix && *prefix){
+ int done = 0;
+***************
+*** 1763,1768 ****
+--- 1910,1921 ----
+ if(flags & OE_USER_MODIFIED){
+ fs_give((void **)prefix);
+ *prefix = removing_quotes(cpystr(buf));
++ orig_sf = *prefix && **prefix ?
++ (F_OFF(F_QUELL_FLOWED_TEXT, ps)
++ && F_OFF(F_STRIP_WS_BEFORE_SEND, ps)
++ && (strcmp(*prefix, "> ") == 0
++ || strcmp(*prefix, ">") == 0)) : 0;
++ send_flowed = orig_sf;
+ edited = 1;
+ }
+
+***************
+*** 2251,2256 ****
+--- 2404,2413 ----
+ buf[0] = '\0';
+
+ switch(type){
++ case iFfrom:
++ addr = env && env->sparep ? env->sparep : NULL;
++ break;
++
+ case iFrom:
+ addr = env ? env->from : NULL;
+ break;
+***************
+*** 2682,2702 ****
+
+ break;
+
+ case iFrom:
+ case iTo:
+ case iCc:
+ case iSender:
+ case iRecips:
+ case iInit:
+ get_addr_data(env, type, buf, maxlen);
+ break;
+
+! case iRoleNick:
+! if(role && role->nick){
+! strncpy(buf, role->nick, maxlen);
+! buf[maxlen] = '\0';
+! }
+! break;
+
+ case iAddress:
+ case iMailbox:
+--- 2839,2959 ----
+
+ break;
+
++ case iRole:
++ if (ps_global->role)
++ sprintf(buf, ps_global->role);
++ break;
++
++ case iRoleNick:
++ if(role && role->nick){
++ strncpy(buf, role->nick, maxlen);
++ buf[maxlen] = '\0';
++ }
++ break;
++
++ case iFfrom:
+ case iFrom:
+ case iTo:
+ case iCc:
+ case iSender:
+ case iRecips:
+ case iInit:
++ if (env)
+ get_addr_data(env, type, buf, maxlen);
+ break;
+
+! case iFolder:
+! sprintf(buf,ps_global->cur_folder);
+! break;
+!
+! case iCollection:
+! sprintf(buf,ps_global->context_current->nickname);
+! break;
+!
+! case iFlag:
+! {MAILSTREAM *stream = find_open_stream();
+! MSGNO_S *msgmap = NULL;
+! long msgno;
+! MESSAGECACHE *mc;
+! strcpy(buf, "_FLAG_"); /* default value */
+! if (stream){
+! mn_init(&msgmap, stream->nmsgs);
+! msgno = mn_m2raw(msgmap, rules_cursor_pos(stream));
+! if (msgno > 0L) mc = stream ? mail_elt(stream, msgno) : NULL;
+! if (mc)
+! sprintf(buf,"%s%s%s%s",mc->flagged ? "*" : "",
+! mc->recent ? (mc->seen ? "R" : "N") : (mc->seen) ? "R" : "U",
+! mc->answered ? "A" : "",
+! mc->deleted ? "D" : "" );
+! mn_give(&msgmap);
+! }
+! }
+! break;
+!
+! case iNick:
+! {
+! ADDRESS *tmp_adr = NULL;
+! if (env){
+! tmp_adr = env->from ? copyaddr(env->from)
+! : env->sender ? copyaddr(env->sender) : NULL;
+! get_nickname_from_addr(tmp_adr,buf,maxlen);
+! mail_free_address(&tmp_adr);
+! }
+! }
+! break;
+!
+! case iAddressCc:
+! case iAddressRecip:
+! case iAddressTo:
+! case iFadd:
+! {
+! int plen = 0; /* partial length */
+! ADDRESS *sparep2 = (type == iAddressTo || type == iAddressRecip)
+! ? ((env && env->to)
+! ? copyaddrlist(env->to)
+! : NULL)
+! : (type == iAddressCc)
+! ? ((env && env->cc)
+! ? copyaddrlist(env->cc)
+! : NULL)
+! : ((env && env->sparep)
+! ? copyaddr((ADDRESS *)env->sparep)
+! : NULL);
+! ADDRESS *sparep;
+!
+! if (type == iAddressRecip){
+! ADDRESS *last_to = NULL;
+!
+! for(last_to = sparep2;last_to && last_to->next; last_to= last_to->next);
+!
+! /* Make the end of To list point to cc list */
+! if(last_to)
+! last_to->next = (env && env->cc ? copyaddrlist(env->cc) : NULL);
+!
+! }
+! sparep = sparep2;
+! for(; sparep ; sparep = sparep->next)
+! if(sparep && sparep->mailbox && sparep->mailbox[0] &&
+! (plen ? plen + 1 : plen) + strlen(sparep->mailbox) <= maxlen){
+! if (plen == 0)
+! strcpy(buf, sparep->mailbox);
+! else{
+! strcat(buf, " ");
+! strcat(buf, sparep->mailbox);
+! }
+! if(sparep->host &&
+! sparep->host[0] &&
+! sparep->host[0] != '.' &&
+! strlen(buf) + strlen(sparep->host) + 1 <= maxlen){
+! strcat(buf, "@");
+! strcat(buf, sparep->host);
+! }
+! plen = strlen(buf);
+! }
+! mail_free_address(&sparep2);
+! }
+!
+! break;
+
+ case iAddress:
+ case iMailbox:
+***************
+*** 2715,2720 ****
+--- 2972,2982 ----
+
+ break;
+
++ case iLcc: /* fake it, there are not enough spare pointers */
++ if (env && env->date)
++ sprintf(buf,env->date);
++ break;
++
+ case iNews:
+ case iCurNews:
+ get_news_data(env, type, buf, maxlen);
+***************
+*** 2826,2832 ****
+ if(!env)
+ return;
+
+! strncpy(buf, ps_global->VAR_REPLY_INTRO, MAX_DELIM);
+ buf[MAX_DELIM] = '\0';
+ /* preserve exact default behavior from before */
+ if(!strcmp(buf, DEFAULT_REPLY_INTRO)){
+--- 3088,3106 ----
+ if(!env)
+ return;
+
+! { RULE_RESULT *rule;
+! rule = get_result_rule(V_REPLY_LEADIN_RULES,
+! FOR_RULE | FOR_REPLY_INTRO, env);
+! if(rule){
+! strncpy(buf, rule->result, MAX_DELIM);
+! if (rule->result)
+! fs_give((void **)&rule->result);
+! fs_give((void **)&rule);
+! }
+! else
+! strncpy(buf, ps_global->VAR_REPLY_INTRO, MAX_DELIM);
+! }
+!
+ buf[MAX_DELIM] = '\0';
+ /* preserve exact default behavior from before */
+ if(!strcmp(buf, DEFAULT_REPLY_INTRO)){
+***************
+*** 2988,2996 ****
+ }
+ else if(!outgoing->newsgroups)
+ outgoing->newsgroups = cpystr(env->newsgroups);
+- if(!IS_NEWS(ps_global->mail_stream))
+- q_status_message(SM_ORDER, 2, 3,
+- "Replying to message that MAY or MAY NOT have been posted to newsgroup");
+ }
+
+ return(ret);
+--- 3262,3267 ----
+***************
+*** 3051,3056 ****
+--- 3322,3329 ----
+
+ if(is_sig){
+ /*
++ * First we check if there is a rule about signatures, if there is
++ * use it, otherwise keep going and do the following:
+ * If role->litsig is set, we use it;
+ * Else, if VAR_LITERAL_SIG is set, we use that;
+ * Else, if role->sig is set, we use that;
+***************
+*** 3064,3077 ****
+ * there is no reason to mix them, so we don't provide support to
+ * do so.
+ */
+! if(role && role->litsig)
+! literal_sig = role->litsig;
+! else if(ps_global->VAR_LITERAL_SIG)
+! literal_sig = ps_global->VAR_LITERAL_SIG;
+! else if(role && role->sig)
+! sigfile = role->sig;
+! else
+! sigfile = ps_global->VAR_SIGNATURE_FILE;
+ }
+ else if(role && role->template)
+ sigfile = role->template;
+--- 3337,3361 ----
+ * there is no reason to mix them, so we don't provide support to
+ * do so.
+ */
+! { RULE_RESULT *rule;
+! rule = get_result_rule(V_COMPOSE_RULES, FOR_RULE|FOR_COMPOSE, env);
+! if (rule){
+! sigfile = cpystr(rule->result);
+! if (rule->result)
+! fs_give((void **)&rule->result);
+! fs_give((void **)&rule);
+! }
+! }
+! if (!sigfile){
+! if(role && role->litsig)
+! literal_sig = role->litsig;
+! else if(ps_global->VAR_LITERAL_SIG)
+! literal_sig = ps_global->VAR_LITERAL_SIG;
+! else if(role && role->sig)
+! sigfile = role->sig;
+! else
+! sigfile = ps_global->VAR_SIGNATURE_FILE;
+! }
+ }
+ else if(role && role->template)
+ sigfile = role->template;
+***************
+*** 3269,3275 ****
+ }
+ }
+ }
+! else if(pt->what_for & FOR_REPLY_INTRO)
+ repl = get_reply_data(env, role, pt->ctype,
+ subbuf, sizeof(subbuf)-1);
+
+--- 3553,3559 ----
+ }
+ }
+ }
+! else if(pt->what_for & (FOR_REPLY_INTRO|FOR_RULE))
+ repl = get_reply_data(env, role, pt->ctype,
+ subbuf, sizeof(subbuf)-1);
+
+***************
+*** 3747,3755 ****
+ }
+ }
+
+! if(role)
+ q_status_message1(SM_ORDER, 3, 4,
+ "Forwarding using role \"%.200s\"", role->nick);
+
+ if(role && role->template){
+ char *filtered;
+--- 4031,4044 ----
+ }
+ }
+
+! if (ps_global->role)
+! fs_give((void **)&ps_global->role);
+!
+! if(role){
+ q_status_message1(SM_ORDER, 3, 4,
+ "Forwarding using role \"%.200s\"", role->nick);
++ ps_global->role = cpystr(role->nick);
++ }
+
+ if(role && role->template){
+ char *filtered;
+***************
+*** 3953,3958 ****
+--- 4242,4248 ----
+ #if defined(DOS) && !defined(_WINDOWS)
+ free((void *)reserve);
+ #endif
++ outgoing->sparep = env && env->from ? (ADDRESS *)copyaddr(env->from) : NULL;
+ pine_send(outgoing, &body, "FORWARD MESSAGE",
+ role, NULL, reply.flags ? &reply : NULL, redraft_pos,
+ NULL, NULL, FALSE);
+***************
+*** 4873,4881 ****
+ * tied our hands, alter the prefix to continue flowed
+ * formatting...
+ */
+! if(flow_res)
+ wrapflags |= GFW_FLOW_RESULT;
+
+ filters[i].filter = gf_wrap;
+ /*
+ * The 80 will cause longer lines than what is likely
+--- 5163,5174 ----
+ * tied our hands, alter the prefix to continue flowed
+ * formatting...
+ */
+! if(flow_res && send_flowed)
+ wrapflags |= GFW_FLOW_RESULT;
+
++ filters[i].filter = gf_quote_test;
++ filters[i++].data = gf_line_test_opt(select_quote, NULL);
++
+ filters[i].filter = gf_wrap;
+ /*
+ * The 80 will cause longer lines than what is likely
+***************
+*** 4909,4916 ****
+ * We also want to fold "> " quotes so we get the
+ * attributions correct.
+ */
+! if(flow_res && prefix && !strucmp(prefix, "> "))
+ *(prefix_p = prefix + 1) = '\0';
+ if(!(wrapflags & GFW_FLOWED)
+ && flow_res){
+ filters[i].filter = gf_line_test;
+--- 5202,5210 ----
+ * We also want to fold "> " quotes so we get the
+ * attributions correct.
+ */
+! if(flow_res && send_flowed && prefix && !strucmp(prefix, "> "))
+ *(prefix_p = prefix + 1) = '\0';
++ send_flowed = 1; /* reset for next call */
+ if(!(wrapflags & GFW_FLOWED)
+ && flow_res){
+ filters[i].filter = gf_line_test;
+***************
+*** 4938,4945 ****
+ }
+
+ if(prefix){
+! if(F_ON(F_ENABLE_SIGDASHES, ps_global) ||
+! F_ON(F_ENABLE_STRIP_SIGDASHES, ps_global)){
+ dashdata = 0;
+ filters[i].filter = gf_line_test;
+ filters[i++].data = gf_line_test_opt(sigdash_strip, &dashdata);
+--- 5232,5239 ----
+ }
+
+ if(prefix){
+! if(strip && (F_ON(F_ENABLE_SIGDASHES, ps_global) ||
+! F_ON(F_ENABLE_STRIP_SIGDASHES, ps_global))){
+ dashdata = 0;
+ filters[i].filter = gf_line_test;
+ filters[i++].data = gf_line_test_opt(sigdash_strip, &dashdata);
+diff -rc pine4.63/pine/rules.c pine4.63.I.USE/pine/rules.c
+*** pine4.63/pine/rules.c Thu May 19 19:59:15 2005
+--- pine4.63.I.USE/pine/rules.c Thu May 19 19:57:27 2005
+***************
+*** 0 ****
+--- 1,905 ----
++ /* This module was written by
++ *
++ * Eduardo Chappa (chappa@math.washington.edu)
++ * http://www.math.washington.edu/~chappa/pine/
++ *
++ * Original Version: November 1999
++ * Last Modified : December 14, 2004
++ *
++ * Send bug reports about this module to the address above.
++ */
++
++ #include "rules.h"
++
++ void free_token_value(token)
++ TOKEN_VALUE **token;
++ {
++ if(token && *token){
++ if ((*token)->testxt)
++ fs_give((void **)&((*token)->testxt));
++ if((*token)->next)
++ free_token_value(&((*token)->next));
++ fs_give((void **)token);
++ }
++ }
++
++ void free_condition(condition)
++ CONDITION_S **condition;
++ {
++ if(condition && *condition){
++ if ((*condition)->tname)
++ fs_give((void **)&((*condition)->tname));
++ if ((*condition)->value)
++ free_token_value(&((*condition)->value));
++ if((*condition)->next)
++ free_condition(&((*condition)->next));
++ fs_give((void **)condition);
++ }
++ }
++
++ void free_ruleaction(raction)
++ RULEACTION_S **raction;
++ {
++ if(raction && *raction){
++ if ((*raction)->token)
++ fs_give((void **)&((*raction)->token));
++ if ((*raction)->function)
++ fs_give((void **)&((*raction)->function));
++ if ((*raction)->value)
++ fs_give((void **)&((*raction)->value));
++ fs_give((void **)raction);
++ }
++ }
++
++ void free_rule(rule)
++ RULE_S **rule;
++ {
++ if(rule && *rule){
++ free_condition(&((*rule)->condition));
++ free_ruleaction(&((*rule)->action));
++ fs_give((void **)rule);
++ }
++ }
++
++ void free_rule_list(rule)
++ RULELIST **rule;
++ {
++ if(!*rule)
++ return;
++
++ if((*rule)->next)
++ free_rule_list(&((*rule)->next));
++
++ if((*rule)->prule)
++ free_rule(&((*rule)->prule));
++
++ fs_give((void **)rule);
++ }
++
++ void
++ free_parsed_rule_list(rule)
++ PRULELIST_S **rule;
++ {
++ if(!*rule)
++ return;
++
++ if((*rule)->next)
++ free_parsed_rule_list(&((*rule)->next));
++
++ if((*rule)->rlist)
++ free_rule_list(&((*rule)->rlist));
++
++ fs_give((void **)rule);
++ }
++
++ void *
++ alloc_mem (amount)
++ size_t amount;
++ {
++ void *genmem;
++ memset(genmem = fs_get(amount), 0, amount);
++ return genmem;
++ }
++
++ int
++ isolate_condition (data, cvalue, len)
++ char *data, **cvalue;
++ int *len;
++ {
++ char *p = data;
++ int done = 0, error = 0, next_condition = 0, l;
++
++ *cvalue = NULL;
++ while (*p && !done){
++ switch (*p){
++ case '_': *cvalue = advance_to_char(p,'}', STRICT, NULL);
++ if(*cvalue){
++ strcat(*cvalue,"}");
++ p += strlen(*cvalue);
++ }
++ else
++ error++;
++ done++;
++ case ' ': p++;
++ break;
++ case '&': if (*(p+1) == '&'){ /* looking for && */
++ p += 2;
++ next_condition++;
++ }
++ else{
++ error++;
++ done++;
++ }
++ break;
++ case '=': /* looking for => or -> */
++ case '-': if ((*(p+1) == '>') && (!next_condition)){
++ is_save = (*p == '-');
++ p += 2;
++ }
++ else
++ error++;
++ done++;
++ break;
++ default : done++;
++ error++;
++ break;
++ }
++ }
++ *len = p - data;
++ return error ? -1 : (*cvalue ? 1 : 0);
++ }
++
++ TOKEN_VALUE *
++ parse_group_data (data, error)
++ char *data;
++ int *error;
++ {
++ TOKEN_VALUE *rvalue;
++ char *p;
++ int offset, err = 0;
++
++ if(error)
++ *error = 0;
++
++ if (!data)
++ return (TOKEN_VALUE *) NULL;
++
++ rvalue = (TOKEN_VALUE *) alloc_mem(sizeof(TOKEN_VALUE));
++ if (p = advance_to_char(data,';', STRICT, &offset)){
++ rvalue->testxt = cpystr(p);
++ data += strlen(p) + 1 + offset;
++ rvalue->next = parse_group_data(data, error);
++ }
++ else if (p = advance_to_char(data,'}', STRICT, NULL))
++ rvalue->testxt = cpystr(p);
++ else{
++ err++;
++ free_token_value(&rvalue);
++ }
++ if (error)
++ *error += err;
++ return(rvalue);
++ }
++
++ CONDITION_S *
++ fill_condition(data)
++ char *data;
++ {
++ CONDITION_S *condition;
++ int i, done, error = 0;
++ char *group;
++
++ for (i = 0, done = 0; !done && (i < NTOKENS); i++)
++ done = strncmp(data,token_rules[i], strlen(token_rules[i])) ? 0 : 1;
++ if (done){
++ condition = (CONDITION_S *) alloc_mem(sizeof(CONDITION_S));
++ condition->tname = cpystr(token_rules[--i]);
++ }
++ else
++ return (CONDITION_S *)NULL;
++
++ data += strlen(token_rules[i]);
++ for (; *data && *data == ' '; data++);
++ if (*data){
++ for (i = 0, done = 0; !done && (i < NREL); i++)
++ done = strncmp(data, rel_rules_test[i].value, 2) ? 0 : 1;
++ if (done)
++ condition->ttype = rel_rules_test[--i].ttype;
++ else{
++ free_condition(&condition);
++ return (CONDITION_S *) NULL;
++ }
++ }
++ data += 2;
++ for (; *data && *data == ' '; data++);
++ if (*data++ != '{'){
++ free_condition(&condition);
++ return (CONDITION_S *) NULL;
++ }
++ group = advance_to_char(data,'}', STRICT, &error);
++ if (group || (!group && error < 0)){
++ condition->value = parse_group_data(data, &error);
++ if(group && error)
++ free_condition(&condition);
++ if(group)
++ fs_give((void **) &group);
++ }
++ else
++ free_condition(&condition);
++ return condition;
++ }
++
++ CONDITION_S *
++ parse_condition (data, eoc)
++ char *data;
++ int *eoc; /* end of condition, equal to -1 on error */
++ {
++ CONDITION_S *condition = NULL;
++ char *p = data, *cvalue;
++ int len, error = 0, rv;
++
++ if((rv = isolate_condition(data, &cvalue, &len)) > 0){
++ if(condition = fill_condition(cvalue))
++ condition->next = parse_condition(data+len, eoc);
++ else
++ error++;
++ }
++ *eoc += len;
++ if (error)
++ *eoc = -1;
++ return condition;
++ }
++
++ RULEACTION_S *
++ parse_action (data, context)
++ char *data;
++ int context;
++ {
++ int i, done;
++ RULEACTION_S *raction = NULL;
++ char *function, *p = data;
++
++ if (!p)
++ return (RULEACTION_S *) NULL;
++
++ for (; *p && *p == ' '; p++);
++ if (!*p)
++ return (RULEACTION_S *) NULL;
++
++ if (is_save){
++ raction = (RULEACTION_S *) alloc_mem(sizeof(RULEACTION_S));
++ raction->function = cpystr("_SAVE_");
++ raction->value = (TOKEN_VALUE *) alloc_mem(sizeof(TOKEN_VALUE));
++ raction->context |= FOR_SAVE;
++ raction->exec = extended_value;
++ raction->value->testxt = cpystr(p);
++ return raction;
++ }
++ for (i = 0, done = 0; !done && (i < NFCN); i++)
++ done = (strstr(p,rule_fcns[i].name) == p);
++ p += done ? strlen(rule_fcns[--i].name) + 1 : 0;
++ if(!*p || (rule_fcns[i].what_for && !(rule_fcns[i].what_for & context)))
++ return (RULEACTION_S *) NULL;
++ if (done){
++ raction = (RULEACTION_S *) alloc_mem(sizeof(RULEACTION_S));
++ raction->function = cpystr(rule_fcns[i].name);
++ raction->context = rule_fcns[i].what_for;
++ raction->exec = rule_fcns[i].execute;
++ raction->value = (TOKEN_VALUE *) alloc_mem(sizeof(TOKEN_VALUE));
++ raction->value->testxt = advance_to_char(p,'}', STRICT, NULL);
++ if(!raction->value->testxt)
++ free_ruleaction(&raction);
++ return raction;
++ }
++
++ done = (((function = strstr(p, "_TRIM_")) != NULL)
++ ? 1 : ((function = strstr(p, "_REXTRIM_")) != NULL)
++ ? 2 : ((function = strstr(p, "_REPLACE_")) != NULL)
++ ? 3 : 0);
++
++ if(!function)
++ return (RULEACTION_S *) NULL;
++
++ *function = '\0';
++ raction = (RULEACTION_S *) alloc_mem(sizeof(RULEACTION_S));
++ raction->token = get_name_token(p);
++ *function = '_';
++ p += strlen(raction->token) + 1;
++ for (; *p && *p == ' '; p++);
++ if (!strncmp(p,":=",2))
++ p += 2;
++ else{
++ free_ruleaction(&raction);
++ return (RULEACTION_S *) NULL;
++ }
++ for (; *p && *p == ' '; p++);
++ if (p != function){
++ free_ruleaction(&raction);
++ return (RULEACTION_S *) NULL;
++ }
++ p += done == 1 ? 6: 9;
++ if (*p != '{'){
++ free_ruleaction(&raction);
++ return (RULEACTION_S *) NULL;
++ }
++ *p = '\0';
++ for(i = 0; i < NFCN && strcmp(function, rule_fcns[i].name);i++);
++ raction->function = cpystr(function);
++ raction->is_trim = strcmp(function,"_TRIM_") ? 0 : 1;
++ raction->is_rextrim = strcmp(function,"_REXTRIM_") ? 0 : 1;
++ raction->is_replace = strcmp(function,"_REPLACE_") ? 0 : 1;
++ raction->context = rule_fcns[i].what_for;
++ raction->exec = rule_fcns[i].execute;
++ *p++ = '{';
++ raction->value = parse_group_data(p, NULL);
++ if(!raction->value->testxt)
++ free_ruleaction(&raction);
++ return raction;
++ }
++
++ RULE_S *
++ parse_rule (data, context)
++ char *data;
++ int context;
++ {
++ RULE_S *prule; /*parsed rule */
++ int len = 0;
++
++ if (!(prule = (RULE_S *) alloc_mem(sizeof(RULE_S))) ||
++ !(prule->condition = parse_condition(data, &len)) ||
++ !(prule->action = parse_action(data+len, context)))
++ free_rule(&prule);
++
++ return prule;
++ }
++
++ RULELIST *
++ get_rule_list(list, context, i)
++ char **list;
++ int context, i;
++ {
++ RULE_S *rule;
++ RULELIST *trulelist = NULL;
++
++ if (list[i] && *list[i]){
++ if(rule = parse_rule(list[i], context)){
++ trulelist = (RULELIST *)alloc_mem(sizeof(RULELIST));
++ trulelist->prule = rule;
++ trulelist->next = get_rule_list(list, context, i+1);
++ }
++ else
++ trulelist = get_rule_list(list, context, i+1);
++ }
++ return trulelist;
++ }
++
++ PRULELIST_S *
++ add_prule(rule_list, rule)
++ PRULELIST_S *rule_list;
++ PRULELIST_S *rule;
++ {
++ if (!rule_list)
++ rule_list = (PRULELIST_S *) alloc_mem(sizeof(PRULELIST_S));
++
++ if(rule_list->next)
++ rule_list->next = add_prule(rule_list->next, rule);
++ else{
++ if (rule_list->rlist)
++ rule_list->next = rule;
++ else
++ rule_list = rule;
++ }
++ return rule_list;
++ }
++
++ void
++ add_rule(code, context)
++ int code, context;
++ {
++ char **list = ps_global->vars[code].current_val.l;
++ PRULELIST_S *prulelist, *trulelist, *orulelist;
++
++ if (list && *list && **list){
++ trulelist = (PRULELIST_S *)alloc_mem(sizeof(PRULELIST_S));
++ trulelist->varnum = code;
++ if (trulelist->rlist = get_rule_list(list, context, 0))
++ ps_global->rule_list = add_prule(ps_global->rule_list, trulelist);
++ else
++ free_parsed_rule_list(&trulelist);
++ }
++ }
++
++ void
++ create_rule_list(void)
++ {
++ add_rule(V_THREAD_DISP_STYLE_RULES,FOR_RULE|FOR_THREAD);
++ add_rule(V_THREAD_INDEX_STYLE_RULES,FOR_RULE|FOR_THREAD);
++ add_rule(V_COMPOSE_RULES,FOR_RULE|FOR_COMPOSE);
++ add_rule(V_FORWARD_RULES,FOR_RULE|FOR_COMPOSE);
++ add_rule(V_INDEX_RULES,FOR_RULE|FOR_INDEX);
++ add_rule(V_REPLACE_RULES,FOR_RULE|FOR_REPLACE);
++ add_rule(V_REPLY_INDENT_RULES,FOR_RULE|FOR_COMPOSE);
++ add_rule(V_REPLY_LEADIN_RULES,FOR_RULE|FOR_REPLY_INTRO);
++ add_rule(V_RESUB_RULES,FOR_RULE|FOR_RESUB|FOR_TRIM);
++ add_rule(V_SAVE_RULES,FOR_RULE|FOR_SAVE);
++ add_rule(V_SMTP_RULES,FOR_RULE|FOR_COMPOSE);
++ add_rule(V_SORT_RULES,FOR_RULE|FOR_SORT);
++ add_rule(V_STARTUP_RULES,FOR_RULE|FOR_STARTUP);
++ }
++
++ int
++ condition_contains_token(condition, token)
++ CONDITION_S *condition;
++ char *token;
++ {
++ if (!condition)
++ return 0;
++
++ if (!strcmp(condition->tname, token))
++ return 1;
++ else
++ return condition_contains_token(condition->next, token);
++ }
++
++ RULELIST *
++ get_rulelist_from_code(code, list)
++ int code;
++ PRULELIST_S *list;
++ {
++ if (!list)
++ return (RULELIST *) NULL;
++
++ if(list->varnum == code)
++ return list->rlist;
++ else
++ return get_rulelist_from_code(code, list->next);
++ }
++
++ char *
++ test_rule(rlist, ctxt, env, n)
++ RULELIST *rlist;
++ int ctxt, *n;
++ ENVELOPE *env;
++ {
++ char *result;
++
++ if(!rlist)
++ return NULL;
++
++ if (result = process_rule(rlist->prule, ctxt, env))
++ return result;
++ else{
++ (*n)++;
++ return test_rule(rlist->next, ctxt, env, n);
++ }
++ }
++
++ RULE_S *
++ get_rule (rule, n)
++ RULELIST *rule;
++ int n;
++ {
++ if (!rule)
++ return (RULE_S *) NULL;
++
++ return n ? get_rule(rule->next, n-1) : rule->prule;
++ }
++
++ /* get_result_rule:
++ * Parameters: list: the list of rules to be passed to the function to check
++ * rule_context: context of the rule
++ * env : envelope used to check the rule, if needed.
++ *
++ * Returns: The value of the first rule that is satisfied in the list, or
++ * NULL if not. This function should be called in the following
++ * way (notice that memory is freed by caller).
++ *
++ * You should use this function to obtain the result of a rule. You can
++ * also call directly "process_rule", but I advice to use this function if
++ * there's no difference on which function to call.
++
++ RULE_RESULT *rule;
++
++ rule = (RULE_RESULT *)
++ get_result_rule(V_SOME_RULE, context, envelope);
++
++ if (rule){
++ assign the value of rule->result;
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ */
++
++ RULE_RESULT *
++ get_result_rule(code, rule_context, env)
++ int code, rule_context;
++ ENVELOPE *env;
++ {
++ char *rule_result;
++ RULE_RESULT *rule = NULL;
++ RULELIST *rlist;
++ int n = 0;
++
++ rlist = get_rulelist_from_code(code, ps_global->rule_list);
++ if (rlist){
++ rule_result = test_rule(rlist, rule_context, env, &n);
++ if (rule_result && *rule_result){
++ rule = (RULE_RESULT *) fs_get (sizeof(RULE_RESULT));
++ rule->result = rule_result;
++ rule->number = n;
++ }
++ }
++ return rule;
++ }
++
++ /* process_rule:
++ Parameters: rule_data, is a rule. It's obtained as
++ rule_data = ps_global->VAR_SOME_RULE[n], for
++ some integer n
++ rule_context: context of the rule, and
++ env: An envelope if needed.
++
++ Returns : The value of the processed rule_data if the processing was
++ successful and matches context and possibly the envelope, or
++ NULL if there's no match
++ */
++
++ char *
++ process_rule (prule, rule_context, env)
++ RULE_S *prule;
++ int rule_context;
++ ENVELOPE *env;
++ {
++ int rv;
++ char *result = NULL;
++ CONDITION_S *condition;
++
++ if(!prule)
++ return NULL;
++
++ for(condition = prule->condition;
++ condition &&
++ (rv = test_condition(condition, rule_context, env));
++ condition = condition->next);
++
++ if(rv && !condition)
++ result = (prule->action->exec)(prule->action, rule_context, env);
++
++ return result;
++ }
++
++ TOKEN_VALUE *
++ copy_parsed_value(value, ctxt, env)
++ TOKEN_VALUE *value;
++ int ctxt;
++ ENVELOPE *env;
++ {
++ TOKEN_VALUE *tval = NULL;
++
++ if(!value)
++ return NULL;
++
++ if(value->testxt){
++ tval = (TOKEN_VALUE *) alloc_mem(sizeof(TOKEN_VALUE));
++ tval->testxt = detoken_src(value->testxt, ctxt, env, NULL, NULL, NULL);
++ }
++ if(value->next)
++ tval->next = copy_parsed_value(value->next, ctxt, env);
++
++ return tval;
++ }
++
++ int
++ test_condition(condition, rule_context, env)
++ CONDITION_S *condition;
++ int rule_context;
++ ENVELOPE *env;
++ {
++ int next_step;
++ TOKEN_VALUE *group;
++
++ group = copy_parsed_value(condition->value, rule_context, env);
++ next_step = (*rel_rules_test[condition->ttype].execute)(condition, group, env, rule_context);
++ free_token_value(&group);
++ return next_step;
++ }
++
++ /* returns the name of the token it found or NULL if there is no token, the
++ * real value of the token is obtained by calling the detoken_src function.
++ */
++
++ char *
++ get_name_token (condition)
++ char *condition;
++ {
++ char *p = NULL, *q, *s;
++
++ if ((q = strchr(condition,'_')) && (s = strchr(q+1,'_'))){
++ char c = *++s;
++ *s = '\0';
++ p = cpystr(q);
++ *s = c;
++ }
++ return p;
++ }
++
++ /* This function tests if a string contained in the variable "group" is
++ * in the "condition"
++ */
++ int test_in (condition, group, env, context)
++ TOKEN_VALUE *group;
++ CONDITION_S *condition;
++ ENVELOPE *env;
++ int context;
++ {
++ int rv = 0;
++ char *test;
++ TOKEN_VALUE *test_group = group;
++
++ test = detoken_src(condition->tname, context, env, NULL, NULL, NULL);
++ if (test){
++ while (rv == 0 && test_group){
++ if(!*test || strstr(test_group->testxt, test))
++ rv++;
++ else
++ test_group = test_group->next;
++ }
++ }
++ return rv;
++ }
++
++ int test_ni (condition, group, env, context)
++ TOKEN_VALUE *group;
++ CONDITION_S *condition;
++ ENVELOPE *env;
++ int context;
++ {
++ int rv = 0;
++ char *test;
++ TOKEN_VALUE *test_group = group;
++
++ test = detoken_src(condition->tname, context, env, NULL, NULL, NULL);
++ if (test){
++ if(!test_group)
++ rv++;
++ while (rv == 0 && test_group){
++ if(!*test_group->testxt || strstr(test, test_group->testxt))
++ rv++;
++ else
++ test_group = test_group->next;
++ }
++ }
++ return rv;
++ }
++
++ int test_not_in (condition, group, env, context)
++ TOKEN_VALUE *group;
++ CONDITION_S *condition;
++ ENVELOPE *env;
++ int context;
++ {
++ return !test_in(condition, group, env, context);
++ }
++
++ int test_not_ni (condition, group, env, context)
++ TOKEN_VALUE *group;
++ CONDITION_S *condition;
++ ENVELOPE *env;
++ int context;
++ {
++ return !test_ni(condition, group, env, context);
++ }
++
++ int test_eq (condition, group, env, context)
++ CONDITION_S *condition;
++ TOKEN_VALUE *group;
++ ENVELOPE *env;
++ int context;
++ {
++ int rv = 0;
++ char *test;
++ TOKEN_VALUE *test_group = group;
++
++ test = detoken_src(condition->tname, context, env, NULL, NULL, NULL);
++ if (test){
++ while (rv == 0 && test_group){
++ if((!*test && !*test_group->testxt) || !strcmp(test_group->testxt, test))
++ rv++;
++ else
++ test_group = test_group->next;
++ }
++ }
++ return rv;
++ }
++
++ int test_not_eq (condition, group, env, context)
++ CONDITION_S *condition;
++ TOKEN_VALUE *group;
++ ENVELOPE *env;
++ int context;
++ {
++ return !test_eq(condition, group, env, context);
++ }
++
++ char *
++ do_trim (test, tval)
++ char *test;
++ TOKEN_VALUE *tval;
++ {
++ char *begin_text;
++ int offset = 0;
++
++ if (!tval)
++ return test;
++
++ while(begin_text = strstr(test+offset,tval->testxt)){
++ strcpy(begin_text, begin_text+strlen(tval->testxt));
++ offset = begin_text - test;
++ }
++
++ return do_trim(test, tval->next);
++ }
++
++ char *
++ trim (action, context, env)
++ RULEACTION_S *action;
++ int context;
++ ENVELOPE *env;
++ {
++ char *begin_text, *test;
++ RULEACTION_S *taction = action;
++ int offset;
++
++ if (taction->context & context){
++ test = detoken_src(taction->token, context, env, NULL, NULL, NULL);
++ if (test)
++ test = do_trim(test, taction->value);
++ return test;
++ }
++ return NULL;
++ }
++
++
++ char *
++ do_rextrim (test, tval)
++ char *test;
++ TOKEN_VALUE *tval;
++ {
++ char *begin_text, *trim_text;
++ int offset = 0;
++
++ if (!tval)
++ return test;
++
++ trim_text = expand(test, tval->testxt);
++ while(trim_text && (begin_text = strstr(test+offset,trim_text))){
++ strcpy(begin_text, begin_text+strlen(trim_text));
++ offset = begin_text - test;
++ }
++
++ return do_rextrim(test, tval->next);
++ }
++
++ char *
++ rextrim (action, context, env)
++ RULEACTION_S *action;
++ int context;
++ ENVELOPE *env;
++ {
++ char *begin_text, *trim_text, *test;
++ RULEACTION_S *taction = action;
++ TOKEN_VALUE **token = NULL;
++ int offset;
++
++ if (taction->context & context){
++ test = detoken_src(taction->token, context, env, NULL, NULL, NULL);
++ if (test){
++ test = do_rextrim(test, taction->value);
++ }
++ return test;
++ }
++ else
++ return NULL;
++ }
++
++ char *
++ raw_value (action, context,env)
++ RULEACTION_S *action;
++ int context;
++ ENVELOPE *env;
++ {
++ return (action->context & context) ? cpystr(action->value->testxt) : NULL;
++ }
++
++ char *
++ extended_value (action, ctxt,env)
++ RULEACTION_S *action;
++ int ctxt;
++ ENVELOPE *env;
++ {
++ return (action->context & ctxt)
++ ? detoken_src(action->value->testxt, ctxt, env, NULL, NULL, NULL)
++ : NULL;
++ }
++
++ /* advances given_string until it finds given_char */
++ char *
++ advance_to_char(given_string,given_char, flag, error)
++ char *given_string;
++ char given_char;
++ int flag;
++ int *error;
++ {
++ char *b, *s, c;
++ int i, err = 0, quoted ;
++
++ if (error)
++ *error = 0;
++
++ if (!given_string || !*given_string)
++ return NULL;
++
++ b = s = cpystr(given_string);
++ for(i = 0, quoted = 0, c = *s; c ; c = *++s){
++ if(c == '\\'){
++ quoted++;
++ continue;
++ }
++ if(quoted){
++ quoted = 0;
++ if (c == given_char){
++ err += flag & STRICT ? 0 : 1;
++ err++;
++ break;
++ }
++ b[i++] = '\\';
++ }
++ if(c == given_char){
++ err += flag & STRICT ? 0 : 1;
++ break;
++ }
++ b[i++] = c;
++ }
++ b[i] = '\0';
++ if (b && (strlen(b) == strlen(given_string)) && (flag & STRICT))
++ return NULL; /* character not found */
++
++ if(b && !*b){
++ fs_give((void **)&b);
++ err = -1;
++ }
++
++ if (error)
++ *error = err;
++
++ return b;
++ }
++
++ /* Regular Expressions Support */
++
++ char *
++ expand (string, pattern)
++ char *string;
++ char *pattern;
++ {
++ char tmp[1000];
++ int error, i = 0;
++ char *new_start, c;
++ char *ret_string = NULL;
++ regex_t preg;
++ regmatch_t pmatch;
++
++ if (error = regcomp(&preg, pattern, REG_EXTENDED)){
++ regerror(error, &preg, tmp, 1000);
++ return NULL;
++ }
++
++ if(((error = regexec(&preg, string, 1, &pmatch, 0)) != REG_NOMATCH)&& !error){
++ c = string[pmatch.rm_eo];
++ string[pmatch.rm_eo] = '\0';
++ ret_string = cpystr(string+pmatch.rm_so);
++ string[pmatch.rm_eo] = c;
++ }
++ return ret_string;
++ }
+diff -rc pine4.63/pine/rules.h pine4.63.I.USE/pine/rules.h
+*** pine4.63/pine/rules.h Thu May 19 19:59:15 2005
+--- pine4.63.I.USE/pine/rules.h Thu May 19 19:57:27 2005
+***************
+*** 0 ****
+--- 1,204 ----
++ #include "headers.h"
++ #ifndef _REGEX_H_
++ #include <regex.h>
++ #endif
++
++ int is_save; /* this rule has the form condition -> folder */
++ typedef struct {
++ char *value;
++ int type;
++ } RULE_ACTION;
++
++
++ RULE_RESULT *get_result_rule PROTO ((int, int, ENVELOPE *));
++ char *test_rule PROTO ((RULELIST *, int, ENVELOPE *, int *));
++ char *process_rule PROTO ((RULE_S *, int, ENVELOPE *));
++ int test_condition PROTO ((CONDITION_S *, int, ENVELOPE *));
++ int test_in PROTO ((CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int));
++ int test_ni PROTO ((CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int));
++ int test_not_in PROTO ((CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int));
++ int test_not_ni PROTO ((CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int));
++ int test_eq PROTO ((CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int));
++ int test_not_eq PROTO ((CONDITION_S *, TOKEN_VALUE *, ENVELOPE *, int));
++ char *trim PROTO ((RULEACTION_S *, int, ENVELOPE *));
++ char *rextrim PROTO ((RULEACTION_S *, int, ENVELOPE *));
++ char *raw_value PROTO ((RULEACTION_S *, int, ENVELOPE *));
++ char *extended_value PROTO ((RULEACTION_S *, int, ENVELOPE *));
++ char *expand PROTO((char *, char *));
++ char *get_name_token PROTO((char *));
++ char *advance_to_char PROTO ((char *, char, int, int *));
++
++ /* Separators:
++ *
++ * A separator is a string that separates the rule condition with the rule
++ * action. Below is the list of separators
++ *
++ */
++
++ #define SAVE_TO_SEP "->"
++ #define APPLY_SEP "=>"
++
++ /*------- Definitions of tokens -------*/
++ /*------ Keep the list alphabetically sorted, thanks -------*/
++
++ #define ADDR_TOKEN "_ADDRESS_"
++ #define ADDCC_TOKEN "_ADDRESSCC_"
++ #define ADDRECIP_TOKEN "_ADDRESSRECIPS_"
++ #define ADDTO_TOKEN "_ADDRESSTO_"
++ #define BCC_TOKEN "_BCC_"
++ #define CC_TOKEN "_CC_"
++ #define COLLECT_TOKEN "_COLLECTION_"
++ #define FLAG_TOKEN "_FLAG_"
++ #define FOLDER_TOKEN "_FOLDER_"
++ #define FADDRESS_TOKEN "_FORWARDADDRESS_"
++ #define FFROM_TOKEN "_FORWARDFROM_"
++ #define FROM_TOKEN "_FROM_"
++ #define LCC_TOKEN "_LCC_"
++ #define NICK_TOKEN "_NICK_"
++ #define ROLE_TOKEN "_ROLE_"
++ #define SEND_TOKEN "_SENDER_"
++ #define SUBJ_TOKEN "_SUBJECT_"
++ #define THDDSPSTY_TOKEN "_THREADSTYLE_"
++ #define THDNDXSTY_TOKEN "_THREADINDEX_"
++ #define TO_TOKEN "_TO_"
++
++ /* Mail related tokens
++ *
++ * The following is an array with the list of tokens.
++ */
++
++ char* token_rules[] = {
++ FROM_TOKEN,
++ NICK_TOKEN,
++ ROLE_TOKEN,
++ FOLDER_TOKEN,
++ SUBJ_TOKEN,
++ THDDSPSTY_TOKEN,
++ THDNDXSTY_TOKEN,
++ FLAG_TOKEN,
++ COLLECT_TOKEN,
++ THDDSPSTY_TOKEN,
++ ADDR_TOKEN,
++ TO_TOKEN,
++ ADDTO_TOKEN,
++ ADDCC_TOKEN,
++ ADDRECIP_TOKEN,
++ SEND_TOKEN,
++ CC_TOKEN,
++ LCC_TOKEN,
++ BCC_TOKEN,
++ FFROM_TOKEN,
++ FADDRESS_TOKEN,
++ NULL
++ };
++
++ #define NTOKENS (sizeof(token_rules)/sizeof(token_rules[0]) - 1)
++
++ /*------ Definitions of relational operands -------------*/
++
++ typedef struct {
++ char *value;
++ TestType ttype;
++ int (*execute)();
++ } REL_TOKEN;
++
++ /* Relational Operands */
++ #define AND_REL "&&" /* For putting more than one condition */
++ #define IN_REL "<<" /* For belonging relation */
++ #define NI_REL ">>" /* For contain relation */
++ #define NOT_IN_REL "!<" /* Negation of IN_REL */
++ #define NOT_NI_REL "!>" /* Negation of NI_REL */
++ #define EQ_REL "==" /* Test of equality */
++ #define NOT_EQ_REL "!=" /* Test of inequality */
++ #define OPEN_SET "{" /* Braces to open a set */
++ #define CLOSE_SET "}" /* Braces to close a set*/
++
++ REL_TOKEN rel_rules_test[] = {
++ {EQ_REL, Equal, test_eq},
++ {IN_REL, Subset, test_in},
++ {NI_REL, Includes, test_ni},
++ {NOT_EQ_REL, NotEqual, test_not_eq},
++ {NOT_IN_REL, NotSubset, test_not_in},
++ {NOT_NI_REL, NotIncludes, test_not_ni},
++ {NULL, EndTypes, NULL}
++ };
++
++ #define NREL (sizeof(rel_rules_test)/sizeof(rel_rules_test[0]) - 1)
++
++ /*--- Context in which these variables can be used ---*/
++
++ typedef struct use_context {
++ char *name;
++ int what_for;
++ } USE_IN_CONTEXT;
++
++
++ static USE_IN_CONTEXT tokens_use[] = {
++ {NICK_TOKEN, FOR_SAVE},
++ {FROM_TOKEN, FOR_SAVE},
++ {ROLE_TOKEN, FOR_COMPOSE},
++ {FOLDER_TOKEN, FOR_SAVE|FOR_FOLDER|FOR_THREAD},
++ {SUBJ_TOKEN, FOR_SAVE|FOR_FOLDER},
++ {FLAG_TOKEN, FOR_SAVE|FOR_FLAG},
++ {COLLECT_TOKEN, FOR_SAVE|FOR_COMPOSE|FOR_FOLDER|FOR_THREAD},
++ {THDDSPSTY_TOKEN, FOR_THREAD},
++ {THDNDXSTY_TOKEN, FOR_THREAD},
++ {ADDR_TOKEN, FOR_SAVE|FOR_FOLDER},
++ {TO_TOKEN, FOR_SAVE},
++ {ADDTO_TOKEN, FOR_SAVE|FOR_COMPOSE},
++ {ADDCC_TOKEN, FOR_SAVE|FOR_COMPOSE},
++ {ADDRECIP_TOKEN, FOR_SAVE|FOR_COMPOSE},
++ {SEND_TOKEN, FOR_SAVE},
++ {CC_TOKEN, FOR_SAVE},
++ {BCC_TOKEN, FOR_COMPOSE},
++ {LCC_TOKEN, FOR_COMPOSE},
++ {FFROM_TOKEN, FOR_COMPOSE},
++ {FADDRESS_TOKEN, FOR_COMPOSE},
++ {NULL, FOR_NOTHING}
++ };
++
++
++ typedef struct {
++ char *name;
++ char* (*execute)();
++ int what_for;
++ } RULE_FCN;
++
++ #define INDEX_FCN "_INDEX_"
++ #define REPLACE_FCN "_REPLACE_"
++ #define REPLYSTR_FCN "_RESTR_"
++ #define REPLY_FCN "_REPLY_"
++ #define RESUB_FCN "_RESUB_"
++ #define REXTRIM_FCN "_REXTRIM_"
++ #define SAVE_FCN "_SAVE_"
++ #define SIGNATURE_FCN "_SIGNATURE_"
++ #define SMTP_FCN "_SMTP_"
++ #define SORT_FCN "_SORT_"
++ #define STARTUP_FCN "_STARTUP_"
++ #define THRDSTYLE_FCN "_THREADSTYLE_"
++ #define THRDINDEX_FCN "_THREADINDEX_"
++ #define TRIM_FCN "_TRIM_"
++
++
++ RULE_FCN rule_fcns[] = {
++ {SAVE_FCN, extended_value, FOR_SAVE},
++ {REPLY_FCN, extended_value, FOR_REPLY_INTRO},
++ {TRIM_FCN, trim, FOR_TRIM | FOR_RESUB},
++ {REPLACE_FCN, extended_value, FOR_REPLACE},
++ {SORT_FCN, raw_value, FOR_SORT},
++ {INDEX_FCN, raw_value, FOR_INDEX},
++ {REPLYSTR_FCN, raw_value, FOR_COMPOSE},
++ {SIGNATURE_FCN, raw_value, FOR_COMPOSE},
++ {RESUB_FCN, extended_value, FOR_RESUB},
++ {STARTUP_FCN, raw_value, FOR_STARTUP},
++ {REXTRIM_FCN, rextrim, FOR_TRIM | FOR_RESUB},
++ {THRDSTYLE_FCN, raw_value, FOR_THREAD},
++ {THRDINDEX_FCN, raw_value, FOR_THREAD},
++ {SMTP_FCN, raw_value, FOR_COMPOSE}
++ };
++
++ #define NFCN (sizeof(rule_fcns)/sizeof(rule_fcns[0]))
++
++ #define STRICT 0x1
++ #define RELAXED 0x2
++
+diff -rc pine4.63/pine/send.c pine4.63.I.USE/pine/send.c
+*** pine4.63/pine/send.c Mon Mar 21 12:14:41 2005
+--- pine4.63.I.USE/pine/send.c Thu May 19 19:57:31 2005
+***************
+*** 377,382 ****
+--- 377,387 ----
+ role->nick = cpystr("Default Role");
+ }
+
++ if (ps_global->role)
++ fs_give((void **)&ps_global->role);
++
++ ps_global->role = cpystr(role->nick);
++
+ pine_state->redrawer = NULL;
+ compose_mail(NULL, NULL, role, NULL, NULL);
+ free_action(&role);
+***************
+*** 581,588 ****
+ }
+ ps_global->next_screen = prev_screen;
+ ps_global->redrawer = redraw;
+! if(role)
+ role = combine_inherited_role(role);
+ }
+ break;
+ case 'f':
+--- 586,597 ----
+ }
+ ps_global->next_screen = prev_screen;
+ ps_global->redrawer = redraw;
+! if (ps_global->role)
+! fs_give((void **)&ps_global->role);
+! if(role){
+ role = combine_inherited_role(role);
++ ps_global->role = cpystr(role->nick);
++ }
+ }
+ break;
+ case 'f':
+***************
+*** 675,680 ****
+--- 684,694 ----
+
+ if(exists & FEX_ISFILE){
+ context_apply(tmp, p_cntxt, mbox, sizeof(tmp));
++ if (!strncmp(tmp, "#md/",4) || !struncmp(tmp, "#mc/", 4)){
++ char tmp2[MAILTMPLEN];
++ maildir_file_path(tmp, tmp2);
++ strcpy(tmp, tmp2);
++ }
+ if(!(IS_REMOTE(tmp) || is_absolute_path(tmp))){
+ /*
+ * The mbox is relative to the home directory.
+***************
+*** 775,780 ****
+--- 789,799 ----
+
+ if(exists & FEX_ISFILE){
+ context_apply(tmp, p_cntxt, mbox, sizeof(tmp));
++ if (!strncmp(tmp, "#md/",4) || !struncmp(tmp, "#mc/", 4)){
++ char tmp2[MAILTMPLEN];
++ maildir_file_path(tmp, tmp2);
++ strcpy(tmp, tmp2);
++ }
+ if(!(IS_REMOTE(tmp) || is_absolute_path(tmp))){
+ /*
+ * The mbox is relative to the home directory.
+***************
+*** 864,869 ****
+--- 883,889 ----
+ if(given_to)
+ rfc822_parse_adrlist(&outgoing->to, given_to, ps_global->maildomain);
+
++ outgoing->subject = cpystr(ps_global->subject);
+ outgoing->message_id = generate_message_id();
+
+ /*
+***************
+*** 894,902 ****
+ }
+ }
+
+! if(role)
+ q_status_message1(SM_ORDER, 3, 4, "Composing using role \"%.200s\"",
+ role->nick);
+
+ /*
+ * The type of storage object allocated below is vitally
+--- 914,928 ----
+ }
+ }
+
+! if (ps_global->role)
+! fs_give((void **)&ps_global->role);
+!
+!
+! if(role){
+ q_status_message1(SM_ORDER, 3, 4, "Composing using role \"%.200s\"",
+ role->nick);
++ ps_global->role = cpystr(role->nick);
++ }
+
+ /*
+ * The type of storage object allocated below is vitally
+***************
+*** 2195,2201 ****
+ static struct headerentry he_template[]={
+ {"From : ", "From", h_composer_from, 10, 0, NULL,
+ build_address, NULL, NULL, addr_book_compose, "To AddrBk", NULL,
+! 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, KS_TOADDRBOOK},
+ {"Reply-To: ", "Reply To", h_composer_reply_to, 10, 0, NULL,
+ build_address, NULL, NULL, addr_book_compose, "To AddrBk", NULL,
+ 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, KS_TOADDRBOOK},
+--- 2221,2227 ----
+ static struct headerentry he_template[]={
+ {"From : ", "From", h_composer_from, 10, 0, NULL,
+ build_address, NULL, NULL, addr_book_compose, "To AddrBk", NULL,
+! 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, KS_TOADDRBOOK},
+ {"Reply-To: ", "Reply To", h_composer_reply_to, 10, 0, NULL,
+ build_address, NULL, NULL, addr_book_compose, "To AddrBk", NULL,
+ 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, KS_TOADDRBOOK},
+***************
+*** 2302,2308 ****
+ #define N_OURREPLYTO 21
+ #define N_OURHDRS 22
+ #define N_SENDER 23
+!
+ #define TONAME "To"
+ #define CCNAME "cc"
+ #define SUBJNAME "Subject"
+--- 2328,2335 ----
+ #define N_OURREPLYTO 21
+ #define N_OURHDRS 22
+ #define N_SENDER 23
+! #define CAN_EDIT(x) (!((x)->never_allow_changing_from) && \
+! F_ON(F_ALLOW_CHANGING_FROM, (x)))
+ #define TONAME "To"
+ #define CCNAME "cc"
+ #define SUBJNAME "Subject"
+***************
+*** 2310,2316 ****
+ /* this is used in pine_send and pine_simple_send */
+ /* name::type::canedit::writehdr::localcopy::rcptto */
+ static PINEFIELD pf_template[] = {
+! {"From", Address, 0, 1, 1, 0},
+ {"Reply-To", Address, 0, 1, 1, 0},
+ {TONAME, Address, 1, 1, 1, 1},
+ {CCNAME, Address, 1, 1, 1, 1},
+--- 2337,2343 ----
+ /* this is used in pine_send and pine_simple_send */
+ /* name::type::canedit::writehdr::localcopy::rcptto */
+ static PINEFIELD pf_template[] = {
+! {"From", Address, 1, 1, 1, 0},
+ {"Reply-To", Address, 0, 1, 1, 0},
+ {TONAME, Address, 1, 1, 1, 1},
+ {CCNAME, Address, 1, 1, 1, 1},
+***************
+*** 2459,2465 ****
+ *p = *(p+4);
+
+ pf->type = pf_template[i].type;
+! pf->canedit = pf_template[i].canedit;
+ pf->rcptto = pf_template[i].rcptto;
+ pf->writehdr = pf_template[i].writehdr;
+ pf->localcopy = pf_template[i].localcopy;
+--- 2486,2492 ----
+ *p = *(p+4);
+
+ pf->type = pf_template[i].type;
+! pf->canedit = (i == N_FROM) ? CAN_EDIT(ps_global) : pf_template[i].canedit;
+ pf->rcptto = pf_template[i].rcptto;
+ pf->writehdr = pf_template[i].writehdr;
+ pf->localcopy = pf_template[i].localcopy;
+***************
+*** 3175,3180 ****
+--- 3202,3210 ----
+ pbf = &pbuf1;
+ standard_picobuf_setup(pbf);
+
++ pbf->auto_cmds = ps_global->initial_cmds_backup +
++ ps_global->initial_cmds_offset;
++
+ /*
+ * Cancel any pending initial commands since pico uses a different
+ * input routine. If we didn't cancel them, they would happen after
+***************
+*** 3662,3667 ****
+--- 3692,3702 ----
+ he->rich_header = 0;
+ }
+ }
++ if (F_ON(F_ALLOW_CHANGING_FROM, ps_global) &&
++ !ps_global->never_allow_changing_from){
++ he->display_it = 1; /* show it */
++ he->rich_header = 0;
++ }
+
+ he_from = he;
+ break;
+***************
+*** 3769,3774 ****
+--- 3804,3827 ----
+ removing_trailing_white_space(pf->textbuf);
+ (void)removing_double_quotes(pf->textbuf);
+ build_address(pf->textbuf, &addr, NULL, NULL, NULL);
++ if (!strncmp(pf->name,"Lcc",3) && addr && *addr){
++ RULE_RESULT *rule;
++
++ outgoing->date = cpystr(addr);
++ rule = get_result_rule(V_FORWARD_RULES,
++ FOR_RULE|FOR_COMPOSE|FOR_TRIM, outgoing);
++ if (rule){
++ addr = cpystr(rule->result);
++ removing_trailing_white_space(addr);
++ (void)removing_extra_stuff(addr);
++ if (rule->result)
++ fs_give((void **)&rule->result);
++ fs_give((void **)&rule);
++ }
++ if (outgoing->date)
++ fs_give((void **)&outgoing->date);
++ }
++
+ rfc822_parse_adrlist(pf->addr, addr,
+ ps_global->maildomain);
+ fs_give((void **)&addr);
+***************
+*** 4274,4282 ****
+--- 4327,4338 ----
+ /* turn off user input timeout when in composer */
+ saved_user_timeout = ps_global->hours_to_timeout;
+ ps_global->hours_to_timeout = 0;
++ ps_global->in_pico = 1; /* in */
+ dprint(1, (debugfile, "\n ---- COMPOSER ----\n"));
+ editor_result = pico(pbf);
++ ps_global->force_check_now = 0; /* do not check incoming folders now */
+ dprint(4, (debugfile, "... composer returns (0x%x)\n", editor_result));
++ ps_global->in_pico = 0; /* out */
+ ps_global->hours_to_timeout = saved_user_timeout;
+
+ #if defined(DOS) && !defined(_WINDOWS)
+***************
+*** 4285,4291 ****
+ #ifdef _WINDOWS
+ mswin_setwindowmenu (MENU_DEFAULT);
+ #endif
+! fix_windsize(ps_global);
+ /*
+ * Only reinitialize signals if we didn't receive an interesting
+ * one while in pico, since pico's return is part of processing that
+--- 4341,4352 ----
+ #ifdef _WINDOWS
+ mswin_setwindowmenu (MENU_DEFAULT);
+ #endif
+! if (ps_global->send_immediately){
+! if(ps_global->free_initial_cmds_backup)
+! fs_give((void **)&ps_global->free_initial_cmds_backup);
+! }
+! else
+! fix_windsize(ps_global);
+ /*
+ * Only reinitialize signals if we didn't receive an interesting
+ * one while in pico, since pico's return is part of processing that
+***************
+*** 4345,4351 ****
+ if(outgoing->return_path)
+ mail_free_address(&outgoing->return_path);
+
+! outgoing->return_path = rfc822_cpy_adr(outgoing->from);
+
+ /*
+ * Don't ever believe the sender that is there.
+--- 4406,4414 ----
+ if(outgoing->return_path)
+ mail_free_address(&outgoing->return_path);
+
+! outgoing->return_path = F_ON(F_USE_DOMAIN_NAME,ps_global)
+! ? rfc822_cpy_adr(generate_from())
+! : rfc822_cpy_adr(outgoing->from);
+
+ /*
+ * Don't ever believe the sender that is there.
+***************
+*** 4947,4956 ****
+ if(sending_filter_requested
+ && !filter_message_text(sending_filter_requested, outgoing,
+ *body, &orig_so, &header)){
+! q_status_message1(SM_ORDER, 3, 3,
+ "Problem filtering! Nothing sent%.200s.",
+ fcc ? " or saved to fcc" : "");
+! continue;
+ }
+
+ /*------ Actually post -------*/
+--- 5010,5025 ----
+ if(sending_filter_requested
+ && !filter_message_text(sending_filter_requested, outgoing,
+ *body, &orig_so, &header)){
+! if (!ps_global->send_immediately){
+! q_status_message1(SM_ORDER, 3, 3,
+ "Problem filtering! Nothing sent%.200s.",
+ fcc ? " or saved to fcc" : "");
+! continue;
+! }
+! else{
+! fprintf(stderr, "Problem filtering! Nothing sent or saved to Fcc\n");
+! exit(-1);
+! }
+ }
+
+ /*------ Actually post -------*/
+***************
+*** 5171,5176 ****
+--- 5240,5247 ----
+ /*----- Mail Post FAILED, back to composer -----*/
+ if(result & (P_MAIL_LOSE | P_FCC_LOSE)){
+ dprint(1, (debugfile, "Send failed, continuing\n"));
++ if (ps_global->send_immediately)
++ exit(1);
+
+ if(result & P_FCC_LOSE){
+ /*
+***************
+*** 5205,5210 ****
+--- 5276,5282 ----
+ update_answered_flags(reply);
+
+ /*----- Signed, sealed, delivered! ------*/
++ if (!ps_global->send_immediately)
+ q_status_message(SM_ORDER, 0, 3,
+ pine_send_status(result, fcc, tmp_20k_buf, NULL));
+
+***************
+*** 5789,5795 ****
+ if(background_posting(FALSE))
+ return("Can't send while background posting. Use postpone.");
+
+! if(F_ON(F_SEND_WO_CONFIRM, ps_global))
+ return(NULL);
+
+ ps_global->redrawer = redraw_pico;
+--- 5861,5867 ----
+ if(background_posting(FALSE))
+ return("Can't send while background posting. Use postpone.");
+
+! if(!ps_global->send_immediately && F_ON(F_SEND_WO_CONFIRM, ps_global))
+ return(NULL);
+
+ ps_global->redrawer = redraw_pico;
+***************
+*** 5940,5946 ****
+
+ opts[i].ch = -1;
+
+! fix_windsize(ps_global);
+
+ while(1){
+ if(filters && filters->filter && (p = strindex(filters->filter, ' ')))
+--- 6012,6019 ----
+
+ opts[i].ch = -1;
+
+! if (!ps_global->send_immediately)
+! fix_windsize(ps_global);
+
+ while(1){
+ if(filters && filters->filter && (p = strindex(filters->filter, ' ')))
+***************
+*** 6075,6081 ****
+
+ if(double_rad +
+ (dsn_requested ? 4 : F_ON(F_DSN, ps_global) ? 1 : 0) > 11)
+! rv = double_radio_buttons(tmp_20k_buf, -FOOTER_ROWS(ps_global), opts,
+ 'y', 'z',
+ (F_ON(F_DSN, ps_global) && allow_flowed)
+ ? h_send_prompt_dsn_flowed :
+--- 6148,6155 ----
+
+ if(double_rad +
+ (dsn_requested ? 4 : F_ON(F_DSN, ps_global) ? 1 : 0) > 11)
+! rv = ps_global->send_immediately ? 'y' :
+! double_radio_buttons(tmp_20k_buf, -FOOTER_ROWS(ps_global), opts,
+ 'y', 'z',
+ (F_ON(F_DSN, ps_global) && allow_flowed)
+ ? h_send_prompt_dsn_flowed :
+***************
+*** 6084,6090 ****
+ h_send_prompt,
+ RB_NORM);
+ else
+! rv = radio_buttons(tmp_20k_buf, -FOOTER_ROWS(ps_global), opts,
+ 'y', 'z',
+ (double_rad +
+ (dsn_requested ? 4 : F_ON(F_DSN, ps_global)
+--- 6158,6165 ----
+ h_send_prompt,
+ RB_NORM);
+ else
+! rv = ps_global->send_immediately ? 'y' :
+! radio_buttons(tmp_20k_buf, -FOOTER_ROWS(ps_global), opts,
+ 'y', 'z',
+ (double_rad +
+ (dsn_requested ? 4 : F_ON(F_DSN, ps_global)
+***************
+*** 6671,6679 ****
+ if(tmp_so = so_get(PicoText, NULL, EDIT_ACCESS)){
+ gf_set_so_writec(&pc, tmp_so);
+ ps_global->mangled_screen = 1;
+! suspend_busy_alarm();
+! ClearScreen();
+! fflush(stdout);
+ if(tmpf){
+ PIPE_S *fpipe;
+
+--- 6746,6756 ----
+ if(tmp_so = so_get(PicoText, NULL, EDIT_ACCESS)){
+ gf_set_so_writec(&pc, tmp_so);
+ ps_global->mangled_screen = 1;
+! if (!ps_global->send_immediately){
+! suspend_busy_alarm();
+! ClearScreen();
+! fflush(stdout);
+! }
+ if(tmpf){
+ PIPE_S *fpipe;
+
+***************
+*** 6779,6787 ****
+ b->encoding = ENCOTHER;
+ set_mime_type_by_grope(b, NULL);
+ }
+!
+! ClearScreen();
+! resume_busy_alarm(0);
+ }
+ else
+ errstr = "Can't create space for filtered text.";
+--- 6856,6865 ----
+ b->encoding = ENCOTHER;
+ set_mime_type_by_grope(b, NULL);
+ }
+! if (!ps_global->send_immediately){
+! ClearScreen();
+! resume_busy_alarm(0);
+! }
+ }
+ else
+ errstr = "Can't create space for filtered text.";
+***************
+*** 6812,6821 ****
+ if(tmp_so)
+ so_give(&tmp_so);
+
+! q_status_message1(SM_ORDER | SM_DING, 3, 6, "Problem filtering: %.200s",
+ errstr);
+! dprint(1, (debugfile, "Filter FAILED: %s\n",
+ errstr ? errstr : "?"));
+ }
+
+ return(errstr == NULL);
+--- 6890,6905 ----
+ if(tmp_so)
+ so_give(&tmp_so);
+
+! if (!ps_global->send_immediately){
+! q_status_message1(SM_ORDER | SM_DING, 3, 6, "Problem filtering: %.200s",
+ errstr);
+! dprint(1, (debugfile, "Filter FAILED: %s\n",
+ errstr ? errstr : "?"));
++ }
++ else{
++ fprintf(stderr, "Filter FAILED: %s\n", errstr ? errstr : "?");
++ exit(-1);
++ }
+ }
+
+ return(errstr == NULL);
+***************
+*** 6971,6979 ****
+ char error_buf[200], *error_mess = NULL, *postcmd;
+ ADDRESS *a;
+ ENVELOPE *fake_env = NULL;
+! int addr_error_count, we_cancel = 0;
+ long smtp_opts = 0L;
+! char *verbose_file = NULL;
+ BODY *bp = NULL;
+ PINEFIELD *pf;
+
+--- 7055,7063 ----
+ char error_buf[200], *error_mess = NULL, *postcmd;
+ ADDRESS *a;
+ ENVELOPE *fake_env = NULL;
+! int addr_error_count, we_cancel = 0, choice, num_rules = 0, added_rules = -1;
+ long smtp_opts = 0L;
+! char *verbose_file = NULL, **smtp_list;
+ BODY *bp = NULL;
+ PINEFIELD *pf;
+
+***************
+*** 7101,7119 ****
+ * was either none specified or we decided not to use it. So,
+ * if there's an smtp-server defined anywhere,
+ */
+! if(alt_smtp_servers && alt_smtp_servers[0] && alt_smtp_servers[0][0]){
+! /*---------- SMTP ----------*/
+! dprint(4, (debugfile, "call_mailer: via TCP (%s)\n",
+! alt_smtp_servers[0]));
+! TIME_STAMP("smtp-open start (tcp)", 1);
+! sending_stream = smtp_open(alt_smtp_servers, smtp_opts);
+ }
+! else if(ps_global->VAR_SMTP_SERVER && ps_global->VAR_SMTP_SERVER[0]
+! && ps_global->VAR_SMTP_SERVER[0][0]){
+ /*---------- SMTP ----------*/
+! dprint(4, (debugfile, "call_mailer: via TCP\n"));
+ TIME_STAMP("smtp-open start (tcp)", 1);
+! sending_stream = smtp_open(ps_global->VAR_SMTP_SERVER, smtp_opts);
+ }
+ else if(postcmd = smtp_command(ps_global->c_client_error)){
+ char *cmdlist[2];
+--- 7185,7234 ----
+ * was either none specified or we decided not to use it. So,
+ * if there's an smtp-server defined anywhere,
+ */
+!
+! /* First we check for rules and make a list using the rules */
+! if(ps_global->VAR_SMTP_RULES && ps_global->VAR_SMTP_RULES[0]
+! && ps_global->VAR_SMTP_RULES[0][0])
+! while (ps_global->VAR_SMTP_RULES[num_rules]) num_rules++;
+!
+! if(num_rules){
+! int i = 0, j = 0;
+!
+! added_rules = 0;
+! smtp_list = (char **) fs_get ((num_rules + 1)*sizeof(char*));
+! for (i = 0; i < num_rules; i++){
+! RULELIST *rule = get_rulelist_from_code(V_SMTP_RULES,
+! ps_global->rule_list);
+! RULE_S *prule = get_rule(rule, i);
+! if(prule){
+! char *rule_result = process_rule(prule, FOR_RULE|FOR_COMPOSE,
+! header->env);
+! if (rule_result && *rule_result){
+! smtp_list[j++] = cpystr(rule_result);
+! added_rules++;
+! }
+! }
+! }
+ }
+!
+! if (added_rules < 0){
+! smtp_list = (char **) fs_get (sizeof(char*));
+! added_rules = 0;
+! }
+! smtp_list[added_rules] = NULL;
+!
+! choice = smtp_list && smtp_list[0] && smtp_list[0][0] ? 3 :
+! (alt_smtp_servers && alt_smtp_servers[0] && alt_smtp_servers[0][0] ? 2 :
+! (ps_global->VAR_SMTP_SERVER && ps_global->VAR_SMTP_SERVER[0] && ps_global->VAR_SMTP_SERVER[0][0] ? 1 : -1));
+!
+! if(choice > 0){
+ /*---------- SMTP ----------*/
+! dprint(4, (debugfile, "call_mailer: via TCP (%s)\n",
+! smtp_list[0]));
+ TIME_STAMP("smtp-open start (tcp)", 1);
+! sending_stream = smtp_open(choice == 3 ? smtp_list
+! : (choice == 2 ? alt_smtp_servers
+! : ps_global->VAR_SMTP_SERVER), smtp_opts);
+ }
+ else if(postcmd = smtp_command(ps_global->c_client_error)){
+ char *cmdlist[2];
+***************
+*** 7313,7318 ****
+--- 7428,7435 ----
+
+ q_status_message(SM_ORDER | SM_DING, 4, 7, error_mess);
+ dprint(1, (debugfile, "call_mailer ERROR: %s\n", error_mess));
++ if (ps_global->send_immediately)
++ printf("%s\n",error_mess);
+ return(-1);
+ }
+ else{
+diff -rc pine4.63/pine/signals.c pine4.63.I.USE/pine/signals.c
+*** pine4.63/pine/signals.c Thu Nov 4 14:33:05 2004
+--- pine4.63.I.USE/pine/signals.c Thu May 19 19:57:34 2005
+***************
+*** 673,679 ****
+
+ add_review_message(buf, -1);
+ }
+! else{
+ q_status_message(SM_ORDER, 0, 1, progress);
+
+ /*
+--- 673,680 ----
+
+ add_review_message(buf, -1);
+ }
+! else if (!ps_global->send_immediately
+! && !ps_global->checking_incfld){
+ q_status_message(SM_ORDER, 0, 1, progress);
+
+ /*
+***************
+*** 683,700 ****
+ * its min display time yet. In that case, we don't want
+ * to force out the initial message.
+ */
+! display_message('x');
+ }
+ }
+
+ #ifdef _WINDOWS
+ mswin_setcursor (MSWIN_CURSOR_BUSY);
+ #endif
+ fflush(stdout);
+ }
+
+ /* set alarm */
+! if(F_OFF(F_DISABLE_ALARM, ps_global))
+ alarm(seconds);
+
+ return(retval);
+--- 684,703 ----
+ * its min display time yet. In that case, we don't want
+ * to force out the initial message.
+ */
+! display_message('x');
+ }
+ }
+
+ #ifdef _WINDOWS
+ mswin_setcursor (MSWIN_CURSOR_BUSY);
+ #endif
++ if (!ps_global->send_immediately)
+ fflush(stdout);
+ }
+
+ /* set alarm */
+! if(F_OFF(F_DISABLE_ALARM, ps_global) && !ps_global->send_immediately
+! && !ps_global->checking_incfld)
+ alarm(seconds);
+
+ return(retval);
+***************
+*** 731,748 ****
+
+ right = (slots_used - 4)/2;
+ left = slots_used - 4 - right;
+ sprintf(progress, "%s |%*s100%%%*s|",
+ busy_message, left, "", right, "");
+ q_status_message(SM_ORDER,
+ message_pri>=2 ? max(message_pri,3) : 0,
+! message_pri+2, progress);
+ }
+ else{
+ sprintf(progress, "%s%*sDONE", busy_message,
+ DISPLAY_CHARS_COLS - 4 + 1, "");
+ q_status_message(SM_ORDER,
+ message_pri>=2 ? max(message_pri,3) : 0,
+! message_pri+2, progress);
+ }
+ }
+ else
+--- 734,755 ----
+
+ right = (slots_used - 4)/2;
+ left = slots_used - 4 - right;
++ if (!ps_global->send_immediately){
+ sprintf(progress, "%s |%*s100%%%*s|",
+ busy_message, left, "", right, "");
++ if (!ps_global->checking_incfld)
+ q_status_message(SM_ORDER,
+ message_pri>=2 ? max(message_pri,3) : 0,
+! message_pri+2, progress);}
+ }
+ else{
++ if (!ps_global->send_immediately){
+ sprintf(progress, "%s%*sDONE", busy_message,
+ DISPLAY_CHARS_COLS - 4 + 1, "");
++ if (!ps_global->checking_incfld)
+ q_status_message(SM_ORDER,
+ message_pri>=2 ? max(message_pri,3) : 0,
+! message_pri+2, progress);}
+ }
+ }
+ else
+diff -rc pine4.63/pine/status.c pine4.63.I.USE/pine/status.c
+*** pine4.63/pine/status.c Tue Apr 26 15:15:45 2005
+--- pine4.63.I.USE/pine/status.c Thu May 19 19:57:28 2005
+***************
+*** 142,147 ****
+--- 142,150 ----
+ char *clean_msg;
+ size_t mlen;
+
++ if (ps_global->send_immediately)
++ return;
++
+ /*
+ * By convention, we have min_time equal to zero in messages which we
+ * think are not as important, so-called comfort messages. We have
+***************
+*** 1184,1190 ****
+ char *q2;
+ int rv;
+
+! if(!ps_global->ttyo)
+ return(pre_screen_config_want_to(question, dflt, on_ctrl_C));
+ #ifdef _WINDOWS
+ if (mswin_usedialog ()) {
+--- 1187,1193 ----
+ char *q2;
+ int rv;
+
+! if((!ps_global->ttyo) || (ps_global->send_immediately))
+ return(pre_screen_config_want_to(question, dflt, on_ctrl_C));
+ #ifdef _WINDOWS
+ if (mswin_usedialog ()) {
+diff -rc pine4.63/pine/strings.c pine4.63.I.USE/pine/strings.c
+*** pine4.63/pine/strings.c Fri Apr 15 15:07:17 2005
+--- pine4.63.I.USE/pine/strings.c Thu May 19 19:57:27 2005
+***************
+*** 6069,6075 ****
+ SortOrder def_sort;
+ int def_sort_rev;
+
+! if(decode_sort(p, &def_sort, &def_sort_rev) != -1){
+ action->sort_is_set = 1;
+ action->sortorder = def_sort;
+ action->revsort = (def_sort_rev ? 1 : 0);
+--- 6069,6075 ----
+ SortOrder def_sort;
+ int def_sort_rev;
+
+! if(decode_sort(p, &def_sort, &def_sort_rev, 0) != -1){
+ action->sort_is_set = 1;
+ action->sortorder = def_sort;
+ action->revsort = (def_sort_rev ? 1 : 0);
+***************
+*** 9624,9629 ****
+--- 9624,9635 ----
+ break;
+
+ case '#':
++ if(!struncmp(patfolder, "#md/", 4)
++ || !struncmp(patfolder, "#mc/", 4)){
++ maildir_file_path(patfolder, tmp1);
++ strncpy(patfolder, tmp1, sizeof(patfolder));
++ patfolder[sizeof(patfolder)-1] = '\0';
++ }
+ if(!strcmp(patfolder, stream->mailbox))
+ match++;
+
+***************
+*** 11417,11419 ****
+--- 11423,11457 ----
+
+ return(idata);
+ }
++
++
++ void
++ removing_extra_stuff(string)
++ char *string;
++ {
++ char *p = NULL;
++ int change = 0, length = 0;
++
++
++ if(!string)
++ return;
++
++ for(; *string; string++, length++)
++ p = ((unsigned char)*string != ',') ? NULL : (!p) ? string : p;
++
++ if(p)
++ *p = '\0';
++
++ string -= length;
++ for (; *string; string++){
++ if (change){
++ *string = ' ';
++ change = 0;
++ }
++ if ((((unsigned char)*string == ' ') ||
++ ((unsigned char)*string == ',')) &&
++ ((unsigned char)*(string + 1) == ','))
++ change++;
++ }
++ }
++
+diff -rc pine4.63/pine/takeaddr.c pine4.63.I.USE/pine/takeaddr.c
+*** pine4.63/pine/takeaddr.c Mon Mar 7 15:16:41 2005
+--- pine4.63.I.USE/pine/takeaddr.c Thu May 19 19:57:32 2005
+***************
+*** 1782,1791 ****
+--- 1782,1793 ----
+ TA_S *p;
+ int rc, found = 0, wrapped = 0, flags;
+ char *result = NULL, buf[MAX_SEARCH+1], tmp[MAX_SEARCH+20];
++ static char last_pat[MAX_SEARCH+1] = {'\0'};
+ static char last[MAX_SEARCH+1];
+ HelpType help;
+ static ESCKEY_S ekey[] = {
+ {0, 0, "", ""},
++ {ctrl('N'), 9, "^N", "Ins Pat"},
+ {ctrl('Y'), 10, "^Y", "Top"},
+ {ctrl('V'), 11, "^V", "Bottom"},
+ {-1, 0, NULL, NULL}};
+***************
+*** 1806,1822 ****
+ tmp,ekey,help,&flags);
+ if(rc == 3)
+ help = help == NO_HELP ? h_config_whereis : NO_HELP;
+! else if(rc == 0 || rc == 1 || rc == 10 || rc == 11 || !buf[0]){
+ if(rc == 0 && !buf[0] && last[0]){
+ strncpy(buf, last, sizeof(buf)-1);
+ buf[sizeof(buf)-1] = '\0';
+ }
+!
+! break;
+ }
+ }
+
+ if(rc == 0 && buf[0]){
+ p = current;
+ while(p = next_taline(p))
+ if(srchstr((char *)rfc1522_decode((unsigned char *)tmp_20k_buf,
+--- 1808,1828 ----
+ tmp,ekey,help,&flags);
+ if(rc == 3)
+ help = help == NO_HELP ? h_config_whereis : NO_HELP;
+! else if(rc == 0 || rc == 1 || rc == 10 || rc == 11 || rc == 9 || !buf[0]){
+ if(rc == 0 && !buf[0] && last[0]){
+ strncpy(buf, last, sizeof(buf)-1);
+ buf[sizeof(buf)-1] = '\0';
+ }
+! if (rc == 9)
+! insert_pattern_in_string(buf, last_pat, MAX_SEARCH);
+! else
+! break;
+ }
+ }
+
+ if(rc == 0 && buf[0]){
++ strncpy(last_pat, buf, sizeof(last_pat));
++ last_pat[sizeof(last_pat)-1] = '\0';
+ p = current;
+ while(p = next_taline(p))
+ if(srchstr((char *)rfc1522_decode((unsigned char *)tmp_20k_buf,
diff --git a/packages/pine/pine-4.63/pine-ldap3.patch b/packages/pine/pine-4.63/pine-ldap3.patch
new file mode 100644
index 0000000000..a824438fbd
--- /dev/null
+++ b/packages/pine/pine-4.63/pine-ldap3.patch
@@ -0,0 +1,11 @@
+--- pine4.63/pine/bldaddr.c.orig 2005-07-12 15:40:04.000000000 +0200
++++ pine4.63/pine/bldaddr.c 2005-07-12 15:40:14.000000000 +0200
+@@ -6504,7 +6504,7 @@
+ ldap_v3_is_supported(ld)
+ LDAP *ld;
+ {
+- int v3_is_supported_by_server = 0;
++ int v3_is_supported_by_server = 1;
+ #ifdef NO_VERSION3_PROTO_YET
+ /*
+ * When we use version 3 protocol we will be getting back utf8 results.
diff --git a/packages/pine/pine-4.63/transparency.patch b/packages/pine/pine-4.63/transparency.patch
new file mode 100644
index 0000000000..890cf13f6c
--- /dev/null
+++ b/packages/pine/pine-4.63/transparency.patch
@@ -0,0 +1,14 @@
+diff -ru pine4.55-orig/pico/osdep/unix pine4.55/pico/osdep/unix
+--- pine4.55-orig/pico/osdep/unix 2003-04-15 17:20:22.000000000 -0500
++++ pine4.55/pico/osdep/unix 2003-06-23 13:05:19.000000000 -0500
+@@ -998,7 +998,9 @@
+ if(ANSI_COLOR()){
+ char buf[10];
+
+- if(color < 8)
++ if(color == 0)
++ memcpy(buf, "\033[49m", 6);
++ else if(color < 8)
+ sprintf(buf, "\033[4%cm", color + '0');
+ else
+ sprintf(buf, "\033[10%cm", (color-8) + '0');
diff --git a/packages/pine/pine_4.63.bb b/packages/pine/pine_4.63.bb
index b8a11639a6..87cf602c96 100644
--- a/packages/pine/pine_4.63.bb
+++ b/packages/pine/pine_4.63.bb
@@ -1,59 +1,82 @@
-DESCRIPTION = "Pine(R) - a Program for Internet News & Email"
-SECTION = "console/network"
-LICENSE = "Pine"
-DEPENDS = "ncurses"
-RDEPENDS_pine = "pico"
-HOMEPAGE = "http://www.washington.edu/pine/"
-MAINTAINER = "Michael 'Mickey' Lauer <mickey@Vanille.de>"
+DESCRIPTION = "Pine(R) - a Program for Internet News & Email"
+PR = "r1"
+SECTION = "console/network"
+LICENSE = "Pine"
+DEPENDS = "ncurses libldap"
+RDEPENDS_pine = "pico"
+HOMEPAGE = "http://www.washington.edu/pine/"
+MAINTAINER = "Michael 'Mickey' Lauer <mickey_at_Vanille.de>"
-SRC_URI = "ftp://ftp.cac.washington.edu/pine/pine${PV}.tar.bz2"
-S = "${WORKDIR}/pine${PV}"
+SRC_URI = "ftp://ftp.cac.washington.edu/pine/pine.tar.bz2 \
+ file://pine-4.63/pine-4.63-r2-chappa-all.patch;patch=1 \
+ file://pine-4.63/pine-4.62-spooldir-permissions.patch;patch=1 \
+ file://pine-4.63/pine-4.30-ldap.patch;patch=1 \
+ file://pine-4.63/pine-ldap3.patch;patch=1 \
+ file://pine-4.63/pine-4.56-passfile.patch;patch=1 \
+ file://pine-4.63/pine-4.61-largeterminal.patch;patch=1 \
+ file://pine-4.63/pine-4.31-segfix.patch;patch=1 \
+ file://pine-4.63/pine-4.40-lockfile-perm.patch;patch=1 \
+ file://pine-4.63/imap-2000-time.patch;patch=1 \
+ file://pine-4.63/transparency.patch;patch=1 \
+ file://pine-4.63/pine-4.61-subjectlength.patch;patch=1"
-inherit autotools
+S = "${WORKDIR}/pine${PV}"
-#
+inherit autotools
+
+#
# ~lart Pine's build structure...
-#
-PARALLEL_MAKE = ""
-EXTRA_OEMAKE = "-e"
-export MAKE = 'MAKE="make -e" make -e'
-
-CFLAGS += "-I${S}/imap/c-client"
-LDFLAGS += "${S}/imap/c-client/c-client.a -lssl -lcrypt"
-
-export SSLDEFINES = "-DSSL_CERT_DIRECTORY=\\"/etc/ssl/certs\\" -DSSL_KEY_DIRECTORY=\\"/etc/ssl/private\\""
-export SSLCFLAGS = "${CFLAGS} -I${STAGING_INCDIR}/openssl ${SSLDEFINES}"
-export SSLLDFLAGS = "-lssl -lcrypt ${LDFLAGS} -L${STAGING_LIBDIR}/openssl"
-export EXTRALDFLAGS = "${LDFLAGS}"
-
-do_configure() {
- ln -sf ${S}/imap/c-client ${S}/c-client
- cd ${S}/pico/osdep && \
- ${BUILD_CC} -o includer includer.c
- cd ${S}/pine/osdep && \
- ${BUILD_CC} -o includer includer.c
-}
-
-do_compile() {
- unset CFLAGS && unset LDFLAGS
- cd ${S}/imap && oe_runmake slx
-
- for i in pico pine
- do
- cd ${S}/$i && oe_runmake -f makefile.lnx
- done
-}
-
-BINARIES = "imap/mailutil/mailutil imap/mlock/mlock pico/pico pico/pilot pine/pine"
-
-do_install() {
- install -d 0644 ${D}${bindir}
- for binary in ${BINARIES}
- do
- install -m 0755 $binary ${D}${bindir}
- done
-}
-
-PACKAGES = "pico pine"
-FILES_pico = "${bindir}/pico ${bindir}/pilot"
+#
+PARALLEL_MAKE = ""
+EXTRA_OEMAKE = "-e"
+export MAKE = 'MAKE="make -e" make -e'
+
+CFLAGS += "-I${S}/imap/c-client"
+LDFLAGS += "${S}/imap/c-client/c-client.a -lssl -lcrypt"
+
+export SSLDEFINES = "-DSSL_CERT_DIRECTORY=\\"/etc/ssl/certs\\" -DSSL_KEY_DIRECTORY=\\"/etc/ssl/private\\""
+export SSLCFLAGS = "${CFLAGS} -I${STAGING_INCDIR}/openssl ${SSLDEFINES}"
+export SSLLDFLAGS = "-lssl -lcrypt ${LDFLAGS} -L${STAGING_LIBDIR}/openssl"
+export LDAPCFLAGS = "-DENABLE_LDAP"
+export LDAPLIBS = "-lldap -llber"
+export EXTRALDFLAGS = "${LDFLAGS}"
+
+do_configure() {
+ ln -sf ${S}/imap/c-client ${S}/c-client
+ cd ${S}/pico/osdep && \
+ ${BUILD_CC} -o includer includer.c
+ cd ${S}/pine/osdep && \
+ ${BUILD_CC} -o includer includer.c
+ mkdir ${S}/ldap
+ cd ${S}/ldap &&
+ ln -sf ${STAGING_INCDIR} include &&
+ ln -sf ${STAGING_LIBDIR} libraries
+ cd ${S}
+ sed -e "s:/usr/local/lib/pine.conf:/etc/pine.conf:" \
+ -i "${S}/pine/osdep/os-lnx.h" || exit 1
+ ls -l ${S}/contrib/ldap-setup
+}
+
+do_compile() {
+ unset CFLAGS && unset LDFLAGS
+ cd ${S}/imap && oe_runmake slx
+
+ for i in pico pine
+ do
+ cd ${S}/$i && oe_runmake -f makefile.lnx
+ done
+}
+
+BINARIES = "imap/mailutil/mailutil imap/mlock/mlock pico/pico pico/pilot pine/pine"
+
+do_install() {
+ install -d 0644 ${D}${bindir}
+ for binary in ${BINARIES}
+ do
+ install -m 0755 $binary ${D}${bindir}
+ done
+}
+
+PACKAGES = "pico pine"
+FILES_pico = "${bindir}/pico ${bindir}/pilot"
diff --git a/packages/tetex/tetex-native_3.0.bb b/packages/tetex/tetex-native_3.0.bb
index 86f634c892..b4b68bed5c 100644
--- a/packages/tetex/tetex-native_3.0.bb
+++ b/packages/tetex/tetex-native_3.0.bb
@@ -1,18 +1,23 @@
include tetex_${PV}.bb
inherit native
-
DEPENDS = ""
+PR = "r1"
do_configure() {
oe_runconf
}
-BINARIES = "texk/web2c/tangle utils/texinfo/info/makedoc utils/texinfo/makeinfo/makeinfo"
+BINARIES = "texk/web2c/tangle \
+ texk/web2c/ctangle \
+ texk/web2c/otangle \
+ texk/web2c/tie \
+ utils/texinfo/info/makedoc \
+ utils/texinfo/makeinfo/makeinfo"
do_stage() {
for binary in ${BINARIES}
do
- install -m 0755 texk/web2c/tangle ${STAGING_BINDIR}
+ install -m 0755 $binary ${STAGING_BINDIR}
done
}