1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
1 |
/*
|
2 |
* Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org>
|
|
3 |
* Copyright (C) 2004 g10 Code GmbH
|
|
4 |
*
|
|
5 |
* This program is free software; you can redistribute it and/or modify
|
|
6 |
* it under the terms of the GNU General Public License as published by
|
|
7 |
* the Free Software Foundation; either version 2 of the License, or
|
|
8 |
* (at your option) any later version.
|
|
9 |
*
|
|
10 |
* This program is distributed in the hope that it will be useful,
|
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13 |
* GNU General Public License for more details.
|
|
14 |
*
|
|
15 |
* You should have received a copy of the GNU General Public License
|
|
16 |
* along with this program; if not, write to the Free Software
|
|
17 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
18 |
*/
|
|
19 |
||
20 |
#if HAVE_CONFIG_H
|
|
21 |
# include "config.h"
|
|
22 |
#endif
|
|
23 |
||
24 |
#include "mutt.h" |
|
25 |
#include "mutt_menu.h" |
|
26 |
#include "mutt_curses.h" |
|
27 |
#include "pager.h" |
|
28 |
#include "mbyte.h" |
|
29 |
||
30 |
#include <termios.h> |
|
31 |
#include <sys/types.h> |
|
32 |
#include <fcntl.h> |
|
33 |
#include <stdlib.h> |
|
34 |
#include <unistd.h> |
|
35 |
#include <string.h> |
|
36 |
#include <errno.h> |
|
37 |
#include <ctype.h> |
|
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
38 |
#ifdef HAVE_SYS_TIME_H
|
39 |
# include <sys/time.h>
|
|
40 |
#endif
|
|
41 |
#include <time.h> |
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
42 |
|
43 |
#ifdef HAVE_LANGINFO_YESEXPR
|
|
44 |
#include <langinfo.h> |
|
45 |
#endif
|
|
46 |
||
47 |
/* not possible to unget more than one char under some curses libs, and it
|
|
48 |
* is impossible to unget function keys in SLang, so roll our own input
|
|
49 |
* buffering routines.
|
|
50 |
*/
|
|
51 |
size_t UngetCount = 0; |
|
52 |
static size_t UngetBufLen = 0; |
|
53 |
static event_t *KeyEvent; |
|
54 |
||
55 |
void mutt_refresh (void) |
|
56 |
{
|
|
57 |
/* don't refresh when we are waiting for a child. */
|
|
58 |
if (option (OPTKEEPQUIET)) |
|
59 |
return; |
|
60 |
||
61 |
/* don't refresh in the middle of macros unless necessary */
|
|
62 |
if (UngetCount && !option (OPTFORCEREFRESH)) |
|
63 |
return; |
|
64 |
||
65 |
/* else */
|
|
66 |
refresh (); |
|
67 |
}
|
|
68 |
||
69 |
/* Make sure that the next refresh does a full refresh. This could be
|
|
70 |
optmized by not doing it at all if DISPLAY is set as this might
|
|
71 |
indicate that a GUI based pinentry was used. Having an option to
|
|
72 |
customize this is of course the Mutt way. */
|
|
73 |
void mutt_need_hard_redraw (void) |
|
74 |
{
|
|
1.1.10
by Bhavani Shankar
Import upstream version 1.5.19 |
75 |
keypad (stdscr, TRUE); |
76 |
clearok (stdscr, TRUE); |
|
77 |
set_option (OPTNEEDREDRAW); |
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
78 |
}
|
79 |
||
80 |
event_t mutt_getch (void) |
|
81 |
{
|
|
82 |
int ch; |
|
83 |
event_t err = {-1, OP_NULL }, ret; |
|
1.1.10
by Bhavani Shankar
Import upstream version 1.5.19 |
84 |
event_t timeout = {-2, OP_NULL}; |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
85 |
|
86 |
if (!option(OPTUNBUFFEREDINPUT) && UngetCount) |
|
87 |
return (KeyEvent[--UngetCount]); |
|
88 |
||
89 |
SigInt = 0; |
|
90 |
||
91 |
mutt_allow_interrupt (1); |
|
92 |
#ifdef KEY_RESIZE
|
|
93 |
/* ncurses 4.2 sends this when the screen is resized */
|
|
94 |
ch = KEY_RESIZE; |
|
95 |
while (ch == KEY_RESIZE) |
|
96 |
#endif /* KEY_RESIZE */ |
|
97 |
ch = getch (); |
|
98 |
mutt_allow_interrupt (0); |
|
99 |
||
100 |
if (SigInt) |
|
101 |
mutt_query_exit (); |
|
102 |
||
103 |
if(ch == ERR) |
|
1.1.7
by Christoph Berg
Import upstream version 1.5.17 |
104 |
{
|
105 |
/* either timeout or the terminal has been lost */
|
|
106 |
if (!isatty (0)) |
|
107 |
{
|
|
108 |
endwin (); |
|
109 |
exit (1); |
|
110 |
}
|
|
1.1.10
by Bhavani Shankar
Import upstream version 1.5.19 |
111 |
return timeout; |
1.1.7
by Christoph Berg
Import upstream version 1.5.17 |
112 |
}
|
113 |
||
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
114 |
if ((ch & 0x80) && option (OPTMETAKEY)) |
115 |
{
|
|
116 |
/* send ALT-x as ESC-x */
|
|
117 |
ch &= ~0x80; |
|
118 |
mutt_ungetch (ch, 0); |
|
119 |
ret.ch = '\033'; |
|
120 |
ret.op = 0; |
|
121 |
return ret; |
|
122 |
}
|
|
123 |
||
124 |
ret.ch = ch; |
|
125 |
ret.op = 0; |
|
126 |
return (ch == ctrl ('G') ? err : ret); |
|
127 |
}
|
|
128 |
||
129 |
int _mutt_get_field (/* const */ char *field, char *buf, size_t buflen, int complete, int multiple, char ***files, int *numfiles) |
|
130 |
{
|
|
131 |
int ret; |
|
132 |
int x, y; |
|
133 |
||
134 |
ENTER_STATE *es = mutt_new_enter_state(); |
|
135 |
||
136 |
do
|
|
137 |
{
|
|
138 |
CLEARLINE (LINES-1); |
|
139 |
addstr (field); |
|
140 |
mutt_refresh (); |
|
141 |
getyx (stdscr, y, x); |
|
142 |
ret = _mutt_enter_string (buf, buflen, y, x, complete, multiple, files, numfiles, es); |
|
143 |
}
|
|
144 |
while (ret == 1); |
|
145 |
CLEARLINE (LINES-1); |
|
146 |
mutt_free_enter_state (&es); |
|
147 |
||
148 |
return (ret); |
|
149 |
}
|
|
150 |
||
151 |
int mutt_get_field_unbuffered (char *msg, char *buf, size_t buflen, int flags) |
|
152 |
{
|
|
153 |
int rc; |
|
154 |
||
155 |
set_option (OPTUNBUFFEREDINPUT); |
|
156 |
rc = mutt_get_field (msg, buf, buflen, flags); |
|
157 |
unset_option (OPTUNBUFFEREDINPUT); |
|
158 |
||
159 |
return (rc); |
|
160 |
}
|
|
161 |
||
162 |
void mutt_clear_error (void) |
|
163 |
{
|
|
164 |
Errorbuf[0] = 0; |
|
165 |
if (!option(OPTNOCURSES)) |
|
166 |
CLEARLINE (LINES-1); |
|
167 |
}
|
|
168 |
||
169 |
void mutt_edit_file (const char *editor, const char *data) |
|
170 |
{
|
|
171 |
char cmd[LONG_STRING]; |
|
172 |
||
173 |
mutt_endwin (NULL); |
|
174 |
mutt_expand_file_fmt (cmd, sizeof (cmd), editor, data); |
|
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
175 |
if (mutt_system (cmd)) |
176 |
{
|
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
177 |
mutt_error (_("Error running \"%s\"!"), cmd); |
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
178 |
mutt_sleep (2); |
179 |
}
|
|
1.1.10
by Bhavani Shankar
Import upstream version 1.5.19 |
180 |
#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
|
181 |
/* the terminal may have been resized while the editor owned it */
|
|
182 |
mutt_resize_screen (); |
|
183 |
#endif
|
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
184 |
keypad (stdscr, TRUE); |
185 |
clearok (stdscr, TRUE); |
|
186 |
}
|
|
187 |
||
188 |
int mutt_yesorno (const char *msg, int def) |
|
189 |
{
|
|
190 |
event_t ch; |
|
191 |
char *yes = _("yes"); |
|
192 |
char *no = _("no"); |
|
193 |
char *answer_string; |
|
194 |
size_t answer_string_len; |
|
195 |
||
196 |
#ifdef HAVE_LANGINFO_YESEXPR
|
|
197 |
char *expr; |
|
198 |
regex_t reyes; |
|
199 |
regex_t reno; |
|
200 |
int reyes_ok; |
|
201 |
int reno_ok; |
|
202 |
char answer[2]; |
|
203 |
||
204 |
answer[1] = 0; |
|
205 |
||
206 |
reyes_ok = (expr = nl_langinfo (YESEXPR)) && expr[0] == '^' && |
|
207 |
!regcomp (&reyes, expr, REG_NOSUB|REG_EXTENDED); |
|
208 |
reno_ok = (expr = nl_langinfo (NOEXPR)) && expr[0] == '^' && |
|
209 |
!regcomp (&reno, expr, REG_NOSUB|REG_EXTENDED); |
|
210 |
#endif
|
|
211 |
||
212 |
CLEARLINE(LINES-1); |
|
213 |
||
214 |
/*
|
|
215 |
* In order to prevent the default answer to the question to wrapped
|
|
216 |
* around the screen in the even the question is wider than the screen,
|
|
217 |
* ensure there is enough room for the answer and truncate the question
|
|
218 |
* to fit.
|
|
219 |
*/
|
|
220 |
answer_string = safe_malloc (COLS + 1); |
|
221 |
snprintf (answer_string, COLS + 1, " ([%s]/%s): ", def == M_YES ? yes : no, def == M_YES ? no : yes); |
|
222 |
answer_string_len = strlen (answer_string); |
|
223 |
printw ("%.*s%s", COLS - answer_string_len, msg, answer_string); |
|
224 |
FREE (&answer_string); |
|
225 |
||
226 |
FOREVER
|
|
227 |
{
|
|
228 |
mutt_refresh (); |
|
229 |
ch = mutt_getch (); |
|
230 |
if (CI_is_return (ch.ch)) |
|
231 |
break; |
|
1.1.10
by Bhavani Shankar
Import upstream version 1.5.19 |
232 |
if (ch.ch < 0) |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
233 |
{
|
234 |
def = -1; |
|
235 |
break; |
|
236 |
}
|
|
237 |
||
238 |
#ifdef HAVE_LANGINFO_YESEXPR
|
|
239 |
answer[0] = ch.ch; |
|
240 |
if (reyes_ok ? |
|
241 |
(regexec (& reyes, answer, 0, 0, 0) == 0) : |
|
242 |
#else
|
|
243 |
if ( |
|
244 |
#endif
|
|
245 |
(tolower (ch.ch) == 'y')) |
|
246 |
{
|
|
247 |
def = M_YES; |
|
248 |
break; |
|
249 |
}
|
|
250 |
else if ( |
|
251 |
#ifdef HAVE_LANGINFO_YESEXPR
|
|
252 |
reno_ok ? |
|
253 |
(regexec (& reno, answer, 0, 0, 0) == 0) : |
|
254 |
#endif
|
|
255 |
(tolower (ch.ch) == 'n')) |
|
256 |
{
|
|
257 |
def = M_NO; |
|
258 |
break; |
|
259 |
}
|
|
260 |
else
|
|
261 |
{
|
|
262 |
BEEP(); |
|
263 |
}
|
|
264 |
}
|
|
265 |
||
266 |
#ifdef HAVE_LANGINFO_YESEXPR
|
|
267 |
if (reyes_ok) |
|
268 |
regfree (& reyes); |
|
269 |
if (reno_ok) |
|
270 |
regfree (& reno); |
|
271 |
#endif
|
|
272 |
||
273 |
if (def != -1) |
|
274 |
{
|
|
275 |
addstr ((char *) (def == M_YES ? yes : no)); |
|
276 |
mutt_refresh (); |
|
277 |
}
|
|
278 |
return (def); |
|
279 |
}
|
|
280 |
||
281 |
/* this function is called when the user presses the abort key */
|
|
282 |
void mutt_query_exit (void) |
|
283 |
{
|
|
284 |
mutt_flushinp (); |
|
285 |
curs_set (1); |
|
286 |
if (Timeout) |
|
287 |
timeout (-1); /* restore blocking operation */ |
|
288 |
if (mutt_yesorno (_("Exit Mutt?"), M_YES) == M_YES) |
|
289 |
{
|
|
290 |
endwin (); |
|
291 |
exit (1); |
|
292 |
}
|
|
293 |
mutt_clear_error(); |
|
294 |
mutt_curs_set (-1); |
|
295 |
SigInt = 0; |
|
296 |
}
|
|
297 |
||
298 |
void mutt_curses_error (const char *fmt, ...) |
|
299 |
{
|
|
300 |
va_list ap; |
|
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
301 |
char scratch[LONG_STRING]; |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
302 |
|
303 |
va_start (ap, fmt); |
|
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
304 |
vsnprintf (scratch, sizeof (scratch), fmt, ap); |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
305 |
va_end (ap); |
306 |
||
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
307 |
dprint (1, (debugfile, "%s\n", scratch)); |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
308 |
mutt_format_string (Errorbuf, sizeof (Errorbuf), |
1.1.7
by Christoph Berg
Import upstream version 1.5.17 |
309 |
0, COLS-2, FMT_LEFT, 0, scratch, sizeof (scratch), 0); |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
310 |
|
311 |
if (!option (OPTKEEPQUIET)) |
|
312 |
{
|
|
313 |
BEEP (); |
|
314 |
SETCOLOR (MT_COLOR_ERROR); |
|
315 |
mvaddstr (LINES-1, 0, Errorbuf); |
|
316 |
clrtoeol (); |
|
317 |
SETCOLOR (MT_COLOR_NORMAL); |
|
318 |
mutt_refresh (); |
|
319 |
}
|
|
320 |
||
321 |
set_option (OPTMSGERR); |
|
322 |
}
|
|
323 |
||
324 |
void mutt_curses_message (const char *fmt, ...) |
|
325 |
{
|
|
326 |
va_list ap; |
|
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
327 |
char scratch[LONG_STRING]; |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
328 |
|
329 |
va_start (ap, fmt); |
|
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
330 |
vsnprintf (scratch, sizeof (scratch), fmt, ap); |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
331 |
va_end (ap); |
332 |
||
333 |
mutt_format_string (Errorbuf, sizeof (Errorbuf), |
|
1.1.7
by Christoph Berg
Import upstream version 1.5.17 |
334 |
0, COLS-2, FMT_LEFT, 0, scratch, sizeof (scratch), 0); |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
335 |
|
336 |
if (!option (OPTKEEPQUIET)) |
|
337 |
{
|
|
338 |
SETCOLOR (MT_COLOR_MESSAGE); |
|
339 |
mvaddstr (LINES - 1, 0, Errorbuf); |
|
340 |
clrtoeol (); |
|
341 |
SETCOLOR (MT_COLOR_NORMAL); |
|
342 |
mutt_refresh (); |
|
343 |
}
|
|
344 |
||
345 |
unset_option (OPTMSGERR); |
|
346 |
}
|
|
347 |
||
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
348 |
void mutt_progress_init (progress_t* progress, const char *msg, |
349 |
unsigned short flags, unsigned short inc, |
|
350 |
long size) |
|
351 |
{
|
|
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
352 |
struct timeval tv = { 0, 0 }; |
353 |
||
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
354 |
if (!progress) |
355 |
return; |
|
1.1.10
by Bhavani Shankar
Import upstream version 1.5.19 |
356 |
if (option(OPTNOCURSES)) |
357 |
return; |
|
358 |
||
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
359 |
memset (progress, 0, sizeof (progress_t)); |
360 |
progress->inc = inc; |
|
361 |
progress->flags = flags; |
|
362 |
progress->msg = msg; |
|
363 |
progress->size = size; |
|
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
364 |
if (progress->size) { |
365 |
if (progress->flags & M_PROGRESS_SIZE) |
|
366 |
mutt_pretty_size (progress->sizestr, sizeof (progress->sizestr), |
|
367 |
progress->size); |
|
368 |
else
|
|
369 |
snprintf (progress->sizestr, sizeof (progress->sizestr), "%ld", |
|
370 |
progress->size); |
|
371 |
}
|
|
372 |
if (!inc) |
|
373 |
{
|
|
374 |
if (size) |
|
375 |
mutt_message ("%s (%s)", msg, progress->sizestr); |
|
376 |
else
|
|
377 |
mutt_message (msg); |
|
378 |
return; |
|
379 |
}
|
|
380 |
if (gettimeofday (&tv, NULL) < 0) |
|
381 |
dprint (1, (debugfile, "gettimeofday failed: %d\n", errno)); |
|
382 |
/* if timestamp is 0 no time-based suppression is done */
|
|
383 |
if (TimeInc) |
|
1.1.10
by Bhavani Shankar
Import upstream version 1.5.19 |
384 |
progress->timestamp = ((unsigned int) tv.tv_sec * 1000) |
385 |
+ (unsigned int) (tv.tv_usec / 1000); |
|
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
386 |
mutt_progress_update (progress, 0, 0); |
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
387 |
}
|
388 |
||
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
389 |
void mutt_progress_update (progress_t* progress, long pos, int percent) |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
390 |
{
|
391 |
char posstr[SHORT_STRING]; |
|
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
392 |
short update = 0; |
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
393 |
struct timeval tv = { 0, 0 }; |
394 |
unsigned int now = 0; |
|
395 |
||
1.1.10
by Bhavani Shankar
Import upstream version 1.5.19 |
396 |
if (option(OPTNOCURSES)) |
397 |
return; |
|
398 |
||
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
399 |
if (!progress->inc) |
400 |
goto out; |
|
401 |
||
402 |
/* refresh if size > inc */
|
|
403 |
if (progress->flags & M_PROGRESS_SIZE && |
|
404 |
(pos >= progress->pos + (progress->inc << 10))) |
|
405 |
update = 1; |
|
406 |
else if (pos >= progress->pos + progress->inc) |
|
407 |
update = 1; |
|
408 |
||
409 |
/* skip refresh if not enough time has passed */
|
|
410 |
if (update && progress->timestamp && !gettimeofday (&tv, NULL)) { |
|
1.1.10
by Bhavani Shankar
Import upstream version 1.5.19 |
411 |
now = ((unsigned int) tv.tv_sec * 1000) |
412 |
+ (unsigned int) (tv.tv_usec / 1000); |
|
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
413 |
if (now && now - progress->timestamp < TimeInc) |
414 |
update = 0; |
|
415 |
}
|
|
416 |
||
417 |
/* always show the first update */
|
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
418 |
if (!pos) |
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
419 |
update = 1; |
420 |
||
421 |
if (update) |
|
422 |
{
|
|
423 |
if (progress->flags & M_PROGRESS_SIZE) |
|
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
424 |
{
|
425 |
pos = pos / (progress->inc << 10) * (progress->inc << 10); |
|
426 |
mutt_pretty_size (posstr, sizeof (posstr), pos); |
|
427 |
}
|
|
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
428 |
else
|
429 |
snprintf (posstr, sizeof (posstr), "%ld", pos); |
|
1.3.1
by Antonio Radici
Import upstream version 1.5.20 |
430 |
|
431 |
dprint (5, (debugfile, "updating progress: %s\n", posstr)); |
|
432 |
||
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
433 |
progress->pos = pos; |
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
434 |
if (now) |
435 |
progress->timestamp = now; |
|
436 |
||
437 |
if (progress->size > 0) |
|
438 |
{
|
|
439 |
mutt_message ("%s %s/%s (%d%%)", progress->msg, posstr, progress->sizestr, |
|
1.1.9
by Michael Vogt
Import upstream version 1.5.18 |
440 |
percent > 0 ? percent : |
441 |
(int) (100.0 * (double) progress->pos / progress->size)); |
|
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
442 |
}
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
443 |
else
|
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
444 |
{
|
445 |
if (percent > 0) |
|
446 |
mutt_message ("%s %s (%d%%)", progress->msg, posstr, percent); |
|
447 |
else
|
|
448 |
mutt_message ("%s %s", progress->msg, posstr); |
|
449 |
}
|
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
450 |
}
|
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
451 |
|
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
452 |
out: |
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
453 |
if (pos >= progress->size) |
454 |
mutt_clear_error (); |
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
455 |
}
|
456 |
||
457 |
void mutt_show_error (void) |
|
458 |
{
|
|
459 |
if (option (OPTKEEPQUIET)) |
|
460 |
return; |
|
461 |
||
462 |
SETCOLOR (option (OPTMSGERR) ? MT_COLOR_ERROR : MT_COLOR_MESSAGE); |
|
463 |
CLEARLINE (LINES-1); |
|
464 |
addstr (Errorbuf); |
|
465 |
SETCOLOR (MT_COLOR_NORMAL); |
|
466 |
}
|
|
467 |
||
468 |
void mutt_endwin (const char *msg) |
|
469 |
{
|
|
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
470 |
int e = errno; |
471 |
||
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
472 |
if (!option (OPTNOCURSES)) |
473 |
{
|
|
474 |
CLEARLINE (LINES - 1); |
|
475 |
||
476 |
attrset (A_NORMAL); |
|
477 |
mutt_refresh (); |
|
478 |
endwin (); |
|
479 |
}
|
|
480 |
||
481 |
if (msg && *msg) |
|
482 |
{
|
|
483 |
puts (msg); |
|
484 |
fflush (stdout); |
|
485 |
}
|
|
1.1.8
by Christoph Berg
Import upstream version 1.5.17+20080114 |
486 |
|
487 |
errno = e; |
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
488 |
}
|
489 |
||
490 |
void mutt_perror (const char *s) |
|
491 |
{
|
|
492 |
char *p = strerror (errno); |
|
493 |
||
494 |
dprint (1, (debugfile, "%s: %s (errno = %d)\n", s, |
|
495 |
p ? p : "unknown error", errno)); |
|
496 |
mutt_error ("%s: %s (errno = %d)", s, p ? p : _("unknown error"), errno); |
|
497 |
}
|
|
498 |
||
499 |
int mutt_any_key_to_continue (const char *s) |
|
500 |
{
|
|
501 |
struct termios t; |
|
502 |
struct termios old; |
|
503 |
int f, ch; |
|
504 |
||
505 |
f = open ("/dev/tty", O_RDONLY); |
|
506 |
tcgetattr (f, &t); |
|
507 |
memcpy ((void *)&old, (void *)&t, sizeof(struct termios)); /* save original state */ |
|
508 |
t.c_lflag &= ~(ICANON | ECHO); |
|
509 |
t.c_cc[VMIN] = 1; |
|
510 |
t.c_cc[VTIME] = 0; |
|
511 |
tcsetattr (f, TCSADRAIN, &t); |
|
512 |
fflush (stdout); |
|
513 |
if (s) |
|
514 |
fputs (s, stdout); |
|
515 |
else
|
|
516 |
fputs (_("Press any key to continue..."), stdout); |
|
517 |
fflush (stdout); |
|
518 |
ch = fgetc (stdin); |
|
519 |
fflush (stdin); |
|
520 |
tcsetattr (f, TCSADRAIN, &old); |
|
521 |
close (f); |
|
522 |
fputs ("\r\n", stdout); |
|
523 |
mutt_clear_error (); |
|
524 |
return (ch); |
|
525 |
}
|
|
526 |
||
527 |
int mutt_do_pager (const char *banner, |
|
528 |
const char *tempfile, |
|
529 |
int do_color, |
|
530 |
pager_t *info) |
|
531 |
{
|
|
532 |
int rc; |
|
533 |
||
534 |
if (!Pager || mutt_strcmp (Pager, "builtin") == 0) |
|
535 |
rc = mutt_pager (banner, tempfile, do_color, info); |
|
536 |
else
|
|
537 |
{
|
|
538 |
char cmd[STRING]; |
|
539 |
||
540 |
mutt_endwin (NULL); |
|
541 |
mutt_expand_file_fmt (cmd, sizeof(cmd), Pager, tempfile); |
|
542 |
if (mutt_system (cmd) == -1) |
|
543 |
{
|
|
544 |
mutt_error (_("Error running \"%s\"!"), cmd); |
|
545 |
rc = -1; |
|
546 |
}
|
|
547 |
else
|
|
548 |
rc = 0; |
|
549 |
mutt_unlink (tempfile); |
|
550 |
}
|
|
551 |
||
552 |
return rc; |
|
553 |
}
|
|
554 |
||
555 |
int _mutt_enter_fname (const char *prompt, char *buf, size_t blen, int *redraw, int buffy, int multiple, char ***files, int *numfiles) |
|
556 |
{
|
|
557 |
event_t ch; |
|
558 |
||
559 |
mvaddstr (LINES-1, 0, (char *) prompt); |
|
560 |
addstr (_(" ('?' for list): ")); |
|
561 |
if (buf[0]) |
|
562 |
addstr (buf); |
|
563 |
clrtoeol (); |
|
564 |
mutt_refresh (); |
|
565 |
||
566 |
ch = mutt_getch(); |
|
1.1.10
by Bhavani Shankar
Import upstream version 1.5.19 |
567 |
if (ch.ch < 0) |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
568 |
{
|
569 |
CLEARLINE (LINES-1); |
|
570 |
return (-1); |
|
571 |
}
|
|
572 |
else if (ch.ch == '?') |
|
573 |
{
|
|
574 |
mutt_refresh (); |
|
575 |
buf[0] = 0; |
|
576 |
_mutt_select_file (buf, blen, M_SEL_FOLDER | (multiple ? M_SEL_MULTI : 0), |
|
577 |
files, numfiles); |
|
578 |
*redraw = REDRAW_FULL; |
|
579 |
}
|
|
580 |
else
|
|
581 |
{
|
|
582 |
char *pc = safe_malloc (mutt_strlen (prompt) + 3); |
|
583 |
||
584 |
sprintf (pc, "%s: ", prompt); /* __SPRINTF_CHECKED__ */ |
|
585 |
mutt_ungetch (ch.op ? 0 : ch.ch, ch.op ? ch.op : 0); |
|
586 |
if (_mutt_get_field (pc, buf, blen, (buffy ? M_EFILE : M_FILE) | M_CLEAR, multiple, files, numfiles) |
|
587 |
!= 0) |
|
588 |
buf[0] = 0; |
|
589 |
MAYBE_REDRAW (*redraw); |
|
590 |
FREE (&pc); |
|
591 |
}
|
|
592 |
||
593 |
return 0; |
|
594 |
}
|
|
595 |
||
596 |
void mutt_ungetch (int ch, int op) |
|
597 |
{
|
|
598 |
event_t tmp; |
|
599 |
||
600 |
tmp.ch = ch; |
|
601 |
tmp.op = op; |
|
602 |
||
603 |
if (UngetCount >= UngetBufLen) |
|
604 |
safe_realloc (&KeyEvent, (UngetBufLen += 128) * sizeof(event_t)); |
|
605 |
||
606 |
KeyEvent[UngetCount++] = tmp; |
|
607 |
}
|
|
608 |
||
609 |
void mutt_flushinp (void) |
|
610 |
{
|
|
611 |
UngetCount = 0; |
|
612 |
flushinp (); |
|
613 |
}
|
|
614 |
||
615 |
#if (defined(USE_SLANG_CURSES) || defined(HAVE_CURS_SET))
|
|
616 |
/* The argument can take 3 values:
|
|
617 |
* -1: restore the value of the last call
|
|
618 |
* 0: make the cursor invisible
|
|
619 |
* 1: make the cursor visible
|
|
620 |
*/
|
|
621 |
void mutt_curs_set (int cursor) |
|
622 |
{
|
|
623 |
static int SavedCursor = 1; |
|
624 |
||
625 |
if (cursor < 0) |
|
626 |
cursor = SavedCursor; |
|
627 |
else
|
|
628 |
SavedCursor = cursor; |
|
629 |
||
630 |
if (curs_set (cursor) == ERR) { |
|
631 |
if (cursor == 1) /* cnorm */ |
|
632 |
curs_set (2); /* cvvis */ |
|
633 |
}
|
|
634 |
}
|
|
635 |
#endif
|
|
636 |
||
637 |
int mutt_multi_choice (char *prompt, char *letters) |
|
638 |
{
|
|
639 |
event_t ch; |
|
640 |
int choice; |
|
641 |
char *p; |
|
642 |
||
643 |
mvaddstr (LINES - 1, 0, prompt); |
|
644 |
clrtoeol (); |
|
645 |
FOREVER
|
|
646 |
{
|
|
647 |
mutt_refresh (); |
|
648 |
ch = mutt_getch (); |
|
1.1.10
by Bhavani Shankar
Import upstream version 1.5.19 |
649 |
if (ch.ch < 0 || CI_is_return (ch.ch)) |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
650 |
{
|
651 |
choice = -1; |
|
652 |
break; |
|
653 |
}
|
|
654 |
else
|
|
655 |
{
|
|
656 |
p = strchr (letters, ch.ch); |
|
657 |
if (p) |
|
658 |
{
|
|
659 |
choice = p - letters + 1; |
|
660 |
break; |
|
661 |
}
|
|
662 |
else if (ch.ch <= '9' && ch.ch > '0') |
|
663 |
{
|
|
664 |
choice = ch.ch - '0'; |
|
665 |
if (choice <= mutt_strlen (letters)) |
|
666 |
break; |
|
667 |
}
|
|
668 |
}
|
|
669 |
BEEP (); |
|
670 |
}
|
|
671 |
CLEARLINE (LINES - 1); |
|
672 |
mutt_refresh (); |
|
673 |
return choice; |
|
674 |
}
|
|
675 |
||
676 |
/*
|
|
677 |
* addwch would be provided by an up-to-date curses library
|
|
678 |
*/
|
|
679 |
||
680 |
int mutt_addwch (wchar_t wc) |
|
681 |
{
|
|
682 |
char buf[MB_LEN_MAX*2]; |
|
683 |
mbstate_t mbstate; |
|
684 |
size_t n1, n2; |
|
685 |
||
686 |
memset (&mbstate, 0, sizeof (mbstate)); |
|
687 |
if ((n1 = wcrtomb (buf, wc, &mbstate)) == (size_t)(-1) || |
|
688 |
(n2 = wcrtomb (buf + n1, 0, &mbstate)) == (size_t)(-1)) |
|
689 |
return -1; /* ERR */ |
|
690 |
else
|
|
691 |
return addstr (buf); |
|
692 |
}
|
|
693 |
||
694 |
||
695 |
/*
|
|
696 |
* This formats a string, a bit like
|
|
697 |
* snprintf (dest, destlen, "%-*.*s", min_width, max_width, s),
|
|
698 |
* except that the widths refer to the number of character cells
|
|
699 |
* when printed.
|
|
700 |
*/
|
|
701 |
||
702 |
void mutt_format_string (char *dest, size_t destlen, |
|
703 |
int min_width, int max_width, |
|
1.1.7
by Christoph Berg
Import upstream version 1.5.17 |
704 |
int justify, char m_pad_char, |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
705 |
const char *s, size_t n, |
706 |
int arboreal) |
|
707 |
{
|
|
708 |
char *p; |
|
709 |
wchar_t wc; |
|
710 |
int w; |
|
711 |
size_t k, k2; |
|
712 |
char scratch[MB_LEN_MAX]; |
|
713 |
mbstate_t mbstate1, mbstate2; |
|
714 |
||
715 |
memset(&mbstate1, 0, sizeof (mbstate1)); |
|
716 |
memset(&mbstate2, 0, sizeof (mbstate2)); |
|
717 |
--destlen; |
|
718 |
p = dest; |
|
719 |
for (; n && (k = mbrtowc (&wc, s, n, &mbstate1)); s += k, n -= k) |
|
720 |
{
|
|
721 |
if (k == (size_t)(-1) || k == (size_t)(-2)) |
|
722 |
{
|
|
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
723 |
if (k == (size_t)(-1) && errno == EILSEQ) |
724 |
memset (&mbstate1, 0, sizeof (mbstate1)); |
|
725 |
||
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
726 |
k = (k == (size_t)(-1)) ? 1 : n; |
727 |
wc = replacement_char (); |
|
728 |
}
|
|
729 |
if (arboreal && wc < M_TREE_MAX) |
|
730 |
w = 1; /* hack */ |
|
731 |
else
|
|
732 |
{
|
|
733 |
if (!IsWPrint (wc)) |
|
734 |
wc = '?'; |
|
735 |
w = wcwidth (wc); |
|
736 |
}
|
|
737 |
if (w >= 0) |
|
738 |
{
|
|
739 |
if (w > max_width || (k2 = wcrtomb (scratch, wc, &mbstate2)) > destlen) |
|
740 |
break; |
|
741 |
min_width -= w; |
|
742 |
max_width -= w; |
|
743 |
strncpy (p, scratch, k2); |
|
744 |
p += k2; |
|
745 |
destlen -= k2; |
|
746 |
}
|
|
747 |
}
|
|
748 |
w = (int)destlen < min_width ? destlen : min_width; |
|
749 |
if (w <= 0) |
|
750 |
*p = '\0'; |
|
1.1.7
by Christoph Berg
Import upstream version 1.5.17 |
751 |
else if (justify == FMT_RIGHT) /* right justify */ |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
752 |
{
|
753 |
p[w] = '\0'; |
|
754 |
while (--p >= dest) |
|
755 |
p[w] = *p; |
|
756 |
while (--w >= 0) |
|
757 |
dest[w] = m_pad_char; |
|
758 |
}
|
|
1.1.7
by Christoph Berg
Import upstream version 1.5.17 |
759 |
else if (justify == FMT_CENTER) /* center */ |
760 |
{
|
|
761 |
char *savedp = p; |
|
762 |
int half = (w+1) / 2; /* half of cushion space */ |
|
763 |
||
764 |
p[w] = '\0'; |
|
765 |
||
766 |
/* move str to center of buffer */
|
|
767 |
while (--p >= dest) |
|
768 |
p[half] = *p; |
|
769 |
||
770 |
/* fill rhs */
|
|
771 |
p = savedp + half; |
|
772 |
while (--w >= half) |
|
773 |
*p++ = m_pad_char; |
|
774 |
||
775 |
/* fill lhs */
|
|
776 |
while (half--) |
|
777 |
dest[half] = m_pad_char; |
|
778 |
}
|
|
779 |
else /* left justify */ |
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
780 |
{
|
781 |
while (--w >= 0) |
|
782 |
*p++ = m_pad_char; |
|
783 |
*p = '\0'; |
|
784 |
}
|
|
785 |
}
|
|
786 |
||
787 |
/*
|
|
788 |
* This formats a string rather like
|
|
789 |
* snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
|
|
790 |
* snprintf (dest, destlen, fmt, s);
|
|
791 |
* except that the numbers in the conversion specification refer to
|
|
792 |
* the number of character cells when printed.
|
|
793 |
*/
|
|
794 |
||
795 |
static void mutt_format_s_x (char *dest, |
|
796 |
size_t destlen, |
|
797 |
const char *prefix, |
|
798 |
const char *s, |
|
799 |
int arboreal) |
|
800 |
{
|
|
1.1.7
by Christoph Berg
Import upstream version 1.5.17 |
801 |
int justify = FMT_RIGHT; |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
802 |
char *p; |
803 |
int min_width; |
|
804 |
int max_width = INT_MAX; |
|
805 |
||
806 |
if (*prefix == '-') |
|
1.1.7
by Christoph Berg
Import upstream version 1.5.17 |
807 |
++prefix, justify = FMT_LEFT; |
808 |
else if (*prefix == '=') |
|
809 |
++prefix, justify = FMT_CENTER; |
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
810 |
min_width = strtol (prefix, &p, 10); |
811 |
if (*p == '.') |
|
812 |
{
|
|
813 |
prefix = p + 1; |
|
814 |
max_width = strtol (prefix, &p, 10); |
|
815 |
if (p <= prefix) |
|
816 |
max_width = INT_MAX; |
|
817 |
}
|
|
818 |
||
819 |
mutt_format_string (dest, destlen, min_width, max_width, |
|
1.1.7
by Christoph Berg
Import upstream version 1.5.17 |
820 |
justify, ' ', s, mutt_strlen (s), arboreal); |
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
821 |
}
|
822 |
||
823 |
void mutt_format_s (char *dest, |
|
824 |
size_t destlen, |
|
825 |
const char *prefix, |
|
826 |
const char *s) |
|
827 |
{
|
|
828 |
mutt_format_s_x (dest, destlen, prefix, s, 0); |
|
829 |
}
|
|
830 |
||
831 |
void mutt_format_s_tree (char *dest, |
|
832 |
size_t destlen, |
|
833 |
const char *prefix, |
|
834 |
const char *s) |
|
835 |
{
|
|
836 |
mutt_format_s_x (dest, destlen, prefix, s, 1); |
|
837 |
}
|
|
838 |
||
839 |
/*
|
|
840 |
* mutt_paddstr (n, s) is almost equivalent to
|
|
1.1.7
by Christoph Berg
Import upstream version 1.5.17 |
841 |
* mutt_format_string (bigbuf, big, n, n, FMT_LEFT, ' ', s, big, 0), addstr (bigbuf)
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
842 |
*/
|
843 |
||
844 |
void mutt_paddstr (int n, const char *s) |
|
845 |
{
|
|
846 |
wchar_t wc; |
|
847 |
int w; |
|
848 |
size_t k; |
|
849 |
size_t len = mutt_strlen (s); |
|
850 |
mbstate_t mbstate; |
|
851 |
||
852 |
memset (&mbstate, 0, sizeof (mbstate)); |
|
853 |
for (; len && (k = mbrtowc (&wc, s, len, &mbstate)); s += k, len -= k) |
|
854 |
{
|
|
855 |
if (k == (size_t)(-1) || k == (size_t)(-2)) |
|
856 |
{
|
|
1.1.5
by Christoph Berg
Import upstream version 1.5.15+20070412 |
857 |
if (k == (size_t) (-1)) |
858 |
memset (&mbstate, 0, sizeof (mbstate)); |
|
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
859 |
k = (k == (size_t)(-1)) ? 1 : len; |
860 |
wc = replacement_char (); |
|
861 |
}
|
|
862 |
if (!IsWPrint (wc)) |
|
863 |
wc = '?'; |
|
864 |
w = wcwidth (wc); |
|
865 |
if (w >= 0) |
|
866 |
{
|
|
867 |
if (w > n) |
|
868 |
break; |
|
869 |
addnstr ((char *)s, k); |
|
870 |
n -= w; |
|
871 |
}
|
|
872 |
}
|
|
873 |
while (n-- > 0) |
|
874 |
addch (' '); |
|
875 |
}
|
|
876 |
||
1.1.7
by Christoph Berg
Import upstream version 1.5.17 |
877 |
/* See how many bytes to copy from string so its at most maxlen bytes
|
878 |
* long and maxwid columns wide */
|
|
879 |
int mutt_wstr_trunc (const char *src, size_t maxlen, size_t maxwid, size_t *width) |
|
880 |
{
|
|
881 |
wchar_t wc; |
|
882 |
int w = 0, l = 0, cl; |
|
883 |
size_t cw, n; |
|
884 |
mbstate_t mbstate; |
|
885 |
||
886 |
if (!src) |
|
887 |
goto out; |
|
888 |
||
889 |
n = mutt_strlen (src); |
|
890 |
||
891 |
memset (&mbstate, 0, sizeof (mbstate)); |
|
892 |
for (w = 0; n && (cl = mbrtowc (&wc, src, n, &mbstate)); src += cl, n -= cl) |
|
893 |
{
|
|
894 |
if (cl == (size_t)(-1) || cl == (size_t)(-2)) |
|
895 |
cw = cl = 1; |
|
896 |
else
|
|
897 |
cw = wcwidth (wc); |
|
898 |
if (cl + l > maxlen || cw + w > maxwid) |
|
899 |
break; |
|
900 |
l += cl; |
|
901 |
w += cw; |
|
902 |
}
|
|
903 |
out: |
|
904 |
if (width) |
|
905 |
*width = w; |
|
906 |
return l; |
|
907 |
}
|
|
908 |
||
909 |
/*
|
|
910 |
* returns the number of bytes the first (multibyte) character
|
|
911 |
* of input consumes:
|
|
912 |
* < 0 ... conversion error
|
|
913 |
* = 0 ... end of input
|
|
914 |
* > 0 ... length (bytes)
|
|
915 |
*/
|
|
916 |
int mutt_charlen (const char *s, int *width) |
|
917 |
{
|
|
918 |
wchar_t wc; |
|
919 |
mbstate_t mbstate; |
|
920 |
size_t k, n; |
|
921 |
||
922 |
if (!s || !*s) |
|
923 |
return 0; |
|
924 |
||
925 |
n = mutt_strlen (s); |
|
926 |
memset (&mbstate, 0, sizeof (mbstate)); |
|
927 |
k = mbrtowc (&wc, s, n, &mbstate); |
|
928 |
if (width) |
|
929 |
*width = wcwidth (wc); |
|
930 |
return (k == (size_t)(-1) || k == (size_t)(-2)) ? -1 : k; |
|
931 |
}
|
|
932 |
||
1.1.2
by Martin Pitt
Import upstream version 1.5.11+cvs20060403 |
933 |
/*
|
934 |
* mutt_strwidth is like mutt_strlen except that it returns the width
|
|
935 |
* refering to the number of characters cells.
|
|
936 |
*/
|
|
937 |
||
938 |
int mutt_strwidth (const char *s) |
|
939 |
{
|
|
940 |
wchar_t wc; |
|
941 |
int w; |
|
942 |
size_t k, n; |
|
943 |
mbstate_t mbstate; |
|
944 |
||
945 |
if (!s) return 0; |
|
946 |
||
947 |
n = mutt_strlen (s); |
|
948 |
||
949 |
memset (&mbstate, 0, sizeof (mbstate)); |
|
950 |
for (w=0; n && (k = mbrtowc (&wc, s, n, &mbstate)); s += k, n -= k) |
|
951 |
{
|
|
952 |
if (k == (size_t)(-1) || k == (size_t)(-2)) |
|
953 |
{
|
|
954 |
k = (k == (size_t)(-1)) ? 1 : n; |
|
955 |
wc = replacement_char (); |
|
956 |
}
|
|
957 |
if (!IsWPrint (wc)) |
|
958 |
wc = '?'; |
|
959 |
w += wcwidth (wc); |
|
960 |
}
|
|
961 |
return w; |
|
962 |
}
|