NeoMutt  2025-01-09-41-g086358
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 priv->win_height = -1;
144 for (int i = 0; i <= priv->top_line; i++)
145 if (!priv->lines[i].cont_line)
146 priv->win_height++;
147 for (int i = 0; i < priv->lines_max; i++)
148 {
149 priv->lines[i].offset = 0;
150 priv->lines[i].cid = -1;
151 priv->lines[i].cont_line = false;
152 priv->lines[i].syntax_arr_size = 0;
153 priv->lines[i].search_arr_size = -1;
154 priv->lines[i].quote = NULL;
155
156 MUTT_MEM_REALLOC(&(priv->lines[i].syntax), 1, struct TextSyntax);
157 if (priv->search_compiled && priv->lines[i].search)
158 FREE(&(priv->lines[i].search));
159 }
160
161 if (!repopulate)
162 {
163 priv->lines_used = 0;
164 priv->top_line = 0;
165 }
166
167 int i = -1;
168 int j = -1;
169 const PagerFlags flags = priv->has_types | priv->search_flag |
170 (priv->pview->flags & MUTT_PAGER_NOWRAP) |
171 (priv->pview->flags & MUTT_PAGER_STRIPES);
172
173 while (display_line(priv->fp, &priv->bytes_read, &priv->lines, ++i,
174 &priv->lines_used, &priv->lines_max, flags, &priv->quote_list,
175 &priv->q_level, &priv->force_redraw, &priv->search_re,
176 priv->pview->win_pager, &priv->ansi_list) == 0)
177 {
178 if (!priv->lines[i].cont_line && (++j == priv->win_height))
179 {
180 if (!repopulate)
181 priv->top_line = i;
182 if (!priv->search_flag)
183 break;
184 }
185 }
186 }
187
188 if ((priv->redraw & PAGER_REDRAW_PAGER) || (priv->top_line != priv->old_top_line))
189 {
190 do
191 {
192 mutt_window_move(priv->pview->win_pager, 0, 0);
193 priv->cur_line = priv->top_line;
194 priv->old_top_line = priv->top_line;
195 priv->win_height = 0;
196 priv->force_redraw = false;
197
198 while ((priv->win_height < priv->pview->win_pager->state.rows) &&
199 (priv->lines[priv->cur_line].offset <= priv->st.st_size - 1))
200 {
201 const PagerFlags flags = (priv->pview->flags & MUTT_DISPLAYFLAGS) |
202 priv->hide_quoted | priv->search_flag |
203 (priv->pview->flags & MUTT_PAGER_NOWRAP) |
204 (priv->pview->flags & MUTT_PAGER_STRIPES);
205
206 if (display_line(priv->fp, &priv->bytes_read, &priv->lines, priv->cur_line,
207 &priv->lines_used, &priv->lines_max, flags, &priv->quote_list,
208 &priv->q_level, &priv->force_redraw, &priv->search_re,
209 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, priv->win_height, 0);
215 }
216 } while (priv->force_redraw);
217
218 const bool c_tilde = cs_subset_bool(NeoMutt->sub, "tilde");
220 while (priv->win_height < priv->pview->win_pager->state.rows)
221 {
223 if (c_tilde)
224 mutt_window_addch(priv->pview->win_pager, '~');
225 priv->win_height++;
226 mutt_window_move(priv->pview->win_pager, priv->win_height, 0);
227 }
229 }
230
232 mutt_debug(LL_DEBUG5, "repaint done\n");
233 return 0;
234}
235
240{
241 if (nc->event_type != NT_COLOR)
242 return 0;
243 if (!nc->global_data || !nc->event_data)
244 return -1;
245
246 struct EventColor *ev_c = nc->event_data;
247 struct MuttWindow *win_pager = nc->global_data;
248 struct PagerPrivateData *priv = win_pager->wdata;
249 if (!priv)
250 return 0;
251
252 // MT_COLOR_MAX is sent on `uncolor *`
253 if (COLOR_QUOTED(ev_c->cid) || (ev_c->cid == MT_COLOR_MAX))
254 {
255 // rework quoted colours
257 }
258
259 if (ev_c->cid == MT_COLOR_MAX)
260 {
261 for (size_t i = 0; i < priv->lines_max; i++)
262 {
263 FREE(&(priv->lines[i].syntax));
264 }
265 priv->lines_used = 0;
266 }
267
268 mutt_debug(LL_DEBUG5, "color done\n");
269 return 0;
270}
271
276{
277 if (nc->event_type != NT_CONFIG)
278 return 0;
279 if (!nc->global_data || !nc->event_data)
280 return -1;
281
282 struct EventConfig *ev_c = nc->event_data;
283 struct MuttWindow *win_pager = nc->global_data;
284
285 if (mutt_str_equal(ev_c->name, "pager_index_lines"))
286 {
287 config_pager_index_lines(win_pager);
288 mutt_debug(LL_DEBUG5, "config done\n");
289 }
290
291 return 0;
292}
293
298{
299 if (nc->event_type != NT_INDEX)
300 return 0;
301 if (!nc->global_data)
302 return -1;
303
304 struct MuttWindow *win_pager = nc->global_data;
305
306 struct PagerPrivateData *priv = win_pager->wdata;
307 if (!priv)
308 return 0;
309
310 struct IndexSharedData *shared = nc->event_data;
311
313 {
314 win_pager->actions |= WA_RECALC;
315 mutt_debug(LL_DEBUG5, "index done, request WA_RECALC\n");
316 priv->loop = PAGER_LOOP_QUIT;
317 }
318 else if (nc->event_subtype & NT_INDEX_EMAIL)
319 {
320 win_pager->actions |= WA_RECALC;
321 mutt_debug(LL_DEBUG5, "index done, request WA_RECALC\n");
322 priv->pager_redraw = true;
323 if (shared && shared->email && (priv->loop != PAGER_LOOP_QUIT))
324 {
325 priv->loop = PAGER_LOOP_RELOAD;
326 }
327 else
328 {
329 priv->loop = PAGER_LOOP_QUIT;
330 priv->rc = 0;
331 }
332 }
333
334 return 0;
335}
336
341{
342 if (nc->event_type != NT_PAGER)
343 return 0;
344 if (!nc->global_data || !nc->event_data)
345 return -1;
346
347 mutt_debug(LL_DEBUG5, "pager done\n");
348 return 0;
349}
350
355{
356 if (nc->event_type != NT_WINDOW)
357 return 0;
358 if (!nc->global_data || !nc->event_data)
359 return -1;
361 return 0;
362
363 struct MuttWindow *win_pager = nc->global_data;
364 struct EventWindow *ev_w = nc->event_data;
365 if (ev_w->win != win_pager)
366 return 0;
367
368 struct MuttWindow *dlg = window_find_parent(win_pager, WT_DLG_INDEX);
369 if (!dlg)
370 dlg = window_find_parent(win_pager, WT_DLG_PAGER);
371
372 struct IndexSharedData *shared = dlg->wdata;
373
379
380 mutt_debug(LL_DEBUG5, "window delete done\n");
381
382 return 0;
383}
384
392 struct PagerPrivateData *priv)
393{
397 win->wdata = priv;
398 win->recalc = pager_recalc;
399 win->repaint = pager_repaint;
400
406
407 return win;
408}
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.
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:89
static int pager_pager_observer(struct NotifyCallback *nc)
Notification that the Pager has changed - Implements observer_t -.
Definition: pager.c:340
static int pager_color_observer(struct NotifyCallback *nc)
Notification that a Color has changed - Implements observer_t -.
Definition: pager.c:239
static int pager_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: pager.c:275
static int pager_index_observer(struct NotifyCallback *nc)
Notification that the Index has changed - Implements observer_t -.
Definition: pager.c:297
static int pager_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: pager.c:354
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:474
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:306
struct MuttWindow * window_find_parent(struct MuttWindow *win, enum WindowType type)
Find a (grand-)parent of a Window by type.
Definition: mutt_window.c:520
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: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:495
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:350
#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:83
struct MuttWindow * pager_window_new(struct IndexSharedData *shared, struct PagerPrivateData *priv)
Create a new Pager Window (list of Emails)
Definition: pager.c:391
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: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 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
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