NeoMutt  2025-12-11-1039-g550ac6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
format.c
Go to the documentation of this file.
1
22
28
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 "gui/lib.h"
37#include "format.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 const size_t len = buf_len(buf);
55 if (len >= max_cols)
56 return;
57
58 const size_t pad = max_cols - len;
59 buf_alloc(buf, max_cols + 1);
60
61 switch (justify)
62 {
63 case JUSTIFY_LEFT:
64 {
65 memset(buf->dptr, pad_char, pad);
66 break;
67 }
68
69 case JUSTIFY_CENTER:
70 {
71 if (pad > 1)
72 {
73 memmove(buf->data + (pad / 2), buf->data, len + 1);
74 memset(buf->data, pad_char, pad / 2);
75 }
76 memset(buf->data + len + (pad / 2), pad_char, (pad + 1) / 2);
77 break;
78 }
79
80 case JUSTIFY_RIGHT:
81 {
82 memmove(buf->data + pad, buf->data, len + 1);
83 memset(buf->data, pad_char, pad);
84 break;
85 }
86 }
87
88 buf->dptr += pad;
89 buf->dptr[0] = '\0';
90}
91
107int format_string(struct Buffer *buf, int min_cols, int max_cols, enum FormatJustify justify,
108 char pad_char, const char *str, size_t n, bool arboreal)
109{
110 wchar_t wc = 0;
111 int w = 0;
112 size_t k = 0;
113 char scratch[MB_LEN_MAX] = { 0 };
114 mbstate_t mbstate1 = { 0 };
115 mbstate_t mbstate2 = { 0 };
116 bool escaped = false;
117 int used_cols = 0;
118
119 for (; (n > 0) && (k = mbrtowc(&wc, str, n, &mbstate1)); str += k, n -= k)
120 {
121 if ((k == ICONV_ILLEGAL_SEQ) || (k == ICONV_BUF_TOO_SMALL))
122 {
123 if ((k == ICONV_ILLEGAL_SEQ) && (errno == EILSEQ))
124 memset(&mbstate1, 0, sizeof(mbstate1));
125
126 k = (k == ICONV_ILLEGAL_SEQ) ? 1 : n;
127 wc = ReplacementChar;
128 }
129
130 // How many screen cells will the character require?
131 if (escaped)
132 {
133 escaped = false;
134 w = 0;
135 }
136 else if (arboreal && (wc == MUTT_SPECIAL_INDEX))
137 {
138 escaped = true;
139 w = 0;
140 }
141 else if (arboreal && (wc < MUTT_TREE_MAX))
142 {
143 w = 1; /* hack */
144 }
145 else if (iswspace(wc))
146 {
147 w = MAX(1, wcwidth(wc));
148 }
149 else
150 {
151#ifdef HAVE_ISWBLANK
152 if (iswblank(wc))
153 wc = ' '; // LCOV_EXCL_LINE
154 else
155#endif
156 if (!IsWPrint(wc))
157 wc = '?';
158 w = wcwidth(wc);
159 }
160
161 // It'll require _some_ space
162 if (w >= 0)
163 {
164 if (w > max_cols)
165 continue;
166 size_t k2 = wcrtomb(scratch, wc, &mbstate2);
167 if (k2 == ICONV_ILLEGAL_SEQ)
168 continue; // LCOV_EXCL_LINE
169
170 used_cols += w;
171
172 min_cols -= w;
173 max_cols -= w;
174 buf_addstr_n(buf, scratch, k2);
175 }
176 }
177
178 // How much space is left?
179 w = min_cols;
180 if (w > 0)
181 {
182 used_cols += w;
183 }
184
185 if (w > 0)
186 buf_justify(buf, justify, buf_len(buf) + w, pad_char);
187
188 return used_cols;
189}
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:109
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:497
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition buffer.c:342
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:107
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
Convenience wrapper for the gui headers.
@ MUTT_TREE_MAX
Definition thread.h:70
@ MUTT_SPECIAL_INDEX
Colour indicator.
Definition thread.h:72
#define IsWPrint(wc)
Definition mbyte.h:40
#define MAX(a, b)
Return the maximum of two values.
Definition memory.h:38
wchar_t ReplacementChar
When a Unicode character can't be displayed, use this instead.
Definition charset.c:62
#define EILSEQ
Definition charset.c:56
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition charset.h:116
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition charset.h:114
Convenience wrapper for the library headers.
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