/*
* Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org>
* Copyright (C) 2004 g10 Code GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "mutt.h"
#include "mutt_menu.h"
#include "mutt_curses.h"
#include "pager.h"
#include "mbyte.h"
#include <termios.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#ifdef HAVE_LANGINFO_YESEXPR
#include <langinfo.h>
#endif
/* not possible to unget more than one char under some curses libs, and it
* is impossible to unget function keys in SLang, so roll our own input
* buffering routines.
*/
size_t UngetCount = 0;
static size_t UngetBufLen = 0;
static event_t *KeyEvent;
void mutt_refresh (void)
{
/* don't refresh when we are waiting for a child. */
if (option (OPTKEEPQUIET))
return;
/* don't refresh in the middle of macros unless necessary */
if (UngetCount && !option (OPTFORCEREFRESH))
return;
/* else */
refresh ();
}
/* Make sure that the next refresh does a full refresh. This could be
optmized by not doing it at all if DISPLAY is set as this might
indicate that a GUI based pinentry was used. Having an option to
customize this is of course the Mutt way. */
void mutt_need_hard_redraw (void)
{
if (!getenv ("DISPLAY"))
{
keypad (stdscr, TRUE);
clearok (stdscr, TRUE);
set_option (OPTNEEDREDRAW);
}
}
event_t mutt_getch (void)
{
int ch;
event_t err = {-1, OP_NULL }, ret;
if (!option(OPTUNBUFFEREDINPUT) && UngetCount)
return (KeyEvent[--UngetCount]);
SigInt = 0;
mutt_allow_interrupt (1);
#ifdef KEY_RESIZE
/* ncurses 4.2 sends this when the screen is resized */
ch = KEY_RESIZE;
while (ch == KEY_RESIZE)
#endif /* KEY_RESIZE */
ch = getch ();
mutt_allow_interrupt (0);
if (SigInt)
mutt_query_exit ();
if(ch == ERR)
{
/* either timeout or the terminal has been lost */
if (!isatty (0))
{
endwin ();
exit (1);
}
return err;
}
if ((ch & 0x80) && option (OPTMETAKEY))
{
/* send ALT-x as ESC-x */
ch &= ~0x80;
mutt_ungetch (ch, 0);
ret.ch = '\033';
ret.op = 0;
return ret;
}
ret.ch = ch;
ret.op = 0;
return (ch == ctrl ('G') ? err : ret);
}
int _mutt_get_field (/* const */ char *field, char *buf, size_t buflen, int complete, int multiple, char ***files, int *numfiles)
{
int ret;
int x, y;
ENTER_STATE *es = mutt_new_enter_state();
do
{
CLEARLINE (LINES-1);
addstr (field);
mutt_refresh ();
getyx (stdscr, y, x);
ret = _mutt_enter_string (buf, buflen, y, x, complete, multiple, files, numfiles, es);
}
while (ret == 1);
CLEARLINE (LINES-1);
mutt_free_enter_state (&es);
return (ret);
}
int mutt_get_field_unbuffered (char *msg, char *buf, size_t buflen, int flags)
{
int rc;
set_option (OPTUNBUFFEREDINPUT);
rc = mutt_get_field (msg, buf, buflen, flags);
unset_option (OPTUNBUFFEREDINPUT);
return (rc);
}
void mutt_clear_error (void)
{
Errorbuf[0] = 0;
if (!option(OPTNOCURSES))
CLEARLINE (LINES-1);
}
void mutt_edit_file (const char *editor, const char *data)
{
char cmd[LONG_STRING];
mutt_endwin (NULL);
mutt_expand_file_fmt (cmd, sizeof (cmd), editor, data);
if (mutt_system (cmd))
{
mutt_error (_("Error running \"%s\"!"), cmd);
mutt_sleep (2);
}
keypad (stdscr, TRUE);
clearok (stdscr, TRUE);
}
int mutt_yesorno (const char *msg, int def)
{
event_t ch;
char *yes = _("yes");
char *no = _("no");
char *answer_string;
size_t answer_string_len;
#ifdef HAVE_LANGINFO_YESEXPR
char