Ejemplo n.º 1
0
int
main(int argc, char *argv[])
#endif
{
    UCS      c;
    register int    f;
    register int    n;
    register BUFFER *bp;
    int	     viewflag = FALSE;		/* are we starting in view mode?*/
    int	     starton = 0;		/* where's dot to begin with?	*/
    int      setlocale_collate = 1;
    char     bname[NBUFN];		/* buffer name of file to read	*/
    char    *file_to_edit = NULL;
    char    *display_charmap = NULL, *dc;
    char    *keyboard_charmap = NULL;
    int      use_system = 0;
    char    *err = NULL;

    set_input_timeout(600);
    Pmaster = NULL;     		/* turn OFF composer functionality */
    km_popped = 0;

    /*
     * Read command line flags before initializing, otherwise, we never
     * know to init for f_keys...
     */
    file_to_edit = pico_args(argc, argv, &starton, &viewflag, &setlocale_collate);

    set_collation(setlocale_collate, 1);

#define cpstr(s) strcpy((char *)fs_get(1+strlen(s)), s)

#ifdef	_WINDOWS	
    init_utf8_display(1, NULL);
#else	/* UNIX */


    if(display_character_set)
      display_charmap = cpstr(display_character_set);
#if   HAVE_LANGINFO_H && defined(CODESET)
    else if((dc = nl_langinfo_codeset_wrapper()) != NULL)
      display_charmap = cpstr(dc);
#endif

    if(!display_charmap)
      display_charmap = cpstr("US-ASCII");

    if(keyboard_character_set)
      keyboard_charmap = cpstr(keyboard_character_set);
    else
      keyboard_charmap = cpstr(display_charmap);


    if(use_system_translation){
#if	PREREQ_FOR_SYS_TRANSLATION
	use_system++;
	/* This modifies its arguments */
	if(setup_for_input_output(use_system, &display_charmap, &keyboard_charmap,
				  &input_cs, &err) == -1){
	    fprintf(stderr, "%s\n", err ? err : "trouble with character set");
	    exit(1);
	}
	else if(err){
	    fprintf(stderr, "%s\n", err);
	    fs_give((void **) &err);
	}
#endif
    }

    if(!use_system){
	if(setup_for_input_output(use_system, &display_charmap, &keyboard_charmap,
				  &input_cs, &err) == -1){
	    fprintf(stderr, "%s\n", err ? err : "trouble with character set");
	    exit(1);
	}
	else if(err){
	    fprintf(stderr, "%s\n", err);
	    fs_give((void **) &err);
	}
    }

    if(keyboard_charmap){
	set_locale_charmap(keyboard_charmap);
	free((void *) keyboard_charmap);
    }

    if(display_charmap)
      free((void *) display_charmap);

#endif	/* UNIX */

    /*
     * There are a couple arguments that we need to be sure
     * are converted for internal use.
     */
    if(alt_speller)
      alt_speller = cpstr(fname_to_utf8(alt_speller));

    if(opertree && opertree[0]){
	strncpy(opertree, fname_to_utf8(opertree), sizeof(opertree));
	opertree[sizeof(opertree)-1] = '\0';
    }

    if(glo_quote_str_orig)
      glo_quote_str = utf8_to_ucs4_cpystr(fname_to_utf8(glo_quote_str_orig));

    if(glo_wordseps_orig)
      glo_wordseps = utf8_to_ucs4_cpystr(fname_to_utf8(glo_wordseps_orig));

    if(file_to_edit)
      file_to_edit = cpstr(fname_to_utf8(file_to_edit));

#undef cpstr

#if	defined(DOS) || defined(OS2)
    if(file_to_edit){			/* strip quotes? */
	int   l;

	if(strchr("'\"", file_to_edit[0])
	   && (l = strlen(file_to_edit)) > 1
	   && file_to_edit[l-1] == file_to_edit[0]){
	    file_to_edit[l-1] = '\0';	/* blat trailing quote */
	    file_to_edit++;		/* advance past leading quote */
	}
    }
#endif

    if(!vtinit())			/* Displays.            */
	exit(1);

    strncpy(bname, "main", sizeof(bname));		/* default buffer name */
    bname[sizeof(bname)-1] = '\0';
    edinit(bname);			/* Buffers, windows.   */

    update();				/* let the user know we are here */

#ifdef	_WINDOWS
    mswin_setwindow(NULL, NULL, NULL, NULL, NULL, NULL);
    mswin_showwindow();
    mswin_showcaret(1);			/* turn on for main window */
    mswin_allowpaste(MSWIN_PASTE_FULL);
    mswin_setclosetext("Use the ^X command to exit Pico.");
    mswin_setscrollcallback (pico_scroll_callback);
#endif

#if	defined(USE_TERMCAP) || defined(USE_TERMINFO) || defined(VMS)
    if(kbesc == NULL){			/* will arrow keys work ? */
	(*term.t_putchar)('\007');
	emlwrite("Warning: keypad keys may be non-functional", NULL);
    }
#endif	/* USE_TERMCAP/USE_TERMINFO/VMS */

    if(file_to_edit){			/* Any file to edit? */

	makename(bname, file_to_edit);	/* set up a buffer for this file */

	bp = curbp;			/* read in first file */
	makename(bname, file_to_edit);
	strncpy(bp->b_bname, bname, sizeof(bp->b_bname));
	bp->b_bname[sizeof(bp->b_bname)-1] = '\0';

	if(strlen(file_to_edit) >= NFILEN){
	    char buf[128];

	    snprintf(buf, sizeof(buf), "Filename \"%.10s...\" too long", file_to_edit);
	    emlwrite(buf, NULL);
	    file_to_edit = NULL;
	}
	else{
	    strncpy(bp->b_fname, file_to_edit, sizeof(bp->b_fname));
	    bp->b_fname[sizeof(bp->b_fname)-1] = '\0';
	    if (((gmode&MDTREE) && !in_oper_tree(file_to_edit)) ||
		readin(file_to_edit, (viewflag==FALSE), TRUE) == ABORT) {
		if ((gmode&MDTREE) && !in_oper_tree(file_to_edit)){
		    EML eml;
		    eml.s = opertree;
		    emlwrite(_("Can't read file from outside of %s"), &eml);
		}

		file_to_edit = NULL;
	    }
	}

	if(!file_to_edit){
	    strncpy(bp->b_bname, "main", sizeof(bp->b_bname));
	    bp->b_bname[sizeof(bp->b_bname)-1] = '\0';
	    strncpy(bp->b_fname, "", sizeof(bp->b_fname));
	    bp->b_fname[sizeof(bp->b_fname)-1] = '\0';
	}

	bp->b_dotp = bp->b_linep;
	bp->b_doto = 0;

	if (viewflag)			/* set the view mode */
	  bp->b_mode |= MDVIEW;
    }

    /* setup to process commands */
    lastflag = 0;			/* Fake last flags.     */
    curbp->b_mode |= gmode;		/* and set default modes*/

    curwp->w_flag |= WFMODE;		/* and force an update	*/

    if(timeoutset){
	EML eml;

	eml.s = comatose(get_input_timeout());
	emlwrite(_("Checking for new mail every %s seconds"), &eml);
    }


    forwline(0, starton - 1);		/* move dot to specified line */

    while(1){

	if(km_popped){
	    km_popped--;
	    if(km_popped == 0) /* cause bottom three lines to be repainted */
	      curwp->w_flag |= WFHARD;
	}

	if(km_popped){  /* temporarily change to cause menu to be painted */
	    term.t_mrow = 2;
	    curwp->w_ntrows -= 2;
	    curwp->w_flag |= WFMODE;
	    movecursor(term.t_nrow-2, 0); /* clear status line, too */
	    peeol();
	}

	update();			/* Fix up the screen    */
	if(km_popped){
	    term.t_mrow = 0;
	    curwp->w_ntrows += 2;
	}

#ifdef	MOUSE
#ifdef  EX_MOUSE
	/* New mouse function for real mouse text seletion. */
	register_mfunc(mouse_in_pico, 2, 0, term.t_nrow - (term.t_mrow + 1),
		       term.t_ncol);
#else
	mouse_in_content(KEY_MOUSE, -1, -1, 0, 0);
	register_mfunc(mouse_in_content, 2, 0, term.t_nrow - (term.t_mrow + 1),
		       term.t_ncol);
#endif
#endif
#ifdef	_WINDOWS
	mswin_setdndcallback (pico_file_drop);
	mswin_mousetrackcallback(pico_cursor);
#endif
	c = GetKey();
#ifdef	MOUSE
#ifdef  EX_MOUSE
	clear_mfunc(mouse_in_pico);
#else
	clear_mfunc(mouse_in_content);
#endif
#endif
#ifdef	_WINDOWS
	mswin_cleardndcallback ();
	mswin_mousetrackcallback(NULL);
#endif

	if(timeoutset && (c == NODATA || time_to_check())){
	    if(pico_new_mail())
	      emlwrite(_("You may possibly have new mail."), NULL);
	}

	if(km_popped)
	  switch(c){
	    case NODATA:
	    case (CTRL|'L'):
	      km_popped++;
	      break;
	    
	    default:
	      /* clear bottom three lines */
	      mlerase();
	      break;
	  }

	if(c == NODATA)
	  continue;

	if(mpresf){			/* erase message line? */
	    if(mpresf++ > MESSDELAY)
	      mlerase();
	}

	f = FALSE;
	n = 1;

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

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

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

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


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

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

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

    flush_ordered_messages();
    mark_status_dirty();

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

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

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

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

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

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

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

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

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

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

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

	setbitn(OE_CTRL_T_KEY, bitmap);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    while(return_v == -10) {

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

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

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

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

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

	switch(ucs){

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	    break;

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

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

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

            break;

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

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

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

		shift = ucs4_strlen(kb);

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

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

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

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

	    goto cancel;

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

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

		string[i] = 0;
	    }

	    break;

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

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

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

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

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

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

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

	    break;


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

	      mouse_get_last (NULL, &mp);

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

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

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

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

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

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

		case M_BUTTON_RIGHT :
#ifdef	_WINDOWS

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

		  mp.col -= dline.col;

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

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

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

		  line_paint(field_pos, &dline, &passwd);

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

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

	    break;
#endif


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

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

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

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

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

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

            fflush(stdout);

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

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

		if(return_v != -10)
		  break;
	    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return(return_v);
}
Ejemplo n.º 3
0
Archivo: pico.c Proyecto: ctubio/alpine
/*
 * pico - the main routine for Pine's composer.
 *
 */
int
pico(PICO *pm)
{
    UCS      c;
    register int    f;
    register int    n;
    char     bname[NBUFN];		/* buffer name of file to read */
    extern   struct on_display ods;
    int      checkpointcnt = 0, input = 0;
    int      ret;
    char     chkptfile[NLINE];
#ifdef	_WINDOWS
    int      cursor_shown;
#endif

    Pmaster       = pm;
    gmode	  = MDWRAP;
    gmode        |= pm->pine_flags;	/* high 4 bits rsv'd for pine */

    alt_speller   = pm->alt_spell;
    pico_all_done = 0;
    km_popped     = 0;

    if(!vtinit())			/* Init Displays.      */
      return(COMP_CANCEL);

    strncpy(bname, "main", sizeof(bname));		/* default buffer name */
    bname[sizeof(bname)-1] = '\0';
    edinit(bname);			/* Buffers, windows.   */

    if(InitMailHeader(pm))		/* init mail header structure */
      gmode &= ~(P_BODY | P_HEADEND);	/* flip off special header stuff */

    /* setup to process commands */
    lastflag = 0;			/* Fake last flags.     */
    curbp->b_mode |= gmode;		/* and set default modes*/

    if(Pmaster->pine_anchor)
      pico_anchor = utf8_to_ucs4_cpystr(Pmaster->pine_anchor);
    else
      pico_anchor = NULL;

    if(Pmaster->quote_str)
      glo_quote_str = utf8_to_ucs4_cpystr(Pmaster->quote_str);
    else
      glo_quote_str = NULL;

    if(Pmaster->wordseps)
      glo_wordseps = ucs4_cpystr(Pmaster->wordseps);
    else
      glo_wordseps = NULL;

    bindtokey(DEL, (gmode & P_DELRUBS) ? forwdel : backdel);

    if(pm->msgtext)
      breplace(pm->msgtext);

#ifdef	_WINDOWS
    cursor_shown = mswin_showcaret(1);	/* turn on for main window */
    mswin_allowpaste(MSWIN_PASTE_FULL);
    mswin_setscrollcallback (pico_scroll_callback);
#endif

    /* prepare for checkpointing */
    chkptfile[0] = '\0';
    chkptinit((*Pmaster->ckptdir)(chkptfile, sizeof(chkptfile)), sizeof(chkptfile));
    if(gmode & P_CHKPTNOW)
      writeout(chkptfile, TRUE);

    pico_all_done = setjmp(finstate);	/* jump out of HUP handler ? */

    if(gmode & MDALTNOW){
	while(!pico_all_done){
	    if(((gmode & P_BODY) || !Pmaster->headents)
	       && alt_editor(0, 1) < 0)
	      break;			/* if problem, drop into pico */

	    if(Pmaster->headents){
		update();		/* paint screen, n' start editing... */
		HeaderEditor((gmode & (P_HEADEND | P_BODY)) ? 2 : 0, 0);
		gmode |= P_BODY;	/* make sure we enter alt ed next */
	    }
	    else
	      pico_all_done = COMP_EXIT;
	}
    }
    else if(!pico_all_done){
	if(gmode & P_BODY){		/* begin editing the header? */
	    ArrangeHeader();		/* line up pointers */
	    /*
	     * Move to the offset pine asked us to move to.
	     * Perhaps we should be checking to see if this is
	     * a reasonable number before moving.
	     */
	    if(Pmaster && Pmaster->edit_offset)
	      forwchar(FALSE, Pmaster->edit_offset);
	}
	else{
	    update();			/* paint screen, */
	    HeaderEditor((gmode & P_HEADEND) ? 2 : 0, 0);
	}
    }

    while(1){
	if(pico_all_done){
#ifdef	_WINDOWS
	    if(!cursor_shown)
	      mswin_showcaret(0);

	    mswin_allowpaste(MSWIN_PASTE_DISABLE);
	    mswin_setscrollcallback (NULL);
#endif
	    ret = anycb() ? BUF_CHANGED : 0;
	    switch(pico_all_done){	/* prepare for/handle final events */
	      case COMP_EXIT :		/* already confirmed */
		packheader();
		if(Pmaster 
		   && (Pmaster->strip_ws_before_send
		       || Pmaster->allow_flowed_text))
		  cleanwhitespace();
		ret |= COMP_EXIT;
		break;

	      case COMP_CANCEL :	/* also already confirmed */
		packheader();
		ret = COMP_CANCEL;
		break;

	      case COMP_GOTHUP:
		/* 
		 * pack up and let caller know that we've received a SIGHUP
		 */
		if(ComposerEditing)		/* expand addr if needed */
		  call_builder(&headents[ods.cur_e], NULL, NULL);

		packheader();
		ret |= COMP_GOTHUP;
		break;

	      case COMP_SUSPEND :
	      default:			/* safest if internal error */
		/*
		 * If we're in the headers mark the current header line
		 * with start_here bit so caller knows where to reset.
		 * Also set the edit_offset, which is either the offset
		 * into this header line or the offset into the body.
		 * Packheader will adjust edit_offset for multi-line
		 * headers.
		 */
		if(ComposerEditing){		/* in the headers */
		    headents[ods.cur_e].start_here = 1;
		    Pmaster->edit_offset = ods.p_ind;
		}
		else{
		    register LINE *clp;
		    register long  offset;

		    for(clp = lforw(curbp->b_linep), offset = 0L;
			clp != curwp->w_dotp;
			clp = lforw(clp))
		      offset += (llength(clp) + 1);

		    Pmaster->edit_offset = offset + curwp->w_doto;
		}

		packheader();
		ret |= COMP_SUSPEND;
		break;
	    }

	    if(pico_anchor)
	      fs_give((void **) &pico_anchor);
	    if(glo_quote_str)
	      fs_give((void **) &glo_quote_str);
	    if(glo_wordseps)
	      fs_give((void **) &glo_wordseps);

	    vttidy();			/* clean up tty modes */
	    zotdisplay();		/* blast display buffers */
	    zotedit();
	    our_unlink(chkptfile);
	    Pmaster = NULL;		/* blat global */

	    return(ret);
	}

	if(km_popped){
	    km_popped--;
	    if(km_popped == 0) /* cause bottom three lines to be repainted */
	      curwp->w_flag |= WFHARD;
	}

	if(km_popped){  /* temporarily change to cause menu to be painted */
	    term.t_mrow = 2;
	    curwp->w_ntrows -= 2;
	    curwp->w_flag |= WFMODE;
	    movecursor(term.t_nrow-2, 0); /* clear status line, too */
	    peeol();
	}

	update();			/* Fix up the screen    */
	if(km_popped){
	    term.t_mrow = 0;
	    curwp->w_ntrows += 2;
	}

#ifdef	MOUSE
#ifdef  EX_MOUSE
	/* New mouse function for real mouse text seletion. */
	register_mfunc(mouse_in_pico, 2, 0, term.t_nrow - (term.t_mrow+1),
		       term.t_ncol);
#else
	mouse_in_content(KEY_MOUSE, -1, -1, -1, 0);
	register_mfunc(mouse_in_content, 2, 0, term.t_nrow - (term.t_mrow + 1),
		       term.t_ncol);
#endif
#endif
#ifdef	_WINDOWS
	mswin_setdndcallback (composer_file_drop);
	mswin_mousetrackcallback(pico_cursor);
#endif
	c = GetKey();
        if (term.t_nrow < 6 && c != NODATA){
            (*term.t_beep)();
            emlwrite(_("Please make the screen bigger."), NULL);
            continue;
        }

#ifdef	MOUSE
#ifdef  EX_MOUSE
	clear_mfunc(mouse_in_pico);
#else
	clear_mfunc(mouse_in_content);
#endif
#endif
#ifdef	_WINDOWS
	mswin_cleardndcallback ();
	mswin_mousetrackcallback(NULL);
#endif
	if(c == NODATA || time_to_check()){	/* new mail ? */
	    if((*Pmaster->newmail)(c == NODATA ? 0 : 2, 1) >= 0){
		int rv;

		if(km_popped){
		    term.t_mrow = 2;
		    curwp->w_ntrows -= 2;
		    curwp->w_flag |= WFHARD;
		    km_popped = 0;
		}

		clearcursor();
		mlerase();
		rv = (*Pmaster->showmsg)(c);
		ttresize();
		picosigs();	/* restore altered handlers */
		if(rv)		/* Did showmsg corrupt the display? */
		  PaintBody(0);	/* Yes, repaint */

		mpresf = 1;
		input = 0;
	    }

	    clearcursor();
	    movecursor(0, 0);
	}

	if(km_popped)
	  switch(c){
	    case NODATA:
	    case (CTRL|'L'):
	      km_popped++;
	      break;
	    
	    default:
	      mlerase();
	      break;
	  }

	if(c == NODATA)		/* no op, getkey timed out */
	  continue;
	else if(!input++)
	  (*Pmaster->keybinput)();

	if (mpresf != FALSE) {		/* message stay around only  */
	    if (mpresf++ > NMMESSDELAY)	/* so long! */
	      mlerase();
	}

	f = FALSE;			/* vestigial */
	n = 1;
					/* Do it.               */
	execute(normalize_cmd(c, pfkm, 2), f, n);
	if(++checkpointcnt >= CHKPTDELAY){
	    checkpointcnt = 0;
	    writeout(chkptfile, TRUE);
	}
    }
}