NeoMutt  2025-01-09-117-gace867
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 "debug/lib.h"
72#include "lib.h"
73#include "color/lib.h"
74#include "index/lib.h"
75#include "display.h"
76#include "private_data.h"
77
84static int config_pager_index_lines(struct MuttWindow *win)
85{
86 if (!mutt_window_is_visible(win))
87 return 0;
88
89 struct MuttWindow *dlg = dialog_find(win);
90 struct MuttWindow *panel_index = window_find_child(dlg, WT_INDEX);
91 struct MuttWindow *win_index = window_find_child(panel_index, WT_MENU);
92 if (!win_index)
93 return -1;
94
95 const short c_pager_index_lines = cs_subset_number(NeoMutt->sub, "pager_index_lines");
96
97 if (c_pager_index_lines > 0)
98 {
99 win_index->req_rows = c_pager_index_lines;
100 win_index->size = MUTT_WIN_SIZE_FIXED;
101
102 panel_index->size = MUTT_WIN_SIZE_MINIMISE;
103 panel_index->state.visible = true;
104 }
105 else
106 {
108 win_index->size = MUTT_WIN_SIZE_MAXIMISE;
109
110 panel_index->size = MUTT_WIN_SIZE_MAXIMISE;
111 panel_index->state.visible = false;
112 }
113
115 mutt_debug(LL_DEBUG5, "config, request WA_REFLOW\n");
116 return 0;
117}
118
122static int pager_recalc(struct MuttWindow *win)
123{
124 win->actions |= WA_REPAINT;
125 mutt_debug(LL_DEBUG5, "recalc done, request WA_REPAINT\n");
126 return 0;
127}
128
132static int pager_repaint(struct MuttWindow *win)
133{
134 struct PagerPrivateData *priv = win->wdata;
135 if (!priv || !priv->pview || !priv->pview->pdata)
136 return 0;
137
138 dump_pager(priv);
139
140 // We need to populate more lines, but not change position
141 const bool repopulate = (priv->cur_line > priv->lines_used);
142 if ((priv->redraw & PAGER_REDRAW_FLOW) || repopulate)
143 {
144 priv->win_height = -1;
145 for (int i = 0; i <= priv->top_line; i++)
146 if (!priv->lines[i].cont_line)
147 priv->win_height++;
148 for (int i = 0; i < priv->lines_max; i++)
149 {
150 priv->lines[i].offset = 0;
151 priv->lines[i].cid = -1;
152 priv->lines[i].cont_line = false;
153 priv->lines[i].syntax_arr_size = 0;
154 priv->lines[i].search_arr_size = -1;
155 priv->lines[i].quote = NULL;
156
157 MUTT_MEM_REALLOC(&(priv->lines[i].syntax), 1, struct TextSyntax);
158 if (priv->search_compiled && priv->lines[i].search)
159 FREE(&(priv->lines[i].search));
160 }
161
162 if (!repopulate)
163 {
164 priv->lines_used = 0;
165 priv->top_line = 0;
166 }
167
168 int i = -1;
169 int j = -1;
170 const PagerFlags flags = priv->has_types | priv->search_flag |
171 (priv->pview->flags & MUTT_PAGER_NOWRAP) |
172 (priv->pview->flags & MUTT_PAGER_STRIPES);
173
174 while (display_line(priv->fp, &priv->bytes_read, &priv->lines, ++i,
175 &priv->lines_used, &priv->lines_max, flags, &priv->quote_list,
176 &priv->q_level, &priv->force_redraw, &priv->search_re,
177 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 const PagerFlags flags = (priv->pview->flags & MUTT_DISPLAYFLAGS) |
203 priv->hide_quoted | priv->search_flag |
204 (priv->pview->flags & MUTT_PAGER_NOWRAP) |
205 (priv->pview->flags & MUTT_PAGER_STRIPES);
206
207 if (display_line(priv->fp, &priv->bytes_read, &priv->lines, priv->cur_line,
208 &priv->lines_used, &priv->lines_max, flags, &priv->quote_list,
209 &priv->q_level, &priv->force_redraw, &priv->search_re,
210 priv->pview->win_pager, &priv->ansi_list) > 0)
211 {
212 priv->win_height++;
213 }
214 priv->cur_line++;
215 mutt_window_move(priv->pview->win_pager, priv->win_height, 0);
216 }
217 } while (priv->force_redraw);
218
219 const bool c_tilde = cs_subset_bool(NeoMutt->sub, "tilde");
221 while (priv->win_height < priv->pview->win_pager->state.rows)
222 {
224 if (c_tilde)
225 mutt_window_addch(priv->pview->win_pager, '~');
226 priv->win_height++;
227 mutt_window_move(priv->pview->win_pager, priv->win_height, 0);
228 }
230 }
231
233 mutt_debug(LL_DEBUG5, "repaint done\n");
234 return 0;
235}
236
241{
242 if (nc->event_type != NT_COLOR)
243 return 0;
244 if (!nc->global_data || !nc->event_data)
245 return -1;
246
247 struct EventColor *ev_c = nc->event_data;
248 struct MuttWindow *win_pager = nc->global_data;
249 struct PagerPrivateData *priv = win_pager->wdata;
250 if (!priv)
251 return 0;
252
253 // MT_COLOR_MAX is sent on `uncolor *`
254 if (COLOR_QUOTED(ev_c->cid) || (ev_c->cid == MT_COLOR_MAX))
255 {
256 // rework quoted colours
258 }
259
260 if (ev_c->cid == MT_COLOR_MAX)
261 {
262 for (size_t i = 0; i < priv->lines_max; i++)
263 {
264 FREE(&(priv->lines[i].syntax));
265 }
266 priv->lines_used = 0;
267 }
268
269 mutt_debug(LL_DEBUG5, "color done\n");
270 return 0;
271}
272
277{
278 if (nc->event_type != NT_CONFIG)
279 return 0;
280 if (!nc->global_data || !nc->event_data)
281 return -1;
282
283 struct EventConfig *ev_c = nc->event_data;
284 struct MuttWindow *win_pager = nc->global_data;
285
286 if (mutt_str_equal(ev_c->name, "pager_index_lines"))
287 {
288 config_pager_index_lines(win_pager);
289 mutt_debug(LL_DEBUG5, "config done\n");
290 }
291
292 return 0;
293}
294
299{
300 if (nc->event_type != NT_INDEX)
301 return 0;
302 if (!nc->global_data)
303 return -1;
304
305 struct MuttWindow *win_pager = nc->global_data;
306
307 struct PagerPrivateData *priv = win_pager->wdata;
308 if (!priv)
309 return 0;
310
311 struct IndexSharedData *shared = nc->event_data;
312
314 {
315 win_pager->actions |= WA_RECALC;
316 mutt_debug(LL_DEBUG5, "index done, request WA_RECALC\n");
317 priv->loop = PAGER_LOOP_QUIT;
318 }
319 else if (nc->event_subtype & NT_INDEX_EMAIL)
320 {
321 win_pager->actions |= WA_RECALC;
322 mutt_debug(LL_DEBUG5, "index done, request WA_RECALC\n");
323 priv->pager_redraw = true;
324 if (shared && shared->email && (priv->loop != PAGER_LOOP_QUIT))
325 {
326 priv->loop = PAGER_LOOP_RELOAD;
327 }
328 else
329 {
330 priv->loop = PAGER_LOOP_QUIT;
331 priv->rc = 0;
332 }
333 }
334
335 return 0;
336}
337
342{
343 if (nc->event_type != NT_PAGER)
344 return 0;
345 if (!nc->global_data || !nc->event_data)
346 return -1;
347
348 mutt_debug(LL_DEBUG5, "pager done\n");
349 return 0;
350}
351
356{
357 if (nc->event_type != NT_WINDOW)
358 return 0;
359 if (!nc->global_data || !nc->event_data)
360 return -1;
362 return 0;
363
364 struct MuttWindow *win_pager = nc->global_data;
365 struct EventWindow *ev_w = nc->event_data;
366 if (ev_w->win != win_pager)
367 return 0;
368
369 struct MuttWindow *dlg = window_find_parent(win_pager, WT_DLG_INDEX);
370 if (!dlg)
371 dlg = window_find_parent(win_pager, WT_DLG_PAGER);
372
373 struct IndexSharedData *shared = dlg->wdata;
374
380
381 mutt_debug(LL_DEBUG5, "window delete done\n");
382
383 return 0;
384}
385
393 struct PagerPrivateData *priv)
394{
398 win->wdata = priv;
399 win->recalc = pager_recalc;
400 win->repaint = pager_repaint;
401
407
408 return win;
409}
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:99
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:55
@ MT_COLOR_TILDE
Pager: empty lines after message.
Definition: color.h:83
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.
Convenience wrapper for the debug headers.
void dump_pager(struct PagerPrivateData *priv)
Definition: pager.c:128
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:90
static int pager_pager_observer(struct NotifyCallback *nc)
Notification that the Pager has changed - Implements observer_t -.
Definition: pager.c:341
static int pager_color_observer(struct NotifyCallback *nc)
Notification that a Color has changed - Implements observer_t -.
Definition: pager.c:240
static int pager_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: pager.c:276
static int pager_index_observer(struct NotifyCallback *nc)
Notification that the Index has changed - Implements observer_t -.
Definition: pager.c:298
static int pager_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: pager.c:355
static int pager_recalc(struct MuttWindow *win)
Recalculate the Pager display - Implements MuttWindow::recalc() -.
Definition: pager.c:122
static int pager_repaint(struct MuttWindow *win)
Repaint the Pager display - Implements MuttWindow::repaint() -.
Definition: pager.c:132
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:48
#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:661
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:477
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:309
struct MuttWindow * window_find_parent(struct MuttWindow *win, enum WindowType type)
Find a (grand-)parent of a Window by type.
Definition: mutt_window.c:523
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 row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:300
struct MuttWindow * window_find_child(struct MuttWindow *win, enum WindowType type)
Recursively find a child Window of a given type.
Definition: mutt_window.c:498
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:247
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
Definition: mutt_window.c:353
#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_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
@ 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_NOWRAP
Format for term width, ignore $wrap.
Definition: lib.h:71
#define MUTT_DISPLAYFLAGS
Definition: lib.h:77
uint16_t PagerFlags
Flags for dlg_pager(), e.g. MUTT_SHOWFLAT.
Definition: lib.h:59
#define MUTT_PAGER_STRIPES
Striped highlighting.
Definition: lib.h:74
#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:84
struct MuttWindow * pager_window_new(struct IndexSharedData *shared, struct PagerPrivateData *priv)
Create a new Pager Window (list of Emails)
Definition: pager.c:392
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:28
Key value store.
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition: subset.h:51
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: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: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:43
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:47
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: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: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