5948 lines · 137.5 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. */ /* * misc2.c: Various functions. */#include "vim.h" #ifdef HAVE_FCNTL_H# include <fcntl.h>	    /* for chdir() */#endif static char_u	*username = NULL; /* cached result of mch_get_user_name() */ static char_u	*ff_expand_buffer = NULL; /* used for expanding filenames */ #if defined(FEAT_VIRTUALEDIT) || defined(PROTO)static int coladvance2 __ARGS((pos_T *pos, int addspaces, int finetune, colnr_T wcol)); /* * Return TRUE if in the current mode we need to use virtual. */    intvirtual_active(){    /* While an operator is being executed we return "virtual_op", because     * VIsual_active has already been reset, thus we can't check for "block"     * being used. */    if (virtual_op != MAYBE)	return virtual_op;    return (ve_flags == VE_ALL# ifdef FEAT_VISUAL	    || ((ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V)# endif	    || ((ve_flags & VE_INSERT) && (State & INSERT)));} /* * Get the screen position of the cursor. */    intgetviscol(){    colnr_T	x;     getvvcol(curwin, &curwin->w_cursor, &x, NULL, NULL);    return (int)x;} /* * Get the screen position of character col with a coladd in the cursor line. */    intgetviscol2(col, coladd)    colnr_T	col;    colnr_T	coladd;{    colnr_T	x;    pos_T	pos;     pos.lnum = curwin->w_cursor.lnum;    pos.col = col;    pos.coladd = coladd;    getvvcol(curwin, &pos, &x, NULL, NULL);    return (int)x;} /* * Go to column "wcol", and add/insert white space as necessary to get the * cursor in that column. * The caller must have saved the cursor line for undo! */    intcoladvance_force(wcol)    colnr_T wcol;{    int rc = coladvance2(&curwin->w_cursor, TRUE, FALSE, wcol);     if (wcol == MAXCOL)	curwin->w_valid &= ~VALID_VIRTCOL;    else    {	/* Virtcol is valid */	curwin->w_valid |= VALID_VIRTCOL;	curwin->w_virtcol = wcol;    }    return rc;}#endif /* * Try to advance the Cursor to the specified screen column. * If virtual editing: fine tune the cursor position. * Note that all virtual positions off the end of a line should share * a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)), * beginning at coladd 0. * * return OK if desired column is reached, FAIL if not */    intcoladvance(wcol)    colnr_T	wcol;{    int rc = getvpos(&curwin->w_cursor, wcol);     if (wcol == MAXCOL || rc == FAIL)	curwin->w_valid &= ~VALID_VIRTCOL;    else if (*ml_get_cursor() != TAB)    {	/* Virtcol is valid when not on a TAB */	curwin->w_valid |= VALID_VIRTCOL;	curwin->w_virtcol = wcol;    }    return rc;} /* * Return in "pos" the position of the cursor advanced to screen column "wcol". * return OK if desired column is reached, FAIL if not */    intgetvpos(pos, wcol)    pos_T   *pos;    colnr_T wcol;{#ifdef FEAT_VIRTUALEDIT    return coladvance2(pos, FALSE, virtual_active(), wcol);}     static intcoladvance2(pos, addspaces, finetune, wcol)    pos_T	*pos;    int		addspaces;	/* change the text to achieve our goal? */    int		finetune;	/* change char offset for the exact column */    colnr_T	wcol;		/* column to move to */{#endif    int		idx;    char_u	*ptr;    char_u	*line;    colnr_T	col = 0;    int		csize = 0;    int		one_more;#ifdef FEAT_LINEBREAK    int		head = 0;#endif     one_more = (State & INSERT)		    || restart_edit != NUL#ifdef FEAT_VISUAL		    || (VIsual_active && *p_sel != 'o')#endif#ifdef FEAT_VIRTUALEDIT		    || ((ve_flags & VE_ONEMORE) && wcol < MAXCOL)#endif		    ;    line = ml_get_curline();     if (wcol >= MAXCOL)    {	    idx = (int)STRLEN(line) - 1 + one_more;	    col = wcol; #ifdef FEAT_VIRTUALEDIT	    if ((addspaces || finetune) && !VIsual_active)	    {		curwin->w_curswant = linetabsize(line) + one_more;		if (curwin->w_curswant > 0)		    --curwin->w_curswant;	    }#endif    }    else    {#ifdef FEAT_VIRTUALEDIT	int width = W_WIDTH(curwin) - win_col_off(curwin); 	if (finetune		&& curwin->w_p_wrap# ifdef FEAT_VERTSPLIT		&& curwin->w_width != 0# endif		&& wcol >= (colnr_T)width)	{	    csize = linetabsize(line);	    if (csize > 0)		csize--; 	    if (wcol / width > (colnr_T)csize / width		    && ((State & INSERT) == 0 || (int)wcol > csize + 1))	    {		/* In case of line wrapping don't move the cursor beyond the		 * right screen edge.  In Insert mode allow going just beyond		 * the last character (like what happens when typing and		 * reaching the right window edge). */		wcol = (csize / width + 1) * width - 1;	    }	}#endif 	idx = -1;	ptr = line;	while (col <= wcol && *ptr != NUL)	{	    /* Count a tab for what it's worth (if list mode not on) */#ifdef FEAT_LINEBREAK	    csize = win_lbr_chartabsize(curwin, ptr, col, &head);	    mb_ptr_adv(ptr);#else	    csize = lbr_chartabsize_adv(&ptr, col);#endif	    col += csize;	}	idx = (int)(ptr - line);	/*	 * Handle all the special cases.  The virtual_active() check	 * is needed to ensure that a virtual position off the end of	 * a line has the correct indexing.  The one_more comparison	 * replaces an explicit add of one_more later on.	 */	if (col > wcol || (!virtual_active() && one_more == 0))	{	    idx -= 1;# ifdef FEAT_LINEBREAK	    /* Don't count the chars from 'showbreak'. */	    csize -= head;# endif	    col -= csize;	} #ifdef FEAT_VIRTUALEDIT	if (virtual_active()		&& addspaces		&& ((col != wcol && col != wcol + 1) || csize > 1))	{	    /* 'virtualedit' is set: The difference between wcol and col is	     * filled with spaces. */ 	    if (line[idx] == NUL)	    {		/* Append spaces */		int	correct = wcol - col;		char_u	*newline = alloc(idx + correct + 1);		int	t; 		if (newline == NULL)		    return FAIL; 		for (t = 0; t < idx; ++t)		    newline[t] = line[t]; 		for (t = 0; t < correct; ++t)		    newline[t + idx] = ' '; 		newline[idx + correct] = NUL; 		ml_replace(pos->lnum, newline, FALSE);		changed_bytes(pos->lnum, (colnr_T)idx);		idx += correct;		col = wcol;	    }	    else	    {		/* Break a tab */		int	linelen = (int)STRLEN(line);		int	correct = wcol - col - csize + 1; /* negative!! */		char_u	*newline;		int	t, s = 0;		int	v; 		if (-correct > csize)		    return FAIL; 		newline = alloc(linelen + csize);		if (newline == NULL)		    return FAIL; 		for (t = 0; t < linelen; t++)		{		    if (t != idx)			newline[s++] = line[t];		    else			for (v = 0; v < csize; v++)			    newline[s++] = ' ';		} 		newline[linelen + csize - 1] = NUL; 		ml_replace(pos->lnum, newline, FALSE);		changed_bytes(pos->lnum, idx);		idx += (csize - 1 + correct);		col += correct;	    }	}#endif    }     if (idx < 0)	pos->col = 0;    else	pos->col = idx; #ifdef FEAT_VIRTUALEDIT    pos->coladd = 0;     if (finetune)    {	if (wcol == MAXCOL)	{	    /* The width of the last character is used to set coladd. */	    if (!one_more)	    {		colnr_T	    scol, ecol; 		getvcol(curwin, pos, &scol, NULL, &ecol);		pos->coladd = ecol - scol;	    }	}	else	{	    int b = (int)wcol - (int)col; 	    /* The difference between wcol and col is used to set coladd. */	    if (b > 0 && b < (MAXCOL - 2 * W_WIDTH(curwin)))		pos->coladd = b; 	    col += b;	}    }#endif #ifdef FEAT_MBYTE    /* prevent cursor from moving on the trail byte */    if (has_mbyte)	mb_adjust_cursor();#endif     if (col < wcol)	return FAIL;    return OK;} /* * inc(p) * * Increment the line pointer 'p' crossing line boundaries as necessary. * Return 1 when going to the next line. * Return 2 when moving forward onto a NUL at the end of the line). * Return -1 when at the end of file. * Return 0 otherwise. */    intinc_cursor(){    return inc(&curwin->w_cursor);}     intinc(lp)    pos_T  *lp;{    char_u  *p = ml_get_pos(lp);     if (*p != NUL)	/* still within line, move to next char (may be NUL) */    {#ifdef FEAT_MBYTE	if (has_mbyte)	{	    int l = (*mb_ptr2len)(p); 	    lp->col += l;	    return ((p[l] != NUL) ? 0 : 2);	}#endif	lp->col++;#ifdef FEAT_VIRTUALEDIT	lp->coladd = 0;#endif	return ((p[1] != NUL) ? 0 : 2);    }    if (lp->lnum != curbuf->b_ml.ml_line_count)     /* there is a next line */    {	lp->col = 0;	lp->lnum++;#ifdef FEAT_VIRTUALEDIT	lp->coladd = 0;#endif	return 1;    }    return -1;} /* * incl(lp): same as inc(), but skip the NUL at the end of non-empty lines */    intincl(lp)    pos_T    *lp;{    int	    r;     if ((r = inc(lp)) >= 1 && lp->col)	r = inc(lp);    return r;} /* * dec(p) * * Decrement the line pointer 'p' crossing line boundaries as necessary. * Return 1 when crossing a line, -1 when at start of file, 0 otherwise. */    intdec_cursor(){    return dec(&curwin->w_cursor);}     intdec(lp)    pos_T  *lp;{    char_u	*p; #ifdef FEAT_VIRTUALEDIT    lp->coladd = 0;#endif    if (lp->col > 0)		/* still within line */    {	lp->col--;#ifdef FEAT_MBYTE	if (has_mbyte)	{	    p = ml_get(lp->lnum);	    lp->col -= (*mb_head_off)(p, p + lp->col);	}#endif	return 0;    }    if (lp->lnum > 1)		/* there is a prior line */    {	lp->lnum--;	p = ml_get(lp->lnum);	lp->col = (colnr_T)STRLEN(p);#ifdef FEAT_MBYTE	if (has_mbyte)	    lp->col -= (*mb_head_off)(p, p + lp->col);#endif	return 1;    }    return -1;			/* at start of file */} /* * decl(lp): same as dec(), but skip the NUL at the end of non-empty lines */    intdecl(lp)    pos_T    *lp;{    int	    r;     if ((r = dec(lp)) == 1 && lp->col)	r = dec(lp);    return r;} /* * Make sure curwin->w_cursor.lnum is valid. */    voidcheck_cursor_lnum(){    if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)    {#ifdef FEAT_FOLDING	/* If there is a closed fold at the end of the file, put the cursor in	 * its first line.  Otherwise in the last line. */	if (!hasFolding(curbuf->b_ml.ml_line_count,						&curwin->w_cursor.lnum, NULL))#endif	    curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;    }    if (curwin->w_cursor.lnum <= 0)	curwin->w_cursor.lnum = 1;} /* * Make sure curwin->w_cursor.col is valid. */    voidcheck_cursor_col(){    colnr_T len;

Lines 1–500 of 5948.