3118 lines · 72.8 KB · C
RawDownload
/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved	by Bram Moolenaar * * Do ":help uganda"  in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. * See README.txt for an overview of the Vim source code. */ /* * ui.c: functions that handle the user interface. * 1. Keyboard input stuff, and a bit of windowing stuff.  These are called *    before the machine specific stuff (mch_*) so that we can call the GUI *    stuff instead if the GUI is running. * 2. Clipboard stuff. * 3. Input buffer stuff. */ #include "vim.h"     voidui_write(s, len)    char_u  *s;    int	    len;{#ifdef FEAT_GUI    if (gui.in_use && !gui.dying && !gui.starting)    {	gui_write(s, len);	if (p_wd)	    gui_wait_for_chars(p_wd);	return;    }#endif#ifndef NO_CONSOLE    /* Don't output anything in silent mode ("ex -s") unless 'verbose' set */    if (!(silent_mode && p_verbose == 0))    {#ifdef FEAT_MBYTE	char_u	*tofree = NULL; 	if (output_conv.vc_type != CONV_NONE)	{	    /* Convert characters from 'encoding' to 'termencoding'. */	    tofree = string_convert(&output_conv, s, &len);	    if (tofree != NULL)		s = tofree;	}#endif 	mch_write(s, len); #ifdef FEAT_MBYTE	if (output_conv.vc_type != CONV_NONE)	    vim_free(tofree);#endif    }#endif} #if defined(UNIX) || defined(VMS) || defined(PROTO)/* * When executing an external program, there may be some typed characters that * are not consumed by it.  Give them back to ui_inchar() and they are stored * here for the next call. */static char_u *ta_str = NULL;static int ta_off;	/* offset for next char to use when ta_str != NULL */static int ta_len;	/* length of ta_str when it's not NULL*/     voidui_inchar_undo(s, len)    char_u	*s;    int		len;{    char_u  *new;    int	    newlen;     newlen = len;    if (ta_str != NULL)	newlen += ta_len - ta_off;    new = alloc(newlen);    if (new != NULL)    {	if (ta_str != NULL)	{	    mch_memmove(new, ta_str + ta_off, (size_t)(ta_len - ta_off));	    mch_memmove(new + ta_len - ta_off, s, (size_t)len);	    vim_free(ta_str);	}	else	    mch_memmove(new, s, (size_t)len);	ta_str = new;	ta_len = newlen;	ta_off = 0;    }}#endif /* * ui_inchar(): low level input funcion. * Get characters from the keyboard. * Return the number of characters that are available. * If "wtime" == 0 do not wait for characters. * If "wtime" == -1 wait forever for characters. * If "wtime" > 0 wait "wtime" milliseconds for a character. * * "tb_change_cnt" is the value of typebuf.tb_change_cnt if "buf" points into * it.  When typebuf.tb_change_cnt changes (e.g., when a message is received * from a remote client) "buf" can no longer be used.  "tb_change_cnt" is NULL * otherwise. */    intui_inchar(buf, maxlen, wtime, tb_change_cnt)    char_u	*buf;    int		maxlen;    long	wtime;	    /* don't use "time", MIPS cannot handle it */    int		tb_change_cnt;{    int		retval = 0; #if defined(FEAT_GUI) && (defined(UNIX) || defined(VMS))    /*     * Use the typeahead if there is any.     */    if (ta_str != NULL)    {	if (maxlen >= ta_len - ta_off)	{	    mch_memmove(buf, ta_str + ta_off, (size_t)ta_len);	    vim_free(ta_str);	    ta_str = NULL;	    return ta_len;	}	mch_memmove(buf, ta_str + ta_off, (size_t)maxlen);	ta_off += maxlen;	return maxlen;    }#endif #ifdef FEAT_PROFILE    if (do_profiling == PROF_YES && wtime != 0)	prof_inchar_enter();#endif #ifdef NO_CONSOLE_INPUT    /* Don't wait for character input when the window hasn't been opened yet.     * Do try reading, this works when redirecting stdin from a file.     * Must return something, otherwise we'll loop forever.  If we run into     * this very often we probably got stuck, exit Vim. */    if (no_console_input())    {	static int count = 0; # ifndef NO_CONSOLE	retval = mch_inchar(buf, maxlen, (wtime >= 0 && wtime < 10)						? 10L : wtime, tb_change_cnt);	if (retval > 0 || typebuf_changed(tb_change_cnt) || wtime >= 0)	    goto theend;# endif	if (wtime == -1 && ++count == 1000)	    read_error_exit();	buf[0] = CAR;	retval = 1;	goto theend;    }#endif     /* If we are going to wait for some time or block... */    if (wtime == -1 || wtime > 100L)    {	/* ... allow signals to kill us. */	(void)vim_handle_signal(SIGNAL_UNBLOCK); 	/* ... there is no need for CTRL-C to interrupt something, don't let	 * it set got_int when it was mapped. */	if (mapped_ctrl_c)	    ctrl_c_interrupts = FALSE;    } #ifdef FEAT_GUI    if (gui.in_use)    {	if (gui_wait_for_chars(wtime) && !typebuf_changed(tb_change_cnt))	    retval = read_from_input_buf(buf, (long)maxlen);    }#endif#ifndef NO_CONSOLE# ifdef FEAT_GUI    else# endif    {	retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt);    }#endif     if (wtime == -1 || wtime > 100L)	/* block SIGHUP et al. */	(void)vim_handle_signal(SIGNAL_BLOCK);     ctrl_c_interrupts = TRUE; #ifdef NO_CONSOLE_INPUTtheend:#endif#ifdef FEAT_PROFILE    if (do_profiling == PROF_YES && wtime != 0)	prof_inchar_exit();#endif    return retval;} /* * return non-zero if a character is available */    intui_char_avail(){#ifdef FEAT_GUI    if (gui.in_use)    {	gui_mch_update();	return input_available();    }#endif#ifndef NO_CONSOLE# ifdef NO_CONSOLE_INPUT    if (no_console_input())	return 0;# endif    return mch_char_avail();#else    return 0;#endif} /* * Delay for the given number of milliseconds.	If ignoreinput is FALSE then we * cancel the delay if a key is hit. */    voidui_delay(msec, ignoreinput)    long	msec;    int		ignoreinput;{#ifdef FEAT_GUI    if (gui.in_use && !ignoreinput)	gui_wait_for_chars(msec);    else#endif	mch_delay(msec, ignoreinput);} /* * If the machine has job control, use it to suspend the program, * otherwise fake it by starting a new shell. * When running the GUI iconify the window. */    voidui_suspend(){#ifdef FEAT_GUI    if (gui.in_use)    {	gui_mch_iconify();	return;    }#endif    mch_suspend();} #if !defined(UNIX) || !defined(SIGTSTP) || defined(PROTO) || defined(__BEOS__)/* * When the OS can't really suspend, call this function to start a shell. * This is never called in the GUI. */    voidsuspend_shell(){    if (*p_sh == NUL)	EMSG(_(e_shellempty));    else    {	MSG_PUTS(_("new shell started\n"));	do_shell(NULL, 0);    }}#endif /* * Try to get the current Vim shell size.  Put the result in Rows and Columns. * Use the new sizes as defaults for 'columns' and 'lines'. * Return OK when size could be determined, FAIL otherwise. */    intui_get_shellsize(){    int	    retval; #ifdef FEAT_GUI    if (gui.in_use)	retval = gui_get_shellsize();    else#endif	retval = mch_get_shellsize();     check_shellsize();     /* adjust the default for 'lines' and 'columns' */    if (retval == OK)    {	set_number_default("lines", Rows);	set_number_default("columns", Columns);    }    return retval;} /* * Set the size of the Vim shell according to Rows and Columns, if possible. * The gui_set_shellsize() or mch_set_shellsize() function will try to set the * new size.  If this is not possible, it will adjust Rows and Columns. *//*ARGSUSED*/    voidui_set_shellsize(mustset)    int		mustset;	/* set by the user */{#ifdef FEAT_GUI    if (gui.in_use)	gui_set_shellsize(mustset,# ifdef WIN3264		TRUE# else		FALSE# endif		, RESIZE_BOTH);    else#endif	mch_set_shellsize();} /* * Called when Rows and/or Columns changed.  Adjust scroll region and mouse * region. */    voidui_new_shellsize(){    if (full_screen && !exiting)    {#ifdef FEAT_GUI	if (gui.in_use)	    gui_new_shellsize();	else#endif	    mch_new_shellsize();    }}     voidui_breakcheck(){#ifdef FEAT_GUI    if (gui.in_use)	gui_mch_update();    else#endif	mch_breakcheck();} /***************************************************************************** * Functions for copying and pasting text between applications. * This is always included in a GUI version, but may also be included when the * clipboard and mouse is available to a terminal version such as xterm. * Note: there are some more functions in ops.c that handle selection stuff. * * Also note that the majority of functions here deal with the X 'primary' * (visible - for Visual mode use) selection, and only that. There are no * versions of these for the 'clipboard' selection, as Visual mode has no use * for them. */ #if defined(FEAT_CLIPBOARD) || defined(PROTO) /* * Selection stuff using Visual mode, for cutting and pasting text to other * windows. */ /* * Call this to initialise the clipboard.  Pass it FALSE if the clipboard code * is included, but the clipboard can not be used, or TRUE if the clipboard can * be used.  Eg unix may call this with FALSE, then call it again with TRUE if * the GUI starts. */    voidclip_init(can_use)    int	    can_use;{    VimClipboard *cb;     cb = &clip_star;    for (;;)    {	cb->available  = can_use;	cb->owned      = FALSE;	cb->start.lnum = 0;	cb->start.col  = 0;	cb->end.lnum   = 0;	cb->end.col    = 0;	cb->state      = SELECT_CLEARED; 	if (cb == &clip_plus)	    break;	cb = &clip_plus;    }} /* * Check whether the VIsual area has changed, and if so try to become the owner * of the selection, and free any old converted selection we may still have * lying around.  If the VIsual mode has ended, make a copy of what was * selected so we can still give it to others.	Will probably have to make sure * this is called whenever VIsual mode is ended. */    voidclip_update_selection(){    pos_T    start, end;     /* If visual mode is only due to a redo command ("."), then ignore it */    if (!redo_VIsual_busy && VIsual_active && (State & NORMAL))    {	if (lt(VIsual, curwin->w_cursor))	{	    start = VIsual;	    end = curwin->w_cursor;#ifdef FEAT_MBYTE	    if (has_mbyte)		end.col += (*mb_ptr2len)(ml_get_cursor()) - 1;#endif	}	else	{	    start = curwin->w_cursor;	    end = VIsual;	}	if (!equalpos(clip_star.start, start)		|| !equalpos(clip_star.end, end)		|| clip_star.vmode != VIsual_mode)	{	    clip_clear_selection();	    clip_star.start = start;	    clip_star.end = end;	    clip_star.vmode = VIsual_mode;	    clip_free_selection(&clip_star);	    clip_own_selection(&clip_star);	    clip_gen_set_selection(&clip_star);	}    }}     voidclip_own_selection(cbd)    VimClipboard	*cbd;{    /*     * Also want to check somehow that we are reading from the keyboard rather     * than a mapping etc.     */    if (!cbd->owned && cbd->available)    {	cbd->owned = (clip_gen_own_selection(cbd) == OK);#ifdef FEAT_X11	if (cbd == &clip_star)	{	    /* May have to show a different kind of highlighting for the	     * selected area.  There is no specific redraw command for this,	     * just redraw all windows on the current buffer. */	    if (cbd->owned		    && (get_real_state() == VISUAL					    || get_real_state() == SELECTMODE)		    && clip_isautosel()		    && hl_attr(HLF_V) != hl_attr(HLF_VNC))		redraw_curbuf_later(INVERTED_ALL);	}#endif    }}     voidclip_lose_selection(cbd)    VimClipboard	*cbd;{#ifdef FEAT_X11    int	    was_owned = cbd->owned;#endif    int     visual_selection = (cbd == &clip_star);     clip_free_selection(cbd);

Lines 1–500 of 3118.