NeoMutt  2024-02-01-23-g345d7b
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
format.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <errno.h>
31#include <limits.h>
32#include <stdbool.h>
33#include <stdlib.h>
34#include <string.h>
35#include <wchar.h>
36#include "mutt/lib.h"
37#include "format.h"
38#include "mutt_thread.h"
39#ifdef HAVE_ISWBLANK
40#include <wctype.h>
41#endif
42
59void mutt_simple_format(char *buf, size_t buflen, int min_width, int max_width,
60 enum FormatJustify justify, char pad_char,
61 const char *s, size_t n, bool arboreal)
62{
63 wchar_t wc = 0;
64 int w;
65 size_t k;
66 char scratch[MB_LEN_MAX] = { 0 };
67 mbstate_t mbstate1 = { 0 };
68 mbstate_t mbstate2 = { 0 };
69 bool escaped = false;
70
71 buflen--;
72 char *p = buf;
73 for (; n && (k = mbrtowc(&wc, s, n, &mbstate1)); s += k, n -= k)
74 {
75 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
76 {
77 if ((k == ICONV_ILLEGAL_SEQ) && (errno == EILSEQ))
78 memset(&mbstate1, 0, sizeof(mbstate1));
79
80 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : n;
81 wc = ReplacementChar;
82 }
83 if (escaped)
84 {
85 escaped = false;
86 w = 0;
87 }
88 else if (arboreal && (wc == MUTT_SPECIAL_INDEX))
89 {
90 escaped = true;
91 w = 0;
92 }
93 else if (arboreal && (wc < MUTT_TREE_MAX))
94 {
95 w = 1; /* hack */
96 }
97 else
98 {
99#ifdef HAVE_ISWBLANK
100 if (iswblank(wc))
101 wc = ' ';
102 else
103#endif
104 if (!IsWPrint(wc))
105 wc = '?';
106 w = wcwidth(wc);
107 }
108 if (w >= 0)
109 {
110 if (w > max_width)
111 continue;
112 size_t k2 = wcrtomb(scratch, wc, &mbstate2);
113 if ((k2 == ICONV_ILLEGAL_SEQ) || (k2 > buflen))
114 continue;
115
116 min_width -= w;
117 max_width -= w;
118 strncpy(p, scratch, k2);
119 p += k2;
120 buflen -= k2;
121 }
122 }
123 w = ((int) buflen < min_width) ? buflen : min_width;
124 if (w <= 0)
125 {
126 *p = '\0';
127 }
128 else if (justify == JUSTIFY_RIGHT) /* right justify */
129 {
130 p[w] = '\0';
131 while (--p >= buf)
132 p[w] = *p;
133 while (--w >= 0)
134 buf[w] = pad_char;
135 }
136 else if (justify == JUSTIFY_CENTER) /* center */
137 {
138 char *savedp = p;
139 int half = (w + 1) / 2; /* half of cushion space */
140
141 p[w] = '\0';
142
143 /* move str to center of buffer */
144 while (--p >= buf)
145 p[half] = *p;
146
147 /* fill rhs */
148 p = savedp + half;
149 while (--w >= half)
150 *p++ = pad_char;
151
152 /* fill lhs */
153 while (half--)
154 buf[half] = pad_char;
155 }
156 else /* left justify */
157 {
158 while (--w >= 0)
159 *p++ = pad_char;
160 *p = '\0';
161 }
162}
163
178void mutt_format(char *buf, size_t buflen, const char *prec, const char *s, bool arboreal)
179{
180 enum FormatJustify justify = JUSTIFY_RIGHT;
181 char *p = NULL;
182 int min_width;
183 int max_width = INT_MAX;
184
185 if (*prec == '-')
186 {
187 prec++;
188 justify = JUSTIFY_LEFT;
189 }
190 else if (*prec == '=')
191 {
192 prec++;
193 justify = JUSTIFY_CENTER;
194 }
195 min_width = strtol(prec, &p, 10);
196 if (*p == '.')
197 {
198 prec = p + 1;
199 max_width = strtol(prec, &p, 10);
200 if (p <= prec)
201 max_width = INT_MAX;
202 }
203
204 mutt_simple_format(buf, buflen, min_width, max_width, justify, ' ', s,
205 mutt_str_len(s), arboreal);
206}
void mutt_format(char *buf, size_t buflen, const char *prec, const char *s, bool arboreal)
Format a string like snprintf()
Definition: format.c:178
void mutt_simple_format(char *buf, size_t buflen, int min_width, int max_width, enum FormatJustify justify, char pad_char, const char *s, size_t n, bool arboreal)
Format a string, like snprintf()
Definition: format.c:59
Simple string formatting.
FormatJustify
Alignment for mutt_simple_format()
Definition: format.h:33
@ JUSTIFY_RIGHT
Right justify the text.
Definition: format.h:36
@ JUSTIFY_LEFT
Left justify the text.
Definition: format.h:34
@ JUSTIFY_CENTER
Centre the text.
Definition: format.h:35
#define IsWPrint(wc)
Definition: mbyte.h:41
wchar_t ReplacementChar
When a Unicode character can't be displayed, use this instead.
Definition: charset.c:61
#define EILSEQ
Definition: charset.c:55
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition: charset.h:106
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition: charset.h:104
Convenience wrapper for the library headers.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:545
Create/manipulate threading in emails.
@ MUTT_TREE_MAX
Definition: mutt_thread.h:71
@ MUTT_SPECIAL_INDEX
Colour indicator.
Definition: mutt_thread.h:73