diff -Nur Makefile.am Makefile.am --- Makefile.am Thu Feb 12 08:48:07 2004 +++ Makefile.am Mon Aug 2 23:51:15 2004 @@ -27,7 +27,7 @@ score.c send.c sendlib.c signal.c sort.c \ status.c system.c thread.c charset.c history.c lib.c \ muttlib.c editmsg.c utf8.c mbyte.c wcwidth.c \ - url.c ascii.c + url.c ascii.c sidebar.c mutt_LDADD = @MUTT_LIB_OBJECTS@ @LIBOBJS@ $(LIBIMAP) $(MUTTLIBS) \ $(INTLLIBS) $(LIBICONV) @@ -67,7 +67,7 @@ EXTRA_mutt_SOURCES = account.c md5c.c mutt_sasl.c mutt_socket.c mutt_ssl.c \ mutt_tunnel.c pop.c pop_auth.c pop_lib.c pgp.c pgpinvoke.c pgpkey.c \ pgplib.c sha1.c pgpmicalg.c gnupgparse.c resize.c dotlock.c remailer.c \ - browser.h mbyte.h remailer.h url.h mutt_ssl_nss.c pgppacket.c + browser.h mbyte.h remailer.h url.h mutt_ssl_nss.c pgppacket.c sidebar.h EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP TODO configure acconfig.h account.h \ attach.h buffy.h charset.h copy.h dotlock.h functions.h gen_defs \ diff -Nur OPS OPS --- OPS Thu Apr 25 13:26:56 2002 +++ OPS Mon Aug 2 23:51:17 2004 @@ -168,3 +168,8 @@ OP_MAIN_SHOW_LIMIT "show currently active limit pattern" OP_MAIN_COLLAPSE_THREAD "collapse/uncollapse current thread" OP_MAIN_COLLAPSE_ALL "collapse/uncollapse all threads" +OP_SCROLL_MBOX_UP "scroll the mailbox pane up 1 page" +OP_SCROLL_MBOX_DOWN "scroll the mailbox pane down 1 page" +OP_NEXT_MBOX "go down to next mailbox" +OP_PREV_MBOX "go to previous mailbox" +OP_OPEN_MBOX "open hilighted mailbox" diff -Nur PATCHES PATCHES --- PATCHES Mon Nov 26 19:16:52 2001 +++ PATCHES Mon Aug 2 23:51:20 2004 @@ -0,0 +1 @@ +patch-1.5.6.jrh.sidebar.8 diff -Nur buffy.c buffy.c --- buffy.c Mon Mar 25 11:30:23 2002 +++ buffy.c Mon Aug 2 23:51:15 2004 @@ -233,7 +233,7 @@ char path[_POSIX_PATH_MAX]; struct stat contex_sb; time_t t; - + CONTEXT *ctx; #ifdef USE_IMAP /* update postponed count as well, on force */ if (force) @@ -266,6 +266,8 @@ for (tmp = Incoming; tmp; tmp = tmp->next) { + if ( tmp->new == 1 ) + tmp->has_new = 1; tmp->new = 0; #ifdef USE_IMAP @@ -320,10 +322,27 @@ case M_MMDF: case M_KENDRA: - if (STAT_CHECK) + { + if (STAT_CHECK || tmp->msgcount == 0) { + BUFFY b = *tmp; + int msgcount = 0; + int msg_unread = 0; BuffyCount++; - tmp->new = 1; + /* parse the mailbox, to see how much mail there is */ + ctx = mx_open_mailbox( tmp->path, M_READONLY | M_QUIET | M_NOSORT, + NULL); + if(ctx) + { + msgcount = ctx->msgcount; + msg_unread = ctx->unread; + mx_close_mailbox(ctx, 0); + } + *tmp = b; + tmp->msgcount = msgcount; + tmp->msg_unread = msg_unread; + if(STAT_CHECK) + tmp->has_new = tmp->new = 1; } #ifdef BUFFY_SIZE else @@ -335,7 +354,7 @@ if (tmp->newly_created && (sb.st_ctime != sb.st_mtime || sb.st_ctime != sb.st_atime)) tmp->newly_created = 0; - + } break; case M_MAILDIR: @@ -346,6 +365,8 @@ tmp->magic = 0; break; } + tmp->msgcount = 0; + tmp->msg_unread = 0; while ((de = readdir (dirp)) != NULL) { char *p; @@ -354,22 +375,61 @@ { /* one new and undeleted message is enough */ BuffyCount++; - tmp->new = 1; - break; + tmp->has_new = tmp->new = 1; + tmp->msgcount++; + tmp->msg_unread++; + } + } + closedir (dirp); + snprintf (path, sizeof (path), "%s/cur", tmp->path); + if ((dirp = opendir (path)) == NULL) + { + tmp->magic = 0; + break; + } + while ((de = readdir (dirp)) != NULL) + { + char *p; + if (*de->d_name != '.' && + (!(p = strstr (de->d_name, ":2,")) || !strchr (p + 3, 'T'))) + { + /* one new and undeleted message is enough */ + BuffyCount++; + tmp->has_new = tmp->new = 1; + tmp->msgcount++; } } closedir (dirp); break; case M_MH: - if ((tmp->new = mh_buffy (tmp->path)) > 0) - BuffyCount++; + { + DIR *dp; + struct dirent *de; + if ((tmp->new = mh_buffy (tmp->path)) > 0) + BuffyCount++; + + if ((dp = opendir (path)) == NULL) + break; + tmp->msgcount = 0; + while ((de = readdir (dp))) + { + if (mh_valid_message (de->d_name)) + { + tmp->msgcount++; + tmp->has_new = tmp->new = 1; + } + } + closedir (dp); + } break; #ifdef USE_IMAP case M_IMAP: - if ((tmp->new = imap_mailbox_check (tmp->path, 1)) > 0) + tmp->msgcount = imap_mailbox_check(tmp->path, 0); + if ((tmp->new = imap_mailbox_check (tmp->path, 1)) > 0) { BuffyCount++; + } else tmp->new = 0; diff -Nur buffy.h buffy.h --- buffy.h Fri Mar 3 10:10:06 2000 +++ buffy.h Mon Aug 2 23:51:17 2004 @@ -23,7 +23,11 @@ long size; #endif /* BUFFY_SIZE */ struct buffy_t *next; + struct buffy_t *prev; short new; /* mailbox has new mail */ + short has_new; /* set it new if new and not read */ + int msgcount; /* total number of messages */ + int msg_unread; /* number of unread messages */ short notified; /* user has been notified */ short magic; /* mailbox type */ short newly_created; /* mbox or mmdf just popped into existence */ diff -Nur color.c color.c --- color.c Thu Apr 26 13:36:33 2001 +++ color.c Mon Aug 2 23:51:15 2004 @@ -89,6 +89,7 @@ { "bold", MT_COLOR_BOLD }, { "underline", MT_COLOR_UNDERLINE }, { "index", MT_COLOR_INDEX }, + { "sidebarnew", MT_COLOR_NEW }, { NULL, 0 } }; diff -Nur compose.c compose.c --- compose.c Wed Jul 24 08:41:29 2002 +++ compose.c Mon Aug 2 23:51:15 2004 @@ -69,7 +69,7 @@ #define HDR_XOFFSET 10 #define TITLE_FMT "%10s" /* Used for Prompts, which are ASCII */ -#define W (COLS - HDR_XOFFSET) +#define W (COLS - HDR_XOFFSET - SidebarWidth) static char *Prompts[] = { @@ -108,7 +108,7 @@ static void redraw_pgp_lines (int pgp) { - mvaddstr (HDR_PGP, 0, " PGP: "); + mvaddstr (HDR_PGP, SidebarWidth, " PGP: "); if ((pgp & (PGPENCRYPT | PGPSIGN)) == (PGPENCRYPT | PGPSIGN)) addstr (_("Sign, Encrypt")); else if (pgp & PGPENCRYPT) @@ -119,7 +119,7 @@ addstr (_("Clear")); clrtoeol (); - move (HDR_PGPSIGINFO, 0); + move (HDR_PGPSIGINFO, SidebarWidth); clrtoeol (); if (pgp & PGPSIGN) printw ("%s%s", _(" sign as: "), PgpSignAs ? PgpSignAs : _("")); @@ -184,7 +184,7 @@ int c; char *t; - mvaddstr (HDR_MIX, 0, " Mix: "); + mvaddstr (HDR_MIX, SidebarWidth, " Mix: "); if (!chain) { @@ -199,7 +199,7 @@ if (t && t[0] == '0' && t[1] == '\0') t = ""; - if (c + mutt_strlen (t) + 2 >= COLS) + if (c + mutt_strlen (t) + 2 >= COLS - SidebarWidth) break; addstr (NONULL(t)); @@ -251,7 +251,7 @@ buf[0] = 0; rfc822_write_address (buf, sizeof (buf), addr); - mvprintw (line, 0, TITLE_FMT, Prompts[line - 1]); + mvprintw (line, SidebarWidth, TITLE_FMT, Prompts[line - 1]); mutt_paddstr (W, buf); } @@ -261,10 +261,10 @@ draw_envelope_addr (HDR_TO, msg->env->to); draw_envelope_addr (HDR_CC, msg->env->cc); draw_envelope_addr (HDR_BCC, msg->env->bcc); - mvprintw (HDR_SUBJECT, 0, TITLE_FMT, Prompts[HDR_SUBJECT - 1]); + mvprintw (HDR_SUBJECT, SidebarWidth, TITLE_FMT, Prompts[HDR_SUBJECT - 1]); mutt_paddstr (W, NONULL (msg->env->subject)); draw_envelope_addr (HDR_REPLYTO, msg->env->reply_to); - mvprintw (HDR_FCC, 0, TITLE_FMT, Prompts[HDR_FCC - 1]); + mvprintw (HDR_FCC, SidebarWidth, TITLE_FMT, Prompts[HDR_FCC - 1]); mutt_paddstr (W, fcc); @@ -278,7 +278,7 @@ #endif SETCOLOR (MT_COLOR_STATUS); - mvaddstr (HDR_ATTACH - 1, 0, _("-- Attachments")); + mvaddstr (HDR_ATTACH - 1, SidebarWidth, _("-- Attachments")); BKGDSET (MT_COLOR_STATUS); clrtoeol (); @@ -307,7 +307,7 @@ /* redraw the expanded list so the user can see the result */ buf[0] = 0; rfc822_write_address (buf, sizeof (buf), *addr); - move (line, HDR_XOFFSET); + move (line, HDR_XOFFSET+SidebarWidth); mutt_paddstr (W, buf); return 0; @@ -548,7 +548,7 @@ if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) == 0) { mutt_str_replace (&msg->env->subject, buf); - move (HDR_SUBJECT, HDR_XOFFSET); + move (HDR_SUBJECT, HDR_XOFFSET + SidebarWidth); clrtoeol (); if (msg->env->subject) mutt_paddstr (W, msg->env->subject); @@ -563,7 +563,7 @@ { strfcpy (fcc, buf, _POSIX_PATH_MAX); mutt_pretty_mailbox (fcc); - move (HDR_FCC, HDR_XOFFSET); + move (HDR_FCC, HDR_XOFFSET + SidebarWidth); mutt_paddstr (W, fcc); fccSet = 1; } diff -Nur curs_main.c curs_main.c --- curs_main.c Wed Jan 16 20:44:25 2002 +++ curs_main.c Mon Aug 2 23:51:16 2004 @@ -525,6 +525,7 @@ if (menu->redraw & REDRAW_FULL) { + draw_sidebar(menu->menu); menu_redraw_full (menu); mutt_show_error (); } @@ -548,7 +549,9 @@ if (menu->redraw & REDRAW_STATUS) { + DrawFullLine = 1; menu_status_line (buf, sizeof (buf), menu, NONULL (Status)); + DrawFullLine = 0; CLEARLINE (option (OPTSTATUSONTOP) ? 0 : LINES-2); SETCOLOR (MT_COLOR_STATUS); mutt_paddstr (COLS, buf); @@ -974,6 +977,7 @@ menu->redraw = REDRAW_FULL; break; + case OP_OPEN_MBOX: case OP_MAIN_CHANGE_FOLDER: if (attach_msg) @@ -991,7 +995,9 @@ buf[0] = '\0'; mutt_buffy (buf, sizeof (buf)); - if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1) + if ( op == OP_OPEN_MBOX ) + strncpy( buf, CurBuffy->path, sizeof(buf) ); + else if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1) break; if (!buf[0]) { @@ -1961,6 +1967,12 @@ menu->redraw = REDRAW_FULL; break; + case OP_SCROLL_MBOX_UP: + case OP_SCROLL_MBOX_DOWN: + case OP_NEXT_MBOX: + case OP_PREV_MBOX: + scroll_sidebar(op,menu); + break; default: if (menu->menu == MENU_MAIN) km_error_key (MENU_MAIN); diff -Nur doc/instdoc.sh doc/instdoc.sh --- doc/instdoc.sh Thu Jan 1 00:00:00 1970 +++ doc/instdoc.sh Mon Aug 2 23:51:20 2004 @@ -0,0 +1,24 @@ +#!/bin/sh -- + +prefix=/usr/local +exec_prefix=${prefix} +bindir=${exec_prefix}/bin +libdir=${exec_prefix}/lib +mandir=${prefix}/man +srcdir=. +docdir=/usr/local/doc/mutt +includedir=${prefix}/include +top_srcdir=.. +top_builddir=.. + +SOURCE="$1" +TARGET="$2" + + +rm -f "$TARGET" + +sed -e "s;/usr/local/bin/;$bindir/;g" \ + -e "s;/usr/local/doc/mutt/;$docdir/;g" \ + "$SOURCE" > $TARGET + +chmod 644 "$TARGET" diff -Nur doc/muttrc.man doc/muttrc.man --- doc/muttrc.man Wed Feb 11 13:57:35 2004 +++ doc/muttrc.man Mon Aug 2 23:51:19 2004 @@ -1783,7 +1783,7 @@ .B ispell .nf Type: path -Default: \(lq/usr/bin/ispell\(rq +Default: \(lqispell\(rq .fi .IP How to invoke ispell (GNU's spell-checking software). @@ -1911,6 +1911,16 @@ .IP This specifies the folder into which read mail in your \(lq$spoolfile\(rq folder will be appended. + + +.TP +.B mbox_pane_width +.nf +Type: number +Default: 0 +.fi +.IP +The width of the mailbox list pane (left sidebar like in GUIs). .TP diff -Nur flags.c flags.c --- flags.c Tue Jan 15 21:18:11 2002 +++ flags.c Mon Aug 2 23:51:16 2004 @@ -218,6 +218,7 @@ */ if (h->searched && (changed != h->changed || deleted != ctx->deleted || tagged != ctx->tagged)) h->searched = 0; + draw_sidebar(0); } void mutt_tag_set_flag (int flag, int bf) diff -Nur flea flea --- flea Thu Jan 1 00:00:00 1970 +++ flea Mon Aug 2 23:51:20 2004 @@ -0,0 +1,311 @@ +#!/bin/sh + +# +# File a bug against the Mutt mail user agent. +# + +# +# $Id: muttbug.sh.in,v 2.18 2001/10/10 09:56:51 roessler Exp $ +# + +# +# Copyright (c) 2000 Thomas Roessler +# +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +# + +SUBMIT="submit@bugs.guug.de" +DEBIAN_SUBMIT="submit@bugs.debian.org" + +prefix=/usr/local + +DEBUGGER=no +SENDMAIL=/usr/sbin/sendmail +sysconfdir=${prefix}/etc +pkgdatadir=@pkgdatadir@ + +include_file () +{ + echo + echo "--- Begin $1" + sed -e 's/^-/- -/' $1 | egrep -v '^[ ]*(#|$)' + echo "--- End $1" + echo +} + +debug_gdb () +{ + cat << EOF > $SCRATCH/gdb.rc +bt +list +quit +EOF + $DEBUGGER -n -x $SCRATCH/gdb.rc -c $CORE mutt +} + +debug_dbx () +{ + cat << EOF > $SCRATCH/dbx.rc +where +list +quit +EOF + $DEBUGGER -s $SCRATCH/dbx.rc mutt $CORE +} + +debug_sdb () +{ + cat << EOF > $SCRATCH/sdb.rc +t +w +q +EOF + $DEBUGGER mutt $CORE < $SCRATCH/sdb.rc +} + +case `echo -n` in +"") n=-n; c= ;; + *) n=; c='\c' ;; +esac + + +exec > /dev/tty +exec < /dev/tty + +SCRATCH=${TMPDIR-/tmp}/`basename $0`.`hostname`.$$ + +mkdir ${SCRATCH} || \ +{ + echo "`basename $0`: Can't create temporary directory." >& 2 ; + exit 1 ; +} + +trap "rm -r -f ${SCRATCH} ; trap '' 0 ; exit" 0 1 2 + +TEMPLATE=${SCRATCH}/template.txt + +echo "Please enter a one-line description of the problem you experience:" +echo $n "> $c" +read SUBJECT + +cat < $c" + read _CORE + test "$_CORE" && CORE="$_CORE" +fi + +echo $n "Do you want to include your personal mutt configuration files? [Y|n] $c" +read personal +case "$personal" in +[nN]*) personal=no ;; + *) personal=yes ;; +esac + +echo $n "Do you want to include your system's global mutt configuration file? [Y|n] $c" +read global +case "$global" in +[nN]*) global=no ;; + *) global=yes ;; +esac + +if test -f /etc/debian_version ; then + DEBIAN=yes + echo $n "Checking whether mutt has been installed as a package... $c" + DEBIANVERSION="`dpkg -l mutt | grep '^[ih]' | awk '{print $3}'`" 2> /dev/null + if test "$DEBIANVERSION" ; then + DPKG=yes + else + DPKG=no + unset DEBIANVERSION + fi + echo "$DPKG" + echo $n "File this bug with Debian? [Y|n] $c" + read DPKG + case "$DPKG" in + [nN]) DPKG=no ;; + *) DPKG=yes ;; + esac +else + DEBIAN=no + DPKG=no +fi + +MUTTVERSION="`mutt -v | head -1 | awk '{print $2}'`" +test "$DPKG" = "yes" && SUBMIT="$SUBMIT, $DEBIAN_SUBMIT" + +exec > ${TEMPLATE} + +test "$EMAIL" && echo "From: $EMAIL" +test "$REPLYTO" && echo "Reply-To: $REPLYTO" +test "$ORGANIZATION" && echo "Organization: $ORGANIZATION" + +echo "Subject: mutt-$MUTTVERSION: $SUBJECT" +echo "To: $SUBMIT" +echo "Bcc: ${EMAIL-$LOGNAME}" +echo +echo "Package: mutt" +echo "Version: ${DEBIANVERSION-$MUTTVERSION}" +echo "Severity: $severity" +echo +echo "-- Please type your report below this line" +echo +echo +echo + +if test "$DEBIAN" = "yes" ; then + echo "Obtaining Debian-specific information..." > /dev/tty + bug -p -s dummy mutt | \ + sed -n -e "/^-- System Information/,/^---/p" | \ + grep -v '^---' +fi + +echo +echo "-- Build environment information" +echo +echo "(Note: This is the build environment installed on the system" +echo "muttbug is run on. Information may or may not match the environment" +echo "used to build mutt.)" +echo +echo "- gcc version information" +echo "gcc" +gcc -v 2>&1 +echo +echo "- CFLAGS" +echo -Wall -pedantic -g -O2 + + +echo +echo "-- Mutt Version Information" +echo +mutt -v + +if test "$CORE" && test -f "$CORE" ; then + echo + echo "-- Core Dump Analysis Output" + echo + + case "$DEBUGGER" in + *sdb) debug_sdb $CORE ;; + *dbx) debug_dbx $CORE ;; + *gdb) debug_gdb $CORE ;; + esac + + echo +fi + +if test "$personal" = "yes" ; then + CANDIDATES=".muttrc-${MUTTVERSION} .muttrc .mutt/muttrc-${MUTTVERSION} .mutt/muttrc" + MATCHED="none" + for f in $CANDIDATES; do + if test -f "${HOME}/$f" ; then + MATCHED="${HOME}/$f" + break + fi + done + + if test "$MATCHED" = "none" ; then + echo "Warning: Can't find your personal .muttrc." >&2 + else + include_file $MATCHED + fi +fi + + +if test "$global" = "yes" ; then + CANDIDATES="Muttrc-${MUTTVERSION} Muttrc" + DIRECTORIES="$sysconfdir $pkgdatadir" + MATCHED="none" + for d in $DIRECTORIES ; do + for f in $CANDIDATES; do + if test -f $d/$f ; then + MATCHED="$d/$f" + break + fi + done + test "$MATCHED" = "none" || break + done + + if test "$MATCHED" = "none" ; then + echo "Warning: Can't find global Muttrc." >&2 + else + include_file $MATCHED + fi +fi + +exec > /dev/tty + +cp $TEMPLATE $SCRATCH/mutt-bug.txt + +input="e" +while : ; do + if test "$input" = "e" ; then + ${VISUAL-${EDITOR-vi}} $SCRATCH/mutt-bug.txt + if cmp $SCRATCH/mutt-bug.txt ${TEMPLATE} > /dev/null ; then + echo "Warning: Bug report was not modified!" + fi + fi + + echo $n "Submit, Edit, View, Quit? [S|e|v|q] $c" + read _input + input="`echo $_input | tr EVSQ evsq`" + case $input in + e*) ;; + v*) ${PAGER-more} $SCRATCH/mutt-bug.txt ;; + s*|"") $SENDMAIL -t < $SCRATCH/mutt-bug.txt ; exit ;; + q*) exit + esac +done + diff -Nur functions.h functions.h --- functions.h Tue Sep 11 11:20:34 2001 +++ functions.h Mon Aug 2 23:51:17 2004 @@ -146,6 +146,11 @@ + { "scroll-mbox-up", OP_SCROLL_MBOX_UP, NULL }, + { "scroll-mbox-down", OP_SCROLL_MBOX_DOWN, NULL }, + { "next-mbox", OP_NEXT_MBOX, NULL }, + { "previous-mbox", OP_PREV_MBOX, NULL }, + { "open-mbox", OP_OPEN_MBOX, NULL }, { NULL, 0, NULL } }; @@ -239,6 +244,11 @@ + { "scroll-mbox-up", OP_SCROLL_MBOX_UP, NULL }, + { "scroll-mbox-down", OP_SCROLL_MBOX_DOWN, NULL }, + { "next-mbox", OP_NEXT_MBOX, NULL }, + { "previous-mbox", OP_PREV_MBOX, NULL }, + { "open-mbox", OP_OPEN_MBOX, NULL }, { NULL, 0, NULL } }; diff -Nur globals.h globals.h --- globals.h Thu Jan 3 20:57:19 2002 +++ globals.h Mon Aug 2 23:51:17 2004 @@ -157,6 +157,9 @@ WHERE short ScoreThresholdRead; WHERE short ScoreThresholdFlag; +WHERE struct buffy_t *CurBuffy INITVAL(0); +WHERE short DrawFullLine INITVAL(0); +WHERE short SidebarWidth; #ifdef USE_IMAP WHERE short ImapKeepalive; #endif diff -Nur init.h init.h --- init.h Wed Jul 24 08:41:29 2002 +++ init.h Mon Aug 2 23:51:17 2004 @@ -986,6 +986,11 @@ ** This specifies the folder into which read mail in your ``$$spoolfile'' ** folder will be appended. */ + { "mbox_pane_width", DT_NUM, R_BOTH, UL &SidebarWidth, 0 }, + /* + ** .pp + ** The width of the mailbox list pane (left sidebar like in GUIs). + */ { "mbox_type", DT_MAGIC,R_NONE, UL &DefaultMagic, M_MBOX }, /* ** .pp diff -Nur menu.c menu.c --- menu.c Wed Feb 11 10:07:17 2004 +++ menu.c Mon Aug 2 23:51:16 2004 @@ -151,7 +151,7 @@ void menu_pad_string (char *s, size_t n) { int shift = option (OPTARROWCURSOR) ? 3 : 0; - int cols = COLS - shift; + int cols = COLS - shift - SidebarWidth; mutt_format_string (s, n, cols, cols, 0, ' ', s, strlen (s), 1); s[n - 1] = 0; @@ -201,6 +201,7 @@ char buf[STRING]; int i; + draw_sidebar(1); for (i = menu->top; i < menu->top + menu->pagelen; i++) { if (i < menu->max) @@ -211,7 +212,7 @@ if (option (OPTARROWCURSOR)) { attrset (menu->color (i)); - CLEARLINE (i - menu->top + menu->offset); + CLEARLINE_WIN (i - menu->top + menu->offset); if (i == menu->current) { @@ -221,7 +222,7 @@ addch (' '); } else - move (i - menu->top + menu->offset, 3); + move (i - menu->top + menu->offset, SidebarWidth + 3); print_enriched_string (menu->color(i), (unsigned char *) buf, 1); SETCOLOR (MT_COLOR_NORMAL); @@ -236,14 +237,14 @@ else attrset (menu->color (i)); - CLEARLINE (i - menu->top + menu->offset); + CLEARLINE_WIN (i - menu->top + menu->offset); print_enriched_string (menu->color(i), (unsigned char *) buf, i != menu->current); SETCOLOR (MT_COLOR_NORMAL); BKGDSET (MT_COLOR_NORMAL); } } else - CLEARLINE (i - menu->top + menu->offset); + CLEARLINE_WIN (i - menu->top + menu->offset); } menu->redraw = 0; } @@ -258,7 +259,7 @@ return; } - move (menu->oldcurrent + menu->offset - menu->top, 0); + move (menu->oldcurrent + menu->offset - menu->top, SidebarWidth); SETCOLOR (MT_COLOR_NORMAL); BKGDSET (MT_COLOR_NORMAL); @@ -273,13 +274,13 @@ clrtoeol (); menu_make_entry (buf, sizeof (buf), menu, menu->oldcurrent); menu_pad_string (buf, sizeof (buf)); - move (menu->oldcurrent + menu->offset - menu->top, 3); + move (menu->oldcurrent + menu->offset - menu->top, SidebarWidth+3); print_enriched_string (menu->color(menu->oldcurrent), (unsigned char *) buf, 1); SETCOLOR (MT_COLOR_NORMAL); } /* now draw it in the new location */ - move (menu->current + menu->offset - menu->top, 0); + move (menu->current + menu->offset - menu->top, SidebarWidth); SETCOLOR (MT_COLOR_INDICATOR); addstr ("->"); SETCOLOR (MT_COLOR_NORMAL); @@ -298,7 +299,7 @@ menu_pad_string (buf, sizeof (buf)); SETCOLOR (MT_COLOR_INDICATOR); BKGDSET (MT_COLOR_INDICATOR); - CLEARLINE (menu->current - menu->top + menu->offset); + CLEARLINE_WIN (menu->current - menu->top + menu->offset); print_enriched_string (menu->color(menu->current), (unsigned char *) buf, 0); SETCOLOR (MT_COLOR_NORMAL); BKGDSET (MT_COLOR_NORMAL); @@ -310,7 +311,7 @@ { char buf[STRING]; - move (menu->current + menu->offset - menu->top, 0); + move (menu->current + menu->offset - menu->top, SidebarWidth); menu_make_entry (buf, sizeof (buf), menu, menu->current); menu_pad_string (buf, sizeof (buf)); diff -Nur mutt_curses.h mutt_curses.h --- mutt_curses.h Thu May 31 15:35:10 2001 +++ mutt_curses.h Mon Aug 2 23:51:17 2004 @@ -58,6 +58,7 @@ #undef lines #endif /* lines */ +#define CLEARLINE_WIN(x) move(x,SidebarWidth), clrtoeol() #define CLEARLINE(x) move(x,0), clrtoeol() #define CENTERLINE(x,y) move(y, (COLS-strlen(x))/2), addstr(x) #define BEEP() do { if (option (OPTBEEP)) beep(); } while (0) @@ -119,6 +120,7 @@ MT_COLOR_BOLD, MT_COLOR_UNDERLINE, MT_COLOR_INDEX, + MT_COLOR_NEW, MT_COLOR_MAX }; diff -Nur mutt_dotlock.c mutt_dotlock.c --- mutt_dotlock.c Wed Feb 11 13:58:27 2004 +++ mutt_dotlock.c Thu Jan 1 00:00:00 1970 @@ -1,755 +0,0 @@ -/* - * Copyright (C) 1996-2000 Michael R. Elkins - * Copyright (C) 1998-2000 Thomas Roessler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - */ - -/* - * This module either be compiled into Mutt, or it can be - * built as a separate program. For building it - * separately, define the DL_STANDALONE preprocessor - * macro. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef _POSIX_PATH_MAX -#include -#endif - -#include "dotlock.h" -#include "config.h" - -#ifdef HAVE_GETOPT_H -#include -#endif - -#ifdef DL_STANDALONE -# include "reldate.h" -#endif - -#define MAXLINKS 1024 /* maximum link depth */ - -#ifdef DL_STANDALONE - -# define LONG_STRING 1024 -# define MAXLOCKATTEMPT 5 - -# define strfcpy(A,B,C) strncpy (A,B,C), *(A+(C)-1)=0 - -# ifdef USE_SETGID - -# ifdef HAVE_SETEGID -# define SETEGID setegid -# else -# define SETEGID setgid -# endif -# ifndef S_ISLNK -# define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK ? 1 : 0) -# endif - -# endif - -# ifndef HAVE_SNPRINTF -extern int snprintf (char *, size_t, const char *, ...); -# endif - -#else /* DL_STANDALONE */ - -# ifdef USE_SETGID -# error Do not try to compile dotlock as a mutt module when requiring egid switching! -# endif - -# include "mutt.h" -# include "mx.h" - -#endif /* DL_STANDALONE */ - -static int DotlockFlags; -static int Retry = MAXLOCKATTEMPT; - -#ifdef DL_STANDALONE -static char *Hostname; -#endif - -#ifdef USE_SETGID -static gid_t UserGid; -static gid_t MailGid; -#endif - -static int dotlock_deference_symlink (char *, size_t, const char *); -static int dotlock_prepare (char *, size_t, const char *, int fd); -static int dotlock_check_stats (struct stat *, struct stat *); -static int dotlock_dispatch (const char *, int fd); - -#ifdef DL_STANDALONE -static int dotlock_init_privs (void); -static void usage (const char *); -#endif - -static void dotlock_expand_link (char *, const char *, const char *); -static void BEGIN_PRIVILEGED (void); -static void END_PRIVILEGED (void); - -/* These functions work on the current directory. - * Invoke dotlock_prepare () before and check their - * return value. - */ - -static int dotlock_try (void); -static int dotlock_unlock (const char *); -static int dotlock_unlink (const char *); -static int dotlock_lock (const char *); - - -#ifdef DL_STANDALONE - -#define check_flags(a) if (a & DL_FL_ACTIONS) usage (argv[0]) - -int main (int argc, char **argv) -{ - int i; - char *p; - struct utsname utsname; - - /* first, drop privileges */ - - if (dotlock_init_privs () == -1) - return DL_EX_ERROR; - - - /* determine the system's host name */ - - uname (&utsname); - if (!(Hostname = strdup (utsname.nodename))) /* __MEM_CHECKED__ */ - return DL_EX_ERROR; - if ((p = strchr (Hostname, '.'))) - *p = '\0'; - - - /* parse the command line options. */ - DotlockFlags = 0; - - while ((i = getopt (argc, argv, "dtfupr:")) != EOF) - { - switch (i) - { - /* actions, mutually exclusive */ - case 't': check_flags (DotlockFlags); DotlockFlags |= DL_FL_TRY; break; - case 'd': check_flags (DotlockFlags); DotlockFlags |= DL_FL_UNLINK; break; - case 'u': check_flags (DotlockFlags); DotlockFlags |= DL_FL_UNLOCK; break; - - /* other flags */ - case 'f': DotlockFlags |= DL_FL_FORCE; break; - case 'p': DotlockFlags |= DL_FL_USEPRIV; break; - case 'r': DotlockFlags |= DL_FL_RETRY; Retry = atoi (optarg); break; - - default: usage (argv[0]); - } - } - - if (optind == argc || Retry < 0) - usage (argv[0]); - - return dotlock_dispatch (argv[optind], -1); -} - - -/* - * Determine our effective group ID, and drop - * privileges. - * - * Return value: - * - * 0 - everything went fine - * -1 - we couldn't drop privileges. - * - */ - - -static int -dotlock_init_privs (void) -{ - -# ifdef USE_SETGID - - UserGid = getgid (); - MailGid = getegid (); - - if (SETEGID (UserGid) != 0) - return -1; - -# endif - - return 0; -} - - -#else /* DL_STANDALONE */ - -/* - * This function is intended to be invoked from within - * mutt instead of mx.c's invoke_dotlock (). - */ - -int dotlock_invoke (const char *path, int fd, int flags, int retry) -{ - int currdir; - int r; - - DotlockFlags = flags; - - if ((currdir = open (".", O_RDONLY)) == -1) - return DL_EX_ERROR; - - if (!(DotlockFlags & DL_FL_RETRY) || retry) - Retry = MAXLOCKATTEMPT; - else - Retry = 0; - - r = dotlock_dispatch (path, fd); - - fchdir (currdir); - close (currdir); - - return r; -} - -#endif /* DL_STANDALONE */ - - -static int dotlock_dispatch (const char *f, int fd) -{ - char realpath[_POSIX_PATH_MAX]; - - /* If dotlock_prepare () succeeds [return value == 0], - * realpath contains the basename of f, and we have - * successfully changed our working directory to - * `dirname $f`. Additionally, f has been opened for - * reading to verify that the user has at least read - * permissions on that file. - * - * For a more detailed explanation of all this, see the - * lengthy comment below. - */ - - if (dotlock_prepare (realpath, sizeof (realpath), f, fd) != 0) - return DL_EX_ERROR; - - /* Actually perform the locking operation. */ - - if (DotlockFlags & DL_FL_TRY) - return dotlock_try (); - else if (DotlockFlags & DL_FL_UNLOCK) - return dotlock_unlock (realpath); - else if (DotlockFlags & DL_FL_UNLINK) - return dotlock_unlink (realpath); - else /* lock */ - return dotlock_lock (realpath); -} - - -/* - * Get privileges - * - * This function re-acquires the privileges we may have - * if the user told us to do so by giving the "-p" - * command line option. - * - * BEGIN_PRIVILEGES () won't return if an error occurs. - * - */ - -static void -BEGIN_PRIVILEGED (void) -{ -#ifdef USE_SETGID - if (DotlockFlags & DL_FL_USEPRIV) - { - if (SETEGID (MailGid) != 0) - { - /* perror ("setegid"); */ - exit (DL_EX_ERROR); - } - } -#endif -} - -/* - * Drop privileges - * - * This function drops the group privileges we may have. - * - * END_PRIVILEGED () won't return if an error occurs. - * - */ - -static void -END_PRIVILEGED (void) -{ -#ifdef USE_SETGID - if (DotlockFlags & DL_FL_USEPRIV) - { - if (SETEGID (UserGid) != 0) - { - /* perror ("setegid"); */ - exit (DL_EX_ERROR); - } - } -#endif -} - -#ifdef DL_STANDALONE - -/* - * Usage information. - * - * This function doesn't return. - * - */ - -static void -usage (const char *av0) -{ - fprintf (stderr, "dotlock [Mutt %s (%s)]\n", VERSION, ReleaseDate); - fprintf (stderr, "usage: %s [-t|-f|-u|-d] [-p] [-r ] file\n", - av0); - - fputs ("\noptions:" - "\n -t\t\ttry" - "\n -f\t\tforce" - "\n -u\t\tunlock" - "\n -d\t\tunlink" - "\n -p\t\tprivileged" -#ifndef USE_SETGID - " (ignored)" -#endif - "\n -r \tRetry locking" - "\n", stderr); - - exit (DL_EX_ERROR); -} - -#endif - -/* - * Access checking: Let's avoid to lock other users' mail - * spool files if we aren't permitted to read them. - * - * Some simple-minded access (2) checking isn't sufficient - * here: The problem is that the user may give us a - * deeply nested path to a file which has the same name - * as the file he wants to lock, but different - * permissions, say, e.g. - * /tmp/lots/of/subdirs/var/spool/mail/root. - * - * He may then try to replace /tmp/lots/of/subdirs by a - * symbolic link to / after we have invoked access () to - * check the file's permissions. The lockfile we'd - * create or remove would then actually be - * /var/spool/mail/root. - * - * To avoid this attack, we proceed as follows: - * - * - First, follow symbolic links a la - * dotlock_deference_symlink (). - * - * - get the result's dirname. - * - * - chdir to this directory. If you can't, bail out. - * - * - try to open the file in question, only using its - * basename. If you can't, bail out. - * - * - fstat that file and compare the result to a - * subsequent lstat (only using the basename). If - * the comparison fails, bail out. - * - * dotlock_prepare () is invoked from main () directly - * after the command line parsing has been done. - * - * Return values: - * - * 0 - Evereything's fine. The program's new current - * directory is the contains the file to be locked. - * The string pointed to by bn contains the name of - * the file to be locked. - * - * -1 - Something failed. Don't continue. - * - * tlr, Jul 15 1998 - */ - -static int -dotlock_check_stats (struct stat *fsb, struct stat *lsb) -{ - /* S_ISLNK (fsb->st_mode) should actually be impossible, - * but we may have mixed up the parameters somewhere. - * play safe. - */ - - if (S_ISLNK (lsb->st_mode) || S_ISLNK (fsb->st_mode)) - return -1; - - if ((lsb->st_dev != fsb->st_dev) || - (lsb->st_ino != fsb->st_ino) || - (lsb->st_mode != fsb->st_mode) || - (lsb->st_nlink != fsb->st_nlink) || - (lsb->st_uid != fsb->st_uid) || - (lsb->st_gid != fsb->st_gid) || - (lsb->st_rdev != fsb->st_rdev) || - (lsb->st_size != fsb->st_size)) - { - /* something's fishy */ - return -1; - } - - return 0; -} - -static int -dotlock_prepare (char *bn, size_t l, const char *f, int _fd) -{ - struct stat fsb, lsb; - char realpath[_POSIX_PATH_MAX]; - char *basename, *dirname; - char *p; - int fd; - int r; - - if (dotlock_deference_symlink (realpath, sizeof (realpath), f) == -1) - return -1; - - if ((p = strrchr (realpath, '/'))) - { - *p = '\0'; - basename = p + 1; - dirname = realpath; - } - else - { - basename = realpath; - dirname = "."; - } - - if (strlen (basename) + 1 > l) - return -1; - - strfcpy (bn, basename, l); - - if (chdir (dirname) == -1) - return -1; - - if (_fd != -1) - fd = _fd; - else if ((fd = open (basename, O_RDONLY)) == -1) - return -1; - - r = fstat (fd, &fsb); - - if (_fd == -1) - close (fd); - - if (r == -1) - return -1; - - if (lstat (basename, &lsb) == -1) - return -1; - - if (dotlock_check_stats (&fsb, &lsb) == -1) - return -1; - - return 0; -} - -/* - * Expand a symbolic link. - * - * This function expects newpath to have space for - * at least _POSIX_PATH_MAX characters. - * - */ - -static void -dotlock_expand_link (char *newpath, const char *path, const char *link) -{ - const char *lb = NULL; - size_t len; - - /* link is full path */ - if (*link == '/') - { - strfcpy (newpath, link, _POSIX_PATH_MAX); - return; - } - - if ((lb = strrchr (path, '/')) == NULL) - { - /* no path in link */ - strfcpy (newpath, link, _POSIX_PATH_MAX); - return; - } - - len = lb - path + 1; - memcpy (newpath, path, len); - strfcpy (newpath + len, link, _POSIX_PATH_MAX - len); -} - - -/* - * Deference a chain of symbolic links - * - * The final path is written to d. - * - */ - -static int -dotlock_deference_symlink (char *d, size_t l, const char *path) -{ - struct stat sb; - char realpath[_POSIX_PATH_MAX]; - const char *pathptr = path; - int count = 0; - - while (count++ < MAXLINKS) - { - if (lstat (pathptr, &sb) == -1) - { - /* perror (pathptr); */ - return -1; - } - - if (S_ISLNK (sb.st_mode)) - { - char linkfile[_POSIX_PATH_MAX]; - char linkpath[_POSIX_PATH_MAX]; - int len; - - if ((len = readlink (pathptr, linkfile, sizeof (linkfile))) == -1) - { - /* perror (pathptr); */ - return -1; - } - - linkfile[len] = '\0'; - dotlock_expand_link (linkpath, pathptr, linkfile); - strfcpy (realpath, linkpath, sizeof (realpath)); - pathptr = realpath; - } - else - break; - } - - strfcpy (d, pathptr, l); - return 0; -} - -/* - * Dotlock a file. - * - * realpath is assumed _not_ to be an absolute path to - * the file we are about to lock. Invoke - * dotlock_prepare () before using this function! - * - */ - -#define HARDMAXATTEMPTS 10 - -static int -dotlock_lock (const char *realpath) -{ - char lockfile[_POSIX_PATH_MAX + LONG_STRING]; - char nfslockfile[_POSIX_PATH_MAX + LONG_STRING]; - size_t prev_size = 0; - int fd; - int count = 0; - int hard_count = 0; - struct stat sb; - time_t t; - - snprintf (nfslockfile, sizeof (nfslockfile), "%s.%s.%d", - realpath, Hostname, (int) getpid ()); - snprintf (lockfile, sizeof (lockfile), "%s.lock", realpath); - - - BEGIN_PRIVILEGED (); - - unlink (nfslockfile); - - while ((fd = open (nfslockfile, O_WRONLY | O_EXCL | O_CREAT, 0)) < 0) - { - END_PRIVILEGED (); - - - if (errno != EAGAIN) - { - /* perror ("cannot open NFS lock file"); */ - return DL_EX_ERROR; - } - - - BEGIN_PRIVILEGED (); - } - - END_PRIVILEGED (); - - - close (fd); - - while (hard_count++ < HARDMAXATTEMPTS) - { - - BEGIN_PRIVILEGED (); - link (nfslockfile, lockfile); - END_PRIVILEGED (); - - if (stat (nfslockfile, &sb) != 0) - { - /* perror ("stat"); */ - return DL_EX_ERROR; - } - - if (sb.st_nlink == 2) - break; - - if (count == 0) - prev_size = sb.st_size; - - if (prev_size == sb.st_size && ++count > Retry) - { - if (DotlockFlags & DL_FL_FORCE) - { - BEGIN_PRIVILEGED (); - unlink (lockfile); - END_PRIVILEGED (); - - count = 0; - continue; - } - else - { - BEGIN_PRIVILEGED (); - unlink (nfslockfile); - END_PRIVILEGED (); - return DL_EX_EXIST; - } - } - - prev_size = sb.st_size; - - /* don't trust sleep (3) as it may be interrupted - * by users sending signals. - */ - - t = time (NULL); - do { - sleep (1); - } while (time (NULL) == t); - } - - BEGIN_PRIVILEGED (); - unlink (nfslockfile); - END_PRIVILEGED (); - - return DL_EX_OK; -} - - -/* - * Unlock a file. - * - * The same comment as for dotlock_lock () applies here. - * - */ - -static int -dotlock_unlock (const char *realpath) -{ - char lockfile[_POSIX_PATH_MAX + LONG_STRING]; - int i; - - snprintf (lockfile, sizeof (lockfile), "%s.lock", - realpath); - - BEGIN_PRIVILEGED (); - i = unlink (lockfile); - END_PRIVILEGED (); - - if (i == -1) - return DL_EX_ERROR; - - return DL_EX_OK; -} - -/* remove an empty file */ - -static int -dotlock_unlink (const char *realpath) -{ - struct stat lsb; - int i = -1; - - if (dotlock_lock (realpath) != DL_EX_OK) - return DL_EX_ERROR; - - if ((i = lstat (realpath, &lsb)) == 0 && lsb.st_size == 0) - unlink (realpath); - - dotlock_unlock (realpath); - - return (i == 0) ? DL_EX_OK : DL_EX_ERROR; -} - - -/* - * Check if a file can be locked at all. - * - * The same comment as for dotlock_lock () applies here. - * - */ - -static int -dotlock_try (void) -{ -#ifdef USE_SETGID - struct stat sb; -#endif - - if (access (".", W_OK) == 0) - return DL_EX_OK; - -#ifdef USE_SETGID - if (stat (".", &sb) == 0) - { - if ((sb.st_mode & S_IWGRP) == S_IWGRP && sb.st_gid == MailGid) - return DL_EX_NEED_PRIVS; - } -#endif - - return DL_EX_IMPOSSIBLE; -} diff -Nur muttbug.sh muttbug.sh --- muttbug.sh Thu Jan 1 00:00:00 1970 +++ muttbug.sh Mon Aug 2 23:51:20 2004 @@ -0,0 +1,311 @@ +#!/bin/sh + +# +# File a bug against the Mutt mail user agent. +# + +# +# $Id: muttbug.sh.in,v 2.18 2001/10/10 09:56:51 roessler Exp $ +# + +# +# Copyright (c) 2000 Thomas Roessler +# +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. +# + +SUBMIT="submit@bugs.guug.de" +DEBIAN_SUBMIT="submit@bugs.debian.org" + +prefix=/usr/local + +DEBUGGER=no +SENDMAIL=/usr/sbin/sendmail +sysconfdir=${prefix}/etc +pkgdatadir=@pkgdatadir@ + +include_file () +{ + echo + echo "--- Begin $1" + sed -e 's/^-/- -/' $1 | egrep -v '^[ ]*(#|$)' + echo "--- End $1" + echo +} + +debug_gdb () +{ + cat << EOF > $SCRATCH/gdb.rc +bt +list +quit +EOF + $DEBUGGER -n -x $SCRATCH/gdb.rc -c $CORE mutt +} + +debug_dbx () +{ + cat << EOF > $SCRATCH/dbx.rc +where +list +quit +EOF + $DEBUGGER -s $SCRATCH/dbx.rc mutt $CORE +} + +debug_sdb () +{ + cat << EOF > $SCRATCH/sdb.rc +t +w +q +EOF + $DEBUGGER mutt $CORE < $SCRATCH/sdb.rc +} + +case `echo -n` in +"") n=-n; c= ;; + *) n=; c='\c' ;; +esac + + +exec > /dev/tty +exec < /dev/tty + +SCRATCH=${TMPDIR-/tmp}/`basename $0`.`hostname`.$$ + +mkdir ${SCRATCH} || \ +{ + echo "`basename $0`: Can't create temporary directory." >& 2 ; + exit 1 ; +} + +trap "rm -r -f ${SCRATCH} ; trap '' 0 ; exit" 0 1 2 + +TEMPLATE=${SCRATCH}/template.txt + +echo "Please enter a one-line description of the problem you experience:" +echo $n "> $c" +read SUBJECT + +cat < $c" + read _CORE + test "$_CORE" && CORE="$_CORE" +fi + +echo $n "Do you want to include your personal mutt configuration files? [Y|n] $c" +read personal +case "$personal" in +[nN]*) personal=no ;; + *) personal=yes ;; +esac + +echo $n "Do you want to include your system's global mutt configuration file? [Y|n] $c" +read global +case "$global" in +[nN]*) global=no ;; + *) global=yes ;; +esac + +if test -f /etc/debian_version ; then + DEBIAN=yes + echo $n "Checking whether mutt has been installed as a package... $c" + DEBIANVERSION="`dpkg -l mutt | grep '^[ih]' | awk '{print $3}'`" 2> /dev/null + if test "$DEBIANVERSION" ; then + DPKG=yes + else + DPKG=no + unset DEBIANVERSION + fi + echo "$DPKG" + echo $n "File this bug with Debian? [Y|n] $c" + read DPKG + case "$DPKG" in + [nN]) DPKG=no ;; + *) DPKG=yes ;; + esac +else + DEBIAN=no + DPKG=no +fi + +MUTTVERSION="`mutt -v | head -1 | awk '{print $2}'`" +test "$DPKG" = "yes" && SUBMIT="$SUBMIT, $DEBIAN_SUBMIT" + +exec > ${TEMPLATE} + +test "$EMAIL" && echo "From: $EMAIL" +test "$REPLYTO" && echo "Reply-To: $REPLYTO" +test "$ORGANIZATION" && echo "Organization: $ORGANIZATION" + +echo "Subject: mutt-$MUTTVERSION: $SUBJECT" +echo "To: $SUBMIT" +echo "Bcc: ${EMAIL-$LOGNAME}" +echo +echo "Package: mutt" +echo "Version: ${DEBIANVERSION-$MUTTVERSION}" +echo "Severity: $severity" +echo +echo "-- Please type your report below this line" +echo +echo +echo + +if test "$DEBIAN" = "yes" ; then + echo "Obtaining Debian-specific information..." > /dev/tty + bug -p -s dummy mutt | \ + sed -n -e "/^-- System Information/,/^---/p" | \ + grep -v '^---' +fi + +echo +echo "-- Build environment information" +echo +echo "(Note: This is the build environment installed on the system" +echo "muttbug is run on. Information may or may not match the environment" +echo "used to build mutt.)" +echo +echo "- gcc version information" +echo "gcc" +gcc -v 2>&1 +echo +echo "- CFLAGS" +echo -Wall -pedantic -g -O2 + + +echo +echo "-- Mutt Version Information" +echo +mutt -v + +if test "$CORE" && test -f "$CORE" ; then + echo + echo "-- Core Dump Analysis Output" + echo + + case "$DEBUGGER" in + *sdb) debug_sdb $CORE ;; + *dbx) debug_dbx $CORE ;; + *gdb) debug_gdb $CORE ;; + esac + + echo +fi + +if test "$personal" = "yes" ; then + CANDIDATES=".muttrc-${MUTTVERSION} .muttrc .mutt/muttrc-${MUTTVERSION} .mutt/muttrc" + MATCHED="none" + for f in $CANDIDATES; do + if test -f "${HOME}/$f" ; then + MATCHED="${HOME}/$f" + break + fi + done + + if test "$MATCHED" = "none" ; then + echo "Warning: Can't find your personal .muttrc." >&2 + else + include_file $MATCHED + fi +fi + + +if test "$global" = "yes" ; then + CANDIDATES="Muttrc-${MUTTVERSION} Muttrc" + DIRECTORIES="$sysconfdir $pkgdatadir" + MATCHED="none" + for d in $DIRECTORIES ; do + for f in $CANDIDATES; do + if test -f $d/$f ; then + MATCHED="$d/$f" + break + fi + done + test "$MATCHED" = "none" || break + done + + if test "$MATCHED" = "none" ; then + echo "Warning: Can't find global Muttrc." >&2 + else + include_file $MATCHED + fi +fi + +exec > /dev/tty + +cp $TEMPLATE $SCRATCH/mutt-bug.txt + +input="e" +while : ; do + if test "$input" = "e" ; then + ${VISUAL-${EDITOR-vi}} $SCRATCH/mutt-bug.txt + if cmp $SCRATCH/mutt-bug.txt ${TEMPLATE} > /dev/null ; then + echo "Warning: Bug report was not modified!" + fi + fi + + echo $n "Submit, Edit, View, Quit? [S|e|v|q] $c" + read _input + input="`echo $_input | tr EVSQ evsq`" + case $input in + e*) ;; + v*) ${PAGER-more} $SCRATCH/mutt-bug.txt ;; + s*|"") $SENDMAIL -t < $SCRATCH/mutt-bug.txt ; exit ;; + q*) exit + esac +done + diff -Nur muttlib.c muttlib.c --- muttlib.c Mon Mar 25 11:29:32 2002 +++ muttlib.c Mon Aug 2 23:51:17 2004 @@ -991,7 +991,10 @@ ch = *src++; /* pad char */ /* calculate space left on line. if we've already written more data than will fit on the line, ignore the rest of the line */ - count = (COLS < destlen ? COLS : destlen); + if ( DrawFullLine ) + count = (COLS < destlen ? COLS : destlen); + else + count = ((COLS-SidebarWidth) < destlen ? COLS - SidebarWidth : destlen); if (count > wlen) { count -= wlen; /* how many chars left on this line */ diff -Nur pager.c pager.c --- pager.c Sun Jan 13 08:52:15 2002 +++ pager.c Mon Aug 2 23:51:16 2004 @@ -1032,7 +1032,7 @@ wchar_t wc; mbstate_t mbstate; - int wrap_cols = COLS - WrapMargin; + int wrap_cols = COLS - WrapMargin - SidebarWidth; if (wrap_cols <= 0) wrap_cols = COLS; @@ -1655,7 +1655,7 @@ if ((redraw & REDRAW_BODY) || topline != oldtopline) { do { - move (bodyoffset, 0); + move (bodyoffset, SidebarWidth); curline = oldtopline = topline; lines = 0; force_redraw = 0; @@ -1668,6 +1668,7 @@ &QuoteList, &q_level, &force_redraw, &SearchRE) > 0) lines++; curline++; + move(lines + bodyoffset, SidebarWidth); } last_offset = lineInfo[curline].offset; } while (force_redraw); @@ -1681,6 +1682,7 @@ addch ('~'); addch ('\n'); lines++; + move(lines + bodyoffset, SidebarWidth); } /* We are going to update the pager status bar, so it isn't * necessary to reset to normal color now. */ @@ -1693,20 +1695,22 @@ /* print out the pager status bar */ SETCOLOR (MT_COLOR_STATUS); BKGDSET (MT_COLOR_STATUS); - CLEARLINE (statusoffset); + CLEARLINE_WIN(statusoffset); if (IsHeader (extra)) { _mutt_make_string (buffer, - COLS-9 < sizeof (buffer) ? COLS-9 : sizeof (buffer), + COLS-9-SidebarWidth < sizeof (buffer) ? + COLS-9-SidebarWidth : sizeof (buffer), NONULL (PagerFmt), Context, extra->hdr, M_FORMAT_MAKEPRINT); } else if (IsMsgAttach (extra)) { _mutt_make_string (buffer, - COLS - 9 < sizeof (buffer) ? COLS - 9: sizeof (buffer), + COLS - 9 - SidebarWidth < sizeof (buffer) ? + COLS - 9 - SidebarWidth : sizeof (buffer), NONULL (PagerFmt), Context, extra->bdy->hdr, M_FORMAT_MAKEPRINT); } - mutt_paddstr (COLS-10, IsHeader (extra) || IsMsgAttach (extra) ? + mutt_paddstr (COLS-10-SidebarWidth, IsHeader (extra) || IsMsgAttach (extra) ? buffer : banner); addstr (" -- ("); if (last_pos < sb.st_size - 1) @@ -1722,15 +1726,18 @@ /* redraw the pager_index indicator, because the * flags for this message might have changed. */ menu_redraw_current (index); - + draw_sidebar(MENU_PAGER); /* print out the index status bar */ menu_status_line (buffer, sizeof (buffer), index, NONULL(Status)); - - move (indexoffset + (option (OPTSTATUSONTOP) ? 0 : (indexlen - 1)), 0); + move (indexoffset + (option (OPTSTATUSONTOP) ? 0 : (indexlen - 1)), + SidebarWidth); SETCOLOR (MT_COLOR_STATUS); - mutt_paddstr (COLS, buffer); + mutt_paddstr (COLS-SidebarWidth, buffer); SETCOLOR (MT_COLOR_NORMAL); } + /* if we're not using the index, update every time */ + if ( index == 0 ) + draw_sidebar(MENU_PAGER); redraw = 0; @@ -2537,6 +2544,13 @@ + case OP_SCROLL_MBOX_UP: + case OP_SCROLL_MBOX_DOWN: + case OP_NEXT_MBOX: + case OP_PREV_MBOX: + case OP_OPEN_MBOX: + scroll_sidebar(ch, MENU_PAGER); + break; default: ch = -1; break; diff -Nur sidebar.c sidebar.c --- sidebar.c Thu Jan 1 00:00:00 1970 +++ sidebar.c Mon Aug 2 23:51:20 2004 @@ -0,0 +1,168 @@ +#include "sidebar.h" +#include "buffy.h" +#include +#include "keymap.h" + +/*BUFFY *CurBuffy = 0;*/ +static BUFFY *TopBuffy = 0; +static BUFFY *BottomBuffy = 0; +static int known_lines = 0; + +static int quick_log10(int n) +{ + int c = 0; + if ( n == 0 ) return 0; + while ( n > 0 ) { + n /= 10; + c++; + } + return c; +} + +void calc_boundaries (int skip_end) +{ + BUFFY *tmp = Incoming; + + if ( known_lines != LINES ) { + TopBuffy = CurBuffy = BottomBuffy = 0; + known_lines = LINES; + } + for ( ; tmp->next != 0; tmp = tmp->next ) + tmp->next->prev = tmp; + + if ( TopBuffy == 0 && BottomBuffy == 0 ) + TopBuffy = Incoming; + if ( BottomBuffy == 0 ) { + int count = LINES - 2 - (skip_end != MENU_PAGER); + BottomBuffy = TopBuffy; + while ( --count && BottomBuffy->next ) + BottomBuffy = BottomBuffy->next; + } + else if ( TopBuffy == CurBuffy->next ) { + int count = LINES - 2 - (skip_end != MENU_PAGER); + BottomBuffy = CurBuffy; + tmp = BottomBuffy; + while ( --count && tmp->prev) + tmp = tmp->prev; + TopBuffy = tmp; + } + else if ( BottomBuffy == CurBuffy->prev ) { + int count = LINES - 2 - (skip_end != MENU_PAGER); + TopBuffy = CurBuffy; + tmp = TopBuffy; + while ( --count && tmp->next ) + tmp = tmp->next; + BottomBuffy = tmp; + } +} + +char *make_sidebar_entry(char *box, int size, int new) +{ + static char *entry = 0; + char *c; + int i = 0; + c = realloc(entry, SidebarWidth + 1); + if ( c ) entry = c; + entry[SidebarWidth] = 0; + for (; i < SidebarWidth; entry[i++] = ' ' ); + i = strlen(box); + strncpy( entry, box, i < SidebarWidth ? i :SidebarWidth ); + if ( new ) + sprintf( + entry + SidebarWidth - 5 - quick_log10(size) - quick_log10(new), + "% d(%d)", size, new); + else + sprintf( entry + SidebarWidth - 3 - quick_log10(size), "% d", size); + return entry; +} + +int draw_sidebar(int skip_end) { + + int lines = 1; + BUFFY *tmp; + + if ( SidebarWidth == 0 ) return 0; + + SETCOLOR(MT_COLOR_STATUS); + /* draw the divider */ + for ( ; lines < LINES-1-(skip_end != MENU_PAGER); lines++ ) { + move(lines, SidebarWidth - 1); + addch('|'); + } + if ( Incoming == 0 ) return 0; + lines = 1; /* go back to the top */ + + if ( known_lines != LINES || TopBuffy == 0 || BottomBuffy == 0 ) + calc_boundaries(skip_end); + if ( CurBuffy == 0 ) CurBuffy = Incoming; + + tmp = TopBuffy; + + SETCOLOR(MT_COLOR_NORMAL); + + for ( ; tmp && lines < LINES-1 - (skip_end != MENU_PAGER); tmp = tmp->next ) { + if ( tmp == CurBuffy ) + SETCOLOR(MT_COLOR_INDICATOR); + else if ( tmp->msg_unread > 0 ) + SETCOLOR(MT_COLOR_NEW); + else + SETCOLOR(MT_COLOR_NORMAL); + + move( lines, 0 ); + if ( Context && !strcmp( tmp->path, Context->path ) ) { + printw( "%.*s", SidebarWidth, + make_sidebar_entry(basename(tmp->path), Context->msgcount, + Context->unread)); + tmp->msg_unread = Context->unread; + } + else + printw( "%.*s", SidebarWidth, + make_sidebar_entry(basename(tmp->path), tmp->msgcount, + tmp->msg_unread)); + lines++; + } + SETCOLOR(MT_COLOR_NORMAL); + for ( ; lines < LINES - 1 - (skip_end != MENU_PAGER); lines++ ) { + int i = 0; + move( lines, 0 ); + for ( ; i < SidebarWidth - 1; i++ ) + addch(' '); + } + return 0; +} + +void scroll_sidebar(int op, int menu) +{ + switch (op) { + case OP_NEXT_MBOX: + if ( CurBuffy->next == NULL ) return; + CurBuffy = CurBuffy->next; + break; + case OP_PREV_MBOX: + if ( CurBuffy == Incoming ) return; + { + BUFFY *tmp = Incoming; + while ( tmp->next && strcmp(tmp->next->path, CurBuffy->path) ) tmp = tmp->next; + CurBuffy = tmp; + } + break; + case OP_SCROLL_MBOX_UP: + CurBuffy = TopBuffy; + if ( CurBuffy != Incoming ) { + calc_boundaries(menu); + CurBuffy = CurBuffy->prev; + } + break; + case OP_SCROLL_MBOX_DOWN: + CurBuffy = BottomBuffy; + if ( CurBuffy->next ) { + calc_boundaries(menu); + CurBuffy = CurBuffy->next; + } + break; + default: + return; + } + calc_boundaries(menu); + draw_sidebar(menu); +} diff -Nur sidebar.h sidebar.h --- sidebar.h Thu Jan 1 00:00:00 1970 +++ sidebar.h Mon Aug 2 23:51:20 2004 @@ -0,0 +1,13 @@ +#include "mutt.h" +#include "mutt_curses.h" + +struct MBOX_LIST { + char *path; + int msgcount; + int new; +} MBLIST; + +/* parameter is whether or not to go to the status line */ +/* used for omitting the last | that covers up the status bar in the index */ +int draw_sidebar(int); +void scroll_sidebar(int, int);