NeoMutt  2024-12-12-14-g7b49f7
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
pager.c
Go to the documentation of this file.
1
63#include "config.h"
64#include <stdbool.h>
65#include <stddef.h>
66#include <sys/stat.h>
67#include "mutt/lib.h"
68#include "config/lib.h"
69#include "core/lib.h"
70#include "gui/lib.h"
71#include "lib.h"
72#include "color/lib.h"
73#include "index/lib.h"
74#include "display.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 dump_pager(priv);
138
139 // We need to populate more lines, but not change position
140 const bool repopulate = (priv->cur_line > priv->lines_used);
141 if ((priv->redraw & PAGER_REDRAW_FLOW) || repopulate)
142 {
143 if (!(priv->pview->flags & MUTT_PAGER_RETWINCH))
144 {
145 priv->win_height = -1;
146 for (int i = 0; i <= priv->top_line; i++)
147 if (!priv->lines[i].cont_line)
148 priv->win_height++;
149 for (int i = 0; i < priv->lines_max; i++)
150 {
151 priv->lines[i].offset = 0;
152 priv->lines[i].cid = -1;
153 priv->lines[i].cont_line = false;
154 priv->lines[i].syntax_arr_size = 0;
155 priv->lines[i].search_arr_size = -1;
156 priv->lines[i].quote = NULL;
157
158 MUTT_MEM_REALLOC(&(priv->lines[i].syntax), 1, struct TextSyntax);
159 if (priv->search_compiled && priv->lines[i].search)
160 FREE(&(priv->lines[i].search));
161 }
162
163 if (!repopulate)
164 {
165 priv->lines_used = 0;
166 priv->top_line = 0;
167 }
168 }
169 int i = -1;
170 int j = -1;
171 const PagerFlags flags = priv->has_types | priv->search_flag |
172 (priv->pview->flags & MUTT_PAGER_NOWRAP) |
173 (priv->pview->flags & MUTT_PAGER_STRIPES);
174
175 while (display_line(priv->fp, &priv->bytes_read, &priv->lines, ++i,
176 &priv->lines_used, &priv->lines_max, flags, &priv->quote_list,
177 &priv->q_level, &priv->force_redraw, &priv->search_re,
178 priv->pview->win_pager, &priv->ansi_list) == 0)
179 {
180 if (!priv->lines[i].cont_line && (++j == priv->win_height))
181 {
182 if (!repopulate)
183 priv->top_line = i;
184 if (!priv->search_flag)
185 break;
186 }
187 }
188 }
189
190 if ((priv->redraw & PAGER_REDRAW_PAGER) || (priv->top_line != priv->old_top_line))
191 {
192 do
193 {
194 mutt_window_move(priv->pview->win_pager, 0, 0);
195 priv->cur_line = priv->top_line;
196 priv->old_top_line = priv->top_line;
197 priv->win_height = 0;
198 priv->force_redraw = false;
199
200 while ((priv->win_height < priv->pview->win_pager->state.rows) &&
201 (priv->lines[priv->cur_line].offset <= priv->st.st_size - 1))
202 {
203 const PagerFlags flags = (priv->pview->flags & MUTT_DISPLAYFLAGS) |
204 priv->hide_quoted | priv->search_flag |
205 (priv->pview->flags & MUTT_PAGER_NOWRAP) |
206 (priv->pview->flags & MUTT_PAGER_STRIPES);
207
208 if (display_line(priv->fp, &priv->bytes_read, &priv->lines, priv->cur_line,
209 &priv->lines_used, &priv->lines_max, flags, &priv->quote_list,
210 &priv->q_level, &priv->force_redraw, &priv->search_re,
211 priv->pview->win_pager, &priv->ansi_list) > 0)
212 {
213 priv->win_height++;
214 }
215 priv->cur_line++;
216 mutt_window_move(priv->pview->win_pager, 0, priv->win_height);
217 }
218 } while (priv->force_redraw);
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 (COLOR_QUOTED(ev_c->cid) || (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 }
267 priv->lines_used = 0;
268 }
269
270 mutt_debug(LL_DEBUG5, "color done\n");
271 return 0;
272}
273
278{
279 if (nc->event_type != NT_CONFIG)
280 return 0;
281 if (!nc->global_data || !nc->event_data)
282 return -1;
283
284 struct EventConfig *ev_c = nc->event_data;
285 struct MuttWindow *win_pager = nc->global_data;
286
287 if (mutt_str_equal(ev_c->name, "pager_index_lines"))
288 {
289 config_pager_index_lines(win_pager);
290 mutt_debug(LL_DEBUG5, "config done\n");
291 }
292
293 return 0;
294}
295
300{
301 if (nc->event_type != NT_GLOBAL)
302 return 0;
303 if (!nc->global_data)
304 return -1;
306 return 0;
307
308 struct MuttWindow *win_pager = nc->global_data;
309
310 struct PagerPrivateData *priv = win_pager->wdata;
311 const struct PagerView *pview = priv ? priv->pview : NULL;
312 if (priv && pview && (priv->redraw & PAGER_REDRAW_FLOW) && (pview->flags & MUTT_PAGER_RETWINCH))
313 {
314 priv->rc = OP_REFORMAT_WINCH;
315 }
316
317 return 0;
318}
319
324{
325 if (nc->event_type != NT_INDEX)
326 return 0;
327 if (!nc->global_data)
328 return -1;
329
330 struct MuttWindow *win_pager = nc->global_data;
331
332 struct PagerPrivateData *priv = win_pager->wdata;
333 if (!priv)
334 return 0;
335
336 struct IndexSharedData *shared = nc->event_data;
337
339 {
340 win_pager->actions |= WA_RECALC;
341 mutt_debug(LL_DEBUG5, "index done, request WA_RECALC\n");
342 priv->loop = PAGER_LOOP_QUIT;
343 }
344 else if (nc->event_subtype & NT_INDEX_EMAIL)
345 {
346 win_pager->actions |= WA_RECALC;
347 mutt_debug(LL_DEBUG5, "index done, request WA_RECALC\n");
348 priv->pager_redraw = true;
349 if (shared && shared->email && (priv->loop != PAGER_LOOP_QUIT))
350 {
351 priv->loop = PAGER_LOOP_RELOAD;
352 }
353 else
354 {
355 priv->loop = PAGER_LOOP_QUIT;
356 priv->rc = 0;
357 }
358 }
359
360 return 0;
361}
362
367{
368 if (nc->event_type != NT_PAGER)
369 return 0;
370 if (!nc->global_data || !nc->event_data)
371 return -1;
372
373 mutt_debug(LL_DEBUG5, "pager done\n");
374 return 0;
375}
376
381{
382 if (nc->event_type != NT_WINDOW)
383 return 0;
384 if (!nc->global_data || !nc->event_data)
385 return -1;
387 return 0;
388
389 struct MuttWindow *win_pager = nc->global_data;
390 struct EventWindow *ev_w = nc->event_data;
391 if (ev_w->win != win_pager)
392 return 0;
393
394 struct MuttWindow *dlg = window_find_parent(win_pager, WT_DLG_INDEX);
395 if (!dlg)
396 dlg = window_find_parent(win_pager, WT_DLG_PAGER);
397
398 struct IndexSharedData *shared = dlg->wdata;
399
406
407 mutt_debug(LL_DEBUG5, "window delete done\n");
408
409 return 0;
410}
411
419 struct PagerPrivateData *priv)
420{
424 win->wdata = priv;
425 win->recalc = pager_recalc;
426 win->repaint = pager_repaint;
427
434
435 return win;
436}
Color and attribute parsing.
void mutt_color_observer_remove(observer_t callback, void *global_data)
Remove an observer.
Definition: notify.c:71
void mutt_color_observer_add(observer_t callback, void *global_data)
Add an observer.
Definition: notify.c:61
@ MT_COLOR_MAX
Definition: color.h:90
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:55
@ MT_COLOR_TILDE
Pager: empty lines after message.
Definition: color.h:74
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:143
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:47
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:89
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:1052
Pager Display.
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
static int pager_pager_observer(struct NotifyCallback *nc)
Notification that the Pager has changed - Implements observer_t -.
Definition: pager.c:366
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:277
static int pager_index_observer(struct NotifyCallback *nc)
Notification that the Index has changed - Implements observer_t -.
Definition: pager.c:323
static int pager_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: pager.c:380
static int pager_global_observer(struct NotifyCallback *nc)
Notification that a Global Event occurred - Implements observer_t -.
Definition: pager.c:299
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:70
#define NT_INDEX_EMAIL
Email has changed.
Definition: lib.h:71
@ LL_DEBUG5
Log at debug level 5.
Definition: logging2.h:47
#define FREE(x)
Definition: memory.h:55
#define MUTT_MEM_REALLOC(pptr, n, type)
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:230
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
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:660
const 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:63
const struct AttrColor * mutt_curses_set_color_by_id(enum ColorId cid)
Set the colour and attributes by the colour id.
Definition: mutt_curses.c:79
bool mutt_window_is_visible(struct MuttWindow *win)
Is the Window visible?
Definition: mutt_window.c:512
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:344
struct MuttWindow * window_find_parent(struct MuttWindow *win, enum WindowType type)
Find a (grand-)parent of a Window by type.
Definition: mutt_window.c:558
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:182
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:297
struct MuttWindow * window_find_child(struct MuttWindow *win, enum WindowType type)
Recursively find a child Window of a given type.
Definition: mutt_window.c:533
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:244
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
Definition: mutt_window.c:388
#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, dlg_index()
Definition: mutt_window.h:87
@ WT_INDEX
A panel containing the Index Window.
Definition: mutt_window.h:97
@ WT_DLG_PAGER
Pager Dialog, dlg_pager()
Definition: mutt_window.h:85
@ 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:39
@ NT_WINDOW_DELETE
Window is about to be deleted.
Definition: mutt_window.h:229
#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:53
@ MUTT_WIN_SIZE_FIXED
Window has a fixed size.
Definition: mutt_window.h:48
@ MUTT_WIN_SIZE_MINIMISE
Window size depends on its children.
Definition: mutt_window.h:50
@ MUTT_WIN_SIZE_MAXIMISE
Window wants as much space as possible.
Definition: mutt_window.h:49
@ NT_GLOBAL_COMMAND
A NeoMutt command.
Definition: neomutt.h:63
@ NT_WINDOW
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:57
@ 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:53
@ 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
@ PAGER_LOOP_RELOAD
Reload the Pager from scratch.
Definition: lib.h:154
@ PAGER_LOOP_QUIT
Quit the Pager.
Definition: lib.h:153
#define MUTT_PAGER_RETWINCH
Need reformatting on SIGWINCH.
Definition: lib.h:71
#define MUTT_PAGER_NOWRAP
Format for term width, ignore $wrap.
Definition: lib.h:73
#define MUTT_DISPLAYFLAGS
Definition: lib.h:79
uint16_t PagerFlags
Flags for dlg_pager(), e.g. MUTT_SHOWFLAT.
Definition: lib.h:59
#define MUTT_PAGER_STRIPES
Striped highlighting.
Definition: lib.h:76
#define PAGER_REDRAW_FLOW
Reflow the pager.
Definition: lib.h:192
#define PAGER_REDRAW_PAGER
Redraw the pager.
Definition: lib.h:191
#define PAGER_REDRAW_NO_FLAGS
No flags are set.
Definition: lib.h:190
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:418
Private state data for the Pager.
void qstyle_recolor(struct QuoteStyle *quote_list)
Recolour quotes after colour changes.
Definition: qstyle.c:464
#define COLOR_QUOTED(cid)
Definition: quoted.h:39
Key value store.
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition: subset.h:52
An Event that happened to a Colour.
Definition: notify2.h:55
enum ColorId cid
Colour ID that has changed.
Definition: notify2.h:56
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:239
struct MuttWindow * win
Window that changed.
Definition: mutt_window.h:240
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:59
struct TextSyntax * search
Array of search text in the line.
Definition: display.h:60
bool cont_line
Continuation of a previous line (wrapped by NeoMutt)
Definition: display.h:53
short cid
Default line colour, e.g. MT_COLOR_SIGNATURE.
Definition: display.h:52
struct QuoteStyle * quote
Quoting style for this line (pointer into PagerPrivateData->quote_list)
Definition: display.h:62
LOFF_T offset
Offset into Email file (PagerPrivateData->fp)
Definition: display.h:51
short syntax_arr_size
Number of items in syntax array.
Definition: display.h:56
struct TextSyntax * syntax
Array of coloured text in the line.
Definition: display.h:57
int(* repaint)(struct MuttWindow *win)
Definition: mutt_window.h:187
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:173
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:42
struct Notify * notify
Notifications handler.
Definition: neomutt.h:43
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
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:172
struct PagerData * pdata
Data that pager displays. NOTNULL.
Definition: lib.h:173
PagerFlags flags
Additional settings to tweak pager's function.
Definition: lib.h:175
struct MuttWindow * win_pager
Pager Window.
Definition: lib.h:180
Highlighting for a piece of text.
Definition: display.h:39
bool visible
Window is visible.
Definition: mutt_window.h:60
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:62