(h ? _("Bounce message to %s") : _("Bounce messages to %s")),
buf);
- if (mutt_strwidth (prompt) > COLS - extra_space) {
+ if (m_strwidth(prompt) > COLS - extra_space) {
mutt_format_string(prompt, sizeof(prompt), 0, COLS - extra_space, 0, 0,
prompt, sizeof(prompt), 0);
m_strcat(prompt, sizeof(prompt), "...?");
/* }}} */
+typedef union __attribute__((transparent_union)) anytype {
+ void *ptr;
+ long li;
+ int i;
+ short si;
+} anytype;
+
#include "mem.h"
#include "str.h"
#include "rx.h"
#include "url.h"
-typedef union __attribute__((transparent_union)) anytype {
- void *ptr;
- long li;
- int i;
- short si;
-} anytype;
-
#endif
return 0;
}
+/** \brief Retutnrs the on-screen width of the string, multi-byte aware.
+ *
+ * The function assumes that at rendering time, any non printable character or
+ * any unrecognized multibyte sequence will be replaced with a 1-cell wide
+ * char.
+ *
+ * \param[in] s the string;
+ * \return the width of \c s.
+ */
+ssize_t m_strwidth (const char *s)
+{
+ const ssize_t len = m_strlen(s);
+ mbstate_t mbstate;
+ ssize_t w = 0, pos = 0;
+
+ p_clear(&mbstate, 1);
+
+ while (pos < len) {
+ wchar_t wc;
+ ssize_t nb;
+
+ nb = mbrtowc(&wc, s + pos, len - pos, &mbstate);
+ switch (nb) {
+ case -2:
+ return w + 1;
+
+ case -1: /* assume we will replace that char with a ? later */
+ wc = '?';
+ default:
+ w += iswprint(wc) ? wcwidth(wc) : 1;
+ pos -= nb;
+ }
+ }
+
+ return w;
+}
+
+ssize_t m_strformat(char *dst, ssize_t dlen, int width, const char *fmt,
+ format_t *callback, anytype cdata, format_flag flags)
+{
+ ssize_t pos = flags & M_FORMAT_ARROWCURSOR ? 3 : 0;
+
+ m_strpad(dst, dlen, '\0', pos + 1);
+ if (!fmt)
+ return pos;
+
+ while (*fmt) {
+ int ch;
+
+ if (*fmt == '%') {
+ char ifstr[STRING], elstr[STRING], prefix[STRING];
+
+ *ifstr = *elstr = *prefix = '\0';
+
+ if (*++fmt == '%') {
+ pos += m_strputc(dst + pos, dlen - pos, *fmt++);
+ continue;
+ }
+
+ if (*fmt == '?') {
+ flags |= M_FORMAT_OPTIONAL;
+ fmt++;
+ } else {
+ ssize_t pfxlen;
+ flags &= ~M_FORMAT_OPTIONAL;
+
+ /* eat the format string */
+ pfxlen = strspn(fmt, "0123456789.-");
+ m_strncpy(prefix, sizeof(prefix), fmt, pfxlen);
+ fmt += pfxlen;
+ }
+
+ /* save the character to switch on */
+ if (!(ch = *fmt++))
+ break;
+
+ if (flags & M_FORMAT_OPTIONAL) {
+ ssize_t iflen;
+ const char *p;
+
+ if (*fmt++ != '?')
+ break; /* bad format */
+
+ /* eat the `if' part of the string */
+ iflen = strcspn(fmt, "?&");
+ m_strncpy(ifstr, ssizeof(ifstr), fmt, iflen);
+ fmt += iflen;
+
+ /* eat the `else' part of the string (optional) */
+ if (*fmt == '&')
+ fmt++; /* skip the & */
+
+ p = m_strchrnul(fmt, '?');
+ m_strncpy(elstr, ssizeof(elstr), fmt, p - fmt);
+ fmt = p;
+
+ if (!*fmt++) /* move past the trailing `?' */
+ break; /* bad format */
+ }
+
+ switch (ch) {
+ char lower, nodots, buf[LONG_STRING];
+
+ case '>': /* right justify to EOL */
+ width -= m_strwidth(dst);
+
+ ch = *fmt++; /* pad char */
+
+ if (width > 0) {
+ m_strformat(buf, sizeof(buf), 0, fmt, callback, cdata, flags);
+ width -= m_strwidth(buf);
+ pos += m_strpad(dst + pos, dlen - pos, ch, width);
+ pos += m_strcpy(dst + pos, dlen - pos, buf);
+ }
+ return pos; /* skip rest of input */
+
+ case '|': /* pad to EOL */
+ width -= m_strwidth(dst);
+ return pos + m_strpad(dst + pos, dlen - pos, *fmt, width);
+
+ default:
+ lower = nodots = 0;
+
+ while (ch == '_' || ch == ':') {
+ lower |= ch == '_';
+ nodots |= ch == ':';
+ ch = *fmt++;
+ }
+
+ /* use callback function to handle this case */
+ fmt = callback(buf, sizeof (buf), ch, fmt, prefix,
+ ifstr, elstr, cdata, flags);
+
+ if (lower)
+ m_strtolower(buf);
+
+ if (nodots) {
+ char *p;
+
+ for (p = buf; *p; p++) {
+ if (*p == '.')
+ *p = '_';
+ }
+ }
+
+ pos += m_strcpy(dst + pos, dlen - pos, buf);
+ break;
+ }
+ continue;
+ }
+
+ if (*fmt == '\\') {
+ if (!*++fmt)
+ break;
+ switch ((ch = *fmt++)) {
+ case 'n': pos += m_strputc(dst + pos, dlen - pos, '\n'); break;
+ case 't': pos += m_strputc(dst + pos, dlen - pos, '\t'); break;
+ case 'r': pos += m_strputc(dst + pos, dlen - pos, '\r'); break;
+ case 'f': pos += m_strputc(dst + pos, dlen - pos, '\f'); break;
+ case 'v': pos += m_strputc(dst + pos, dlen - pos, '\v'); break;
+ default: pos += m_strputc(dst + pos, dlen - pos, ch); break;
+ }
+ } else {
+ ssize_t len = strcspn(fmt, "%\\");
+
+ pos += m_strncpy(dst + pos, dlen - pos, fmt, len);
+ fmt += len;
+ }
+ }
+
+ return pos;
+}
+
/*@}*/
return 0;
}
+ssize_t m_strwidth(const char *s);
+
/****************************************************************************/
/* comparisons */
/****************************************************************************/
return dlen + m_strncpy(dst + dlen, n - dlen, src, l);
}
+/* flags for m_strformat() */
+typedef enum {
+ M_FORMAT_FORCESUBJ = (1 << 0), /* print the subject even if unchanged */
+ M_FORMAT_TREE = (1 << 1), /* draw the thread tree */
+ M_FORMAT_MAKEPRINT = (1 << 2), /* make sure that all chars are printable */
+ M_FORMAT_OPTIONAL = (1 << 3),
+ M_FORMAT_STAT_FILE = (1 << 4), /* used by mutt_attach_fmt */
+ M_FORMAT_ARROWCURSOR = (1 << 5), /* reserve space for arrow_cursor */
+ M_FORMAT_INDEX = (1 << 6) /* this is a main index entry */
+} format_flag;
+
+typedef const char *
+format_t(char *, ssize_t, char, const char *,
+ const char *, const char *, const char *, anytype, format_flag);
+
+ssize_t m_strformat(char *, ssize_t, int, const char *,
+ format_t *, anytype, format_flag);
+
/****************************************************************************/
/* parsing related */
/****************************************************************************/
addch (' ');
}
-/*
- * mutt_strwidth is like m_strlenexcept that it returns the width
- * refering to the number of characters cells.
- */
-
-int mutt_strwidth (const char *s)
-{
- wchar_t wc;
- int w;
- ssize_t k, n;
- mbstate_t mbstate;
-
- if (!s)
- return 0;
-
- n = m_strlen(s);
-
- p_clear(&mbstate, 1);
- for (w = 0; n && (k = mbrtowc (&wc, s, n, &mbstate)); s += k, n -= k) {
- if (k == -1 || k == -2) {
- k = (k == -1) ? 1 : n;
- wc = CharsetReplacement;
- }
- if (!iswprint(wc))
- wc = '?';
- w += wcwidth (wc);
- }
- return w;
-}
int mutt_parse_mono (BUFFER *, BUFFER *, unsigned long, BUFFER *);
int mutt_parse_unmono (BUFFER *, BUFFER *, unsigned long, BUFFER *);
int mutt_query_complete (char *, ssize_t);
-int mutt_strwidth (const char *);
int mutt_user_is_recipient (HEADER *);
int mutt_yesorno (const char *, int);
void mutt_set_header_color (CONTEXT *, HEADER *);
cur = cur->next;
}
- l = mutt_strwidth (p);
+ l = m_strwidth(p);
if (l > SecondColumn)
SecondColumn = l;
cur->addr = rfc822_parse_adrlist (cur->addr, p);
p = strtok (NULL, "\t\n");
if (p) {
- l = mutt_strwidth (p);
+ l = m_strwidth(p);
if (l > FirstColumn)
FirstColumn = l;
cur->name = m_strdup(p);
int op; /* function op */
} event_t;
-/* flags for m_strformat() */
-typedef enum {
- M_FORMAT_FORCESUBJ = (1 << 0), /* print the subject even if unchanged */
- M_FORMAT_TREE = (1 << 1), /* draw the thread tree */
- M_FORMAT_MAKEPRINT = (1 << 2), /* make sure that all chars are printable */
- M_FORMAT_OPTIONAL = (1 << 3),
- M_FORMAT_STAT_FILE = (1 << 4), /* used by mutt_attach_fmt */
- M_FORMAT_ARROWCURSOR = (1 << 5), /* reserve space for arrow_cursor */
- M_FORMAT_INDEX = (1 << 6) /* this is a main index entry */
-} format_flag;
-
/* types for mutt_add_hook() */
#define M_FOLDERHOOK 1
#define M_MBOXHOOK (1<<1)
}
}
-ssize_t m_strformat(char *dst, ssize_t dlen, int width, const char *fmt,
- format_t *callback, anytype cdata, format_flag flags)
-{
- ssize_t pos = flags & M_FORMAT_ARROWCURSOR ? 3 : 0;
-
- m_strpad(dst, dlen, '\0', pos + 1);
- if (!fmt)
- return pos;
-
- while (*fmt) {
- int ch;
-
- if (*fmt == '%') {
- char ifstr[STRING], elstr[STRING], prefix[STRING];
-
- *ifstr = *elstr = *prefix = '\0';
-
- if (*++fmt == '%') {
- pos += m_strputc(dst + pos, dlen - pos, *fmt++);
- continue;
- }
-
- if (*fmt == '?') {
- flags |= M_FORMAT_OPTIONAL;
- fmt++;
- } else {
- ssize_t pfxlen;
- flags &= ~M_FORMAT_OPTIONAL;
-
- /* eat the format string */
- pfxlen = strspn(fmt, "0123456789.-");
- m_strncpy(prefix, sizeof(prefix), fmt, pfxlen);
- fmt += pfxlen;
- }
-
- /* save the character to switch on */
- if (!(ch = *fmt++))
- break;
-
- if (flags & M_FORMAT_OPTIONAL) {
- ssize_t iflen;
- const char *p;
-
- if (*fmt++ != '?')
- break; /* bad format */
-
- /* eat the `if' part of the string */
- iflen = strcspn(fmt, "?&");
- m_strncpy(ifstr, ssizeof(ifstr), fmt, iflen);
- fmt += iflen;
-
- /* eat the `else' part of the string (optional) */
- if (*fmt == '&')
- fmt++; /* skip the & */
-
- p = m_strchrnul(fmt, '?');
- m_strncpy(elstr, ssizeof(elstr), fmt, p - fmt);
- fmt = p;
-
- if (!*fmt++) /* move past the trailing `?' */
- break; /* bad format */
- }
-
- switch (ch) {
- char lower, nodots, buf[LONG_STRING];
-
- case '>': /* right justify to EOL */
- width -= mutt_strwidth(dst);
-
- ch = *fmt++; /* pad char */
-
- if (width > 0) {
- m_strformat(buf, sizeof(buf), 0, fmt, callback, cdata, flags);
- width -= mutt_strwidth(buf);
- pos += m_strpad(dst + pos, dlen - pos, ch, width);
- pos += m_strcpy(dst + pos, dlen - pos, buf);
- }
- return pos; /* skip rest of input */
-
- case '|': /* pad to EOL */
- width -= mutt_strwidth(dst);
- return pos + m_strpad(dst + pos, dlen - pos, *fmt, width);
-
- default:
- lower = nodots = 0;
-
- while (ch == '_' || ch == ':') {
- lower |= ch == '_';
- nodots |= ch == ':';
- ch = *fmt++;
- }
-
- /* use callback function to handle this case */
- fmt = callback(buf, sizeof (buf), ch, fmt, prefix,
- ifstr, elstr, cdata, flags);
-
- if (lower)
- m_strtolower(buf);
-
- if (nodots) {
- char *p;
-
- for (p = buf; *p; p++) {
- if (*p == '.')
- *p = '_';
- }
- }
-
- pos += m_strcpy(dst + pos, dlen - pos, buf);
- break;
- }
- continue;
- }
-
- if (*fmt == '\\') {
- if (!*++fmt)
- break;
- switch ((ch = *fmt++)) {
- case 'n': pos += m_strputc(dst + pos, dlen - pos, '\n'); break;
- case 't': pos += m_strputc(dst + pos, dlen - pos, '\t'); break;
- case 'r': pos += m_strputc(dst + pos, dlen - pos, '\r'); break;
- case 'f': pos += m_strputc(dst + pos, dlen - pos, '\f'); break;
- case 'v': pos += m_strputc(dst + pos, dlen - pos, '\v'); break;
- default: pos += m_strputc(dst + pos, dlen - pos, ch); break;
- }
- } else {
- ssize_t len = strcspn(fmt, "%\\");
-
- pos += m_strncpy(dst + pos, dlen - pos, fmt, len);
- fmt += len;
- }
- }
-
- return pos;
-}
-
/* returns 0 if OK to proceed, -1 to abort, 1 to retry */
int mutt_save_confirm (const char *s, struct stat *st)
{
#define MoreArgs(p) (*p->dptr && *p->dptr != ';' && *p->dptr != '#')
-typedef const char *
-format_t(char *, ssize_t, char, const char *,
- const char *, const char *, const char *, anytype, format_flag);
-
-ssize_t m_strformat(char *, ssize_t, int, const char *,
- format_t *, anytype, format_flag);
-
void set_quadoption (int, int);
int query_quadoption (int, const char *);
int quadoption (int);
(p ? _("Bounce message to %s") : _("Bounce messages to %s")),
buf);
- if (mutt_strwidth (prompt) > COLS - extra_space) {
+ if (m_strwidth(prompt) > COLS - extra_space) {
mutt_format_string (prompt, sizeof (prompt) - 4,
0, COLS - extra_space, 0, 0,
prompt, sizeof (prompt), 0);