NeoMutt  2025-09-05-55-g97fc89
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 <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 105 of file msgwin.c.

106{
107 if (!str || !*str)
108 return;
109
110 mbstate_t mbstate = { 0 };
111 struct MwChar mwc = { 0 };
112
113 size_t str_len = mutt_str_len(str);
114
115 while (*str && (str_len > 0))
116 {
117 wchar_t wc = L'\0';
118 size_t consumed = mbrtowc(&wc, str, str_len, &mbstate);
119 if (consumed == 0)
120 break;
121
122 if (consumed == ICONV_ILLEGAL_SEQ)
123 {
124 memset(&mbstate, 0, sizeof(mbstate));
125 wc = ReplacementChar;
126 consumed = 1;
127 }
128 else if (consumed == ICONV_BUF_TOO_SMALL)
129 {
130 wc = ReplacementChar;
131 consumed = str_len;
132 }
133
134 int wchar_width = wcwidth(wc);
135 if (wchar_width < 0)
136 wchar_width = 1;
137
138 if (wc == 0xfe0f) // Emoji variation
139 {
140 int size = ARRAY_SIZE(chars);
141 if (size > 0)
142 {
143 struct MwChar *es_prev = ARRAY_GET(chars, size - 1);
144 if (es_prev->width == 1)
145 es_prev->width = 2;
146 }
147 }
148
149 mwc = (struct MwChar) { wchar_width, consumed, ac_color };
150 ARRAY_ADD(chars, mwc);
151
152 str += consumed;
153 str_len -= consumed;
154 }
155}
#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:98
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition charset.h:96
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition string.c:498
Description of a single character.
const struct AttrColor * ac_color
Colour to use.
unsigned char width
Width in screen cells.
+ 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 177 of file msgwin.c.

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

303{
304 if (!win)
305 win = msgcont_get_msgwin();
306 if (!win)
307 return;
308
309 rows = CLAMP(rows, 1, MSGWIN_MAX_ROWS);
310
311 if (rows != win->state.rows)
312 {
313 win->req_rows = rows;
314 mutt_window_reflow(NULL);
315 }
316}
#define CLAMP(val, lo, hi)
Definition memory.h:38
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.
struct WindowState state
Current state of the Window.
short req_rows
Number of rows required.
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition mutt_window.h:62
+ 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 370 of file msgwin.c.

371{
374
375 struct MsgWinWindowData *wdata = msgwin_wdata_new();
376
377 win->wdata = wdata;
379 win->recalc = msgwin_recalc;
380 win->repaint = msgwin_repaint;
381
382 if (interactive)
384
385 // Copy the container's dimensions
386 win->state = MessageContainer->state;
387
389
390 return win;
391}
static int msgwin_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition msgwin.c:326
static int msgwin_recalc(struct MuttWindow *win)
Recalculate the display of the Message Window - Implements MuttWindow::recalc() -.
Definition msgwin.c:160
static bool msgwin_recursor(struct MuttWindow *win)
Recursor the Message Window - Implements MuttWindow::recursor() -.
Definition msgwin.c:282
static int msgwin_repaint(struct MuttWindow *win)
Redraw the Message Window - Implements MuttWindow::repaint() -.
Definition msgwin.c:250
void msgwin_wdata_free(struct MuttWindow *win, void **ptr)
Free the private data - Implements MuttWindow::wdata_free() -.
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.
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.
@ WT_MESSAGE
Window for messages/errors.
Definition mutt_window.h:99
@ MUTT_WIN_ORIENT_VERTICAL
Window uses all available vertical space.
Definition mutt_window.h:39
#define MUTT_WIN_SIZE_UNLIMITED
Use as much space as possible.
Definition mutt_window.h:53
@ MUTT_WIN_SIZE_FIXED
Window has a fixed size.
Definition mutt_window.h:48
@ NT_WINDOW
MuttWindow has changed, NotifyWindow, EventWindow.
Definition notify_type.h:57
Message Window private Window data.
int(* repaint)(struct MuttWindow *win)
void * wdata
Private data.
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
int(* recalc)(struct MuttWindow *win)
void(* wdata_free)(struct MuttWindow *win, void **ptr)
bool(* recursor)(struct MuttWindow *win)
+ 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 400 of file msgwin.c.

401{
402 if (!win)
403 win = msgcont_get_msgwin();
404 if (!win)
405 return NULL;
406
407 struct MsgWinWindowData *wdata = win->wdata;
408
409 return buf_string(wdata->text);
410}
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.
+ 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 418 of file msgwin.c.

419{
420 if (!win)
421 win = msgcont_get_msgwin();
422 if (!win)
423 return;
424
425 struct MsgWinWindowData *wdata = win->wdata;
426
427 if (text)
428 {
429 buf_addstr(wdata->text, text);
430 measure(&wdata->chars, text, ac_color);
431 mutt_debug(LL_DEBUG5, "MW ADD: %zu, %s\n", buf_len(wdata->text),
432 buf_string(wdata->text));
433 }
434 else
435 {
436 int rows = msgwin_calc_rows(wdata, win->state.cols, buf_string(wdata->text));
437 msgwin_set_rows(win, rows);
438 win->actions |= WA_RECALC;
439 }
440}
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:177
void measure(struct MwCharArray *chars, const char *str, const struct AttrColor *ac_color)
Measure a string in bytes and cells.
Definition msgwin.c:105
void msgwin_set_rows(struct MuttWindow *win, short rows)
Resize the Message Window.
Definition msgwin.c:302
#define WA_RECALC
Recalculate the contents of the Window.
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
short cols
Number of columns, 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_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 449 of file msgwin.c.

451{
452 if (!win)
453 win = msgcont_get_msgwin();
454 if (!win)
455 return;
456
457 struct MsgWinWindowData *wdata = win->wdata;
458
459 if (text)
460 {
461 const char *dptr = wdata->text->dptr;
462 buf_addstr_n(wdata->text, text, bytes);
463 measure(&wdata->chars, dptr, ac_color);
464 mutt_debug(LL_DEBUG5, "MW ADD: %zu, %s\n", buf_len(wdata->text),
465 buf_string(wdata->text));
466 }
467 else
468 {
469 int rows = msgwin_calc_rows(wdata, win->state.cols, buf_string(wdata->text));
470 msgwin_set_rows(win, rows);
471 win->actions |= WA_RECALC;
472 }
473}
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 483 of file msgwin.c.

484{
485 if (!win)
486 win = msgcont_get_msgwin();
487 if (!win)
488 return;
489
490 struct MsgWinWindowData *wdata = win->wdata;
491
492 if (mutt_str_equal(buf_string(wdata->text), text))
493 return;
494
495 buf_strcpy(wdata->text, text);
496 ARRAY_FREE(&wdata->chars);
497 if (wdata->text)
498 {
499 const struct AttrColor *ac_normal = simple_color_get(MT_COLOR_NORMAL);
500 const struct AttrColor *ac_color = simple_color_get(color);
501 const struct AttrColor *ac_merge = merged_color_overlay(ac_normal, ac_color);
502
503 measure(&wdata->chars, buf_string(wdata->text), ac_merge);
504 }
505
506 mutt_debug(LL_DEBUG5, "MW SET: %zu, %s\n", buf_len(wdata->text),
507 buf_string(wdata->text));
508
509 int rows = msgwin_calc_rows(wdata, win->state.cols, buf_string(wdata->text));
510 msgwin_set_rows(win, rows);
511 win->actions |= WA_RECALC;
512}
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:95
@ MT_COLOR_NORMAL
Plain text.
Definition color.h:54
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 518 of file msgwin.c.

519{
521}
void msgwin_set_text(struct MuttWindow *win, const char *text, enum ColorId color)
Set the text for the Message Window.
Definition msgwin.c:483
+ 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 529 of file msgwin.c.

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