summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--commands.c2
-rw-r--r--curs_lib.c40
-rw-r--r--doc/manual.xml.head66
-rw-r--r--init.h16
-rw-r--r--lib.h7
-rw-r--r--menu.c2
-rw-r--r--muttlib.c43
-rw-r--r--query.c2
-rw-r--r--recvcmd.c2
9 files changed, 165 insertions, 15 deletions
diff --git a/commands.c b/commands.c
index 2fdcb7ff..85a67b23 100644
--- a/commands.c
+++ b/commands.c
@@ -283,7 +283,7 @@ void ci_bounce_message (HEADER *h, int *redraw)
if (mutt_strwidth (prompt) > COLS - extra_space)
{
mutt_format_string (prompt, sizeof (prompt),
- 0, COLS-extra_space, 0, 0,
+ 0, COLS-extra_space, FMT_LEFT, 0,
scratch, sizeof (scratch), 0);
safe_strcat (prompt, sizeof (prompt), "...?");
}
diff --git a/curs_lib.c b/curs_lib.c
index 70fca171..e9dbaa8b 100644
--- a/curs_lib.c
+++ b/curs_lib.c
@@ -292,7 +292,7 @@ void mutt_curses_error (const char *fmt, ...)
dprint (1, (debugfile, "%s\n", scratch));
mutt_format_string (Errorbuf, sizeof (Errorbuf),
- 0, COLS-2, 0, 0, scratch, sizeof (scratch), 0);
+ 0, COLS-2, FMT_LEFT, 0, scratch, sizeof (scratch), 0);
if (!option (OPTKEEPQUIET))
{
@@ -317,7 +317,7 @@ void mutt_curses_message (const char *fmt, ...)
va_end (ap);
mutt_format_string (Errorbuf, sizeof (Errorbuf),
- 0, COLS-2, 0, 0, scratch, sizeof (scratch), 0);
+ 0, COLS-2, FMT_LEFT, 0, scratch, sizeof (scratch), 0);
if (!option (OPTKEEPQUIET))
{
@@ -641,7 +641,7 @@ int mutt_addwch (wchar_t wc)
void mutt_format_string (char *dest, size_t destlen,
int min_width, int max_width,
- int right_justify, char m_pad_char,
+ int justify, char m_pad_char,
const char *s, size_t n,
int arboreal)
{
@@ -688,7 +688,7 @@ void mutt_format_string (char *dest, size_t destlen,
w = (int)destlen < min_width ? destlen : min_width;
if (w <= 0)
*p = '\0';
- else if (right_justify)
+ else if (justify == FMT_RIGHT) /* right justify */
{
p[w] = '\0';
while (--p >= dest)
@@ -696,7 +696,27 @@ void mutt_format_string (char *dest, size_t destlen,
while (--w >= 0)
dest[w] = m_pad_char;
}
- else
+ else if (justify == FMT_CENTER) /* center */
+ {
+ char *savedp = p;
+ int half = (w+1) / 2; /* half of cushion space */
+
+ p[w] = '\0';
+
+ /* move str to center of buffer */
+ while (--p >= dest)
+ p[half] = *p;
+
+ /* fill rhs */
+ p = savedp + half;
+ while (--w >= half)
+ *p++ = m_pad_char;
+
+ /* fill lhs */
+ while (half--)
+ dest[half] = m_pad_char;
+ }
+ else /* left justify */
{
while (--w >= 0)
*p++ = m_pad_char;
@@ -718,13 +738,15 @@ static void mutt_format_s_x (char *dest,
const char *s,
int arboreal)
{
- int right_justify = 1;
+ int justify = FMT_RIGHT;
char *p;
int min_width;
int max_width = INT_MAX;
if (*prefix == '-')
- ++prefix, right_justify = 0;
+ ++prefix, justify = FMT_LEFT;
+ else if (*prefix == '=')
+ ++prefix, justify = FMT_CENTER;
min_width = strtol (prefix, &p, 10);
if (*p == '.')
{
@@ -735,7 +757,7 @@ static void mutt_format_s_x (char *dest,
}
mutt_format_string (dest, destlen, min_width, max_width,
- right_justify, ' ', s, mutt_strlen (s), arboreal);
+ justify, ' ', s, mutt_strlen (s), arboreal);
}
void mutt_format_s (char *dest,
@@ -756,7 +778,7 @@ void mutt_format_s_tree (char *dest,
/*
* mutt_paddstr (n, s) is almost equivalent to
- * mutt_format_string (bigbuf, big, n, n, 0, ' ', s, big, 0), addstr (bigbuf)
+ * mutt_format_string (bigbuf, big, n, n, FMT_LEFT, ' ', s, big, 0), addstr (bigbuf)
*/
void mutt_paddstr (int n, const char *s)
diff --git a/doc/manual.xml.head b/doc/manual.xml.head
index 09873698..b6a6d3d8 100644
--- a/doc/manual.xml.head
+++ b/doc/manual.xml.head
@@ -3259,6 +3259,72 @@ something like <literal>unhook send-hook</literal>.
</sect1>
+<sect1 id="formatstrings">
+<title>Format Strings</title>
+
+<para>
+Format strings are a general concept you'll find in several locations
+through the mutt configuration, especially in the
+<link linkend="index-format">&dollar;index&lowbar;format"</link>,
+<link linkend="pager-format">&dollar;pager&lowbar;format"</link>,
+<link linkend="status-format">&dollar;status&lowbar;format"</link>,
+and other ``*_format'' variables. These can be very straightforward,
+and it's quite possible you already know how to use them.
+</para>
+
+<para>
+The most basic format string element is a percent symbol followed
+by another character. For example, <literal>%s</literal>
+represents a message's Subject: header in the <link
+linkend="index-format">&dollar;index&lowbar;format"</link> variable. The
+``expandos'' available are documented with each format variable, but
+there are general modifiers available with all formatting expandos,
+too. Those are our concern here.
+</para>
+
+<para>
+Some of the modifers are borrowed right out of C (though you might
+know them from Perl, Python, shell, or another langugage). These are
+the [-]m.n modifiers, as in <literal>%-12.12s</literal>. As with
+such programming languages, these modifiers allow you to specify the
+minumum and maximum size of the resulting string, as well as its
+justification. If the ``-'' sign follows the percent, the string will
+be left-justified instead of right-justified. If there's a number
+immediately following that, it's the minimum amount of space the
+formatted string will occupy -- if it's naturally smaller than that, it
+will be padded out with spaces. If a decimal point and another number
+follow, that's the maximum space allowable -- the string will not be
+permitted to exceed that width, no matter its natural size. Each of
+these three elements is optional, so that all these are legal format
+strings:
+<literal>%-12s</literal>
+<literal>%4c</literal>
+<literal>%.15F</literal>
+<literal>%-12.15L</literal>
+</para>
+
+<para>
+Mutt adds some other modifiers to format strings. If you use an equals
+symbol (<literal>=</literal>) as a numeric prefix (like the minus
+above), it will force the string to be centered within its minimum
+space range. For example, <literal>%=14y</literal> will reserve 14
+characters for the %y expansion -- that's the X-Label: header, in
+<literal>&dollar;index&lowbar;format</literal>. If the expansion
+results in a string less than 14 characters, it will be centered in a
+14-character space. If the X-Label for a message were "test", that
+expansion would look like `` test ''.
+</para>
+
+<para>
+There are two very little-known modifiers that affect the way that an
+expando is replaced. If there is an underline (``&lowbar;'') character
+between any format modifiers (as above) and the expando letter, it will
+expands in all lower case. And if you use a colon (``:''), it will
+replace all decimal points with underlines.
+</para>
+
+</sect1>
+
</chapter>
<chapter id="advancedusage">
diff --git a/init.h b/init.h
index 2674bef8..73260a15 100644
--- a/init.h
+++ b/init.h
@@ -225,7 +225,9 @@ struct option_t MuttVars[] = {
** (please see the ``$attachments'' section for possible speed effects)
** .dt %>X .dd right justify the rest of the string and pad with character "X"
** .dt %|X .dd pad to the end of the line with character "X"
+ ** .dt %*X .dd soft-fill with character "X" as pad
** .de
+ ** For an explanation of `soft-fill', see the ``$$index_format'' documentation.
*/
{ "attach_sep", DT_STR, R_NONE, UL &AttachSep, UL "\n" },
/*
@@ -614,7 +616,9 @@ struct option_t MuttVars[] = {
** .dt %u .dd owner name (or numeric uid, if missing)
** .dt %>X .dd right justify the rest of the string and pad with character "X"
** .dt %|X .dd pad to the end of the line with character "X"
+ ** .dt %*X .dd soft-fill with character "X" as pad
** .de
+ ** For an explanation of `soft-fill', see the ``$$index_format'' documentation.
*/
{ "followup_to", DT_BOOL, R_NONE, OPTFOLLOWUPTO, 1 },
/*
@@ -1036,7 +1040,15 @@ struct option_t MuttVars[] = {
** function ``strftime''; a leading bang disables locales.
** .dt %>X .dd right justify the rest of the string and pad with character "X"
** .dt %|X .dd pad to the end of the line with character "X"
+ ** .dt %*X .dd soft-fill with character "X" as pad
** .de
+ ** `Soft-fill' deserves some explanation. Normal right-justification
+ ** will print everything to the left of the %>, displaying padding and
+ ** the whatever lies to the right only if there's room. By contrast,
+ ** soft-fill gives priority to the right-hand side, guaranteeing space
+ ** to display it and showing padding only if there's still room. If
+ ** necessary, soft-fill will eat text leftwards to make room for
+ ** rightward text.
** .pp
** See also: ``$$to_chars''.
*/
@@ -1352,7 +1364,7 @@ struct option_t MuttVars[] = {
** default, Mutt will display the line after the last one on the screen
** at the top of the next page (0 lines of context).
*/
- { "pager_format", DT_STR, R_PAGER, UL &PagerFmt, UL "-%Z- %C/%m: %-20.20n %s%> -- (%P)" },
+ { "pager_format", DT_STR, R_PAGER, UL &PagerFmt, UL "-%Z- %C/%m: %-20.20n %s%* -- (%P)" },
/*
** .pp
** This variable controls the format of the one-line message ``status''
@@ -2739,7 +2751,9 @@ struct option_t MuttVars[] = {
** .dt %V .dd currently active limit pattern, if any *
** .dt %>X .dd right justify the rest of the string and pad with "X"
** .dt %|X .dd pad to the end of the line with "X"
+ ** .dt %*X .dd soft-fill with character "X" as pad
** .de
+ ** For an explanation of `soft-fill', see the ``$$index_format'' documentation.
** .pp
** * = can be optionally printed if nonzero
** .pp
diff --git a/lib.h b/lib.h
index e022bb34..7ff3ebe4 100644
--- a/lib.h
+++ b/lib.h
@@ -84,6 +84,13 @@
# define MAX(a,b) ((a) < (b) ? (b) : (a))
# define MIN(a,b) ((a) < (b) ? (a) : (b))
+/* For mutt_format_string() justifications */
+/* Making left 0 and center -1 is of course completely nonsensical, but
+ * it retains compatibility for any patches that call mutt_format_string.
+ * Once patches are updated to use FMT_*, these can be made sane. */
+#define FMT_LEFT 0
+#define FMT_RIGHT 1
+#define FMT_CENTER -1
#define FOREVER while (1)
diff --git a/menu.c b/menu.c
index e8393b17..631bbed3 100644
--- a/menu.c
+++ b/menu.c
@@ -160,7 +160,7 @@ void menu_pad_string (char *s, size_t n)
int shift = option (OPTARROWCURSOR) ? 3 : 0;
int cols = COLS - shift;
- mutt_format_string (s, n, cols, cols, 0, ' ', scratch, mutt_strlen (scratch), 1);
+ mutt_format_string (s, n, cols, cols, FMT_LEFT, ' ', scratch, mutt_strlen (scratch), 1);
s[n - 1] = 0;
FREE (&scratch);
}
diff --git a/muttlib.c b/muttlib.c
index 497b5f8b..ccfc8695 100644
--- a/muttlib.c
+++ b/muttlib.c
@@ -999,6 +999,7 @@ void mutt_FormatString (char *dest, /* output buffer */
{
char prefix[SHORT_STRING], buf[LONG_STRING], *cp, *wptr = dest, ch;
char ifstring[SHORT_STRING], elsestring[SHORT_STRING];
+ char remainder[LONG_STRING];
size_t wlen, count, len, wid;
pid_t pid;
FILE *filter;
@@ -1147,7 +1148,7 @@ void mutt_FormatString (char *dest, /* output buffer */
cp = prefix;
count = 0;
while (count < sizeof (prefix) &&
- (isdigit ((unsigned char) *src) || *src == '.' || *src == '-'))
+ (isdigit ((unsigned char) *src) || *src == '.' || *src == '-' || *src == '='))
{
*cp++ = *src++;
count++;
@@ -1239,6 +1240,46 @@ void mutt_FormatString (char *dest, /* output buffer */
}
break; /* skip rest of input */
}
+ /* soft fill */
+ else if (ch == '*')
+ {
+ int space;
+
+ /* truncate to fit remainder, pad with chr. */
+ ch = *src++; /* pad chr */
+ mutt_FormatString (remainder, sizeof(remainder), 0, src, callback,
+ data, flags);
+
+ len = mutt_strlen(remainder);
+ space = COLS - wlen - len; /* bytes remaining unformatted */
+
+ /* if space > 0, this is space that needs to be filled */
+ if (space > 0)
+ {
+ memset(wptr, ch, space);
+ wptr += space;
+ wlen += space;
+ }
+
+ /* if space < 0, there's not enough room for remainder -- backtrack */
+ else if (space < 0) {
+ wptr += space;
+ wlen += space;
+ if (wlen < 0) {
+ wptr = dest;
+ wlen = 0;
+ }
+ }
+
+ /* Since remainder is already formatted, copy it *
+ * in. This prevents having to format it twice. */
+ if (len > COLS)
+ len = COLS;
+ memcpy(wptr, remainder, len);
+ wptr += len;
+ wlen += len;
+ }
+
else
{
short tolower = 0;
diff --git a/query.c b/query.c
index 1f88dbee..248394b0 100644
--- a/query.c
+++ b/query.c
@@ -204,7 +204,7 @@ static void query_entry (char *s, size_t slen, MUTTMENU *m, int num)
mutt_format_string (buf2, sizeof (buf2),
FirstColumn + 2, FirstColumn + 2,
- 0, ' ', table[num].data->name,
+ FMT_LEFT, ' ', table[num].data->name,
mutt_strlen (table[num].data->name), 0);
snprintf (s, slen, " %c %3d %s %-*.*s %s",
diff --git a/recvcmd.c b/recvcmd.c
index ff5954ee..7890cfbe 100644
--- a/recvcmd.c
+++ b/recvcmd.c
@@ -182,7 +182,7 @@ void mutt_attach_bounce (FILE * fp, HEADER * hdr,
if (mutt_strwidth (prompt) > COLS - extra_space)
{
mutt_format_string (prompt, sizeof (prompt) - 4,
- 0, COLS-extra_space, 0, 0,
+ 0, COLS-extra_space, FMT_LEFT, 0,
prompt, sizeof (prompt), 0);
safe_strcat (prompt, sizeof (prompt), "...?");
}