⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 misc1.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
	while (*src && (one || (*src != ',' && *src != ' ')) && --dstlen > 0)
	    *dst++ = *src++;
	/* skip separator */
	while ((*src == ' ' || *src == ',') && --dstlen > 0)
	    *dst++ = *src++;
    }
    /* if (dstlen == 0) out of space, what to do??? */

    *dst = NUL;
}

/*
 * Like home_replace, store the replaced string in allocated memory.
 * When something fails, NULL is returned.
 */
    char_u  *
home_replace_save(buf, src)
    BUF	    *buf;	    /* when not NULL, check for help files */
    char_u  *src;	    /* input file name */
{
    char_u	*dst;
    unsigned	len;

    len = 3;			/* space for "~/" and trailing NUL */
    if (src != NULL)		/* just in case */
	len += STRLEN(src);
    dst = alloc(len);
    if (dst != NULL)
	home_replace(buf, src, dst, len, TRUE);
    return dst;
}

/*
 * Compare two file names and return:
 * FPC_SAME   if they both exist and are the same file.
 * FPC_SAMEX  if they both don't exist and have the same file name.
 * FPC_DIFF   if they both exist and are different files.
 * FPC_NOTX   if they both don't exist.
 * FPC_DIFFX  if one of them doesn't exist.
 * For the first name environment variables are expanded
 */
    int
fullpathcmp(s1, s2, checkname)
    char_u *s1, *s2;
    int	    checkname;		/* when both don't exist, check file names */
{
#ifdef UNIX
    char_u	    exp1[MAXPATHL];
    char_u	    full1[MAXPATHL];
    char_u	    full2[MAXPATHL];
    struct stat	    st1, st2;
    int		    r1, r2;

    expand_env(s1, exp1, MAXPATHL);
    r1 = stat((char *)exp1, &st1);
    r2 = stat((char *)s2, &st2);
    if (r1 != 0 && r2 != 0)
    {
	/* if stat() doesn't work, may compare the names */
	if (checkname)
	{
	    if (fnamecmp(exp1, s2) == 0)
		return FPC_SAMEX;
	    r1 = mch_FullName(exp1, full1, MAXPATHL, FALSE);
	    r2 = mch_FullName(s2, full2, MAXPATHL, FALSE);
	    if (r1 == OK && r2 == OK && fnamecmp(full1, full2) == 0)
		return FPC_SAMEX;
	}
	return FPC_NOTX;
    }
    if (r1 != 0 || r2 != 0)
	return FPC_DIFFX;
    if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
	return FPC_SAME;
    return FPC_DIFF;
#else
    char_u  *exp1;		/* expanded s1 */
    char_u  *full1;		/* full path of s1 */
    char_u  *full2;		/* full path of s2 */
    int	    retval = FPC_DIFF;
    int	    r1, r2;

    /* allocate one buffer to store three paths (alloc()/free() is slow!) */
    if ((exp1 = alloc(MAXPATHL * 3)) != NULL)
    {
	full1 = exp1 + MAXPATHL;
	full2 = full1 + MAXPATHL;

	expand_env(s1, exp1, MAXPATHL);
	r1 = mch_FullName(exp1, full1, MAXPATHL, FALSE);
	r2 = mch_FullName(s2, full2, MAXPATHL, FALSE);

	/* If mch_FullName() fails, the file probably doesn't exist. */
	if (r1 != OK && r2 != OK)
	{
	    if (checkname && fnamecmp(exp1, s2) == 0)
		return FPC_SAMEX;
	    retval = FPC_NOTX;
	}
	else if (r1 != OK || r2 != OK)
	    retval = FPC_DIFFX;
	else if (fnamecmp(full1, full2))
	    retval = FPC_DIFF;
	else
	    retval = FPC_SAME;
    }
    vim_free(exp1);
    return retval;
#endif
}

/*
 * get the tail of a path: the file name.
 */
    char_u *
gettail(fname)
    char_u *fname;
{
    char_u  *p1, *p2;

    if (fname == NULL)
	return (char_u *)"";
    for (p1 = p2 = fname; *p2; ++p2)	/* find last part of path */
    {
	if (vim_ispathsep(*p2))
	    p1 = p2 + 1;
    }
    return p1;
}

/*
 * get the next path component (just after the next path separator).
 */
    char_u *
getnextcomp(fname)
    char_u *fname;
{
    while (*fname && !vim_ispathsep(*fname))
	++fname;
    if (*fname)
	++fname;
    return fname;
}

/*
 * Get a pointer to one character past the head of a path name.
 * Unix: after "/"; DOS: after "c:\"; Amiga: after "disk:/"; Mac: no head.
 * If there is no head, path is returned.
 */
    char_u *
get_past_head(path)
    char_u  *path;
{
    char_u  *retval;

#if defined(MSDOS) || defined(WIN32) || defined(OS2)
    /* may skip "c:" */
    if (isalpha(path[0]) && path[1] == ':')
	retval = path + 2;
    else
	retval = path;
#else
# if defined(AMIGA)
    /* may skip "label:" */
    retval = vim_strchr(path, ':');
    if (retval == NULL)
	retval = path;
# else	/* Unix */
    retval = path;
# endif
#endif

    while (vim_ispathsep(*retval))
	++retval;

    return retval;
}

/*
 * return TRUE if 'c' is a path separator.
 */
    int
vim_ispathsep(c)
    int c;
{
#ifdef RISCOS
    return (c == '.' || c == ':');
#else
# ifdef UNIX
    return (c == '/');	    /* UNIX has ':' inside file names */
# else
#  ifdef BACKSLASH_IN_FILENAME
    return (c == ':' || c == '/' || c == '\\');
#  else
#   ifdef VMS
    return (c == ':' || c == '[' || c == ']' || c == '/');
#   else
#    ifdef COLON_AS_PATHSEP
    return (c == ':');
#    else		/* Amiga */
    return (c == ':' || c == '/');
#    endif
#   endif /* VMS */
#  endif
# endif
#endif /* RISC OS */
}

/*
 * Concatenate file names fname1 and fname2 into allocated memory.
 * Only add a '/' or '\\' when 'sep' is TRUE and it is neccesary.
 */
    char_u  *
concat_fnames(fname1, fname2, sep)
    char_u  *fname1;
    char_u  *fname2;
    int	    sep;
{
    char_u  *dest;

    dest = alloc((unsigned)(STRLEN(fname1) + STRLEN(fname2) + 3));
    if (dest != NULL)
    {
	STRCPY(dest, fname1);
	if (sep && *dest && !vim_ispathsep(*(dest + STRLEN(dest) - 1)))
	    STRCAT(dest, PATHSEPSTR);
	STRCAT(dest, fname2);
    }
    return dest;
}

/*
 * FullName_save - Make an allocated copy of a full file name.
 * Returns NULL when out of memory.
 */
    char_u  *
FullName_save(fname, force)
    char_u	*fname;
    int		force;	    /* force expansion, even when it already looks
			       like a full path name */
{
    char_u	*buf;
    char_u	*new_fname = NULL;

    if (fname == NULL)
	return NULL;

    buf = alloc((unsigned)MAXPATHL);
    if (buf != NULL)
    {
	if (mch_FullName(fname, buf, MAXPATHL, force) != FAIL)
	    new_fname = vim_strsave(buf);
	else
	    new_fname = vim_strsave(fname);
	vim_free(buf);
    }
    return new_fname;
}

#if defined(CINDENT) || defined(SYNTAX_HL)

static char_u	*skip_string __ARGS((char_u *p));

/*
 * Find the start of a comment, not knowing if we are in a comment right now.
 * Search starts at w_cursor.lnum and goes backwards.
 */
    FPOS *
find_start_comment(ind_maxcomment)	    /* XXX */
    int		ind_maxcomment;
{
    FPOS	*pos;
    char_u	*line;
    char_u	*p;

    if ((pos = findmatchlimit(NULL, '*', FM_BACKWARD, ind_maxcomment)) == NULL)
	return NULL;

    /*
     * Check if the comment start we found is inside a string.
     */
    line = ml_get(pos->lnum);
    for (p = line; *p && (unsigned)(p - line) < pos->col; ++p)
	p = skip_string(p);
    if ((unsigned)(p - line) > pos->col)
	return NULL;
    return pos;
}

/*
 * Skip over a "string" and a 'c' character.
 */
    static char_u *
skip_string(p)
    char_u  *p;
{
    int	    i;

    /*
     * We loop, because strings may be concatenated: "date""time".
     */
    for ( ; ; ++p)
    {
	if (p[0] == '\'')		    /* 'c' or '\n' or '\000' */
	{
	    if (!p[1])			    /* ' at end of line */
		break;
	    i = 2;
	    if (p[1] == '\\')		    /* '\n' or '\000' */
	    {
		++i;
		while (isdigit(p[i - 1]))   /* '\000' */
		    ++i;
	    }
	    if (p[i] == '\'')		    /* check for trailing ' */
	    {
		p += i;
		continue;
	    }
	}
	else if (p[0] == '"')		    /* start of string */
	{
	    for (++p; p[0]; ++p)
	    {
		if (p[0] == '\\' && p[1])
		    ++p;
		else if (p[0] == '"')	    /* end of string */
		    break;
	    }
	    continue;
	}
	break;				    /* no string found */
    }
    if (!*p)
	--p;				    /* backup from NUL */
    return p;
}
#endif /* CINDENT || SYNTAX_HL */

#ifdef CINDENT

/*
 * Functions for C-indenting.
 * Most of this originally comes from Eric Fischer.
 */
/*
 * Below "XXX" means that this function may unlock the current line.
 */

static int	cin_isdefault __ARGS((char_u *));
static char_u	*after_label __ARGS((char_u *l));
static int	get_indent_nolabel __ARGS((linenr_t lnum));
static int	skip_label __ARGS((linenr_t, char_u **pp, int ind_maxcomment));
static int	cin_ispreproc __ARGS((char_u *));
static int	cin_iscomment __ARGS((char_u *));
static int	commentorempty __ARGS((char_u *));
static int	cin_isterminated __ARGS((char_u *, int));
static int	cin_isfuncdecl __ARGS((char_u *));
static int	cin_isif __ARGS((char_u *));
static int	cin_iselse __ARGS((char_u *));
static int	cin_isdo __ARGS((char_u *));
static int	cin_iswhileofdo __ARGS((char_u *, linenr_t, int));
static FPOS	*find_start_brace __ARGS((int));
static FPOS	*find_match_paren __ARGS((int, int));
static int	find_last_paren __ARGS((char_u *l));
static int	find_match __ARGS((int lookfor, linenr_t ourscope, int ind_maxparen, int ind_maxcomment));

/*
 * Recognize a label: "label:".
 * Note: curwin->w_cursor must be where we are looking for the label.
 */
    int
cin_islabel(ind_maxcomment)		/* XXX */
    int		ind_maxcomment;
{
    char_u	*s;

    s = skipwhite(ml_get_curline());

    /*
     * Exclude "default" from labels, since it should be indented
     * like a switch label.  Same for C++ scope declarations.
     */
    if (cin_isdefault(s))
	return FALSE;
    if (cin_isscopedecl(s))
	return FALSE;

    if (!vim_isIDc(*s))	    /* need at least one ID character */
	return FALSE;

    while (vim_isIDc(*s))
	s++;

    s = skipwhite(s);

    /* "::" is not a label, it's C++ */
    if (*s == ':' && s[1] != ':')
    {
	/*
	 * Only accept a label if the previous line is terminated or is a case
	 * label.
	 */
	FPOS	cursor_save;
	FPOS	*trypos;
	char_u	*line;

	cursor_save = curwin->w_cursor;
	while (curwin->w_cursor.lnum > 1)
	{
	    --curwin->w_cursor.lnum;

	    /*
	     * If we're in a comment now, skip to the start of the comment.
	     */
	    curwin->w_cursor.col = 0;
	    if ((trypos = find_start_comment(ind_maxcomment)) != NULL) /* XXX */
		curwin->w_cursor = *trypos;

	    line = ml_get_curline();
	    if (cin_ispreproc(line))	/* ignore #defines, #if, etc. */
		continue;
	    if (commentorempty(line))
		continue;

	    curwin->w_cursor = cursor_save;
	    if (cin_isterminated(line, TRUE) || cin_isscopedecl(line)
							  || cin_iscase(line))
		return TRUE;
	    return FALSE;
	}
	curwin->w_cursor = cursor_save;
	return TRUE;		/* label at start of file??? */
    }
    return FALSE;
}

/*
 * Recognize a switch label: "case .*:" or "default:".
 */
     int
cin_iscase(s)
    char_u *s;
{
    s = skipwhite(s);
    if (STRNCMP(s, "case", 4) == 0 && !vim_isIDc(s[4]))
    {
	for (s += 4; *s; ++s)
	{
	    if (*s == ':')
	    {
		if (s[1] == ':')	/* skip over "::" for C++ */
		    ++s;
		else
		    return TRUE;
	    }
	    if (*s == '\'' && s[1] && s[2] == '\'')
		s += 2;			/* skip over '.' */
	    else if (*s == '/' && (s[1] == '*' || s[1] == '/'))
		return FALSE;		/* stop at comment */
	    else if (*s == '"')
		return FALSE;		/* stop at string */
	}
	return FALSE;
    }

    if (cin_isdefault(s))
	return TRUE;
    return FALSE;
}

/*
 * Recognize a "default" switch label.
 */
    static int
cin_isdefault(s)
    char_u  *s;
{
    return (STRNCMP(s, "default", 7) == 0 &&
	    *(s = skipwhite(s + 7)) == ':' &&
	    s[1] != ':');
}

/*
 * Recognize a "public/private/proctected" scope declaration label.
 */
    int
cin_isscopedecl(s)
    char_u	*s;
{
    int		i;

    s = skipwhite(s);
    if (STRNCMP(s, "public", 6) == 0)
	i = 6;
    else if (STRNCMP(s, "protected", 9) == 0)
	i = 9;
    else if (STRNCMP(s, "private", 7) == 0)
	i = 7;
    else
	return FALSE;
    return (*(s = skipwhite(s + i)) == ':' && s[1] != ':');
}

/*
 * Return a pointer to the first non-empty non-comment character after a ':'.
 * Return NULL if not found.
 *	  case 234:    a = b;
 *		       ^
 */
    static char_u *
after_label(l)
    char_u  *l;
{
    for ( ; *l; ++l)
    {
	if (*l == ':')
	{
	    if (l[1] == ':')	    /* skip over "::" for C++ */
		++l;
	    else
		break;
	}
	if (*l == '\'' && l[1] && l[2] == '\'')
	    l += 2;		    /* skip over 'x' */
    }
    if (*l == NUL)
	return NULL;
    l = skipwhite(l + 1);
    if (commentorempty(l))
	return NULL;
    return l;
}

/*
 * Get indent of line "lnum", skipping a label.
 * Return 0 if there is nothing after the label.
 */
    static int
get_indent_nolabel(lnum)	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -