NeoMutt  2022-04-29-323-g5fcc6c
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 struct IndexSharedData *shared = dlg->wdata;
99 int vcount = shared->mailbox ? shared->mailbox->vcount : 0;
100 win_index->req_rows = MIN(c_pager_index_lines, vcount);
101 win_index->size = MUTT_WIN_SIZE_FIXED;
102
103 panel_index->size = MUTT_WIN_SIZE_MINIMISE;
104 panel_index->state.visible = true;
105 }
106 else
107 {
109 win_index->size = MUTT_WIN_SIZE_MAXIMISE;
110
111 panel_index->size = MUTT_WIN_SIZE_MAXIMISE;
112 panel_index->state.visible = false;
113 }
114
116 mutt_debug(LL_DEBUG5, "config, request WA_REFLOW\n");
117 return 0;
118}
119
123static int pager_recalc(struct MuttWindow *win)
124{
125 win->actions |= WA_REPAINT;
126 mutt_debug(LL_DEBUG5, "recalc done, request WA_REPAINT\n");
127 return 0;
128}
129
133static int pager_repaint(struct MuttWindow *win)
134{
135 struct PagerPrivateData *priv = win->wdata;
136 if (!priv || !priv->pview || !priv->pview->pdata)
137 return 0;
138
139#ifdef USE_DEBUG_COLOR
140 dump_pager(priv);
141#endif
142
143 // We need to populate more lines, but not change position
144 const bool repopulate = (priv->cur_line > priv->lines_used);
145 if ((priv->redraw & PAGER_REDRAW_FLOW) || repopulate)
146 {
147 if (!(priv->pview->flags & MUTT_PAGER_RETWINCH))
148 {
149 priv->win_height = -1;
150 for (int i = 0; i <= priv->top_line; i++)
151 if (!priv->lines[i].cont_line)
152 priv->win_height++;
153 for (int i = 0; i < priv->lines_max; i++)
154 {
155 priv->lines[i].offset = 0;
156 priv->lines[i].cid = -1;
157 priv->lines[i].cont_line = 0;
158 priv->lines[i].syntax_arr_size = 0;
159 priv->lines[i].search_arr_size = -1;
160 priv->lines[i].quote = NULL;
161
162 mutt_mem_realloc(&(priv->lines[i].syntax), sizeof(struct TextSyntax));
163 if (priv->search_compiled && priv->lines[i].search)
164 FREE(&(priv->lines[i].search));
165 }
166
167 if (!repopulate)
168 {
169 priv->lines_used = 0;
170 priv->top_line = 0;
171 }
172 }
173 int i = -1;
174 int j = -1;
175 while (display_line(priv->fp, &priv->bytes_read, &priv->lines, ++i,
176 &priv->lines_used, &priv->lines_max,
177 priv->has_types | priv->search_flag | (priv->pview->flags & MUTT_PAGER_NOWRAP),
178 &priv->quote_list, &priv->q_level, &priv->force_redraw,
179 &priv->search_re, priv->pview->win_pager, &priv->ansi_list) == 0)
180 {
181 if (!priv->lines[i].cont_line && (++j == priv->win_height))
182 {
183 if (!repopulate)
184 priv->top_line = i;
185 if (!priv->search_flag)
186 break;
187 }
188 }
189 }
190
191 if ((priv->redraw & PAGER_REDRAW_PAGER) || (priv->top_line != priv->old_top_line))
192 {
193 do
194 {
195 mutt_window_move(priv->pview->win_pager, 0, 0);
196 priv->cur_line = priv->top_line;
197 priv->old_top_line = priv->top_line;
198 priv->win_height = 0;
199 priv->force_redraw = false;
200
201 while ((priv->win_height < priv->pview->win_pager->state.rows) &&
202 (priv->lines[priv->cur_line].offset <= priv->st.st_size - 1))
203 {
204 if (display_line(priv->fp, &priv->bytes_read, &priv->lines,
205 priv->cur_line, &priv->lines_used, &priv->lines_max,
206 (priv->pview->flags & MUTT_DISPLAYFLAGS) | priv->hide_quoted |
207 priv->search_flag | (priv->pview->flags & MUTT_PAGER_NOWRAP),
208 &priv->quote_list, &priv->q_level, &priv->force_redraw,
209 &priv->search_re, priv->pview->win_pager, &priv->ansi_list) > 0)
210 {
211 priv->win_height++;
212 }
213 priv->cur_line++;
214 mutt_window_move(priv->pview->win_pager, 0, priv->win_height);
215 }
216 } while (priv->force_redraw);
217 // curses_colors_dump();
218 // attr_color_list_dump(&priv->ansi_list, "All AnsiColors");
219
220 const bool c_tilde = cs_subset_bool(NeoMutt->sub, "tilde");
222 while (priv->win_height < priv->pview->win_pager->state.rows)
223 {
225 if (c_tilde)
226 mutt_window_addch(priv->pview->win_pager, '~');
227 priv->win_height++;
228 mutt_window_move(priv->pview->win_pager, 0, priv->win_height);
229 }
231 }
232
234 mutt_debug(LL_DEBUG5, "repaint done\n");
235 return 0;
236}
237
242{
243 if (nc->event_type != NT_COLOR)
244 return 0;
245 if (!nc->global_data || !nc->event_data)
246 return -1;
247
248 struct EventColor *ev_c = nc->event_data;
249 struct MuttWindow *win_pager = nc->global_data;
250 struct PagerPrivateData *priv = win_pager->wdata;
251 if (!priv)
252 return 0;
253
254 // MT_COLOR_MAX is sent on `uncolor *`
255 if ((ev_c->cid == MT_COLOR_QUOTED) || (ev_c->cid == MT_COLOR_MAX))
256 {
257 // rework quoted colours
259 }
260
261 if (ev_c->cid == MT_COLOR_MAX)
262 {
263 for (size_t i = 0; i < priv->lines_max; i++)
264 {
265 FREE(&(priv->lines[i].syntax));
266 // if (priv->search_compiled && priv->lines[i].search)
267 // FREE(&(priv->lines[i].search));
268 // priv->lines[i].syntax_arr_size = 0;
269 }
270 priv->lines_used = 0;
271
272 // if (priv->search_compiled)
273 // {
274 // regfree(&priv->search_re);
275 // priv->search_compiled = false;
276 // }
277 }
278
279 mutt_debug(LL_DEBUG5, "color done\n");
280 return 0;
281}
282
287{
288 if (nc->event_type != NT_CONFIG)
289 return 0;
290 if (!nc->global_data || !nc->event_data)
291 return -1;
292
293 struct EventConfig *ev_c = nc->event_data;
294 struct MuttWindow *win_pager = nc->global_data;
295
296 if (mutt_str_equal(ev_c->name, "pager_index_lines"))
297 {
298 config_pager_index_lines(win_pager);
299 mutt_debug(LL_DEBUG5, "config done\n");
300 }
301
302 return 0;
303}
304
309{
310 if (nc->event_type != NT_GLOBAL)
311 return 0;
312 if (!nc->global_data)
313 return -1;
315 return 0;
316
317 struct MuttWindow *win_pager = nc->global_data;
318
319 struct PagerPrivateData *priv = win_pager->wdata;
320 if (!priv)
321 return 0;
322
323 if ((priv->redraw & PAGER_REDRAW_FLOW) && (priv->pview->flags & MUTT_PAGER_RETWINCH))
324 {
325 priv->rc = OP_REFORMAT_WINCH;
326 }
327
328 return 0;
329}
330
335{
336 if (nc->event_type != NT_INDEX)
337 return 0;
338 if (!nc->global_data)
339 return -1;
340
341 struct MuttWindow *win_pager = nc->global_data;
342
343 struct PagerPrivateData *priv = win_pager->wdata;
344 if (!priv)
345 return 0;
346
347 struct IndexSharedData *shared = nc->event_data;
348
350 {
351 win_pager->actions |= WA_RECALC;
352 mutt_debug(LL_DEBUG5, "index done, request WA_RECALC\n");
353 priv->loop = PAGER_LOOP_QUIT;
354 }
355 else if (nc->event_subtype & NT_INDEX_EMAIL)
356 {
357 win_pager->actions |= WA_RECALC;
358 mutt_debug(LL_DEBUG5, "index done, request WA_RECALC\n");
359 priv->pager_redraw = true;
360 if (shared && shared->email && (priv->loop != PAGER_LOOP_QUIT))
361 {
362 priv->loop = PAGER_LOOP_RELOAD;
363 }
364 else
365 {
366 priv->loop = PAGER_LOOP_QUIT;
367 priv->rc = 0;
368 }
369 }
370
371 return 0;
372}
373
378{
379 if (nc->event_type != NT_PAGER)
380 return 0;
381 if (!nc->global_data || !nc->event_data)
382 return -1;
383
384 mutt_debug(LL_DEBUG5, "pager done\n");
385 return 0;
386}
387
392{
393 if (nc->event_type != NT_WINDOW)
394 return 0;
395 if (!nc->global_data || !nc->event_data)
396 return -1;
398 return 0;
399
400 struct MuttWindow *win_pager = nc->global_data;
401 struct EventWindow *ev_w = nc->event_data;
402 if (ev_w->win != win_pager)
403 return 0;
404
405 struct MuttWindow *dlg = window_find_parent(win_pager, WT_DLG_INDEX);
406 if (!dlg)
407 dlg = window_find_parent(win_pager, WT_DLG_DO_PAGER);
408
409 struct IndexSharedData *shared = dlg->wdata;
410
417
418 mutt_debug(LL_DEBUG5, "window delete done\n");
419
420 return 0;
421}
422
430 struct PagerPrivateData *priv)
431{
435 win->wdata = priv;
436 win->recalc = pager_recalc;
437 win->repaint = pager_repaint;
438
445
446 return win;
447}
Color and attribute parsing.
@ MT_COLOR_QUOTED
Pager: quoted text.
Definition: color.h:61
@ MT_COLOR_MAX
Definition: color.h:91
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:57
@ MT_COLOR_TILDE
Pager: empty lines after message.
Definition: color.h:75
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:102
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:980
Pager Display.
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
static int pager_pager_observer(struct NotifyCallback *nc)
Notification that the Pager has changed - Implements observer_t -.
Definition: pager.c:377
static int pager_color_observer(struct NotifyCallback *nc)
Notification that a Color has changed - Implements observer_t -.
Definition: pager.c:241
static int pager_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: pager.c:286
static int pager_index_observer(struct NotifyCallback *nc)
Notification that the Index has changed - Implements observer_t -.
Definition: pager.c:334
static int pager_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: pager.c:391
static int pager_global_observer(struct NotifyCallback *nc)
Notification that a Global Event occurred - Implements observer_t -.
Definition: pager.c:308
static int pager_recalc(struct MuttWindow *win)
Recalculate the Pager display - Implements MuttWindow::recalc() -.
Definition: pager.c:123
static int pager_repaint(struct MuttWindow *win)
Repaint the Pager display - Implements MuttWindow::repaint() -.
Definition: pager.c:133
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: logging.h:44
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
#define MIN(a, b)
Definition: memory.h:31
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:807
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:501
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:340
struct MuttWindow * window_find_parent(struct MuttWindow *win, enum WindowType type)
Find a (grand-)parent of a Window by type.
Definition: mutt_window.c:547
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
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:293
struct MuttWindow * window_find_child(struct MuttWindow *win, enum WindowType type)
Recursively find a child Window of a given type.
Definition: mutt_window.c:522
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:242
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
Definition: mutt_window.c:381
#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:206
#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:151
@ PAGER_LOOP_QUIT
Quit the Pager.
Definition: lib.h:150
#define MUTT_PAGER_RETWINCH
Need reformatting on SIGWINCH.
Definition: lib.h:69
#define MUTT_PAGER_NOWRAP
Format for term width, ignore $wrap.
Definition: lib.h:71
#define MUTT_DISPLAYFLAGS
Definition: lib.h:76
#define PAGER_REDRAW_FLOW
Reflow the pager.
Definition: lib.h:189
#define PAGER_REDRAW_PAGER
Redraw the pager.
Definition: lib.h:188
#define PAGER_REDRAW_NO_FLAGS
No flags are set.
Definition: lib.h:187
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:429
Private state data for the Pager.
void qstyle_recolour(struct QuoteStyle *quote_list)
Recolour quotes after colour changes.
Definition: quoted.c:608
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:70
const char * name
Name of config item that changed.
Definition: subset.h:72
An Event that happened to a Window.
Definition: mutt_window.h:216
struct MuttWindow * win
Window that changed.
Definition: mutt_window.h:217
Data shared between Index, Pager and Sidebar.
Definition: shared_data.h:37
struct Email * email
Currently selected Email.
Definition: shared_data.h:42
struct Mailbox * mailbox
Current Mailbox.
Definition: shared_data.h:41
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 vcount
The number of virtual messages.
Definition: mailbox.h:99
int(* repaint)(struct MuttWindow *win)
Definition: mutt_window.h:182
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:171
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
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition: lib.h:170
PagerFlags flags
Additional settings to tweak pager's function.
Definition: lib.h:172
struct MuttWindow * win_pager
Pager Window.
Definition: lib.h:177
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