Beispiel #1
0
static int
tinfoeeop(void)
{
    int i, starting_col, starting_row;

    /*
     * If the terminal doesn't have back color erase, then we have to
     * erase manually to preserve the background color.
     */
    if(pico_usingcolor() && (!_bce || !_cleartoeos)){
	extern int ttcol, ttrow;

	starting_col = ttcol;
	starting_row = ttrow;
	tinfoeeol();				  /* rest of this line */
	for(i = ttrow+1; i <= term.t_nrow; i++){  /* the remaining lines */
	    tinfomove(i, 0);
	    tinfoeeol();
	}

	tinfomove(starting_row, starting_col);
    }
    else if(_cleartoeos)
      putpad(_cleartoeos);

    /* return ignored */
    return(0);
}
Beispiel #2
0
static int
tinfoeeol(void)
{
    int   c, starting_col, starting_line;
    char *last_bg_color;

    /*
     * If the terminal doesn't have back color erase, then we have to
     * erase manually to preserve the background color.
     */
    if(pico_usingcolor() && (!_bce || !_cleartoeoln)){
	extern int ttcol, ttrow;

	starting_col  = ttcol;
	starting_line = ttrow;
	last_bg_color = pico_get_last_bg_color();
	pico_set_nbg_color();
	for(c = ttcol; c < term.t_ncol; c++)
	  ttputc(' ');
	
        tinfomove(starting_line, starting_col);
	if(last_bg_color){
	    pico_set_bg_color(last_bg_color);
	    free(last_bg_color);
	}
    }
    else if(_cleartoeoln)
      putpad(_cleartoeoln);

    /* return ignored */
    return(0);
}
Beispiel #3
0
/*
 * Returns a pointer to the normal color.
 *
 * NOTE: Don't free this!
 */
COLOR_PAIR *
pico_get_normal_color(void)
{
    if(pico_usingcolor() && _nfcolor && _nbcolor &&
       pico_is_good_color(_nfcolor) && pico_is_good_color(_nbcolor)){
	if(!the_normal_color)
	  the_normal_color = new_color_pair(_nfcolor, _nbcolor);
	
	return(the_normal_color);
    }
    else
      return(NULL);
}
Beispiel #4
0
/*
 * If inverse is a color, returns a pointer to that color.
 * If not, returns NULL.
 *
 * NOTE: Don't free this!
 */
COLOR_PAIR *
pico_get_rev_color(void)
{
    if(pico_usingcolor() && _rfcolor && _rbcolor &&
       pico_is_good_color(_rfcolor) && pico_is_good_color(_rbcolor)){
	if(!the_rev_color)
	  the_rev_color = new_color_pair(_rfcolor, _rbcolor);
	
	return(the_rev_color);
    }
    else
      return(NULL);
}
Beispiel #5
0
/*
 * Sets color to (fg,bg).
 * Flags == PSC_NONE  No alternate default if fg,bg fails.
 *       == PSC_NORM  Set it to Normal color on failure.
 *       == PSC_REV   Set it to Reverse color on failure.
 *
 * If flag PSC_RET is set, returns an allocated copy of the previous
 * color pair, otherwise returns NULL.
 */
COLOR_PAIR *
pico_set_colors(char *fg, char *bg, int flags)
{
    int         uc;
    COLOR_PAIR *cp = NULL, *rev = NULL;

    if(flags & PSC_RET)
      cp = pico_get_cur_color();

    if(fg && !strcmp(fg, END_PSEUDO_REVERSE)){
	EndInverse();
	if(cp)
	  free_color_pair(&cp);
    }
    else if(!((uc=pico_usingcolor()) && fg && bg &&
	      pico_set_fg_color(fg) && pico_set_bg_color(bg))){

	if(uc && flags & PSC_NORM)
	  pico_set_normal_color();
	else if(flags & PSC_REV){
	    if((rev = pico_get_rev_color()) != NULL){
		pico_set_fg_color(rev->fg);	/* these will succeed */
		pico_set_bg_color(rev->bg);
	    }
	    else{
		StartInverse();
		if(cp){
		    strncpy(cp->fg, END_PSEUDO_REVERSE, MAXCOLORLEN+1);
		    cp->fg[MAXCOLORLEN] = '\0';
		    strncpy(cp->bg, END_PSEUDO_REVERSE, MAXCOLORLEN+1);
		    cp->bg[MAXCOLORLEN] = '\0';
		}
	    }
	}
    }

    return(cp);
}
Beispiel #6
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);
}
Beispiel #7
0
/*----------------------------------------------------------------------
    Prompt user for a choice among alternatives

Args --  utf8prompt:    The prompt for the question/selection
         line:      The line to prompt on, if negative then relative to bottom
         esc_list:  ESC_KEY_S list of keys
         dflt:	    The selection when the <CR> is pressed (should probably
		      be one of the chars in esc_list)
         on_ctrl_C: The selection when ^C is pressed
         help_text: Text to be displayed on bottom two lines
	 flags:     Logically OR'd flags modifying our behavior to:
		RB_FLUSH_IN    - Discard any pending input chars.
		RB_ONE_TRY     - Only give one chance to answer.  Returns
				 on_ctrl_C value if not answered acceptably
				 on first try.
		RB_NO_NEWMAIL  - Quell the usual newmail check.
		RB_SEQ_SENSITIVE - The caller is sensitive to sequence number
				   changes so return on_ctrl_C if an
				   unsolicited expunge happens while we're
				   viewing a message.
		RB_RET_HELP    - Instead of the regular internal handling
				 way of handling help_text, this just causes
				 radio_buttons to return 3 when help is
				 asked for, so that the caller handles it
				 instead.
	
	 Note: If there are enough keys in the esc_list to need a second
	       screen, and there is no help, then the 13th key will be
	       put in the help position.

Result -- Returns the letter pressed. Will be one of the characters in the
          esc_list argument, or dflt, or on_ctrl_C, or SEQ_EXCEPTION.

This will pause for any new status message to be seen and then prompt the user.
The prompt will be truncated to fit on the screen. Redraw and resize are
handled along with ^Z suspension. Typing ^G will toggle the help text on and
off. Character types that are not buttons will result in a beep (unless one_try
is set).
  ----*/
int
radio_buttons(char *utf8prompt, int line, ESCKEY_S *esc_list, int dflt,
	      int on_ctrl_C, HelpType help_text, int flags)
{
    UCS              ucs;
    register int     ch, real_line;
    char            *q, *ds = NULL;
    unsigned         maxcol;
    int              max_label, i, start, fkey_table[12];
    int		     km_popped = 0;
    struct key	     rb_keys[12];
    struct key_menu  rb_keymenu;
    bitmap_t	     bitmap;
    struct variable *vars = ps_global->vars;
    COLOR_PAIR      *lastc = NULL, *promptc = NULL;

#ifdef	_WINDOWS
    int		     cursor_shown;

    if (mswin_usedialog()){
	MDlgButton button_list[25];
	LPTSTR     free_names[25];
	LPTSTR     free_labels[25];
	int        b, i, ret;
	char     **help;

	memset(&free_names, 0, sizeof(LPTSTR) * 25);
	memset(&free_labels, 0, sizeof(LPTSTR) * 25);
	memset(&button_list, 0, sizeof (MDlgButton) * 25);
	b = 0;

	if(flags & RB_RET_HELP){
	    if(help_text != NO_HELP)
	      alpine_panic("RET_HELP and help in radio_buttons!");

	    button_list[b].ch = '?';
	    button_list[b].rval = 3;
	    button_list[b].name = TEXT("?");
	    free_labels[b] = utf8_to_lptstr(N_("Help"));
	    button_list[b].label = free_labels[b];
	    ++b;
	}

	for(i = 0; esc_list && esc_list[i].ch != -1 && i < 23; ++i){
	  if(esc_list[i].ch != -2){
	    button_list[b].ch = esc_list[i].ch;
	    button_list[b].rval = esc_list[i].rval;
	    free_names[b] = utf8_to_lptstr(esc_list[i].name);
	    button_list[b].name = free_names[b];
	    free_labels[b] = utf8_to_lptstr(esc_list[i].label);
	    button_list[b].label = free_labels[b];
	    ++b;
	  }
	}

	button_list[b].ch = -1;
	
	/* assumption here is that HelpType is char **  */
	help = help_text;

	ret = mswin_select(utf8prompt, button_list, dflt, on_ctrl_C, help, flags);
	for(i = 0; i < 25; i++){
	    if(free_names[i])
	      fs_give((void **) &free_names[i]);
	    if(free_labels[i])
	      fs_give((void **) &free_labels[i]);
	}

	return (ret);
    }

#endif /* _WINDOWS */

    suspend_busy_cue();
    flush_ordered_messages();		/* show user previous status msgs */
    mark_status_dirty();		/* clear message next display call */
    real_line = line > 0 ? line : ps_global->ttyo->screen_rows + line;
    MoveCursor(real_line, RAD_BUT_COL);
    CleartoEOLN();

    /*---- Find widest label ----*/
    max_label = 0;
    for(i = 0; esc_list && esc_list[i].ch != -1 && i < 11; i++){
      if(esc_list[i].ch == -2) /* -2 means to skip this key and leave blank */
	continue;
      if(esc_list[i].name)
        max_label = MAX(max_label, utf8_width(esc_list[i].name));
    }

    if(ps_global->ttyo->screen_cols - max_label - 1 > 0)
      maxcol = ps_global->ttyo->screen_cols - max_label - 1;
    else
      maxcol = 0;

    /*
     * We need to be able to truncate q, so copy it in case it is
     * a readonly string.
     */
    q = cpystr(utf8prompt);

    /*---- Init structs for keymenu ----*/
    for(i = 0; i < 12; i++)
      memset((void *)&rb_keys[i], 0, sizeof(struct key));

    memset((void *)&rb_keymenu, 0, sizeof(struct key_menu));
    rb_keymenu.how_many = 1;
    rb_keymenu.keys     = rb_keys;

    /*---- Setup key menu ----*/
    start = 0;
    clrbitmap(bitmap);
    memset(fkey_table, NO_OP_COMMAND, 12 * sizeof(int));
    if(flags & RB_RET_HELP && help_text != NO_HELP)
      alpine_panic("RET_HELP and help in radio_buttons!");

    /* if shown, always at position 0 */
    if(help_text != NO_HELP || flags & RB_RET_HELP){
	rb_keymenu.keys[0].name  = "?";
	rb_keymenu.keys[0].label = N_("Help");
	setbitn(0, bitmap);
	fkey_table[0] = ctrl('G');
	start++;
    }

    if(on_ctrl_C){
	rb_keymenu.keys[1].name  = "^C";
	rb_keymenu.keys[1].label = N_("Cancel");
	setbitn(1, bitmap);
	fkey_table[1] = ctrl('C');
	start++;
    }

    start = start ? 2 : 0;
    /*---- Show the usual possible keys ----*/
    for(i=start; esc_list && esc_list[i-start].ch != -1; i++){
	/*
	 * If we have an esc_list item we'd like to put in the non-existent
	 * 13th slot, and there is no help, we put it in the help slot
	 * instead.  We're hacking now...!
	 *
	 * We may also have invisible esc_list items that don't show up
	 * on the screen.  We use this when we have two different keys
	 * which are synonyms, like ^P and KEY_UP.  If all the slots are
	 * already full we can still fit invisible keys off the screen to
	 * the right.  A key is invisible if it's label is "".
	 */
	if(i >= 12){
	    if(esc_list[i-start].label
	       && esc_list[i-start].label[0] != '\0'){  /* visible */
		if(i == 12){  /* special case where we put it in help slot */
		    if(help_text != NO_HELP)
		  alpine_panic("Programming botch in radio_buttons(): too many keys");

		    if(esc_list[i-start].ch != -2)
		      setbitn(0, bitmap); /* the help slot */

		    fkey_table[0] = esc_list[i-start].ch;
		    rb_keymenu.keys[0].name  = esc_list[i-start].name;
		    if(esc_list[i-start].ch != -2
		       && esc_list[i-start].rval == dflt
		       && esc_list[i-start].label){
		        size_t l;

			l = strlen(esc_list[i-start].label) + 2;
			ds = (char *)fs_get((l+1) * sizeof(char));
			snprintf(ds, l+1, "[%s]", esc_list[i-start].label);
			ds[l] = '\0';
			rb_keymenu.keys[0].label = ds;
		    }
		    else
		      rb_keymenu.keys[0].label = esc_list[i-start].label;
		}
		else
		  alpine_panic("Botch in radio_buttons(): too many keys");
	    }
	}
	else{
	    if(esc_list[i-start].ch != -2)
	      setbitn(i, bitmap);

	    fkey_table[i] = esc_list[i-start].ch;
	    rb_keymenu.keys[i].name  = esc_list[i-start].name;
	    if(esc_list[i-start].ch != -2
	       && esc_list[i-start].rval == dflt
	       && esc_list[i-start].label){
	        size_t l;

		l = strlen(esc_list[i-start].label) + 2;
		ds = (char *)fs_get((l+1) * sizeof(char));
		snprintf(ds, l+1, "[%s]", esc_list[i-start].label);
		ds[l] = '\0';
		rb_keymenu.keys[i].label = ds;
	    }
	    else
	      rb_keymenu.keys[i].label = esc_list[i-start].label;
	}
    }

    for(; i < 12; i++)
      rb_keymenu.keys[i].name = NULL;

    ps_global->mangled_footer = 1;

#ifdef	_WINDOWS
    cursor_shown = mswin_showcaret(1);
#endif

    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();

    draw_radio_prompt(real_line, RAD_BUT_COL, maxcol, q);

    while(1){
        fflush(stdout);

	/*---- Paint the keymenu ----*/
	if(lastc)
	  (void)pico_set_colorp(lastc, PSC_NONE);
	else
	  EndInverse();

	draw_keymenu(&rb_keymenu, bitmap, ps_global->ttyo->screen_cols,
		     1 - FOOTER_ROWS(ps_global), 0, FirstMenu);
	if(promptc)
	  (void)pico_set_colorp(promptc, PSC_NONE);
	else
	  StartInverse();

	MoveCursor(real_line, MIN(RAD_BUT_COL+utf8_width(q), maxcol+1));

	if(flags & RB_FLUSH_IN)
	  flush_input();

  newcmd:
	/* Timeout 5 min to keep imap mail stream alive */
        ucs = read_char(600);
        dprint((2,
                   "Want_to read: %s (0x%x)\n", pretty_command(ucs), ucs));
	if((ucs < 0x80) && isupper((unsigned char) ucs))
	  ucs = tolower((unsigned char) ucs);

	if(F_ON(F_USE_FK,ps_global)
	   && (((ucs < 0x80) && isalpha((unsigned char) ucs) && !strchr("YyNn",(int) ucs))
	       || ((ucs >= PF1 && ucs <= PF12)
		   && (ucs = fkey_table[ucs - PF1]) == NO_OP_COMMAND))){
	    /*
	     * The funky test above does two things.  It maps
	     * esc_list character commands to function keys, *and* prevents
	     * character commands from input while in function key mode.
	     * NOTE: this breaks if we ever need more than the first
	     * twelve function keys...
	     */
	    if(flags & RB_ONE_TRY){
		ch = ucs = on_ctrl_C;
	        goto out_of_loop;
	    }

	    Writechar(BELL, 0);
	    continue;
	}

        switch(ucs){

          default:
	    for(i = 0; esc_list && esc_list[i].ch != -1; i++)
	      if(ucs == esc_list[i].ch){
		  int len, n;

		  MoveCursor(real_line,len=MIN(RAD_BUT_COL+utf8_width(q),maxcol+1));
		  for(n = 0, len = ps_global->ttyo->screen_cols - len;
		      esc_list[i].label && esc_list[i].label[n] && len > 0;
		      n++, len--)
		    Writechar(esc_list[i].label[n], 0);

		  ch = esc_list[i].rval;
		  goto out_of_loop;
	      }

	    if(flags & RB_ONE_TRY){
		ch = on_ctrl_C;
	        goto out_of_loop;
	    }

	    Writechar(BELL, 0);
	    break;

          case ctrl('M'):
          case ctrl('J'):
            ch = dflt;
	    for(i = 0; esc_list && esc_list[i].ch != -1; i++)
	      if(ch == esc_list[i].rval){
		  int len, n;

		  MoveCursor(real_line,len=MIN(RAD_BUT_COL+utf8_width(q),maxcol+1));
		  for(n = 0, len = ps_global->ttyo->screen_cols - len;
		      esc_list[i].label && esc_list[i].label[n] && len > 0;
		      n++, len--)
		    Writechar(esc_list[i].label[n], 0);
		  break;
	      }

            goto out_of_loop;

          case ctrl('C'):
	    if(on_ctrl_C || (flags & RB_ONE_TRY)){
		ch = on_ctrl_C;
		goto out_of_loop;
	    }

	    Writechar(BELL, 0);
	    break;


          case '?':
          case ctrl('G'):
	    if(FOOTER_ROWS(ps_global) == 1 && km_popped == 0){
		km_popped++;
		FOOTER_ROWS(ps_global) = 3;
		line = -3;
		real_line = ps_global->ttyo->screen_rows + line;
		if(lastc)
		  (void)pico_set_colorp(lastc, PSC_NONE);
		else
		  EndInverse();

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

		draw_radio_prompt(real_line, RAD_BUT_COL, maxcol, q);
		break;
	    }

	    if(flags & RB_RET_HELP){
		ch = 3;
		goto out_of_loop;
	    }
	    else if(help_text != NO_HELP && FOOTER_ROWS(ps_global) > 1){
		mark_keymenu_dirty();
		if(lastc)
		  (void)pico_set_colorp(lastc, PSC_NONE);
		else
		  EndInverse();

		MoveCursor(real_line + 1, RAD_BUT_COL);
		CleartoEOLN();
		MoveCursor(real_line + 2, RAD_BUT_COL);
		CleartoEOLN();
		radio_help(real_line, RAD_BUT_COL, help_text);
		sleep(5);
		MoveCursor(real_line, MIN(RAD_BUT_COL+utf8_width(q), maxcol+1));
		if(promptc)
		  (void)pico_set_colorp(promptc, PSC_NONE);
		else
		  StartInverse();
	    }
	    else
	      Writechar(BELL, 0);

            break;
            

          case NO_OP_COMMAND:
	    goto newcmd;		/* misunderstood escape? */

          case NO_OP_IDLE:		/* UNODIR, keep the stream alive */
	    if(flags & RB_NO_NEWMAIL)
	      goto newcmd;

	    i = new_mail(0, VeryBadTime, NM_DEFER_SORT);
	    if(sp_expunge_count(ps_global->mail_stream)
	       && flags & RB_SEQ_SENSITIVE){
		if(on_ctrl_C)
		  ch = on_ctrl_C;
		else
		  ch = SEQ_EXCEPTION;

		goto out_of_loop;
	    }

	    if(i < 0)
	      break;		/* no changes, get on with life */
            /* Else fall into redraw to adjust displayed numbers and such */


          case KEY_RESIZE:
          case ctrl('L'):
            real_line = line > 0 ? line : ps_global->ttyo->screen_rows + line;
	    if(lastc)
	      (void)pico_set_colorp(lastc, PSC_NONE);
	    else
	      EndInverse();

            ClearScreen();
            redraw_titlebar();
            if(ps_global->redrawer != NULL)
              (*ps_global->redrawer)();
	    if(FOOTER_ROWS(ps_global) == 3 || km_popped)
              redraw_keymenu();

	    if(ps_global->ttyo->screen_cols - max_label - 1 > 0)
	      maxcol = ps_global->ttyo->screen_cols - max_label - 1;
	    else
	      maxcol = 0;

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

	    draw_radio_prompt(real_line, RAD_BUT_COL, maxcol, q);
            break;

        } /* switch */
    }

  out_of_loop:

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

    fs_give((void **) &q);
    if(ds)
      fs_give((void **) &ds);

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

    fflush(stdout);
    resume_busy_cue(0);
    if(km_popped){
	FOOTER_ROWS(ps_global) = 1;
	clearfooter(ps_global);
	ps_global->mangled_body = 1;
    }

    return(ch);
}
Beispiel #8
0
/*----------------------------------------------------------------------
   Handle fetching and filtering a text message segment to be displayed
   by scrolltool or printed or exported or piped.

Args: att   -- segment to fetch
      msgno -- message number segment is a part of
      pc    -- function to write characters from segment with
      style -- Indicates special handling for error messages
      flags -- Indicates special necessary handling

Returns: 1 if errors encountered, 0 if everything went A-OK

 ----*/     
int
decode_text(ATTACH_S	    *att,
	    long int	     msgno,
	    gf_io_t	     pc,
	    HANDLE_S	   **handlesp,
	    DetachErrStyle   style,
	    int		     flags)
{
    FILTLIST_S	filters[14];
    char       *err, *charset;
    int		filtcnt = 0, error_found = 0, column, wrapit;
    int         is_in_sig = OUT_SIG_BLOCK;
    int         is_flowed_msg = 0, add_me = 1, doraw = RAWSTRING;
    int         is_delsp_yes = 0;
    int         filt_only_c0 = 0;
    char       *parmval;
    char       *free_this = NULL;
    STORE_S    *warn_so = NULL;
    DELQ_S      dq;
    URL_HILITE_S uh;

    column = (flags & FM_DISPLAY) ? ps_global->ttyo->screen_cols : 80;

    if(!(flags & FM_DISPLAY))
      flags |= FM_NOINDENT;

    wrapit = column;

    memset(filters, 0, sizeof(filters));

    /* charset the body part is in */
    charset = parameter_val(att->body->parameter, "charset");

    /* determined if it's flowed, affects wrapping and quote coloring */
    if(att->body->type == TYPETEXT
       && !strucmp(att->body->subtype, "plain")
       && (parmval = parameter_val(att->body->parameter, "format"))){
	if(!strucmp(parmval, "flowed"))
	  is_flowed_msg = 1;
	fs_give((void **) &parmval);

	if(is_flowed_msg){
	    if((parmval = parameter_val(att->body->parameter, "delsp")) != NULL){
		if(!strucmp(parmval, "yes"))
		  is_delsp_yes = 1;

		fs_give((void **) &parmval);
	    }
	}
    }

    if(!ps_global->pass_ctrl_chars){
	filters[filtcnt++].filter = gf_escape_filter;
	filters[filtcnt].filter = gf_control_filter;

	filt_only_c0 = 1;
	filters[filtcnt++].data = gf_control_filter_opt(&filt_only_c0);
    }

    if(flags & FM_DISPLAY)
      filters[filtcnt++].filter = gf_tag_filter;

    /*
     * if it's just plain old text, look for url's
     */
    if(!(att->body->subtype && strucmp(att->body->subtype, "plain"))){
	struct variable *vars = ps_global->vars;

	if((F_ON(F_VIEW_SEL_URL, ps_global)
	    || F_ON(F_VIEW_SEL_URL_HOST, ps_global)
	    || F_ON(F_SCAN_ADDR, ps_global))
	   && handlesp){

	    /*
	     * The url_hilite filter really ought to come
	     * after flowing, because flowing with the DelSp=yes parameter
	     * can reassemble broken urls back into identifiable urls.
	     * We add the preflow filter to do only the reassembly part
	     * of the flowing so that we can spot the urls.
	     * At this time (2005-03-29) we know that Apple Mail does
	     * send mail like this sometimes. This filter removes the
	     * sequence  SP CRLF  if that seems safe.
	     */
	    if(ps_global->full_header != 2 && is_delsp_yes)
              filters[filtcnt++].filter = gf_preflow;

	    filters[filtcnt].filter = gf_line_test;
	    filters[filtcnt++].data = gf_line_test_opt(url_hilite,
						       gf_url_hilite_opt(&uh,handlesp,0));
	}

	if((flags & FM_DISPLAY)
           && !(flags & FM_NOCOLOR)
           && pico_usingcolor()
           && VAR_SPECIAL_TEXT_FORE_COLOR 
           && VAR_SPECIAL_TEXT_BACK_COLOR){
            filters[filtcnt].filter = gf_line_test;
            filters[filtcnt++].data = gf_line_test_opt(color_this_text, NULL);
        }

	/*
	 * First, paint the signature.
	 * Disclaimers noted below for coloring quotes apply here as well.
	 */
	if((flags & FM_DISPLAY)
	   && !(flags & FM_NOCOLOR)
	   && pico_usingcolor()
	   && VAR_SIGNATURE_FORE_COLOR
	   && VAR_SIGNATURE_BACK_COLOR){
	    filters[filtcnt].filter = gf_quote_test;
	    filters[filtcnt++].data = gf_line_test_opt(color_signature,
						       &is_in_sig);
	}

	/*
	 * Gotta be careful with this. The color_a_quote filter adds color
	 * to the beginning and end of the line. This will break some
	 * line_test-style filters which come after it. For example, if they
	 * are looking for something at the start of a line (like color_a_quote
	 * itself). I guess we could fix that by ignoring tags at the
	 * beginning of the line when doing the search.
	 */
	if((flags & FM_DISPLAY)
	   && !(flags & FM_NOCOLOR)
	   && pico_usingcolor()
	   && VAR_QUOTE1_FORE_COLOR
	   && VAR_QUOTE1_BACK_COLOR){
	    add_me = 0;
	    filters[filtcnt].filter = gf_quote_test;
	    filters[filtcnt++].data = gf_line_test_opt(color_a_quote, &is_flowed_msg);
	}
    }
    else if(!strucmp(att->body->subtype, "richtext")){
	int plain_opt;

	plain_opt = !(flags&FM_DISPLAY);

	/* maybe strip everything! */
	filters[filtcnt].filter = gf_rich2plain;
	filters[filtcnt++].data = gf_rich2plain_opt(&plain_opt);
	/* width to use for file or printer */
	if(wrapit - 5 > 0)
	  wrapit -= 5;
    }
    else if(!strucmp(att->body->subtype, "enriched")){
	int plain_opt;

	plain_opt = !(flags&FM_DISPLAY);

	filters[filtcnt].filter = gf_enriched2plain;
	filters[filtcnt++].data = gf_enriched2plain_opt(&plain_opt);
	/* width to use for file or printer */
	if(wrapit - 5 > 0)
	  wrapit -= 5;
    }
    else if(!strucmp(att->body->subtype, "html") && ps_global->full_header < 2){
/*BUG:	    sniff the params for "version=2.0" ala draft-ietf-html-spec-01 */
	int	 opts = 0;

	clear_html_risk();

	if(flags & FM_DISPLAY){
	    gf_io_t	 warn_pc;

	    if(handlesp){		/* pass on handles awareness */
		opts |= GFHP_HANDLES;

		if(F_OFF(F_QUELL_HOST_AFTER_URL, ps_global) && !(flags & FM_HIDESERVER))
		  opts |= GFHP_SHOW_SERVER;
	    }

	    if(!(flags & FM_NOEDITORIAL)){
		warn_so = so_get(CharStar, NULL, EDIT_ACCESS);
		gf_set_so_writec(&warn_pc, warn_so);
		format_editorial(HTML_WARNING, column, flags, handlesp, warn_pc);
		gf_clear_so_writec(warn_so);
		so_puts(warn_so, "\015\012");
		so_writec('\0', warn_so);
	    }
	}
	else
	  opts |= GFHP_STRIPPED;	/* don't embed anything! */

	if(flags & FM_NOHTMLREL)
	  opts |= GFHP_NO_RELATIVE;

	if(flags & FM_HTMLRELATED)
	  opts |= GFHP_RELATED_CONTENT;

	if(flags & FM_HTML)
	  opts |= GFHP_HTML;

	if(flags & FM_HTMLIMAGES)
	  opts |= GFHP_HTML_IMAGES;

	wrapit = 0;		/* wrap already handled! */
	filters[filtcnt].filter = gf_html2plain;
	filters[filtcnt++].data = gf_html2plain_opt(NULL, column,
						    (flags & (FM_NOINDENT | FM_HTML))
						      ? 0
						      : format_view_margin(),
						    handlesp, set_html_risk, opts);

	if(warn_so){
	    filters[filtcnt].filter = gf_prepend_editorial;
	    filters[filtcnt++].data = gf_prepend_editorial_opt(get_html_risk,
							       (char *) so_text(warn_so));
	}
    }

    if (add_me){
      filters[filtcnt].filter = gf_quote_test;
      filters[filtcnt++].data = gf_line_test_opt(select_quote, &doraw);
    }

    /*
     * If the message is not flowed, we do the quote suppression before
     * the wrapping, because the wrapping does not preserve the quote
     * characters at the beginnings of the lines in that case.
     * Otherwise, we defer until after the wrapping.
     *
     * Also, this is a good place to do quote-replacement on nonflowed
     * messages because no other filters depend on the "> ".
     * Quote-replacement is easier in the flowed case and occurs
     * automatically in the flowed wrapping filter.
     */
    if(!is_flowed_msg
       && ps_global->full_header == 0
       && !(att->body->subtype && strucmp(att->body->subtype, "plain"))
       && (flags & FM_DISPLAY)){
	if(ps_global->quote_suppression_threshold != 0){
	    memset(&dq, 0, sizeof(dq));
	    dq.lines = ps_global->quote_suppression_threshold;
	    dq.is_flowed = is_flowed_msg;
	    dq.indent_length = 0;		/* indent didn't happen yet */
	    dq.saved_line = &free_this;
	    dq.handlesp   = handlesp;
	    dq.do_color   = (!(flags & FM_NOCOLOR) && pico_usingcolor());

	    filters[filtcnt].filter = gf_quote_test;
	    filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
	}
	if(ps_global->VAR_QUOTE_REPLACE_STRING
	    && F_ON(F_QUOTE_REPLACE_NOFLOW, ps_global)){
	    filters[filtcnt].filter = gf_line_test;
	    filters[filtcnt++].data = gf_line_test_opt(replace_quotes, NULL);
	}
    }

    if(wrapit && !(flags & FM_NOWRAP)){
	int wrapflags = (flags & FM_DISPLAY) ? (GFW_HANDLES|GFW_SOFTHYPHEN)
					     : GFW_NONE;

	if(flags & FM_DISPLAY
	   && !(flags & FM_NOCOLOR)
	   && pico_usingcolor())
	  wrapflags |= GFW_USECOLOR;

	/* text/flowed (RFC 2646 + draft)? */
	if(ps_global->full_header != 2 && is_flowed_msg){
	    wrapflags |= GFW_FLOWED;

	    if(is_delsp_yes)
	      wrapflags |= GFW_DELSP;
	}

	filters[filtcnt].filter = gf_wrap;
	filters[filtcnt++].data = gf_wrap_filter_opt(wrapit, column,
						     (flags & FM_NOINDENT)
						       ? 0
						       : format_view_margin(),
						     0, wrapflags);
    }

    /*
     * This has to come after wrapping has happened because the user tells
     * us how many quoted lines to display, and we want that number to be
     * the wrapped lines, not the pre-wrapped lines. We do it before the
     * wrapping if the message is not flowed, because the wrapping does not
     * preserve the quote characters at the beginnings of the lines in that
     * case.
     */
    if(is_flowed_msg
       && ps_global->full_header == 0
       && !(att->body->subtype && strucmp(att->body->subtype, "plain"))
       && (flags & FM_DISPLAY)
       && ps_global->quote_suppression_threshold != 0){
	memset(&dq, 0, sizeof(dq));
	dq.lines = ps_global->quote_suppression_threshold;
	dq.is_flowed = is_flowed_msg;
	dq.indent_length = (wrapit && !(flags & FM_NOWRAP)
			    && !(flags & FM_NOINDENT))
			       ? format_view_margin()[0]
			       : 0;
	dq.saved_line = &free_this;
	dq.handlesp   = handlesp;
	dq.do_color   = (!(flags & FM_NOCOLOR) && pico_usingcolor());

	filters[filtcnt].filter = gf_quote_test;
	filters[filtcnt++].data = gf_line_test_opt(delete_quotes, &dq);
    }

    if(charset){
	if(F_OFF(F_QUELL_CHARSET_WARNING, ps_global)
	   && !(flags & FM_NOEDITORIAL)){
	    int rv = TRUE;
	    CONV_TABLE *ct = NULL;

	    /*
	     * Need editorial if message charset is not ascii
	     * and the display charset is not either the same
	     * as the message charset or UTF-8.
	     */
	    if(strucmp(charset, "us-ascii")
	       && !((ps_global->display_charmap
		     && !strucmp(charset, ps_global->display_charmap))
	            || !strucmp("UTF-8", ps_global->display_charmap))){

		/*
		 * This is probably overkill. We're just using this
		 * conversion_table routine to get at the quality.
		 */
		if(ps_global->display_charmap)
		  ct = conversion_table(charset, ps_global->display_charmap);

		rv = charset_editorial(charset, msgno, handlesp, flags,
				       ct ? ct->quality : CV_NO_TRANSLATE_POSSIBLE,
				       column, pc);
	    }
	    if(!rv)
	      goto write_error;
	}

	fs_give((void **) &charset);
    }

    /* Format editorial comment about unknown encoding */
    if(att->body->encoding > ENCQUOTEDPRINTABLE){
	char buf[2048];

	snprintf(buf, sizeof(buf), ENCODING_DISCLAIMER, body_encodings[att->body->encoding]);

	if(!(format_editorial(buf, column, flags, handlesp, pc) == NULL
	     && gf_puts(NEWLINE, pc) && gf_puts(NEWLINE, pc)))
	  goto write_error;
    }

    err = detach(ps_global->mail_stream, msgno, att->number, 0L,
		 NULL, pc, filtcnt ? filters : NULL, 0);
    
    delete_unused_handles(handlesp);
    
    if(free_this)
      fs_give((void **) &free_this);

    if(warn_so)
      so_give(&warn_so);
    
    if(err) {
	error_found++;
	if(style == QStatus) {
	    q_status_message1(SM_ORDER, 3, 4, "%.200s", err);
	} else if(style == InLine) {
	    char buftmp[MAILTMPLEN];

	    snprintf(buftmp, sizeof(buftmp), "%s",
		    att->body->description ? att->body->description : "");
	    snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s   [Error: %s]  %c%s%c%s%s",
		    NEWLINE, err,
		    att->body->description ? '\"' : ' ',
		    att->body->description ? buftmp : "",
		    att->body->description ? '\"' : ' ',
		    NEWLINE, NEWLINE);
	    if(!gf_puts(tmp_20k_buf, pc))
	      goto write_error;
	}
    }

    if(att->body->subtype
       && (!strucmp(att->body->subtype, "richtext")
	   || !strucmp(att->body->subtype, "enriched"))
       && !(flags & FM_DISPLAY)){
	if(!gf_puts(NEWLINE, pc) || !gf_puts(NEWLINE, pc))
	  goto write_error;
    }

    return(error_found);

  write_error:
    if(style == QStatus)
      q_status_message1(SM_ORDER, 3, 4, "Error writing message: %.200s", 
			error_description(errno));

    return(1);
}
Beispiel #9
0
char *
format_editorial(char *s, int width, int flags, HANDLE_S **handlesp, gf_io_t pc)
{
    gf_io_t	 gc;
    int		*margin;
    EDITORIAL_S  es;
    URL_HILITE_S uh;

    /* ASSUMPTION #2,341: All MIME-decoding is done by now */
    gf_set_readc(&gc, s, strlen(s), CharStar, 0);

    margin = format_view_margin();
    if(flags & FM_NOINDENT)
      margin[0] = margin[1] = 0;

    /* safety net */
    if(width - (margin[0] + margin[1]) < 5){
	margin[0] = margin[1] = 0;
	if(width < 5)
	  width = 80;
    }

    width -= (margin[0] + margin[1]);

    if(width > 40){
	width -= 12;

	es.prelen = MAX(2, MIN(margin[0] + 6, sizeof(es.prefix) - 3));
	snprintf(es.prefix, sizeof(es.prefix), "%s[ ", repeat_char(es.prelen - 2, ' '));
	es.postlen = 2;
	strncpy(es.postfix, " ]", sizeof(es.postfix));
	es.postfix[sizeof(es.postfix)-1] = '\0';
    }
    else if(width > 20){
	width -= 6;

	es.prelen = MAX(2, MIN(margin[0] + 3, sizeof(es.prefix) - 3));
	snprintf(es.prefix, sizeof(es.prefix), "%s[ ", repeat_char(es.prelen - 2, ' '));
	es.postlen = 2;
	strncpy(es.postfix, " ]", sizeof(es.postfix));
	es.postfix[sizeof(es.postfix)-1] = '\0';
    }
    else{
	width -= 2;
	strncpy(es.prefix, "[", sizeof(es.prefix));
	es.prefix[sizeof(es.prefix)-1] = '\0';
	strncpy(es.postfix, "]", sizeof(es.postfix));
	es.postfix[sizeof(es.postfix)-1] = '\0';
	es.prelen = 1;
	es.postlen = 1;
    }

    es.do_color = (!(flags & FM_NOCOLOR) && (flags & FM_DISPLAY) && pico_usingcolor());

    gf_filter_init();

    /* catch urls */
    if((F_ON(F_VIEW_SEL_URL, ps_global)
	|| F_ON(F_VIEW_SEL_URL_HOST, ps_global)
	|| F_ON(F_SCAN_ADDR, ps_global))
       && handlesp){
	gf_link_filter(gf_line_test,
		       gf_line_test_opt(url_hilite,
				        gf_url_hilite_opt(&uh,handlesp,0)));
    }
      
    gf_link_filter(gf_wrap, gf_wrap_filter_opt(width, width, NULL, 0,
					       (handlesp ? GFW_HANDLES : GFW_NONE)));
    gf_link_filter(gf_line_test, gf_line_test_opt(quote_editorial, &es));

    /* If not for display, change to local end of line */
    if(!(flags & FM_DISPLAY))
	gf_link_filter(gf_nvtnl_local, NULL);

    return(gf_pipe(gc, pc));
}
Beispiel #10
0
/*----------------------------------------------------------------------
  Output line of length len to the display observing embedded attributes

 Args:  x      -- column position on the screen
        y      -- column position on the screen
        line   -- text to be output
        length -- length of text to be output

 Result: text is output
         cursor position is updated
  ----------------------------------------------------------------------*/
void
PutLine0n8b(int x, int y, register char *line, int length, HANDLE_S *handles)
{
    unsigned char c;
    int is_inv = 0, is_bold = 0, is_uline = 0, is_fg = 0, is_bg = 0;
#ifdef	_WINDOWS
    int hkey = 0;
#endif

    MoveCursor(x,y);

    while(length--){

	c = (unsigned char) *line++;

	if(c == (unsigned char) TAG_EMBED && length){

	    length--;

	    switch(*line++){
	      case TAG_INVON :
		StartInverse();
		is_inv = 1;
		break;

	      case TAG_INVOFF :
		EndInverse();
		is_inv = 0;
		break;

	      case TAG_BOLDON :
		StartBold();
		is_bold = 1;
		break;

	      case TAG_BOLDOFF :
		EndBold();
		is_bold = 0;
		break;

	      case TAG_ITALICON : /* express italic as uline in terminal */
	      case TAG_ULINEON :
		StartUnderline();
		is_uline = 1;
		break;

	      case TAG_ITALICOFF : /* express italic as uline in terminal */
	      case TAG_ULINEOFF :
		EndUnderline();
		is_uline = 0;
		break;

	      case TAG_HANDLE :
		length -= *line + 1;	/* key length plus length tag */
		if(handles){
		    int  key, n, current_key = 0;

		    for(key = 0, n = *line++; n; n--) /* forget Horner? */
		      key = (key * 10) + (*line++ - '0');

#if	_WINDOWS
		    hkey = key;
#endif

		    if(handles->using_is_used){
			HANDLE_S *h;

			for(h = handles; h; h = h->next)
			  if(h->is_used)
			    break;
			
			if(h)
			  current_key = h->key;
		    }
		    else
		      current_key = handles->key;

		    if(key == current_key){
			COLOR_PAIR *curcolor = NULL;
			COLOR_PAIR *revcolor = NULL;

			if(handles->color_unseen
			   && (curcolor = pico_get_cur_color())
			   && (colorcmp(curcolor->fg, ps_global->VAR_NORM_FORE_COLOR)
			       || colorcmp(curcolor->bg, ps_global->VAR_NORM_BACK_COLOR))
			   && (revcolor = apply_rev_color(curcolor,
							  ps_global->index_color_style)))
			  (void) pico_set_colorp(revcolor, PSC_NONE);
			else{

			    if(pico_usingcolor() &&
			       ps_global->VAR_SLCTBL_FORE_COLOR &&
			       ps_global->VAR_SLCTBL_BACK_COLOR){
				pico_set_normal_color();
			    }
			    else
			      EndBold();

			    StartInverse();
			    is_inv = 1;
			}

			if(curcolor)
			  free_color_pair(&curcolor);

			if(revcolor)
			  free_color_pair(&revcolor);
		    }
		}
		else{
		    /* BUG: complain? */
		    line += *line + 1;
		}

		break;

	      case TAG_FGCOLOR :
		if(length < RGBLEN){
		    dprint((9,
			       "FGCOLOR not proper length, ignoring\n"));
		    length = 0;
		    break;
		}

		(void)pico_set_fg_color(line);
		is_fg = 1;
		length -= RGBLEN;
		line += RGBLEN;
		break;

	      case TAG_BGCOLOR :
		if(length < RGBLEN){
		    dprint((9,
			       "BGCOLOR not proper length, ignoring\n"));
		    length = 0;
		    break;
		}

		(void)pico_set_bg_color(line);
		is_bg = 1;
		length -= RGBLEN;
		line += RGBLEN;
		break;

	      case TAG_EMBED:			/* literal "embed" char */
		Writechar(TAG_EMBED, 0);
		break;

	      case TAG_STRIKEON :		/* unsupported text markup */
	      case TAG_STRIKEOFF :
	      case TAG_BIGON :
	      case TAG_BIGOFF :
	      case TAG_SMALLON :
	      case TAG_SMALLOFF :
	      default :				/* Eat unrecognized tag - TAG_BIGON, etc */
		break;
	    }					/* tag with handle, skip it */
	}	
	else
	  Writechar(c, 0);
    }


#if	_WINDOWS_X
    if(hkey) {
	char *tmp_file = NULL, ext[32], mtype[128];
	HANDLE_S *h;
	extern HANDLE_S *get_handle (HANDLE_S *, int);

	if((h = get_handle(handles, hkey)) && h->type == Attach){
	    ext[0] = '\0';
	    strncpy(mtype, body_type_names(h->h.attach->body->type), sizeof(mtype));
	    mtype[sizeof(mtype)-1] = '\0';
	    if (h->h.attach->body->subtype) {
		strncat (mtype, "/", sizeof(mtype)-strlen(mtype)-1);
		mtype[sizeof(mtype)-1] = '\0';
		strncat (mtype, h->h.attach->body->subtype, sizeof(mtype)-strlen(mtype)-1);
		mtype[sizeof(mtype)-1] = '\0';
	    }

	    if(!set_mime_extension_by_type(ext, mtype)){
		char *p, *extp = NULL;

		if((p = get_filename_parameter(NULL, 0, h->h.attach->body, &extp)) != NULL){
		    if(extp){
			strncpy(ext, extp, sizeof(ext));
			ext[sizeof(ext)-1] = '\0';
		    }

		    fs_give((void **) &p);
		}
	    }

	    if(ext[0] && (tmp_file = temp_nam_ext(NULL, "im", ext))){
		FILE *f = our_fopen(tmp_file, "w");

		mswin_registericon(x, h->key, tmp_file);

		fclose(f);
		our_unlink(tmp_file);
		fs_give((void **)&tmp_file);
	    }
	}
    }
#endif
    if(is_inv){
	dprint((9,
		   "INVERSE left on at end of line, turning off now\n"));
	EndInverse();
    }
    if(is_bold){
	dprint((9,
		   "BOLD left on at end of line, turning off now\n"));
	EndBold();
    }
    if(is_uline){
	dprint((9,
		   "UNDERLINE left on at end of line, turning off now\n"));
	EndUnderline();
    }
    if(is_fg || is_bg)
      pico_set_normal_color();

}