NeoMutt  2025-01-09-117-gace867
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
window.c
Go to the documentation of this file.
1
56#include "config.h"
57#include <stdarg.h>
58#include <stdbool.h>
59#include <stdint.h>
60#include <stdio.h>
61#include "mutt/lib.h"
62#include "gui/lib.h"
63#include "color/lib.h"
64#include "expando/lib.h"
65#include "muttlib.h"
66#include "wdata.h"
67
75static void message_bar(struct MuttWindow *win, int percent, const char *fmt, ...)
76{
77 if (!fmt || !win || !win->wdata)
78 return;
79
80 va_list ap;
81 char buf[1024] = { 0 };
82 struct Buffer *buf2 = buf_pool_get();
83 int w = (percent * win->state.cols) / 100;
84 size_t l;
85
86 va_start(ap, fmt);
87 vsnprintf(buf, sizeof(buf), fmt, ap);
88 l = mutt_strwidth(buf);
89 va_end(ap);
90
91 format_string(buf2, 0, win->state.cols - 2, JUSTIFY_LEFT, 0, buf, sizeof(buf), false);
92
93 mutt_window_move(win, 0, 0);
94
95 if ((percent != -1) && simple_color_is_set(MT_COLOR_PROGRESS))
96 {
97 if (l < w)
98 {
99 /* The string fits within the colour bar */
101 mutt_window_addstr(win, buf_string(buf2));
102 w -= l;
103 while (w-- > 0)
104 {
105 mutt_window_addch(win, ' ');
106 }
108 }
109 else
110 {
111 /* The string is too long for the colour bar */
112 int off = mutt_wstr_trunc(buf_string(buf2), buf2->dsize, w, NULL);
113
114 char ch = buf_at(buf2, off);
115 buf2->data[off] = '\0';
117 mutt_window_addstr(win, buf_string(buf2));
118 buf2->data[off] = ch;
120 mutt_window_addstr(win, buf2->data + off);
121 }
122 }
123 else
124 {
125 mutt_window_addstr(win, buf_string(buf2));
126 }
127
129 buf_pool_release(&buf2);
130}
131
135static int progress_window_recalc(struct MuttWindow *win)
136{
137 if (!win || !win->wdata)
138 return -1;
139
140 struct ProgressWindowData *wdata = win->wdata;
141 wdata->display_pos = wdata->update_pos;
142 wdata->display_time = wdata->update_time;
143
144 if (wdata->is_bytes)
145 {
146 struct Buffer *pretty = buf_pool_get();
147 mutt_str_pretty_size(pretty, wdata->display_pos);
148 mutt_str_copy(wdata->pretty_pos, buf_string(pretty), sizeof(wdata->pretty_pos));
149 buf_pool_release(&pretty);
150 }
151
152 if ((wdata->update_percent < 0) && (wdata->size != 0))
153 wdata->display_percent = 100 * wdata->display_pos / wdata->size;
154 else
155 wdata->display_percent = wdata->update_percent;
156
157 win->actions |= WA_REPAINT;
158 return 0;
159}
160
164static int progress_window_repaint(struct MuttWindow *win)
165{
166 if (!win || !win->wdata)
167 return -1;
168
169 struct ProgressWindowData *wdata = win->wdata;
170 if (wdata->msg[0] == '\0')
171 return 0;
172
173 if (wdata->size == 0)
174 {
175 if (wdata->display_percent >= 0)
176 {
177 if (wdata->is_bytes)
178 {
179 /* L10N: Progress bar: `%s` loading text, `%s` pretty size (e.g. 4.6K),
180 `%d` is the number, `%%` is the percent symbol.
181 `%d` and `%%` may be reordered, or space inserted, if you wish. */
182 message_bar(wdata->win, wdata->display_percent, _("%s %s (%d%%)"),
183 wdata->msg, wdata->pretty_pos, wdata->display_percent);
184 }
185 else
186 {
187 /* L10N: Progress bar: `%s` loading text, `%zu` position,
188 `%d` is the number, `%%` is the percent symbol.
189 `%d` and `%%` may be reordered, or space inserted, if you wish. */
190 message_bar(wdata->win, wdata->display_percent, _("%s %zu (%d%%)"),
191 wdata->msg, wdata->display_pos, wdata->display_percent);
192 }
193 }
194 else
195 {
196 if (wdata->is_bytes)
197 {
198 /* L10N: Progress bar: `%s` loading text, `%s` position/size */
199 message_bar(wdata->win, -1, _("%s %s"), wdata->msg, wdata->pretty_pos);
200 }
201 else
202 {
203 /* L10N: Progress bar: `%s` loading text, `%zu` position */
204 message_bar(wdata->win, -1, _("%s %zu"), wdata->msg, wdata->display_pos);
205 }
206 }
207 }
208 else
209 {
210 if (wdata->is_bytes)
211 {
212 /* L10N: Progress bar: `%s` loading text, `%s/%s` position/size,
213 `%d` is the number, `%%` is the percent symbol.
214 `%d` and `%%` may be reordered, or space inserted, if you wish. */
215 message_bar(wdata->win, wdata->display_percent, _("%s %s/%s (%d%%)"),
216 wdata->msg, wdata->pretty_pos, wdata->pretty_size, wdata->display_percent);
217 }
218 else
219 {
220 /* L10N: Progress bar: `%s` loading text, `%zu/%zu` position/size,
221 `%d` is the number, `%%` is the percent symbol.
222 `%d` and `%%` may be reordered, or space inserted, if you wish. */
223 message_bar(wdata->win, wdata->display_percent, _("%s %zu/%zu (%d%%)"),
224 wdata->msg, wdata->display_pos, wdata->size, wdata->display_percent);
225 }
226 }
227
228 return 0;
229}
230
237static bool percent_needs_update(const struct ProgressWindowData *wdata, int percent)
238{
239 return (percent > wdata->display_percent);
240}
241
248static bool pos_needs_update(const struct ProgressWindowData *wdata, long pos)
249{
250 const unsigned shift = wdata->is_bytes ? 10 : 0;
251 return pos >= (wdata->display_pos + (wdata->size_inc << shift));
252}
253
260static bool time_needs_update(const struct ProgressWindowData *wdata, size_t now)
261{
262 if (wdata->time_inc == 0)
263 return true;
264
265 if (now < wdata->display_time)
266 return true;
267
268 const size_t elapsed = (now - wdata->display_time);
269 return (wdata->time_inc < elapsed);
270}
271
279bool progress_window_update(struct MuttWindow *win, size_t pos, int percent)
280{
281 if (!win || !win->wdata)
282 return false;
283
284 struct ProgressWindowData *wdata = win->wdata;
285
286 if (percent >= 0)
287 {
288 if (!percent_needs_update(wdata, percent))
289 return false;
290 }
291 else
292 {
293 if (!pos_needs_update(wdata, pos))
294 return false;
295 }
296
297 const uint64_t now = mutt_date_now_ms();
298 if (!time_needs_update(wdata, now))
299 return false;
300
301 wdata->update_pos = pos;
302 wdata->update_percent = percent;
303 wdata->update_time = now;
305 return true;
306}
307
316struct MuttWindow *progress_window_new(size_t size, size_t size_inc,
317 size_t time_inc, bool is_bytes)
318{
319 if (size_inc == 0) // The user has disabled the progress bar
320 return NULL;
321
327
328 struct ProgressWindowData *wdata = progress_wdata_new();
329 wdata->win = win;
330 wdata->size = size;
331 wdata->size_inc = size_inc;
332 wdata->time_inc = time_inc;
333 wdata->is_bytes = is_bytes;
334
335 if (is_bytes)
336 {
337 struct Buffer *pretty = buf_pool_get();
338 mutt_str_pretty_size(pretty, size);
339 mutt_str_copy(wdata->pretty_size, buf_string(pretty), sizeof(wdata->pretty_size));
340 buf_pool_release(&pretty);
341 }
342
343 win->wdata = wdata;
345
346 return win;
347}
348
355void progress_window_set_message(struct MuttWindow *win, const char *fmt, va_list ap)
356{
357 if (!win || !win->wdata || !fmt)
358 return;
359
360 struct ProgressWindowData *wdata = win->wdata;
361
362 vsnprintf(wdata->msg, sizeof(wdata->msg), fmt, ap);
363
365}
366
373{
374 if (!win || !win->wdata)
375 return;
376
377 struct ProgressWindowData *wdata = win->wdata;
378
379 wdata->size = size;
380 wdata->display_pos = 0;
381 wdata->display_percent = 0;
382 wdata->display_time = 0;
384}
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition: buffer.c:668
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
Color and attribute parsing.
bool simple_color_is_set(enum ColorId cid)
Is the object coloured?
Definition: simple.c:116
@ MT_COLOR_PROGRESS
Progress bar.
Definition: color.h:57
@ MT_COLOR_NORMAL
Plain text.
Definition: color.h:55
size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
Work out how to truncate a widechar string.
Definition: curs_lib.c:385
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition: curs_lib.c:445
Parse Expando string.
int format_string(struct Buffer *buf, int min_cols, int max_cols, enum FormatJustify justify, char pad_char, const char *str, size_t n, bool arboreal)
Format a string, like snprintf()
Definition: format.c:108
@ JUSTIFY_LEFT
Left justify the text.
Definition: format.h:34
static int progress_window_recalc(struct MuttWindow *win)
Recalculate the Progress Bar - Implements MuttWindow::recalc() -.
Definition: window.c:135
static int progress_window_repaint(struct MuttWindow *win)
Repaint the Progress Bar - Implements MuttWindow::repaint() -.
Definition: window.c:164
void progress_wdata_free(struct MuttWindow *win, void **ptr)
Free Progress Bar Window data - Implements MuttWindow::wdata_free() -.
Definition: wdata.c:45
Convenience wrapper for the gui headers.
uint64_t mutt_date_now_ms(void)
Return the number of milliseconds since the Unix epoch.
Definition: date.c:465
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:582
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
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
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:381
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_STATUS_BAR
Status Bar containing extra info about the Index/Pager/etc.
Definition: mutt_window.h:102
@ MUTT_WIN_ORIENT_VERTICAL
Window uses all available vertical space.
Definition: mutt_window.h:39
#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
int mutt_str_pretty_size(struct Buffer *buf, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1003
Some miscellaneous functions.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:96
struct ProgressWindowData * progress_wdata_new(void)
Create new Progress Bar Window Data.
Definition: wdata.c:37
Progress Bar Window Data.
void progress_window_set_size(struct MuttWindow *win, size_t size)
Set the progress size.
Definition: window.c:372
static bool percent_needs_update(const struct ProgressWindowData *wdata, int percent)
Do we need to update, given the current percentage?
Definition: window.c:237
bool progress_window_update(struct MuttWindow *win, size_t pos, int percent)
Update the Progress Bar Window.
Definition: window.c:279
void progress_window_set_message(struct MuttWindow *win, const char *fmt, va_list ap)
Set the progress message.
Definition: window.c:355
static void message_bar(struct MuttWindow *win, int percent, const char *fmt,...)
Draw a colourful progress bar.
Definition: window.c:75
static bool time_needs_update(const struct ProgressWindowData *wdata, size_t now)
Do we need to update, given the current time?
Definition: window.c:260
static bool pos_needs_update(const struct ProgressWindowData *wdata, long pos)
Do we need to update, given the current pos?
Definition: window.c:248
struct MuttWindow * progress_window_new(size_t size, size_t size_inc, size_t time_inc, bool is_bytes)
Create a new Progress Bar Window.
Definition: window.c:316
String manipulation buffer.
Definition: buffer.h:36
size_t dsize
Length of data.
Definition: buffer.h:39
char * data
Pointer to data.
Definition: buffer.h:37
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
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:173
void(* wdata_free)(struct MuttWindow *win, void **ptr)
Definition: mutt_window.h:159
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
Progress Bar Window Data.
Definition: wdata.h:36
int update_percent
Updated percentage complete.
Definition: wdata.h:55
char msg[1024]
Message to display.
Definition: wdata.h:40
size_t size
Total expected size.
Definition: wdata.h:42
char pretty_pos[24]
Pretty string for the position.
Definition: wdata.h:51
size_t time_inc
Time increment.
Definition: wdata.h:44
uint64_t update_time
Time of last update.
Definition: wdata.h:56
int display_percent
Displayed percentage complete.
Definition: wdata.h:49
size_t display_pos
Displayed position.
Definition: wdata.h:48
size_t size_inc
Size increment.
Definition: wdata.h:43
bool is_bytes
true if measuring bytes
Definition: wdata.h:45
size_t update_pos
Updated position.
Definition: wdata.h:54
struct MuttWindow * win
Window to draw on.
Definition: wdata.h:37
uint64_t display_time
Time of last display.
Definition: wdata.h:50
char pretty_size[24]
Pretty string for size.
Definition: wdata.h:41
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:61