Esempio n. 1
0
void
end_screen(char *message, int exit_val)
{
    int footer_rows_was_one = 0;

    if(panicking())
      return;

    if(FOOTER_ROWS(ps_global) == 1){
	footer_rows_was_one++;
	FOOTER_ROWS(ps_global) = 3;
	mark_status_unknown();
    }

    flush_status_messages(exit_val ? 0 : 1);

    blank_keymenu(_lines - 2, 0);

    if(message){
	StartInverse();
	PutLine0(_lines - 2, 0, message);
    }
    
    EndInverse();

    MoveCursor(_lines - 1, 0);

    mswin_showcaret(F_ON(F_SHOW_CURSOR, ps_global));

    if(footer_rows_was_one){
	FOOTER_ROWS(ps_global) = 1;
	mark_status_unknown();
    }
}
Esempio n. 2
0
File: radio.c Progetto: nysan/alpine
/*----------------------------------------------------------------------
   Paint the screen with the radio buttons prompt
  ----*/
void
draw_radio_prompt(int line, unsigned start_c, unsigned max_c, char *q)
{
    size_t len;
    unsigned x, width, got_width;
    char  *tmpq = NULL, *useq;

    width = utf8_width(q);
    if(width > max_c - start_c + 1){
	tmpq = (char *) fs_get((len=(strlen(q)+1)) * sizeof(char));
	(void) utf8_to_width(tmpq, q, len, max_c - start_c + 1, &got_width);
	useq = tmpq;
	width = got_width;
    }
    else
      useq = q;

    PutLine0(line, start_c, useq);
    x = start_c + width;
    MoveCursor(line, x);
    while(x++ < ps_global->ttyo->screen_cols)
      Writechar(' ', 0);

    MoveCursor(line, start_c + width);
    fflush(stdout);
    if(tmpq)
      fs_give((void **) &tmpq);
}
Esempio n. 3
0
/*----------------------------------------------------------------------
      Printf style output line to the screen at given position, 5 args

 Args:  x -- column position on the screen
        y -- column position on the screen
        line -- printf style line of text to output

 Result: text is output
         cursor position is update
  ----------------------------------------------------------------------*/
void
/*VARARGS6*/
PutLine5(int x, int y, char *line, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5)
{
    char buffer[PUTLINE_BUFLEN];

    snprintf(buffer, sizeof(buffer), line, arg1, arg2, arg3, arg4, arg5);
    buffer[sizeof(buffer)-1] = '\0';
    PutLine0(x, y, buffer);
}
Esempio n. 4
0
/*----------------------------------------------------------------------
      Printf style output line to the screen at given position, 1 arg

 Input:  position on the screen
         line of text to output

 Result: text is output
         cursor position is update
  ----------------------------------------------------------------------*/
void
/*VARARGS2*/
PutLine1(int x, int y, char *line, void *arg1)
{
    char buffer[PUTLINE_BUFLEN];

    snprintf(buffer, sizeof(buffer), line, arg1);
    buffer[sizeof(buffer)-1] = '\0';
    PutLine0(x, y, buffer);
}
Esempio n. 5
0
File: radio.c Progetto: nysan/alpine
/*----------------------------------------------------------------------

  ----*/
void
radio_help(int line, int column, HelpType help)
{
    char **text;

    /* assumption here is that HelpType is char **  */
    text = help;
    if(text == NULL)
      return;
    
    MoveCursor(line + 1, column);
    CleartoEOLN();
    if(text[0])
      PutLine0(line + 1, column, text[0]);

    MoveCursor(line + 2, column);
    CleartoEOLN();
    if(text[1])
      PutLine0(line + 2, column, text[1]);

    fflush(stdout);
}
Esempio n. 6
0
/*----------------------------------------------------------------------
       Output a UTF-8 line to the screen, centered

  Input:  Line number to print on, string to output
  
 Result:  String is output to screen
          Returns column number line is output on
  ----------------------------------------------------------------------*/
int
Centerline(int line, char *string)
{
    int width, col;

    width = (int) utf8_width(string);

    if (width > ps_global->ttyo->screen_cols)
      col = 0;
    else
      col = (ps_global->ttyo->screen_cols - width) / 2;

    PutLine0(line, col, string);

    return(col);
}
options()
{
	/** change options... **/
	/* return:
	 *	> 0	if restort was done - to indicate we might need to
	 *	 	change the page of our headers as a consequence
	 *		of the new sort order
	 *	< 0	if user entered 'x' to quit elm immediately
	 *	0	otherwise
	 */

	int	ch,
	     	resort = 0;
	char	*strcpy(),
	     	temp[SLEN];	/* needed when an option is run through
				 * expand_env(), because that function
				 * is destructive of the original
				 */

	display_options();

	clearerr(stdin);

	while(1) {
	  ClearLine(LINES-4);

	  Centerline(LINES-4,
 "Select first letter of option line, '>' to save, or 'i' to return to index.");

	  PutLine0(LINES-2, 0, "Command: ");

	  ch = ReadCh();
	  ch = tolower(ch);

	  clear_error();	/* remove possible "sorting" message etc... */

	  one_liner(one_liner_for(ch));

	  switch (ch) {
	    case 'c' : optionally_enter(raw_calendar_file, 2, 23, FALSE, FALSE);
		       strcpy(temp, raw_calendar_file);
		       expand_env(calendar_file, temp);
		       break;
	    case 'd' : optionally_enter(raw_pager, 3, 23, FALSE, FALSE);
		       strcpy(temp, raw_pager);
		       expand_env(pager, temp);
		       clear_pages = (equal(pager, "builtin+") ||
			             equal(pager, "internal+"));
		       break;
	    case 'e' : optionally_enter(raw_editor, 4, 23, FALSE, FALSE);
		       strcpy(temp, raw_editor);
		       expand_env(editor, temp);
	               break;
	    case 'f' : optionally_enter(raw_folders, 5, 23, FALSE, FALSE);
		       strcpy(temp, raw_folders);
		       expand_env(folders, temp);
		       break;
	    case 's' : if(change_sort(6,23)) resort++;			break;
	    case 'o' : optionally_enter(raw_sentmail, 7, 23, FALSE, FALSE);
		       strcpy(temp, raw_sentmail);
		       expand_env(sent_mail, temp);
		       break;
	    case 'p' : optionally_enter(raw_printout, 8, 23, FALSE, FALSE);
		       strcpy(temp, raw_printout);
		       expand_env(printout, temp);
		       break;
	    case 'y' : optionally_enter(full_username, 9, 23, FALSE, FALSE);
		       break;
	    case 'a' : on_or_off(&arrow_cursor, 12, 23); 		break;
	    case 'm' : on_or_off(&mini_menu, 13, 23);
		       headers_per_page = LINES - (mini_menu ? 13 : 8); break;

	    case 'u' : switch_user_level(&user_level,15, 23);		break;
	    case 'n' : on_or_off(&names_only, 16, 23);			break;

	    case '?' : options_help();
	               PutLine0(LINES-2,0,"Command: ");			break;

	    case '>' : printf("Save options in .elm/elmrc...");
		       fflush(stdout);    save_options();		break;

	    case 'x' :	return(-1);	/* exit elm */
	    case 'q' :	/* pop back up to previous level, in this case == 'i' */
	    case 'i' :  /* return to index screen */
			return(resort ? 1 : 0);
	    case ctrl('L'): display_options();				break;
	    default: error("Command unknown!");
	  }

	}
}
Esempio n. 8
0
int
optionally_enter(char *utf8string, int y_base, int x_base, int utf8string_size,
		 char *utf8prompt, ESCKEY_S *escape_list, HelpType help, int *flags)
{
    UCS           *string = NULL, ucs;
    size_t         string_size;
    UCS           *s2;
    UCS           *saved_original = NULL;
    char          *candidate;
    UCS           *kill_buffer = NULL;
    UCS           *k, *kb;
    int            field_pos;		/* offset into array dline.vl */
    int            i, j, return_v, cols, prompt_width, too_thin,
                   real_y_base, km_popped, passwd;
    char         **help_text;
    long	   fkey_table[12];
    struct	   key_menu *km;
    bitmap_t	   bitmap;
    COLOR_PAIR    *lastc = NULL, *promptc = NULL;
    struct variable *vars = ps_global->vars;
    struct display_line dline;
#ifdef	_WINDOWS
    int		   cursor_shown;
#endif

    dprint((5, "=== optionally_enter called ===\n"));
    dprint((9, "utf8string:\"%s\"  y:%d  x:%d  length: %d append: %d\n",
               utf8string ? utf8string : "",
	       x_base, y_base, utf8string_size,
	       (flags && *flags & OE_APPEND_CURRENT)));
    dprint((9, "passwd:%d   utf8prompt:\"%s\"   label:\"%s\"\n",
	       (flags && *flags & OE_PASSWD_NOAST) ? 10 :
		   (flags && *flags & OE_PASSWD) ? 1 : 0,
	       utf8prompt ? utf8prompt : "",
	       (escape_list && escape_list[0].ch != -1 && escape_list[0].label)
		 ? escape_list[0].label: ""));

    if(!ps_global->ttyo)
      return(pre_screen_config_opt_enter(utf8string, utf8string_size, utf8prompt,
					 escape_list, help, flags));

#ifdef _WINDOWS
    if (mswin_usedialog ())
      return(win_dialog_opt_enter(utf8string, utf8string_size, utf8prompt,
				  escape_list, help, flags));
#endif


    /*
     * Utf8string comes in as UTF-8. We'll convert it to a UCS-4 array and operate on
     * that array, then convert it back before returning. Utf8string_size is the size
     * of the utf8string array but that doesn't help us much for the array we need to
     * operate on here. We'll just allocate a big array and then cut it off when
     * sending it back.
     *
     * This should come before the specialized calls above but those aren't
     * converted to use UCS-4 yet.
     */
    string = utf8_to_ucs4_cpystr(utf8string);
    dline.vused = ucs4_strlen(string);

    string_size = (2 * MAX(utf8string_size,dline.vused) + 100);
    fs_resize((void **) &string, string_size * sizeof(UCS));

    suspend_busy_cue();
    cols         = ps_global->ttyo->screen_cols;
    prompt_width = utf8_width(utf8prompt);
    too_thin   = 0;
    km_popped  = 0;
    if(y_base > 0)
      real_y_base = y_base;
    else{
        real_y_base = y_base + ps_global->ttyo->screen_rows;
	real_y_base = MAX(real_y_base, 0);
    }

    flush_ordered_messages();
    mark_status_dirty();

    if(flags && *flags & OE_APPEND_CURRENT) /* save a copy in case of cancel */
      saved_original = ucs4_cpystr(string);

    /*
     * build the function key mapping table, skipping predefined keys...
     */
    memset(fkey_table, NO_OP_COMMAND, 12 * sizeof(long));
    for(i = 0, j = 0; escape_list && escape_list[i].ch != -1 && i+j < 12; i++){
	if(i+j == OE_HELP_KEY)
	  j++;

	if(i+j == OE_CANCEL_KEY)
	  j++;

	if(i+j == OE_ENTER_KEY)
	  j++;

	fkey_table[i+j] = escape_list[i].ch;
    }

    /* assumption that HelpType is char **  */
    help_text = help;
    if(help_text){			/*---- Show help text -----*/
	int width = ps_global->ttyo->screen_cols - x_base;

	if(FOOTER_ROWS(ps_global) == 1){
	    km_popped++;
	    FOOTER_ROWS(ps_global) = 3;
	    clearfooter(ps_global);

	    y_base = -3;
	    real_y_base = y_base + ps_global->ttyo->screen_rows;
	}

	for(j = 0; j < 2 && help_text[j]; j++){
	    MoveCursor(real_y_base + 1 + j, x_base);
	    CleartoEOLN();

	    if(width < utf8_width(help_text[j])){
		char *tmp = cpystr(help_text[j]);
		(void) utf8_truncate(tmp, width);
		PutLine0(real_y_base + 1 + j, x_base, tmp);
		fs_give((void **) &tmp);
	    }
	    else
	      PutLine0(real_y_base + 1 + j, x_base, help_text[j]);
	}
    }
    else{
	clrbitmap(bitmap);
	clrbitmap((km = &oe_keymenu)->bitmap);		/* force formatting */
	if(!(flags && (*flags) & OE_DISALLOW_HELP))
	  setbitn(OE_HELP_KEY, bitmap);

	setbitn(OE_ENTER_KEY, bitmap);
	if(!(flags && (*flags) & OE_DISALLOW_CANCEL))
	  setbitn(OE_CANCEL_KEY, bitmap);

	setbitn(OE_CTRL_T_KEY, bitmap);

        /*---- Show the usual possible keys ----*/
	for(i=0,j=0; escape_list && escape_list[i].ch != -1 && i+j < 12; i++){
	    if(i+j == OE_HELP_KEY)
	      j++;

	    if(i+j == OE_CANCEL_KEY)
	      j++;

	    if(i+j == OE_ENTER_KEY)
	      j++;

	    oe_keymenu.keys[i+j].label = escape_list[i].label;
	    oe_keymenu.keys[i+j].name = escape_list[i].name;
	    setbitn(i+j, bitmap);
	}

	for(i = i+j; i < 12; i++)
	  if(!(i == OE_HELP_KEY || i == OE_ENTER_KEY || i == OE_CANCEL_KEY))
	    oe_keymenu.keys[i].name = NULL;

	draw_keymenu(km, bitmap, cols, 1-FOOTER_ROWS(ps_global), 0, FirstMenu);
    }
    
    if(pico_usingcolor() && VAR_PROMPT_FORE_COLOR &&
       VAR_PROMPT_BACK_COLOR &&
       pico_is_good_color(VAR_PROMPT_FORE_COLOR) &&
       pico_is_good_color(VAR_PROMPT_BACK_COLOR)){
	lastc = pico_get_cur_color();
	if(lastc){
	    promptc = new_color_pair(VAR_PROMPT_FORE_COLOR,
				     VAR_PROMPT_BACK_COLOR);
	    (void)pico_set_colorp(promptc, PSC_NONE);
	}
    }
    else
      StartInverse();

    /*
     * if display length isn't wide enough to support input,
     * shorten up the prompt...
     */
    if((dline.dwid = cols - (x_base + prompt_width)) < MIN_OPT_ENT_WIDTH){
	char *p;
	unsigned got_width;

	/*
	 * Scoot prompt pointer forward at least (MIN_OPT_ENT_WIDTH - dline.dwid) screencells.
	 */
	p = utf8_count_forw_width(utf8prompt, MIN_OPT_ENT_WIDTH-dline.dwid, &got_width);
	if(got_width < MIN_OPT_ENT_WIDTH-dline.dwid)
	  p = utf8_count_forw_width(utf8prompt, MIN_OPT_ENT_WIDTH+1-dline.dwid, &got_width);

	if(p){
	    prompt_width = utf8_width(p);
	    dline.dwid =  cols - (x_base + prompt_width);
	    utf8prompt = p;
	}
    }

    /*
     * How many UCS-4 characters will we need to make up the width dwid? It could be
     * unlimited because of zero-width characters, I suppose, but realistically it
     * isn't going to be much more than dwid.
     */
    dline.dlen = 2 * dline.dwid + 100;

    dline.dl    = (UCS *) fs_get(dline.dlen * sizeof(UCS));
    dline.olddl = (UCS *) fs_get(dline.dlen * sizeof(UCS));
    memset(dline.dl,    0, dline.dlen * sizeof(UCS));
    memset(dline.olddl, 0, dline.dlen * sizeof(UCS));

    dline.movecursor = MoveCursor;
    dline.writechar  = Writewchar;

    dline.row   = real_y_base;
    dline.col   = x_base + prompt_width;

    dline.vl    = string;
    dline.vlen  = --string_size;		/* -1 for terminating zero */
    dline.vbase = field_pos = 0;

#ifdef	_WINDOWS
    cursor_shown = mswin_showcaret(1);
#endif
    
    PutLine0(real_y_base, x_base, utf8prompt);

    /*
     * If appending, position field_pos at end of input.
     */
    if(flags && *flags & OE_APPEND_CURRENT)
      while(string[field_pos])
	field_pos++;

    passwd = (flags && *flags & OE_PASSWD_NOAST) ? 10 :
              (flags && *flags & OE_PASSWD)       ?  1 : 0;
    line_paint(field_pos, &dline, &passwd);

    /*----------------------------------------------------------------------
      The main loop
	loops until someone sets the return_v.
      ----------------------------------------------------------------------*/
    return_v = -10;

    while(return_v == -10) {

#ifdef	MOUSE
	mouse_in_content(KEY_MOUSE, -1, -1, 0x5, 0);
	register_mfunc(mouse_in_content, 
		       real_y_base, x_base + prompt_width,
		       real_y_base, ps_global->ttyo->screen_cols);
#endif
#ifdef	_WINDOWS
	mswin_allowpaste(MSWIN_PASTE_LINE);
	g_mc_row = real_y_base;
	g_mc_col = x_base + prompt_width;
	mswin_mousetrackcallback(pcpine_oe_cursor);
#endif

	/* Timeout 10 min to keep imap mail stream alive */
	ps_global->conceal_sensitive_debugging = passwd ? 1 : 0;
        ucs = read_char(600);
	ps_global->conceal_sensitive_debugging = 0;

#ifdef	MOUSE
	clear_mfunc(mouse_in_content);
#endif
#ifdef	_WINDOWS
	mswin_allowpaste(MSWIN_PASTE_DISABLE);
	mswin_mousetrackcallback(NULL);
#endif

	/*
	 * Don't want to intercept all characters if typing in passwd.
	 * We select an ad hoc set that we will catch and let the rest
	 * through.  We would have caught the set below in the big switch
	 * but we skip the switch instead.  Still catch things like ^K,
	 * DELETE, ^C, RETURN.
	 */
	if(passwd)
	  switch(ucs){
            case ctrl('F'):  
	    case KEY_RIGHT:
            case ctrl('B'):
	    case KEY_LEFT:
            case ctrl('U'):
            case ctrl('A'):
	    case KEY_HOME:
            case ctrl('E'):
	    case KEY_END:
	    case TAB:
	      goto ok_for_passwd;
	  }

        if(too_thin && ucs != KEY_RESIZE && ucs != ctrl('Z') && ucs != ctrl('C'))
          goto bleep;

	switch(ucs){

	    /*--------------- KEY RIGHT ---------------*/
          case ctrl('F'):  
	  case KEY_RIGHT:
	    if(field_pos >= string_size || string[field_pos] == '\0')
              goto bleep;

	    line_paint(++field_pos, &dline, &passwd);
	    break;

	    /*--------------- KEY LEFT ---------------*/
          case ctrl('B'):
	  case KEY_LEFT:
	    if(field_pos <= 0)
	      goto bleep;

	    line_paint(--field_pos, &dline, &passwd);
	    break;

          /*-------------------- WORD SKIP --------------------*/
	  case ctrl('@'):
	    /*
	     * Note: read_char *can* return NO_OP_COMMAND which is
	     * the def'd with the same value as ^@ (NULL), BUT since
	     * read_char has a big timeout (>25 secs) it won't.
	     */

	    /* skip thru current word */
	    while(string[field_pos]
		  && isalnum((unsigned char) string[field_pos]))
	      field_pos++;

	    /* skip thru current white space to next word */
	    while(string[field_pos]
		  && !isalnum((unsigned char) string[field_pos]))
	      field_pos++;

	    line_paint(field_pos, &dline, &passwd);
	    break;

          /*--------------------  RETURN --------------------*/
	  case PF4:
	    if(F_OFF(F_USE_FK,ps_global)) goto bleep;
	  case ctrl('J'): 
	  case ctrl('M'): 
	    return_v = 0;
	    break;

          /*-------------------- Destructive backspace --------------------*/
	  case '\177': /* DEL */
	  case ctrl('H'):
            /*   Try and do this with by telling the terminal to delete a
                 a character. If that fails, then repaint the rest of the
                 line, acheiving the same much less efficiently
             */
	    if(field_pos <= 0)
	      goto bleep;

	    field_pos--;
	    /* drop thru to pull line back ... */

          /*-------------------- Delete char --------------------*/
	  case ctrl('D'): 
	  case KEY_DEL: 
            if(field_pos >= string_size || !string[field_pos])
	      goto bleep;

	    dline.vused--;
	    for(s2 = &string[field_pos]; *s2 != 0; s2++)
	      *s2 = s2[1];

	    *s2 = 0;			/* Copy last NULL */
	    line_paint(field_pos, &dline, &passwd);
	    if(flags)		/* record change if requested  */
	      *flags |= OE_USER_MODIFIED;

	    break;

            /*--------------- Kill line -----------------*/
          case ctrl('K'):
            if(kill_buffer != NULL)
              fs_give((void **) &kill_buffer);

	    if(field_pos != 0 || string[0]){
		if(!passwd && F_ON(F_DEL_FROM_DOT, ps_global))
		  dline.vused -= ucs4_strlen(&string[i = field_pos]);
		else
		  dline.vused = i = 0;

		kill_buffer = ucs4_cpystr(&string[field_pos = i]);
		string[field_pos] = '\0';
		line_paint(field_pos, &dline, &passwd);
		if(flags)		/* record change if requested  */
		  *flags |= OE_USER_MODIFIED;
	    }

            break;

            /*------------------- Undelete line --------------------*/
          case ctrl('U'):
            if(kill_buffer == NULL)
              goto bleep;

            /* Make string so it will fit */
            kb = ucs4_cpystr(kill_buffer);
            if(ucs4_strlen(kb) + ucs4_strlen(string) > string_size) 
                kb[string_size - ucs4_strlen(string)] = '\0';
                       
            if(string[field_pos] == '\0') {
                /*--- adding to the end of the string ----*/
                for(k = kb; *k; k++)
		  string[field_pos++] = *k;

                string[field_pos] = '\0';
            }
	    else{
		int shift;

		shift = ucs4_strlen(kb);

		/* shift field_pos ... end to right */
		for(k = &string[field_pos] + ucs4_strlen(&string[field_pos]);
		    k >= &string[field_pos]; k--)
		  *(k+shift) = *k;

                for(k = kb; *k; k++)
		  string[field_pos++] = *k;
            }

	    if(*kb && flags)		/* record change if requested  */
	      *flags |= OE_USER_MODIFIED;

	    dline.vused = ucs4_strlen(string);
            fs_give((void **) &kb);
	    line_paint(field_pos, &dline, &passwd);
            break;
            
	    /*-------------------- Interrupt --------------------*/
	  case ctrl('C'): /* ^C */ 
	    if(F_ON(F_USE_FK,ps_global) || (flags && ((*flags) & OE_DISALLOW_CANCEL)))
	      goto bleep;

	    goto cancel;

	  case PF2:
	    if(F_OFF(F_USE_FK,ps_global) || (flags && ((*flags) & OE_DISALLOW_CANCEL)))
	      goto bleep;

	  cancel:
	    return_v = 1;
	    if(saved_original){
		for(i = 0; saved_original[i]; i++)
		  string[i] = saved_original[i];

		string[i] = 0;
	    }

	    break;

          case ctrl('A'):
	  case KEY_HOME:
            /*-------------------- Start of line -------------*/
	    line_paint(field_pos = 0, &dline, &passwd);
            break;

          case ctrl('E'):
	  case KEY_END:
            /*-------------------- End of line ---------------*/
	    line_paint(field_pos = dline.vused, &dline, &passwd);
            break;

	    /*-------------------- Help --------------------*/
	  case ctrl('G') : 
	  case PF1:
	    if(flags && ((*flags) & OE_DISALLOW_HELP))
	      goto bleep;
	    else if(FOOTER_ROWS(ps_global) == 1 && km_popped == 0){
		km_popped++;
		FOOTER_ROWS(ps_global) = 3;
		clearfooter(ps_global);
		if(lastc)
		  (void)pico_set_colorp(lastc, PSC_NONE);
		else
		  EndInverse();

		draw_keymenu(km, bitmap, cols, 1-FOOTER_ROWS(ps_global),
			     0, FirstMenu);

		if(promptc)
		  (void)pico_set_colorp(promptc, PSC_NONE);
		else
		  StartInverse();

		mark_keymenu_dirty();
		y_base = -3;
		dline.row = real_y_base = y_base + ps_global->ttyo->screen_rows;
		PutLine0(real_y_base, x_base, utf8prompt);
		memset(dline.dl,    0, dline.dlen * sizeof(UCS));
		memset(dline.olddl, 0, dline.dlen * sizeof(UCS));
		line_paint(field_pos, &dline, &passwd);
		break;
	    }

	    if(FOOTER_ROWS(ps_global) > 1){
		mark_keymenu_dirty();
		return_v = 3;
	    }
	    else
	      goto bleep;

	    break;


#ifdef	MOUSE
			    /* Mouse support untested in pine 5.00 */
	  case KEY_MOUSE :
	    {
	      MOUSEPRESS mp;
	      int w;

	      mouse_get_last (NULL, &mp);

	      switch(mp.button){
		case M_BUTTON_LEFT :			/* position cursor */
		  mp.col -= dline.col;

		  /*
		   * We have to figure out which character is under the cursor.
		   * This is complicated by the fact that characters may
		   * be other than one cell wide.
		   */

		  /* the -1 is for the '<' when text is offscreen left */
		  w = (dline.vbase > 0) ? mp.col-1 : mp.col;

		  if(mp.col <= 0)
		    field_pos = dline.vbase - 1;
		  else{
		    if(dline.vused <= dline.vbase
		       || ucs4_str_width_a_to_b(dline.vl,dline.vbase,dline.vused-1) <= w)
		      field_pos = dline.vused;
		    else{
		      /*
		       * Find index of 1st character that causes the
		       * width to be > w.
		       */
		      for(i = 0;
			  ucs4_str_width_a_to_b(dline.vl,dline.vbase,dline.vbase+i) <= w;
			  i++)
			;

		      field_pos = dline.vbase + i;
		    }
		  }
		  
		  field_pos = MIN(MAX(field_pos, 0), dline.vused);

		  /* just allow line_paint to choose vbase */
		  line_paint(field_pos, &dline, &passwd);
		  break;

		case M_BUTTON_RIGHT :
#ifdef	_WINDOWS

		  /*
		   * Same as M_BUTTON_LEFT except we paste in text after
		   * moving the cursor.
		   */

		  mp.col -= dline.col;

		  /* the -1 is for the '<' when text is offscreen left */
		  w = (dline.vbase > 0) ? mp.col-1 : mp.col;

		  if(mp.col <= 0)
		    field_pos = dline.vbase - 1;
		  else{
		    if(dline.vused <= dline.vbase
		       || ucs4_str_width_a_to_b(dline.vl,dline.vbase,dline.vused-1) <= w)
		      field_pos = dline.vused;
		    else{
		      /*
		       * Find index of 1st character that causes the
		       * width to be > w.
		       */
		      for(i = 0;
			  ucs4_str_width_a_to_b(dline.vl,dline.vbase,dline.vbase+i) <= w;
			  i++)
			;

		      field_pos = dline.vbase + i;
		    }
		  }
		  
		  field_pos = MIN(MAX(field_pos, 0), dline.vused);

		  line_paint(field_pos, &dline, &passwd);

		  mswin_allowpaste(MSWIN_PASTE_LINE);
		  mswin_paste_popup();
		  mswin_allowpaste(MSWIN_PASTE_DISABLE);
		  break;
#endif

		case M_BUTTON_MIDDLE :			/* NO-OP for now */
		default:				/* just ignore */
		  break;
	      }
	    }

	    break;
#endif


          case NO_OP_IDLE:
	    /*
	     * Keep mail stream alive by checking for new mail.
	     * If we're asking for a password in a login prompt
	     * we don't want to check for new_mail because the
	     * new mail check might be what got us here in the first
	     * place (because of a filter trying to save a message).
	     * If we need to wait for the user to come back then
	     * the caller will just have to deal with the failure
	     * to login.
	     */
	    i = -1;
	    if(!ps_global->no_newmail_check_from_optionally_enter)
	      i = new_mail(0, 2, NM_DEFER_SORT);

	    if(sp_expunge_count(ps_global->mail_stream) &&
	       flags && ((*flags) & OE_SEQ_SENSITIVE))
	      goto cancel;

	    if(i < 0){
	      line_paint(field_pos, &dline, &passwd);
	      break;			/* no changes, get on with life */
	    }
	    /* Else fall into redraw */

	    /*-------------------- Redraw --------------------*/
	  case ctrl('L'):
            /*---------------- re size ----------------*/
          case KEY_RESIZE:
            
	    dline.row = real_y_base = y_base > 0 ? y_base :
					 y_base + ps_global->ttyo->screen_rows;
	    if(lastc)
	      (void)pico_set_colorp(lastc, PSC_NONE);
	    else
	      EndInverse();

            ClearScreen();
            redraw_titlebar();
            if(ps_global->redrawer != (void (*)(void))NULL)
              (*ps_global->redrawer)();

            redraw_keymenu();
	    if(promptc)
	      (void)pico_set_colorp(promptc, PSC_NONE);
	    else
	      StartInverse();
            
            PutLine0(real_y_base, x_base, utf8prompt);
            cols     =  ps_global->ttyo->screen_cols;
            too_thin = 0;
            if(cols < x_base + prompt_width + 4){
		Writechar(BELL, 0);
                PutLine0(real_y_base, 0, "Screen's too thin. Ouch!");
                too_thin = 1;
            }
	    else{
		dline.col  = x_base + prompt_width;
		dline.dwid = cols - (x_base + prompt_width);
		dline.dlen = 2 * dline.dwid + 100;
		fs_resize((void **) &dline.dl, (size_t) dline.dlen * sizeof(UCS));
		fs_resize((void **) &dline.olddl, (size_t) dline.dlen * sizeof(UCS));
		memset(dline.dl,    0, dline.dlen * sizeof(UCS));
		memset(dline.olddl, 0, dline.dlen * sizeof(UCS));
		line_paint(field_pos, &dline, &passwd);
            }

            fflush(stdout);

            dprint((9,
                    "optionally_enter  RESIZE new_cols:%d  too_thin: %d\n",
                       cols, too_thin));
            break;

	  case PF3 :		/* input to potentially remap */
	  case PF5 :
	  case PF6 :
	  case PF7 :
	  case PF8 :
	  case PF9 :
	  case PF10 :
	  case PF11 :
	  case PF12 :
	      if(F_ON(F_USE_FK,ps_global)
		 && fkey_table[ucs - PF1] != NO_OP_COMMAND)
		ucs = fkey_table[ucs - PF1]; /* remap function key input */
  
          default:
	    if(escape_list){		/* in the escape key list? */
		for(j=0; escape_list[j].ch != -1; j++){
		    if(escape_list[j].ch == ucs){
			return_v = escape_list[j].rval;
			break;
		    }
		}

		if(return_v != -10)
		  break;
	    }

	    if(ucs < 0x80 && FILTER_THIS((unsigned char) ucs)){
       bleep:
		putc(BELL, stdout);
		continue;
	    }

       ok_for_passwd:
	    /*--- Insert a character -----*/
	    if(dline.vused >= string_size)
	      goto bleep;

	    /*---- extending the length of the string ---*/
	    for(s2 = &string[++dline.vused]; s2 - string > field_pos; s2--)
	      *s2 = *(s2-1);

	    string[field_pos++] = ucs;
	    line_paint(field_pos, &dline, &passwd);
	    if(flags)		/* record change if requested  */
	      *flags |= OE_USER_MODIFIED;
		    
	}   /*---- End of switch on char ----*/
    }

#ifdef	_WINDOWS
    if(!cursor_shown)
      mswin_showcaret(0);
#endif

    if(dline.dl)
      fs_give((void **) &dline.dl);

    if(dline.olddl)
      fs_give((void **) &dline.olddl);

    if(saved_original) 
      fs_give((void **) &saved_original);

    if(kill_buffer)
      fs_give((void **) &kill_buffer);

    /*
     * Change string back into UTF-8.
     */
    candidate = ucs4_to_utf8_cpystr(string);

    if(string) 
      fs_give((void **) &string);

    if(candidate){
	strncpy(utf8string, candidate, utf8string_size);
	utf8string[utf8string_size-1] = '\0';
	fs_give((void **) &candidate);
    }

    if (!(flags && (*flags) & OE_KEEP_TRAILING_SPACE))
      removing_trailing_white_space(utf8string);

    if(lastc){
	(void)pico_set_colorp(lastc, PSC_NONE);
	free_color_pair(&lastc);
	if(promptc)
	  free_color_pair(&promptc);
    }
    else
      EndInverse();

    MoveCursor(real_y_base, x_base); /* Move the cursor to show we're done */
    fflush(stdout);
    resume_busy_cue(0);
    if(km_popped){
	FOOTER_ROWS(ps_global) = 1;
	clearfooter(ps_global);
	ps_global->mangled_body = 1;
    }

    return(return_v);
}
int
subshell()
{
	/** spawn a subshell with either the specified command
	    returns non-zero if screen rewrite needed
	**/

	char command[SLEN];
	int  old_raw, helpful, ret;

	helpful = (user_level == 0);

	if (helpful)
	  PutLine0(LINES-3, COLUMNS-40, catgets(elm_msg_cat, ElmSet, ElmUseShellName,
		"(Use the shell name for a shell.)"));
	PutLine0(LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmShellCommand,
		"Shell command: "));
	CleartoEOS();
	command[0] = '\0';
	(void) optionally_enter(command, LINES-2, 15, FALSE, FALSE);
	if (command[0] == 0) {
	  if (helpful)
	    MoveCursor(LINES-3,COLUMNS-40);
	  else
	    MoveCursor(LINES-2,0);
	  CleartoEOS();
	  return 0;
	}

	MoveCursor(LINES,0);
	CleartoEOLN();

	if ((old_raw = RawState()) == ON)
	  Raw(OFF);
	softkeys_off();
	if (cursor_control)
	  transmit_functions(OFF);

	umask(original_umask);	/* restore original umask so users new files are ok */
	ret = system_call(command, SY_USER_SHELL|SY_ENAB_SIGINT|SY_DUMPSTATE);
	umask(077);		/* now put it back to private for mail files */

	SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
	PutLine0(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmPressAnyKeyToReturn,
		"\n\nPress any key to return to ELM: "));
	Raw(ON | NO_TITE);
	(void) getchar();
	printf("\r\n");
	Raw(OFF | NO_TITE); /* Done even if old_raw == ON, to get ti/te right */
	if (old_raw == ON)
	  Raw(ON);

	softkeys_on();
	if (cursor_control)
	  transmit_functions(ON);

	if (ret)
	  error1(catgets(elm_msg_cat, ElmSet, ElmReturnCodeWas,
		"Return code was %d."), ret);

	return 1;
}