コード例 #1
0
ファイル: signal.c プロジェクト: ctubio/alpine
/*----------------------------------------------------------------------
     Set or reset what needs to be set when coming out of pico to run
     an alternate editor.

   Args:   come_back -- If come_back is 0 we're going out of our environment
		          to set up for an external editor.
		        If come_back is 1 we're coming back into pine.
  ----------------------------------------------------------------------*/
int
ttyfix(int come_back)
{
#if	defined(DEBUG) && (!defined(DOS) || defined(_WINDOWS))
    if(debugfile)
        fflush(debugfile);
#endif

    if(come_back) {
#ifdef OS2
        enter_text_mode(NULL);
#endif
        init_screen();
        init_tty_driver(ps_global);
        init_keyboard(F_ON(F_USE_FK,ps_global));
#ifdef OS2
        dont_interrupt();
#endif
        fix_windsize(ps_global);
    }
    else {
        EndInverse();
        end_keyboard(F_ON(F_USE_FK,ps_global));
        end_tty_driver(ps_global);
        end_screen(NULL, 0);
#ifdef OS2
        interrupt_ok();
#endif
    }

    return(0);
}
コード例 #2
0
void
init_screen(void)
{
    /*
     * If we want to show it, turn it on. If we don't care, put it back
     * to the way it was originally.
     */
    mswin_showcaret(F_ON(F_SHOW_CURSOR, ps_global));
    mswin_trayicon(F_ON(F_ENABLE_TRAYICON, ps_global));
    return;					/* NO OP */
}
コード例 #3
0
ファイル: termin.unx.c プロジェクト: nysan/alpine
/*----------------------------------------------------------------------
    Actually set up the tty driver                             (UNIX)

   Args: state -- which state to put it in. 1 means go into raw, 0 out of

  Result: returns 0 if successful and < 0 if not.
  ----*/
int
PineRaw(int state)
{
    int result;

    result = Raw(state);
    
    if(result == 0 && state == 1){
	/*
	 * Only go into 8 bit mode if we are doing something other
	 * than plain ASCII. This will save the folks that have
	 * their parity on their serial lines wrong the trouble of
	 * getting it right
	 */
        if((ps_global->keyboard_charmap && ps_global->keyboard_charmap[0] &&
	   strucmp(ps_global->keyboard_charmap, "us-ascii"))
	   || (ps_global->display_charmap && ps_global->display_charmap[0] &&
	       strucmp(ps_global->display_charmap, "us-ascii")))
	  bit_strip_off();

#ifdef	DEBUG
	if(debug < 9)			/* only on if full debugging set */
#endif
	quit_char_off();
	ps_global->low_speed = ttisslow();
	crlf_proc(0);
	xonxoff_proc(F_ON(F_PRESERVE_START_STOP, ps_global));
    }

    return(result);
}
コード例 #4
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();
    }
}
コード例 #5
0
ファイル: termin.unx.c プロジェクト: nysan/alpine
/*----------------------------------------------------------------------
    Initialize the tty driver to do single char I/O and whatever else  (UNIX)

   Args:  struct pine

 Result: tty driver is put in raw mode so characters can be read one
         at a time. Returns -1 if unsuccessful, 0 if successful.

Some file descriptor voodoo to allow for pipes across vforks. See 
open_mailer for details.
  ----------------------------------------------------------------------*/
int
init_tty_driver(struct pine *ps)
{
#ifdef	MOUSE
    if(F_ON(F_ENABLE_MOUSE, ps_global))
      init_mouse();
#endif	/* MOUSE */

    /* turn off talk permission by default */
    
    if(F_ON(F_ALLOW_TALK, ps))
      allow_talk(ps);
    else
      disallow_talk(ps);

    return(PineRaw(1));
}
コード例 #6
0
ファイル: termin.unx.c プロジェクト: nysan/alpine
/*----------------------------------------------------------------------
  Reading input somehow failed and we need to shutdown now

 Args:  none

 Result: pine exits

  ---*/
void
read_bail(void)
{
    dprint((1, "read_bail: cleaning up\n"));

    /* Do not bail out on a tcp timeout, instead close the troublesome stream */
    if(ps_global->tcptimeout && some_stream_is_locked()){
      ps_global->read_bail = 1;
      return;
    }
    end_signals(1);

    /*
     * This gets rid of temporary cache files for remote addrbooks.
     */
    completely_done_with_adrbks();

    /*
     * This flushes out deferred changes and gets rid of temporary cache
     * files for remote config files.
     */
    if(ps_global->prc){
	if(ps_global->prc->outstanding_pinerc_changes)
	  write_pinerc(ps_global, Main, WRP_NOUSER);

	if(ps_global->prc->rd)
	  rd_close_remdata(&ps_global->prc->rd);
	
	free_pinerc_s(&ps_global->prc);
    }

    /* as does this */
    if(ps_global->post_prc){
	if(ps_global->post_prc->outstanding_pinerc_changes)
	  write_pinerc(ps_global, Post, WRP_NOUSER);

	if(ps_global->post_prc->rd)
	  rd_close_remdata(&ps_global->post_prc->rd);
	
	free_pinerc_s(&ps_global->post_prc);
    }

    sp_end();

    dprint((1, "done with read_bail clean up\n"));

    imap_flush_passwd_cache(TRUE);
    end_keyboard(F_ON(F_USE_FK,ps_global));
    end_tty_driver(ps_global);
    if(filter_data_file(0))
      our_unlink(filter_data_file(0));

    exit(0);
}
コード例 #7
0
ファイル: termin.gen.c プロジェクト: RsrchBoy/dpkg-alpine
/*----------------------------------------------------------------------
    Check to see if the given command is reasonably valid
  
  Args:  ch -- the character to check

 Result:  A valid command is returned, or a well know bad command is returned.
 
 ---*/
UCS
validatekeys(UCS ch)
{
    if(F_ON(F_USE_FK,ps_global)){
	if(ch >= 'a' && ch <= 'z')
	  return(KEY_JUNK);
    }
    else{
	if(ch >= PF1 && ch <= PF12)
	  return(KEY_JUNK);
    }

    return(ch);
}
コード例 #8
0
ファイル: signal.c プロジェクト: ctubio/alpine
/*----------------------------------------------------------------------
      Timeout when no user input for a long, long time.
      Treat it pretty much the same as if we got a HUP.
      Only difference is we sometimes turns the timeout off (when composing).
  ----------------------------------------------------------------------*/
void
user_input_timeout_exit(int to_hours)
{
    char msg[80];

    dprint((1,
            "\n\n** Exiting: user input timeout (%d hours) **\n\n\n\n",
            to_hours));
    snprintf(msg, sizeof(msg), _("\n\nAlpine timed out (No user input for %d %s)\n"), to_hours,
             to_hours > 1 ? "hours" : "hour");
    msg[sizeof(msg)-1] = '\0';
    fast_clean_up();
    end_screen(msg, 0);
    end_titlebar();
    end_keymenu();
    end_keyboard(F_ON(F_USE_FK,ps_global));
    end_tty_driver(ps_global);
    end_signals(0);
#if	defined(DEBUG) && (!defined(DOS) || defined(_WINDOWS))
    if(debugfile)
        fclose(debugfile);
#endif
    exit(0);
}
コード例 #9
0
ファイル: newuser.c プロジェクト: sergi/re-alpine
/*
 * Display a new user or new version message.
 */
void
new_user_or_version(struct pine *ps)
{
    char	  **shown_text;
    int		    cmd = MC_NONE;
    int             first_time_alpine_user = 0;
    char	   *error = NULL;
    HelpType	    text;
    SCROLL_S	    sargs;
    STORE_S	   *store;
    HANDLE_S	   *handles = NULL, *htmp;
    gf_io_t	    pc;
    char           *vers = ps->vers_internal;

    first_time_alpine_user = (ps->first_time_user
			      || (ps->pine_pre_vers
				  && isdigit((unsigned char) ps->pine_pre_vers[0])
				  && ps->pine_pre_vers[1] == '.'
				  && isdigit((unsigned char) vers[0])
				  && vers[1] == '.'
				  && ps->pine_pre_vers[0] < '5'	/* it was Pine */
				  && vers[0] >= '5'));		/* Alpine */

    text = ps->first_time_user    ? new_user_greeting :
            first_time_alpine_user ? new_alpine_user_greeting : new_version_greeting;

    shown_text = text;

    /*
     * Set it if the major revision number
     * (the first after the dot) has changed.
     */
    ps->phone_home = (first_time_alpine_user
		      || (ps->pine_pre_vers
			  && isdigit((unsigned char) ps->pine_pre_vers[0])
			  && ps->pine_pre_vers[1] == '.'
			  && isdigit((unsigned char) ps->pine_pre_vers[2])
			  && isdigit((unsigned char) vers[0])
			  && vers[1] == '.'
			  && isdigit((unsigned char) vers[2])
			  && strncmp(ps->pine_pre_vers, vers, 3) < 0));

    /*
     * At this point, shown_text is a charstarstar with html
     * Turn it into a charstar with digested html
     */
    do{
	init_helper_getc(shown_text);
	init_handles(&handles);

	if((store = so_get(CharStar, NULL, EDIT_ACCESS)) != NULL){
	    gf_set_so_writec(&pc, store);
	    gf_filter_init();

	    gf_link_filter(gf_html2plain,
			   gf_html2plain_opt("x-alpine-help:",
					     ps->ttyo->screen_cols, non_messageview_margin(),
					     &handles, NULL, GFHP_LOCAL_HANDLES));

	    error = gf_pipe(helper_getc, pc);

	    gf_clear_so_writec(store);

	    if(!error){
		struct key_menu km;
		struct key	keys[24];

		for(htmp = handles; htmp; htmp = htmp->next)
		  if(htmp->type == URL
		     && htmp->h.url.path
		     && (htmp->h.url.path[0] == 'x'
			 || htmp->h.url.path[0] == '#'))
		    htmp->force_display = 1;

		/* This is mostly here to get the curses variables
		 * for line and column in sync with where the
		 * cursor is on the screen. This gets warped when
		 * the composer is called because it does it's own
		 * stuff
		 */
		ClearScreen();

		memset(&sargs, 0, sizeof(SCROLL_S));
		sargs.text.text	   = so_text(store);
		sargs.text.src	   = CharStar;
		sargs.text.desc	   = "greeting text";
		sargs.text.handles = handles;
		sargs.bar.title	   = "GREETING TEXT";
		sargs.bar.style	   = TextPercent;
		sargs.proc.tool	   = nuov_processor;
		sargs.help.text	   = main_menu_tx;
		sargs.help.title   = "MAIN PINE HELP";
		sargs.resize_exit  = 1;
		sargs.keys.menu	   = &km;
		km		   = nuov_keymenu;
		km.keys		   = keys;
		memcpy(&keys[0], nuov_keymenu.keys,
		       (nuov_keymenu.how_many * 12) * sizeof(struct key));
		setbitmap(sargs.keys.bitmap);

		if(ps->phone_home){
		    km.keys[NUOV_EXIT].label = "Exit this greeting";
		    km.keys[NUOV_EXIT].bind.nch = 1;
		}
		else{
		    km.keys[NUOV_EXIT].label	= "[Exit this greeting]";
		    km.keys[NUOV_EXIT].bind.nch = 3;
		    clrbitn(NUOV_VIEW, sargs.keys.bitmap);
		}

		if(ps->first_time_user)
		  clrbitn(NUOV_RELNOTES, sargs.keys.bitmap);

		cmd = scrolltool(&sargs);

		flush_input();

		if(F_ON(F_BLANK_KEYMENU,ps_global))
		  FOOTER_ROWS(ps_global) = 1;

		ClearScreen();
	    }

	    so_give(&store);
	}

	free_handles(&handles);
    }
    while(cmd == MC_RESIZE);
}
コード例 #10
0
ファイル: text.c プロジェクト: mavit/alpine
/*----------------------------------------------------------------------
   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);
}
コード例 #11
0
ファイル: editorial.c プロジェクト: carriercomm/alpine-1
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));
}
コード例 #12
0
ファイル: init.c プロジェクト: RsrchBoy/dpkg-alpine
/*----------------------------------------------------------------------
     Offer to delete old sent-mail folders

  Args: sml -- The list of sent-mail folders
 
  ----*/
int
prune_folders(CONTEXT_S *prune_cntxt, char *folder_base, int cur_month,
	      char *type, unsigned int pr)
{
    char         path2[MAXPATH+1],  prompt[128], tmp[21];
    int          month_to_use, exists;
    struct sm_folder *mail_list, *sm;

    mail_list = get_mail_list(prune_cntxt, folder_base);
    free_folder_list(prune_cntxt);

#ifdef	DEBUG
    for(sm = mail_list; sm != NULL && sm->name != NULL; sm++)
      dprint((5,"Old sent-mail: %5d  %s\n", sm->month_num,
	     sm->name[0] ? sm->name : "?"));
#endif

    for(sm = mail_list; sm != NULL && sm->name != NULL; sm++)
      if(sm->month_num == cur_month - 1)
        break;  /* matched a month */
 
    month_to_use = (sm == NULL || sm->name == NULL) ? cur_month - 1 : 0;

    dprint((5, "Month_to_use : %d\n", month_to_use));

    if(month_to_use == 0 || pr == PRUNE_NO_AND_ASK || pr == PRUNE_NO_AND_NO)
      goto delete_old;

    strncpy(path2, folder_base, sizeof(path2)-1);
    path2[sizeof(path2)-1] = '\0';

    if(F_ON(F_PRUNE_USES_ISO,ps_global)){             /* sent-mail-yyyy-mm */
	snprintf(path2 + strlen(path2), sizeof(path2)-strlen(path2), "-%4.4d-%2.2d", month_to_use/12,
		month_to_use % 12 + 1);
    }
    else{
	strncpy(tmp, month_abbrev((month_to_use % 12)+1), 20);
	tmp[sizeof(tmp)-1] = '\0';
	lcase((unsigned char *) tmp);
#ifdef	DOS
	if(*prune_cntxt->context != '{'){
	  int i;

	  i = strlen(path2);
	  snprintf(path2 + (size_t)((i > 4) ? 4 : i),
	           sizeof(path2)- ((i > 4) ? 4 : i),
		  "%2.2d%2.2d", (month_to_use % 12) + 1,
		  ((month_to_use / 12) - 1900) % 100);
	}
	else
#endif
	snprintf(path2 + strlen(path2), sizeof(path2)-strlen(path2), "-%.20s-%d", tmp, month_to_use/12);
    }

    Writechar(BELL, 0);
    snprintf(prompt, sizeof(prompt), "Move current \"%.50s\" to \"%.50s\"", folder_base, path2);
    if((exists = folder_exists(prune_cntxt, folder_base)) == FEX_ERROR){
        dprint((5, "prune_folders: Error testing existence\n"));
        return(0);
    }
    else if(exists == FEX_NOENT){	/* doesn't exist */
        dprint((5, "prune_folders: nothing to prune <%s %s>\n",
		   prune_cntxt->context ? prune_cntxt->context : "?",
		   folder_base ? folder_base : "?"));
        goto delete_old;
    }
    else if(!(exists & FEX_ISFILE)
	    || pr == PRUNE_NO_AND_ASK || pr == PRUNE_NO_AND_NO
	    || ((pr == PRUNE_ASK_AND_ASK || pr == PRUNE_ASK_AND_NO) &&
	        want_to(prompt, 'n', 0, h_wt_expire, WT_FLUSH_IN) == 'n')){
	dprint((5, "User declines renaming %s\n",
	       ps_global->VAR_DEFAULT_FCC ? ps_global->VAR_DEFAULT_FCC : "?"));
	goto delete_old;
    }

    prune_move_folder(folder_base, path2, prune_cntxt);

  delete_old:
    if(pr == PRUNE_ASK_AND_ASK || pr == PRUNE_YES_AND_ASK
       || pr == PRUNE_NO_AND_ASK)
      delete_old_mail(mail_list, prune_cntxt, type);

    if((sm = mail_list) != NULL){
	while(sm->name){
	    fs_give((void **)&(sm->name));
	    sm++;
	}

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

    return(1);
}
コード例 #13
0
ファイル: mailcap.c プロジェクト: carriercomm/alpine-1
/*
 * Returns the mailcap entry for type/subtype from the successfull
 * mailcap entry, or NULL if none.  Command string still contains % stuff.
 */
MailcapEntry *
mc_get_command(int type, char *subtype, BODY *body,
	       int check_extension, int *sp_handlingp)
{
    MailcapEntry *mc;
    char	  tmp_subtype[256], tmp_ext[16], *ext = NULL;

    dprint((5, "- mc_get_command(%s/%s) -\n",
	       body_type_names(type),
	       subtype ? subtype : "?"));

    if(type == TYPETEXT
       && (!subtype || !strucmp(subtype, "plain"))
       && F_ON(F_SHOW_TEXTPLAIN_INT, ps_global))
      return(NULL);

    mc_init();

    if(check_extension){
	char     *fname;
	MT_MAP_T  e2b;

	/*
	 * Special handling for when we're looking at what's likely
	 * binary application data. Look for a file name extension
	 * that we might use to hook a helper app to.
	 *
	 * NOTE: This used to preclude an "app/o-s" mailcap entry
	 *       since this took precedence.  Now that there are
	 *       typically two scans through the check_extension
	 *       mechanism, the mailcap entry now takes precedence.
	 */
	if((fname = get_filename_parameter(NULL, 0, body, &e2b.from.ext)) != NULL
	   && e2b.from.ext && e2b.from.ext[0]){
	    if(strlen(e2b.from.ext) < sizeof(tmp_ext) - 2){
		strncpy(ext = tmp_ext, e2b.from.ext - 1, sizeof(tmp_ext)); /* remember it */
		tmp_ext[sizeof(tmp_ext)-1] = '\0';
		if(mt_srch_mime_type(mt_srch_by_ext, &e2b)){
		    type = e2b.to.mime.type;		/* mapped type */
		    strncpy(subtype = tmp_subtype, e2b.to.mime.subtype,
			    sizeof(tmp_subtype)-1);
		    tmp_subtype[sizeof(tmp_subtype)-1] = '\0';
		    fs_give((void **) &e2b.to.mime.subtype);
		    body = NULL;		/* the params no longer apply */
		}
	    }

	    fs_give((void **) &fname);
	}
	else{
	    if(fname)
	      fs_give((void **) &fname);

	    return(NULL);
	}
    }

    for(mc = MailcapData.head; mc; mc = mc->next)
      if(mc_ctype_match(type, subtype, mc->contenttype)
	 && mc_passes_test(mc, type, subtype, body)){
	  dprint((9, 
		     "mc_get_command: type=%s/%s, command=%s\n", 
		     body_type_names(type),
		     subtype ? subtype : "?",
		     mc->command ? mc->command : "?"));
	  return(mc);
      }

    if(mime_os_specific_access()){
	static MailcapEntry  fake_mc;
	static char	     fake_cmd[1024];
	char		     tmp_mime_type[256];

	memset(&fake_mc, 0, sizeof(MailcapEntry));
	fake_cmd[0] = '\0';
	fake_mc.command = fake_cmd;

	snprintf(tmp_mime_type, sizeof(tmp_mime_type), "%s/%s", body_types[type], subtype);
	if(mime_get_os_mimetype_command(tmp_mime_type, ext, fake_cmd,
					sizeof(fake_cmd), check_extension, sp_handlingp))
	  return(&fake_mc);
    }

    return(NULL);
}
コード例 #14
0
ファイル: setup.c プロジェクト: RsrchBoy/dpkg-alpine
/*----------------------------------------------------------------------
    Present pinerc data for manipulation

    Args: None

  Result: help edit certain pinerc fields.
  ---*/
void
option_screen(struct pine *ps, int edit_exceptions)
{
    char	    tmp[MAXPATH+1], *pval, **lval;
    int		    i, j, ln = 0, readonly_warning = 0;
    struct	    variable  *vtmp;
    CONF_S	   *ctmpa = NULL, *ctmpb, *first_line = NULL;
    FEATURE_S	   *feature;
    PINERC_S       *prc = NULL;
    SAVED_CONFIG_S *vsave;
    OPT_SCREEN_S    screen;
    int             expose_hidden_config, add_hidden_vars_title = 0;

    dprint((3, "-- option_screen --\n"));

    expose_hidden_config = F_ON(F_EXPOSE_HIDDEN_CONFIG, ps_global);
    treat_color_vars_as_text = expose_hidden_config;

    ew = edit_exceptions ? ps_global->ew_for_except_vars : Main;

    if(ps->restricted)
      readonly_warning = 1;
    else{
	switch(ew){
	  case Main:
	    prc = ps->prc;
	    break;
	  case Post:
	    prc = ps->post_prc;
	    break;
	  default:
	    break;
	}

	readonly_warning = prc ? prc->readonly : 1;
	if(prc && prc->quit_to_edit){
	    quit_to_edit_msg(prc);
	    treat_color_vars_as_text = 0;
	    return;
	}
    }

    ps->next_screen = SCREEN_FUN_NULL;

    mailcap_free(); /* free resources we won't be using for a while */

    if(ps->fix_fixed_warning)
      offer_to_fix_pinerc(ps);

    /*
     * First, find longest variable name
     */
    for(vtmp = ps->vars; vtmp->name; vtmp++){
	if(exclude_config_var(ps, vtmp, expose_hidden_config))
	  continue;

	if((i = utf8_width(pretty_var_name(vtmp->name))) > ln)
	  ln = i;
    }

    dprint((9, "initialize config list\n"));

    /*
     * Next, allocate and initialize config line list...
     */
    for(vtmp = ps->vars; vtmp->name; vtmp++){
	/*
	 * INCOMING_FOLDERS is currently the first of the normally
	 * hidden variables. Should probably invent a more robust way
	 * to keep this up to date.
	 */
	if(expose_hidden_config && vtmp == &ps->vars[V_INCOMING_FOLDERS])
	  add_hidden_vars_title = 1;

	if(exclude_config_var(ps, vtmp, expose_hidden_config))
	  continue;

	if(add_hidden_vars_title){

	    add_hidden_vars_title = 0;

	    new_confline(&ctmpa);		/* Blank line */
	    ctmpa->flags	       |= CF_NOSELECT | CF_B_LINE;

	    new_confline(&ctmpa)->var	= NULL;
	    ctmpa->help			= NO_HELP;
	    ctmpa->valoffset		= 2;
	    ctmpa->flags	       |= CF_NOSELECT;
	    ctmpa->value = cpystr("--- [ Normally hidden configuration options ] ---");

	    new_confline(&ctmpa);		/* Blank line */
	    ctmpa->flags	       |= CF_NOSELECT | CF_B_LINE;
	}

	if(vtmp->is_list)
	  lval  = LVAL(vtmp, ew);
	else
	  pval  = PVAL(vtmp, ew);

	new_confline(&ctmpa)->var = vtmp;
	if(!first_line)
	  first_line = ctmpa;

	ctmpa->valoffset = ln + 3;
	if(vtmp->is_list)
	  ctmpa->keymenu	 = &config_text_wshuf_keymenu;
	else
	  ctmpa->keymenu	 = &config_text_keymenu;
	  
	ctmpa->help	 = config_help(vtmp - ps->vars, 0);
	ctmpa->tool	 = text_tool;

	utf8_snprintf(tmp, sizeof(tmp), "%-*.100w =", ln, pretty_var_name(vtmp->name));
	tmp[sizeof(tmp)-1] = '\0';
	ctmpa->varname  = cpystr(tmp);
	ctmpa->varnamep = ctmpb = ctmpa;
	ctmpa->flags   |= CF_STARTITEM;
	if(vtmp == &ps->vars[V_FEATURE_LIST]){	/* special checkbox case */
	    char *this_sect, *new_sect;

	    ctmpa->flags		 |= CF_NOSELECT;
	    ctmpa->keymenu		  = &config_checkbox_keymenu;
	    ctmpa->tool			  = NULL;

	    /* put a nice delimiter before list */
	    new_confline(&ctmpa)->var = NULL;
	    ctmpa->varnamep		  = ctmpb;
	    ctmpa->keymenu		  = &config_checkbox_keymenu;
	    ctmpa->help			  = NO_HELP;
	    ctmpa->tool			  = checkbox_tool;
	    ctmpa->valoffset		  = feature_indent();
	    ctmpa->flags		 |= CF_NOSELECT;
	    ctmpa->value = cpystr("Set    Feature Name");

	    new_confline(&ctmpa)->var = NULL;
	    ctmpa->varnamep		  = ctmpb;
	    ctmpa->keymenu		  = &config_checkbox_keymenu;
	    ctmpa->help			  = NO_HELP;
	    ctmpa->tool			  = checkbox_tool;
	    ctmpa->valoffset		  = feature_indent();
	    ctmpa->flags		 |= CF_NOSELECT;
	    ctmpa->value = cpystr("---  ----------------------");

	    for(i = 0, this_sect = NULL; (feature = feature_list(i)); i++)
	      if((new_sect = feature_list_section(feature)) &&
		 (strcmp(new_sect, HIDDEN_PREF) != 0)){
		  if(this_sect != new_sect){
		      new_confline(&ctmpa)->var = NULL;
		      ctmpa->varnamep		= ctmpb;
		      ctmpa->keymenu		= &config_checkbox_keymenu;
		      ctmpa->help		= NO_HELP;
		      ctmpa->tool		= checkbox_tool;
		      ctmpa->valoffset		= 2;
		      ctmpa->flags	       |= (CF_NOSELECT | CF_STARTITEM);
		      snprintf(tmp, sizeof(tmp), "[ %s ]", this_sect = new_sect);
		      tmp[sizeof(tmp)-1] = '\0';
		      ctmpa->value = cpystr(tmp);
		  }

		  new_confline(&ctmpa)->var = vtmp;
		  ctmpa->varnamep	    = ctmpb;
		  ctmpa->keymenu	    = &config_checkbox_keymenu;
		  ctmpa->help		    = config_help(vtmp-ps->vars,
							  feature->id);
		  ctmpa->tool		    = checkbox_tool;
		  ctmpa->valoffset	    = feature_indent();
		  ctmpa->varmem		    = i;
		  ctmpa->value		    = pretty_value(ps, ctmpa);
	      }
	}
	else if(standard_radio_var(ps, vtmp)){
	    standard_radio_setup(ps, &ctmpa, vtmp, NULL);
	}
	else if(vtmp == &ps->vars[V_SORT_KEY]){ /* radio case */
	    SortOrder def_sort;
	    int       def_sort_rev;

	    ctmpa->flags       |= CF_NOSELECT;
	    ctmpa->keymenu      = &config_radiobutton_keymenu;
	    ctmpa->tool		= NULL;

	    /* put a nice delimiter before list */
	    new_confline(&ctmpa)->var = NULL;
	    ctmpa->varnamep		  = ctmpb;
	    ctmpa->keymenu		  = &config_radiobutton_keymenu;
	    ctmpa->help			  = NO_HELP;
	    ctmpa->tool			  = radiobutton_tool;
	    ctmpa->valoffset		  = 12;
	    ctmpa->flags		 |= CF_NOSELECT;
	    ctmpa->value = cpystr("Set    Sort Options");

	    new_confline(&ctmpa)->var = NULL;
	    ctmpa->varnamep	      = ctmpb;
	    ctmpa->keymenu	      = &config_radiobutton_keymenu;
	    ctmpa->help		      = NO_HELP;
	    ctmpa->tool		      = radiobutton_tool;
	    ctmpa->valoffset	      = 12;
	    ctmpa->flags             |= CF_NOSELECT;
	    ctmpa->value = cpystr("---  ----------------------");

	    decode_sort(pval, &def_sort, &def_sort_rev);

	    for(j = 0; j < 2; j++){
		for(i = 0; ps->sort_types[i] != EndofList; i++){
		    new_confline(&ctmpa)->var = vtmp;
		    ctmpa->varnamep	      = ctmpb;
		    ctmpa->keymenu	      = &config_radiobutton_keymenu;
		    ctmpa->help		      = config_help(vtmp - ps->vars, 0);
		    ctmpa->tool		      = radiobutton_tool;
		    ctmpa->valoffset	      = 12;
		    ctmpa->varmem	      = i + (j * EndofList);
		    ctmpa->value	      = pretty_value(ps, ctmpa);
		}
	    }
	}
	else if(vtmp == &ps->vars[V_USE_ONLY_DOMAIN_NAME]){ /* yesno case */
	    ctmpa->keymenu = &config_yesno_keymenu;
	    ctmpa->tool	   = yesno_tool;
	    ctmpa->value   = pretty_value(ps, ctmpa);
	}
	else if(vtmp == &ps->vars[V_LITERAL_SIG]){
	    ctmpa->tool    = litsig_text_tool;
	    ctmpa->value   = pretty_value(ps, ctmpa);
	}
	else if(vtmp == &ps->vars[V_INBOX_PATH]){
	    ctmpa->tool    = inbox_path_text_tool;
	    ctmpa->value   = pretty_value(ps, ctmpa);
	}
	else if(vtmp == &ps->vars[V_POST_CHAR_SET]
#ifndef _WINDOWS
		|| vtmp == &ps->vars[V_CHAR_SET]
	        || vtmp == &ps->vars[V_KEY_CHAR_SET]
#endif /* !_WINDOWS */
		|| vtmp == &ps->vars[V_UNK_CHAR_SET]){
	    ctmpa->keymenu = &config_text_to_charsets_keymenu;
	    ctmpa->tool    = to_charsets_text_tool;
	    ctmpa->value   = pretty_value(ps, ctmpa);
	}
	else if(vtmp->is_list){
	    int (*t_tool)(struct pine *, int, CONF_S **, unsigned);
	    struct key_menu *km;

	    t_tool = NULL;
	    km = NULL;
	    if(vtmp == &ps->vars[V_INCCHECKLIST]){
		t_tool = incoming_monitoring_list_tool;
		km     = &config_text_keymenu;
	    }
	    else if(vtmp == &ps->vars[V_PERMLOCKED]){
		t_tool = stayopen_list_tool;
		km     = &config_text_wshufandfldr_keymenu;
	    }

	    if(lval){
		for(i = 0; lval[i]; i++){
		    if(i)
		      (void)new_confline(&ctmpa);

		    ctmpa->var       = vtmp;
		    ctmpa->varmem    = i;
		    ctmpa->valoffset = ln + 3;
		    ctmpa->value     = pretty_value(ps, ctmpa);
		    ctmpa->keymenu   = km ? km : &config_text_wshuf_keymenu;
		    ctmpa->help      = config_help(vtmp - ps->vars, 0);
		    ctmpa->tool      = t_tool ? t_tool : text_tool;
		    ctmpa->varnamep  = ctmpb;
		}
	    }
	    else{
		ctmpa->varmem = 0;
		ctmpa->value  = pretty_value(ps, ctmpa);
		ctmpa->tool   = t_tool ? t_tool : text_tool;
		ctmpa->keymenu = km ? km : &config_text_wshuf_keymenu;
	    }
	}
	else{
	    if(vtmp == &ps->vars[V_FILLCOL]
	       || vtmp == &ps->vars[V_SLEEP]
	       || vtmp == &ps->vars[V_QUOTE_SUPPRESSION]
	       || vtmp == &ps->vars[V_OVERLAP]
	       || vtmp == &ps->vars[V_MAXREMSTREAM]
	       || vtmp == &ps->vars[V_MARGIN]
	       || vtmp == &ps->vars[V_DEADLETS]
	       || vtmp == &ps->vars[V_NMW_WIDTH]
	       || vtmp == &ps->vars[V_STATUS_MSG_DELAY]
	       || vtmp == &ps->vars[V_ACTIVE_MSG_INTERVAL]
	       || vtmp == &ps->vars[V_MAILCHECK]
	       || vtmp == &ps->vars[V_MAILCHECKNONCURR]
	       || vtmp == &ps->vars[V_MAILDROPCHECK]
	       || vtmp == &ps->vars[V_NNTPRANGE]
	       || vtmp == &ps->vars[V_TCPOPENTIMEO]
	       || vtmp == &ps->vars[V_TCPREADWARNTIMEO]
	       || vtmp == &ps->vars[V_TCPWRITEWARNTIMEO]
	       || vtmp == &ps->vars[V_TCPQUERYTIMEO]
	       || vtmp == &ps->vars[V_RSHOPENTIMEO]
	       || vtmp == &ps->vars[V_SSHOPENTIMEO]
	       || vtmp == &ps->vars[V_INCCHECKTIMEO]
	       || vtmp == &ps->vars[V_INCCHECKINTERVAL]
	       || vtmp == &ps->vars[V_INC2NDCHECKINTERVAL]
	       || vtmp == &ps->vars[V_USERINPUTTIMEO]
	       || vtmp == &ps->vars[V_REMOTE_ABOOK_VALIDITY]
	       || vtmp == &ps->vars[V_REMOTE_ABOOK_HISTORY])
	      ctmpa->flags |= CF_NUMBER;

	    ctmpa->value = pretty_value(ps, ctmpa);
	}
    }

    dprint((9, "add hidden features\n"));

    /* add the hidden features */
    if(expose_hidden_config){
	char *new_sect;

	new_confline(&ctmpa);		/* Blank line */
	ctmpa->flags	       |= CF_NOSELECT | CF_B_LINE;

	new_confline(&ctmpa)->var	= NULL;
	ctmpa->help			= NO_HELP;
	ctmpa->valoffset		= 2;
	ctmpa->flags	       |= CF_NOSELECT;
	ctmpa->value = cpystr("--- [ Normally hidden configuration features ] ---");

	new_confline(&ctmpa);		/* Blank line */
	ctmpa->flags	       |= CF_NOSELECT | CF_B_LINE;

	vtmp = &ps->vars[V_FEATURE_LIST];

	ctmpa->flags		 |= CF_NOSELECT;
	ctmpa->keymenu		  = &config_checkbox_keymenu;
	ctmpa->tool			  = NULL;

	/* put a nice delimiter before list */
	new_confline(&ctmpa)->var = NULL;
	ctmpa->varnamep		  = ctmpb;
	ctmpa->keymenu		  = &config_checkbox_keymenu;
	ctmpa->help			  = NO_HELP;
	ctmpa->tool			  = checkbox_tool;
	ctmpa->valoffset		  = feature_indent();
	ctmpa->flags		 |= CF_NOSELECT;
	ctmpa->value = cpystr("Set    Feature Name");

	new_confline(&ctmpa)->var = NULL;
	ctmpa->varnamep		  = ctmpb;
	ctmpa->keymenu		  = &config_checkbox_keymenu;
	ctmpa->help			  = NO_HELP;
	ctmpa->tool			  = checkbox_tool;
	ctmpa->valoffset		  = feature_indent();
	ctmpa->flags		 |= CF_NOSELECT;
	ctmpa->value = cpystr("---  ----------------------");

	for(i = 0; (feature = feature_list(i)); i++)
	  if((new_sect = feature_list_section(feature)) &&
	     (strcmp(new_sect, HIDDEN_PREF) == 0)){

	      new_confline(&ctmpa)->var	= vtmp;
	      ctmpa->varnamep		= ctmpb;
	      ctmpa->keymenu		= &config_checkbox_keymenu;
	      ctmpa->help		= config_help(vtmp-ps->vars,
						      feature->id);
	      ctmpa->tool		= checkbox_tool;
	      ctmpa->valoffset		= feature_indent();
	      ctmpa->varmem		= i;
	      ctmpa->value		= pretty_value(ps, ctmpa);
	  }
    }

    vsave = save_config_vars(ps, expose_hidden_config);
    first_line = first_sel_confline(first_line);

    memset(&screen, 0, sizeof(screen));
    screen.ro_warning = readonly_warning;
    /* TRANSLATORS: Print something1 using something2.
       "configuration" is something1 */
    switch(conf_scroll_screen(ps, &screen, first_line,
			      edit_exceptions ? CONFIG_SCREEN_TITLE_EXC
					      : CONFIG_SCREEN_TITLE,
			      _("configuration"), 0)){
      case 0:
	break;

      case 1:
	write_pinerc(ps, ew, WRP_NONE);
	break;
    
      case 10:
	revert_to_saved_config(ps, vsave, expose_hidden_config);
	if(prc)
	  prc->outstanding_pinerc_changes = 0;

	break;
      
      default:
	q_status_message(SM_ORDER,7,10,
	    "conf_scroll_screen bad ret, not supposed to happen");
	break;
    }

    pval = PVAL(&ps->vars[V_SORT_KEY], ew);
    if(vsave[V_SORT_KEY].saved_user_val.p && pval
       && strcmp(vsave[V_SORT_KEY].saved_user_val.p, pval)){
	if(!mn_get_mansort(ps_global->msgmap)){
	    clear_index_cache(ps_global->mail_stream, 0);
	    reset_sort_order(SRT_VRB);
	}
    }

    treat_color_vars_as_text = 0;
    free_saved_config(ps, &vsave, expose_hidden_config);
#ifdef _WINDOWS
    mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
#endif
}
コード例 #15
0
ファイル: print.c プロジェクト: nysan/alpine
/*----------------------------------------------------------------------
       Open the printer

  Args: desc -- Description of item to print. Should have one trailing blank.

  Return value: < 0 is a failure.
		0 a success.

This does most of the work of popen so we can save the standard output of the
command we execute and send it back to the user.
  ----*/
int
open_printer(char *desc)
{
#ifndef _WINDOWS
    char command[201], prompt[200];
    int  cmd, rc, just_one;
    char *p, *init, *nick;
    char aname[100], wname[100];
    char *printer;
    int	 done = 0, i, lastprinter, cur_printer = 0;
    HelpType help;
    char   **list;
    static ESCKEY_S ekey[] = {
	/* TRANSLATORS: these are command labels for printing screen */
	{'y', 'y', "Y", N_("Yes")},
	{'n', 'n', "N", N_("No")},
	/* TRANSLATORS: go to Previous Printer in list */
	{ctrl('P'), 10, "^P", N_("Prev Printer")},
	{ctrl('N'), 11, "^N", N_("Next Printer")},
	{-2,   0,   NULL, NULL},
	/* TRANSLATORS: use Custom Print command */
	{'c', 'c', "C", N_("CustomPrint")},
	{KEY_UP,    10, "", ""},
	{KEY_DOWN,  11, "", ""},
	{-1, 0, NULL, NULL}};
#define PREV_KEY   2
#define NEXT_KEY   3
#define CUSTOM_KEY 5
#define UP_KEY     6
#define DOWN_KEY   7

    trailer      = NULL;
    init         = NULL;
    nick         = NULL;
    command[sizeof(command)-1] = '\0';

    if(ps_global->VAR_PRINTER == NULL){
        q_status_message(SM_ORDER | SM_DING, 3, 5,
	"No printer has been chosen.  Use SETUP on main menu to make choice.");
	return(-1);
    }

    /* Is there just one print command available? */
    just_one = (ps_global->printer_category!=3&&ps_global->printer_category!=2)
	       || (ps_global->printer_category == 2
		   && !(ps_global->VAR_STANDARD_PRINTER
			&& ps_global->VAR_STANDARD_PRINTER[0]
			&& ps_global->VAR_STANDARD_PRINTER[1]))
	       || (ps_global->printer_category == 3
		   && !(ps_global->VAR_PERSONAL_PRINT_COMMAND
			&& ps_global->VAR_PERSONAL_PRINT_COMMAND[0]
			&& ps_global->VAR_PERSONAL_PRINT_COMMAND[1]));

    if(F_ON(F_CUSTOM_PRINT, ps_global))
      ekey[CUSTOM_KEY].ch = 'c'; /* turn this key on */
    else
      ekey[CUSTOM_KEY].ch = -2;  /* turn this key off */

    if(just_one){
	ekey[PREV_KEY].ch = -2;  /* turn these keys off */
	ekey[NEXT_KEY].ch = -2;
	ekey[UP_KEY].ch   = -2;
	ekey[DOWN_KEY].ch = -2;
    }
    else{
	ekey[PREV_KEY].ch = ctrl('P'); /* turn these keys on */
	ekey[NEXT_KEY].ch = ctrl('N');
	ekey[UP_KEY].ch   = KEY_UP;
	ekey[DOWN_KEY].ch = KEY_DOWN;
	/*
	 * count how many printers in list and find the default in the list
	 */
	if(ps_global->printer_category == 2)
	  list = ps_global->VAR_STANDARD_PRINTER;
	else
	  list = ps_global->VAR_PERSONAL_PRINT_COMMAND;

	for(i = 0; list[i]; i++)
	  if(strcmp(ps_global->VAR_PRINTER, list[i]) == 0)
	    cur_printer = i;
	
	lastprinter = i - 1;
    }

    help = NO_HELP;
    ps_global->mangled_footer = 1;

    while(!done){
	if(init)
	  fs_give((void **)&init);

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

	if(just_one)
	  printer = ps_global->VAR_PRINTER;
	else
	  printer = list[cur_printer];

	parse_printer(printer, &nick, &p, &init, &trailer, NULL, NULL);
	strncpy(command, p, sizeof(command)-1);
	command[sizeof(command)-1] = '\0';
	fs_give((void **)&p);
	/* TRANSLATORS: Print something1 using something2.
	   For example, Print configuration using printer three. */
	snprintf(prompt, sizeof(prompt), _("Print %s using \"%s\" ? "),
		desc ? desc : "",
		*nick ? nick : command);
	prompt[sizeof(prompt)-1] = '\0';

	fs_give((void **)&nick);
	
	cmd = radio_buttons(prompt, -FOOTER_ROWS(ps_global),
				 ekey, 'y', 'x', help, RB_NORM);
	
	switch(cmd){
	  case 'y':
	    q_status_message1(SM_ORDER, 0, 9,
		"Printing with command \"%s\"", command);
	    done++;
	    break;

	  case 10:
	    cur_printer = (cur_printer>0)
				? (cur_printer-1)
				: lastprinter;
	    break;

	  case 11:
	    cur_printer = (cur_printer<lastprinter)
				? (cur_printer+1)
				: 0;
	    break;

	  case 'n':
	  case 'x':
	    done++;
	    break;

	  case 'c':
	    done++;
	    break;

	  default:
	    break;
	}
    }

    if(cmd == 'c'){
	if(init)
	  fs_give((void **)&init);

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

	snprintf(prompt, sizeof(prompt), "Enter custom command : ");
	prompt[sizeof(prompt)-1] = '\0';
	command[0] = '\0';
	rc = 1;
	help = NO_HELP;
	while(rc){
	    int flags = OE_APPEND_CURRENT;

	    rc = optionally_enter(command, -FOOTER_ROWS(ps_global), 0,
		sizeof(command), prompt, NULL, help, &flags);
	    
	    if(rc == 1){
		cmd = 'x';
		rc = 0;
	    }
	    else if(rc == 3)
	      help = (help == NO_HELP) ? h_custom_print : NO_HELP;
	    else if(rc == 0){
		removing_trailing_white_space(command);
		removing_leading_white_space(command);
		q_status_message1(SM_ORDER, 0, 9,
		    "Printing with command \"%s\"", command);
	    }
	}
    }

    if(cmd == 'x' || cmd == 'n'){
	q_status_message(SM_ORDER, 0, 2, "Print cancelled");
	if(init)
	  fs_give((void **)&init);

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

	return(-1);
    }

    display_message('x');

    ps_global->print = (PRINT_S *)fs_get(sizeof(PRINT_S));
    memset(ps_global->print, 0, sizeof(PRINT_S));

    strncpy(aname, ANSI_PRINTER, sizeof(aname)-1);
    aname[sizeof(aname)-1] = '\0';
    strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
    strncpy(wname, WYSE_PRINTER, sizeof(wname)-1);
    wname[sizeof(wname)-1] = '\0';
    strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
    if(strucmp(command, ANSI_PRINTER) == 0
       || strucmp(command, aname) == 0
       || strucmp(command, WYSE_PRINTER) == 0
       || strucmp(command, wname) == 0){
        /*----------- Attached printer ---------*/
        q_status_message(SM_ORDER, 0, 9,
	    "Printing to attached desktop printer...");
        display_message('x');
	xonxoff_proc(1);			/* make sure XON/XOFF used */
	crlf_proc(1);				/* AND LF->CR xlation */
	if(strucmp(command, ANSI_PRINTER) == 0
	   || strucmp(command, aname) == 0){
	    fputs("\033[5i", stdout);
	    ansi_off = 1;
	}
	else{
	    ansi_off = 0;
	    printf("%c", 18); /* aux on for wyse60,
			         Chuck Everett <*****@*****.**> */
	}

        ps_global->print->fp = stdout;
        if(strucmp(command, ANSI_PRINTER) == 0
	   || strucmp(command, WYSE_PRINTER) == 0){
	    /* put formfeed at the end of the trailer string */
	    if(trailer){
		int len = strlen(trailer);

		fs_resize((void **)&trailer, len+2);
		trailer[len] = '\f';
		trailer[len+1] = '\0';
	    }
	    else
	      trailer = cpystr("\f");
	}
    }
    else{
        /*----------- Print by forking off a UNIX command ------------*/
        dprint((4, "Printing using command \"%s\"\n",
	       command ? command : "?"));
	ps_global->print->result = temp_nam(NULL, "pine_prt");
	if(ps_global->print->result &&
	   (ps_global->print->pipe = open_system_pipe(command,
						      &ps_global->print->result, NULL,
						      PIPE_WRITE | PIPE_STDERR, 0,
						      pipe_callback, NULL))){
	    ps_global->print->fp = ps_global->print->pipe->out.f;
	}
	else{
	    if(ps_global->print->result){
		our_unlink(ps_global->print->result);
		fs_give((void **)&ps_global->print->result);
	    }

            q_status_message1(SM_ORDER | SM_DING, 3, 4,
			      "Error opening printer: %s",
                              error_description(errno));
            dprint((2, "Error popening printer \"%s\"\n",
                      error_description(errno)));
	    if(init)
	      fs_give((void **)&init);

	    if(trailer)
	      fs_give((void **)&trailer);
	    
	    return(-1);
        }
    }

    ps_global->print->err = 0;
    if(init){
	if(*init)
	  fputs(init, ps_global->print->fp);

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

    cb.cbuf[0] = '\0';
    cb.cbufp   = cb.cbuf;
    cb.cbufend = cb.cbuf;
#else /* _WINDOWS */
    int status;
    LPTSTR desclpt = NULL;

    if(desc)
      desclpt = utf8_to_lptstr(desc);

    if (status = mswin_print_ready (0, desclpt)) {
        q_status_message1(SM_ORDER | SM_DING, 3, 4,
			  "Error starting print job: %s",
			  mswin_print_error(status));
	if(desclpt)
	  fs_give((void **) &desclpt);

        return(-1);
    }

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

    q_status_message(SM_ORDER, 0, 9, "Printing to windows printer...");
    display_message('x');

    /* init print control structure */
    ps_global->print = (PRINT_S *)fs_get(sizeof(PRINT_S));
    memset(ps_global->print, 0, sizeof(PRINT_S));

    ps_global->print->err = 0;
#endif /* _WINDOWS */

    return(0);
}
コード例 #16
0
ファイル: newmail.c プロジェクト: carriercomm/alpine
/*----------------------------------------------------------------------
     new_mail() - check for new mail in the inbox
 
  Input:  force       -- flag indicating we should check for new mail no matter
          time_for_check_point -- 0: GoodTime, 1: BadTime, 2: VeryBadTime
	  flags -- whether to q a new mail status message or defer the sort

  Result: returns -1 if there was no new mail. Otherwise returns the
          sorted message number of the smallest message number that
          was changed. That is the screen needs to be repainted from
          that message down.

  Limit frequency of checks because checks use some resources. That is
  they generate an IMAP packet or require locking the local mailbox.
  (Acutally the lock isn't required, a stat will do, but the current
   c-client mail code locks before it stats.)

  Returns >= 0 only if there is a change in the given mail stream. Otherwise
  this returns -1.  On return the message counts in the pine
  structure are updated to reflect the current number of messages including
  any new mail and any expunging.
 
 --- */
long
new_mail(int force_arg, CheckPointTime time_for_check_point, int flags)
{
    static time_t last_check_point_call = 0;
    long          since_last_input;
    time_t        expunged_reaper_to, adj_idle_timeout, interval, adj;
    static int    nexttime = 0;
    time_t        now;
    long          n, rv = 0, t_nm_count = 0, exp_count;
    MAILSTREAM   *m;
    int           force, i, started_on;
    int           new_mail_was_announced = 0;
    int           have_pinged_non_special = 0;
    int		  timeo;

    dprint((9, "new mail called (force=%d %s flags=0x%x)\n",
	       force_arg,
	       time_for_check_point == GoodTime    ? "GoodTime" :
	        time_for_check_point == BadTime     ? "BadTime"  :
		 time_for_check_point == VeryBadTime ? "VeryBad"  :
		  time_for_check_point == DoItNow     ? "DoItNow"  : "?",
	       flags));

    force = force_arg;

    now = time(0);

    timeo = get_input_timeout();

    if(time_for_check_point == GoodTime)
      adrbk_maintenance();

    if(time_for_check_point == GoodTime || force_arg)
      folder_unseen_count_updater(UFU_ANNOUNCE | (force_arg ? UFU_FORCE : 0));

    if(sp_need_to_rethread(ps_global->mail_stream))
      force = 1;

    if(!force && sp_unsorted_newmail(ps_global->mail_stream))
      force = !(flags & NM_DEFER_SORT);

    if(!ps_global->mail_stream
       || !(timeo || force || sp_a_locked_stream_changed()))
      return(-1);

    last_check_point_call = now;
    since_last_input = (long) now - (long) time_of_last_input();

    /*
     * We have this for loop followed by the do-while so that we will prefer
     * to ping the active streams before we ping the inactive ones, in cases
     * where the pings or checks are taking a long time.
     */
    for(i = 0; i < ps_global->s_pool.nstream; i++){
	m = ps_global->s_pool.streams[i];
	if(!m || m->halfopen ||
	   (m != ps_global->mail_stream &&
	    !(force_arg && sp_flagged(m, SP_LOCKED))))
	  continue;
	
	/*
	 * This for() loop is only the current folder, unless the user
	 * has forced the check, in which case it is all locked folders.
	 */
	
	/*
	 * After some amount of inactivity on a stream, the server may
	 * close the stream. Each protocol has its own idea of how much
	 * inactivity should be allowed before the stream is closed. For
	 * example, IMAP specifies that the server should not close the
	 * stream unilaterally until at least 30 minutes of inactivity.
	 * The GET_IDLETIMEOUT call gives us that time in minutes. We
	 * want to be sure to keep the stream alive if it is about to die
	 * due to inactivity.
	 */
	adj_idle_timeout = 60 * (long) mail_parameters(m,GET_IDLETIMEOUT,NULL);
	if(adj_idle_timeout <= 0)
	  adj_idle_timeout = 600;

	adj = (adj_idle_timeout >= 50 * FUDGE) ? 5 * FUDGE :
	        (adj_idle_timeout >= 30 * FUDGE) ? 3 * FUDGE :
	          (adj_idle_timeout >= 20 * FUDGE) ? 2 * FUDGE : FUDGE;
	adj_idle_timeout = MAX(adj_idle_timeout - adj, 120);

	/*
	 * Set interval to mail-check-interval unless
	 * mail-check-interval-noncurrent is nonzero and this is not inbox
	 * or current stream.
	 */
	if(ps_global->check_interval_for_noncurr > 0
	   && m != ps_global->mail_stream
	   && !sp_flagged(m, SP_INBOX))
	  interval = ps_global->check_interval_for_noncurr;
	else
	  interval = timeo;

	/*
	 * We want to make sure that we notice expunges, but we don't have
	 * to be fanatical about it. Every once in a while we'll do a ping
	 * because we haven't had a command that notices expunges for a
	 * while. It's also a larger number than interval so it gives us a
	 * convenient interval to do slower pinging than interval if we
	 * are busy.
	 */
	if(interval <= adj_idle_timeout)
	  expunged_reaper_to = MIN(MAX(2*interval,180), adj_idle_timeout);
	else
	  expunged_reaper_to = interval;

	/*
	 * User may want to avoid new mail checking while composing.
	 * In this case we will only do the keepalives.
	 */
	if(timeo == 0
	   || (flags & NM_FROM_COMPOSER
	       && ((F_ON(F_QUELL_PINGS_COMPOSING, ps_global)
	            && !sp_flagged(m, SP_INBOX))
	           ||
	           (F_ON(F_QUELL_PINGS_COMPOSING_INBOX, ps_global)
	            && sp_flagged(m, SP_INBOX))))){
	    interval = expunged_reaper_to = 0;
	}

	dprint((9,
	       "%s: force=%d interval=%ld exp_reap_to=%ld adj_idle_to=%ld\n",
	       STREAMNAME(m), force_arg, (long) interval,
	       (long) expunged_reaper_to, (long) adj_idle_timeout));
	dprint((9,
	       "   since_last_ping=%ld since_last_reap=%ld\n",
	       (long) (now - sp_last_ping(m)),
	       (long) (now - sp_last_expunged_reaper(m))));

	/* if check_point does a check it resets last_ping time */
	if(force_arg || (timeo && expunged_reaper_to > 0))
	  (void) check_point(m, time_for_check_point, flags);

	/*
	 * Remember that unless force_arg is set, this check is really
	 * only for the current folder. This is usually going to fire
	 * on the first test, which is the interval the user set.
	 */
	if(force_arg
	   ||
	   (timeo
	    &&
	    ((interval && (now - sp_last_ping(m) >= interval-1))
	     ||
	     (expunged_reaper_to
	      && (now - sp_last_expunged_reaper(m)) >= expunged_reaper_to)
	     ||
	     (now - sp_last_ping(m) >= adj_idle_timeout)))){

	    if((flags & NM_STATUS_MSG) && pith_opt_newmail_check_cue)
	      (*pith_opt_newmail_check_cue)(TRUE);

	    dprint((7, "Mail_Ping(%s): lastping=%ld er=%ld%s%s %s\n",
		   STREAMNAME(m),
		   (long) (now - sp_last_ping(m)),
		   (long) (now - sp_last_expunged_reaper(m)),
		   force_arg                      ? " [forced]" :
		    interval && (now-sp_last_ping(m) >= interval-1)
						   ? " [it's time]" :
		    expunged_reaper_to
		     && (now - sp_last_expunged_reaper(m) >= expunged_reaper_to)
						    ? " [expunged reaper]"
						    : " [keepalive]",
		   m == ps_global->mail_stream ? " [current]" : "",
		   debug_time(0,1)));

	    /*
	     * We're about to ping the stream.
	     * If the stream is a #move Mail Drop there is a minimum time
	     * between re-opens of the mail drop to check for new mail.
	     * If the check is forced by the user, they want it to
	     * happen now. We use knowledge of c-client internals to
	     * make this happen.
	     */
	    if(force_arg && m && m->snarf.name)
	      m->snarf.time = 0;

	    /*-- Ping the stream to check for new mail --*/
	    if(sp_dead_stream(m)){
		dprint((6, "no check: stream is dead\n"));
	    }
	    else if(!pine_mail_ping(m)){
		dprint((6, "ping failed: stream is dead\n"));
		sp_set_dead_stream(m, 1);
	    }

	    dprint((7, "Ping complete: %s\n", debug_time(0,1)));

	    if((flags & NM_STATUS_MSG) && pith_opt_newmail_check_cue)
	      (*pith_opt_newmail_check_cue)(FALSE);
	}
    }

    if(nexttime < 0 || nexttime >= ps_global->s_pool.nstream)
      nexttime = 0;

    i = started_on = nexttime;
    do {
	m = ps_global->s_pool.streams[i];

	nexttime = i;
	if(ps_global->s_pool.nstream > 0)
	  i = (i + 1) % ps_global->s_pool.nstream;

	/*
	 * This do() loop handles all the other streams that weren't covered
	 * in the for() loop above.
	 */
	if((!m || m->halfopen) ||
	   (m == ps_global->mail_stream ||
	    (force_arg && sp_flagged(m, SP_LOCKED)))){
	    nexttime = i;
	    continue;
	}

	/*
	 * If it is taking an extra long time to do the pings and checks,
	 * think about skipping some of them. Always do at least one of
	 * these non-special streams (if they are due to be pinged).
	 * The nexttime variable keeps track of where we were so that we
	 * don't always ping the first one in the list and then skip out.
	 */
	if((time(0) - now >= 5) && have_pinged_non_special){
	    dprint((7, "skipping pings due to delay: %s\n",
			debug_time(0,1)));
	    break;
	}

	nexttime = i;
	have_pinged_non_special++;

	adj_idle_timeout = 60 * (long) mail_parameters(m,GET_IDLETIMEOUT,NULL);
	if(adj_idle_timeout <= 0)
	  adj_idle_timeout = 600;

	adj = (adj_idle_timeout >= 50 * FUDGE) ? 5 * FUDGE :
	        (adj_idle_timeout >= 30 * FUDGE) ? 3 * FUDGE :
	          (adj_idle_timeout >= 20 * FUDGE) ? 2 * FUDGE : FUDGE;
	adj_idle_timeout = MAX(adj_idle_timeout - adj, 120);

	if(ps_global->check_interval_for_noncurr > 0
	   && m != ps_global->mail_stream
	   && !sp_flagged(m, SP_INBOX))
	  interval = ps_global->check_interval_for_noncurr;
	else
	  interval = timeo;

	if(interval <= adj_idle_timeout)
	  expunged_reaper_to = MIN(MAX(2*interval,180), adj_idle_timeout);
	else
	  expunged_reaper_to = interval;

	if(timeo == 0
	   || (flags & NM_FROM_COMPOSER
	       && ((F_ON(F_QUELL_PINGS_COMPOSING, ps_global)
	            && !sp_flagged(m, SP_INBOX))
	           ||
	           (F_ON(F_QUELL_PINGS_COMPOSING_INBOX, ps_global)
	            && sp_flagged(m, SP_INBOX))))){
	    interval = expunged_reaper_to = 0;
	}

	dprint((9,
	       "%s: force=%d interval=%ld exp_reap_to=%ld adj_idle_to=%ld\n",
	       STREAMNAME(m), force_arg, (long) interval,
	       (long) expunged_reaper_to, (long) adj_idle_timeout));
	dprint((9,
	    "   since_last_ping=%ld since_last_reap=%ld since_last_input=%ld\n",
	    (long) (now - sp_last_ping(m)),
	    (long) (now - sp_last_expunged_reaper(m)),
	    (long) since_last_input));

	/* if check_point does a check it resets last_ping time */
	if(force_arg || (timeo && expunged_reaper_to > 0))
	  (void) check_point(m, time_for_check_point, flags);


	/*
	 * The check here is a little bit different from the current folder
	 * check in the for() loop above. In particular, we defer our
	 * pinging for awhile if the last input was recent (except for the
	 * inbox!). We ping streams which are cached but not actively being
	 * used (that is, the non-locked streams) at a slower rate.
	 * If we don't use them for a long time we will eventually close them
	 * (in maybe_kill_old_stream()) but we do it when we want to instead
	 * of when the server wants us to by attempting to keep it alive here.
	 * The other reason to ping the cached streams is that we only get
	 * told the new mail in those streams is recent one time, the messages
	 * that weren't handled here will no longer be recent next time
	 * we open the folder.
	 */
	if((force_arg && sp_flagged(m, SP_LOCKED))
	   ||
	   (timeo
	    &&
	    ((interval
	      && sp_flagged(m, SP_LOCKED)
	      && ((since_last_input >= 3
		   && (now-sp_last_ping(m) >= interval-1))
		  || (sp_flagged(m, SP_INBOX)
		      && (now-sp_last_ping(m) >= interval-1))))
	     ||
	     (expunged_reaper_to
	      && sp_flagged(m, SP_LOCKED)
	      && (now-sp_last_expunged_reaper(m) >= expunged_reaper_to))
	     ||
	     (expunged_reaper_to
	      && !sp_flagged(m, SP_LOCKED)
	      && since_last_input >= 3
	      && (now-sp_last_ping(m) >= expunged_reaper_to))
	     ||
	     (now - sp_last_ping(m) >= adj_idle_timeout)))){

	    if((flags & NM_STATUS_MSG) && pith_opt_newmail_check_cue)
	      (*pith_opt_newmail_check_cue)(TRUE);

	    dprint((7,
		   "Mail_Ping(%s): lastping=%ld er=%ld%s idle: %ld %s\n",
		   STREAMNAME(m),
		   (long) (now - sp_last_ping(m)),
		   (long) (now - sp_last_expunged_reaper(m)),
		   (force_arg && sp_flagged(m, SP_LOCKED)) ? " [forced]" :
		   (interval
		    && sp_flagged(m, SP_LOCKED)
		    && ((since_last_input >= 3
		         && (now-sp_last_ping(m) >= interval-1))
		        || (sp_flagged(m, SP_INBOX)
			    && (now-sp_last_ping(m) >= interval-1))))
				    ? " [it's time]" :
		   (expunged_reaper_to
		    && sp_flagged(m, SP_LOCKED)
		    && (now-sp_last_expunged_reaper(m) >= expunged_reaper_to))
				    ? " [expunged reaper]" :
		   (expunged_reaper_to
		    && !sp_flagged(m, SP_LOCKED)
		    && since_last_input >= 3
		    && (now-sp_last_ping(m) >= expunged_reaper_to))
				     ? " [slow ping]" : " [keepalive]",
		   since_last_input,
		   debug_time(0,1)));

	    /*
	     * We're about to ping the stream.
	     * If the stream is a #move Mail Drop there is a minimum time
	     * between re-opens of the mail drop to check for new mail.
	     * If the check is forced by the user, they want it to
	     * happen now. We use knowledge of c-client internals to
	     * make this happen.
	     */
	    if(force_arg && m && m->snarf.name)
	      m->snarf.time = 0;

	    /*-- Ping the stream to check for new mail --*/
	    if(sp_dead_stream(m)){
		dprint((6, "no check: stream is dead\n"));
	    }
	    else if(!pine_mail_ping(m)){
		dprint((6, "ping failed: stream is dead\n"));
		sp_set_dead_stream(m, 1);
	    }

	    dprint((7, "Ping complete: %s\n", debug_time(0,1)));

	    if((flags & NM_STATUS_MSG) && pith_opt_newmail_check_cue)
	      (*pith_opt_newmail_check_cue)(FALSE);
	}
    } while(i != started_on);

    /*
     * Current mail box state changed, could be additions or deletions.
     * Also check if we need to do sorting that has been deferred.
     * We handle the current stream separately from the rest in the
     * similar loop that follows this paragraph.
     */
    m = ps_global->mail_stream;
    if(sp_mail_box_changed(m) || sp_unsorted_newmail(m)
       || sp_need_to_rethread(m)){
        dprint((7,
	 "Cur new mail, %s, new_mail_count: %ld expunge: %ld, max_msgno: %ld\n",
		   (m && m->mailbox) ? m->mailbox : "?",
		   sp_new_mail_count(m),
		   sp_expunge_count(m),
		   mn_get_total(sp_msgmap(m))));

	new_mail_was_announced = 0;
	if(sp_mail_box_changed(m))
	  fixup_flags(m, sp_msgmap(m));

        if(sp_new_mail_count(m))
	  process_filter_patterns(m, sp_msgmap(m), sp_new_mail_count(m));

	/* worry about sorting */
        if((sp_new_mail_count(m) > 0L
	    || sp_unsorted_newmail(m)
	    || sp_need_to_rethread(m))
	   && !((flags & NM_DEFER_SORT)
		|| any_lflagged(sp_msgmap(m), MN_HIDE)))
	  refresh_sort(m, sp_msgmap(m),
		       (flags & NM_STATUS_MSG) ? SRT_VRB : SRT_NON);
        else if(sp_new_mail_count(m) > 0L)
	  sp_set_unsorted_newmail(m, 1);

        if(sp_new_mail_count(m) > 0L){
            sp_set_mail_since_cmd(m, sp_mail_since_cmd(m)+sp_new_mail_count(m));
	    rv += (t_nm_count = sp_new_mail_count(m));
	    sp_set_new_mail_count(m, 0L);

	    if((flags & NM_STATUS_MSG) && pith_opt_newmail_announce){
		for(n = m->nmsgs; n > 1L; n--)
		  if(!get_lflag(m, NULL, n, MN_EXLD))
		    break;

		(*pith_opt_newmail_announce)(m, n, t_nm_count);

		if(n)
		  new_mail_was_announced++;
	    }
        }

	update_folder_unseen_by_stream(m, new_mail_was_announced ? UFU_NONE : UFU_ANNOUNCE);

	if(flags & NM_STATUS_MSG)
	  sp_set_mail_box_changed(m, 0);
    }

    /* the rest of the streams */
    for(i = 0; i < ps_global->s_pool.nstream; i++){
	m = ps_global->s_pool.streams[i];
	if(!m || m == ps_global->mail_stream)
	  continue;

	if(sp_mail_box_changed(m)){
	    /*-- New mail for this stream, queue up the notification --*/
	    dprint((7,
	     "New mail, %s, new_mail_count: %ld expunge: %ld, max_msgno: %ld\n",
		       (m && m->mailbox) ? m->mailbox : "?",
		       sp_new_mail_count(m),
		       sp_expunge_count(m),
		       mn_get_total(sp_msgmap(m))));

	    new_mail_was_announced = 0;
	    fixup_flags(m, sp_msgmap(m));

	    if(sp_new_mail_count(m))
	      process_filter_patterns(m, sp_msgmap(m), sp_new_mail_count(m));

	    if(sp_new_mail_count(m) > 0){
		sp_set_unsorted_newmail(m, 1);
		sp_set_mail_since_cmd(m, sp_mail_since_cmd(m) +
					 sp_new_mail_count(m));
		if(sp_flagged(m, SP_LOCKED) && sp_flagged(m, SP_USERFLDR))
		  rv += (t_nm_count = sp_new_mail_count(m));

		sp_set_new_mail_count(m, 0L);

		/* messages only for user's streams */
		if(flags & NM_STATUS_MSG
		   && pith_opt_newmail_announce
		   && sp_flagged(m, SP_LOCKED)
		   && sp_flagged(m, SP_USERFLDR)){
		    for(n = m->nmsgs; n > 1L; n--)
		      if(!get_lflag(m, NULL, n, MN_EXLD))
			break;

		    (*pith_opt_newmail_announce)(m, n, t_nm_count);

		    if(n)
		      new_mail_was_announced++;
		}
	    }

	    update_folder_unseen_by_stream(m, new_mail_was_announced ? UFU_NONE : UFU_ANNOUNCE);

	    if(flags & NM_STATUS_MSG)
	      sp_set_mail_box_changed(m, 0);
	}
    }

    /* so quit_screen can tell new mail from expunged mail */
    exp_count = sp_expunge_count(ps_global->mail_stream);

    /* see if we want to kill any cached streams */
    for(i = 0; i < ps_global->s_pool.nstream; i++){
	m = ps_global->s_pool.streams[i];
	if(sp_last_ping(m) >= now)
          maybe_kill_old_stream(m);
    }

    /*
     * This is here to prevent banging on the down arrow key (or holding
     * it down and repeating) at the end of the index from causing
     * a whole bunch of new mail checks. Last_nextitem_forcechk does get
     * set at the place it is tested in mailcmd.c, but this is here to
     * reset it to a little bit later in case it takes a second or more
     * to check for the mail. If we didn't do this, we'd just check every
     * keystroke as long as the checks took more than a second.
     */
    if(force_arg)
      ps_global->last_nextitem_forcechk = time(0);

    dprint((6, "******** new mail returning %ld  ********\n", 
	       rv ? rv : (exp_count ? 0 : -1)));
    return(rv ? rv : (exp_count ? 0 : -1));
}
コード例 #17
0
ファイル: ldap.c プロジェクト: RsrchBoy/dpkg-alpine
/*
 * This function does white pages lookups.
 *
 * Args  string -- the string to use in the lookup
 *
 * Returns     NULL -- lookup failed
 *          Address -- A single address is returned if lookup was successfull.
 */
ADDRESS *
wp_lookups(char *string, WP_ERR_S *wp_err, int recursing)
{
    ADDRESS *ret_a = NULL;
    char ebuf[200];
#ifdef	ENABLE_LDAP
    LDAP_SERV_RES_S *free_when_done = NULL;
    LDAPLookupStyle style;
    LDAP_CHOOSE_S *winning_e = NULL;
    LDAP_SERV_S *info = NULL;
    static char *fakedomain = "@";
    char *tmp_a_string;
    int   auwe_rv = 0;

    /*
     * Runtime ldap lookup of addrbook entry.
     */
    if(!strncmp(string, RUN_LDAP, LEN_RL)){
	LDAP_SERV_RES_S *head_of_result_list;

	info = break_up_ldap_server(string+LEN_RL);
        head_of_result_list = ldap_lookup(info, "", NULL, wp_err, 1);

	if(head_of_result_list){
	    if(!wp_exit)
	      auwe_rv = ask_user_which_entry(head_of_result_list, string,
					     &winning_e,
					     wp_err,
					     wp_err->wp_err_occurred
					     ? DisplayIfOne : DisplayIfTwo);

	    if(auwe_rv != -5)
	      free_when_done = head_of_result_list;
	}
	else{
	    wp_err->wp_err_occurred = 1;
	    if(wp_err->error){
		q_status_message(SM_ORDER, 3, 5, wp_err->error);
		display_message('x');
		fs_give((void **)&wp_err->error);
	    }

	    /* try using backup email address */
	    if(info && info->mail && *info->mail){
		tmp_a_string = cpystr(info->mail);
		rfc822_parse_adrlist(&ret_a, tmp_a_string, fakedomain);
		fs_give((void **)&tmp_a_string);

		wp_err->error =
		  cpystr(_("Directory lookup failed, using backup email address"));
	    }
	    else{
		/*
		 * Do this so the awful LDAP: ... string won't show up
		 * in the composer. This shouldn't actually happen in
		 * real life, so we're not too concerned about it. If we
		 * were we'd want to recover the nickname we started with
		 * somehow, or something like that.
		 */
		ret_a = mail_newaddr();
		ret_a->mailbox = cpystr("missing-username");
		wp_err->error = cpystr(_("Directory lookup failed, no backup email address available"));
	    }

	    q_status_message(SM_ORDER, 3, 5, wp_err->error);
	    display_message('x');
	}
    }
    else{
	style = F_ON(F_COMPOSE_REJECTS_UNQUAL, ps_global)
			? DisplayIfOne : DisplayIfTwo;
	auwe_rv = ldap_lookup_all(string, as.n_serv, recursing, style, NULL,
				  &winning_e, wp_err, &free_when_done);
    }

    if(winning_e && auwe_rv != -5){
	ret_a = address_from_ldap(winning_e);

	if(pith_opt_save_ldap_entry && ret_a && F_ON(F_ADD_LDAP_TO_ABOOK, ps_global) && !info)
	  (*pith_opt_save_ldap_entry)(ps_global, winning_e, 1);


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

    /* Info's only set in the RUN_LDAP case */
    if(info){
	if(ret_a && ret_a->host){
	    ADDRESS *backup = NULL;

	    if(info->mail && *info->mail)
	      rfc822_parse_adrlist(&backup, info->mail, fakedomain);

	    if(!backup || !address_is_same(ret_a, backup)){
		if(wp_err->error){
		    q_status_message(SM_ORDER, 3, 5, wp_err->error);
		    display_message('x');
		    fs_give((void **)&wp_err->error);
		}

		snprintf(ebuf, sizeof(ebuf),
	       _("Warning: current address different from saved address (%s)"),
		   info->mail);
		wp_err->error = cpystr(ebuf);
		q_status_message(SM_ORDER, 3, 5, wp_err->error);
		display_message('x');
	    }

	    if(backup)
	      mail_free_address(&backup);
	}

	free_ldap_server_info(&info);
    }

    if(free_when_done)
      free_ldap_result_list(&free_when_done);
#endif	/* ENABLE_LDAP */

    if(ret_a){
	if(ret_a->mailbox){  /* indicates there was a MAIL attribute */
	    if(!ret_a->host || !ret_a->host[0]){
		if(ret_a->host)
		  fs_give((void **)&ret_a->host);

		ret_a->host = cpystr("missing-hostname");
		wp_err->wp_err_occurred = 1;
		if(wp_err->error)
		  fs_give((void **)&wp_err->error);

		wp_err->error = cpystr(_("Missing hostname in LDAP address"));
		q_status_message(SM_ORDER, 3, 5, wp_err->error);
		display_message('x');
	    }

	    if(!ret_a->mailbox[0]){
		if(ret_a->mailbox)
		  fs_give((void **)&ret_a->mailbox);

		ret_a->mailbox = cpystr("missing-username");
		wp_err->wp_err_occurred = 1;
		if(wp_err->error)
		  fs_give((void **)&wp_err->error);

		wp_err->error = cpystr(_("Missing username in LDAP address"));
		q_status_message(SM_ORDER, 3, 5, wp_err->error);
		display_message('x');
	    }
	}
	else{
	    wp_err->wp_err_occurred = 1;

	    if(wp_err->error)
	      fs_give((void **)&wp_err->error);

	    snprintf(ebuf, sizeof(ebuf), _("No email address available for \"%s\""),
		    (ret_a->personal && *ret_a->personal)
			    ? ret_a->personal
			    : "selected entry");
	    wp_err->error = cpystr(ebuf);
	    q_status_message(SM_ORDER, 3, 5, wp_err->error);
	    display_message('x');
	    mail_free_address(&ret_a);
	    ret_a = NULL;
	}
    }

    return(ret_a);
}
コード例 #18
0
ファイル: signal.c プロジェクト: ctubio/alpine
/*----------------------------------------------------------------------
     Suspend Pine. Reset tty and suspend. Suspend is finished when this returns

   Args:  The pine structure

 Result:  Execution suspended for a while. Screen will need redrawing
          after this is done.

 Instead of the usual handling of ^Z by catching a signal, we actually read
the ^Z and then clean up the tty driver, then kill ourself to stop, and
pick up where we left off when execution resumes.
  ----------------------------------------------------------------------*/
UCS
do_suspend(void)
{
    struct pine *pine = ps_global;
    time_t now;
    UCS retval;
#if defined(DOS) || defined(OS2)
    int   result, orig_cols, orig_rows;
#else
    int   isremote;
#endif
#ifdef	DOS
    static char *shell = NULL;
#define	STD_SHELL	"COMMAND.COM"
#else
#ifdef	OS2
    static char *shell = NULL;
#define	STD_SHELL	"CMD.EXE"
#endif
#endif

    if(!have_job_control()) {
        bogus_command(ctrl('Z'), F_ON(F_USE_FK, pine) ? "F1" : "?");
        return(NO_OP_COMMAND);
    }

    if(F_OFF(F_CAN_SUSPEND, pine)) {
        q_status_message(SM_ORDER | SM_DING, 3, 3,
                         _("Alpine suspension not enabled - see help text"));
        return(NO_OP_COMMAND);
    }

#ifdef	_WINDOWS
    mswin_minimize();
    return(NO_OP_COMMAND);
#else

    isremote = (ps_global->mail_stream && ps_global->mail_stream->mailbox
                && (*ps_global->mail_stream->mailbox == '{'
                    || (*ps_global->mail_stream->mailbox == '*'
                        && *(ps_global->mail_stream->mailbox + 1) == '{')));

    now = time((time_t *)0);
    dprint((1, "\n\n --- %s - SUSPEND ----  %s",
            isremote ? "REMOTE" : "LOCAL", ctime(&now)));
    ttyfix(0);

#if defined(DOS) || defined(OS2)
    suspend_notice("exit");
    if (!shell) {
        char *p;

        if (!((shell = getenv("SHELL")) || (shell = getenv("COMSPEC"))))
            shell = STD_SHELL;

        shell = cpystr(shell);			/* copy in free storage */
        for(p = shell; (p = strchr(p, '/')); p++)
            *p = '\\';
    }

    result = system(shell);
#else
    if(F_ON(F_SUSPEND_SPAWNS, ps_global)) {
        PIPE_S *syspipe;

        if((syspipe = open_system_pipe(NULL, NULL, NULL, PIPE_USER|PIPE_RESET,
                                       0, pipe_callback, pipe_report_error)) != NULL) {
            suspend_notice("exit");
#ifndef	SIGCHLD
            if(isremote)
                suspend_warning();
#endif
            (void) close_system_pipe(&syspipe, NULL, pipe_callback);
        }
    }
    else {
        suspend_notice("fg");

        if(isremote)
            suspend_warning();

        stop_process();
    }
#endif	/* DOS */

    now = time((time_t *)0);
    dprint((1, "\n\n ---- RETURN FROM SUSPEND ----  %s",
            ctime(&now)));

    ttyfix(1);

#if defined(DOS) || defined(OS2)
    orig_cols = pine->ttyo->screen_cols;
    orig_rows = pine->ttyo->screen_rows;
#endif

    fix_windsize(pine);

#if defined(DOS) || defined(OS2)
    if(orig_cols != pine->ttyo->screen_cols ||
            orig_rows != pine->ttyo->screen_rows)
        retval = KEY_RESIZE;
    else
#endif
        retval = ctrl('L');;

#if	defined(DOS) || defined(OS2)
    if(result == -1)
        q_status_message1(SM_ORDER | SM_DING, 3, 4,
                          _("Error loading \"%s\""), shell);
#endif

    if(isremote && !pine_mail_ping(ps_global->mail_stream))
        q_status_message(SM_ORDER | SM_DING, 4, 9,
                         _("Suspended for too long, IMAP connection broken"));

    return(retval);
#endif	/* !_WINDOWS */
}
コード例 #19
0
ファイル: termin.unx.c プロジェクト: nysan/alpine
/*----------------------------------------------------------------------
  Read input characters with lots of processing for arrow keys and such  (UNIX)

 Args:  time_out -- The timeout to for the reads 

 Result: returns the character read. Possible special chars.

    This deals with function and arrow keys as well. 

  The idea is that this routine handles all escape codes so it done in
  only one place. Especially so the back arrow key can work when entering
  things on a line. Also so all function keys can be disabled and not
  cause weird things to happen.
  ---*/
UCS
read_char(int time_out)
{
    UCS status, cc, ch;
    int (*key_rec)(int);

    key_rec = key_recorder;
    if(ps_global->conceal_sensitive_debugging)
      key_rec = NULL;

    /* Get input from initial-keystrokes */
    if(process_config_input(&cc)){
	ch = cc;
	return(ch);
    }

    if((ch = check_for_timeout(time_out)) != READY_TO_READ)
      goto done;
    
    switch(status = kbseq(pine_simple_ttgetc, key_rec, read_bail,
			  ps_global->input_cs, &ch)){
      case KEY_DOUBLE_ESC:
	/*
	 * Special hack to get around comm devices eating control characters.
	 */
	if(check_for_timeout(5) != READY_TO_READ){
	    dprint((9, "Read char: incomplete double escape timed out...\n"));
	    ch = KEY_JUNK;		/* user typed ESC ESC, then stopped */
	    goto done;
	}
	else
	  ch = READ_A_CHAR();

	ch &= 0x7f;

	/* We allow a 3-digit number between 001 and 255 */
	if(isdigit((unsigned char) ch)){
	    int n = 0, i = ch - '0';

	    if(i < 0 || i > 2){
		dprint((9, "Read char: double escape followed by 1st digit not 0, 1, or 2... (%d)\n", i));
		ch = KEY_JUNK;
		goto done;		/* bogus literal char value */
	    }

	    while(n++ < 2){
		if(check_for_timeout(5) != READY_TO_READ
		   || (!isdigit((unsigned char) (ch = READ_A_CHAR()))
		       || (n == 1 && i == 2 && ch > '5')
		       || (n == 2 && i == 25 && ch > '5'))){
		    dprint((9, "Read char: bad double escape, either timed out or too large 3-digit num...\n"));
		    ch = KEY_JUNK;	/* user typed ESC ESC #, stopped */
		    goto done;
		}

		i = (i * 10) + (ch - '0');
	    }

	    ch = i;
	}
	else{	/* or, normal case, ESC ESC c  means ^c */
	    if(islower((unsigned char) ch))	/* canonicalize if alpha */
	      ch = toupper((unsigned char) ch);

	    ch = (isalpha((unsigned char)ch) || ch == '@'
		  || (ch >= '[' && ch <= '_'))
		   ? ctrl(ch) : ((ch == SPACE) ? ctrl('@'): ch);
	    dprint((9, "Read char: this is a successful double escape...\n"));
	}

	goto done;

#ifdef MOUSE
      case KEY_XTERM_MOUSE:
	if(mouseexist()){
	    /*
	     * Special hack to get mouse events from an xterm.
	     * Get the details, then pass it past the keymenu event
	     * handler, and then to the installed handler if there
	     * is one...
	     */
	    static int    down = 0;
	    int           x, y, button;
	    unsigned long cmd;

	    clear_cursor_pos();
	    button = READ_A_CHAR() & 0x03;

	    x = READ_A_CHAR() - '!';
	    y = READ_A_CHAR() - '!';

	    ch = NO_OP_COMMAND;
	    if(button == 0){		/* xterm button 1 down */
		down = 1;
		if(checkmouse(&cmd, 1, x, y))
		  ch = cmd;
	    }
	    else if (down && button == 3){
		down = 0;
		if(checkmouse(&cmd, 0, x, y))
		  ch = cmd;
	    }

	    goto done;
	}

	break;
#endif /* MOUSE */

      case  KEY_UP	:
      case  KEY_DOWN	:
      case  KEY_RIGHT	:
      case  KEY_LEFT	:
      case  KEY_PGUP	:
      case  KEY_PGDN	:
      case  KEY_HOME	:
      case  KEY_END	:
      case  KEY_DEL	:
      case  PF1		:
      case  PF2		:
      case  PF3		:
      case  PF4		:
      case  PF5		:
      case  PF6		:
      case  PF7		:
      case  PF8		:
      case  PF9		:
      case  PF10	:
      case  PF11	:
      case  PF12	:
        dprint((9, "Read char returning: 0x%x %s\n", status, pretty_command(status)));
	return(status);

      case  CTRL_KEY_UP	:
	status = KEY_UP;
        dprint((9, "Read char returning: 0x%x %s (for CTRL_KEY_UP)\n", status, pretty_command(status)));
	return(status);

      case  CTRL_KEY_DOWN	:
	status = KEY_DOWN;
        dprint((9, "Read char returning: 0x%x %s (for CTRL_KEY_DOWN)\n", status, pretty_command(status)));
	return(status);

      case  CTRL_KEY_RIGHT	:
	status = KEY_RIGHT;
        dprint((9, "Read char returning: 0x%x %s (for CTRL_KEY_RIGHT)\n", status, pretty_command(status)));
	return(status);

      case  CTRL_KEY_LEFT	:
	status = KEY_LEFT;
        dprint((9, "Read char returning: 0x%x %s (for CTRL_KEY_LEFT)\n", status, pretty_command(status)));
	return(status);

      case KEY_SWALLOW_Z:
	status = KEY_JUNK;
      case KEY_SWAL_UP:
      case KEY_SWAL_DOWN:
      case KEY_SWAL_LEFT:
      case KEY_SWAL_RIGHT:
	do
	  if(check_for_timeout(2) != READY_TO_READ){
	      status = KEY_JUNK;
	      break;
	  }
	while(!strchr("~qz", READ_A_CHAR()));
	ch = (status == KEY_JUNK) ? status : status - (KEY_SWAL_UP - KEY_UP);
	goto done;

      case KEY_KERMIT:
	do{
	    cc = ch;
	    if(check_for_timeout(2) != READY_TO_READ){
		status = KEY_JUNK;
		break;
	    }
	    else
	      ch = READ_A_CHAR();
	}while(cc != '\033' && ch != '\\');

	ch = KEY_JUNK;
	goto done;

      case BADESC:
	ch = KEY_JUNK;
	goto done;

      case 0: 	/* regular character */
      default:
	/*
	 * we used to strip (ch &= 0x7f;), but this seems much cleaner
	 * in the face of line noise and has the benefit of making it
	 * tougher to emit mistakenly labeled MIME...
	 */
	if((ch & ~0x7f)
	   && ((!ps_global->keyboard_charmap || !strucmp(ps_global->keyboard_charmap, "US-ASCII"))
	       && (!ps_global->display_charmap || !strucmp(ps_global->display_charmap, "US-ASCII")))){
	    dprint((9, "Read char sees ch = 0x%x status=0x%x, returns KEY_JUNK\n", ch, status));
	    return(KEY_JUNK);
	}
	else if(ch == ctrl('Z')){
	    dprint((9, "Read char got ^Z, calling do_suspend\n"));
	    ch = do_suspend();
	    dprint((9, "After do_suspend Read char returns 0x%x %s\n", ch, pretty_command(ch)));
	    return(ch);
	}
#ifdef MOUSE
	else if(ch == ctrl('\\')){
	    int e;

	    dprint((9, "Read char got ^\\, toggle xterm mouse\n"));
	    if(F_ON(F_ENABLE_MOUSE, ps_global)){
		(e=mouseexist()) ? end_mouse() : (void) init_mouse();
		if(e != mouseexist())
		  q_status_message1(SM_ASYNC, 0, 2, "Xterm mouse tracking %s!",
						     mouseexist() ? "on" : "off");
		else if(!e)
		  q_status_message1(SM_ASYNC, 0, 2, "See help for feature \"%s\" ($DISPLAY variable set?)", pretty_feature_name(feature_list_name(F_ENABLE_MOUSE), -1));
	    }
	    else
	      q_status_message1(SM_ASYNC, 0, 2, "Feature \"%s\" not enabled",
				pretty_feature_name(feature_list_name(F_ENABLE_MOUSE), -1));

	    return(NO_OP_COMMAND);
	}
#endif /* MOUSE */


      done:
#ifdef	DEBUG
	if(ps_global->conceal_sensitive_debugging && debug < 10){
	    dprint((9, "Read char returning: <hidden char>\n"));
	}
	else{
	    dprint((9, "Read char returning: 0x%x %s\n", ch, pretty_command(ch)));
	}
#endif

        return(ch);
    }

    /* not reachable */
    return(KEY_JUNK);
}
コード例 #20
0
ファイル: signal.c プロジェクト: ctubio/alpine
/*
 * pipe_callback - handle pine-specific pipe setup like child
 *		   signal handler and possibly any display stuff
 * BUG: this function should probably be in a "alpine/pipe.c"
 */
void
pipe_callback(PIPE_S *syspipe, int flags, void *data)
{
#ifdef _WINDOWS
    bitmap_t bitmap;
#endif
    if(flags & OSB_PRE_OPEN) {
        dprint((5, "Opening pipe: (%s%s%s%s%s%s)\n",
                (syspipe->mode & PIPE_WRITE)   ? "W":"", (syspipe->mode & PIPE_READ)  ? "R":"",
                (syspipe->mode & PIPE_NOSHELL) ? "N":"", (syspipe->mode & PIPE_PROT)  ? "P":"",
                (syspipe->mode & PIPE_USER)    ? "U":"", (syspipe->mode & PIPE_RESET) ? "T":""));

#ifdef	_WINDOWS
        q_status_message(SM_ORDER, 0, 0,
                         "Waiting for called program to finish...");

        flush_status_messages(1);
        setbitmap(bitmap);
        draw_keymenu(&pipe_cancel_keymenu, bitmap, ps_global->ttyo->screen_cols,
                     1-FOOTER_ROWS(ps_global), 0, FirstMenu);
#else  /* UNIX */

        if(!(syspipe->mode & (PIPE_WRITE | PIPE_READ)) && !(syspipe->mode & PIPE_SILENT)) {
            flush_status_messages(0);		/* just clean up display */
            ClearScreen();
            fflush(stdout);
        }

        if(syspipe->mode & PIPE_RESET)
            ttyfix(0);

#ifdef	SIGCHLD
        /*
         * Prepare for demise of child.  Use SIGCHLD if it's available so
         * we can do useful things, like keep the IMAP stream alive, while
         * we're waiting on the child. The handler may have been changed by
         * something in the composer, in particular, by an alt_editor call.
         * So we need to re-set it to child_signal and then set it back
         * when we're done.
         */
        child_signalled = child_jump = 0;
        syspipe->chld   = signal(SIGCHLD, child_signal);
#endif
#endif /* UNIX */
    }
    else if(flags & OSB_POST_OPEN) {
#ifdef	_WINDOWS

        clearfooter(ps_global);
        ps_global->mangled_footer = 1;

        if((int) data == -2)
            q_status_message1(SM_ORDER, 2, 3, "Ignoring completion of %s", syspipe->command);

#else  /* UNIX */
        if(!(syspipe->mode & (PIPE_WRITE | PIPE_READ)) && !(syspipe->mode & PIPE_SILENT)) {
            ClearScreen();
            ps_global->mangled_screen = 1;
        }

        if(syspipe->mode & PIPE_RESET)
            ttyfix(1);

#ifdef	SIGCHLD
        (void) signal(SIGCHLD,  SIG_DFL);
#endif
#endif /* UNIX */
    }
    else if(flags & OSB_PRE_CLOSE) {
#ifdef	SIGCHLD
        /*
         * this is here so close_system_pipe so it has something
         * to do while we're waiting on the other end of the
         * pipe to complete.  When we're in the background for
         * a shell, the the side effect is pinging
         */
        RETSIGTYPE (*alarm_sig)();
        int	old_cue = F_ON(F_SHOW_DELAY_CUE, ps_global);

        /*
         * remember the current SIGALRM handler, and make sure it's
         * installed when we're finished just in case the longjmp
         * out of the SIGCHLD handler caused sleep() to lose it.
         * Don't pay any attention to that man behind the curtain.
         */
        alarm_sig = signal(SIGALRM, SIG_IGN);
        (void) F_SET(F_SHOW_DELAY_CUE, ps_global, 0);
        ps_global->noshow_timeout = 1;
        while(!child_signalled) {
            /* wake up and prod server */
            if(!(syspipe->mode & PIPE_NONEWMAIL))
                new_mail(0, 2,
                         (syspipe->mode & PIPE_RESET) ? NM_NONE : NM_DEFER_SORT);

            if(!child_signalled) {
                if(setjmp(child_state) == 0) {
                    child_jump = 1;	/* prepare to wake up */
                    sleep(600);		/* give it 5mins to happend */
                }
                else
                    our_sigunblock(SIGCHLD);
            }

            child_jump = 0;
        }

        ps_global->noshow_timeout = 0;
        F_SET(F_SHOW_DELAY_CUE, ps_global, old_cue);
        (void) signal(SIGALRM, alarm_sig);
        (void) signal(SIGCHLD, syspipe->chld);
#endif
    }
    else if(flags & OSB_POST_CLOSE) {
        if(syspipe->mode & PIPE_RESET)		/* restore our tty modes */
            ttyfix(1);

        if(!(syspipe->mode & (PIPE_WRITE | PIPE_READ | PIPE_SILENT))) {
            ClearScreen();			/* No I/O to forked child */
            ps_global->mangled_screen = 1;
        }
    }
}
コード例 #21
0
ファイル: radio.c プロジェクト: nysan/alpine
/*----------------------------------------------------------------------
    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);
}
コード例 #22
0
/*----------------------------------------------------------------------
       Get the current window size
  
   Args: ttyo -- pointer to structure to store window size in

  NOTE: we don't override the given values unless we know better
 ----*/
int
get_windsize(struct ttyo *ttyo)
{
    char	fontName[LF_FACESIZE+1];
    char	fontSize[12];
    char	fontStyle[64];
    char        fontCharSet[256];
    char	windowPosition[32], windowPositionReg[32];
    char	foreColor[64], backColor[64];
    int		newRows, newCols;
    char	cursorStyle[32];

    cursorStyle[0] = '\0';

    /* Get the new window parameters and update the 'pinerc' variables. */
    mswin_getwindow(fontName, sizeof(fontName), fontSize, sizeof(fontSize),
		    fontStyle, sizeof(fontStyle),
		    windowPosition, sizeof(windowPosition),
		    foreColor, sizeof(foreColor),
		    backColor, sizeof(backColor),
		    cursorStyle, sizeof(cursorStyle),
		    fontCharSet, sizeof(fontCharSet));

    if(!ps_global->VAR_FONT_NAME
       || strucmp(ps_global->VAR_FONT_NAME, fontName))
      set_variable(V_FONT_NAME, fontName, 1, 0,
		   ps_global->ew_for_except_vars);

    if(!ps_global->VAR_FONT_SIZE
       || strucmp(ps_global->VAR_FONT_SIZE, fontSize))
      set_variable(V_FONT_SIZE, fontSize, 1, 0,
		   ps_global->ew_for_except_vars);

    if(!ps_global->VAR_FONT_STYLE
       || strucmp(ps_global->VAR_FONT_STYLE, fontStyle))
      set_variable(V_FONT_STYLE, fontStyle, 1, 0,
		   ps_global->ew_for_except_vars);

    if(!ps_global->VAR_FONT_CHAR_SET
       || strucmp(ps_global->VAR_FONT_CHAR_SET, fontCharSet))
      set_variable(V_FONT_CHAR_SET, fontCharSet, 1, 0,
		   ps_global->ew_for_except_vars);

    if(strnicmp(windowPosition, "MIN0", 4) && !strchr(windowPosition, '!')){
	   if(F_ON(F_STORE_WINPOS_IN_CONFIG, ps_global)){
	       if(!ps_global->VAR_WINDOW_POSITION
		  || strucmp(ps_global->VAR_WINDOW_POSITION, windowPosition))
		 set_variable(V_WINDOW_POSITION, windowPosition, 1, 0,
			      ps_global->ew_for_except_vars);
	   }
	   else{
	       /*
		* Get the window position stored in the registry.
		*
		* If current window position is not in the registry or is
		* different from what is there, save it.
		*/
	       if((!mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, windowPositionReg,
			      sizeof(windowPositionReg)) ||
		   strucmp(windowPositionReg, windowPosition))
		  && (ps_global->update_registry != UREG_NEVER_SET))
		 mswin_reg(MSWR_OP_SET | MSWR_OP_FORCE, MSWR_PINE_POS, windowPosition,
			   (size_t)NULL);
	   }
    }
    
    mswin_getprintfont(fontName, sizeof(fontName),
		       fontSize, sizeof(fontSize),
		       fontStyle, sizeof(fontStyle),
		       fontCharSet, sizeof(fontCharSet));
    if(!ps_global->VAR_PRINT_FONT_NAME
       || strucmp(ps_global->VAR_PRINT_FONT_NAME, fontName))
      set_variable(V_PRINT_FONT_NAME, fontName, 1, 0,
		   ps_global->ew_for_except_vars);

    if(!ps_global->VAR_PRINT_FONT_SIZE
       || strucmp(ps_global->VAR_PRINT_FONT_SIZE, fontSize))
      set_variable(V_PRINT_FONT_SIZE, fontSize, 1, 0,
		   ps_global->ew_for_except_vars);

    if(!ps_global->VAR_PRINT_FONT_STYLE
       || strucmp(ps_global->VAR_PRINT_FONT_STYLE, fontStyle))
      set_variable(V_PRINT_FONT_STYLE, fontStyle, 1, 0,
		   ps_global->ew_for_except_vars);

    if(!ps_global->VAR_PRINT_FONT_CHAR_SET
       || strucmp(ps_global->VAR_PRINT_FONT_CHAR_SET, fontCharSet))
      set_variable(V_PRINT_FONT_CHAR_SET, fontCharSet, 1, 0,
		   ps_global->ew_for_except_vars);

    if(!ps_global->VAR_NORM_FORE_COLOR
       || strucmp(ps_global->VAR_NORM_FORE_COLOR, foreColor))
      set_variable(V_NORM_FORE_COLOR, foreColor, 1, 0,
		   ps_global->ew_for_except_vars);

    if(!ps_global->VAR_NORM_BACK_COLOR
       || strucmp(ps_global->VAR_NORM_BACK_COLOR, backColor))
      set_variable(V_NORM_BACK_COLOR, backColor, 1, 0,
		   ps_global->ew_for_except_vars);

    if(cursorStyle[0] && !ps_global->VAR_CURSOR_STYLE
       || strucmp(ps_global->VAR_CURSOR_STYLE, cursorStyle))
      set_variable(V_CURSOR_STYLE, cursorStyle, 1, 0,
		   ps_global->ew_for_except_vars);

    /* Get new window size.  Compare to old.  The window may have just
     * moved, in which case we don't bother updating the size. */
    mswin_getscreensize(&newRows, &newCols);
    if (newRows == ttyo->screen_rows && newCols == ttyo->screen_cols)
	    return (NO_OP_COMMAND);

    /* True resize. */
    ttyo->screen_rows = newRows;
    ttyo->screen_cols = newCols;

    if (ttyo->screen_rows > MAX_SCREEN_ROWS)
	ttyo->screen_rows = MAX_SCREEN_ROWS;
    if (ttyo->screen_cols > MAX_SCREEN_COLS)
	ttyo->screen_cols = MAX_SCREEN_COLS;

    return(KEY_RESIZE);
}
コード例 #23
0
ファイル: termin.gen.c プロジェクト: RsrchBoy/dpkg-alpine
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);
}
コード例 #24
0
ファイル: dispfilt.c プロジェクト: RsrchBoy/dpkg-alpine
/*
 * dfilter - pipe the data from the given storage object thru the
 *	     global display filter and into whatever the putchar's
 *	     function points to.
 *
 *	     Input is assumed to be UTF-8.
 *	     That's converted to user's locale and passed to rawcmd.
 *	     That's converted back to UTF-8 and passed through aux_filters.
 */
char *
dfilter(char *rawcmd, STORE_S *input_so, gf_io_t output_pc, FILTLIST_S *aux_filters)
{
    char *status = NULL, *cmd, *resultf = NULL, *tmpfile = NULL;
    int   key = 0, silent = 0;

    if((cmd = expand_filter_tokens(rawcmd,NULL,&tmpfile,&resultf,NULL,&key,NULL, &silent)) != NULL){
	suspend_busy_cue();
#ifndef	_WINDOWS
	if(!silent){
	  ps_global->mangled_screen = 1;
	  ClearScreen();
	}
	fflush(stdout);
#endif

	/*
	 * If it was requested that the interaction take place via
	 * a tmpfile, fill it with text from our input_so, and let
	 * system_pipe handle the rest.  Session key and tmp file
	 * mode support additions based loosely on a patch 
	 * supplied by Thomas Stroesslin <*****@*****.**>
	 */
	if(tmpfile){
	    PIPE_S	  *filter_pipe;
	    FILE          *fp;
	    gf_io_t	   gc, pc;
	    STORE_S       *tmpf_so;

	    /* write the tmp file */
	    so_seek(input_so, 0L, 0);
	    if((tmpf_so = so_get(FileStar, tmpfile, WRITE_ACCESS|OWNER_ONLY|WRITE_TO_LOCALE)) != NULL){
	        if(key){
		    so_puts(tmpf_so, filter_session_key());
                    so_puts(tmpf_so, NEWLINE);
		}
	        /* copy input to tmp file */
		gf_set_so_readc(&gc, input_so);
		gf_set_so_writec(&pc, tmpf_so);
		gf_filter_init();
		status = gf_pipe(gc, pc);
		gf_clear_so_readc(input_so);
		gf_clear_so_writec(tmpf_so);
		if(so_give(&tmpf_so) != 0 && status == NULL)
		  status = error_description(errno);

		/* prepare the terminal in case the filter uses it */
		if(status == NULL){
		    if((filter_pipe = open_system_pipe(cmd, NULL, NULL,
						PIPE_USER | (silent ? PIPE_SILENT : 
						(F_ON(F_DISABLE_TERM_RESET_DISP, ps_global) ? 0 : PIPE_RESET)),
						      0, pipe_callback, NULL)) != NULL){
			if(close_system_pipe(&filter_pipe, NULL, pipe_callback) == 0){
			    /* pull result out of tmp file */
			    if((fp = our_fopen(tmpfile, "rb")) != NULL){
				gf_set_readc(&gc, fp, 0L, FileStar, READ_FROM_LOCALE);
				gf_filter_init();
				if(aux_filters)
				  for( ; aux_filters->filter; aux_filters++)
				    gf_link_filter(aux_filters->filter,
						   aux_filters->data);

				status = gf_pipe(gc, output_pc);
				fclose(fp);
			    }
			    else
			      status = "Can't read result of display filter";
			}
			else
			  status = "Filter command returned error.";
		    }
		    else
		      status = "Can't open pipe for display filter";
		}

		our_unlink(tmpfile);
	    }
	    else
	      status = "Can't open display filter tmp file";
	}
	else if((status = gf_filter(cmd, key ? filter_session_key() : NULL,
				   input_so, output_pc, aux_filters, silent,
				   F_ON(F_DISABLE_TERM_RESET_DISP, ps_global),
				   pipe_callback)) != NULL){
	    unsigned long ch;

	    fprintf(stdout,"\r\n%s  Hit return to continue.", status);
	    fflush(stdout);
	    while((ch = read_char(300)) != ctrl('M') && ch != NO_OP_IDLE)
	      putchar(BELL);
	}

	if(resultf){
	    if(name_file_size(resultf) > 0L)
	      display_output_file(resultf, "Filter", NULL, DOF_BRIEF);

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

	resume_busy_cue(0);
#ifndef	_WINDOWS
	if(!silent)
	  ClearScreen();
#endif
	fs_give((void **)&cmd);
    }

    return(status);
}