From: Pierre Habouzit Date: Sun, 3 Dec 2006 14:28:10 +0000 (+0100) Subject: move some string functions in lib-lib ! X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=commitdiff_plain;h=15d63145b9f11a1fa58c74abbeab7533ea2e5d21 move some string functions in lib-lib ! Signed-off-by: Pierre Habouzit --- diff --git a/commands.c b/commands.c index 6f9a0d3..3590596 100644 --- a/commands.c +++ b/commands.c @@ -251,7 +251,7 @@ void ci_bounce_message (HEADER * h, int *redraw) (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), "...?"); diff --git a/lib-lib/lib-lib.h b/lib-lib/lib-lib.h index c19a9ac..1b0769a 100644 --- a/lib-lib/lib-lib.h +++ b/lib-lib/lib-lib.h @@ -101,6 +101,13 @@ /* }}} */ +typedef union __attribute__((transparent_union)) anytype { + void *ptr; + long li; + int i; + short si; +} anytype; + #include "mem.h" #include "str.h" @@ -114,11 +121,4 @@ #include "rx.h" #include "url.h" -typedef union __attribute__((transparent_union)) anytype { - void *ptr; - long li; - int i; - short si; -} anytype; - #endif diff --git a/lib-lib/str.c b/lib-lib/str.c index f421530..53f6ebb 100644 --- a/lib-lib/str.c +++ b/lib-lib/str.c @@ -220,4 +220,177 @@ int ascii_strncasecmp(const char *a, const char *b, ssize_t n) 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; +} + /*@}*/ diff --git a/lib-lib/str.h b/lib-lib/str.h index fd80950..1beac83 100644 --- a/lib-lib/str.h +++ b/lib-lib/str.h @@ -193,6 +193,8 @@ static inline ssize_t m_strnlen(const char *s, ssize_t n) { return 0; } +ssize_t m_strwidth(const char *s); + /****************************************************************************/ /* comparisons */ /****************************************************************************/ @@ -359,6 +361,24 @@ m_strncat(char *dst, ssize_t n, const char *src, ssize_t l) { 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 */ /****************************************************************************/ diff --git a/lib-ui/curs_lib.c b/lib-ui/curs_lib.c index 510eccf..45d7b03 100644 --- a/lib-ui/curs_lib.c +++ b/lib-ui/curs_lib.c @@ -706,32 +706,3 @@ void mutt_paddstr (int n, const char *s) 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; -} diff --git a/lib-ui/curses.h b/lib-ui/curses.h index 4e1c183..074a93c 100644 --- a/lib-ui/curses.h +++ b/lib-ui/curses.h @@ -183,7 +183,6 @@ int mutt_parse_uncolor (BUFFER *, BUFFER *, unsigned long, BUFFER *); 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 *); diff --git a/lib-ui/query.c b/lib-ui/query.c index 3ba0e98..d1933f8 100644 --- a/lib-ui/query.c +++ b/lib-ui/query.c @@ -100,14 +100,14 @@ static QUERY *run_query (char *s, int quiet) 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); diff --git a/mutt.h b/mutt.h index ae133c9..520c4c9 100644 --- a/mutt.h +++ b/mutt.h @@ -30,17 +30,6 @@ typedef struct { 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) diff --git a/muttlib.c b/muttlib.c index 946a2f5..5608e34 100644 --- a/muttlib.c +++ b/muttlib.c @@ -326,142 +326,6 @@ void mutt_safe_path(char *s, ssize_t l, address_t *a) } } -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) { diff --git a/protos.h b/protos.h index 081a937..562e34a 100644 --- a/protos.h +++ b/protos.h @@ -14,13 +14,6 @@ void mutt_mktemp (char *) __attribute__((deprecated)); #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); diff --git a/recvcmd.c b/recvcmd.c index bf965a0..e4db1d8 100644 --- a/recvcmd.c +++ b/recvcmd.c @@ -163,7 +163,7 @@ void mutt_attach_bounce (FILE * fp, HEADER * hdr __attribute__ ((unused)), (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);