NeoMutt  2024-11-14-34-g5aaf0d
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 <string.h>
34#include <wchar.h>
35#include "mutt/lib.h"
36#include "format.h"
37#include "mutt_thread.h"
38#ifdef HAVE_ISWBLANK
39#include <wctype.h>
40#endif
41
49void buf_justify(struct Buffer *buf, enum FormatJustify justify, size_t max_cols, char pad_char)
50{
51 if (!buf || (pad_char == '\0'))
52 return;
53
54 size_t len = buf_len(buf);
55 if (len >= max_cols)
56 return;
57
58 buf_alloc(buf, len + max_cols);
59
60 max_cols -= len;
61
62 switch (justify)
63 {
64 case JUSTIFY_LEFT:
65 {
66 memset(buf->dptr, pad_char, max_cols);
67 break;
68 }
69
70 case JUSTIFY_CENTER:
71 {
72 if (max_cols > 1)
73 {
74 memmove(buf->data + (max_cols / 2), buf->data, len);
75 memset(buf->data, pad_char, max_cols / 2);
76 }
77 memset(buf->data + len + (max_cols / 2), pad_char, (max_cols + 1) / 2);
78 break;
79 }
80
81 case JUSTIFY_RIGHT:
82 {
83 memmove(buf->data + max_cols, buf->data, len);
84 memset(buf->data, pad_char, max_cols);
85 break;
86 }
87 }
88
89 buf->dptr += max_cols;
90 buf->dptr[0] = '\0';
91}
92
108int format_string(struct Buffer *buf, int min_cols, int max_cols, enum FormatJustify justify,
109 char pad_char, const char *str, size_t n, bool arboreal)
110{
111 wchar_t wc = 0;
112 int w = 0;
113 size_t k = 0;
114 char scratch[MB_LEN_MAX] = { 0 };
115 mbstate_t mbstate1 = { 0 };
116 mbstate_t mbstate2 = { 0 };
117 bool escaped = false;
118 int used_cols = 0;
119
120 for (; (n > 0) && (k = mbrtowc(&wc, str, n, &mbstate1)); str += k, n -= k)
121 {
122 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
123 {
124 if ((k == ICONV_ILLEGAL_SEQ) && (errno == EILSEQ))
125 memset(&mbstate1, 0, sizeof(mbstate1));
126
127 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : n;
128 wc = ReplacementChar;
129 }
130
131 // How many screen cells will the character require?
132 if (escaped)
133 {
134 escaped = false;
135 w = 0;
136 }
137 else if (arboreal && (wc == MUTT_SPECIAL_INDEX))
138 {
139 escaped = true;
140 w = 0;
141 }
142 else if (arboreal && (wc < MUTT_TREE_MAX))
143 {
144 w = 1; /* hack */
145 }
146 else if (iswspace(wc))
147 {
148 w = 1;
149 }
150 else
151 {
152#ifdef HAVE_ISWBLANK
153 if (iswblank(wc))
154 wc = ' '; // LCOV_EXCL_LINE
155 else
156#endif
157 if (!IsWPrint(wc))
158 wc = '?';
159 w = wcwidth(wc);
160 }
161
162 // It'll require _some_ space
163 if (w >= 0)
164 {
165 if (w > max_cols)
166 continue;
167 size_t k2 = wcrtomb(scratch, wc, &mbstate2);
168 if (k2 == ICONV_ILLEGAL_SEQ)
169 continue; // LCOV_EXCL_LINE
170
171 used_cols += w;
172
173 min_cols -= w;
174 max_cols -= w;
175 buf_addstr_n(buf, scratch, k2);
176 }
177 }
178
179 // How much space is left?
180 w = min_cols;
181 if (w > 0)
182 {
183 used_cols += w;
184 }
185
186 if (w > 0)
187 buf_justify(buf, justify, buf_len(buf) + w, pad_char);
188
189 return used_cols;
190}
size_t buf_addstr_n(struct Buffer *buf, const char *s, size_t len)
Add a string to a Buffer, expanding it if necessary.
Definition: buffer.c:96
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:491
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:337
void buf_justify(struct Buffer *buf, enum FormatJustify justify, size_t max_cols, char pad_char)
Justify a string.
Definition: format.c:49
int format_string(struct Buffer *buf, int min_cols, int max_cols, enum FormatJustify justify, char pad_char, const char *str, size_t n, bool arboreal)
Format a string, like snprintf()
Definition: format.c:108
Simple string formatting.
FormatJustify
Alignment for format_string()
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:98
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition: charset.h:96
Convenience wrapper for the library headers.
Create/manipulate threading in emails.
@ MUTT_TREE_MAX
Definition: mutt_thread.h:71
@ MUTT_SPECIAL_INDEX
Colour indicator.
Definition: mutt_thread.h:73
String manipulation buffer.
Definition: buffer.h:36
char * dptr
Current read/write position.
Definition: buffer.h:38
char * data
Pointer to data.
Definition: buffer.h:37