#include <stdio.h>
#include <xterm.h>
#include <error.h>
#include <data.h>
#include <xcharmouse.h>
#include <xterm_io.h>
#if OPT_WIDE_CHARS
#include <fontutils.h>
#include <menu.h>
#endif
#include <assert.h>
#include <signal.h>
#define getMinRow(screen) ((term->flags & ORIGIN) ? (screen)->top_marg : 0)
#define getMaxRow(screen) ((term->flags & ORIGIN) ? (screen)->bot_marg : (screen)->max_row)
#define getMinCol(screen) 0
#define getMaxCol(screen) ((screen)->max_col)
ScrnBuf
Allocate(int nrow, int ncol, Char ** addr)
{
ScrnBuf base;
Char *tmp;
int i, j, k;
size_t entries = MAX_PTRS * nrow;
size_t length = BUF_PTRS * nrow * ncol;
if ((base = TypeCallocN(ScrnPtr, entries)) == 0)
SysError(ERROR_SCALLOC);
if ((tmp = TypeCallocN(Char, length)) == 0)
SysError(ERROR_SCALLOC2);
*addr = tmp;
for (i = k = 0; i < nrow; i++) {
base[k] = 0;
k += BUF_HEAD;
for (j = BUF_HEAD; j < MAX_PTRS; j++) {
base[k++] = tmp;
tmp += ncol;
}
}
return (base);
}
static int
Reallocate(ScrnBuf * sbuf,
Char ** sbufaddr,
int nrow,
int ncol,
int oldrow,
int oldcol)
{
ScrnBuf base;
Char *tmp;
int i, j, k, minrows;
size_t mincols;
Char *oldbuf;
int move_down = 0, move_up = 0;
size_t entries = MAX_PTRS * nrow;
size_t length = BUF_PTRS * nrow * ncol;
if (sbuf == NULL || *sbuf == NULL) {
return 0;
}
oldbuf = *sbufaddr;
if (nrow < oldrow
&& term->misc.resizeGravity == SouthWestGravity) {
move_up = (oldrow - nrow)
- (term->screen.max_row - term->screen.cur_row);
if (move_up < 0)
move_up = 0;
memmove(*sbuf, *sbuf + (move_up * MAX_PTRS),
MAX_PTRS * (oldrow - move_up) * sizeof((*sbuf)[0]));
}
*sbuf = TypeRealloc(ScrnPtr, entries, *sbuf);
if (*sbuf == 0)
SysError(ERROR_RESIZE);
base = *sbuf;
if ((tmp = TypeCallocN(Char, length)) == 0)
SysError(ERROR_SREALLOC);
*sbufaddr = tmp;
minrows = (oldrow < nrow) ? oldrow : nrow;
mincols = (oldcol < ncol) ? oldcol : ncol;
if (nrow > oldrow
&& term->misc.resizeGravity == SouthWestGravity) {
move_down = Min(nrow - oldrow, term->screen.savedlines);
tmp += (ncol * move_down * BUF_PTRS);
}
for (i = k = 0; i < minrows; i++) {
k += BUF_HEAD;
for (j = BUF_HEAD; j < MAX_PTRS; j++) {
memcpy(tmp, base[k++], mincols);
tmp += ncol;
}
}
for (i = k = 0, tmp = *sbufaddr; i < nrow; i++) {
for (j = 0; j < BUF_HEAD; j++)
base[k++] = 0;
for (j = BUF_HEAD; j < MAX_PTRS; j++) {
base[k++] = tmp;
tmp += ncol;
}
}
free(oldbuf);
return move_down ? move_down : -move_up;
}
#if OPT_WIDE_CHARS
#if 0
static void
dump_screen(const char *tag,
ScrnBuf sbuf,
Char * sbufaddr,
unsigned nrow,
unsigned ncol)
{
unsigned y, x;
TRACE(("DUMP %s, ptrs %d\n", tag, term->num_ptrs));
TRACE((" sbuf %p\n", sbuf));
TRACE((" sbufaddr %p\n", sbufaddr));
TRACE((" nrow %d\n", nrow));
TRACE((" ncol %d\n", ncol));
for (y = 0; y < nrow; ++y) {
ScrnPtr ptr = BUF_CHARS(sbuf, y);
TRACE(("%3d:%p:", y, ptr));
for (x = 0; x < ncol; ++x) {
Char c = ptr[x];
if (c == 0)
c = '~';
TRACE(("%c", c));
}
TRACE(("\n"));
}
}
#else
#define dump_screen(tag, sbuf, sbufaddr, nrow, ncol)
#endif
static void
ReallocateBufOffsets(ScrnBuf * sbuf,
Char ** sbufaddr,
unsigned nrow,
unsigned ncol,
size_t new_max_offsets)
{
unsigned i;
int j, k;
ScrnBuf base;
Char *oldbuf, *tmp;
size_t entries, length;
int old_max_ptrs = MAX_PTRS;
assert(nrow != 0);
assert(ncol != 0);
assert(new_max_offsets != 0);
dump_screen("before", *sbuf, *sbufaddr, nrow, ncol);
term->num_ptrs = new_max_offsets;
entries = MAX_PTRS * nrow;
length = BUF_PTRS * nrow * ncol;
oldbuf = *sbufaddr;
*sbuf = TypeRealloc(ScrnPtr, entries, *sbuf);
if (*sbuf == 0)
SysError(ERROR_RESIZE);
base = *sbuf;
if ((tmp = TypeCallocN(Char, length)) == 0)
SysError(ERROR_SREALLOC);
*sbufaddr = tmp;
for (i = k = 0; i < nrow; i++) {
k += BUF_HEAD;
for (j = BUF_HEAD; j < old_max_ptrs; j++) {
memcpy(tmp, base[k++], ncol);
tmp += ncol;
}
tmp += ncol * (new_max_offsets - old_max_ptrs);
}
for (i = k = 0, tmp = *sbufaddr; i < nrow; i++) {
for (j = 0; j < BUF_HEAD; j++)
base[k++] = 0;
for (j = BUF_HEAD; j < MAX_PTRS; j++) {
base[k++] = tmp;
tmp += ncol;
}
}
free(oldbuf);
dump_screen("after", *sbuf, *sbufaddr, nrow, ncol);
term->num_ptrs = old_max_ptrs;
}
void
ChangeToWide(TScreen * screen)
{
unsigned new_bufoffset = (OFF_COM2H + 1);
int savelines = screen->scrollWidget ? screen->savelines : 0;
if (screen->wide_chars)
return;
TRACE(("ChangeToWide\n"));
if (xtermLoadWideFonts(term, True)) {
if (savelines < 0)
savelines = 0;
ReallocateBufOffsets(&screen->allbuf, &screen->sbuf_address,
(unsigned) (MaxRows(screen) + savelines),
(unsigned) MaxCols(screen),
new_bufoffset);
if (screen->altbuf)
ReallocateBufOffsets(&screen->altbuf, &screen->abuf_address,
(unsigned) MaxRows(screen),
(unsigned) MaxCols(screen),
new_bufoffset);
screen->wide_chars = True;
term->num_ptrs = new_bufoffset;
screen->visbuf = &screen->allbuf[MAX_PTRS * savelines];
update_font_utf8_mode();
SetVTFont(term, screen->menu_font_number, TRUE, NULL);
}
TRACE(("...ChangeToWide\n"));
}
#endif
void
ScrnDisownSelection(TScreen * screen)
{
if (ScrnHaveSelection(screen)) {
DisownSelection(term);
}
}
void
ScreenWrite(TScreen * screen,
PAIRED_CHARS(Char * str, Char * str2),
unsigned flags,
unsigned cur_fg_bg,
unsigned length)
{
#if OPT_ISO_COLORS
#if OPT_EXT_COLORS
Char *fbf = 0;
Char *fbb = 0;
#else
Char *fb = 0;
#endif
#endif
#if OPT_DEC_CHRSET
Char *cb = 0;
#endif
Char *attrs;
int avail = MaxCols(screen) - screen->cur_col;
Char *chars;
int wrappedbit;
#if OPT_WIDE_CHARS
Char starcol1, starcol2;
Char *comb1l = 0, *comb1h = 0, *comb2l = 0, *comb2h = 0;
#endif
unsigned real_width = visual_width(PAIRED_CHARS(str, str2), length);
if (avail <= 0)
return;
if (length > (unsigned) avail)
length = avail;
if (length == 0 || real_width == 0)
return;
chars = SCRN_BUF_CHARS(screen, screen->cur_row) + screen->cur_col;
attrs = SCRN_BUF_ATTRS(screen, screen->cur_row) + screen->cur_col;
if_OPT_WIDE_CHARS(screen, {
comb1l = SCRN_BUF_COM1L(screen, screen->cur_row) + screen->cur_col;
comb1h = SCRN_BUF_COM1H(screen, screen->cur_row) + screen->cur_col;
comb2l = SCRN_BUF_COM2L(screen, screen->cur_row) + screen->cur_col;
comb2h = SCRN_BUF_COM2H(screen, screen->cur_row) + screen->cur_col;
});
if_OPT_EXT_COLORS(screen, {
fbf = SCRN_BUF_FGRND(screen, screen->cur_row) + screen->cur_col;
fbb = SCRN_BUF_BGRND(screen, screen->cur_row) + screen->cur_col;
});
if_OPT_ISO_TRADITIONAL_COLORS(screen, {
fb = SCRN_BUF_COLOR(screen, screen->cur_row) + screen->cur_col;
});
if_OPT_DEC_CHRSET({
cb = SCRN_BUF_CSETS(screen, screen->cur_row) + screen->cur_col;
});
wrappedbit = ScrnTstWrapped(screen, screen->cur_row);
#if OPT_WIDE_CHARS
starcol1 = *chars;
starcol2 = chars[length - 1];
#endif
if (flags & INVISIBLE) {
memset(chars, ' ', length);
} else {
memcpy(chars, str, length);
}
#if OPT_BLINK_TEXT
if ((flags & BLINK) && !(screen->blink_as_bold)) {
ScrnSetBlinked(screen, screen->cur_row);
}
#endif
#define ERROR_1 0x20
#define ERROR_2 0x00
if_OPT_WIDE_CHARS(screen, {
Char *char2;
if (real_width != length) {
Char *char1 = chars;
char2 = SCRN_BUF_WIDEC(screen, screen->cur_row);
char2 += screen->cur_col;
if (screen->cur_col && starcol1 == HIDDEN_LO && *char2 == HIDDEN_HI
&& iswide(char1[-1] | (char2[-1] << 8))) {
char1[-1] = ERROR_1;
char2[-1] = ERROR_2;
}
while (length) {
int ch = *str;
if (str2)
ch |= *str2 << 8;
*char1 = *str;
char1++;
str++;
if (str2) {
*char2 = *str2;
str2++;
} else
*char2 = 0;
char2++;
length--;
if (iswide(ch)) {
*char1 = HIDDEN_LO;
*char2 = HIDDEN_HI;
char1++;
char2++;
}
}
if (*char1 == HIDDEN_LO
&& *char2 == HIDDEN_HI
&& char1[-1] == HIDDEN_LO
&& char2[-1] == HIDDEN_HI) {
*char1 = ERROR_1;
*char2 = ERROR_2;
}
}
else {
if ((char2 = SCRN_BUF_WIDEC(screen, screen->cur_row)) != 0) {
char2 += screen->cur_col;
if (screen->cur_col && starcol1 == HIDDEN_LO && *char2 == HIDDEN_HI
&& iswide(chars[-1] | (char2[-1] << 8))) {
chars[-1] = ERROR_1;
char2[-1] = ERROR_2;
}
if (chars[length] == HIDDEN_LO && char2[length] == HIDDEN_HI &&
iswide(starcol2 | (char2[length - 1] << 8))) {
chars[length] = ERROR_1;
char2[length] = ERROR_2;
}
if ((flags & INVISIBLE) || (str2 == 0))
memset(char2, 0, length);
else
memcpy(char2, str2, length);
}
}
});
flags &= ATTRIBUTES;
flags |= CHARDRAWN;
memset(attrs, (Char) flags, real_width);
if_OPT_WIDE_CHARS(screen, {
memset(comb1l, 0, real_width);
memset(comb2l, 0, real_width);
memset(comb1h, 0, real_width);
memset(comb2h, 0, real_width);
});
if_OPT_EXT_COLORS(screen, {
memset(fbf, (Char) (cur_fg_bg >> 8), real_width);
memset(fbb, (Char) (cur_fg_bg & 0xff), real_width);
});
if_OPT_ISO_TRADITIONAL_COLORS(screen, {
memset(fb, cur_fg_bg, real_width);
});
if_OPT_DEC_CHRSET({
memset(cb, curXtermChrSet(screen->cur_row), real_width);
});
if (wrappedbit)
ScrnSetWrapped(screen, screen->cur_row);
else
ScrnClrWrapped(screen, screen->cur_row);
if_OPT_WIDE_CHARS(screen, {
screen->last_written_col = screen->cur_col + real_width - 1;
screen->last_written_row = screen->cur_row;
});
if_OPT_XMC_GLITCH(screen, {
Resolve_XMC(screen);
});
}
static void
ScrnClearLines(TScreen * screen, ScrnBuf sb, int where, unsigned n, unsigned size)
{
int i, j;
size_t len = ScrnPointers(screen, n);
int last = (n * MAX_PTRS);
TRACE(("ScrnClearLines(where %d, n %d, size %d)\n", where, n, size));
assert(n != 0);
assert(size != 0);
memcpy((char *) screen->save_ptr,
(char *) &sb[MAX_PTRS * where],
len);
if (TERM_COLOR_FLAGS(term)) {
int flags = TERM_COLOR_FLAGS(term);
for (i = 0; i < last; i += MAX_PTRS) {
for (j = 0; j < MAX_PTRS; j++) {
if (j < BUF_HEAD)
screen->save_ptr[i + j] = 0;
else if (j == OFF_ATTRS)
memset(screen->save_ptr[i + j], flags, size);
#if OPT_ISO_COLORS
#if OPT_EXT_COLORS
else if (j == OFF_FGRND)
memset(screen->save_ptr[i + j], term->sgr_foreground, size);
else if (j == OFF_BGRND)
memset(screen->save_ptr[i + j], term->cur_background, size);
#else
else if (j == OFF_COLOR)
memset(screen->save_ptr[i + j], xtermColorPair(), size);
#endif
#endif
else
bzero(screen->save_ptr[i + j], size);
}
}
} else {
for (i = 0; i < last; i += MAX_PTRS) {
for (j = 0; j < BUF_HEAD; j++)
screen->save_ptr[i + j] = 0;
for (j = BUF_HEAD; j < MAX_PTRS; j++)
bzero(screen->save_ptr[i + j], size);
}
}
}
size_t
ScrnPointers(TScreen * screen, size_t len)
{
len *= MAX_PTRS;
if (len > screen->save_len) {
if (screen->save_len)
screen->save_ptr = TypeRealloc(ScrnPtr, len, screen->save_ptr);
else
screen->save_ptr = TypeMallocN(ScrnPtr, len);
screen->save_len = len;
if (screen->save_ptr == 0)
SysError(ERROR_SAVE_PTR);
}
return len * sizeof(ScrnPtr);
}
void
ScrnInsertLine(TScreen * screen, ScrnBuf sb, int last, int where,
unsigned n, unsigned size)
{
size_t len = ScrnPointers(screen, n);
assert(where >= 0);
assert(last >= (int) n);
assert(last >= where);
assert(n != 0);
assert(size != 0);
assert(MAX_PTRS > 0);
ScrnClearLines(screen, sb, (last -= n - 1), n, size);
assert(last >= where);
memmove((char *) &sb[MAX_PTRS * (where + n)],
(char *) &sb[MAX_PTRS * where],
MAX_PTRS * sizeof(char *) * (last - where));
memcpy((char *) &sb[MAX_PTRS * where],
(char *) screen->save_ptr,
len);
}
void
ScrnDeleteLine(TScreen * screen, ScrnBuf sb, int last, int where,
unsigned n, unsigned size)
{
assert(where >= 0);
assert(last >= where + (int) n - 1);
assert(n != 0);
assert(size != 0);
assert(MAX_PTRS > 0);
ScrnClearLines(screen, sb, where, n, size);
memmove((char *) &sb[MAX_PTRS * where],
(char *) &sb[MAX_PTRS * (where + n)],
MAX_PTRS * sizeof(char *) * ((last -= n - 1) - where));
memcpy((char *) &sb[MAX_PTRS * last],
(char *) screen->save_ptr,
MAX_PTRS * sizeof(char *) * n);
}
void
ScrnInsertChar(TScreen * screen, unsigned n)
{
ScrnBuf sb = screen->visbuf;
unsigned last = MaxCols(screen);
int row = screen->cur_row;
unsigned col = screen->cur_col;
unsigned i;
Char *ptr = BUF_CHARS(sb, row);
Char *attrs = BUF_ATTRS(sb, row);
int wrappedbit = ScrnTstWrapped(screen, row);
int flags = CHARDRAWN | TERM_COLOR_FLAGS(term);
size_t nbytes;
if (last <= (col + n)) {
if (last <= col)
return;
n = last - col;
}
nbytes = (last - (col + n));
assert(screen->cur_col >= 0);
assert(screen->cur_row >= 0);
assert(n > 0);
assert(last > n);
ScrnClrWrapped(screen, row);
for (i = last - 1; i >= col + n; i--) {
unsigned j = i - n;
assert(i >= n);
ptr[i] = ptr[j];
attrs[i] = attrs[j];
}
for (i = col; i < col + n; i++)
ptr[i] = ' ';
for (i = col; i < col + n; i++)
attrs[i] = flags;
if_OPT_EXT_COLORS(screen, {
ptr = BUF_FGRND(sb, row);
memmove(ptr + col + n, ptr + col, nbytes);
memset(ptr + col, term->sgr_foreground, n);
ptr = BUF_BGRND(sb, row);
memmove(ptr + col + n, ptr + col, nbytes);
memset(ptr + col, term->cur_background, n);
});
if_OPT_ISO_TRADITIONAL_COLORS(screen, {
ptr = BUF_COLOR(sb, row);
memmove(ptr + col + n, ptr + col, nbytes);
memset(ptr + col, xtermColorPair(), n);
});
if_OPT_DEC_CHRSET({
ptr = BUF_CSETS(sb, row);
memmove(ptr + col + n, ptr + col, nbytes);
memset(ptr + col, curXtermChrSet(row), n);
});
if_OPT_WIDE_CHARS(screen, {
ptr = BUF_WIDEC(sb, row);
memmove(ptr + col + n, ptr + col, nbytes);
memset(ptr + col, 0, n);
ptr = BUF_COM1L(sb, row);
memmove(ptr + col + n, ptr + col, nbytes);
memset(ptr + col, 0, n);
ptr = BUF_COM1H(sb, row);
memmove(ptr + col + n, ptr + col, nbytes);
memset(ptr + col, 0, n);
ptr = BUF_COM2L(sb, row);
memmove(ptr + col + n, ptr + col, nbytes);
memset(ptr + col, 0, n);
ptr = BUF_COM2H(sb, row);
memmove(ptr + col + n, ptr + col, nbytes);
memset(ptr + col, 0, n);
});
if (wrappedbit)
ScrnSetWrapped(screen, row);
else
ScrnClrWrapped(screen, row);
}
void
ScrnDeleteChar(TScreen * screen, unsigned n)
{
ScrnBuf sb = screen->visbuf;
unsigned last = MaxCols(screen);
unsigned row = screen->cur_row;
unsigned col = screen->cur_col;
Char *ptr = BUF_CHARS(sb, row);
Char *attrs = BUF_ATTRS(sb, row);
size_t nbytes;
if (last <= (col + n)) {
if (last <= col)
return;
n = last - col;
}
nbytes = (last - (col + n));
assert(screen->cur_col >= 0);
assert(screen->cur_row >= 0);
assert(n > 0);
assert(last > n);
memmove(ptr + col, ptr + col + n, nbytes);
memmove(attrs + col, attrs + col + n, nbytes);
bzero(ptr + last - n, n);
memset(attrs + last - n, (Char) (TERM_COLOR_FLAGS(term)), n);
if_OPT_EXT_COLORS(screen, {
ptr = BUF_FGRND(sb, row);
memmove(ptr + col, ptr + col + n, nbytes);
memset(ptr + last - n, term->sgr_foreground, n);
ptr = BUF_BGRND(sb, row);
memmove(ptr + col, ptr + col + n, nbytes);
memset(ptr + last - n, term->cur_background, n);
});
if_OPT_ISO_TRADITIONAL_COLORS(screen, {
ptr = BUF_COLOR(sb, row);
memmove(ptr + col, ptr + col + n, nbytes);
memset(ptr + last - n, xtermColorPair(), n);
});
if_OPT_DEC_CHRSET({
ptr = BUF_CSETS(sb, row);
memmove(ptr + col, ptr + col + n, nbytes);
memset(ptr + last - n, curXtermChrSet(row), n);
});
if_OPT_WIDE_CHARS(screen, {
ptr = BUF_WIDEC(sb, row);
memmove(ptr + col, ptr + col + n, nbytes);
memset(ptr + last - n, 0, n);
ptr = BUF_COM1L(sb, row);
memmove(ptr + col, ptr + col + n, nbytes);
memset(ptr + last - n, 0, n);
ptr = BUF_COM1H(sb, row);
memmove(ptr + col, ptr + col + n, nbytes);
memset(ptr + last - n, 0, n);
ptr = BUF_COM2L(sb, row);
memmove(ptr + col, ptr + col + n, nbytes);
memset(ptr + last - n, 0, n);
ptr = BUF_COM2H(sb, row);
memmove(ptr + col, ptr + col + n, nbytes);
memset(ptr + last - n, 0, n);
});
ScrnClrWrapped(screen, row);
}
void
ScrnRefresh(TScreen * screen,
int toprow,
int leftcol,
int nrows,
int ncols,
Bool force)
{
int y = toprow * FontHeight(screen) + screen->border;
int row;
int topline = screen->topline;
int maxrow = toprow + nrows - 1;
int scrollamt = screen->scroll_amt;
int max = screen->max_row;
int gc_changes = 0;
#ifdef __CYGWIN__
static char first_time = 1;
#endif
static int recurse = 0;
TRACE(("ScrnRefresh (%d,%d) - (%d,%d)%s\n",
toprow, leftcol,
nrows, ncols,
force ? " force" : ""));
if (screen->cursor_col >= leftcol
&& screen->cursor_col <= (leftcol + ncols - 1)
&& screen->cursor_row >= toprow + topline
&& screen->cursor_row <= maxrow + topline)
screen->cursor_state = OFF;
for (row = toprow; row <= maxrow; y += FontHeight(screen), row++) {
#if OPT_ISO_COLORS
#if OPT_EXT_COLORS
Char *fbf = 0;
Char *fbb = 0;
#define ColorOf(col) (unsigned) ((fbf[col] << 8) | fbb[col])
#else
Char *fb = 0;
#define ColorOf(col) (unsigned) (fb[col])
#endif
#endif
#if OPT_DEC_CHRSET
Char *cb = 0;
#endif
#if OPT_WIDE_CHARS
int wideness = 0;
Char *widec = 0;
#define WIDEC_PTR(cell) widec ? &widec[cell] : 0
#define BLANK_CEL(cell) ((chars[cell] == ' ') && (widec == 0 || widec[cell] == 0))
#else
#define BLANK_CEL(cell) (chars[cell] == ' ')
#endif
Char cs = 0;
Char *chars;
Char *attrs;
int col = leftcol;
int maxcol = leftcol + ncols - 1;
int hi_col = maxcol;
int lastind;
unsigned flags;
unsigned test;
unsigned fg_bg = 0, fg = 0, bg = 0;
int x;
GC gc;
Bool hilite;
if (row < screen->top_marg || row > screen->bot_marg)
lastind = row;
else
lastind = row - scrollamt;
TRACE(("ScrnRefresh row=%d lastind=%d/%d\n", row, lastind, max));
if (lastind < 0 || lastind > max)
continue;
chars = SCRN_BUF_CHARS(screen, lastind + topline);
attrs = SCRN_BUF_ATTRS(screen, lastind + topline);
if_OPT_DEC_CHRSET({
cb = SCRN_BUF_CSETS(screen, lastind + topline);
});
if_OPT_WIDE_CHARS(screen, {
widec = SCRN_BUF_WIDEC(screen, lastind + topline);
});
if_OPT_WIDE_CHARS(screen, {
if (recurse < 3) {
if (leftcol > 0 &&
(chars[leftcol] | (widec[leftcol] << 8)) == HIDDEN_CHAR &&
iswide(chars[leftcol - 1] | (widec[leftcol - 1] << 8))) {
leftcol--;
ncols++;
col = leftcol;
}
} else {
fprintf(stderr, "This should not happen. Why is it so?\n");
}
});
if (row < screen->startHRow || row > screen->endHRow ||
(row == screen->startHRow && maxcol < screen->startHCol) ||
(row == screen->endHRow && col >= screen->endHCol)) {
#if OPT_DEC_CHRSET
if (CSET_DOUBLE(*cb)) {
col /= 2;
maxcol /= 2;
}
#endif
if (!force) {
while (col <= maxcol && (attrs[col] & ~BOLD) == 0 &&
BLANK_CEL(col))
col++;
while (col <= maxcol && (attrs[maxcol] & ~BOLD) == 0 &&
BLANK_CEL(maxcol))
maxcol--;
}
#if OPT_DEC_CHRSET
if (CSET_DOUBLE(*cb)) {
col *= 2;
maxcol *= 2;
}
#endif
hilite = False;
} else {
if (row == screen->startHRow && col < screen->startHCol) {
recurse++;
ScrnRefresh(screen, row, col, 1, screen->startHCol - col,
force);
col = screen->startHCol;
}
if (row == screen->endHRow && maxcol >= screen->endHCol) {
recurse++;
ScrnRefresh(screen, row, screen->endHCol, 1,
maxcol - screen->endHCol + 1, force);
maxcol = screen->endHCol - 1;
}
if (screen->highlight_selection
&& screen->send_mouse_pos != VT200_HIGHLIGHT_MOUSE) {
hi_col = screen->max_col;
while (hi_col > 0 && !(attrs[hi_col] & CHARDRAWN))
hi_col--;
}
hilite = True;
}
if (col > maxcol)
continue;
if_OPT_DEC_CHRSET({
if (CSET_DOUBLE(*cb)) {
col /= 2;
maxcol /= 2;
}
cs = cb[col];
});
flags = attrs[col];
#if OPT_WIDE_CHARS
if (widec)
wideness = iswide(chars[col] | (widec[col] << 8));
else
wideness = 0;
#endif
if_OPT_EXT_COLORS(screen, {
fbf = SCRN_BUF_FGRND(screen, lastind + topline);
fbb = SCRN_BUF_BGRND(screen, lastind + topline);
fg_bg = ColorOf(col);
fg = extract_fg(fg_bg, flags);
bg = extract_bg(fg_bg, flags);
});
if_OPT_ISO_TRADITIONAL_COLORS(screen, {
fb = SCRN_BUF_COLOR(screen, lastind + topline);
fg_bg = ColorOf(col);
fg = extract_fg(fg_bg, flags);
bg = extract_bg(fg_bg, flags);
});
gc = updatedXtermGC(screen, flags, fg_bg, hilite);
gc_changes |= (flags & (FG_COLOR | BG_COLOR));
x = CurCursorX(screen, row + topline, col);
lastind = col;
for (; col <= maxcol; col++) {
if ((attrs[col] != flags)
|| (hilite && (col > hi_col))
#if OPT_ISO_COLORS
|| ((flags & FG_COLOR)
&& (extract_fg(ColorOf(col), attrs[col]) != fg))
|| ((flags & BG_COLOR)
&& (extract_bg(ColorOf(col), attrs[col]) != bg))
#endif
#if OPT_WIDE_CHARS
|| (widec
&& ((iswide(chars[col] | (widec[col] << 8))) != wideness)
&& !((chars[col] | (widec[col] << 8)) == HIDDEN_CHAR))
#endif
#if OPT_DEC_CHRSET
|| (cb[col] != cs)
#endif
) {
assert(col >= lastind);
TRACE(("ScrnRefresh looping drawXtermText %d..%d:%s\n",
lastind, col,
visibleChars(PAIRED_CHARS(&chars[lastind],
WIDEC_PTR(lastind)),
(unsigned) (col - lastind))));
test = flags;
checkVeryBoldColors(test, fg);
x = drawXtermText(screen, test & DRAWX_MASK, gc, x, y,
cs,
PAIRED_CHARS(&chars[lastind], WIDEC_PTR(lastind)),
(unsigned) (col - lastind), 0);
if_OPT_WIDE_CHARS(screen, {
int i;
Char *comb1l = BUF_COM1L(screen->visbuf, row + topline);
Char *comb2l = BUF_COM2L(screen->visbuf, row + topline);
Char *comb1h = BUF_COM1H(screen->visbuf, row + topline);
Char *comb2h = BUF_COM2H(screen->visbuf, row + topline);
for (i = lastind; i < col; i++) {
int my_x = CurCursorX(screen, row + topline, i);
int base = chars[i] | (widec[i] << 8);
int comb1 = comb1l[i] | (comb1h[i] << 8);
int comb2 = comb2l[i] | (comb2h[i] << 8);
if (iswide(base))
my_x = CurCursorX(screen, row + topline, i - 1);
if (comb1 != 0) {
drawXtermText(screen, (test & DRAWX_MASK)
| NOBACKGROUND, gc, my_x, y, cs,
PAIRED_CHARS(comb1l + i, comb1h + i),
1, iswide(base));
}
if (comb2 != 0) {
drawXtermText(screen, (test & DRAWX_MASK)
| NOBACKGROUND, gc, my_x, y, cs,
PAIRED_CHARS(comb2l + i, comb2h + i),
1, iswide(base));
}
}
});
resetXtermGC(screen, flags, hilite);
lastind = col;
if (hilite && (col > hi_col))
hilite = False;
flags = attrs[col];
if_OPT_EXT_COLORS(screen, {
fg_bg = ColorOf(col);
fg = extract_fg(fg_bg, flags);
bg = extract_bg(fg_bg, flags);
});
if_OPT_ISO_TRADITIONAL_COLORS(screen, {
fg_bg = ColorOf(col);
fg = extract_fg(fg_bg, flags);
bg = extract_bg(fg_bg, flags);
});
if_OPT_DEC_CHRSET({
cs = cb[col];
});
#if OPT_WIDE_CHARS
if (widec)
wideness = iswide(chars[col] | (widec[col] << 8));
#endif
gc = updatedXtermGC(screen, flags, fg_bg, hilite);
gc_changes |= (flags & (FG_COLOR | BG_COLOR));
}
if (chars[col] == 0) {
#if OPT_WIDE_CHARS
if (widec == 0 || widec[col] == 0)
#endif
chars[col] = ' ';
}
}
assert(col >= lastind);
TRACE(("ScrnRefresh calling drawXtermText %d..%d:%s\n",
lastind, col,
visibleChars(PAIRED_CHARS(&chars[lastind], WIDEC_PTR(lastind)),
(unsigned) (col - lastind))));
test = flags;
checkVeryBoldColors(test, fg);
drawXtermText(screen, test & DRAWX_MASK, gc, x, y,
cs,
PAIRED_CHARS(&chars[lastind], WIDEC_PTR(lastind)),
(unsigned) (col - lastind), 0);
if_OPT_WIDE_CHARS(screen, {
int i;
Char *comb1l = BUF_COM1L(screen->visbuf, row + topline);
Char *comb2l = BUF_COM2L(screen->visbuf, row + topline);
Char *comb1h = BUF_COM1H(screen->visbuf, row + topline);
Char *comb2h = BUF_COM2H(screen->visbuf, row + topline);
for (i = lastind; i < col; i++) {
int my_x = CurCursorX(screen, row + topline, i);
int base = chars[i] | (widec[i] << 8);
int comb1 = comb1l[i] | (comb1h[i] << 8);
int comb2 = comb2l[i] | (comb2h[i] << 8);
if (iswide(base))
my_x = CurCursorX(screen, row + topline, i - 1);
if (comb1 != 0) {
drawXtermText(screen, (test & DRAWX_MASK) |
NOBACKGROUND, gc, my_x, y, cs,
PAIRED_CHARS(comb1l + i, comb1h + i),
1, iswide(base));
}
if (comb2 != 0) {
drawXtermText(screen, (test & DRAWX_MASK) |
NOBACKGROUND, gc, my_x, y, cs,
PAIRED_CHARS(comb2l + i, comb2h + i),
1, iswide(base));
}
}
});
resetXtermGC(screen, flags, hilite);
}
if_OPT_ISO_COLORS(screen, {
if (gc_changes & FG_COLOR)
SGR_Foreground(term->cur_foreground);
if (gc_changes & BG_COLOR)
SGR_Background(term->cur_background);
});
#if defined(__CYGWIN__) && defined(TIOCSWINSZ)
if (first_time == 1) {
TTYSIZE_STRUCT ts;
first_time = 0;
TTYSIZE_ROWS(ts) = nrows;
TTYSIZE_COLS(ts) = ncols;
ts.ws_xpixel = term->core.width;
ts.ws_ypixel = term->core.height;
SET_TTYSIZE(screen->respond, ts);
}
#endif
recurse--;
}
void
ScrnUpdate(TScreen * screen,
int toprow,
int leftcol,
int nrows,
int ncols,
Bool force)
{
if (ScrnHaveSelection(screen)
&& (toprow <= screen->endHRow)
&& (toprow + nrows - 1 >= screen->startHRow)) {
ScrnDisownSelection(screen);
}
ScrnRefresh(screen, toprow, leftcol, nrows, ncols, force);
}
void
ClearBufRows(TScreen * screen,
int first,
int last)
{
ScrnBuf buf = screen->visbuf;
unsigned len = MaxCols(screen);
int row;
int flags = TERM_COLOR_FLAGS(term);
TRACE(("ClearBufRows %d..%d\n", first, last));
for (row = first; row <= last; row++) {
ScrnClrWrapped(screen, row);
bzero(BUF_CHARS(buf, row), len);
memset(BUF_ATTRS(buf, row), flags, len);
if_OPT_EXT_COLORS(screen, {
memset(BUF_FGRND(buf, row), term->sgr_foreground, len);
memset(BUF_BGRND(buf, row), term->cur_background, len);
});
if_OPT_ISO_TRADITIONAL_COLORS(screen, {
memset(BUF_COLOR(buf, row), xtermColorPair(), len);
});
if_OPT_DEC_CHRSET({
memset(BUF_CSETS(buf, row), 0, len);
});
if_OPT_WIDE_CHARS(screen, {
memset(BUF_WIDEC(buf, row), 0, len);
memset(BUF_COM1L(buf, row), 0, len);
memset(BUF_COM1H(buf, row), 0, len);
memset(BUF_COM2L(buf, row), 0, len);
memset(BUF_COM2H(buf, row), 0, len);
});
}
}
int
ScreenResize(TScreen * screen,
int width,
int height,
unsigned *flags)
{
int code, rows, cols;
int border = 2 * screen->border;
int move_down_by;
#ifdef TTYSIZE_STRUCT
TTYSIZE_STRUCT ts;
#endif
Window tw = VWindow(screen);
TRACE(("ScreenResize %dx%d border %d font %dx%d\n",
height, width, border,
FontHeight(screen), FontWidth(screen)));
assert(width > 0);
assert(height > 0);
if (width >= FullWidth(screen)) {
XClearArea(screen->display, tw,
FullWidth(screen), 0,
0, (unsigned) height,
False);
}
if (height >= FullHeight(screen)) {
XClearArea(screen->display, tw,
0, FullHeight(screen),
(unsigned) width, 0,
False);
}
TRACE(("..computing rows/cols: %.2f %.2f\n",
(double) (height - border) / FontHeight(screen),
(double) (width - border - ScrollbarWidth(screen)) / FontWidth(screen)));
rows = (height - border) / FontHeight(screen);
cols = (width - border - ScrollbarWidth(screen)) / FontWidth(screen);
if (rows < 1)
rows = 1;
if (cols < 1)
cols = 1;
if (MaxRows(screen) != rows || MaxCols(screen) != cols) {
int savelines = (screen->scrollWidget
? screen->savelines
: 0);
int delta_rows = rows - MaxRows(screen);
TRACE(("...ScreenResize chars %dx%d\n", rows, cols));
if (screen->cursor_state)
HideCursor();
if (screen->alternate
&& term->misc.resizeGravity == SouthWestGravity)
SwitchBufPtrs(screen);
if (screen->altbuf)
(void) Reallocate(&screen->altbuf,
&screen->abuf_address,
rows,
cols,
MaxRows(screen),
MaxCols(screen));
move_down_by = Reallocate(&screen->allbuf,
&screen->sbuf_address,
rows + savelines, cols,
MaxRows(screen) + savelines,
MaxCols(screen));
screen->visbuf = &screen->allbuf[MAX_PTRS * savelines];
set_max_row(screen, screen->max_row + delta_rows);
set_max_col(screen, cols - 1);
if (term->misc.resizeGravity == SouthWestGravity) {
screen->savedlines -= move_down_by;
if (screen->savedlines < 0)
screen->savedlines = 0;
if (screen->savedlines > screen->savelines)
screen->savedlines = screen->savelines;
if (screen->topline < -screen->savedlines)
screen->topline = -screen->savedlines;
set_cur_row(screen, screen->cur_row + move_down_by);
screen->cursor_row += move_down_by;
ScrollSelection(screen, move_down_by, True);
if (screen->alternate)
SwitchBufPtrs(screen);
}
set_tb_margins(screen, 0, screen->max_row);
*flags &= ~ORIGIN;
if (screen->cur_row > screen->max_row)
set_cur_row(screen, screen->max_row);
if (screen->cur_col > screen->max_col)
set_cur_col(screen, screen->max_col);
screen->fullVwin.height = height - border;
screen->fullVwin.width = width - border - screen->fullVwin.sb_info.width;
} else if (FullHeight(screen) == height && FullWidth(screen) == width)
return (0);
screen->fullVwin.fullheight = height;
screen->fullVwin.fullwidth = width;
if (screen->scrollWidget)
ResizeScrollBar(term);
ResizeSelection(screen, rows, cols);
#ifndef NO_ACTIVE_ICON
if (screen->iconVwin.window) {
XWindowChanges changes;
screen->iconVwin.width =
MaxCols(screen) * screen->iconVwin.f_width;
screen->iconVwin.height =
MaxRows(screen) * screen->iconVwin.f_height;
changes.width = screen->iconVwin.fullwidth =
screen->iconVwin.width + 2 * term->misc.icon_border_width;
changes.height = screen->iconVwin.fullheight =
screen->iconVwin.height + 2 * term->misc.icon_border_width;
changes.border_width = term->misc.icon_border_width;
TRACE(("resizing icon window %dx%d\n", changes.height, changes.width));
XConfigureWindow(XtDisplay(term), screen->iconVwin.window,
CWWidth | CWHeight | CWBorderWidth, &changes);
}
#endif
#ifdef TTYSIZE_STRUCT
TTYSIZE_ROWS(ts) = rows;
TTYSIZE_COLS(ts) = cols;
#ifdef USE_STRUCT_WINSIZE
ts.ws_xpixel = width;
ts.ws_ypixel = height;
#endif
code = SET_TTYSIZE(screen->respond, ts);
TRACE(("return %d from SET_TTYSIZE %dx%d\n", code, rows, cols));
(void) code;
#if defined(SIGWINCH) && defined(USE_STRUCT_TTYSIZE)
if (screen->pid > 1) {
int pgrp;
TRACE(("getting process-group\n"));
if (ioctl(screen->respond, TIOCGPGRP, &pgrp) != -1) {
TRACE(("sending SIGWINCH to process group %d\n", pgrp));
kill_process_group(pgrp, SIGWINCH);
}
}
#endif
#else
TRACE(("ScreenResize cannot do anything to pty\n"));
#endif
return (0);
}
Bool
non_blank_line(ScrnBuf sb,
int row,
int col,
int len)
{
int i;
Char *ptr = BUF_CHARS(sb, row);
for (i = col; i < len; i++) {
if (ptr[i])
return True;
}
if_OPT_WIDE_CHARS((&(term->screen)), {
if ((ptr = BUF_WIDEC(sb, row)) != 0) {
for (i = col; i < len; i++) {
if (ptr[i])
return True;
}
}
});
return False;
}
void
xtermParseRect(TScreen * screen, int nparams, int *params, XTermRect * target)
{
memset(target, 0, sizeof(*target));
target->top = (nparams > 0) ? params[0] : getMinRow(screen) + 1;
target->left = (nparams > 1) ? params[1] : getMinCol(screen) + 1;
target->bottom = (nparams > 2) ? params[2] : getMaxRow(screen) + 1;
target->right = (nparams > 3) ? params[3] : getMaxCol(screen) + 1;
TRACE(("parsed rectangle %d,%d %d,%d\n",
target->top,
target->left,
target->bottom,
target->right));
}
static Bool
validRect(TScreen * screen, XTermRect * target)
{
TRACE(("comparing against screensize %dx%d\n",
getMaxRow(screen) + 1,
getMaxCol(screen) + 1));
return (target != 0
&& target->top > getMinRow(screen)
&& target->left > getMinCol(screen)
&& target->top <= target->bottom
&& target->left <= target->right
&& target->top <= getMaxRow(screen) + 1
&& target->right <= getMaxCol(screen) + 1);
}
void
ScrnFillRectangle(TScreen * screen, XTermRect * target, int value, unsigned flags)
{
TRACE(("filling rectangle with '%c'\n", value));
if (validRect(screen, target)) {
unsigned left = target->left - 1;
unsigned size = target->right - left;
Char attrs = flags;
int row;
attrs &= ATTRIBUTES;
attrs |= CHARDRAWN;
for (row = target->bottom - 1; row >= (target->top - 1); row--) {
TRACE(("filling %d [%d..%d]\n", row, left + 1, left + size));
memset(SCRN_BUF_ATTRS(screen, row) + left, attrs, size);
memset(SCRN_BUF_CHARS(screen, row) + left, (Char) value, size);
if_OPT_WIDE_CHARS(screen, {
bzero(SCRN_BUF_WIDEC(screen, row) + left, size);
});
}
ScrnUpdate(screen,
target->top - 1,
target->left - 1,
(target->bottom - target->top) + 1,
(target->right - target->left) + 1,
False);
}
}
#if OPT_DEC_RECTOPS
void
ScrnCopyRectangle(TScreen * screen, XTermRect * source, int nparam, int *params)
{
TRACE(("copying rectangle\n"));
if (validRect(screen, source)) {
XTermRect target;
xtermParseRect(screen,
((nparam > 3) ? 2 : (nparam - 1)),
params + 1,
&target);
if (validRect(screen, &target)) {
unsigned high = (source->bottom - source->top) + 1;
unsigned wide = (source->right - source->left) + 1;
unsigned size = (high * wide);
int row, col, n;
Char *attrs = TypeMallocN(Char, size);
Char *chars = TypeMallocN(Char, size);
#if OPT_WIDE_CHARS
Char *widec = TypeMallocN(Char, size);
if (widec == 0)
return;
#endif
if (attrs == 0
|| chars == 0)
return;
TRACE(("OK - make copy %dx%d\n", high, wide));
target.bottom = target.top + (high - 1);
target.right = target.left + (wide - 1);
for (row = source->top - 1; row < source->bottom; ++row) {
for (col = source->left - 1; col < source->right; ++col) {
n = ((1 + row - source->top) * wide) + (1 + col - source->left);
attrs[n] = SCRN_BUF_ATTRS(screen, row)[col] | CHARDRAWN;
chars[n] = SCRN_BUF_CHARS(screen, row)[col];
if_OPT_WIDE_CHARS(screen, {
widec[n] = SCRN_BUF_WIDEC(screen, row)[col];
})
}
}
for (row = target.top - 1; row < target.bottom; ++row) {
for (col = target.left - 1; col < target.right; ++col) {
if (row >= getMinRow(screen)
&& row <= getMaxRow(screen)
&& col >= getMinCol(screen)
&& col <= getMaxCol(screen)) {
n = ((1 + row - target.top) * wide) + (1 + col - target.left);
SCRN_BUF_ATTRS(screen, row)[col] = attrs[n];
SCRN_BUF_CHARS(screen, row)[col] = chars[n];
if_OPT_WIDE_CHARS(screen, {
SCRN_BUF_WIDEC(screen, row)[col] = widec[n];
})
}
}
}
free(attrs);
free(chars);
#if OPT_WIDE_CHARS
free(widec);
#endif
ScrnUpdate(screen,
(target.top - 1),
(target.left - 1),
(target.bottom - target.top) + 1,
((target.right - target.left) + 1),
False);
}
}
}
void
ScrnMarkRectangle(TScreen * screen,
XTermRect * target,
Bool reverse,
int nparam,
int *params)
{
Bool exact = (screen->cur_decsace == 2);
TRACE(("%s %s\n",
reverse ? "reversing" : "marking",
(exact
? "rectangle"
: "region")));
if (validRect(screen, target)) {
int top = target->top - 1;
int bottom = target->bottom - 1;
int row, col;
int n;
for (row = top; row <= bottom; ++row) {
int left = ((exact || (row == top))
? (target->left - 1)
: getMinCol(screen));
int right = ((exact || (row == bottom))
? (target->right - 1)
: getMaxCol(screen));
TRACE(("marking %d [%d..%d]\n", row, left + 1, right + 1));
for (col = left; col <= right; ++col) {
unsigned flags = SCRN_BUF_ATTRS(screen, row)[col];
for (n = 0; n < nparam; ++n) {
#if OPT_TRACE
if (row == top && col == left)
TRACE(("attr param[%d] %d\n", n + 1, params[n]));
#endif
if (reverse) {
switch (params[n]) {
case 1:
flags ^= BOLD;
break;
case 4:
flags ^= UNDERLINE;
break;
case 5:
flags ^= BLINK;
break;
case 7:
flags ^= INVERSE;
break;
}
} else {
switch (params[n]) {
case 0:
flags &= ~SGR_MASK;
break;
case 1:
flags |= BOLD;
break;
case 4:
flags |= UNDERLINE;
break;
case 5:
flags |= BLINK;
break;
case 7:
flags |= INVERSE;
break;
case 22:
flags &= ~BOLD;
break;
case 24:
flags &= ~UNDERLINE;
break;
case 25:
flags &= ~BLINK;
break;
case 27:
flags &= ~INVERSE;
break;
}
}
}
#if OPT_TRACE
if (row == top && col == left)
TRACE(("first mask-change is %#x\n",
SCRN_BUF_ATTRS(screen, row)[col] ^ flags));
#endif
SCRN_BUF_ATTRS(screen, row)[col] = flags;
}
}
ScrnRefresh(screen,
(target->top - 1),
(exact ? (target->left - 1) : getMinCol(screen)),
(target->bottom - target->top) + 1,
(exact
? ((target->right - target->left) + 1)
: (getMaxCol(screen) - getMinCol(screen) + 1)),
False);
}
}
void
ScrnWipeRectangle(TScreen * screen,
XTermRect * target)
{
TRACE(("wiping rectangle\n"));
if (validRect(screen, target)) {
int top = target->top - 1;
int bottom = target->bottom - 1;
int row, col;
for (row = top; row <= bottom; ++row) {
int left = (target->left - 1);
int right = (target->right - 1);
TRACE(("wiping %d [%d..%d]\n", row, left + 1, right + 1));
for (col = left; col <= right; ++col) {
if (!((screen->protected_mode == DEC_PROTECT)
&& (SCRN_BUF_ATTRS(screen, row)[col] & PROTECTED))) {
SCRN_BUF_ATTRS(screen, row)[col] |= CHARDRAWN;
SCRN_BUF_CHARS(screen, row)[col] = ' ';
if_OPT_WIDE_CHARS(screen, {
SCRN_BUF_WIDEC(screen, row)[col] = '\0';
})
}
}
}
ScrnUpdate(screen,
(target->top - 1),
(target->left - 1),
(target->bottom - target->top) + 1,
((target->right - target->left) + 1),
False);
}
}
#endif