diff options
-rw-r--r-- | commands.c | 2 | ||||
-rw-r--r-- | curs_lib.c | 40 | ||||
-rw-r--r-- | doc/manual.xml.head | 66 | ||||
-rw-r--r-- | init.h | 16 | ||||
-rw-r--r-- | lib.h | 7 | ||||
-rw-r--r-- | menu.c | 2 | ||||
-rw-r--r-- | muttlib.c | 43 | ||||
-rw-r--r-- | query.c | 2 | ||||
-rw-r--r-- | recvcmd.c | 2 |
9 files changed, 165 insertions, 15 deletions
@@ -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), "...?"); } @@ -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">$index_format"</link>, +<link linkend="pager-format">$pager_format"</link>, +<link linkend="status-format">$status_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">$index_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>$index_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 (``_'') 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"> @@ -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 @@ -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) @@ -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); } @@ -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; @@ -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", @@ -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), "...?"); } |