static char rcsid[] = "@(#)$Id: in_utils.c,v 1.53 2006/04/09 07:37:18 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.53 $ $State: Exp $
*
* Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI>
* (was hurtta+elm@ozone.FMI.FI)
******************************************************************************
* The Elm Mail System
*
* Copyright (c) 1988-1992 USENET Community Trust
* Copyright (c) 1986,1987 Dave Taylor
*****************************************************************************/
/** Mindless I/O routines for ELM
**/
#include "def_elm.h"
#include "s_elm.h"
DEBUG_VAR(Debug,__FILE__,"ui");
static unsigned char *s2us P_((char *str));
static unsigned char *s2us(str)
char *str;
{
return (unsigned char *)str;
}
static char *us2s P_((unsigned char *str));
static char *us2s(str)
unsigned char *str;
{
return (char *)str;
}
#include <errno.h>
#ifndef ANSI_C
extern int errno; /* system error number */
#endif
extern int tabspacing;
#define erase_a_char() { Writechar(BACKSPACE); Writechar(' '); \
Writechar(BACKSPACE); FlushBuffer(); }
int prompt_letter(
#if ANSI_C
int line, char *letters, int def,
int flags,
struct menu_context *page,
const char * format, const char *msg, ...
#else
line, letters, def, flags, page, format, msg, va_alist
#endif
)
#if !ANSI_C
int line;
char *letters;
int def;
int flags;
struct menu_context *page;
CONST char * format;
CONST char *msg;
va_dcl
#endif
{
struct string *question = NULL;
int ch;
int center = flags & PROMPT_center;
int yesno = flags & PROMPT_yesno;
int mark = flags & PROMPT_redraw_mark;
int ctrlL = flags & PROMPT_ctrlL;
int cancel = flags & PROMPT_cancel;
int cols = 0;
va_list vl;
Va_start(vl, msg); /* defined in defs.h */
question = elm_smessage(0,format,msg,vl);
va_end(vl);
do {
int LINES, COLUMNS;
int l;
char *x;
menu_get_sizes(page,&LINES, &COLUMNS);
/* FIXME: Not correct */
l = string_len(question);
cols = COLUMNS - ( l + 5 ); /* 5 for "Yes." + 1 */
if (cols < 0) {
cols = 0;
}
menu_MoveCursor(page,line, (center || (cols < 2)) ? 0 : cols-2);
menu_CleartoEOLN(page);
menu_PutLineX(page,line, center ? cols/2 : cols,
FRM("%S%c%c"), question, def, BACKSPACE);
FlushBuffer();
ch = menu_ReadCh(page, REDRAW_MARK
| ( cancel ? READCH_sig_char : 0 ));
if (ch == REDRAW_MARK) {
if (mark)
break;
continue;
}
if (ctrlL && ch == ('L'&31)) {
break;
}
if (cancel && ch == TERMCH_interrupt_char)
break;
if (ch == EOF)
break;
/* Look first letters without lowercasing */
for (x = letters; *x; x++) {
if (ch == *x) {
menu_Writechar(page,ch);
goto out;
}
}
if(ch == '\n' || ch == '\r')
ch = def;
else {
#ifdef ASCII_CTYPE
if (isascii(ch))
#endif
ch = tolower(ch);
}
for (x = letters; *x; x++) {
if (ch == *x) {
menu_Writechar(page,ch);
goto out;
}
}
if(ch == *def_ans_yes && yesno) {
menu_Write_to_screen(page,CATGETS(elm_msg_cat, ElmSet,
ElmYesWord, "Yes."));
break;
} else if (ch == *def_ans_no && yesno) {
menu_Write_to_screen(page,CATGETS(elm_msg_cat, ElmSet,
ElmNoWord, "No."));
break;
}
menu_Writechar(page,'?');
FlushBuffer();
#if POLL_METHOD
wait_for_timeout(1);
#else
sleep(1);
#endif
} while (EOF != ch);
out:
FlushBuffer();
free_string(&question);
if (EOF != ch && REDRAW_MARK != ch && ('L'&31) != ch &&
TERMCH_interrupt_char != ch) {
if (sleepmsg > 0) {
#if POLL_METHOD
wait_for_timeout((sleepmsg + 1) / 2);
#else
sleep((sleepmsg + 1) / 2);
#endif
}
menu_MoveCursor(page,line, (center || (cols < 2)) ? 0 : cols-2);
menu_CleartoEOLN(page);
}
return ch;
}
int want_to(question, dflt, where, clear_and_center, page)
char *question;
int dflt;
int where, clear_and_center;
struct menu_context *page;
{
/** Ask 'question' on 'where' left enough to just leave room for an
answer, returning the answer in lower case.
Echo answer as full "Yes" or "No". 'dflt' is the
default answer if <return> is pressed.
**/
int ch, cols;
int LINES, COLUMNS;
int redraw1 = 0;
redraw:
menu_get_sizes(page,&LINES, &COLUMNS);
cols = COLUMNS - (strlen(question) + 5 ); /* 5 for "Yes." + 1 */
if (cols < 0) {
cols = 0;
}
DPRINT(Debug,3, (&Debug,"want_to: pos line=%d column=%d\n",
where, (clear_and_center || (cols < 2)) ? 0 : cols-2));
menu_MoveCursor(page,
where, (clear_and_center || (cols < 2)) ? 0 : cols-2);
menu_CleartoEOLN(page);
menu_PutLineX(page,
where, clear_and_center ? cols/2 : cols,
FRM("%s%c%c"), question, dflt, BACKSPACE);
FlushBuffer();
ch = menu_ReadCh(page, REDRAW_MARK);
if (ch == REDRAW_MARK) {
menu_ClearScreen(page); /* Clear possible redraw mark */
/* Call refresh routines of children */
menu_redraw_children(page);
redraw1++;
goto redraw;
}
if (ch == EOF) {
leave(0);
}
ch = tolower(ch);
while (!( ch == *def_ans_yes || ch == *def_ans_no || ch == '\n' || ch == '\r')) {
ch = menu_ReadCh(page,REDRAW_MARK);
if (ch == REDRAW_MARK) {
menu_ClearScreen(page); /* Clear possible redraw mark */
/* Call refresh routines of children */
menu_redraw_children(page);
redraw1++;
goto redraw;
}
if (ch == EOF) {
leave(0); /* ???? global reference */
}
#ifdef ASCII_CTYPE
if (isascii(ch))
#endif
ch = tolower(ch);
}
if(ch == '\n' || ch == '\r')
ch = dflt;
if(ch == *def_ans_yes)
menu_Write_to_screen(page,
CATGETS(elm_msg_cat, ElmSet, ElmYesWord,
"Yes."));
else if (ch == *def_ans_no)
menu_Write_to_screen(page,
CATGETS(elm_msg_cat, ElmSet, ElmNoWord,
"No."));
else {
DPRINT(Debug,3,(&Debug,"want_to [%s]=%c\n",question,ch));
return(ch); /* Don't write anything, just return */
}
FlushBuffer();
if (sleepmsg > 0) {
#if POLL_METHOD
wait_for_timeout((sleepmsg + 1) / 2);
#else
sleep((sleepmsg + 1) / 2);
#endif
}
menu_MoveCursor(page,where,
(clear_and_center || (cols < 2)) ? 0 : cols-2);
menu_CleartoEOLN(page);
if (redraw1)
menu_trigger_redraw(page);
DPRINT(Debug,3,(&Debug,"want_to [%s]=%c\n",question,ch));
return(ch);
}
int read_number(ch, item, current, page,prompt_area)
int ch;
CONST struct string *item;
int current;
struct menu_context *page;
struct menu_context *prompt_area;
{
/** Read a number, where 'ch' is the leading digit! **/
/* If redraw is used use
menu_trigger_redraw(page)
*/
struct string * buff = new_string(display_charset);
int need_redraw = 0;
int num, status;
int bad, li,co, line;
fill_ascii_to_string(buff,1,ch);
menu_get_sizes(page,&li, &co);
redraw:
/* FIXME --optionally_enter* should use prompt_page */
line = menu_GetAbsLine(prompt_area,0);
status = optionally_enter2(page,
&buff, line, co-40,
OE_APPEND_CURRENT|OE_REDRAW_MARK|
OE_SIG_CHAR /* allow Ctrl-C */,
CATGETS(elm_msg_cat, ElmSet,
ElmSetCurrentTo,
"Set current %S to :"), item);
if (status == -1) /* Ctrl-C */
return(current);
if (status == REDRAW_MARK) {
menu_ClearScreen(page); /* Reset possible redraw flag */
/* Can not set menu_trigger_redraw here or causes
redraw loop ... */
need_redraw = 1;
goto redraw;
}
if (need_redraw)
menu_trigger_redraw(page);
if (0 == string_len(buff)) {
free_string(&buff);
return current;
}
num = string_to_long(buff,&bad);
free_string(&buff);
if (bad >= 0)
return current;
return(num);
}
int enter_helper(info,base_page)
struct enter_info *info;
struct menu_context *base_page;
{
int append_current, passwd, allowmime,
redraw, alt_solidus, allowtab, use_editor_escape,
tabaction, sig_char;
struct string **buffer;
int ret = 0;
/* Only add comma on beginning of editing ... */
int add_comma = 0 != (info -> flags & OE_ADD_COMMA);
info->ch_count = 0;
buffer = info->give_buffer(info,em_redraw_initial, base_page);
restart: /* give_buffer may modify flags .... */
append_current = 0 != (info -> flags & OE_APPEND_CURRENT);
passwd = 0 != (info -> flags & OE_PASSWD);
allowmime = 0 != (info -> flags & OE_ALLOW_MIMEENC);
redraw = (info -> flags & OE_REDRAW_MARK) ? REDRAW_MARK : 0;
alt_solidus = 0 != (info -> flags & OE_ALT_SOLIDUS);
use_editor_escape = 0 != (info -> flags & OE_EDITOR_ESCAPE);
tabaction = 0 != (info -> flags & OE_TABACTION);
allowtab = !tabaction;
sig_char = 0 != (info -> flags & OE_SIG_CHAR) ? READCH_sig_char : 0;
DPRINT(Debug,4,
(&Debug,
"== enter_helper: ch_count=%d %s%s%s%s%s%s%s%s%s%s\n",
info->ch_count,
append_current ? "append_current " : "",
add_comma ? "add_comma " : "",
passwd ? "passwd " : "",
allowmime ? "allowmime " : "",
redraw ? "redraw " : "",
alt_solidus ? "alt_solidus " : "",
use_editor_escape ? "use_editor_escape " : "",
allowtab ? "allowtab " : "",
tabaction ? "tabaction " : "",
sig_char ? "sig_char " : ""));
while(buffer) {
int escaped = OFF;
do {
int wrap_column;
struct charset_state *ch;
int LINES,COLUMNS;
int resize;
resize_mark:
resize = 0;
if (!info->current_page) {
DPRINT(Debug,9,(&Debug,
"enter_helper: menu_context erased .. resetting\n"));
info->current_page = base_page;
}
menu_get_sizes(info->current_page, &LINES, &COLUMNS);
if (info->current_page != base_page) {
if (menu_resized(info->current_page)) {
menu_get_sizes(info->current_page, &LINES, &COLUMNS);
if (info->ch_count == 0)
buffer = info->give_buffer(info,em_redraw_initial,
base_page);
else
buffer = info->give_buffer(info,em_redraw, base_page);
goto restart;
} else if (menu_need_redraw(info->current_page)) {
internal_redraw:
menu_ClearScreen(info->current_page); /* Reset redraw flag */
if (info->ch_count == 0)
buffer = info->give_buffer(info,em_redraw_initial,
base_page);
else
buffer = info->give_buffer(info,em_redraw, base_page);
goto restart;
}
}
wrap_column = COLUMNS -5;
ch = menu_ReadCh2(info->current_page,
redraw|READCH_CURSOR|resize|
(escaped ? 0 :
READCH_term_char|sig_char)|
(escaped ? READCH_quote : 0));
reprocess_key:
if (!ch) {
DPRINT(Debug,4,(&Debug, "-- enter_helper: EOF?\n"));
/* we've hit EOF */
ret = 1;
goto out;
}
if (ch->caller_flags) {
DPRINT(Debug,4,(&Debug, "-- enter_helper: flags: %d\n",
ch->caller_flags));
add_comma = 0;
switch(ch->caller_flags) {
int len;
int tab_seen;
case RESIZE_MARK:
DPRINT(Debug,4, (&Debug," ... resizing\n"));
goto resize_mark;
case REDRAW_MARK:
if (info->current_page != base_page) {
DPRINT(Debug,4, (&Debug," ... redrawing\n"));
goto internal_redraw;
}
ret = REDRAW_MARK;
goto out;
case TERMCH_eof_char:
/* we've hit EOF */
ret = 1;
goto out;
case TERMCH_backspace:
if (!append_current && info->ch_count == 0 && *buffer) {
struct string * str = new_string((*buffer)->
string_type);
free_string(buffer);
*buffer = str;
info->ch_count++;
buffer = info->give_buffer(info,em_redraw, base_page);
goto restart;
}
/* This is tricky. Here we are dealing with all situations
* under which a backspace (really whatever erase char is
* set to, not necessarily \b) erases the previous
* character. It will erase unless escaped, because if
* it's escaped it is taken literally.
*/
escaped = OFF;
tab_seen = 0;
if (!*buffer || 0 == ((len = string_len(*buffer)))) {
/* Wrap to previous line if possible ... */
buffer = info->give_buffer(info,em_bs_prev,base_page);
if (!buffer)
goto restart;
}
if (*buffer && 0 < (len = string_len(*buffer))) {
int X = 0;
struct string * str = clip_from_string(*buffer,&X,
len-1);
uint16 c = give_unicode_from_string(*buffer,len-1);
if (0x0009 /* HT */ == c ||
/* FIXME: We may need redraw that also if there is double
with characters -- following is only rough estimation
and not necessary always correct ....
*/
0 != (CS_printable_len & charset_properties((*buffer)->string_type)))
tab_seen++;
else if(!passwd)
menu_Writechar(info->current_page,BACKSPACE);
free_string(buffer);
*buffer = str;
}
if(!passwd) {
if (tab_seen) { /* Redraw if TABulators or double width characters*/
buffer = info->give_buffer(info,em_redraw,
base_page);
goto restart;
} else {
menu_Writechar(info->current_page,' ');
menu_Writechar(info->current_page,BACKSPACE);
}
FlushBuffer();
}
break;
case TERMCH_word_erase:
if (!append_current && info->ch_count == 0 && *buffer) {
struct string * str = new_string((*buffer)->
string_type);
free_string(buffer);
*buffer = str;
info->ch_count++;
buffer = info->give_buffer(info,em_redraw,base_page);
goto restart;
}
if (!passwd) { /* back up a word! */
uint16 c;
int X = 0;
struct string * str;
tab_seen = 0;
if (!*buffer || 0 == (len = string_len(*buffer)))
continue; /* no point staying here.. */
len--;
if (0x002F /* / */
== give_unicode_from_string(*buffer,len)) {
len--;
erase_a_char();
} else {
while (len >= 0 &&
( c = give_unicode_from_string(*buffer,
len)) &&
( 0x0020 /* SPACE */ == c ||
0x0009 /* HT */ == c)) {
len--;
if (0x0009 /* HT */ == c)
tab_seen++;
if (!tab_seen)
erase_a_char();
}
while (len >= 0 &&
( c = give_unicode_from_string(*buffer,len)) &&
0x0020 /* SPACE */ != c &&
0x0009 /* HT */ != c &&
0x002F /* '/' */ != c) {
len--;
if (0x0009 /* HT */ == c)
tab_seen++;
if (!tab_seen)
erase_a_char();
}
}
str = clip_from_string(*buffer,&X,len+1);
free_string(buffer);
*buffer = str;
if (tab_seen) { /* Redraw if TABulators */
buffer = info->give_buffer(info,em_redraw,
base_page);
goto restart;
}
}
case TERMCH_reprint_char:
if (info->ch_count == 0)
buffer = info->give_buffer(info,em_redraw_initial,
base_page);
else
buffer = info->give_buffer(info,em_redraw, base_page);
goto restart;
case TERMCH_kill_line:
if (*buffer) {
struct string * str = new_string((*buffer)->
string_type);
free_string(buffer);
*buffer = str;
}
info->ch_count++;
buffer = info->give_buffer(info,em_redraw,base_page);
goto restart;
case TERMCH_interrupt_char:
if (*buffer)
free_string(buffer); /* clean up string, and... */
ret = -1;
goto out;
case LEFT_MARK:
buffer = info->give_buffer(info,em_left,base_page);
goto restart;
case UP_MARK:
case DOWN_MARK:
case RIGHT_MARK:
if (!append_current && info->ch_count == 0 && *buffer) {
/* Goto end of buffer */
info->ch_count++;
buffer = info->give_buffer(info,em_redraw,base_page);
goto restart;
}
switch(ch->caller_flags) {
case UP_MARK:
buffer = info->give_buffer(info,em_prev,base_page);
goto restart;
case DOWN_MARK:
buffer = info->give_buffer(info,em_next,base_page);
goto restart;
case RIGHT_MARK:
buffer = info->give_buffer(info,em_right,base_page);
goto restart;
}
break;
}
} else if (use_editor_escape &&
state_is_onebyte(ch) == escape_char &&
info->ch_count == 0 &&
(!append_current ||
!*buffer ||
0 == string_len(*buffer))) {
DPRINT(Debug,4,(&Debug,
"-- enter_helper: editor escape (%c)\n",
escape_char));
/* NOTE: em_editor_escape must NOT set OE_editor_escape */
info -> flags &= ~OE_EDITOR_ESCAPE;
buffer = info->give_buffer(info,em_editor_escape,base_page);
goto restart;
} else {
uint16 code = give_unicode_from_state(ch);
DPRINT(Debug,(passwd ? 51 : 4),
(&Debug,
"-- enter_helper: unicode=%04X\n",
code));
if (info->ch_count++ == 0) {
if (code == 0x000A /* LF */ ||
code == 0x000D /* CR */ ) {
buffer = info->give_buffer(info,em_enter,base_page);
goto restart;
} else if (alt_solidus && code == 0x002F /* '/' */) {
ret = OE_ALT_SOLIDUS;
goto out;
} else if (! append_current || !*buffer) {
CleartoEOLN();
if (*buffer)
free_string(buffer);
*buffer = new_string(ch->charset);
}
}
switch (code) {
case 0x000A: /* LF */
case 0x000D: /* CR */
buffer = info->give_buffer(info,em_enter,base_page);
goto restart;
case 0x000C: /* Ctrl-L */
if (redraw) {
buffer = info->give_buffer(info,em_redraw,base_page);
ret = REDRAW_MARK;
goto out;
}
goto other;
case 0x0000:
if (*buffer)
free_string(buffer); /* clean up string, and... */
ret = -1;
goto out;
case 0x003D: /* '=' */
if (allowmime && !escaped && !passwd) {
/* Allow user to PASTE mime encoded words
* (not editing)
*/
int len = string_len(*buffer);
int ok = 1;
int raw = '=';
int x1,y1;
int idx = 0;
struct string * temp = NULL;
struct string * temp2 = NULL;
/* MIME encoded word can be totally 75 characters
... */
char raw_data[80];
uint16 c;
if (len > 0 &&
( c = give_unicode_from_string(*buffer,len-1)) &&
0x0020 /* SPACE */ != c &&
0x0009 /* HT */ != c)
goto other;
menu_GetXYLocation(info->current_page,&x1, &y1);
menu_StartXX(info->current_page,pg_BOLD);
while (ok) {
if (idx > 78) {
ok = 0;
break;
}
raw_data[idx++] = raw;
menu_Writechar(info->current_page,raw);
ch = menu_ReadCh2(info->current_page,
redraw|READCH_CURSOR|
READCH_term_char);
if (ch -> caller_flags) {
ok = 0;
break;
}
raw = state_is_onebyte(ch);
DPRINT(Debug,4,(&Debug,
"-- enter_helper: raw=%d (%c)\n",
raw,raw));
if (!raw) {
ok = 0;
break;
} else if ('\\' == raw) {
/* No escape in mime encoded word ... */
ok = 0;
break;
} else if (1 == idx && '?' != raw) {
/* Not start with =? */
ok = 0;
break;
} else if (whitespace(raw) ||
'\r' == raw ||
'\n' == raw) {
/* Terminating characters */
break;
} else if (raw < ' ' || raw > 126) {
ok = 0;
break;
}
}
menu_EndXX(info->current_page,pg_BOLD);
menu_MoveCursor(info->current_page,x1,y1);
menu_CleartoEOLN(info->current_page);
raw_data[idx] = '\0';
DPRINT(Debug,4,(&Debug,
"-- enter_helper: ok=%d, encoded word=%s\n",
ok,raw_data));
temp = hdr_to_string(HDR_TEXT,raw_data,
display_charset,ok);
temp2 = cat_strings(*buffer,temp,0);
free_string(buffer);
*buffer = temp2;
free_string(&temp);
/* We redraw buffer on here so that it is
visible if catenate succeed or not ...
*/
buffer = info->give_buffer(info,em_redraw,base_page);
if (!buffer)
goto restart;
goto reprocess_key;
}
goto other;
case 0x0009: /* HT */
if (tabaction) {
DPRINT(Debug,4,(&Debug, "-- tabaction...\n"));
buffer = info->give_buffer(info,em_tabaction,
base_page);
if (!buffer)
goto restart;
break;
}
goto other;
default:
other:
if (!*buffer)
*buffer = new_string(ch->charset);
if (escaped) { /* We erase last \ */
int len = string_len(*buffer);
int X = 0;
struct string * str =
clip_from_string(*buffer,&X,len-1);
erase_a_char();
free_string(buffer);
*buffer = str;
escaped = OFF;
} else if (code == 0x005C /* \ */ &&
!passwd) {
escaped = ON;
} else if (add_comma &&
!passwd) {
int line, col;
int len;
/* Add comma (,) after addresses on header
editing screen ... */
GetXYLocation(&line, &col);
if (col +1 >= COLUMNS) {
buffer = info->give_buffer(info,em_next,base_page);
if (!buffer)
goto restart;
}
len = string_len(*buffer);
/* If user typed comma we not need auto-add
another one
*/
if (0x002C /* ',' */ == code)
add_comma = 0;
else if (len > 0) {
uint16 c,c2;
c = give_unicode_from_string(*buffer,len-1);
/* Add comma before TAB or
after '>' and ')' */
if ((0x0009 /* HT */ == code &&
0x0009 /* HT */ != c &&
0x0020 /* SPACE */ != c &&
0x002C /* ',' */ != c) ||
(0x0020 /* SPACE */ != code &&
0x003E /* '>' */ == c) ||
0x0029 /* ')' */ == c) {
add_ascii_to_string(*buffer,s2us(","));
menu_Writechar(info->current_page,',');
/* Only add comma on beginning
of editing */
add_comma = 0;
} else if (len > 1 &&
(c2 = give_unicode_from_string(*buffer,
len-2)) &&
/* Add comma before last character */
0x002C /* ',' */ != c2 &&
0x0020 /* SPACE */ == c &&
0x0028 /* '(' */ != code &&
0x003C /* '<' */ != code) {
int X = 0;
struct string * str =
clip_from_string(*buffer,&X,len-1);
add_ascii_to_string(str,s2us(", "));
free_string(buffer);
*buffer = str;
menu_Writechar(info->current_page,BACKSPACE);
menu_Writechar(info->current_page,',');
menu_Writechar(info->current_page,' ');
/* Only add comma on beginning
of editing */
add_comma = 0;
} else if (0x0020 /* SPACE */ != code)
add_comma = 0;
}
}
/* Note that HT (0x0009) is not printable character
but space (0x0032) is printable character
*/
if (0x0009 /* HT */ == code &&
allowtab) {
int line,col;
GetXYLocation(&line, &col);
if (!passwd &&
((col / get_tabspacing() ) +1) * get_tabspacing()
>= COLUMNS) {
buffer = info->give_buffer(info,em_next,base_page);
if (!buffer)
goto restart;
}
add_state_to_string(*buffer,ch);
if (!passwd) {
menu_Write_to_screen(info->current_page,
FRM("%C"),ch);
/* Call possible word wrapping routine
*/
GetXYLocation(&line, &col);
if (col >= wrap_column) {
buffer = info->give_buffer(info,em_wrap,
base_page);
if (!buffer)
goto restart;
}
}
} else if (!state_printable(ch) && !passwd) {
/* non-printing character - warn with bell */
menu_Writechar(info->current_page,'\007');
} else {
int line, col;
GetXYLocation(&line, &col);
if (!passwd && col +1 >= COLUMNS) {
buffer = info->give_buffer(info,em_next,
base_page);
if (!buffer)
goto restart;
}
if (!*buffer)
*buffer = new_string(ch->charset);
add_state_to_string(*buffer,ch);
if (!passwd) {
menu_Write_to_screen(info->current_page,
FRM("%C"),ch);
/* Call possible word wrapping routine */
GetXYLocation(&line, &col);
if (col >= wrap_column) {
buffer = info->give_buffer(info,em_wrap,
base_page);
if (!buffer)
goto restart;
}
}
}
}
}
} while(1);
}
out:
if (base_page != info->current_page) {
erase_menu_context(& info->current_page);
DPRINT(Debug,9,(&Debug,
"enter_helper: erasing menu_context created by give_buffer()\n"));
info->current_page = base_page;
menu_trigger_redraw(base_page);
}
DPRINT(Debug,9,(&Debug,
"enter_helper=%d (returns)\n",ret));
return ret;
}
static struct string **gb_optionally_enter P_((struct enter_info *I,
enum enter_mode em,
struct menu_context *base_page));
static struct string **gb_optionally_enter(I,em, base_page)
struct enter_info *I;
enum enter_mode em;
struct menu_context *base_page;
{
int passwd = 0 != (I->flags & OE_PASSWD);
int append_current = 0 != (I->flags & OE_APPEND_CURRENT);
switch(em) {
int line,col;
int line1,col1;
case em_redraw_initial:
if (!append_current) {
PutLineX(I->px, I->py, FRM("%S"), I->pvector[0]);
if(!passwd && I->pvector[1]) {
Write_to_screen(FRM("%S"), I->pvector[1]);
CleartoEOLN();
MoveCursor(I->px,I->py + string_len(I->pvector[0]));
}
I->ch_count = 0;
break;
}
/* FALLTHRU */
case em_redraw:
GetXYLocation(&line1, &col1);
PutLineX(I->px, I->py, FRM("%S"), I->pvector[0]);
if(!passwd && I->pvector[1]) {
Write_to_screen(FRM("%S"), I->pvector[1]);
}
CleartoEOLN();
GetXYLocation(&line, &col); /* Clear also next lines if cursor was there */
while (line < line1 && col1 >= I->py) {
line++;
MoveCursor(line,I->py);
CleartoEOLN();
}
break;
case em_enter:
DPRINT(Debug,4,
(&Debug, "-- gb_optionally_enter(..,%d)=NULL\n",
em));
return NULL;
}
DPRINT(Debug,4,(&Debug, "-- gb_optionally_enter(..,%d)=non null\n",
em));
return &(I->pvector[1]);
}
int optionally_enter2 P_((struct menu_context *page,
struct string **buffer,
int x, int y, int flags,
const char * format, const char *msg, ...));
int optionally_enter2 (
#if ANSI_C
struct menu_context *page,
struct string **buffer,
int x, int y, int flags,
const char * format, const char *msg, ...
#else
page, buffer, x, y, flags, format, msg, va_alist
#endif
)
#if !ANSI_C
struct menu_context *page;
struct string **buffer;
int x;
int y;
int flags;
CONST char * format;
CONST char *msg;
va_dcl
#endif
{
/** This will display the string on the screen and allow the user to
either accept it (by pressing RETURN) or alter it according to
what the user types. The various flags are:
string is the buffer to use (with optional initial value)
x,y is the location we're at on the screen (-1,-1 means
that we can't use this info and need to find out
the current location)
append_current means that we have an initial string and that
the cursor should be placed at the END of the line,
not the beginning (the default).
passwd accept non-printing characters and do not echo
entered characters.
If we hit an interrupt or EOF we'll return non-zero.
**/
int ret = 0;
struct string *question = NULL;
struct string *vector[2];
struct enter_info INFO;
static int nested_redraw_mark = 0;
va_list vl;
Va_start(vl, msg); /* defined in defs.h */
question = elm_smessage(0,format,msg,vl);
va_end(vl);
if(!(x >=0 && y >= 0))
GetXYLocation(&x, &y);
DPRINT(Debug,10, (&Debug, "optionally_enter2: (x,y) = %d,%d (line,col)\n",
x,y));
MoveCursor(x,y);
#if 0 /* ???? where this is needed?? */
if (redraw && nested_redraw_mark) {
nested_redraw_mark = 0;
DPRINT(Debug,4,
(&Debug,
"optionally_enter2: nested_redraw_mark set returning REDRAW_MARK\n"));
ret = REDRAW_MARK;
goto out;
}
#endif
nested_redraw_mark = 1;
/** now we have the screen as we want it and the cursor in the
right place, we can loop around on the input and return the
string as soon as the user presses <RETURN>
**/
vector[0] = question;
vector[1] = *buffer;
INFO.counter = 0;
INFO.pvector = vector;
INFO.px = x;
INFO.py = y;
INFO.give_buffer = gb_optionally_enter;
INFO.flags = flags;
INFO.ch_count = 0;
INFO.builtin = NULL;
INFO.dir_p = NULL;
INFO.current_page = page;
ret = enter_helper(&INFO, page);
*buffer = vector[1];
#if 0
out:
#endif
nested_redraw_mark = 0;
free_string(&question);
DPRINT(Debug,4,(&Debug,
"-- optionally_enter2=%d (%s%s*buffer=%p%s)\n",
ret,
ret == REDRAW_MARK ? "REDRAW_MARK, ": "",
ret == OE_ALT_SOLIDUS ? "OE_ALT_SOLIDUS, ": "",
*buffer,
*buffer ? "" : " = NULL"));
nested_redraw_mark = 0;
return ret;
}
int optionally_enter(string, x, y, flags, size,page)
char *string;
int x,y,flags;
int size;
struct menu_context *page;
{
int ret;
struct string * buffer = NULL;
char *str = NULL;
DPRINT(Debug,50,
(&Debug,
"optionally_enter: flags=%d size=%d\n",
flags,size));
buffer = new_string2(display_charset,s2us(string));
ret = optionally_enter2(page, &buffer,x,y,flags,FRM(""));
if (buffer) {
/* We line was totally erased, it does not necessary be
display_charset (but instead keyboard charset)
*/
struct string * s1 = convert_string(display_charset,buffer,0);
/* Includes only printable characters if not passwd,
* so we not need ask printable only characters
*/
str = us2s(stream_from_string(s1,0,NULL));
free_string(&s1);
}
if (str) {
strfcpy(string,str,size);
free(str); str = NULL;
} else
string[0] = '\0';
DPRINT(Debug,50,(&Debug,
"optionally_enter=%d string=%s\n",
ret,string));
if (buffer)
free_string(&buffer);
return(ret);
}
int GetPrompt(page)
struct menu_context *page;
{
/** This routine does a read/timeout for a single character.
The way that this was determined is that the routine to
read a character is called, then the "errno" is checked
against EINTR (interrupted call). If they match, this
returns NO_OP_COMMAND otherwise it returns the normal
command. On many systems, the EINTR will never be returned
so we instead longjmp from the signal handler.
**/
int ch;
if (elm_timeout > 0) {
alarm((unsigned) elm_timeout);
}
if (SETJMP(GetPromptBuf)) {
InGetPrompt = 0;
ch = NO_OP_COMMAND;
alarm((unsigned) 0);
#ifdef REMOTE_MBX
close_cached_connections();
#endif
}
else {
errno = 0;
InGetPrompt = 1;
ch = menu_ReadCh(page, 0|READCH_CURSOR);
if (errno == EINTR) ch = NO_OP_COMMAND;
#ifdef EAGAIN
if (errno == EAGAIN) ch = NO_OP_COMMAND;
#endif
#ifdef EWOULDBLOCK
if (errno == EWOULDBLOCK) ch = NO_OP_COMMAND;
#endif
InGetPrompt = 0;
alarm((unsigned) 0);
}
return(ch);
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1