NeoMutt  2023-05-17-56-ga67199
Teaching an old dog new tricks
DOXYGEN
pager.c
Go to the documentation of this file.
1
61#include "config.h"
62#include <stddef.h>
63#include <inttypes.h> // IWYU pragma: keep
64#include <stdbool.h>
65#include <sys/stat.h>
66#include "mutt/lib.h"
67#include "config/lib.h"
68#include "core/lib.h"
69#include "gui/lib.h"
70#include "lib.h"
71#include "color/lib.h"
72#include "index/lib.h"
73#include "display.h"
74#include "opcodes.h"
75#include "private_data.h"
76
83static int config_pager_index_lines(struct MuttWindow *win)
84{
85 if (!mutt_window_is_visible(win))
86 return 0;
87
88 struct MuttWindow *dlg = dialog_find(win);
89 struct MuttWindow *panel_index = window_find_child(dlg, WT_INDEX);
90 struct MuttWindow *win_index = window_find_child(panel_index, WT_MENU);
91 if (!win_index)
92 return -1;
93
94 const short c_pager_index_lines = cs_subset_number(NeoMutt->sub, "pager_index_lines");
95
96 if (c_pager_index_lines > 0)
97 {
98 win_index->req_rows = c_pager_index_lines;
99 win_index->size = MUTT_WIN_SIZE_FIXED;
100
101 panel_index->size = MUTT_WIN_SIZE_MINIMISE;
102 panel_index->state.visible = true;
103 }
104 else
105 {
107 win_index->size = MUTT_WIN_SIZE_MAXIMISE;
108
109 panel_index->size = MUTT_WIN_SIZE_MAXIMISE;
110 panel_index->state.visible = false;
111 }
112
114 mutt_debug(LL_DEBUG5, "config, request WA_REFLOW\n");
115 return 0;
116}
117
121static int pager_recalc(struct MuttWindow *win)
122{
123 win->actions |= WA_REPAINT;
124 mutt_debug(LL_DEBUG5, "recalc done, request WA_REPAINT\n");
125 return 0;
126}
127
131static int pager_repaint(struct MuttWindow *win)
132{
133 struct PagerPrivateData *priv = win->wdata;
134 if (!priv || !priv->pview || !priv->pview->pdata)
135 return 0;
136
137#ifdef USE_DEBUG_COLOR
138 dump_pager(priv);
139#endif
140
141 // We need to populate more lines, but not change position
142 const bool repopulate = (priv->cur_line > priv->lines_used);
143 if ((priv->redraw & PAGER_REDRAW_FLOW) || repopulate)
144 {
145 if (!(priv->pview->flags & MUTT_PAGER_RETWINCH))
146 {
147 priv->win_height = -1;
148 for (int i = 0; i <= priv->top_line; i++)
149 if (!priv->lines[i].cont_line)
150 priv->win_height++;
151 for (int i = 0; i < priv->lines_max; i++)
152 {
153 priv->lines[i].offset = 0;
154 priv->lines[i].cid = -1;
155 priv->lines[i].cont_line = false;
156 priv->lines[i].syntax_arr_size = 0;
157 priv->lines[i].search_arr_size = -1;
158 priv->lines[i].quote = NULL;
159
160 mutt_mem_realloc(&(priv->lines[i].syntax), sizeof(struct TextSyntax));
161 if (priv->search_compiled && priv->lines[i].search)
162 FREE(&(priv->lines[i].search));
163 }
164
165 if (!repopulate)
166 {
167 priv->lines_used = 0;
168 priv->top_line = 0;
169 }
170 }
171 int i = -1;
172 int j = -1;
173 while (display_line(priv->fp, &priv->bytes_read, &priv->lines, ++i,
174 &priv->lines_used, &priv->lines_max,
175 priv->has_types | priv->search_flag | (priv->pview->flags & MUTT_PAGER_NOWRAP),
176 &priv->quote_list, &priv->q_level, &priv->force_redraw,
177 &priv->search_re, priv->pview->win_pager, &priv->ansi_list) == 0)
178 {
179 if (!priv->lines[i].cont_line && (++j == priv->win_height))
180 {
181 if (!repopulate)
182 priv->top_line = i;
183 if (!priv->search_flag)
184 break;
185 }
186 }
187 }
188
189 if ((priv->redraw & PAGER_REDRAW_PAGER) || (priv->top_line != priv->old_top_line))
190 {
191 do
192 {
193 mutt_window_move(priv->pview->win_pager, 0, 0);
194 priv->cur_line = priv->top_line;
195 priv->old_top_line = priv->top_line;
196 priv->win_height = 0;
197 priv->force_redraw = false;
198
199 while ((priv->win_height < priv->pview->win_pager->state.rows) &&
200 (priv->lines[priv->cur_line].offset <= priv->st.st_size - 1))
201 {
202 if (display_line(priv->fp, &priv->bytes_read, &priv->lines,
203 priv->cur_line, &priv->lines_used, &priv->lines_max,
204 (priv->pview->flags & MUTT_DISPLAYFLAGS) | priv->hide_quoted |
205 priv->search_flag | (priv->pview->flags & MUTT_PAGER_NOWRAP),
206 &priv->quote_list, &priv->q_level, &priv->force_redraw,
207 &priv->search_re, priv->pview->win_pager, &priv->ansi_list) > 0)
208 {
209 priv->win_height++;
210 }
211 priv->cur_line++;
212 mutt_window_move(priv->pview->win_pager, 0, priv->win_height);
213 }
214 } while (priv->force_redraw);
215
216 const bool c_tilde = cs_subset_bool(NeoMutt->sub, "tilde");
218 while (priv->win_height < priv->pview->win_pager->state.rows)
219 {
221 if (c_tilde)
222 mutt_window_addch(priv->pview->win_pager, '~');
223 priv->win_height++;
224 mutt_window_move(priv->pview->win_pager, 0, priv->win_height);
225 }
227 }
228
230 mutt_debug(LL_DEBUG5, "repaint done\n");
231 return 0;
232}
233
238{
239 if (nc->event_type != NT_COLOR)
240 return 0;
241 if (!nc->global_data || !nc->event_data)
242 return -1;
243
244 struct EventColor *ev_c = nc->event_data;
245 struct MuttWindow *win_pager = nc->global_data;
246 struct PagerPrivateData *priv = win_pager->wdata;
247 if (!priv)
248 return 0;
249
250 // MT_COLOR_MAX is sent on `uncolor *`
251 if ((ev_c->cid == MT_COLOR_QUOTED) || (ev_c->cid == MT_COLOR_MAX))
252 {
253 // rework quoted colours
255 }
256
257 if (ev_c->cid == MT_COLOR_MAX)
258 {
259 for (size_t i = 0; i < priv->lines_max; i++)
260 {
261 FREE(&(priv->lines[i].syntax));
262 }
263 priv->lines_used = 0;
264 }
265
266 mutt_debug(LL_DEBUG5, "color done\n");
267 return 0;
268}
269
274{
275 if (nc->event_type != NT_CONFIG)
276 return 0;
277 if (!nc->global_data || !nc->event_data)
278 return -1;
279
280 struct EventConfig *ev_c = nc->event_data;
281 struct MuttWindow *win_pager = nc->global_data;
282
283 if (mutt_str_equal(ev_c->name, "pager_index_lines"))
284 {
285 config_pager_index_lines(win_pager);
286 mutt_debug(LL_DEBUG5, "config done\n");
287 }
288
289 return 0;
290}
291
296{
297 if (nc->event_type != NT_GLOBAL)
298 return 0;
299 if (!nc->global_data)
300 return -1;
302 return 0;
303
304 struct MuttWindow *win_pager = nc->global_data;
305
306 struct PagerPrivateData *priv = win_pager->wdata;
307 const struct PagerView *pview = priv ? priv->pview : NULL;
308 if (priv && pview && (priv->redraw & PAGER_REDRAW_FLOW) && (pview->flags & MUTT_PAGER_RETWINCH))
309 {
310 priv->rc = OP_REFORMAT_WINCH;
311 }
312
313 return 0;
314}
315
320{
321 if (nc->event_type != NT_INDEX)
322 return 0;
323 if (!nc->global_data)
324 return -1;
325
326 struct MuttWindow *win_pager = nc->global_data;
327
328 struct PagerPrivateData *priv = win_pager->wdata;
329 if (!priv)
330 return 0;
331
332 struct IndexSharedData *shared = nc->event_data;
333
335 {
336 win_pager->actions |= WA_RECALC;
337 mutt_debug(LL_DEBUG5, "index done, request WA_RECALC\n");
338 priv->loop = PAGER_LOOP_QUIT;
339 }
340 else if (nc->event_subtype & NT_INDEX_EMAIL)
341 {
342 win_pager->actions |= WA_RECALC;
343 mutt_debug(LL_DEBUG5, "index done, request WA_RECALC\n");
344 priv->pager_redraw = true;
345 if (shared && shared->email && (priv->loop != PAGER_LOOP_QUIT))
346 {
347 priv->loop = PAGER_LOOP_RELOAD;
348 }
349 else
350 {
351 priv->loop = PAGER_LOOP_QUIT;
352 priv->rc = 0;
353 }
354 }
355
356 return 0;
357}
358
363{
364 if (nc->event_type != NT_PAGER)
365 return 0;
366 if (!nc->global_data || !nc->event_data)
367 return -1;
368
369 mutt_debug(LL_DEBUG5, "pager done\n");
370 return 0;
371}
372
377{
378 if (nc->event_type != NT_WINDOW)
379 return 0;
380 if (!nc->global_data || !nc->event_data)
381 return -1;
383 return 0;
384
385 struct MuttWindow *win_pager = nc->global_data;
386 struct EventWindow *ev_w = nc->event_data;
387 if (ev_w->win != win_pager)
388 return 0;
389
390 struct MuttWindow *dlg = window_find_parent(win_pager, WT_DLG_INDEX);
391 if (!dlg)
392 dlg = window_find_parent(win_pager, WT_DLG_DO_PAGER);
393
394 struct IndexSharedData *shared = dlg->wdata;
395
402
403 mutt_debug(LL_DEBUG5, "window delete done\n");
404
405 return 0;
406}
407
415 struct PagerPrivateData *priv)
416{
420 win->wdata = priv;
421 win->recalc = pager_recalc;
422 win->repaint = pager_repaint;
423
430
431 return win;
432}
Color and attribute parsing.
@ MT_COLOR_QUOTED
Pager: quoted text.
Definition: color.h:61
@ MT_COLOR_MAX
Definition: color.h:92
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:57
@ MT_COLOR_TILDE
Pager: empty lines after message.
Definition: color.h:76
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
void dump_pager(struct PagerPrivateData *priv)
Definition: pager.c:101
struct MuttWindow * dialog_find(struct MuttWindow *win)
Find the parent Dialog of a Window.
Definition: dialog.c:83
int display_line(FILE *fp, LOFF_T *bytes_read, struct Line **lines, int line_num, int *lines_used, int *lines_max, PagerFlags flags, struct QuoteStyle **quote_list, int *q_level, bool *force_redraw, regex_t *search_re, struct MuttWindow *win_pager, struct AttrColorList *ansi_list)
Print a line on screen.
Definition: display.c:1005
Pager Display.
#define mutt_debug(LEVEL,...)
Definition: logging2.h:87
static int pager_pager_observer(struct NotifyCallback *nc)
Notification that the Pager has changed - Implements observer_t -.
Definition: pager.c:362
static int pager_color_observer(struct NotifyCallback *nc)
Notification that a Color has changed - Implements observer_t -.
Definition: pager.c:237
static int pager_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: pager.c:273
static int pager_index_observer(struct NotifyCallback *nc)
Notification that the Index has changed - Implements observer_t -.
Definition: pager.c:319
static int pager_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: pager.c:376
static int pager_global_observer(struct NotifyCallback *nc)
Notification that a Global Event occurred - Implements observer_t -.
Definition: pager.c:295
static int pager_recalc(struct MuttWindow *win)
Recalculate the Pager display - Implements MuttWindow::recalc() -.
Definition: pager.c:121
static int pager_repaint(struct MuttWindow *win)
Repaint the Pager display - Implements MuttWindow::repaint() -.
Definition: pager.c:131
Convenience wrapper for the gui headers.
GUI manage the main index (list of emails)
#define NT_INDEX_MAILBOX
Mailbox has changed.
Definition: lib.h:65
#define NT_INDEX_EMAIL
Email has changed.
Definition: lib.h:66
@ LL_DEBUG5
Log at debug level 5.
Definition: logging2.h:47
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#define FREE(x)
Definition: memory.h:43
Convenience wrapper for the library headers.
bool notify_observer_remove(struct Notify *notify, const observer_t callback, const void *global_data)
Remove an observer from an object.
Definition: notify.c:228
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:189
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
struct AttrColor * mutt_curses_set_normal_backed_color_by_id(enum ColorId cid)
Set the colour and attributes by the colour id.
Definition: mutt_curses.c:65
struct AttrColor * mutt_curses_set_color_by_id(enum ColorId cid)
Set the colour and attributes by the colour id.
Definition: mutt_curses.c:81
bool mutt_window_is_visible(struct MuttWindow *win)
Is the Window visible?
Definition: mutt_window.c:502
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:341
struct MuttWindow * window_find_parent(struct MuttWindow *win, enum WindowType type)
Find a (grand-)parent of a Window by type.
Definition: mutt_window.c:548
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:180
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:294
struct MuttWindow * window_find_child(struct MuttWindow *win, enum WindowType type)
Recursively find a child Window of a given type.
Definition: mutt_window.c:523
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:241
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
Definition: mutt_window.c:382
#define WA_RECALC
Recalculate the contents of the Window.
Definition: mutt_window.h:110
@ WT_CUSTOM
Window with a custom drawing function.
Definition: mutt_window.h:95
@ WT_DLG_INDEX
Index Dialog, index_pager_init()
Definition: mutt_window.h:86
@ WT_INDEX
A panel containing the Index Window.
Definition: mutt_window.h:97
@ WT_DLG_DO_PAGER
Pager Dialog, mutt_do_pager()
Definition: mutt_window.h:84
@ WT_MENU
An Window containing a Menu.
Definition: mutt_window.h:98
@ MUTT_WIN_ORIENT_VERTICAL
Window uses all available vertical space.
Definition: mutt_window.h:38
@ NT_WINDOW_DELETE
Window is about to be deleted.
Definition: mutt_window.h:205
#define WA_REPAINT
Redraw the contents of the Window.
Definition: mutt_window.h:111
#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
@ MUTT_WIN_SIZE_MINIMISE
Window size depends on its children.
Definition: mutt_window.h:49
@ MUTT_WIN_SIZE_MAXIMISE
Window wants as much space as possible.
Definition: mutt_window.h:48
@ NT_GLOBAL_COMMAND
A NeoMutt command.
Definition: neomutt.h:55
@ NT_WINDOW
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:55
@ NT_CONFIG
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:43
@ NT_COLOR
Colour has changed, NotifyColor, EventColor.
Definition: notify_type.h:41
@ NT_PAGER
Pager data has changed, NotifyPager, PagerPrivateData.
Definition: notify_type.h:52
@ NT_INDEX
Index data has changed, NotifyIndex, IndexSharedData.
Definition: notify_type.h:48
@ NT_ALL
Register for all notifications.
Definition: notify_type.h:35
@ NT_GLOBAL
Not object-related, NotifyGlobal.
Definition: notify_type.h:46
All user-callable functions.
@ PAGER_LOOP_RELOAD
Reload the Pager from scratch.
Definition: lib.h:152
@ PAGER_LOOP_QUIT
Quit the Pager.
Definition: lib.h:151
#define MUTT_PAGER_RETWINCH
Need reformatting on SIGWINCH.
Definition: lib.h:70
#define MUTT_PAGER_NOWRAP
Format for term width, ignore $wrap.
Definition: lib.h:72
#define MUTT_DISPLAYFLAGS
Definition: lib.h:77
#define PAGER_REDRAW_FLOW
Reflow the pager.
Definition: lib.h:190
#define PAGER_REDRAW_PAGER
Redraw the pager.
Definition: lib.h:189
#define PAGER_REDRAW_NO_FLAGS
No flags are set.
Definition: lib.h:188
static int config_pager_index_lines(struct MuttWindow *win)
React to changes to $pager_index_lines.
Definition: pager.c:83
struct MuttWindow * pager_window_new(struct IndexSharedData *shared, struct PagerPrivateData *priv)
Create a new Pager Window (list of Emails)
Definition: pager.c:414
Private state data for the Pager.
void qstyle_recolour(struct QuoteStyle *quote_list)
Recolour quotes after colour changes.
Definition: quoted.c:612
Key value store.
An Event that happened to a Colour.
Definition: notify2.h:53
enum ColorId cid
Colour ID that has changed.
Definition: notify2.h:54
A config-change event.
Definition: subset.h:71
const char * name
Name of config item that changed.
Definition: subset.h:73
An Event that happened to a Window.
Definition: mutt_window.h:215
struct MuttWindow * win
Window that changed.
Definition: mutt_window.h:216
Data shared between Index, Pager and Sidebar.
Definition: shared_data.h:37
struct Email * email
Currently selected Email.
Definition: shared_data.h:42
struct Notify * notify
Notifications: NotifyIndex, IndexSharedData.
Definition: shared_data.h:44
short search_arr_size
Number of items in search array.
Definition: display.h:60
struct TextSyntax * search
Array of search text in the line.
Definition: display.h:61
bool cont_line
Continuation of a previous line (wrapped by NeoMutt)
Definition: display.h:54
short cid
Default line colour, e.g. MT_COLOR_QUOTED.
Definition: display.h:53
struct QuoteStyle * quote
Quoting style for this line (pointer into PagerPrivateData->quote_list)
Definition: display.h:63
LOFF_T offset
Offset into Email file (PagerPrivateData->fp)
Definition: display.h:52
short syntax_arr_size
Number of items in syntax array.
Definition: display.h:57
struct TextSyntax * syntax
Array of coloured text in the line.
Definition: display.h:58
int(* repaint)(struct MuttWindow *win)
Definition: mutt_window.h:181
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
void * wdata
Private data.
Definition: mutt_window.h:145
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
short req_rows
Number of rows required.
Definition: mutt_window.h:125
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:170
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
Definition: mutt_window.h:132
enum MuttWindowSize size
Type of Window, e.g. MUTT_WIN_SIZE_FIXED.
Definition: mutt_window.h:131
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Data passed to a notification function.
Definition: observer.h:34
void * event_data
Data from notify_send()
Definition: observer.h:38
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:36
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:37
void * global_data
Data from notify_observer_add()
Definition: observer.h:39
Private state data for the Pager.
Definition: private_data.h:41
PagerFlags hide_quoted
Set to MUTT_HIDE when quoted email is hidden <toggle-quoted>
Definition: private_data.h:60
int rc
Return code from functions.
Definition: private_data.h:73
int q_level
Number of unique quoting levels.
Definition: private_data.h:59
int cur_line
Current line (last line visible on screen)
Definition: private_data.h:51
bool pager_redraw
Force a complete redraw.
Definition: private_data.h:78
int lines_used
Size of lines array (used entries)
Definition: private_data.h:49
int lines_max
Capacity of lines array (total entries)
Definition: private_data.h:50
bool force_redraw
Repaint is needed.
Definition: private_data.h:68
enum PagerLoopMode loop
What the Event Loop should do next, e.g. PAGER_LOOP_CONTINUE.
Definition: private_data.h:79
struct Line * lines
Array of text lines in pager.
Definition: private_data.h:48
PagerRedrawFlags redraw
When to redraw the screen.
Definition: private_data.h:69
int has_types
Set to MUTT_TYPES for PAGER_MODE_EMAIL or MUTT_SHOWCOLOR.
Definition: private_data.h:56
LOFF_T bytes_read
Number of bytes read from file.
Definition: private_data.h:46
int top_line
First visible line on screen.
Definition: private_data.h:55
struct stat st
Stats about Email file.
Definition: private_data.h:45
struct QuoteStyle * quote_list
Tree of quoting levels.
Definition: private_data.h:58
struct PagerView * pview
Object to view in the pager.
Definition: private_data.h:42
struct AttrColorList ansi_list
List of ANSI colours used in the Pager.
Definition: private_data.h:70
regex_t search_re
Compiled search string.
Definition: private_data.h:65
int win_height
Number of lines in the Window.
Definition: private_data.h:54
int old_top_line
Old top line, used for repainting.
Definition: private_data.h:53
FILE * fp
File containing decrypted/decoded/weeded Email.
Definition: private_data.h:44
PagerFlags search_flag
Set to MUTT_SEARCH when search results are visible <search-toggle>
Definition: private_data.h:62
bool search_compiled
Search regex is in use.
Definition: private_data.h:64
Paged view into some data.
Definition: lib.h:170
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition: lib.h:171
PagerFlags flags
Additional settings to tweak pager's function.
Definition: lib.h:173
struct MuttWindow * win_pager
Pager Window.
Definition: lib.h:178
Highlighting for a piece of text.
Definition: display.h:40
bool visible
Window is visible.
Definition: mutt_window.h:59
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:61