fileinfo(
    int fullname,	    // when non-zero print full path
    int shorthelp,
    int	dont_truncate)
{
    char_u	*name;
    int		n;
    char	*p;
    char	*buffer;
    size_t	len;

    buffer = alloc(IOSIZE);
    if (buffer == NULL)
	return;

    if (fullname > 1)	    // 2 CTRL-G: include buffer number
    {
	vim_snprintf(buffer, IOSIZE, "buf %d: ", curbuf->b_fnum);
	p = buffer + STRLEN(buffer);
    }
    else
	p = buffer;

    *p++ = '"';
    if (buf_spname(curbuf) != NULL)
	vim_strncpy((char_u *)p, buf_spname(curbuf), IOSIZE - (p - buffer) - 1);
    else
    {
	if (!fullname && curbuf->b_fname != NULL)
	    name = curbuf->b_fname;
	else
	    name = curbuf->b_ffname;
	home_replace(shorthelp ? curbuf : NULL, name, (char_u *)p,
					  (int)(IOSIZE - (p - buffer)), TRUE);
    }

    vim_snprintf_add(buffer, IOSIZE, "\"%s%s%s%s%s%s",
	    curbufIsChanged() ? (shortmess(SHM_MOD)
					  ?  " [+]" : _(" [Modified]")) : " ",
	    (curbuf->b_flags & BF_NOTEDITED)
#ifdef FEAT_QUICKFIX
		    && !bt_dontwrite(curbuf)
#endif
					? _("[Not edited]") : "",
	    (curbuf->b_flags & BF_NEW)
#ifdef FEAT_QUICKFIX
		    && !bt_dontwrite(curbuf)
#endif
					   ? new_file_message() : "",
	    (curbuf->b_flags & BF_READERR) ? _("[Read errors]") : "",
	    curbuf->b_p_ro ? (shortmess(SHM_RO) ? _("[RO]")
						      : _("[readonly]")) : "",
	    (curbufIsChanged() || (curbuf->b_flags & BF_WRITE_MASK)
							  || curbuf->b_p_ro) ?
								    " " : "");
    // With 32 bit longs and more than 21,474,836 lines multiplying by 100
    // causes an overflow, thus for large numbers divide instead.
    if (curwin->w_cursor.lnum > 1000000L)
	n = (int)(((long)curwin->w_cursor.lnum) /
				   ((long)curbuf->b_ml.ml_line_count / 100L));
    else
	n = (int)(((long)curwin->w_cursor.lnum * 100L) /
					    (long)curbuf->b_ml.ml_line_count);
    if (curbuf->b_ml.ml_flags & ML_EMPTY)
	vim_snprintf_add(buffer, IOSIZE, "%s", _(no_lines_msg));
#ifdef FEAT_CMDL_INFO
    else if (p_ru)
	// Current line and column are already on the screen -- webb
	vim_snprintf_add(buffer, IOSIZE,
		NGETTEXT("%ld line --%d%%--", "%ld lines --%d%%--",
						   curbuf->b_ml.ml_line_count),
		(long)curbuf->b_ml.ml_line_count, n);
#endif
    else
    {
	vim_snprintf_add(buffer, IOSIZE,
		_("line %ld of %ld --%d%%-- col "),
		(long)curwin->w_cursor.lnum,
		(long)curbuf->b_ml.ml_line_count,
		n);
	validate_virtcol();
	len = STRLEN(buffer);
	col_print((char_u *)buffer + len, IOSIZE - len,
		   (int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1);
    }

    (void)append_arg_number(curwin, (char_u *)buffer, IOSIZE,
							 !shortmess(SHM_FILE));

    if (dont_truncate)
    {
	// Temporarily set msg_scroll to avoid the message being truncated.
	// First call msg_start() to get the message in the right place.
	msg_start();
	n = msg_scroll;
	msg_scroll = TRUE;
	msg(buffer);
	msg_scroll = n;
    }
    else
    {
	p = msg_trunc_attr(buffer, FALSE, 0);
	if (restart_edit != 0 || (msg_scrolled && !need_wait_return))
	    // Need to repeat the message after redrawing when:
	    // - When restart_edit is set (otherwise there will be a delay
	    //   before redrawing).
	    // - When the screen was scrolled but there is no wait-return
	    //   prompt.
	    set_keep_msg((char_u *)p, 0);
    }

    vim_free(buffer);
}