1 /**
2 * @file
3 * Simple Pager Dialog
4 *
5 * @authors
6 * Copyright (C) 1996-2002,2007,2010,2012-2013 Michael R. Elkins <me@mutt.org>
7 * Copyright (C) 2020 R Primus <rprimus@gmail.com>
8 *
9 * @copyright
10 * This program is free software: you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License as published by the Free Software
12 * Foundation, either version 2 of the License, or (at your option) any later
13 * version.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 * details.
19 *
20 * You should have received a copy of the GNU General Public License along with
21 * this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 /**
25 * @page pager_dopager Simple Pager Dialog
26 *
27 * The Simple Pager Dialog displays text to the user that can be paged.
28 *
29 * ## Windows
30 *
31 * | Name | Type | Constructor |
32 * | :------------------ | :--------------- | :-------------- |
33 * | Simple Pager Dialog | #WT_DLG_DO_PAGER | mutt_do_pager() |
34 *
35 * **Parent**
36 * - @ref gui_dialog
37 *
38 * **Children**
39 * - @ref pager_ppanel
40 *
41 * ## Data
42 *
43 * The Simple Pager Dialog has no data.
44 *
45 * ## Events
46 *
47 * Once constructed, it is controlled by the following events:
48 *
49 * | Event Type | Handler |
50 * | :---------- | :------------------------ |
51 * | #NT_CONFIG | dopager_config_observer() |
52 * | #NT_WINDOW | dopager_window_observer() |
53 *
54 * The Simple Pager Dialog does not implement MuttWindow::recalc() or
55 * MuttWindow::repaint().
56 */
57
58 #include "config.h"
59 #include <stddef.h>
60 #include <assert.h>
61 #include <stdbool.h>
62 #include "mutt/lib.h"
63 #include "config/lib.h"
64 #include "core/lib.h"
65 #include "gui/lib.h"
66 #include "lib.h"
67 #include "index/lib.h"
68 #include "protos.h"
69
70 struct Email;
71
72 /**
73 * dopager_config_observer - Notification that a Config Variable has changed - Implements ::observer_t - @ingroup observer_api
74 */
dopager_config_observer(struct NotifyCallback * nc)75 static int dopager_config_observer(struct NotifyCallback *nc)
76 {
77 if ((nc->event_type != NT_CONFIG) || !nc->global_data || !nc->event_data)
78 return -1;
79
80 struct EventConfig *ev_c = nc->event_data;
81 if (!mutt_str_equal(ev_c->name, "status_on_top"))
82 return 0;
83
84 struct MuttWindow *dlg = nc->global_data;
85 window_status_on_top(dlg, NeoMutt->sub);
86 mutt_debug(LL_DEBUG5, "config done, request WA_REFLOW\n");
87 return 0;
88 }
89
90 /**
91 * dopager_window_observer - Notification that a Window has changed - Implements ::observer_t - @ingroup observer_api
92 */
dopager_window_observer(struct NotifyCallback * nc)93 static int dopager_window_observer(struct NotifyCallback *nc)
94 {
95 if ((nc->event_type != NT_WINDOW) || !nc->global_data || !nc->event_data)
96 return -1;
97
98 if (nc->event_subtype != NT_WINDOW_DELETE)
99 return 0;
100
101 struct MuttWindow *dlg = nc->global_data;
102 struct EventWindow *ev_w = nc->event_data;
103 if (ev_w->win != dlg)
104 return 0;
105
106 notify_observer_remove(NeoMutt->notify, dopager_config_observer, dlg);
107 notify_observer_remove(dlg->notify, dopager_window_observer, dlg);
108 mutt_debug(LL_DEBUG5, "window delete done\n");
109
110 return 0;
111 }
112
113 /**
114 * mutt_do_pager - Display some page-able text to the user (help or attachment)
115 * @param pview PagerView to construct Pager object
116 * @param e Email to use
117 * @retval 0 Success
118 * @retval -1 Error
119 */
mutt_do_pager(struct PagerView * pview,struct Email * e)120 int mutt_do_pager(struct PagerView *pview, struct Email *e)
121 {
122 assert(pview);
123 assert(pview->pdata);
124 assert(pview->pdata->fname);
125 assert((pview->mode == PAGER_MODE_ATTACH) ||
126 (pview->mode == PAGER_MODE_HELP) || (pview->mode == PAGER_MODE_OTHER));
127
128 struct MuttWindow *dlg =
129 mutt_window_new(WT_DLG_DO_PAGER, MUTT_WIN_ORIENT_VERTICAL, MUTT_WIN_SIZE_MAXIMISE,
130 MUTT_WIN_SIZE_UNLIMITED, MUTT_WIN_SIZE_UNLIMITED);
131
132 struct IndexSharedData *shared = index_shared_data_new();
133 shared->email = e;
134
135 notify_set_parent(shared->notify, dlg->notify);
136
137 dlg->wdata = shared;
138 dlg->wdata_free = index_shared_data_free;
139
140 const bool c_status_on_top = cs_subset_bool(NeoMutt->sub, "status_on_top");
141 struct MuttWindow *panel_pager = ppanel_new(c_status_on_top, shared);
142 dlg->focus = panel_pager;
143 mutt_window_add_child(dlg, panel_pager);
144
145 notify_observer_add(NeoMutt->notify, NT_CONFIG, dopager_config_observer, dlg);
146 notify_observer_add(dlg->notify, NT_WINDOW, dopager_window_observer, dlg);
147 dialog_push(dlg);
148
149 pview->win_index = NULL;
150 pview->win_pbar = window_find_child(panel_pager, WT_STATUS_BAR);
151 pview->win_pager = window_find_child(panel_pager, WT_CUSTOM);
152
153 int rc;
154
155 const char *const c_pager = cs_subset_string(NeoMutt->sub, "pager");
156 if (!c_pager || mutt_str_equal(c_pager, "builtin"))
157 {
158 rc = mutt_pager(pview);
159 }
160 else
161 {
162 struct Buffer *cmd = mutt_buffer_pool_get();
163
164 mutt_endwin();
165 mutt_buffer_file_expand_fmt_quote(cmd, c_pager, pview->pdata->fname);
166 if (mutt_system(mutt_buffer_string(cmd)) == -1)
167 {
168 mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
169 rc = -1;
170 }
171 else
172 rc = 0;
173 mutt_file_unlink(pview->pdata->fname);
174 mutt_buffer_pool_release(&cmd);
175 }
176
177 dialog_pop();
178 mutt_window_free(&dlg);
179 return rc;
180 }
181