This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=9b0dee5fa917d5804aa2ca89a186ea8da64578ca

The branch, master has been updated
       via  9b0dee5fa917d5804aa2ca89a186ea8da64578ca (commit)
      from  f2eb56bb7632e4044173a344964d6739a7ef4b7f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 9b0dee5fa917d5804aa2ca89a186ea8da64578ca
Author: Sergey Poznyakoff <g...@gnu.org.ua>
Date:   Fri Aug 14 22:53:52 2009 +0300

    Mail: configurable `headers' output format.
    
    * mail/from.c: Rewrite using format string.
    * mail/mail.c (default_setup): Set default value for `headline'.
    (main): Fix call to util_do_command.
    * mail/mail.h [HAVE_STDARG_H]: Remove conditions.
    (mail_compile_headline): New proto.
    * mail/mailvar.c (mailvar_tab): New variable "headline".
    * mail/util.c: Minor fixes.
    * NEWS, doc/programs.texi: Update.

-----------------------------------------------------------------------

Summary of changes:
 NEWS                      |   10 +-
 doc/texinfo/programs.texi |  120 ++++++++++-
 mail/from.c               |  518 ++++++++++++++++++++++++++++++++++++++-------
 mail/mail.c               |    3 +-
 mail/mail.h               |    8 +-
 mail/mailvar.c            |    4 +
 mail/util.c               |   21 +--
 7 files changed, 583 insertions(+), 101 deletions(-)

diff --git a/NEWS b/NEWS
index 07bbfef..ed4a90e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU mailutils NEWS -- history of user-visible changes. 2009-08-03
+GNU mailutils NEWS -- history of user-visible changes. 2009-08-14
 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 
 2008, 2009 Free Software Foundation, Inc.
 See the end of file for copying conditions.
@@ -83,6 +83,12 @@ described.
 For each variable, this command prints its name, data type, current
 value and a short description.
 
+** headline variable
+
+The headline variable holds a format string to use for the header
+summary. Its format is mostly compatible with that of the `nail'
+mail reader.
+
 ** showenvelope variable
 
 If the `showenvelope' variable is set, print command will include the
@@ -90,7 +96,7 @@ SMTP envelope in its output.
 
 ** fromfield variable
 
-The `fromenvelope' boolean variable, if set, instructs mail to obtain
+The `fromfield' boolean variable, if set, instructs mail to obtain
 the sender address from the `From:' header.  This is the default.
 If unset, the sender address is obtained from the SMTP envelope.
 
diff --git a/doc/texinfo/programs.texi b/doc/texinfo/programs.texi
index 20be516..4135911 100644
--- a/doc/texinfo/programs.texi
+++ b/doc/texinfo/programs.texi
@@ -2240,14 +2240,14 @@ but before opening the mailbox.
 @itemx --file
 Operate on the mailbox given by the first non-optional command line
 argument. If there is no such argument, read messages from the
-user's @file{mbox} file. @xref{Reading Mail} for more details about
+user's @file{mbox} file. @xref{Reading Mail}, for more details about
 using this option.
 @item -F
 @itemx --byname
 Record outgoing messages in a file named after the first recipient.
 The name is the login-name portion of the address found first on the
 @samp{To:} line in the mail header. This option sets the @samp{byname}
-variable, which see (@xref{byname}).
+variable, which see (@pxref{byname}).
 @item -H
 @itemx --headers
 Print header summary to stdout and exit.
@@ -3482,6 +3482,7 @@ set
 Following variables control the behavior of GNU @command{mail}:
 
 @table @code
+...@kwindex append
 @item append
 @*Type: Boolean, Read-Only
 @*Default: True
@@ -3491,6 +3492,7 @@ Messages saved in mbox are appended to the end rather 
than prepended.
 This is the default and cannot be changed. This variable exists only
 for compatibility with other @command{mailx} implementations.
 
+...@kwindex appenddeadletter
 @item appenddeadletter
 @*Type: Boolean.
 @*Default: False.
@@ -3500,6 +3502,7 @@ If this variable is @code{True}, the contents of canceled 
letter is
 appended to the user's @file{dead.letter} file. Otherwise it overwrites
 its contents.
 
+...@kwindex askbcc
 @item askbcc
 @*Type: Boolean.
 @*Default: False.
@@ -3508,6 +3511,7 @@ its contents.
 When set to @code{True} the user will be prompted to enter @code{Bcc}
 field before composing the message.
 
+...@kwindex askcc
 @item askcc
 @*Type: Boolean.
 @*Default: True.
@@ -3516,6 +3520,7 @@ field before composing the message.
 When set to @code{True} the user will be prompted to enter @code{Cc}
 field before composing the message.
 
+...@kwindex asksub
 @item asksub
 @*Type: Boolean.
 @*Default: True in interactive mode, False otherwise.
@@ -3524,6 +3529,7 @@ field before composing the message.
 When set to @code{True} the user will be prompted to enter @code{Subject}
 field before composing the message.
 
+...@kwindex autoinc
 @item autoinc
 @*Type: Boolean.
 @*Default: True.
@@ -3531,6 +3537,7 @@ field before composing the message.
 
 Automatically incorporate newly arrived messages.
 
+...@kwindex autoprint
 @item autoprint
 @*Type: Boolean.
 @*Default: False.
@@ -3539,6 +3546,7 @@ Automatically incorporate newly arrived messages.
 Causes the delete command to behave like dp - thus, after deleting a
 message, the next one will be typed automatically.
 
+...@kwindex bang
 @item bang
 @*Type: Boolean.
 @*Default: False.
@@ -3548,6 +3556,7 @@ When set, every occurrence of @code{!} in arguments to 
@code{!}
 command is replaced with the last executed command.
 
 @anchor{byname}
+...@kwindex byname
 @item byname
 @*Type: Boolean
 @*Default: Unset
@@ -3561,6 +3570,7 @@ The name is the login-name portion of the address found 
first on the
 It is set by the @option{--byname} (@option{-F}) command line option.
 
 @anchor{datefield}
+...@kwindex datefield
 @item datefield
 @*Type: Boolean.
 @*Default: False.
@@ -3574,6 +3584,7 @@ will fall back to using @acronym{SMTP} envelope.
 
 @xref{fromfield}.
 
+...@kwindex charset
 @item charset
 @*Type: string
 @*Default: @samp{auto}
@@ -3586,6 +3597,7 @@ variable is set to @samp{auto}, @command{mail} tries to 
deduce the
 name of the character set from the value of @code{LC_ALL} environment
 variable. Otherwise, its value is taken as the name of the charset.
 
+...@kwindex cmd
 @item cmd
 @*Type: String.
 @*Default: Unset.
@@ -3593,6 +3605,7 @@ variable. Otherwise, its value is taken as the name of 
the charset.
 
 Contains default shell command for @code{pipe}.
 
+...@kwindex columns
 @item columns
 @*Type: Numeric.
 @*Default: Detected at startup by querying the terminal device. If this
@@ -3601,6 +3614,7 @@ fails, the value of environment variable @code{COLUMNS} 
is used.
 
 This variable contains the number of columns on terminal screen.
 
+...@kwindex crt
 @item crt
 @*Type: Boolean or Numeric
 @*Default: True in interactive mode, False otherwise.
@@ -3614,6 +3628,7 @@ if @code{crt} is set without a value, then the height of 
the terminal
 screen is used to compute the threshold. The number of lines on
 screen is controlled by @code{screen} variable.
 
+...@kwindex debug
 @item debug
 @*Type: String to boolean
 @*Default: Not set
@@ -3628,6 +3643,7 @@ information.  If set to @samp{true} (i.e. @code{set 
debug}), sets
 maximum debugging (@samp{<trace7}) on mailbox and its underlying
 objects.
 
+...@kwindex decode-fallback
 @item decode-fallback
 @*Type: String.
 @*Default: @samp{none}.
@@ -3650,6 +3666,7 @@ Unprintable characters are represented by their octal 
codes. Printable
 ones are printed @samp{as is}.
 @end table
 
+...@kwindex debug
 @item debug
 @*Type: Boolean
 @*Default: Unset
@@ -3658,6 +3675,7 @@ ones are printed @samp{as is}.
 This variable is not used.  It exists for compatibility with other
 @command{mailx} implementations and for future use.
 
+...@kwindex dot
 @item dot
 @*Type: Boolean.
 @*Default: False.
@@ -3666,6 +3684,7 @@ This variable is not used.  It exists for compatibility 
with other
 If @code{True}, causes @command{mail} to interpret a period alone on a line as 
the
 terminator of a message you are sending.
 
+...@kwindex emptystart
 @item emptystart
 @*Type: Boolean.
 @*Default: False.
@@ -3675,6 +3694,7 @@ If the mailbox is empty, @command{mail} normally prints 
@samp{No mail for user}
 exits immediately. If this option is set, @command{mail} will start no matter 
is
 the mailbox empty or not.
 
+...@kwindex editheaders
 @item editheaders
 @*Type: Boolean.
 @*Default: False.
@@ -3684,6 +3704,7 @@ When set, @command{mail} will include message headers in 
the text to
 be the @code{~e} and @code{~v} escapes, thus allowing you to customize
 the headers.
 
+...@kwindex escape
 @item escape
 @*Type: String.
 @*Default: ~
@@ -3692,6 +3713,7 @@ the headers.
 If defined, the first character of this option gives the character to
 denoting escapes.
 
+...@kwindex flipr
 @item flipr
 @*Type: Boolean
 @*Default: Unset
@@ -3700,6 +3722,7 @@ denoting escapes.
 If set, the variable @code{flipr} swaps the meanings of @code{reply}
 and @code{Reply} commands (@pxref{Replying}).
 
+...@kwindex folder
 @item folder
 @*Type: String.
 @*Default: Unset.
@@ -3709,6 +3732,7 @@ The name of the directory to use for storing folders of 
messages. If
 unset, @env{$HOME} is assumed.
 
 @anchor{fromfield}
+...@kwindex fromfield
 @item fromfield
 @*Type: Boolean.
 @*Default: True.
@@ -3719,6 +3743,7 @@ Unsetting this variable tells @command{mail} to obtain it 
from the
 
 @xref{datefield}.
 
+...@kwindex header
 @item header
 @*Type: Boolean.
 @*Default: True, unless started with @option{--nosum} (@option{-N}) option.
@@ -3727,6 +3752,56 @@ Unsetting this variable tells @command{mail} to obtain 
it from the
 Whether to run @code{headers} command automatically after entering
 interactive mode.
 
+...@kwindex headline
+...@item headline
+...@*type: String
+...@*default: @samp{%>%a%4m %18f %16d %3l/%-5o %s}
+
+A format string to use for the header summary.  The @samp{%} character
+introduces a @dfn{format specifier}.  Valid format specifiers are:
+
+...@multitable @columnfractions 0.2 0.8
+...@headitem Letter @tab Meaning
+...@item %a @tab Message attributes.
+...@item %d @tab The date when the message was received.
+...@item %f @tab The address of the message sender.
+...@item %l @tab The number of lines of the message.
+...@item %m @tab Message number.
+...@item %o @tab The number of octets (bytes) in the message.
+...@item %s @tab Message subject (if any).
+...@item %S @tab Message subject (if any) in double quotes.
+...@item %> @tab A @samp{>} for the current message, otherwise a space.
+...@item %< @tab A @samp{<} for the current message, otherwise a space.
+...@item %% @tab A `%' character.
+...@end multitable
+
+Some additional symbols are allowed between @samp{%} and the specifier
+letter. The @samp{-} character immediately following @samp{%}
+indicates that this field should be left aligned. Similarly, the
+...@samp{+} character indicates right alignment. Default alignment
+depends on the type of the specifier: the specifiers that produce
+numeric values (@samp{%l}, @samp{%m}, and @samp{%o}) are aligned to
+the right, whereas the ones producing string values are aligned to the
+left.
+
+A number following @samp{%} or the alignment flag, indicates the
+field width. Consider, for example, the following specifiers:
+
+...@table @asis
+...@item %m
+Print current message number. Take as much screen columns as necessary
+to output it.
+
+...@item %4m
+...@itemx %+4m
+Print current message number. Occupy 4 screen columns, truncate the
+output if it does not fit that width. Align the output to the right. 
+
+...@item %-4m
+Same as above, but align to the left.
+...@end table
+
+...@kwindex hold
 @item hold
 @*Type: Boolean.
 @*Default: False.
@@ -3737,6 +3812,7 @@ user's mailbox (@file{$HOME/mbox}). Otherwise, they will 
be held in
 system mailbox also. This option is in effect only when operating
 upon user's system mailbox.
 
+...@kwindex ignore 
 @item ignore
 @*Type: Boolean.
 @*Default: False.
@@ -3746,6 +3822,7 @@ When set to @code{True}, @command{mail} will ignore 
keyboard interrupts
 when composing messages. Otherwise an interrupt will be taken as a
 signal to abort composing.
 
+...@kwindex ignoreeof
 @item ignoreeof
 @*Type: Boolean.
 @*Default: False.
@@ -3754,6 +3831,7 @@ signal to abort composing.
 Controls whether typing EOF character terminates the letter being
 composed.
 
+...@kwindex indentprefix
 @item indentprefix
 @*Type: String.
 @*Default: "\t" (a tab character).
@@ -3761,6 +3839,7 @@ composed.
 
 String used by the @code{~m} tilde escape for indenting quoted messages.
 
+...@kwindex inplacealiases
 @item inplacealiases
 @*Type: Boolean
 @*Default: False
@@ -3770,6 +3849,7 @@ before entering send mode (@pxref{Composing Mail}). By 
default, the
 address header fields are left intact while composing, the alias
 expansion takes place immediately before sending message.
 
+...@kwindex keep
 @item keep
 @*Type: Boolean, Read-Only
 @*Default: True
@@ -3779,6 +3859,7 @@ Truncate the user's system mailbox when it is empty, 
instead of
 removing it. This is the default and cannot be changed. This variable
 exists only for compatibility with other @command{mailx} implementations.
 
+...@kwindex keepsave
 @item keepsave
 @*Type: Boolean.
 @*Default: False.
@@ -3788,6 +3869,7 @@ Controls whether saved messages should be kept in system 
mailbox too.
 This variable is in effect only when operating upon a user's system
 mailbox.
 
+...@kwindex mailx
 @item mailx
 @*Type: Boolean.
 @*Default: False.
@@ -3807,6 +3889,7 @@ will exit with zero status. By default it exits with zero 
status only
 if the message was sent successfully.
 @end itemize
 
+...@kwindex metamail
 @item metamail
 @*Type: Boolean or String.
 @*Default: True.
@@ -3830,6 +3913,7 @@ set metamail
 set metamail="metamail -m mail -p"
 @end smallexample
 
+...@kwindex mimenoask
 @item mimenoask
 @*Type: String
 @*Default: Empty
@@ -3850,6 +3934,7 @@ will disable prompting before displaying any textual 
files, no
 matter what their subtype is, and before displaying files with
 type @samp{image/jpeg}.
 
+...@kwindex metoo
 @item metoo
 @*Type: Boolean.
 @*Default: False.
@@ -3859,6 +3944,7 @@ Usually, when an alias is expanded that contains the 
sender, the sender
 is removed from the expansion. Setting this option causes the sender to
 be included in the group.
 
+...@kwindex mode
 @item mode
 @*Type: String, Read-Only
 @*Default: The name of current operation mode.
@@ -3888,6 +3974,7 @@ The program operates in send mode. This means it was 
given one or more
 recipient addresses in the command line.
 @end table
 
+...@kwindex nullbody
 @item nullbody
 @* Type: Boolean
 @* Default: True
@@ -3912,6 +3999,7 @@ outputs something on its standard output or error:
 @end group
 @end smallexample
 
+...@kwindex showenvelope
 @item showenvelope
 @*Type: Boolean
 @*Default: Unset
@@ -3919,6 +4007,7 @@ outputs something on its standard output or error:
 If this variable is set, the @code{print} command will include the
 @acronym{STMP} envelope in its output.
 
+...@kwindex nullbodymsg
 @item nullbodymsg
 @*Type: String
 @*Default: Null message body; hope that's ok 
@@ -3930,6 +4019,7 @@ this text, in accordance with the current locale, is 
displayed.
 
 Unsetting this variable disables the warning.
 
+...@kwindex onehop
 @item onehop
 @*Type: Boolean
 @*Default: Unset
@@ -3938,6 +4028,7 @@ Unsetting this variable disables the warning.
 This variable is not used.  It exists for compatibility with other
 @command{mailx} implementations and for future use.
 
+...@kwindex outfolder
 @item outfolder
 @*Type: String.
 @*Default: Unset.
@@ -3947,6 +4038,7 @@ Contains the directory in which files created by 
@code{save},
 @code{write}, etc. commands will be stored. When unset, current
 directory is assumed.
 
+...@kwindex page
 @item page
 @*Type: Boolean.
 @*Default: False.
@@ -3955,6 +4047,7 @@ directory is assumed.
 If set to @code{True}, the @code{pipe} command will emit a linefeed
 character after printing each message.
 
+...@kwindex prompt
 @item prompt
 @*Type: String.
 @*Default: "? "
@@ -3962,6 +4055,7 @@ character after printing each message.
 
 Contains the command prompt sequence.
 
+...@kwindex quiet
 @item quiet
 @*Type: Boolean
 @*Default: Unset
@@ -3970,6 +4064,7 @@ Contains the command prompt sequence.
 This variable is not used.  It exists for compatibility with other
 @command{mailx} implementations and for future use.
 
+...@kwindex quit
 @item quit
 @*Type: Boolean.
 @*Default: False, unless started with @option{--quit} (@option{-q}) option.
@@ -3977,6 +4072,7 @@ This variable is not used.  It exists for compatibility 
with other
 
 When set, causes keyboard interrupts to terminate the program.
 
+...@kwindex rc
 @item rc
 @*Type: Boolean.
 @*Default: True, unless started with @option{--norc} (@option{-N}) option.
@@ -3985,6 +4081,7 @@ When set, causes keyboard interrupts to terminate the 
program.
 When this variable is set, @command{mail} will read the system-wide
 configuration file upon startup. See @ref{Mail Configuration Files}.
 
+...@kwindex readonly
 @item readonly
 @*Type: Boolean
 @*Default: False
@@ -3995,6 +4092,7 @@ When set, mailboxes are opened in readonly mode.  In this 
mode, any
 disabled.  These commands include, but are not limited to: 
 @code{delete}, @code{save} and @code{mbox}.
 
+...@kwindex record
 @item record
 @*Type: String.
 @*Default: Unset.
@@ -4002,12 +4100,14 @@ disabled.  These commands include, but are not limited 
to:
 
 When set, any outgoing message will be saved to the named file.
 
+...@kwindex recursivealiases
 @item recursivealiases
 @*Type: Boolean
 @*Default: True
 
 When set, @command{mail} will expand aliases recursively.
 
+...@kwindex regex
 @item regex
 @*Type: Boolean.
 @*Default: True.
@@ -4016,6 +4116,7 @@ When set, @command{mail} will expand aliases recursively.
 Setting this to @code{True} enables use of regular expressions in
 @samp{/.../} message specifications.
 
+...@kwindex replyprefix
 @item replyprefix
 @*Type: String
 @*Default: @samp{Re: }
@@ -4024,6 +4125,7 @@ Setting this to @code{True} enables use of regular 
expressions in
 Sets the prefix that will be used when constructing the subject line
 of a reply message.
 
+...@kwindex replyregex
 @item replyregex
 @*Type: String
 @*Default: @samp{^re: *}
@@ -4045,6 +4147,7 @@ set 
replyregex="^(re|odp|aw|ang)(\\[[0-9]+\\])?:[[:blank:]]"
 @noindent
 (Notice the quoting of backslash characters).
 
+...@kwindex save
 @item save
 @*Type: Boolean.
 @*Default: True.
@@ -4053,6 +4156,7 @@ set 
replyregex="^(re|odp|aw|ang)(\\[[0-9]+\\])?:[[:blank:]]"
 When set, the aborted messages will be stored in the user's
 @file{dead.file}. See also @code{appenddeadletter}.
 
+...@kwindex screen
 @item screen
 @*Type: Numeric.
 @*Default: Detected at startup by querying the terminal device. If this
@@ -4061,6 +4165,7 @@ fails, the value of environment variable @code{LINES} is 
used.
 
 This variable contains the number of lines on terminal screen.
 
+...@kwindex sendmail
 @item sendmail
 @*Type: String.
 @*Default: sendmail:/usr/lib/sendmail
@@ -4068,6 +4173,7 @@ This variable contains the number of lines on terminal 
screen.
 
 Contains URL of the mail transport agent.
 
+...@kwindex sendwait
 @item sendwait
 @*Type: Boolean
 @*Default: Unset
@@ -4076,6 +4182,7 @@ Contains URL of the mail transport agent.
 This variable is not used.  It exists for compatibility with other
 @command{mailx} implementations and for future use.
 
+...@kwindex showto
 @item showto
 @*Type: Boolean
 @*Default: False
@@ -4084,6 +4191,7 @@ This variable is not used.  It exists for compatibility 
with other
 If the message was sent by the user, print its recipient address in
 the header summary.
 
+...@kwindex Sign
 @item Sign
 @*Type: String.
 @*Default: Unset.
@@ -4093,6 +4201,7 @@ Contains the filename holding users signature. The 
contents of this
 file is appended to the end of a message being composed by @code{~A}
 escape.
 
+...@kwindex sign
 @item sign
 @*Type: String.
 @*Default: Unset.
@@ -4102,6 +4211,7 @@ Contains the user's signature. The contents of this 
variable is appended
 to the end of a message being composed by @code{~a} escape. Use
 @code{Sign} variable, if your signature occupies more than one line.
 
+...@kwindex showto
 @item showto
 @*Type: Boolean
 @*Default: unset
@@ -4111,6 +4221,7 @@ If this variable is set, @command{mail} will show 
@code{To:} addresses
 instead of @code{From:} for all messages that come from the user that
 invoked the program.
 
+...@kwindex subject
 @item subject
 @*Type: String.
 @*Default: Unset.
@@ -4119,6 +4230,7 @@ invoked the program.
 Contains default subject line. This will be used when @code{asksub} is
 off.
 
+...@kwindex toplines
 @item toplines
 @*Type: Numeric.
 @*Default: 5
@@ -4126,6 +4238,7 @@ off.
 
 Number of lines to be displayed by @code{top} and @code{Top} commands.
 
+...@kwindex variable-strict
 @item variable-strict
 @itemx varstrict
 @*Type: Boolean.
@@ -4138,6 +4251,7 @@ variables. Also, if the user is trying to set an unknown 
variable,
 
 @xref{Setting and Unsetting the Variables}.
 
+...@kwindex variable-pretty-print
 @item variable-pretty-print
 @itemx varpp
 @*Type: Boolean.
@@ -4146,6 +4260,7 @@ variables. Also, if the user is trying to set an unknown 
variable,
 If this variable is set, the listing ouput by @command{set} contains short
 descriptions before each variable. @xref{Setting and Unsetting the Variables}. 
 
+...@kwindex verbose
 @item verbose
 @*Type: Boolean.
 @*Default: False.
@@ -4153,6 +4268,7 @@ descriptions before each variable. @xref{Setting and 
Unsetting the Variables}.
 
 When set, the actual delivery of messages is displayed on the user's terminal.
 
+...@kwindex xmailer
 @item xmailer
 @*Type: Boolean.
 @*Default: Set.
diff --git a/mail/from.c b/mail/from.c
index add2643..31e2a92 100644
--- a/mail/from.c
+++ b/mail/from.c
@@ -18,27 +18,220 @@
    MA 02110-1301 USA */
 
 #include "mail.h"
+#include <mu_umaxtostr.h>
 
-/*
- * f[rom] [msglist]
- */
+#define ALIGN_UNDEF -1
+#define ALIGN_RIGHT 0
+#define ALIGN_LEFT  1
 
-int
-mail_from0 (msgset_t *mspec, mu_message_t msg, void *data)
+struct header_call_args
+{
+  msgset_t *mspec;
+  mu_message_t msg;
+  size_t cols_rest;
+  char *buf;
+  size_t size;
+};
+  
+struct header_segm
+{
+  struct header_segm *next;
+  int align;
+  size_t width;
+  void *data;
+  char *(*get) (struct header_call_args *args, void *data);
+};
+
+void
+header_ensure_space (struct header_call_args *args, size_t size)
+{
+  if (size > args->size)
+    {
+      args->buf = xrealloc (args->buf, size);
+      args->size = size;
+    }
+}
+
+static char *
+header_buf_string_len (struct header_call_args *args, const char *str,
+                      size_t len)
+{
+  header_ensure_space (args, len + 1);
+  memcpy (args->buf, str, len);
+  args->buf[len] = 0;
+  return args->buf;
+}
+
+static char *
+header_buf_string (struct header_call_args *args, const char *str)
+{
+  if (!str)
+    return header_buf_string_len (args, "", 0);
+  return header_buf_string_len (args, str, strlen (str));
+}
+
+static void
+format_pad (size_t n)
+{
+  for (; n; n--)
+    fputc (' ', ofile);
+}
+
+static void
+format_headline (struct header_segm *seg, msgset_t *mspec, mu_message_t msg)
+{
+  int screen_cols = util_getcols () - 2;
+  int out_cols = 0;
+  struct header_call_args args;
+
+  args.mspec = mspec;
+  args.msg = msg;
+  args.buf = NULL;
+  args.size = 0;
+  
+  for (; seg; seg = seg->next)
+    {
+      size_t width, len;
+      size_t cols_rest = screen_cols - out_cols;
+      char *p;
+
+      args.cols_rest = cols_rest;
+      p = seg->get (&args, seg->data);
+
+      if (!p)
+       p = "";
+      len = strlen (p);
+      
+      if (seg->width)
+       width = seg->width;
+      else
+       width = len;
+      if (width > cols_rest)
+       width = cols_rest;
+
+      if (len > width)
+       len = width;
+      
+      if (seg->align == ALIGN_RIGHT)
+       {
+         format_pad (width - len);
+         fprintf (ofile, "%*.*s", len, len, p);
+       }
+      else
+       {
+         fprintf (ofile, "%*.*s", len, len, p);
+         format_pad (width - len);
+       }
+      out_cols += width;
+    }
+
+  fprintf (ofile, "\n");
+  free (args.buf);
+}    
+
+static void
+free_headline (struct header_segm *seg)
+{
+  while (seg)
+    {
+      struct header_segm *next = seg->next;
+      if (seg->data)
+       free (seg->data);
+      free (seg);
+      seg = next;
+    }
+}
+
+
+static char *
+hdr_text (struct header_call_args *args, void *data)
+{
+  return data;
+}
+
+static char *
+hdr_cur (struct header_call_args *args, void *data)
+{
+  if (is_current_message (args->mspec->msg_part[0]))
+    return (char*) data;
+  return " ";
+}
+
+/* %a */
+static char *
+hdr_attr (struct header_call_args *args, void *data)
 {
-  mu_header_t hdr = NULL;
-  mu_envelope_t env;
   mu_attribute_t attr;
-  char *from = NULL, *subj = NULL, *fromp, *subjp;
-  int froml, subjl;
-  char date[80], st[10];
-  int cols = util_getcols () - 6;
-  int cflag;
-  size_t m_size = 0, m_lines = 0;
+  char cflag;
+  
+  mu_message_get_attribute (args->msg, &attr);
+  
+  if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_MBOXED))
+    cflag = 'M';
+  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_PRESERVED))
+    cflag = 'P';
+  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_SAVED))
+    cflag = '*';
+  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_TAGGED))
+    cflag = 'T';
+  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_SHOWN))
+    cflag = 'R';
+  else if (mu_attribute_is_recent (attr))
+    cflag = 'N';
+  else if (!mu_attribute_is_read (attr))
+    cflag = 'U';
+  else
+    cflag = ' ';
+  return header_buf_string_len (args, &cflag, 1);
+}
+    
+/* %d */
+static char *
+hdr_date (struct header_call_args *args, void *data)
+{
+  char date[80];
+  mu_header_t hdr;
 
+  mu_message_get_header (args->msg, &hdr);
+  
+  date[0] = 0;
+  if (mailvar_get (NULL, "datefield", mailvar_type_boolean, 0) == 0
+      && mu_header_get_value (hdr, MU_HEADER_DATE,
+                             date, sizeof (date), NULL) == 0)
+    {
+      time_t t;
+      if (mu_parse_date (date, &t, NULL) == 0)
+       strftime (date, sizeof(date), "%a %b %e %H:%M", localtime (&t));
+      else
+       date[0] = 0;
+    }
+
+  if (date[0] == 0)
+    {
+      const char *p;
+      struct tm tm;
+      mu_timezone tz;
+      mu_envelope_t env;
+      
+      mu_message_get_envelope (args->msg, &env);
+      if (mu_envelope_sget_date (env, &p) == 0
+          && mu_parse_ctime_date_time (&p, &tm, &tz) == 0)
+       strftime (date, sizeof(date), "%a %b %e %H:%M", &tm);
+    }
+  return header_buf_string (args, date);
+}
+
+/* %f */
+static char *
+hdr_from (struct header_call_args *args, void *data)
+{
+  char *from = NULL;
+  
   if (mailvar_get (NULL, "fromfield", mailvar_type_boolean, 0) == 0)
     {  
-      mu_message_get_header (msg, &hdr);
+      mu_header_t hdr;
+      
+      mu_message_get_header (args->msg, &hdr);
       if (mu_header_aget_value_unfold (hdr, MU_HEADER_FROM, &from) == 0)
        {
          mu_address_t address = NULL;
@@ -49,7 +242,8 @@ mail_from0 (msgset_t *mspec, mu_message_t msg, void *data)
          
              if (mu_address_sget_email (address, 1, &email) == 0)
                {
-                 if (mailvar_get (NULL, "showto", mailvar_type_boolean, 0) == 0
+                 if (mailvar_get (NULL, "showto",
+                                  mailvar_type_boolean, 0) == 0
                      && mail_is_my_name (email))
                    {
                      char *tmp;
@@ -86,87 +280,263 @@ mail_from0 (msgset_t *mspec, mu_message_t msg, void *data)
       mu_envelope_t env = NULL;
       const char *sender = "";
       
-      if (mu_message_get_envelope (msg, &env) == 0)
+      if (mu_message_get_envelope (args->msg, &env) == 0)
        mu_envelope_sget_sender (env, &sender);
       from = strdup (sender);
     }
 
+  header_buf_string (args, from);
+  free (from);
+  return args->buf;
+}
+
+/* %l */
+static char *
+hdr_lines (struct header_call_args *args, void *data)
+{
+  size_t m_lines;
+  char buf[UINTMAX_STRSIZE_BOUND];
+  mu_message_lines (args->msg, &m_lines);
+  
+  return header_buf_string (args, umaxtostr (m_lines, buf));
+}
+
+/* %m */
+static char *
+hdr_number (struct header_call_args *args, void *data)
+{
+  char buf[UINTMAX_STRSIZE_BOUND];
+  return header_buf_string (args, umaxtostr (args->mspec->msg_part[0], buf));
+}
+
+/* %o */
+static char *
+hdr_size (struct header_call_args *args, void *data)
+{
+  size_t m_size;
+  char buf[UINTMAX_STRSIZE_BOUND];
+  mu_message_size (args->msg, &m_size);
+  
+  return header_buf_string (args, umaxtostr (m_size, buf));
+}
+
+/* %s */
+static char *
+hdr_subject (struct header_call_args *args, void *data)
+{
+  mu_header_t hdr;
+  char *subj = NULL;
+  
+  mu_message_get_header (args->msg, &hdr);
   mu_header_aget_value_unfold (hdr, MU_HEADER_SUBJECT, &subj);
   util_rfc2047_decode (&subj);
   
-  mu_message_get_attribute (msg, &attr);
+  header_buf_string (args, subj);
+  free (subj);
+  return args->buf;
+}
+
+/* %S */
+static char *
+hdr_q_subject (struct header_call_args *args, void *data)
+{
+  mu_header_t hdr;
+  char *subj = NULL;
+  size_t len;
+
+  if (args->cols_rest <= 2)
+    return "\"\"";
   
-  if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_MBOXED))
-    cflag = 'M';
-  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_PRESERVED))
-    cflag = 'P';
-  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_SAVED))
-    cflag = '*';
-  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_TAGGED))
-    cflag = 'T';
-  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_SHOWN))
-    cflag = 'R';
-  else if (mu_attribute_is_recent (attr))
-    cflag = 'N';
-  else if (!mu_attribute_is_read (attr))
-    cflag = 'U';
-  else
-    cflag = ' ';
+  mu_message_get_header (args->msg, &hdr);
+  mu_header_aget_value_unfold (hdr, MU_HEADER_SUBJECT, &subj);
+  if (!subj)
+    return "";
+  util_rfc2047_decode (&subj);
 
-  date[0] = 0;
-  if (mailvar_get (NULL, "datefield", mailvar_type_boolean, 0) == 0
-      && mu_header_get_value (hdr, MU_HEADER_DATE, date, sizeof (date), NULL) 
== 0)
+  len = strlen (subj);
+  if (len + 2 > args->cols_rest)
+    len = args->cols_rest - 2;
+  header_ensure_space (args, len + 3);
+  args->buf[0] = '"';
+  memcpy (args->buf + 1, subj, len);
+  args->buf[len+1] = '"';
+  args->buf[len+2] = 0;
+  free (subj);
+  return args->buf;
+}
+
+
+static struct header_segm *
+new_header_segment (int align, size_t width,
+                   void *data,
+                   char *(*get) (struct header_call_args *, void *))
+{
+  struct header_segm *seg = xmalloc (sizeof (*seg));
+  seg->next = NULL;
+  seg->align = align;
+  seg->width = width;
+  seg->data = data;
+  seg->get = get;
+  return seg;
+}
+
+struct header_segm *
+compile_headline (const char *str)
+{
+  struct header_segm *head = NULL, *tail = NULL;
+  char *text;
+  int align;
+  size_t width;
+  
+#define ALIGN_STRING (align == ALIGN_UNDEF ? ALIGN_LEFT : ALIGN_RIGHT)
+#define ALIGN_NUMBER (align == ALIGN_UNDEF ? ALIGN_RIGHT : ALIGN_LEFT)
+#define ATTACH(p)                              \
+  do                                           \
+    {                                          \
+      if (!head)                               \
+       head = p;                               \
+      else                                     \
+       tail->next = p;                         \
+      tail = p;                                        \
+    }                                          \
+  while (0)
+      
+  while (*str)
     {
-      time_t t;
-      if (mu_parse_date (date, &t, NULL) == 0)
+      struct header_segm *seg;
+      size_t len;
+      char *p = strchr (str, '%');
+      if (!p)
+       len = strlen (str);
+      else
+       len = p - str;
+      if (len)
        {
-         strftime (date, sizeof(date), "%a %b %e %H:%M", localtime (&t));
+         text = xmalloc (len + 1);
+         memcpy (text, str, len);
+         text[len] = 0;
+         seg = new_header_segment (ALIGN_LEFT, 0, text, hdr_text);
+         ATTACH (seg);
+       }
+      if (!p)
+       break;
+
+      str = ++p;
+
+      if (*str == '-')
+       {
+         str++;
+         align = ALIGN_LEFT;
+       }
+      else if (*str == '+')
+       {
+         str++;
+         align = ALIGN_RIGHT;
        }
       else
-       date[0] = 0;
-    }
+       align = ALIGN_UNDEF;
+      
+      if (mu_isdigit (*str))
+       width = strtoul (str, (char**)&str, 10);
+      else
+       width = 0;
 
-  if (date[0] == 0)
-    {
-      const char *p;
-      struct tm tm;
-      mu_timezone tz;
+      switch (*str++)
+       {
+       case '%':
+         seg = new_header_segment (ALIGN_LEFT, 0, xstrdup ("%"), hdr_text);
+         break;
+         
+       case 'a': /* Message attributes. */
+         seg = new_header_segment (ALIGN_STRING, width, NULL, hdr_attr);
+         break;
 
-      mu_message_get_envelope (msg, &env);
-      if (mu_envelope_sget_date (env, &p) == 0
-          && mu_parse_ctime_date_time (&p, &tm, &tz) == 0)
-       strftime (date, sizeof(date), "%a %b %e %H:%M", &tm);
+         /* FIXME: %c    The score of the message. */
+         
+       case 'd': /* Message date */
+         seg = new_header_segment (ALIGN_STRING, width, NULL, hdr_date);
+         break;
+         
+         /* FIXME: %e    The indenting level in threaded mode. */
+         
+       case 'f': /* Message sender */
+         seg = new_header_segment (ALIGN_STRING, width, NULL, hdr_from);
+         break;
+
+         /* FIXME: %i    The message thread structure. */
+         
+       case 'l': /* The number of lines of the message */
+         seg = new_header_segment (ALIGN_NUMBER, width, NULL, hdr_lines);
+         break;
+         
+       case 'm': /* Message number */
+         seg = new_header_segment (ALIGN_NUMBER, width, NULL, hdr_number);
+         break;
+         
+       case 'o': /* The number of octets (bytes) in the message */
+         seg = new_header_segment (ALIGN_NUMBER, width, NULL, hdr_size);
+         break;
+         
+       case 's': /* Message subject (if any) */
+         seg = new_header_segment (ALIGN_STRING, width, NULL, hdr_subject);
+         break;
+
+       case 'S': /* Message subject (if any) in double quotes */
+         seg = new_header_segment (ALIGN_STRING, width, NULL, hdr_q_subject);
+         break;
+         
+         /* FIXME: %t    The position in threaded/sorted order. */
+         
+       case '>': /* A `>' for the current message, otherwise ` ' */
+         seg = new_header_segment (ALIGN_STRING, width, xstrdup (">"), 
hdr_cur);
+         break;
+         
+       case '<': /* A `<' for the current message, otherwise ` ' */
+         seg = new_header_segment (ALIGN_STRING, width, xstrdup ("<"), 
hdr_cur);
+         break;
+
+       default:
+         mu_error (_("unknown escape: %%%c"), str[-1]);
+         len = str - p;
+         text = xmalloc (len);
+         memcpy (text, p, len-1);
+         text[len-1] = 0;
+         seg = new_header_segment (ALIGN_STRING, width, text, hdr_text);
+       }
+      ATTACH (seg);
     }
-  
-  mu_message_size (msg, &m_size);
-  mu_message_lines (msg, &m_lines);
-  
-  snprintf (st, sizeof (st), "%3d/%-5d", m_lines, m_size);
-  
-  /* The "From" field will take a third of the screen.
-     Subject will take the rest.
-     FIXME: This is not quite correct that we use fixed sizes
-     18, 16 for the other fields.
-  */
-  froml = cols / 3;
-  subjl = cols - froml - strlen (st) - 16;
-  
-  fromp = from ? from : "";
-  subjp = subj ? subj : fromp;
-  fprintf (ofile, "%c%c%4d %-18.18s %-16.16s %s %.*s\n",
-          is_current_message (mspec->msg_part[0]) ? '>' : ' ', cflag,
-          mspec->msg_part[0],
-          fromp, date, st, (subjl < 0) ? 0 : subjl, subjp);
-  
-  free (from);
-  free (subj);
+  return head;
+#undef ALIGN_STRING
+#undef ALIGN_NUMBER
+#undef ATTACH
+}
+
+/* FIXME: Should it be part of struct mailvar_variable for "headline"? */
+static struct header_segm *mail_header_line;
+
+void
+mail_compile_headline (struct mailvar_variable *var)
+{
+  free_headline (mail_header_line);
+  mail_header_line = compile_headline (var->value.string);
+}
+
+
+/*
+ * f[rom] [msglist]
+ */
 
+int
+mail_from0 (msgset_t *mspec, mu_message_t msg, void *data)
+{
+  format_headline (mail_header_line, mspec, msg);
   return 0;
 }
 
 int
 mail_from (int argc, char **argv)
 {
-  return util_foreach_msg (argc, argv, MSG_NODELETED|MSG_SILENT, mail_from0, 
NULL);
+  return util_foreach_msg (argc, argv, MSG_NODELETED|MSG_SILENT,
+                          mail_from0, NULL);
 }
 
diff --git a/mail/mail.c b/mail/mail.c
index d633b03..805b0e3 100644
--- a/mail/mail.c
+++ b/mail/mail.c
@@ -287,6 +287,7 @@ static char *default_setup[] = {
   "set recursivealiases",
   "set noinplacealiases",
   "set fromfield",
+  "set headline=\"%>%a%4m %18f %16d %3l/%-5o %s\"",
   
   /* Start in mail reading mode */
   "setq mode=read",
@@ -364,7 +365,7 @@ main (int argc, char **argv)
 
   /* set defaults for execution */
   for (i = 0; i < sizeof (default_setup)/sizeof (default_setup[0]); i++)
-    util_do_command (default_setup[i]);
+    util_do_command ("%s", default_setup[i]);
   util_do_command ("set screen=%d", util_getlines ());
   util_do_command ("set columns=%d", util_getcols ());
   
diff --git a/mail/mail.h b/mail/mail.h
index a600d46..7eeb600 100644
--- a/mail/mail.h
+++ b/mail/mail.h
@@ -45,11 +45,7 @@
 #endif
 #include <sys/wait.h>
 #include <sys/types.h>
-#ifdef HAVE_STDARG_H
-# include <stdarg.h>
-#else
-# include <varargs.h>
-#endif
+#include <stdarg.h>
 #include <signal.h>
 
 #include <confpaths.h>
@@ -200,6 +196,8 @@ extern int mail_folders (int argc, char **argv);
 extern int mail_followup (int argc, char **argv);
 extern int mail_from (int argc, char **argv);
 extern int mail_from0 (msgset_t *mspec, mu_message_t msg, void *data);
+extern void mail_compile_headline (struct mailvar_variable *var);
+
 extern int mail_headers (int argc, char **argv);
 extern int mail_hold (int argc, char **argv);
 extern int mail_help (int argc, char **argv);
diff --git a/mail/mailvar.c b/mail/mailvar.c
index d101ec8..e5cc5ce 100644
--- a/mail/mailvar.c
+++ b/mail/mailvar.c
@@ -130,6 +130,10 @@ struct mailvar_symbol mailvar_tab[] =
     { { "header", },
       MAILVAR_TYPEMASK (mailvar_type_boolean),
       N_("run the `headers' command after entering interactive mode") },
+    { { "headline", },
+      MAILVAR_TYPEMASK (mailvar_type_string),
+      N_("format string to use for the header summary"),
+      mail_compile_headline },
     { { "hold", },
       MAILVAR_TYPEMASK (mailvar_type_boolean),
       N_("hold the read or saved messages in the system mailbox") },
diff --git a/mail/util.c b/mail/util.c
index 95ec9b6..2f485ca 100644
--- a/mail/util.c
+++ b/mail/util.c
@@ -468,7 +468,7 @@ util_get_homedir ()
 char *
 util_fullpath (const char *inpath)
 {
-  return mu_tilde_expansion(inpath, "/", NULL);
+  return mu_tilde_expansion (inpath, "/", NULL);
 }
 
 char *
@@ -661,7 +661,7 @@ util_slist_to_string (mu_list_t list, const char *delim)
 }
 
 void
-util_strcat(char **dest, const char *str)
+util_strcat (char **dest, const char *str)
 {
   if (!*dest)
     *dest = strdup (str);
@@ -754,26 +754,13 @@ util_save_outgoing (mu_message_t msg, char *savefile)
     }
 }
 
-#ifdef HAVE_STDARG_H
 void
 util_error (const char *format, ...)
-#else
-void
-util_error (va_alist)
-     va_dcl
-#endif
 {
   va_list ap;
 
-#ifdef HAVE_STDARG_H
-  va_start(ap, format);
-#else
-  char *format;
-
-  va_start (ap);
-  format = va_arg (ap, char *);
-#endif
-
+  va_start (ap, format);
+  
   vfprintf (stderr, format, ap);
   fprintf (stderr, "\n");
 


hooks/post-receive
-- 
GNU Mailutils


_______________________________________________
Commit-mailutils mailing list
Commit-mailutils@gnu.org
http://lists.gnu.org/mailman/listinfo/commit-mailutils

Reply via email to