NeoMutt  2024-10-02-37-gfa9146
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
msgwin.c File Reference

Message Window. More...

#include "config.h"
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <wchar.h>
#include "mutt/lib.h"
#include "msgwin.h"
#include "color/lib.h"
#include "msgcont.h"
#include "msgwin_wdata.h"
#include "mutt_curses.h"
#include "mutt_window.h"
+ Include dependency graph for msgwin.c:

Go to the source code of this file.

Functions

void measure (struct MwCharArray *chars, const char *str, const struct AttrColor *ac_color)
 Measure a string in bytes and cells.
 
static int msgwin_recalc (struct MuttWindow *win)
 Recalculate the display of the Message Window - Implements MuttWindow::recalc() -.
 
int msgwin_calc_rows (struct MsgWinWindowData *wdata, int cols, const char *str)
 How many rows will a string need?
 
static int msgwin_repaint (struct MuttWindow *win)
 Redraw the Message Window - Implements MuttWindow::repaint() -.
 
static bool msgwin_recursor (struct MuttWindow *win)
 Recursor the Message Window - Implements MuttWindow::recursor() -.
 
void msgwin_set_rows (struct MuttWindow *win, short rows)
 Resize the Message Window.
 
static int msgwin_window_observer (struct NotifyCallback *nc)
 Notification that a Window has changed - Implements observer_t -.
 
struct MuttWindowmsgwin_new (bool interactive)
 Create the Message Window.
 
const char * msgwin_get_text (struct MuttWindow *win)
 Get the text from the Message Window.
 
void msgwin_add_text (struct MuttWindow *win, const char *text, const struct AttrColor *ac_color)
 Add text to the Message Window.
 
void msgwin_add_text_n (struct MuttWindow *win, const char *text, int bytes, const struct AttrColor *ac_color)
 Add some text to the Message Window.
 
void msgwin_set_text (struct MuttWindow *win, const char *text, enum ColorId color)
 Set the text for the Message Window.
 
void msgwin_clear_text (struct MuttWindow *win)
 Clear the text in the Message Window.
 
struct MuttWindowmsgwin_get_window (void)
 Get the Message Window pointer.
 

Detailed Description

Message Window.

Authors
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file msgwin.c.

Function Documentation

◆ measure()

void measure ( struct MwCharArray *  chars,
const char *  str,
const struct AttrColor ac_color 
)

Measure a string in bytes and cells.

Parameters
charsResults
strString to measure
ac_colorColour to associate

Calculate the size of each character in a string in bytes and screen cells.

Definition at line 106 of file msgwin.c.

107{
108 if (!str || !*str)
109 return;
110
111 mbstate_t mbstate = { 0 };
112 struct MwChar mwc = { 0 };
113
114 size_t str_len = mutt_str_len(str);
115
116 while (*str && (str_len > 0))
117 {
118 wchar_t wc = L'\0';
119 size_t consumed = mbrtowc(&wc, str, str_len, &mbstate);
120 if (consumed == 0)
121 break;
122
123 if (consumed == ICONV_ILLEGAL_SEQ)
124 {
125 memset(&mbstate, 0, sizeof(mbstate));
126 wc = ReplacementChar;
127 consumed = 1;
128 }
129 else if (consumed == ICONV_BUF_TOO_SMALL)
130 {
131 wc = ReplacementChar;
132 consumed = str_len;
133 }
134
135 int wchar_width = wcwidth(wc);
136 if (wchar_width < 0)
137 wchar_width = 1;
138
139 if (wc == 0xfe0f) // Emoji variation
140 {
141 size_t size = ARRAY_SIZE(chars);
142 if (size > 0)
143 {
144 struct MwChar *es_prev = ARRAY_GET(chars, size - 1);
145 if (es_prev->width == 1)
146 es_prev->width = 2;
147 }
148 }
149
150 mwc = (struct MwChar) { wchar_width, consumed, ac_color };
151 ARRAY_ADD(chars, mwc);
152
153 str += consumed;
154 str_len -= consumed;
155 }
156}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition: array.h:156
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:87
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:109
wchar_t ReplacementChar
When a Unicode character can't be displayed, use this instead.
Definition: charset.c:61
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition: charset.h:107
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition: charset.h:105
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:496
Description of a single character.
Definition: msgwin_wdata.h:39
const struct AttrColor * ac_color
Colour to use.
Definition: msgwin_wdata.h:42
unsigned char width
Width in screen cells.
Definition: msgwin_wdata.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ msgwin_calc_rows()

int msgwin_calc_rows ( struct MsgWinWindowData wdata,
int  cols,
const char *  str 
)

How many rows will a string need?

Parameters
wdataWindow data
colsColumns to wrap at
strText to measure
Return values
numNumber of rows required
0Error

Divide the width of a string by the width of the Message Window.

< Screen width used

< Offset into str

< Current row

Definition at line 178 of file msgwin.c.

179{
180 if (!wdata || !str || !*str)
181 return 0;
182
183 for (int i = 0; i < MSGWIN_MAX_ROWS; i++)
184 {
185 ARRAY_FREE(&wdata->rows[i]);
186 }
187
188 int width = 0;
189 int offset = 0;
190 int row = 0;
191 bool new_row = false;
192
193 struct MwChunk *chunk = NULL;
194 struct MwChar *mwc = NULL;
195 ARRAY_FOREACH(mwc, &wdata->chars)
196 {
197 const bool nl = (mwc->bytes == 1) && (str[offset] == '\n');
198 if (nl)
199 {
200 new_row = true;
201 offset += mwc->bytes;
202 continue;
203 }
204
205 if (((width + mwc->width) > cols) || new_row)
206 {
207 // ROW IS FULL
208 new_row = false;
209
210 row++;
211 if (row >= MSGWIN_MAX_ROWS)
212 {
213 // NO MORE ROOM
214 break;
215 }
216
217 // Start a new row
218 struct MwChunk tmp = { offset, mwc->bytes, mwc->width, mwc->ac_color };
219
220 mutt_debug(LL_DEBUG5, "row = %d\n", row);
221 ARRAY_ADD(&wdata->rows[row], tmp);
222 chunk = ARRAY_LAST(&wdata->rows[row]);
223
224 width = 0;
225 }
226 else if (!chunk || (mwc->ac_color != chunk->ac_color))
227 {
228 // CHANGE OF COLOUR
229 struct MwChunk tmp = { offset, mwc->bytes, mwc->width, mwc->ac_color };
230 ARRAY_ADD(&wdata->rows[row], tmp);
231 chunk = ARRAY_LAST(&wdata->rows[row]);
232 }
233 else
234 {
235 // MORE OF THE SAME
236 chunk->bytes += mwc->bytes;
237 chunk->width += mwc->width;
238 }
239
240 offset += mwc->bytes;
241 width += mwc->width;
242 }
243
244 mutt_debug(LL_DEBUG5, "msgwin_calc_rows() => %d\n", row + 1);
245 return row + 1;
246}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:212
#define ARRAY_LAST(head)
Convenience method to get the last element.
Definition: array.h:144
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:204
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG5
Log at debug level 5.
Definition: logging2.h:47
#define MSGWIN_MAX_ROWS
Definition: msgwin_wdata.h:30
struct MwCharArray chars
Text: Breakdown of bytes and widths.
Definition: msgwin_wdata.h:68
struct MwChunkArray rows[MSGWIN_MAX_ROWS]
String byte counts for each row.
Definition: msgwin_wdata.h:69
unsigned char bytes
Number of bytes to represent.
Definition: msgwin_wdata.h:41
A block of characters of one colour.
Definition: msgwin_wdata.h:54
unsigned short bytes
Number of bytes in the row.
Definition: msgwin_wdata.h:56
unsigned short width
Width of row in screen cells.
Definition: msgwin_wdata.h:57
unsigned short offset
Offset into MsgWinWindowData.text.
Definition: msgwin_wdata.h:55
const struct AttrColor * ac_color
Colour to use.
Definition: msgwin_wdata.h:58
+ Here is the caller graph for this function:

◆ msgwin_set_rows()

void msgwin_set_rows ( struct MuttWindow win,
short  rows 
)

Resize the Message Window.

Parameters
winMessage Window
rowsNumber of rows required

Resize the other Windows to allow a multi-line message to be displayed.

Note
rows will be clamped between 1 and 3 (MSGWIN_MAX_ROWS) inclusive

Definition at line 303 of file msgwin.c.

304{
305 if (!win)
306 win = msgcont_get_msgwin();
307 if (!win)
308 return;
309
310 rows = CLAMP(rows, 1, MSGWIN_MAX_ROWS);
311
312 if (rows != win->state.rows)
313 {
314 win->req_rows = rows;
315 mutt_window_reflow(NULL);
316 }
317}
#define CLAMP(val, lo, hi)
Definition: memory.h:33
struct MuttWindow * msgcont_get_msgwin(void)
Get the Message Window.
Definition: msgcont.c:117
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:343
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:126
short req_rows
Number of rows required.
Definition: mutt_window.h:124
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:61
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ msgwin_new()

struct MuttWindow * msgwin_new ( bool  interactive)

Create the Message Window.

Return values
ptrNew Window

Definition at line 371 of file msgwin.c.

372{
375
376 struct MsgWinWindowData *wdata = msgwin_wdata_new();
377
378 win->wdata = wdata;
380 win->recalc = msgwin_recalc;
381 win->repaint = msgwin_repaint;
382
383 if (interactive)
385
386 // Copy the container's dimensions
388
390
391 return win;
392}
static int msgwin_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: msgwin.c:327
static int msgwin_recalc(struct MuttWindow *win)
Recalculate the display of the Message Window - Implements MuttWindow::recalc() -.
Definition: msgwin.c:161
static bool msgwin_recursor(struct MuttWindow *win)
Recursor the Message Window - Implements MuttWindow::recursor() -.
Definition: msgwin.c:283
static int msgwin_repaint(struct MuttWindow *win)
Redraw the Message Window - Implements MuttWindow::repaint() -.
Definition: msgwin.c:251
void msgwin_wdata_free(struct MuttWindow *win, void **ptr)
Free the private data - Implements MuttWindow::wdata_free() -.
Definition: msgwin_wdata.c:37
struct MuttWindow * MessageContainer
Window acting as a stack for the message windows.
Definition: msgcont.c:40
struct MsgWinWindowData * msgwin_wdata_new(void)
Create new private data for the Message Window.
Definition: msgwin_wdata.c:60
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:191
struct MuttWindow * mutt_window_new(enum WindowType type, enum MuttWindowOrientation orient, enum MuttWindowSize size, int cols, int rows)
Create a new Window.
Definition: mutt_window.c:181
@ WT_MESSAGE
Window for messages/errors.
Definition: mutt_window.h:98
@ MUTT_WIN_ORIENT_VERTICAL
Window uses all available vertical space.
Definition: mutt_window.h:38
#define MUTT_WIN_SIZE_UNLIMITED
Use as much space as possible.
Definition: mutt_window.h:52
@ MUTT_WIN_SIZE_FIXED
Window has a fixed size.
Definition: mutt_window.h:47
@ NT_WINDOW
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:57
Message Window private Window data.
Definition: msgwin_wdata.h:66
int(* repaint)(struct MuttWindow *win)
Definition: mutt_window.h:186
void * wdata
Private data.
Definition: mutt_window.h:144
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:137
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:172
void(* wdata_free)(struct MuttWindow *win, void **ptr)
Definition: mutt_window.h:158
bool(* recursor)(struct MuttWindow *win)
Definition: mutt_window.h:204
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ msgwin_get_text()

const char * msgwin_get_text ( struct MuttWindow win)

Get the text from the Message Window.

Parameters
winMessage Window
Return values
ptrWindow text
Note
Do not free the returned string

Definition at line 401 of file msgwin.c.

402{
403 if (!win)
404 win = msgcont_get_msgwin();
405 if (!win)
406 return NULL;
407
408 struct MsgWinWindowData *wdata = win->wdata;
409
410 return buf_string(wdata->text);
411}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
struct Buffer * text
Cached display string.
Definition: msgwin_wdata.h:67
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ msgwin_add_text()

void msgwin_add_text ( struct MuttWindow win,
const char *  text,
const struct AttrColor ac_color 
)

Add text to the Message Window.

Parameters
winMessage Window
textText to add
ac_colorColour for text

Definition at line 419 of file msgwin.c.

420{
421 if (!win)
422 win = msgcont_get_msgwin();
423 if (!win)
424 return;
425
426 struct MsgWinWindowData *wdata = win->wdata;
427
428 if (text)
429 {
430 buf_addstr(wdata->text, text);
431 measure(&wdata->chars, text, ac_color);
432 mutt_debug(LL_DEBUG5, "MW ADD: %zu, %s\n", buf_len(wdata->text),
433 buf_string(wdata->text));
434 }
435 else
436 {
437 int rows = msgwin_calc_rows(wdata, win->state.cols, buf_string(wdata->text));
438 msgwin_set_rows(win, rows);
439 win->actions |= WA_RECALC;
440 }
441}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:491
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
int msgwin_calc_rows(struct MsgWinWindowData *wdata, int cols, const char *str)
How many rows will a string need?
Definition: msgwin.c:178
void measure(struct MwCharArray *chars, const char *str, const struct AttrColor *ac_color)
Measure a string in bytes and cells.
Definition: msgwin.c:106
void msgwin_set_rows(struct MuttWindow *win, short rows)
Resize the Message Window.
Definition: msgwin.c:303
#define WA_RECALC
Recalculate the contents of the Window.
Definition: mutt_window.h:109
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
Definition: mutt_window.h:131
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:60
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ msgwin_add_text_n()

void msgwin_add_text_n ( struct MuttWindow win,
const char *  text,
int  bytes,
const struct AttrColor ac_color 
)

Add some text to the Message Window.

Parameters
winMessage Window
textText to add
bytesNumber of bytes of text to add
ac_colorColour for text

Definition at line 450 of file msgwin.c.

452{
453 if (!win)
454 win = msgcont_get_msgwin();
455 if (!win)
456 return;
457
458 struct MsgWinWindowData *wdata = win->wdata;
459
460 if (text)
461 {
462 const char *dptr = wdata->text->dptr;
463 buf_addstr_n(wdata->text, text, bytes);
464 measure(&wdata->chars, dptr, ac_color);
465 mutt_debug(LL_DEBUG5, "MW ADD: %zu, %s\n", buf_len(wdata->text),
466 buf_string(wdata->text));
467 }
468 else
469 {
470 int rows = msgwin_calc_rows(wdata, win->state.cols, buf_string(wdata->text));
471 msgwin_set_rows(win, rows);
472 win->actions |= WA_RECALC;
473 }
474}
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
char * dptr
Current read/write position.
Definition: buffer.h:38
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ msgwin_set_text()

void msgwin_set_text ( struct MuttWindow win,
const char *  text,
enum ColorId  color 
)

Set the text for the Message Window.

Parameters
winMessage Window
textText to set
colorColour for text
Note
The text string will be copied

Definition at line 484 of file msgwin.c.

485{
486 if (!win)
487 win = msgcont_get_msgwin();
488 if (!win)
489 return;
490
491 struct MsgWinWindowData *wdata = win->wdata;
492
493 if (mutt_str_equal(buf_string(wdata->text), text))
494 return;
495
496 buf_strcpy(wdata->text, text);
497 ARRAY_FREE(&wdata->chars);
498 if (wdata->text)
499 {
500 const struct AttrColor *ac_normal = simple_color_get(MT_COLOR_NORMAL);
501 const struct AttrColor *ac_color = simple_color_get(color);
502 const struct AttrColor *ac_merge = merged_color_overlay(ac_normal, ac_color);
503
504 measure(&wdata->chars, buf_string(wdata->text), ac_merge);
505 }
506
507 mutt_debug(LL_DEBUG5, "MW SET: %zu, %s\n", buf_len(wdata->text),
508 buf_string(wdata->text));
509
510 int rows = msgwin_calc_rows(wdata, win->state.cols, buf_string(wdata->text));
511 msgwin_set_rows(win, rows);
512 win->actions |= WA_RECALC;
513}
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
struct AttrColor * simple_color_get(enum ColorId cid)
Get the colour of an object by its ID.
Definition: simple.c:88
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:59
const struct AttrColor * merged_color_overlay(const struct AttrColor *base, const struct AttrColor *over)
Combine two colours.
Definition: merged.c:107
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:660
A curses colour and its attributes.
Definition: attr.h:66
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ msgwin_clear_text()

void msgwin_clear_text ( struct MuttWindow win)

Clear the text in the Message Window.

Parameters
winMessage Window

Definition at line 519 of file msgwin.c.

520{
522}
void msgwin_set_text(struct MuttWindow *win, const char *text, enum ColorId color)
Set the text for the Message Window.
Definition: msgwin.c:484
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ msgwin_get_window()

struct MuttWindow * msgwin_get_window ( void  )

Get the Message Window pointer.

Return values
ptrMessage Window

Allow some users direct access to the Message Window.

Definition at line 530 of file msgwin.c.

531{
532 return msgcont_get_msgwin();
533}
+ Here is the call graph for this function:
+ Here is the caller graph for this function: