home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
text
/
vim
/
src
/
screen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-27
|
46KB
|
1,985 lines
/* vi:ts=4:sw=4
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Read the file "credits.txt" for a list of people who contributed.
* Read the file "uganda.txt" for copying and usage conditions.
*/
/*
* screen.c: code for displaying on the screen
*/
#include "vim.h"
#include "globals.h"
#include "proto.h"
#include "param.h"
char *tgoto __PARMS((char *cm, int col, int line));
static char_u *Nextscreen = NULL; /* What is currently on the screen. */
static char_u **LinePointers = NULL; /* array of pointers into Nextscreen */
/*
* Cline_height is set (in cursupdate) to the number of physical
* lines taken by the line the cursor is on. We use this to avoid extra calls
* to plines(). The optimized routine updateline()
* makes sure that the size of the cursor line hasn't changed. If so, lines
* below the cursor will move up or down and we need to call the routine
* updateScreen() to examine the entire screen.
*/
static int Cline_height; /* current size of cursor line */
static int Cline_row; /* starting row of the cursor line on screen */
static FPOS old_cursor = {0, 0}; /* last known end of visual part */
static int oldCurswant = 0; /* last known value of Curswant */
static int canopt; /* TRUE when cursor goto can be optimized */
static int invert = 0; /* set to INVERTCODE when inverting */
#define INVERTCODE 0x80
static int win_line __ARGS((WIN *, linenr_t, int, int));
static void screen_char __ARGS((char_u *, int, int));
static void screenalloc __ARGS((int));
static void screenclear2 __ARGS((void));
static int screen_ins_lines __ARGS((int, int, int, int));
/*
* updateline() - like updateScreen() but only for cursor line
*
* This determines whether or not we need to call updateScreen() to examine
* the entire screen for changes. This occurs if the size of the cursor line
* (in rows) hasn't changed.
*/
void
updateline()
{
int row;
int n;
if (must_redraw) /* must redraw whole screen */
{
updateScreen(must_redraw);
return;
}
screenalloc(TRUE); /* allocate screen buffers if size changed */
if (Nextscreen == NULL || RedrawingDisabled)
return;
screen_start(); /* init cursor position of screen_char() */
cursor_off();
(void)set_highlight('v');
row = win_line(curwin, curwin->w_cursor.lnum, Cline_row, curwin->w_height);
if (row == curwin->w_height + 1) /* line too long for window */
updateScreen(VALID_TO_CURSCHAR);
else
{
n = row - Cline_row;
if (n != Cline_height) /* line changed size */
{
if (n < Cline_height) /* got smaller: delete lines */
win_del_lines(curwin, row, Cline_height - n, FALSE, TRUE);
else /* got bigger: insert lines */
win_ins_lines(curwin, Cline_row + Cline_height, n - Cline_height, FALSE, TRUE);
updateScreen(VALID_TO_CURSCHAR);
}
}
}
/*
* updateScreen()
*
* Based on the current value of curwin->w_topline, transfer a screenfull
* of stuff from Filemem to Nextscreen, and update curwin->w_botline.
*/
void
updateScreen(type)
int type;
{
WIN *wp;
screenalloc(TRUE); /* allocate screen buffers if size changed */
if (Nextscreen == NULL)
return;
if (must_redraw)
{
if (type < must_redraw) /* use maximal type */
type = must_redraw;
must_redraw = 0;
}
if (type == CURSUPD) /* update cursor and then redraw NOT_VALID*/
{
curwin->w_lsize_valid = 0;
cursupdate(); /* will call updateScreen() */
return;
}
if (curwin->w_lsize_valid == 0 && type != CLEAR)
type = NOT_VALID;
if (RedrawingDisabled)
{
must_redraw = type; /* remember type for next time */
return;
}
/*
* if the screen was scrolled up when displaying a message, scroll it down
*/
if (msg_scrolled)
{
clear_cmdline = TRUE;
if (msg_scrolled > Rows - 5) /* clearing is faster */
type = CLEAR;
else if (type != CLEAR)
{
if (screen_ins_lines(0, 0, msg_scrolled, (int)Rows) == FAIL)
type = CLEAR;
win_rest_invalid(firstwin); /* should do only first/last few */
}
msg_scrolled = 0;
}
/*
* reset cmdline_row now (may have been changed temporarily)
*/
compute_cmdrow();
if (type == CLEAR) /* first clear screen */
{
screenclear(); /* will reset clear_cmdline */
type = NOT_VALID;
}
if (clear_cmdline)
gotocmdline(TRUE, NUL); /* first clear cmdline */
/* return if there is nothing to do */
if ((type == VALID && curwin->w_topline == curwin->w_lsize_lnum[0]) ||
(type == INVERTED && old_cursor.lnum == curwin->w_cursor.lnum &&
old_cursor.col == curwin->w_cursor.col && curwin->w_curswant == oldCurswant))
return;
curwin->w_redr_type = type;
/*
* go from top to bottom through the windows, redrawing the ones that need it
*/
cursor_off();
for (wp = firstwin; wp; wp = wp->w_next)
{
if (wp->w_redr_type)
win_update(wp);
if (wp->w_redr_status)
win_redr_status(wp);
}
if (redraw_cmdline)
showmode();
}
/*
* update a single window
*
* This may cause the windows below it also to be redrawn
*/
void
win_update(wp)
WIN *wp;
{
int type = wp->w_redr_type;
register int row;
register int endrow;
linenr_t lnum;
linenr_t lastline = 0; /* only valid if endrow != Rows -1 */
int done; /* if TRUE, we hit the end of the file */
int didline; /* if TRUE, we finished the last line */
int srow = 0; /* starting row of the current line */
int idx;
int i;
long j;
if (type == NOT_VALID)
{
wp->w_redr_status = TRUE;
wp->w_lsize_valid = 0;
}
idx = 0;
row = 0;
lnum = wp->w_topline;
/* The number of rows shown is w_height. */
/* The default last row is the status/command line. */
endrow = wp->w_height;
if (type == VALID || type == VALID_TO_CURSCHAR)
{
/*
* We handle two special cases:
* 1: we are off the top of the screen by a few lines: scroll down
* 2: wp->w_topline is below wp->w_lsize_lnum[0]: may scroll up
*/
if (wp->w_topline < wp->w_lsize_lnum[0]) /* may scroll down */
{
j = wp->w_lsize_lnum[0] - wp->w_topline;
if (j < wp->w_height - 2) /* not too far off */
{
lastline = wp->w_lsize_lnum[0] - 1;
i = plines_m_win(wp, wp->w_topline, lastline);
if (i < wp->w_height - 2) /* less than a screen off */
{
/*
* Try to insert the correct number of lines.
* If not the last window, delete the lines at the bottom.
* win_ins_lines may fail.
*/
if (win_ins_lines(wp, 0, i, FALSE, wp == firstwin) == OK &&
wp->w_lsize_valid)
{
endrow = i;
if ((wp->w_lsize_valid += j) > wp->w_height)
wp->w_lsize_valid = wp->w_height;
for (idx = wp->w_lsize_valid; idx - j >= 0; idx--)
{
wp->w_lsize_lnum[idx] = wp->w_lsize_lnum[idx - j];
wp->w_lsize[idx] = wp->w_lsize[idx - j];
}
idx = 0;
}
}
else if (lastwin == firstwin) /* far off: clearing the screen is faster */
screenclear();
}
else if (lastwin == firstwin) /* far off: clearing the screen is faster */
screenclear();
}
else /* may scroll up */
{
j = -1;
for (i = 0; i < wp->w_lsize_valid; i++) /* try to find wp->w_topline in wp->w_lsize_lnum[] */
{
if (wp->w_lsize_lnum[i] == wp->w_topline)
{
j = i;
break;
}
row += wp->w_lsize[i];
}
if (j == -1) /* wp->w_topline is not in wp->w_lsize_lnum */
{
row = 0;
if (lastwin == firstwin)
screenclear(); /* far off: clearing the screen is faster */
}
else
{
/*
* Try to delete the correct number of lines.
* wp->w_topline is at wp->w_lsize_lnum[i].
*/
if ((row == 0 || win_del_lines(wp, 0, row, FALSE, wp == firstwin) == OK) && wp->w_lsize_valid)
{
srow = row;
row = 0;
for (;;)
{
if (type == VALID_TO_CURSCHAR && lnum == wp->w_cursor.lnum)
break;
if (row + srow + (int)wp->w_lsize[j] >= wp->w_height)
break;
wp->w_lsize[idx] = wp->w_lsize[j];
wp->w_lsize_lnum[idx] = lnum++;
row += wp->w_lsize[idx++];
if ((int)++j >= wp->w_lsize_valid)
break;
}
wp->w_lsize_valid = idx;
}
else
row = 0; /* update all lines */
}
}
if (endrow == wp->w_height && idx == 0) /* no scrolling */
wp->w_lsize_valid = 0;
}
done = didline = FALSE;
screen_start(); /* init cursor position of screen_char() */
if (VIsual.lnum) /* check if we are updating the inverted part */
{
linenr_t from, to;
/* find the line numbers that need to be updated */
if (wp->w_cursor.lnum < old_cursor.lnum)
{
from = wp->w_cursor.lnum;
to = old_cursor.lnum;
}
else
{
from = old_cursor.lnum;
to = wp->w_cursor.lnum;
}
/* if in block mode and changed column or wp->w_curswant: update all lines */
if (Visual_block && (wp->w_cursor.col != old_cursor.col || wp->w_curswant != oldCurswant))
{
if (from > VIsual.lnum)
from = VIsual.lnum;
if (to < VIsual.lnum)
to = VIsual.lnum;
}
if (from < wp->w_topline)
from = wp->w_topline;
if (to >= wp->w_botline)
to = wp->w_botline - 1;
/* find the minimal part to be updated */
if (type == INVERTED)
{
while (lnum < from) /* find start */
{
row += wp->w_lsize[idx++];
++lnum;
}
srow = row;
for (j = idx; j < wp->w_lsize_valid; ++j) /* find end */
{
if (wp->w_lsize_lnum[j] == to + 1)
{
endrow = srow;
break;
}
srow += wp->w_lsize[j];
}
old_cursor = wp->w_cursor;
oldCurswant = wp->w_curswant;
}
/* if we update the lines between from and to set old_cursor */
else if (lnum <= from && (endrow == wp->w_height || lastline >= to))
{
old_cursor = wp->w_cursor;
oldCurswant = wp->w_curswant;
}
}
(void)set_highlight('v');
/*
* Update the screen rows from "row" to "endrow".
* Start at line "lnum" which is at wp->w_lsize_lnum[idx].
*/
for (;;)
{
if (lnum > wp->w_buffer->b_ml.ml_line_count) /* hit the end of the file */
{
done = TRUE;
break;
}
srow = row;
row = win_line(wp, lnum, srow, endrow);
if (row > endrow) /* past end of screen */
{
wp->w_lsize[idx] = plines_win(wp, lnum); /* we may need the size of that */
wp->w_lsize_lnum[idx++] = lnum; /* too long line later on */
break;
}
wp->w_lsize[idx] = row - srow;
wp->w_lsize_lnum[idx++] = lnum;
if (++lnum > wp->w_buffer->b_ml.ml_line_count)
{
done = TRUE;
break;
}
if (row == endrow)
{
didline = TRUE;
break;
}
}
if (idx > wp->w_lsize_valid)
wp->w_lsize_valid = idx;
/* Do we have to do off the top of the screen processing ? */
if (endrow != wp->w_height)
{
row = 0;
for (idx = 0; idx < wp->w_lsize_valid && row < wp->w_height; idx++)
row += wp->w_lsize[idx];
if (row < wp->w_height)
{
done = TRUE;
}
else if (row > wp->w_height) /* Need to blank out the last line */
{
lnum = wp->w_lsize_lnum[idx - 1];
srow = row - wp->w_lsize[idx - 1];
didline = FALSE;
}
else
{
lnum = wp->w_lsize_lnum[idx - 1] + 1;
didline = TRUE;
}
}
wp->w_empty_rows = 0;
/*
* If we didn't hit the end of the file, and we didn't finish the last
* line we were working on, then the line didn't fit.
*/
if (!done && !didline)
{
if (lnum == wp->w_topline)
{
/*
* Single line that does not fit!
* Fill last line with '@' characters.
*/
screen_fill(wp->w_winpos + wp->w_height - 1, wp->w_winpos + wp->w_height, 0, (int)Columns, '@', '@');
wp->w_botline = lnum + 1;
}
else
{
/*
* Clear the rest of the screen and mark the unused lines.
*/
screen_fill(wp->w_winpos + srow, wp->w_winpos + wp->w_height, 0, (int)Columns, '@', ' ');
wp->w_botline = lnum;
wp->w_empty_rows = wp->w_height - srow;
}
}
else
{
/* make sure the rest of the screen is blank */
/* put '~'s on rows that aren't part of the file. */
screen_fill(wp->w_winpos + row, wp->w_winpos + wp->w_height, 0, (int)Columns, '~', ' ');
wp->w_empty_rows = wp->w_height - row;
if (done) /* we hit the end of the file */
wp->w_botline = wp->w_buffer->b_ml.ml_line_count + 1;
else
wp->w_botline = lnum;
}
wp->w_redr_type = 0;
}
/*
* mark all status lines for redraw; used after first :cd
*/
void
status_redraw_all()
{
WIN *wp;
for (wp = firstwin; wp; wp = wp->w_next)
wp->w_redr_status = TRUE;
updateScreen(NOT_VALID);
}
/*
* Redraw the status line of window wp.
*
* If inversion is possible we use it. Else '=' characters are used.
*/
void
win_redr_status(wp)
WIN *wp;
{
int row;
int col;
char_u *p;
int len;
int fillchar;
if (wp->w_status_height) /* if there is a status line */
{
if (set_highlight('s') == OK) /* can highlight */
{
fillchar = ' ';
start_highlight();
}
else /* can't highlight, use '=' */
fillchar = '=';
screen_start(); /* init cursor position */
row = wp->w_winpos + wp->w_height;
col = 0;
p = wp->w_buffer->b_xfilename;
if (p == NULL)
p = (char_u *)"[No File]";
else
{
home_replace(p, NameBuff, MAXPATHL);
p = NameBuff;
}
len = STRLEN(p);
if (wp->w_buffer->b_changed)
len += 4;
if (len > ru_col - 1)
{
screen_outchar('<', row, 0);
p += len - (ru_col - 1) + 1;
len = (ru_col - 1);
col = 1;
}
screen_msg(p, row, col);
if (wp->w_buffer->b_changed)
screen_msg((char_u *)" [+]", row, len - 4);
screen_fill(row, row + 1, len, ru_col, fillchar, fillchar);
stop_highlight();
win_redr_ruler(wp, TRUE);
}
else /* no status line, can only be last window */
redraw_cmdline = TRUE;
wp->w_redr_status = FALSE;
}
/*
* display line "lnum" of window 'wp' on the screen
* Start at row "startrow", stop when "endrow" is reached.
* Return the number of last row the line occupies.
*/
static int
win_line(wp, lnum, startrow, endrow)
WIN *wp;
linenr_t lnum;
int startrow;
int endrow;
{
char_u *screenp;
int c;
int col; /* visual column on screen */
long vcol; /* visual column for tabs */
int row; /* row in the window, excluding w_winpos */
int screen_row; /* row on the screen, including w_winpos */
char_u *ptr;
char_u extra[16]; /* "%ld" must fit in here */
char_u *p_extra;
int n_extra;
int n_spaces = 0;
int fromcol, tocol; /* start/end of inverting */
int noinvcur = FALSE; /* don't invert the cursor */
int temp;
FPOS *top, *bot;
row = startrow;
screen_row = row + wp->w_winpos;
col = 0;
vcol = 0;
fromcol = -10;
tocol = MAXCOL;
canopt = TRUE;
if (VIsual.lnum && wp == curwin) /* visual active in this window */
{
if (ltoreq(wp->w_cursor, VIsual)) /* Visual is after wp->w_cursor */
{
top = &wp->w_cursor;
bot = &VIsual;
}
else /* Visual is before wp->w_cursor */
{
top = &VIsual;
bot = &wp->w_cursor;
}
if (Visual_block) /* block mode */
{
if (lnum >= top->lnum && lnum <= bot->lnum)
{
fromcol = getvcol(wp, top, 2);
temp = getvcol(wp, bot, 2);
if (temp < fromcol)
fromcol = temp;
if (wp->w_curswant != MAXCOL)
{
tocol = getvcol(wp, top, 3);
temp = getvcol(wp, bot, 3);
if (temp > tocol)
tocol = temp;
++tocol;
}
}
}
else /* non-block mode */
{
if (lnum > top->lnum && lnum <= bot->lnum)
fromcol = 0;
else if (lnum == top->lnum)
fromcol = getvcol(wp, top, 2);
if (lnum == bot->lnum)
tocol = getvcol(wp, bot, 3) + 1;
if (VIsual.col == VISUALLINE) /* linewise */
{
if (fromcol > 0)
fromcol = 0;
tocol = VISUALLINE;
}
}
/* if the cursor can't be switched off, don't invert the character
where the cursor is */
if ((T_CI == NULL || *T_CI == NUL) && lnum == wp->w_cursor.lnum)
noinvcur = TRUE;
if (tocol <= wp->w_leftcol) /* inverting is left of screen */
fromcol = 0;
else if (fromcol >= 0 && fromcol < wp->w_leftcol) /* start of invert is left of screen */
fromcol = wp->w_leftcol;
/* if inverting in this line, can't optimize cursor positioning */
if (fromcol >= 0)
canopt = FALSE;
}
ptr = ml_get_buf(wp->w_buffer, lnum, FALSE);
if (!wp->w_p_wrap) /* advance to first character to be displayed */
{
while (vcol < wp->w_leftcol && *ptr)
vcol += chartabsize(*ptr++, vcol);
if (vcol > wp->w_leftcol)
{
n_spaces = vcol - wp->w_leftcol; /* begin with some spaces */
vcol = wp->w_leftcol;
}
}
screenp = LinePointers[screen_row];
if (wp->w_p_nu)
{
sprintf((char *)extra, "%7ld ", (long)lnum);
p_extra = extra;
n_extra = 8;
vcol -= 8; /* so vcol is 0 when line number has been printed */
}
else
{
p_extra = NULL;
n_extra = 0;
}
for (;;)
{
if (!canopt) /* Visual in this line */
{
if (((vcol == fromcol && !(noinvcur && vcol == wp->w_virtcol)) ||
(noinvcur && vcol == wp->w_virtcol + 1 && vcol >= fromcol)) &&
vcol < tocol)
start_highlight(); /* start highlighting */
else if (invert && (vcol == tocol || (noinvcur && vcol == wp->w_virtcol)))
stop_highlight(); /* stop highlighting */
}
/* Get the next character to put on the screen. */
/*
* The 'extra' array contains the extra stuff that is inserted to
* represent special characters (non-printable stuff).
*/
if (n_extra)
{
c = *p_extra++;
n_extra--;
}
else if (n_spaces)
{
c = ' ';
n_spaces--;
}
else
{
if ((c = *ptr++) < ' ' || (c > '~' && c <= 0xa0))
{
/*
* when getting a character from the file, we may have to turn it
* into something else on the way to putting it into 'Nextscreen'.
*/
if (c == TAB && !wp->w_p_list)
{
/* tab amount depends on current column */
n_spaces = (int)wp->w_buffer->b_p_ts - vcol % (int)wp->w_buffer->b_p_ts - 1;
c = ' ';
}
else if (c == NUL && wp->w_p_list)
{
p_extra = (char_u *)"";
n_extra = 1;
c = '$';
}
else if (c != NUL)
{
p_extra = transchar(c);
n_extra = charsize(c) - 1;
c = *p_extra++;
}
}
}
if (c == NUL)
{
if (invert)
{
if (vcol == 0) /* invert first char of empty line */
{
if (*screenp != (' ' ^ INVERTCODE))
{
*screenp = (' ' ^ INVERTCODE);
screen_char(screenp, screen_row, col);
}
++screenp;
++col;
}
stop_highlight();
}
/*
* blank out the rest of this row, if necessary
*/
while (col < Columns && *screenp == ' ')
{
++screenp;
++col;
}
if (col < Columns)
{
screen_fill(screen_row, screen_row + 1, col, (int)Columns, ' ', ' ');
col = Columns;
}
row++;
screen_row++;
break;
}
if (col >= Columns)
{
col = 0;
++row;
++screen_row;
if (!wp->w_p_wrap)
break;
if (row == endrow) /* line got too long for screen */
{
++row;
break;
}
screenp = LinePointers[screen_row];
}
/*
* Store the character in Nextscreen.
* Be careful with characters where (c ^ INVERTCODE == ' '), they may be
* confused with spaces inserted by scrolling.
*/
if (*screenp != (c ^ invert) || c == (' ' ^ INVERTCODE))
{
*screenp = (c ^ invert);
screen_char(screenp, screen_row, col);
}
++screenp;
col++;
vcol++;
}
if (invert)
stop_highlight();
return (row);
}
/*
* output a single character directly to the screen
* update NextScreen
* Note: must do screen_start() before this!
*/
void
screen_outchar(c, row, col)
int c;
int row, col;
{
char_u buf[2];
buf[0] = c;
buf[1] = NUL;
screen_msg(buf, row, col);
}
/*
* put string '*msg' on the screen at position 'row' and 'col'
* update NextScreen
* Note: only outputs within one row, message is truncated at screen boundary!
* Note: must do screen_start() before this!
* Note: caller must make sure that row is valid!
*/
void
screen_msg(msg, row, col)
char_u *msg;
int row;
int col;
{
char_u *screenp;
screenp = LinePointers[row] + col;
while (*msg && col < Columns)
{
if (*screenp != (*msg ^ invert) || *msg == (' ' ^ INVERTCODE))
{
*screenp = (*msg ^ invert);
screen_char(screenp, row, col);
}
++screenp;
++col;
++msg;
}
}
/*
* last cursor position known by screen_char
*/
static int oldrow, oldcol; /* old cursor position */
/*
* reset cursor position. Use whenever cursor moved before calling screen_char.
*/
void
screen_start()
{
oldcol = 9999;
}
/*
* set_highlight - set highlight depending on 'highlight' option and context.
*
* return FAIL if highlighting is not possible, OK otherwise
*/
int
set_highlight(context)
int context;
{
int len;
int i;
int mode;
len = STRLEN(p_hl);
for (i = 0; i < len; i += 3)
if (p_hl[i] == context)
break;
if (i < len)
mode = p_hl[i + 1];
else
mode = 'i';
switch (mode)
{
case 'b': highlight = T_TB; /* bold */
unhighlight = T_TP;
break;
case 's': highlight = T_SO; /* standout */
unhighlight = T_SE;
break;
case 'n': highlight = NULL; /* no highlighting */
unhighlight = NULL;
break;
default: highlight = T_TI; /* invert/reverse */
unhighlight = T_TP;
break;
}
if (highlight == NULL || *highlight == NUL ||
unhighlight == NULL || *unhighlight == NUL)
{
highlight = NULL;
return FAIL;
}
return OK;
}
void
start_highlight()
{
if (highlight != NULL)
{
outstr(highlight);
invert = INVERTCODE;
}
}
void
stop_highlight()
{
if (invert)
{
outstr(unhighlight);
invert = 0;
}
}
/*
* put character '*p' on the screen at position 'row' and 'col'
*/
static void
screen_char(p, row, col)
char_u *p;
int row;
int col;
{
int c;
int noinvcurs;
/*
* Outputting the last character on the screen may scrollup the screen.
* Don't to it!
*/
if (row == Rows - 1 && col == Columns - 1)
return;
if (oldcol != col || oldrow != row)
{
/* check if no cursor movement is allowed in standout mode */
if (invert && !p_wi && (T_MS == NULL || *T_MS == NUL))
noinvcurs = 7;
else
noinvcurs = 0;
/*
* If we're on the same row (which happens a lot!), try to
* avoid a windgoto().
* If we are only a few characters off, output the
* characters. That is faster than cursor positioning.
* This can't be used when inverting (a part of) the line.
*/
if (oldrow == row && oldcol < col)
{
register int i;
i = col - oldcol;
if (i <= 4 + noinvcurs && canopt)
{
while (i)
{
c = *(p - i--);
outchar(c ^ invert);
}
}
else
{
if (noinvcurs)
stop_highlight();
if (T_CRI && *T_CRI) /* use tgoto interface! jw */
OUTSTR(tgoto((char *)T_CRI, 0, i));
else
windgoto(row, col);
if (noinvcurs)
start_highlight();
}
oldcol = col;
}
else
{
if (noinvcurs)
stop_highlight();
windgoto(oldrow = row, oldcol = col);
if (noinvcurs)
start_highlight();
}
}
/*
* For weird invert mechanism: output (un)highlight before every char
* Lots of extra output, but works.
*/
if (p_wi)
{
if (invert)
outstr(highlight);
else
outstr(unhighlight);
}
outchar(*p ^ invert);
oldcol++;
}
/*
* Fill the screen from 'start_row' to 'end_row', from 'start_col' to 'end_col'
* with character 'c1' in first column followed by 'c2' in the other columns.
*/
void
screen_fill(start_row, end_row, start_col, end_col, c1, c2)
int start_row, end_row;
int start_col, end_col;
int c1, c2;
{
int row;
int col;
char_u *screenp;
int did_delete = FALSE;
int c;
if (start_row >= end_row || start_col >= end_col) /* nothing to do */
return;
c1 ^= invert;
c2 ^= invert;
for (row = start_row; row < end_row; ++row)
{
/* try to use delete-line termcap code */
if (c2 == ' ' && end_col == Columns && T_EL != NULL && *T_EL != NUL)
{
/*
* check if we really need to clear something
*/
col = start_col;
screenp = LinePointers[row] + start_col;
if (c1 != ' ') /* don't clear first char */
{
++col;
++screenp;
}
while (col < end_col && *screenp == ' ') /* skip blanks */
{
++col;
++screenp;
}
if (col < end_col) /* something to be cleared */
{
windgoto(row, col);
outstr(T_EL);
}
did_delete = TRUE;
}
screen_start(); /* init cursor position of screen_char() */
screenp = LinePointers[row] + start_col;
c = c1;
for (col = start_col; col < end_col; ++col)
{
if (*screenp != c)
{
*screenp = c;
if (!did_delete || c != ' ')
screen_char(screenp, row, col);
}
++screenp;
c = c2;
}
if (row == Rows - 1)
{
redraw_cmdline = TRUE;
if (c1 == ' ' && c2 == ' ')
clear_cmdline = FALSE;
}
}
}
/*
* recompute all w_botline's. Called after Rows changed.
*/
void
comp_Botline_all()
{
WIN *wp;
for (wp = firstwin; wp; wp = wp->w_next)
comp_Botline(wp);
}
/*
* compute wp->w_botline. Can be called after wp->w_topline changed.
*/
void
comp_Botline(wp)
WIN *wp;
{
linenr_t lnum;
int done = 0;
for (lnum = wp->w_topline; lnum <= wp->w_buffer->b_ml.ml_line_count; ++lnum)
{
if ((done += plines_win(wp, lnum)) > wp->w_height)
break;
}
wp->w_botline = lnum; /* wp->w_botline is the line that is just below the window */
}
static void
screenalloc(clear)
int clear;
{
static int old_Rows = 0;
static int old_Columns = 0;
register int i;
WIN *wp;
int outofmem = FALSE;
/*
* Allocation of the screen buffers is done only when the size changes
* and when Rows and Columns have been set.
*/
if ((Nextscreen != NULL && Rows == old_Rows && Columns == old_Columns) || Rows == 0 || Columns == 0)
return;
comp_col(); /* recompute columns for shown command and ruler */
old_Rows = Rows;
old_Columns = Columns;
/*
* If we're changing the size of the screen, free the old arrays
*/
free(Nextscreen);
free(LinePointers);
for (wp = firstwin; wp; wp = wp->w_next)
win_free_lsize(wp);
Nextscreen = (char_u *)malloc((size_t) (Rows * Columns));
LinePointers = (char_u **)malloc(sizeof(char_u *) * Rows);
for (wp = firstwin; wp; wp = wp->w_next)
{
if (win_alloc_lsize(wp) == FAIL)
{
outofmem = TRUE;
break;
}
}
if (Nextscreen == NULL || LinePointers == NULL || outofmem)
{
emsg(e_outofmem);
free(Nextscreen);
Nextscreen = NULL;
}
else
{
for (i = 0; i < Rows; ++i)
LinePointers[i] = Nextscreen + i * Columns;
}
if (clear)
screenclear2();
}
void
screenclear()
{
screenalloc(FALSE); /* allocate screen buffers if size changed */
screenclear2();
}
static void
screenclear2()
{
if (starting || Nextscreen == NULL)
return;
outstr(T_ED); /* clear the display */
/* blank out Nextscreen */
memset((char *)Nextscreen, ' ', (size_t)(Rows * Columns));
win_rest_invalid(firstwin);
clear_cmdline = FALSE;
if (must_redraw == CLEAR) /* no need to clear again */
must_redraw = NOT_VALID;
}
/*
* check cursor for a valid lnum
*/
void
check_cursor()
{
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
if (curwin->w_cursor.lnum <= 0)
curwin->w_cursor.lnum = 1;
}
void
cursupdate()
{
linenr_t p;
long nlines;
int i;
int temp;
screenalloc(TRUE); /* allocate screen buffers if size changed */
if (Nextscreen == NULL)
return;
check_cursor();
if (bufempty()) /* special case - file is empty */
{
curwin->w_topline = 1;
curwin->w_cursor.lnum = 1;
curwin->w_cursor.col = 0;
curwin->w_lsize[0] = 0;
if (curwin->w_lsize_valid == 0) /* don't know about screen contents */
updateScreen(NOT_VALID);
curwin->w_lsize_valid = 1;
}
else if (curwin->w_cursor.lnum < curwin->w_topline)
{
/*
* If the cursor is above the top of the screen, scroll the screen to
* put it at the top of the screen.
* If we weren't very close to begin with, we scroll more, so that
* the line is close to the middle.
*/
temp = curwin->w_height / 2 - 1;
if (temp < 2)
temp = 2;
if (curwin->w_topline - curwin->w_cursor.lnum >= temp) /* not very close */
{
p = curwin->w_cursor.lnum;
i = plines(p);
temp += i;
/* count lines for 1/2 screenheight */
while (i < curwin->w_height + 1 && i < temp && p > 1)
i += plines(--p);
curwin->w_topline = p;
if (i > curwin->w_height) /* cursor line won't fit, backup one line */
++curwin->w_topline;
}
else if (p_sj > 1) /* scroll at least p_sj lines */
{
for (i = 0; i < p_sj && curwin->w_topline > 1; i += plines(--curwin->w_topline))
;
}
if (curwin->w_topline > curwin->w_cursor.lnum)
curwin->w_topline = curwin->w_cursor.lnum;
updateScreen(VALID);
}
else if (curwin->w_cursor.lnum >= curwin->w_botline)
{
/*
* If the cursor is below the bottom of the screen, scroll the screen to
* put the cursor on the screen.
* If the cursor is less than a screenheight down
* compute the number of lines at the top which have the same or more
* rows than the rows of the lines below the bottom
*/
nlines = curwin->w_cursor.lnum - curwin->w_botline + 1;
if (nlines <= curwin->w_height + 1)
{
/* get the number or rows to scroll minus the number of
free '~' rows */
temp = plines_m(curwin->w_botline, curwin->w_cursor.lnum) - curwin->w_empty_rows;
if (temp <= 0) /* curwin->w_empty_rows is larger, no need to scroll */
nlines = 0;
else if (temp > curwin->w_height) /* more than a screenfull, don't scroll */
nlines = temp;
else
{
/* scroll minimal number of lines */
if (temp < p_sj)
temp = p_sj;
for (i = 0, p = curwin->w_topline; i < temp && p < curwin->w_botline; ++p)
i += plines(p);
if (i >= temp) /* it's possible to scroll */
nlines = p - curwin->w_topline;
else /* below curwin->w_botline, don't scroll */
nlines = 9999;
}
}
/*
* Scroll up if the cursor is off the bottom of the screen a bit.
* Otherwise put it at 1/2 of the screen.
*/
if (nlines >= curwin->w_height / 2 && nlines > p_sj)
{
p = curwin->w_cursor.lnum;
temp = curwin->w_height / 2 + 1;
nlines = 0;
i = 0;
do /* this loop could win a contest ... */
i += plines(p);
while (i < temp && (nlines = 1) != 0 && --p != 0);
curwin->w_topline = p + nlines;
}
else
scrollup(nlines);
updateScreen(VALID);
}
else if (curwin->w_lsize_valid == 0) /* don't know about screen contents */
updateScreen(NOT_VALID);
curwin->w_row = curwin->w_col = curwin->w_virtcol = i = 0;
for (p = curwin->w_topline; p != curwin->w_cursor.lnum; ++p)
if (RedrawingDisabled) /* curwin->w_lsize[] invalid */
curwin->w_row += plines(p);
else
curwin->w_row += curwin->w_lsize[i++];
Cline_row = curwin->w_row;
if (!RedrawingDisabled && i > curwin->w_lsize_valid)
/* Should only happen with a line that is too */
/* long to fit on the last screen line. */
Cline_height = 0;
else
{
if (RedrawingDisabled) /* curwin->w_lsize[] invalid */
Cline_height = plines(curwin->w_cursor.lnum);
else
Cline_height = curwin->w_lsize[i];
curs_columns(!RedrawingDisabled); /* compute curwin->w_virtcol and curwin->w_col */
if (must_redraw)
updateScreen(must_redraw);
}
if (curwin->w_set_curswant)
{
curwin->w_curswant = curwin->w_virtcol;
curwin->w_set_curswant = FALSE;
}
}
/*
* compute curwin->w_col and curwin->w_virtcol
*/
void
curs_columns(scroll)
int scroll; /* when TRUE, may scroll horizontally */
{
int diff;
curwin->w_virtcol = getvcol(curwin, &curwin->w_cursor, 1);
curwin->w_col = curwin->w_virtcol;
if (curwin->w_p_nu)
curwin->w_col += 8;
curwin->w_row = Cline_row;
if (curwin->w_p_wrap) /* long line wrapping, adjust curwin->w_row */
while (curwin->w_col >= Columns)
{
curwin->w_col -= Columns;
curwin->w_row++;
}
else if (scroll) /* no line wrapping, compute curwin->w_leftcol if scrolling is on */
/* if scrolling is off, curwin->w_leftcol is assumed to be 0 */
{
/* If Cursor is in columns 0, start in column 0 */
/* If Cursor is left of the screen, scroll rightwards */
/* If Cursor is right of the screen, scroll leftwards */
if (curwin->w_cursor.col == 0)
{
/* screen has to be redrawn with new curwin->w_leftcol */
if (curwin->w_leftcol != 0 && must_redraw < NOT_VALID)
must_redraw = NOT_VALID;
curwin->w_leftcol = 0;
}
else if (((diff = curwin->w_leftcol + (curwin->w_p_nu ? 8 : 0)
- curwin->w_col) > 0 ||
(diff = curwin->w_col - (curwin->w_leftcol + Columns) + 1) > 0))
{
if (p_ss == 0 || diff >= Columns / 2)
curwin->w_leftcol = curwin->w_col - Columns / 2;
else
{
if (diff < p_ss)
diff = p_ss;
if (curwin->w_col < curwin->w_leftcol + 8)
curwin->w_leftcol -= diff;
else
curwin->w_leftcol += diff;
}
if (curwin->w_leftcol < 0)
curwin->w_leftcol = 0;
if (must_redraw < NOT_VALID)
must_redraw = NOT_VALID; /* screen has to be redrawn with new curwin->w_leftcol */
}
curwin->w_col -= curwin->w_leftcol;
}
if (curwin->w_row > curwin->w_height - 1) /* Cursor past end of screen */
curwin->w_row = curwin->w_height - 1; /* happens with line that does not fit on screen */
}
/*
* get virtual column number of pos
* type = 1: where the cursor is on this character
* type = 2: on the first position of this character (TAB)
* type = 3: on the last position of this character (TAB)
*/
int
getvcol(wp, pos, type)
WIN *wp;
FPOS *pos;
int type;
{
int col;
int vcol;
char_u *ptr;
int incr;
int c;
vcol = 0;
ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
for (col = pos->col; col >= 0; --col)
{
c = *ptr++;
if (c == NUL) /* make sure we don't go past the end of the line */
break;
/* A tab gets expanded, depending on the current column */
incr = chartabsize(c, (long)vcol);
if (col == 0) /* character at pos.col */
{
if (type == 3 || (type == 1 && c == TAB && State == NORMAL && !wp->w_p_list))
--incr;
else
break;
}
vcol += incr;
}
return vcol;
}
void
scrolldown(nlines)
long nlines;
{
register long done = 0; /* total # of physical lines done */
/* Scroll up 'nlines' lines. */
while (nlines--)
{
if (curwin->w_topline == 1)
break;
done += plines(--curwin->w_topline);
}
/*
* Compute the row number of the last row of the cursor line
* and move it onto the screen.
*/
curwin->w_row += done;
if (curwin->w_p_wrap)
curwin->w_row += plines(curwin->w_cursor.lnum) - 1 - curwin->w_virtcol / Columns;
while (curwin->w_row >= curwin->w_height && curwin->w_cursor.lnum > 1)
curwin->w_row -= plines(curwin->w_cursor.lnum--);
}
void
scrollup(nlines)
long nlines;
{
#ifdef NEVER
register long done = 0; /* total # of physical lines done */
/* Scroll down 'nlines' lines. */
while (nlines--)
{
if (curwin->w_topline == curbuf->b_ml.ml_line_count)
break;
done += plines(curwin->w_topline);
if (curwin->w_cursor.lnum == curwin->w_topline)
++curwin->w_cursor.lnum;
++curwin->w_topline;
}
win_del_lines(curwin, 0, done, TRUE, TRUE);
#endif
curwin->w_topline += nlines;
if (curwin->w_topline > curbuf->b_ml.ml_line_count)
curwin->w_topline = curbuf->b_ml.ml_line_count;
if (curwin->w_cursor.lnum < curwin->w_topline)
curwin->w_cursor.lnum = curwin->w_topline;
}
/*
* insert 'nlines' lines at 'row' in window 'wp'
* if 'invalid' is TRUE the wp->w_lsize_lnum[] is invalidated.
* if 'mayclear' is TRUE the screen will be cleared if it is faster than scrolling
* Returns FAIL if the lines are not inserted, OK for success.
*/
int
win_ins_lines(wp, row, nlines, invalid, mayclear)
WIN *wp;
int row;
int nlines;
int invalid;
int mayclear;
{
int did_delete;
int nextrow;
int lastrow;
int retval;
if (invalid)
wp->w_lsize_valid = 0;
if (RedrawingDisabled || nlines <= 0 || wp->w_height < 5)
return FAIL;
if (nlines > wp->w_height - row)
nlines = wp->w_height - row;
if (mayclear && Rows - nlines < 5) /* only a few lines left: redraw is faster */
{
screenclear(); /* will set wp->w_lsize_valid to 0 */
return FAIL;
}
if (nlines == wp->w_height) /* will delete all lines */
return FAIL;
/*
* when scrolling, the message on the command line should be cleared,
* otherwise it will stay there forever.
*/
clear_cmdline = TRUE;
/*
* if the terminal can set a scroll region, use that
*/
if (scroll_region)
{
scroll_region_set(wp);
retval = screen_ins_lines(wp->w_winpos, row, nlines, wp->w_height);
scroll_region_reset();
return retval;
}
if (wp->w_next && p_tf) /* don't delete/insert on fast terminal */
return FAIL;
/*
* If there is a next window or a status line, we first try to delete the
* lines at the bottom to avoid messing what is after the window.
* If this fails and there are following windows, don't do anything to avoid
* messing up those windows, better just redraw.
*/
did_delete = FALSE;
if (wp->w_next || wp->w_status_height)
{
if (screen_del_lines(0, wp->w_winpos + wp->w_height - nlines, nlines, (int)Rows) == OK)
did_delete = TRUE;
else if (wp->w_next)
return FAIL;
}
/*
* if no lines deleted, blank the lines that will end up below the window
*/
if (!did_delete)
{
wp->w_redr_status = TRUE;
redraw_cmdline = TRUE;
nextrow = wp->w_winpos + wp->w_height + wp->w_status_height;
lastrow = nextrow + nlines;
if (lastrow > Rows)
lastrow = Rows;
screen_fill(nextrow - nlines, lastrow - nlines, 0, (int)Columns, ' ', ' ');
}
if (screen_ins_lines(0, wp->w_winpos + row, nlines, (int)Rows) == FAIL)
{
/* deletion will have messed up other windows */
if (did_delete)
{
wp->w_redr_status = TRUE;
win_rest_invalid(wp->w_next);
}
return FAIL;
}
return OK;
}
/*
* delete 'nlines' lines at 'row' in window 'wp'
* If 'invalid' is TRUE curwin->w_lsize_lnum[] is invalidated.
* If 'mayclear' is TRUE the screen will be cleared if it is faster than scrolling
* Return OK for success, FAIL if the lines are not deleted.
*/
int
win_del_lines(wp, row, nlines, invalid, mayclear)
WIN *wp;
int row;
int nlines;
int invalid;
int mayclear;
{
int retval;
if (invalid)
wp->w_lsize_valid = 0;
if (RedrawingDisabled || nlines <= 0)
return FAIL;
if (nlines > wp->w_height - row)
nlines = wp->w_height - row;
if (mayclear && Rows - nlines < 5) /* only a few lines left: redraw is faster */
{
screenclear(); /* will set wp->w_lsize_valid to 0 */
return FAIL;
}
if (nlines == wp->w_height) /* will delete all lines */
return FAIL;
/*
* when scrolling, the message on the command line should be cleared,
* otherwise it will stay there forever.
*/
clear_cmdline = TRUE;
/*
* if the terminal can set a scroll region, use that
*/
if (scroll_region)
{
scroll_region_set(wp);
retval = screen_del_lines(wp->w_winpos, row, nlines, wp->w_height);
scroll_region_reset();
return retval;
}
if (wp->w_next && p_tf) /* don't delete/insert on fast terminal */
return FAIL;
if (screen_del_lines(0, wp->w_winpos + row, nlines, (int)Rows) == FAIL)
return FAIL;
/*
* If there are windows or status lines below, try to put them at the
* correct place. If we can't do that, they have to be redrawn.
*/
if (wp->w_next || wp->w_status_height || cmdline_row < Rows - 1)
{
if (screen_ins_lines(0, wp->w_winpos + wp->w_height - nlines, nlines, (int)Rows) == FAIL)
{
wp->w_redr_status = TRUE;
win_rest_invalid(wp->w_next);
}
}
/*
* If this is the last window and there is no status line, redraw the
* command line later.
*/
else
redraw_cmdline = TRUE;
return OK;
}
/*
* window 'wp' and everything after it is messed up, mark it for redraw
*/
void
win_rest_invalid(wp)
WIN *wp;
{
while (wp)
{
wp->w_lsize_valid = 0;
wp->w_redr_type = NOT_VALID;
wp->w_redr_status = TRUE;
wp = wp->w_next;
}
redraw_cmdline = TRUE;
}
/*
* The rest of the routines in this file perform screen manipulations. The
* given operation is performed physically on the screen. The corresponding
* change is also made to the internal screen image. In this way, the editor
* anticipates the effect of editing changes on the appearance of the screen.
* That way, when we call screenupdate a complete redraw isn't usually
* necessary. Another advantage is that we can keep adding code to anticipate
* screen changes, and in the meantime, everything still works.
*/
/*
* insert lines on the screen and update Nextscreen
* 'end' is the line after the scrolled part. Normally it is Rows.
* When scrolling region used 'off' is the offset from the top for the region.
* 'row' and 'end' are relative to the start of the region.
*
* return FAIL for failure, OK for success.
*/
static int
screen_ins_lines(off, row, nlines, end)
int off;
int row;
int nlines;
int end;
{
int i;
int j;
char_u *temp;
int cursor_row;
if (T_CSC != NULL && *T_CSC != NUL) /* cursor relative to region */
cursor_row = row;
else
cursor_row = row + off;
screenalloc(TRUE); /* allocate screen buffers if size changed */
if (Nextscreen == NULL)
return FAIL;
if (nlines <= 0 || ((T_CIL == NULL || *T_CIL == NUL) &&
(T_IL == NULL || *T_IL == NUL) &&
(T_SR == NULL || *T_SR == NUL || row != 0)))
return FAIL;
/*
* It "looks" better if we do all the inserts at once
*/
if (T_CIL && *T_CIL)
{
windgoto(cursor_row, 0);
if (nlines == 1 && T_IL && *T_IL)
outstr(T_IL);
else
OUTSTR(tgoto((char *)T_CIL, 0, nlines));
}
else
{
for (i = 0; i < nlines; i++)
{
if (i == 0 || cursor_row != 0)
windgoto(cursor_row, 0);
if (T_IL && *T_IL)
outstr(T_IL);
else
outstr(T_SR);
}
}
/*
* Now shift LinePointers nlines down to reflect the inserted lines.
* Clear the inserted lines.
*/
row += off;
end += off;
for (i = 0; i < nlines; ++i)
{
j = end - 1 - i;
temp = LinePointers[j];
while ((j -= nlines) >= row)
LinePointers[j + nlines] = LinePointers[j];
LinePointers[j + nlines] = temp;
memset((char *)temp, ' ', (size_t)Columns);
}
return OK;
}
/*
* delete lines on the screen and update Nextscreen
* 'end' is the line after the scrolled part. Normally it is Rows.
* When scrolling region used 'off' is the offset from the top for the region.
* 'row' and 'end' are relative to the start of the region.
*
* Return OK for success, FAIL if the lines are not deleted.
*/
int
screen_del_lines(off, row, nlines, end)
int off;
int row;
int nlines;
int end;
{
int j;
int i;
char_u *temp;
int cursor_row;
int cursor_end;
if (T_CSC != NULL && *T_CSC != NUL) /* cursor relative to region */
{
cursor_row = row;
cursor_end = end;
}
else
{
cursor_row = row + off;
cursor_end = end + off;
}
screenalloc(TRUE); /* allocate screen buffers if size changed */
if (Nextscreen == NULL)
return FAIL;
if (nlines <= 0 || ((T_DL == NULL || *T_DL == NUL) &&
(T_CDL == NULL || *T_CDL == NUL) &&
row != 0))
return FAIL;
/* delete the lines */
if (T_CDL && *T_CDL)
{
windgoto(cursor_row, 0);
if (nlines == 1 && T_DL && *T_DL)
outstr(T_DL);
else
OUTSTR(tgoto((char *)T_CDL, 0, nlines));
}
else
{
if (row == 0)
{
windgoto(cursor_end - 1, 0);
for (i = 0; i < nlines; i++)
outchar('\n');
}
else
{
for (i = 0; i < nlines; i++)
{
windgoto(cursor_row, 0);
outstr(T_DL); /* delete a line */
}
}
}
/*
* Now shift LinePointers nlines up to reflect the deleted lines.
* Clear the deleted lines.
*/
row += off;
end += off;
for (i = 0; i < nlines; ++i)
{
j = row + i;
temp = LinePointers[j];
while ((j += nlines) <= end - 1)
LinePointers[j - nlines] = LinePointers[j];
LinePointers[j - nlines] = temp;
memset((char *)temp, ' ', (size_t)Columns);
}
return OK;
}
/*
* show the current mode and ruler
*
* If clear_cmdline is TRUE, clear it first.
* If clear_cmdline is FALSE there may be a message there that needs to be
* cleared only if a mode is shown.
*/
void
showmode()
{
int did_clear = clear_cmdline;
int need_clear = FALSE;
if ((p_smd && (State & INSERT)) || Recording)
{
gotocmdline(clear_cmdline, NUL);
if (p_smd)
{
if (State & INSERT)
{
msg_outstr((char_u *)"-- ");
if (p_ri)
msg_outstr((char_u *)"REVERSE ");
if (State == INSERT)
msg_outstr((char_u *)"INSERT --");
else
msg_outstr((char_u *)"REPLACE --");
need_clear = TRUE;
}
}
if (Recording)
{
msg_outstr((char_u *)"recording");
need_clear = TRUE;
}
if (need_clear && !did_clear)
msg_ceol();
}
win_redr_ruler(lastwin, TRUE);
redraw_cmdline = FALSE;
}
/*
* delete mode message
*/
void
delmode()
{
if (Recording)
MSG("recording");
else
MSG("");
}
/*
* if ruler option is set: show current cursor position
* if always is FALSE, only print if position has changed
*/
void
showruler(always)
int always;
{
win_redr_ruler(curwin, always);
}
void
win_redr_ruler(wp, always)
WIN *wp;
int always;
{
static linenr_t oldlnum = 0;
static colnr_t oldcol = 0;
char_u buffer[30];
int row;
int fillchar;
if (p_ru && (redraw_cmdline || always || wp->w_cursor.lnum != oldlnum || wp->w_virtcol != oldcol))
{
cursor_off();
if (wp->w_status_height)
{
row = wp->w_winpos + wp->w_height;
if (set_highlight('s') == OK) /* can use highlighting */
{
fillchar = ' ';
start_highlight();
}
else
fillchar = '=';
}
else
{
row = Rows - 1;
fillchar = ' ';
}
/*
* Some sprintfs return the lenght, some return a pointer.
* To avoid portability problems we use strlen here.
*/
sprintf((char *)buffer, "%ld,%d", wp->w_cursor.lnum, (int)wp->w_cursor.col + 1);
if (wp->w_cursor.col != wp->w_virtcol)
sprintf((char *)buffer + STRLEN(buffer), "-%d", wp->w_virtcol + 1);
screen_start(); /* init cursor position */
screen_msg(buffer, row, ru_col);
screen_fill(row, row + 1, ru_col + (int)STRLEN(buffer), (int)Columns, fillchar, fillchar);
oldlnum = wp->w_cursor.lnum;
oldcol = wp->w_virtcol;
stop_highlight();
}
}
/*
* screen_valid: Returns TRUE if there is a valid screen to write to.
* Returns FALSE when starting up and screen not initialized yet.
* Used by msg() to decide to use either screen_msg() or printf().
*/
int
screen_valid()
{
screenalloc(FALSE); /* allocate screen buffers if size changed */
return (Nextscreen != NULL);
}