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

📄 window.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 4 页
字号:
{
    wp->w_p_scroll = ((unsigned)wp->w_height >> 1);
    if (wp->w_p_scroll == 0)
	wp->w_p_scroll = 1;
}

/*
 * command_height: called whenever p_ch has been changed
 */
    void
command_height(old_p_ch)
    long    old_p_ch;
{
    WIN	    *wp;
    int	    h;

    if (!starting)
    {
	cmdline_row = Rows - p_ch;
	if (p_ch > old_p_ch)		    /* p_ch got bigger */
	{
	    for (wp = lastwin; p_ch > old_p_ch; wp = wp->w_prev)
	    {
		if (wp == NULL)
		{
		    emsg(e_noroom);
		    p_ch = old_p_ch;
		    break;
		}
		h = wp->w_height - (p_ch - old_p_ch);
		if (p_wmh == 0)
		{
		    /* don't make current window zero lines */
		    if (wp == curwin && h < 1)
			h = 1;
		}
		else if (h < p_wmh)
		    h = p_wmh;
		old_p_ch += wp->w_height - h;
		win_new_height(wp, h);
	    }
	    win_comp_pos();
	    /* clear the lines added to cmdline */
	    if (full_screen)
		screen_fill((int)(cmdline_row), (int)Rows, 0,
						   (int)Columns, ' ', ' ', 0);
	    msg_row = cmdline_row;
	    redraw_cmdline = TRUE;
	    return;
	}

	if (msg_row < cmdline_row)
	    msg_row = cmdline_row;
	redraw_cmdline = TRUE;
    }
    win_new_height(lastwin, (int)(lastwin->w_height + old_p_ch - p_ch));
}

    void
last_status()
{
    WIN		*wp;

    if (lastwin->w_status_height)
    {
	/* remove status line */
	if (p_ls == 0 || (p_ls == 1 && firstwin == lastwin))
	{
	    win_new_height(lastwin, lastwin->w_height + 1);
	    lastwin->w_status_height = 0;
	    comp_col();
	}
    }
    else if (p_ls == 2 || (p_ls == 1 && firstwin != lastwin))
    {
	/* go to first window with enough room for a win_new_height(-1) */
	for (wp = lastwin; wp->w_height <= p_wmh; wp = wp->w_prev)
	    if (wp == NULL)
	    {
		emsg(e_noroom);
		return;
	    }
	win_new_height(wp, wp->w_height - 1);
	win_comp_pos();
	lastwin->w_status_height = 1;
	comp_col();
	update_screen(CLEAR);
    }
}

#ifdef FILE_IN_PATH
/*
 * file_name_at_cursor()
 *
 * Return the name of the file under (or to the right of) the cursor.
 *
 * get_file_name_in_path()
 *
 * Return the name of the file at (or to the right of) ptr[col].
 *
 * The p_path variable is searched if the file name does not start with '/'.
 * The string returned has been alloc'ed and should be freed by the caller.
 * NULL is returned if the file name or file is not found.
 *
 * options:
 * FNAME_MESS	    give error messages
 * FNAME_EXP	    expand to path
 * FNAME_HYP	    check for hypertext link
 */
    char_u *
file_name_at_cursor(options, count)
    int	    options;
    long    count;
{
    return get_file_name_in_path(ml_get_curline(),
					curwin->w_cursor.col, options, count);
}

    char_u *
get_file_name_in_path(line, col, options, count)
    char_u  *line;
    int	    col;
    int	    options;
    long    count;
{
    char_u  *ptr;
    char_u  *file_name;
    int	    len;

    /*
     * search forward for what could be the start of a file name
     */
    ptr = line + col;
    while (*ptr != NUL && !vim_isfilec(*ptr))
	++ptr;
    if (*ptr == NUL)		/* nothing found */
    {
	if (options & FNAME_MESS)
	    EMSG("No file name under cursor");
	return NULL;
    }

    /*
     * search backward for first char of the file name
     */
    while (ptr > line && vim_isfilec(ptr[-1]))
	--ptr;

    /*
     * Go one char back to ":" before "//" even when ':' is not in 'isfname'.
     */
    if ((options & FNAME_HYP) && ptr > line && path_is_url(ptr - 1))
	--ptr;

    /*
     * Search forward for the last char of the file name.
     * Also allow "://" when ':' is not in 'isfname'.
     */
    len = 0;
    while (vim_isfilec(ptr[len])
			 || ((options & FNAME_HYP) && path_is_url(ptr + len)))
	++len;

    if (options & FNAME_HYP)
    {
	/* For hypertext links, ignore the name of the machine.
	 * Such a link looks like "type://machine/path". Only "/path" is used.
	 * First search for the string "://", then for the extra '/'
	 */
	if ((file_name = vim_strchr(ptr, ':')) != NULL &&
		((path_is_url(file_name) == URL_SLASH &&
		  (file_name = vim_strchr(file_name + 3, '/')) != NULL) ||
		 (path_is_url(file_name) == URL_BACKSLASH &&
		  (file_name = vim_strchr(file_name + 3, '\\')) != NULL)) &&
		file_name < ptr + len)
	{
	    len -= file_name - ptr;
	    ptr = file_name;
	    if (ptr[1] == '~')	    /* skip '/' for /~user/path */
	    {
		++ptr;
		--len;
	    }
	}
    }

    if (!(options & FNAME_EXP))
	return vim_strnsave(ptr, len);

    return find_file_in_path(ptr, len, options, count);
}

/*
 * Find the file name "ptr[len]" in the path.
 *
 * options:
 * FNAME_MESS	    give error message when not found
 *
 * Uses NameBuff[]!
 *
 * Returns an allocated string for the file name.  NULL for error.
 */
    static char_u *
find_file_in_path(ptr, len, options, count)
    char_u	*ptr;		/* file name */
    int		len;		/* length of file name */
    int		options;
    long	count;		/* use count'th matching file name */
{
    char_u	save_char;
    char_u	*file_name;
    char_u	*curr_path = NULL;
    char_u	*dir;
    int		curr_path_len;
    char_u	*p;
    char_u	*head;


    /* copy file name into NameBuff, expanding environment variables */
    save_char = ptr[len];
    ptr[len] = NUL;
    expand_env(ptr, NameBuff, MAXPATHL);
    ptr[len] = save_char;

    if (mch_isFullName(NameBuff))
    {
	/*
	 * Absolute path, no need to use 'path'.
	 */
	if ((file_name = vim_strsave(NameBuff)) == NULL)
	    return NULL;
	if (mch_getperm(file_name) >= 0)
	    return file_name;
	if (options & FNAME_MESS)
	    EMSG2("Can't find file \"%s\"", NameBuff);
    }
    else
    {
	/*
	 * Relative path, use 'path' option.
	 */
	if (curbuf->b_fname != NULL)
	{
	    curr_path = curbuf->b_fname;
	    ptr = gettail(curr_path);
	    curr_path_len = ptr - curr_path;
	}
	else
	    curr_path_len = 0;
	if ((file_name = alloc((int)(curr_path_len + STRLEN(p_path) +
					    STRLEN(NameBuff) + 3))) == NULL)
	    return NULL;

	for (dir = p_path; *dir && !got_int; )
	{
	    len = copy_option_part(&dir, file_name, 31000, " ,");
	    /* len == 0 means: use current directory */
	    if (len != 0)
	    {
		/* Look for file relative to current file */
		if (file_name[0] == '.' && curr_path_len > 0
				 && (len == 1 || vim_ispathsep(file_name[1])))
		{
		    if (len == 1)	/* just a "." */
			len = 0;
		    else		/* "./path": move "path" */
		    {
			len -= 2;
			mch_memmove(file_name + curr_path_len, file_name + 2,
								 (size_t)len);
		    }
		    STRNCPY(file_name, curr_path, curr_path_len);
		    len += curr_path_len;
		}
		if (!vim_ispathsep(file_name[len - 1]))
		    file_name[len++] = PATHSEP;
		file_name[len] = '\0';

		/*
		 * Handle "**" in the path: 'wildcard in path'.
		 */
		if (mch_has_wildcard(file_name))
		{
		    p = get_past_head(file_name);
		    if (p == file_name)	    /* no absolute file name */
			p = find_file_in_wildcard_path((char_u *)"",
							file_name, 0, &count);
		    else    /* absolute file name, separate head */
		    {
			head = vim_strnsave(file_name,
						   (unsigned)(p - file_name));
			if (head != NULL)
			{
			    p = find_file_in_wildcard_path(head, p, 0, &count);
			    vim_free(head);
			}
		    }
		    if (p != NULL)
		    {
			vim_free(file_name);
			return p;
		    }
		    continue;
		}
	    }
	    STRCPY(file_name + len, NameBuff);

	    /*
	     * Translate names like "src/a/../b/file.c" into "src/b/file.c".
	     */
	    simplify_filename(file_name);
	    if (mch_getperm(file_name) >= 0 && --count == 0)
		return file_name;
	}
	if (options & FNAME_MESS)
	    EMSG2("Can't find file \"%s\" in path", NameBuff);
    }

    /* get here when file doesn't exist */
    vim_free(file_name);
    return NULL;
}

/*
 * find_file_in_wildcard_path(): expand path recursively while searching
 *				     files in path
 *
 * The syntax '**' means the whole subtree.
 * To avoid endless recursion, a counter restricts the depth to 100 levels.
 * In the following pseudo code '+/' will mean '*' followed by '/'
 *
 * in the case of 'set path=,/foo/bar/+/+/,'
 * the function call hierarchy will be
 *   find_file_in_wildcard_path("/", "foo/bar/+/+/", NameBuff, 0);
 *   find_file_in_wildcard_path("/foo/", "bar/+/+/", NameBuff, 0);
 *   find_file_in_wildcard_path("/foo/bar/", "+/+/", NameBuff, 0);
 * which in turn will call
 *   find_file_in_wildcard_path("/foo/bar/dir/", "+/", NameBuff, 1);
 * for each directory 'dir' in '/foo/bar/+'.  It's the next call,
 *   find_file_in_wildcard_path("/foo/bar/dir/dir2/", "", NameBuff, 2);
 * that will try to find the file 'NameBuff' in the given directory.
 *
 * pseudo code:
 *
 *  find_file_in_wildcard_path(path_so_far, wildcards, level)
 *  {
 *    if (level > 100)
 *	return NULL;
 *
 *    file_name = path_so_far + first_segment(wildcards);
 *    rest_of_wildcards = all_but_first_segment(wildcards);
 *
 *    result = expand(file_name);
 *
 *    if (!rest_of_wildcards) {
 *	foreach_path_in(result) {
 *	  if (exists&readable(path + NameBuff))
 *	    return path+NameBuff;
 *	}
 *    } else {
 *	foreach_path_in(result) {
 *	  c = find_file_in_wildcard_path(path, rest_of_wildcards, level+1);
 *	  if (c)
 *	    return c;
 *	}
 *    }
 *    if (infinite_recursion(wildcards)) {
 *	foreach_path_in(result) {
 *	  c = find_file_in_wildcard_path(path, wildcards, level+1);
 *	  if (c)
 *	    return c;
 *	}
 *    }
 *    return NULL;
 *  }
 */
    static char_u *
find_file_in_wildcard_path(path_so_far, wildcards, level, countptr)
    char_u  *path_so_far;
    char_u  *wildcards;
    int	    level;
    long    *countptr;
{
    char_u  *file_name;
    int	    len;
    char_u  *rest_of_wildcards;
    int	    nFiles = 0;
    char_u  **ppFiles;
    int	    i;
    char_u  *c;

    ui_breakcheck();
    if (level > 100 || got_int)
	return NULL;

    if ((file_name = alloc((int)MAXPATHL)) == NULL)
	return NULL;

    STRCPY(file_name, path_so_far);
    len = STRLEN(file_name);
    if (!vim_ispathsep(file_name[len-1]))
    {
	file_name[len++] = PATHSEP;
	file_name[len] = '\0';
    }
    rest_of_wildcards = wildcards;
    if (rest_of_wildcards)
    {
	if (STRNCMP(rest_of_wildcards, "**", 2) == 0)
	    rest_of_wildcards++;
	while (*rest_of_wildcards && !vim_ispathsep(*rest_of_wildcards))
	    file_name[len++] = *rest_of_wildcards++;
	/* file_name[len++] = *rest_of_wildcards++; */
	rest_of_wildcards++;
	file_name[len] = '\0';
    }

    ++expand_interactively;
    expand_wildcards(1, &file_name, &nFiles, &ppFiles, EW_FILE|EW_DIR);
    --expand_interactively;

    if (!*rest_of_wildcards)
    {
	for (i = 0; i < nFiles; ++i)
	{
	    if (!mch_isdir(ppFiles[i]))
		continue;   /* not a directory */
	    STRCPY(file_name, ppFiles[i]);
	    if (!vim_ispathsep(file_name[STRLEN(file_name)-1]))
		STRCAT(file_name, PATHSEPSTR);
	    STRCAT(file_name, NameBuff);
	    if (mch_getperm(file_name) >= 0 && --*countptr == 0)
	    {
		FreeWild(nFiles, ppFiles);
		return file_name;
	    }
	}
    }
    else
    {
	for (i = 0; i < nFiles; ++i)
	{
	    if (!mch_isdir(ppFiles[i]))
		continue;   /* not a directory */
	    c = find_file_in_wildcard_path(ppFiles[i],
					rest_of_wildcards, level+1, countptr);
	    if (c)
	    {
		FreeWild(nFiles, ppFiles);
		vim_free(file_name);
		return c;
	    }
	}
    }

    if (STRNCMP(wildcards, "**", 2) == 0)
    {
	for (i = 0; i < nFiles; ++i)
	{
	    if (!mch_isdir(ppFiles[i]))
		continue;   /* not a directory */
	    c = find_file_in_wildcard_path(ppFiles[i],
						wildcards, level+1, countptr);
	    if (c)
	    {
		FreeWild(nFiles, ppFiles);
		vim_free(file_name);
		return c;
	    }
	}
    }

    FreeWild(nFiles, ppFiles);

    vim_free(file_name);
    return NULL;
}

/*
 * Check if the "://" of a URL is at the pointer, return URL_SLASH.
 * Also check for ":\\", which MS Internet Explorer accepts, return
 * URL_BACKSLASH.
 */
    static int
path_is_url(p)
    char_u  *p;
{
    if (STRNCMP(p, "://", (size_t)3) == 0)
	return URL_SLASH;
    else if (STRNCMP(p, ":\\\\", (size_t)3) == 0)
	return URL_BACKSLASH;
    return 0;
}
#endif /* FILE_IN_PATH */

/*
 * Return the minimal number of rows that is needed on the screen to display
 * the current number of windows.
 */
    int
min_rows()
{
    WIN	    *wp;
    int	    total;

    if (firstwin == NULL)	/* not initialized yet */
	return MIN_LINES;

    total = p_ch;	/* count the room for the status line */
    for (wp = firstwin; wp != NULL; wp = wp->w_next)
	total += p_wmh + wp->w_status_height;
    if (p_wmh == 0)
	total += 1;	/* at least one window should have a line! */
    return total;
}

/*
 * Return TRUE if there is only one window, not counting a help window, unless
 * it is the current window.
 */
    int
only_one_window()
{
    int	    count = 0;
    WIN	    *wp;

    for (wp = firstwin; wp != NULL; wp = wp->w_next)
	if (!wp->w_buffer->b_help || wp == curwin)
	    ++count;
    return (count <= 1);
}

/*
 * Correct the cursor line number in other windows.  Used after changing the
 * current buffer, and before applying autocommands.
 * When "do_curwin" is TRUE, also check current window.
 */
    void
check_lnums(do_curwin)
    int		do_curwin;
{
    WIN		*wp;

    for (wp = firstwin; wp != NULL; wp = wp->w_next)
	if ((do_curwin || wp != curwin) && wp->w_buffer == curbuf)
	{
	    if (wp->w_cursor.lnum > curbuf->b_ml.ml_line_count)
		wp->w_cursor.lnum = curbuf->b_ml.ml_line_count;
	    if (wp->w_topline > curbuf->b_ml.ml_line_count)
		wp->w_topline = curbuf->b_ml.ml_line_count;
	}
}

⌨️ 快捷键说明

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