#include <xterm.h>
#include <data.h>
#include <error.h>
#include <menu.h>
#include <fontutils.h>
#if OPT_WIDE_CHARS
#include <wcwidth.h>
#endif
#include <stdio.h>
#include <ctype.h>
static int ClearInLine(TScreen * screen, int row, int col, int len);
static int handle_translated_exposure(TScreen * screen,
int rect_x,
int rect_y,
unsigned rect_width,
unsigned rect_height);
static void ClearLeft(TScreen * screen);
static void CopyWait(TScreen * screen);
static void horizontal_copy_area(TScreen * screen,
int firstchar,
int nchars,
int amount);
static void vertical_copy_area(TScreen * screen,
int firstline,
int nlines,
int amount);
void
FlushScroll(TScreen * screen)
{
int i;
int shift = -screen->topline;
int bot = screen->max_row - shift;
int refreshtop;
int refreshheight;
int scrolltop;
int scrollheight;
if (screen->cursor_state)
HideCursor();
if (screen->scroll_amt > 0) {
refreshheight = screen->refresh_amt;
scrollheight = screen->bot_marg - screen->top_marg -
refreshheight + 1;
if ((refreshtop = screen->bot_marg - refreshheight + 1 + shift) >
(i = screen->max_row - screen->scroll_amt + 1))
refreshtop = i;
if (screen->scrollWidget && !screen->alternate
&& screen->top_marg == 0) {
scrolltop = 0;
if ((scrollheight += shift) > i)
scrollheight = i;
if ((i = screen->bot_marg - bot) > 0 &&
(refreshheight -= i) < screen->scroll_amt)
refreshheight = screen->scroll_amt;
if ((i = screen->savedlines) < screen->savelines) {
if ((i += screen->scroll_amt) >
screen->savelines)
i = screen->savelines;
screen->savedlines = i;
ScrollBarDrawThumb(screen->scrollWidget);
}
} else {
scrolltop = screen->top_marg + shift;
if ((i = bot - (screen->bot_marg - screen->refresh_amt +
screen->scroll_amt)) > 0) {
if (bot < screen->bot_marg)
refreshheight = screen->scroll_amt + i;
} else {
scrollheight += i;
refreshheight = screen->scroll_amt;
if ((i = screen->top_marg + screen->scroll_amt -
1 - bot) > 0) {
refreshtop += i;
refreshheight -= i;
}
}
}
} else {
refreshheight = -screen->refresh_amt;
scrollheight = screen->bot_marg - screen->top_marg -
refreshheight + 1;
refreshtop = screen->top_marg + shift;
scrolltop = refreshtop + refreshheight;
if ((i = screen->bot_marg - bot) > 0)
scrollheight -= i;
if ((i = screen->top_marg + refreshheight - 1 - bot) > 0)
refreshheight -= i;
}
scrolling_copy_area(screen, scrolltop + screen->scroll_amt,
scrollheight, screen->scroll_amt);
ScrollSelection(screen, -(screen->scroll_amt));
screen->scroll_amt = 0;
screen->refresh_amt = 0;
if (refreshheight > 0) {
ClearCurBackground(screen,
(int) refreshtop * FontHeight(screen) + screen->border,
(int) OriginX(screen),
(unsigned) refreshheight * FontHeight(screen),
(unsigned) Width(screen));
ScrnRefresh(screen, refreshtop, 0, refreshheight,
screen->max_col + 1, False);
}
}
int
AddToRefresh(TScreen * screen)
{
int amount = screen->refresh_amt;
int row = screen->cur_row;
if (amount == 0)
return (0);
if (amount > 0) {
int bottom;
if (row == (bottom = screen->bot_marg) - amount) {
screen->refresh_amt++;
return (1);
}
return (row >= bottom - amount + 1 && row <= bottom);
} else {
int top;
amount = -amount;
if (row == (top = screen->top_marg) + amount) {
screen->refresh_amt--;
return (1);
}
return (row <= top + amount - 1 && row >= top);
}
}
void
xtermScroll(TScreen * screen, int amount)
{
int i = screen->bot_marg - screen->top_marg + 1;
int shift;
int bot;
int refreshtop = 0;
int refreshheight;
int scrolltop;
int scrollheight;
if (screen->cursor_state)
HideCursor();
if (amount > i)
amount = i;
if (screen->jumpscroll) {
if (screen->scroll_amt > 0) {
if (screen->refresh_amt + amount > i)
FlushScroll(screen);
screen->scroll_amt += amount;
screen->refresh_amt += amount;
} else {
if (screen->scroll_amt < 0)
FlushScroll(screen);
screen->scroll_amt = amount;
screen->refresh_amt = amount;
}
refreshheight = 0;
} else {
ScrollSelection(screen, -(amount));
if (amount == i) {
ClearScreen(screen);
return;
}
shift = -screen->topline;
bot = screen->max_row - shift;
scrollheight = i - amount;
refreshheight = amount;
if ((refreshtop = screen->bot_marg - refreshheight + 1 + shift) >
(i = screen->max_row - refreshheight + 1))
refreshtop = i;
if (screen->scrollWidget && !screen->alternate
&& screen->top_marg == 0) {
scrolltop = 0;
if ((scrollheight += shift) > i)
scrollheight = i;
if ((i = screen->savedlines) < screen->savelines) {
if ((i += amount) > screen->savelines)
i = screen->savelines;
screen->savedlines = i;
ScrollBarDrawThumb(screen->scrollWidget);
}
} else {
scrolltop = screen->top_marg + shift;
if ((i = screen->bot_marg - bot) > 0) {
scrollheight -= i;
if ((i = screen->top_marg + amount - 1 - bot) >= 0) {
refreshtop += i;
refreshheight -= i;
}
}
}
if (screen->multiscroll && amount == 1 &&
screen->topline == 0 && screen->top_marg == 0 &&
screen->bot_marg == screen->max_row) {
if (screen->incopy < 0 && screen->scrolls == 0)
CopyWait(screen);
screen->scrolls++;
}
scrolling_copy_area(screen, scrolltop + amount, scrollheight, amount);
if (refreshheight > 0) {
ClearCurBackground(screen,
(int) refreshtop * FontHeight(screen) + screen->border,
(int) OriginX(screen),
(unsigned) refreshheight * FontHeight(screen),
(unsigned) Width(screen));
if (refreshheight > shift)
refreshheight = shift;
}
}
if (screen->scrollWidget && !screen->alternate && screen->top_marg == 0)
ScrnDeleteLine(screen, screen->allbuf,
screen->bot_marg + screen->savelines, 0,
amount, screen->max_col + 1);
else
ScrnDeleteLine(screen, screen->visbuf,
screen->bot_marg, screen->top_marg,
amount, screen->max_col + 1);
if (refreshheight > 0)
ScrnRefresh(screen, refreshtop, 0, refreshheight,
screen->max_col + 1, False);
}
void
RevScroll(TScreen * screen, int amount)
{
int i = screen->bot_marg - screen->top_marg + 1;
int shift;
int bot;
int refreshtop;
int refreshheight;
int scrolltop;
int scrollheight;
if (screen->cursor_state)
HideCursor();
if (amount > i)
amount = i;
if (screen->jumpscroll) {
if (screen->scroll_amt < 0) {
if (-screen->refresh_amt + amount > i)
FlushScroll(screen);
screen->scroll_amt -= amount;
screen->refresh_amt -= amount;
} else {
if (screen->scroll_amt > 0)
FlushScroll(screen);
screen->scroll_amt = -amount;
screen->refresh_amt = -amount;
}
} else {
shift = -screen->topline;
bot = screen->max_row - shift;
refreshheight = amount;
scrollheight = screen->bot_marg - screen->top_marg -
refreshheight + 1;
refreshtop = screen->top_marg + shift;
scrolltop = refreshtop + refreshheight;
if ((i = screen->bot_marg - bot) > 0)
scrollheight -= i;
if ((i = screen->top_marg + refreshheight - 1 - bot) > 0)
refreshheight -= i;
if (screen->multiscroll && amount == 1 &&
screen->topline == 0 && screen->top_marg == 0 &&
screen->bot_marg == screen->max_row) {
if (screen->incopy < 0 && screen->scrolls == 0)
CopyWait(screen);
screen->scrolls++;
}
scrolling_copy_area(screen, scrolltop - amount, scrollheight, -amount);
if (refreshheight > 0) {
ClearCurBackground(screen,
(int) refreshtop * FontHeight(screen) + screen->border,
(int) OriginX(screen),
(unsigned) refreshheight * FontHeight(screen),
(unsigned) Width(screen));
}
}
ScrnInsertLine(screen, screen->visbuf, screen->bot_marg, screen->top_marg,
amount, screen->max_col + 1);
}
void
InsertLine(TScreen * screen, int n)
{
int i;
int shift;
int bot;
int refreshtop;
int refreshheight;
int scrolltop;
int scrollheight;
if (screen->cur_row < screen->top_marg ||
screen->cur_row > screen->bot_marg)
return;
if (screen->cursor_state)
HideCursor();
screen->do_wrap = 0;
if (n > (i = screen->bot_marg - screen->cur_row + 1))
n = i;
if (screen->jumpscroll) {
if (screen->scroll_amt <= 0 &&
screen->cur_row <= -screen->refresh_amt) {
if (-screen->refresh_amt + n > screen->max_row + 1)
FlushScroll(screen);
screen->scroll_amt -= n;
screen->refresh_amt -= n;
} else if (screen->scroll_amt)
FlushScroll(screen);
}
if (!screen->scroll_amt) {
shift = -screen->topline;
bot = screen->max_row - shift;
refreshheight = n;
scrollheight = screen->bot_marg - screen->cur_row - refreshheight + 1;
refreshtop = screen->cur_row + shift;
scrolltop = refreshtop + refreshheight;
if ((i = screen->bot_marg - bot) > 0)
scrollheight -= i;
if ((i = screen->cur_row + refreshheight - 1 - bot) > 0)
refreshheight -= i;
vertical_copy_area(screen, scrolltop - n, scrollheight, -n);
if (refreshheight > 0) {
ClearCurBackground(screen,
(int) refreshtop * FontHeight(screen) + screen->border,
(int) OriginX(screen),
(unsigned) refreshheight * FontHeight(screen),
(unsigned) Width(screen));
}
}
ScrnInsertLine(screen, screen->visbuf, screen->bot_marg, screen->cur_row,
n, screen->max_col + 1);
}
void
DeleteLine(TScreen * screen, int n)
{
int i;
int shift;
int bot;
int refreshtop;
int refreshheight;
int scrolltop;
int scrollheight;
if (screen->cur_row < screen->top_marg ||
screen->cur_row > screen->bot_marg)
return;
if (screen->cursor_state)
HideCursor();
screen->do_wrap = 0;
if (n > (i = screen->bot_marg - screen->cur_row + 1))
n = i;
if (screen->jumpscroll) {
if (screen->scroll_amt >= 0 && screen->cur_row == screen->top_marg) {
if (screen->refresh_amt + n > screen->max_row + 1)
FlushScroll(screen);
screen->scroll_amt += n;
screen->refresh_amt += n;
} else if (screen->scroll_amt)
FlushScroll(screen);
}
if (!screen->scroll_amt) {
shift = -screen->topline;
bot = screen->max_row - shift;
scrollheight = i - n;
refreshheight = n;
if ((refreshtop = screen->bot_marg - refreshheight + 1 + shift) >
(i = screen->max_row - refreshheight + 1))
refreshtop = i;
if (screen->scrollWidget && !screen->alternate && screen->cur_row == 0) {
scrolltop = 0;
if ((scrollheight += shift) > i)
scrollheight = i;
if ((i = screen->savedlines) < screen->savelines) {
if ((i += n) > screen->savelines)
i = screen->savelines;
screen->savedlines = i;
ScrollBarDrawThumb(screen->scrollWidget);
}
} else {
scrolltop = screen->cur_row + shift;
if ((i = screen->bot_marg - bot) > 0) {
scrollheight -= i;
if ((i = screen->cur_row + n - 1 - bot) >= 0) {
refreshheight -= i;
}
}
}
vertical_copy_area(screen, scrolltop + n, scrollheight, n);
if (refreshheight > 0) {
ClearCurBackground(screen,
(int) refreshtop * FontHeight(screen) + screen->border,
(int) OriginX(screen),
(unsigned) refreshheight * FontHeight(screen),
(unsigned) Width(screen));
}
}
if (screen->scrollWidget && !screen->alternate && screen->cur_row == 0)
ScrnDeleteLine(screen, screen->allbuf,
screen->bot_marg + screen->savelines, 0,
n, screen->max_col + 1);
else
ScrnDeleteLine(screen, screen->visbuf,
screen->bot_marg, screen->cur_row,
n, screen->max_col + 1);
}
void
InsertChar(TScreen * screen, int n)
{
register int width;
if (screen->cursor_state)
HideCursor();
screen->do_wrap = 0;
if (n > (width = screen->max_col + 1 - screen->cur_col))
n = width;
if (screen->cur_row - screen->topline <= screen->max_row) {
if (!AddToRefresh(screen)) {
int col = screen->max_col + 1 - n;
if (screen->scroll_amt)
FlushScroll(screen);
#if OPT_DEC_CHRSET
if (CSET_DOUBLE(SCRN_BUF_CSETS(screen, screen->cur_row)[0])) {
col = (screen->max_col + 1) / 2 - n;
}
#endif
if (non_blank_line(screen->visbuf, screen->cur_row,
screen->cur_col, screen->max_col + 1))
horizontal_copy_area(screen, screen->cur_col,
col - screen->cur_col,
n);
ClearCurBackground(
screen,
CursorY(screen, screen->cur_row),
CurCursorX(screen, screen->cur_row, screen->cur_col),
FontHeight(screen),
n * CurFontWidth(screen, screen->cur_row));
}
}
ScrnInsertChar(screen, n);
}
void
DeleteChar(TScreen * screen, int n)
{
int width;
if (screen->cursor_state)
HideCursor();
screen->do_wrap = 0;
if (n > (width = screen->max_col + 1 - screen->cur_col))
n = width;
if (screen->cur_row - screen->topline <= screen->max_row) {
if (!AddToRefresh(screen)) {
int col = screen->max_col + 1 - n;
if (screen->scroll_amt)
FlushScroll(screen);
#if OPT_DEC_CHRSET
if (CSET_DOUBLE(SCRN_BUF_CSETS(screen, screen->cur_row)[0])) {
col = (screen->max_col + 1) / 2 - n;
}
#endif
horizontal_copy_area(screen, screen->cur_col + n,
col - screen->cur_col,
-n);
ClearCurBackground(
screen,
CursorY(screen, screen->cur_row),
CurCursorX(screen, screen->cur_row, col),
FontHeight(screen),
n * CurFontWidth(screen, screen->cur_row));
}
}
ScrnDeleteChar(screen, n);
}
static void
ClearAbove(TScreen * screen)
{
if (screen->protected_mode != OFF_PROTECT) {
int row;
for (row = 0; row <= screen->max_row; row++)
ClearInLine(screen, row, 0, screen->max_col + 1);
} else {
int top, height;
if (screen->cursor_state)
HideCursor();
if ((top = -screen->topline) <= screen->max_row) {
if (screen->scroll_amt)
FlushScroll(screen);
if ((height = screen->cur_row + top) > screen->max_row)
height = screen->max_row;
if ((height -= top) > 0) {
ClearCurBackground(screen,
top * FontHeight(screen) + screen->border,
OriginX(screen),
height * FontHeight(screen),
Width(screen));
}
}
ClearBufRows(screen, 0, screen->cur_row - 1);
}
if (screen->cur_row - screen->topline <= screen->max_row)
ClearLeft(screen);
}
static void
ClearBelow(TScreen * screen)
{
ClearRight(screen, -1);
if (screen->protected_mode != OFF_PROTECT) {
int row;
for (row = screen->cur_row + 1; row <= screen->max_row; row++)
ClearInLine(screen, row, 0, screen->max_col + 1);
} else {
int top;
if ((top = screen->cur_row - screen->topline) <= screen->max_row) {
if (screen->scroll_amt)
FlushScroll(screen);
if (++top <= screen->max_row) {
ClearCurBackground(screen,
top * FontHeight(screen) + screen->border,
OriginX(screen),
(screen->max_row - top + 1) * FontHeight(screen),
Width(screen));
}
}
ClearBufRows(screen, screen->cur_row + 1, screen->max_row);
}
}
static int
ClearInLine(TScreen * screen, int row, int col, int len)
{
int rc = 1;
int flags = TERM_COLOR_FLAGS;
if (col + len < screen->max_col + 1) {
flags |= CHARDRAWN;
} else {
len = screen->max_col + 1 - col;
}
if (screen->protected_mode != OFF_PROTECT) {
int n;
Char *attrs = SCRN_BUF_ATTRS(screen, row) + col;
int saved_mode = screen->protected_mode;
Bool done;
screen->protected_mode = OFF_PROTECT;
do {
done = True;
for (n = 0; n < len; n++) {
if (attrs[n] & PROTECTED) {
rc = 0;
if (n != 0)
ClearInLine(screen, row, col, n);
while ((n < len)
&& (attrs[n] & PROTECTED))
n++;
done = False;
break;
}
}
if (!done) {
attrs += n;
col += n;
len -= n;
}
} while (!done);
screen->protected_mode = saved_mode;
if (len <= 0)
return 0;
}
if (screen->cursor_state)
HideCursor();
screen->do_wrap = 0;
if (row - screen->topline <= screen->max_row) {
if (!AddToRefresh(screen)) {
if (screen->scroll_amt)
FlushScroll(screen);
ClearCurBackground(
screen,
CursorY(screen, row),
CurCursorX(screen, row, col),
FontHeight(screen),
len * CurFontWidth(screen, row));
}
}
memset(SCRN_BUF_CHARS(screen, row) + col, ' ', len);
memset(SCRN_BUF_ATTRS(screen, row) + col, flags, len);
if_OPT_EXT_COLORS(screen, {
memset(SCRN_BUF_FGRND(screen, row) + col, term->sgr_foreground, len);
memset(SCRN_BUF_BGRND(screen, row) + col, term->cur_background, len);
});
if_OPT_ISO_TRADITIONAL_COLORS(screen, {
memset(SCRN_BUF_COLOR(screen, row) + col, xtermColorPair(), len);
});
if_OPT_DEC_CHRSET({
memset(SCRN_BUF_CSETS(screen, row) + col,
curXtermChrSet(screen->cur_row), len);
});
if_OPT_WIDE_CHARS(screen, {
memset(SCRN_BUF_WIDEC(screen, row) + col, 0, len);
memset(SCRN_BUF_COM1L(screen, row) + col, 0, len);
memset(SCRN_BUF_COM1H(screen, row) + col, 0, len);
memset(SCRN_BUF_COM2L(screen, row) + col, 0, len);
memset(SCRN_BUF_COM2H(screen, row) + col, 0, len);
});
return rc;
}
void
ClearRight(TScreen * screen, int n)
{
int len = (screen->max_col - screen->cur_col + 1);
if (n < 0)
n = screen->max_col + 1;
if (n == 0)
n = 1;
if (len > n)
len = n;
(void) ClearInLine(screen, screen->cur_row, screen->cur_col, len);
ScrnClrWrapped(screen, screen->cur_row);
}
static void
ClearLeft(TScreen * screen)
{
(void) ClearInLine(screen, screen->cur_row, 0, screen->cur_col + 1);
}
static void
ClearLine(TScreen * screen)
{
(void) ClearInLine(screen, screen->cur_row, 0, screen->max_col + 1);
}
void
ClearScreen(TScreen * screen)
{
int top;
if (screen->cursor_state)
HideCursor();
screen->do_wrap = 0;
if ((top = -screen->topline) <= screen->max_row) {
if (screen->scroll_amt)
FlushScroll(screen);
ClearCurBackground(screen,
top * FontHeight(screen) + screen->border,
OriginX(screen),
(screen->max_row - top + 1) * FontHeight(screen),
Width(screen));
}
ClearBufRows(screen, 0, screen->max_row);
}
void
do_erase_line(TScreen * screen, int param, int mode)
{
int saved_mode = screen->protected_mode;
if (saved_mode == DEC_PROTECT
&& saved_mode != mode)
screen->protected_mode = OFF_PROTECT;
switch (param) {
case -1:
case 0:
ClearRight(screen, -1);
break;
case 1:
ClearLeft(screen);
break;
case 2:
ClearLine(screen);
break;
}
screen->protected_mode = saved_mode;
}
void
do_erase_display(TScreen * screen, int param, int mode)
{
int saved_mode = screen->protected_mode;
if (saved_mode == DEC_PROTECT
&& saved_mode != mode)
screen->protected_mode = OFF_PROTECT;
switch (param) {
case -1:
case 0:
if (screen->cur_row == 0
&& screen->cur_col == 0) {
screen->protected_mode = saved_mode;
do_erase_display(screen, 2, mode);
saved_mode = screen->protected_mode;
} else
ClearBelow(screen);
break;
case 1:
if (screen->cur_row == screen->max_row
&& screen->cur_col == screen->max_col) {
screen->protected_mode = saved_mode;
do_erase_display(screen, 2, mode);
saved_mode = screen->protected_mode;
} else
ClearAbove(screen);
break;
case 2:
if (screen->protected_mode != OFF_PROTECT) {
int row;
int rc = 1;
for (row = 0; row <= screen->max_row; row++)
rc &= ClearInLine(screen, row, 0, screen->max_col + 1);
if (rc != 0)
saved_mode = OFF_PROTECT;
} else {
ClearScreen(screen);
}
break;
case 3:
screen->savedlines = 0;
ScrollBarDrawThumb(screen->scrollWidget);
break;
}
screen->protected_mode = saved_mode;
}
static void
CopyWait(TScreen * screen)
{
XEvent reply;
XEvent *rep = &reply;
while (1) {
XWindowEvent(screen->display, VWindow(screen),
ExposureMask, &reply);
switch (reply.type) {
case Expose:
HandleExposure(screen, &reply);
break;
case NoExpose:
case GraphicsExpose:
if (screen->incopy <= 0) {
screen->incopy = 1;
if (screen->scrolls > 0)
screen->scrolls--;
}
if (reply.type == GraphicsExpose)
HandleExposure(screen, &reply);
if ((reply.type == NoExpose) ||
((XExposeEvent *) rep)->count == 0) {
if (screen->incopy <= 0 && screen->scrolls > 0)
screen->scrolls--;
if (screen->scrolls == 0) {
screen->incopy = 0;
return;
}
screen->incopy = -1;
}
break;
}
}
}
static void
copy_area(TScreen * screen,
int src_x,
int src_y,
unsigned width,
unsigned height,
int dest_x,
int dest_y)
{
if (width != 0 && height != 0) {
if (screen->incopy && screen->scrolls == 0)
CopyWait(screen);
screen->incopy = -1;
screen->copy_src_x = src_x;
screen->copy_src_y = src_y;
screen->copy_width = width;
screen->copy_height = height;
screen->copy_dest_x = dest_x;
screen->copy_dest_y = dest_y;
XCopyArea(screen->display,
VWindow(screen), VWindow(screen),
NormalGC(screen),
src_x, src_y, width, height, dest_x, dest_y);
}
}
static void
horizontal_copy_area(TScreen * screen,
int firstchar,
int nchars,
int amount)
{
int src_x = CurCursorX(screen, screen->cur_row, firstchar);
int src_y = CursorY(screen, screen->cur_row);
copy_area(screen, src_x, src_y,
(unsigned) nchars * CurFontWidth(screen, screen->cur_row),
FontHeight(screen),
src_x + amount * CurFontWidth(screen, screen->cur_row), src_y);
}
static void
vertical_copy_area(TScreen * screen,
int firstline,
int nlines,
int amount)
{
if (nlines > 0) {
int src_x = OriginX(screen);
int src_y = firstline * FontHeight(screen) + screen->border;
copy_area(screen, src_x, src_y,
(unsigned) Width(screen), nlines * FontHeight(screen),
src_x, src_y - amount * FontHeight(screen));
}
}
void
scrolling_copy_area(TScreen * screen,
int firstline,
int nlines,
int amount)
{
if (nlines > 0) {
vertical_copy_area(screen, firstline, nlines, amount);
}
}
int
HandleExposure(TScreen * screen, XEvent * event)
{
XExposeEvent *reply = (XExposeEvent *) event;
#ifndef NO_ACTIVE_ICON
if (reply->window == screen->iconVwin.window)
screen->whichVwin = &screen->iconVwin;
else
screen->whichVwin = &screen->fullVwin;
#endif
if (!screen->incopy || event->type != Expose)
return handle_translated_exposure(screen, reply->x, reply->y,
reply->width, reply->height);
else {
int both_x1 = Max(screen->copy_src_x, reply->x);
int both_y1 = Max(screen->copy_src_y, reply->y);
int both_x2 = Min(screen->copy_src_x + screen->copy_width,
(unsigned) (reply->x + reply->width));
int both_y2 = Min(screen->copy_src_y + screen->copy_height,
(unsigned) (reply->y + reply->height));
int value = 0;
if (both_x2 > both_x1 && both_y2 > both_y1) {
value = handle_translated_exposure
(screen, reply->x + screen->copy_dest_x - screen->copy_src_x,
reply->y + screen->copy_dest_y - screen->copy_src_y,
reply->width, reply->height);
}
if (reply->x < both_x1 || reply->y < both_y1
|| reply->x + reply->width > both_x2
|| reply->y + reply->height > both_y2)
value = handle_translated_exposure(screen, reply->x, reply->y,
reply->width, reply->height);
return value;
}
}
static int
handle_translated_exposure(TScreen * screen,
int rect_x,
int rect_y,
unsigned rect_width,
unsigned rect_height)
{
int toprow, leftcol, nrows, ncols;
TRACE(("handle_translated_exposure (%d,%d) - (%d,%d)\n",
rect_y, rect_x, rect_height, rect_width));
toprow = (rect_y - screen->border) / FontHeight(screen);
if (toprow < 0)
toprow = 0;
leftcol = (rect_x - OriginX(screen))
/ CurFontWidth(screen, screen->cur_row);
if (leftcol < 0)
leftcol = 0;
nrows = (rect_y + rect_height - 1 - screen->border) /
FontHeight(screen) - toprow + 1;
ncols = (rect_x + rect_width - 1 - OriginX(screen)) /
FontWidth(screen) - leftcol + 1;
toprow -= screen->scrolls;
if (toprow < 0) {
nrows += toprow;
toprow = 0;
}
if (toprow + nrows - 1 > screen->max_row)
nrows = screen->max_row - toprow + 1;
if (leftcol + ncols - 1 > screen->max_col)
ncols = screen->max_col - leftcol + 1;
if (nrows > 0 && ncols > 0) {
ScrnRefresh(screen, toprow, leftcol, nrows, ncols, False);
if (waiting_for_initial_map) {
first_map_occurred();
}
if (screen->cur_row >= toprow &&
screen->cur_row < toprow + nrows &&
screen->cur_col >= leftcol &&
screen->cur_col < leftcol + ncols)
return (1);
}
return (0);
}
void
GetColors(XtermWidget tw, ScrnColors * pColors)
{
TScreen *screen = &tw->screen;
pColors->which = 0;
SET_COLOR_VALUE(pColors, TEXT_FG, screen->foreground);
SET_COLOR_VALUE(pColors, TEXT_BG, tw->core.background_pixel);
SET_COLOR_VALUE(pColors, TEXT_CURSOR, screen->cursorcolor);
SET_COLOR_VALUE(pColors, MOUSE_FG, screen->mousecolor);
SET_COLOR_VALUE(pColors, MOUSE_BG, screen->mousecolorback);
#if OPT_HIGHLIGHT_COLOR
SET_COLOR_VALUE(pColors, HIGHLIGHT_BG, screen->highlightcolor);
#endif
#if OPT_TEK4014
SET_COLOR_VALUE(pColors, TEK_FG, screen->Tforeground);
SET_COLOR_VALUE(pColors, TEK_BG, screen->Tbackground);
#endif
}
void
ChangeColors(XtermWidget tw, ScrnColors * pNew)
{
TScreen *screen = &tw->screen;
#if OPT_TEK4014
Window tek = TWindow(screen);
#endif
if (COLOR_DEFINED(pNew, TEXT_BG)) {
tw->core.background_pixel = COLOR_VALUE(pNew, TEXT_BG);
}
if (COLOR_DEFINED(pNew, TEXT_CURSOR)) {
screen->cursorcolor = COLOR_VALUE(pNew, TEXT_CURSOR);
} else if ((screen->cursorcolor == screen->foreground) &&
(COLOR_DEFINED(pNew, TEXT_FG))) {
screen->cursorcolor = COLOR_VALUE(pNew, TEXT_FG);
}
if (COLOR_DEFINED(pNew, TEXT_FG)) {
Pixel fg = COLOR_VALUE(pNew, TEXT_FG);
screen->foreground = fg;
XSetForeground(screen->display, NormalGC(screen), fg);
XSetBackground(screen->display, ReverseGC(screen), fg);
XSetForeground(screen->display, NormalBoldGC(screen), fg);
XSetBackground(screen->display, ReverseBoldGC(screen), fg);
}
if (COLOR_DEFINED(pNew, TEXT_BG)) {
Pixel bg = COLOR_VALUE(pNew, TEXT_BG);
tw->core.background_pixel = bg;
XSetBackground(screen->display, NormalGC(screen), bg);
XSetForeground(screen->display, ReverseGC(screen), bg);
XSetBackground(screen->display, NormalBoldGC(screen), bg);
XSetForeground(screen->display, ReverseBoldGC(screen), bg);
XSetWindowBackground(screen->display, VWindow(screen),
tw->core.background_pixel);
}
#if OPT_HIGHLIGHT_COLOR
if (COLOR_DEFINED(pNew, HIGHLIGHT_BG)) {
screen->highlightcolor = COLOR_VALUE(pNew, HIGHLIGHT_BG);
}
#endif
if (COLOR_DEFINED(pNew, MOUSE_FG) || (COLOR_DEFINED(pNew, MOUSE_BG))) {
if (COLOR_DEFINED(pNew, MOUSE_FG))
screen->mousecolor = COLOR_VALUE(pNew, MOUSE_FG);
if (COLOR_DEFINED(pNew, MOUSE_BG))
screen->mousecolorback = COLOR_VALUE(pNew, MOUSE_BG);
recolor_cursor(screen->pointer_cursor,
screen->mousecolor, screen->mousecolorback);
recolor_cursor(screen->arrow,
screen->mousecolor, screen->mousecolorback);
XDefineCursor(screen->display, VWindow(screen),
screen->pointer_cursor);
#if OPT_TEK4014
if (tek)
XDefineCursor(screen->display, tek, screen->arrow);
#endif
}
#if OPT_TEK4014
if ((tek) && (COLOR_DEFINED(pNew, TEK_FG) || COLOR_DEFINED(pNew, TEK_BG))) {
ChangeTekColors(screen, pNew);
}
#endif
set_cursor_gcs(screen);
XClearWindow(screen->display, VWindow(screen));
ScrnRefresh(screen, 0, 0, screen->max_row + 1,
screen->max_col + 1, False);
#if OPT_TEK4014
if (screen->Tshow) {
XClearWindow(screen->display, tek);
TekExpose((Widget) NULL, (XEvent *) NULL, (Region) NULL);
}
#endif
}
void
ChangeAnsiColors(XtermWidget tw)
{
TScreen *screen = &tw->screen;
XClearWindow(screen->display, VWindow(screen));
ScrnRefresh(screen, 0, 0,
screen->max_row + 1,
screen->max_col + 1, False);
}
void
ReverseVideo(XtermWidget termw)
{
TScreen *screen = &termw->screen;
GC tmpGC;
Pixel tmp;
#if OPT_TEK4014
Window tek = TWindow(screen);
#endif
if_OPT_ISO_COLORS(screen, {
ColorRes tmp2;
EXCHANGE(screen->Acolors[0], screen->Acolors[7], tmp2)
EXCHANGE(screen->Acolors[8], screen->Acolors[15], tmp2)
});
tmp = termw->core.background_pixel;
if (screen->cursorcolor == screen->foreground)
screen->cursorcolor = tmp;
termw->core.background_pixel = screen->foreground;
screen->foreground = tmp;
EXCHANGE(screen->mousecolor, screen->mousecolorback, tmp)
EXCHANGE(NormalGC(screen), ReverseGC(screen), tmpGC)
EXCHANGE(NormalBoldGC(screen), ReverseBoldGC(screen), tmpGC)
#ifndef NO_ACTIVE_ICON
tmpGC = screen->iconVwin.normalGC;
screen->iconVwin.normalGC = screen->iconVwin.reverseGC;
screen->iconVwin.reverseGC = tmpGC;
tmpGC = screen->iconVwin.normalboldGC;
screen->iconVwin.normalboldGC = screen->iconVwin.reverseboldGC;
screen->iconVwin.reverseboldGC = tmpGC;
#endif
recolor_cursor(screen->pointer_cursor,
screen->mousecolor, screen->mousecolorback);
recolor_cursor(screen->arrow,
screen->mousecolor, screen->mousecolorback);
termw->misc.re_verse = !termw->misc.re_verse;
XDefineCursor(screen->display, VWindow(screen), screen->pointer_cursor);
#if OPT_TEK4014
if (tek)
XDefineCursor(screen->display, tek, screen->arrow);
#endif
if (screen->scrollWidget)
ScrollBarReverseVideo(screen->scrollWidget);
XSetWindowBackground(screen->display, VWindow(screen), termw->core.background_pixel);
XSetWindowBackground(screen->display, VShellWindow, termw->core.background_pixel);
#if OPT_TEK4014
if (tek) {
TekReverseVideo(screen);
}
#endif
XClearWindow(screen->display, VWindow(screen));
ScrnRefresh(screen, 0, 0, screen->max_row + 1,
screen->max_col + 1, False);
#if OPT_TEK4014
if (screen->Tshow) {
XClearWindow(screen->display, tek);
TekExpose((Widget) NULL, (XEvent *) NULL, (Region) NULL);
}
#endif
ReverseOldColors();
update_reversevideo();
}
void
recolor_cursor(Cursor cursor,
unsigned long fg,
unsigned long bg)
{
TScreen *screen = &term->screen;
Display *dpy = screen->display;
XColor colordefs[2];
colordefs[0].pixel = fg;
colordefs[1].pixel = bg;
XQueryColors(dpy, DefaultColormap(dpy, DefaultScreen(dpy)),
colordefs, 2);
XRecolorCursor(dpy, cursor, colordefs, colordefs + 1);
return;
}
#ifdef XRENDERFONT
static XftColor *
getColor(Pixel pixel)
{
#define CACHE_SIZE 4
static struct {
XftColor color;
int use;
} cache[CACHE_SIZE];
static int use;
int i;
int oldest, oldestuse;
XColor color;
oldestuse = 0x7fffffff;
oldest = 0;
for (i = 0; i < CACHE_SIZE; i++) {
if (cache[i].use) {
if (cache[i].color.pixel == pixel) {
cache[i].use = ++use;
return &cache[i].color;
}
}
if (cache[i].use < oldestuse) {
oldestuse = cache[i].use;
oldest = i;
}
}
i = oldest;
color.pixel = pixel;
XQueryColor(term->screen.display, term->core.colormap, &color);
cache[i].color.color.red = color.red;
cache[i].color.color.green = color.green;
cache[i].color.color.blue = color.blue;
cache[i].color.color.alpha = 0xffff;
cache[i].color.pixel = pixel;
cache[i].use = ++use;
return &cache[i].color;
}
static void
xtermXftDrawString(XftDraw * draw,
XftColor * color,
XftFont * font,
int x,
int y,
PAIRED_CHARS(Char * text, Char * text2),
int len,
int fwidth,
int *deltax)
{
#if OPT_WIDE_CHARS && defined(HAVE_TYPE_XFTCHARSPEC)
static XftCharSpec *sbuf;
static unsigned slen;
int n;
int ncells = 0;
if ((int) slen < len) {
slen = (len + 1) * 2;
sbuf = (XftCharSpec *) XtRealloc((char *) sbuf,
slen * sizeof(XftCharSpec));
}
for (n = 0; n < len; n++) {
FcChar32 wc;
if (text2)
wc = *text++ | (*text2++ << 8);
else
wc = *text++;
sbuf[n].ucs4 = wc;
sbuf[n].x = x + fwidth * ncells;
ncells += my_wcwidth(wc);
sbuf[n].y = y;
}
XftDrawCharSpec(draw, color, font, sbuf, len);
if (deltax)
*deltax = ncells * fwidth;
#else
XftDrawString8(draw,
color,
font,
x, y, (unsigned char *) text, len);
if (deltax)
*deltax = len * fwidth;
#endif
}
#endif
#if OPT_CLIP_BOLD
#define beginClipping(screen,gc,pwidth,plength) \
if (pwidth > 2) { \
XRectangle clip; \
int clip_x = x; \
int clip_y = y - FontHeight(screen) + FontDescent(screen); \
clip.x = 0; \
clip.y = 0; \
clip.height = FontHeight(screen); \
clip.width = pwidth * plength; \
XSetClipRectangles(screen->display, gc, \
clip_x, clip_y, \
&clip, 1, Unsorted); \
}
#define endClipping(screen,gc) \
XSetClipMask(screen->display, gc, None)
#else
#define beginClipping(screen,gc,pwidth,plength)
#define endClipping(screen,gc)
#endif
int
drawXtermText(TScreen * screen,
unsigned flags,
GC gc,
int x,
int y,
int chrset,
PAIRED_CHARS(Char * text, Char * text2),
Cardinal len,
int on_wide)
{
int real_length = len;
int underline_len;
int font_width = ((flags & DOUBLEWFONT) ? 2 : 1) * screen->fnt_wide;
#if OPT_WIDE_CHARS
if (text2 == 0) {
static Char *dbuf;
static unsigned dlen;
if (dlen <= len) {
dlen = (len + 1) * 2;
dbuf = (Char *) XtRealloc((char *) dbuf, dlen);
memset(dbuf, 0, dlen);
}
text2 = dbuf;
}
#endif
#ifdef XRENDERFONT
if (screen->renderFont) {
Display *dpy = screen->display;
XftFont *font;
XGCValues values;
if (!screen->renderDraw) {
int scr;
Drawable draw = VWindow(screen);
Visual *visual;
scr = DefaultScreen(dpy);
visual = DefaultVisual(dpy, scr);
screen->renderDraw = XftDrawCreate(dpy, draw, visual,
DefaultColormap(dpy, scr));
}
if ((flags & (BOLD | BLINK))
&& screen->renderFontBold)
font = screen->renderFontBold;
else
font = screen->renderFont;
XGetGCValues(dpy, gc, GCForeground | GCBackground, &values);
if (!(flags & NOBACKGROUND))
XftDrawRect(screen->renderDraw,
getColor(values.background),
x, y,
len * FontWidth(screen), FontHeight(screen));
y += font->ascent;
#if OPT_BOX_CHARS
if (!screen->force_box_chars) {
Cardinal last, first = 0;
Dimension old_wide, old_high = 0;
int curX = x;
for (last = 0; last < len; last++) {
unsigned ch = text[last];
int deltax = 0;
if_OPT_WIDE_CHARS(screen, {
ch = ucs2dec(ch | (text2[last] << 8));
});
if (ch > 0 && ch < 32) {
if (last > first) {
xtermXftDrawString(screen->renderDraw,
getColor(values.foreground),
font, curX, y,
PAIRED_CHARS(text + first,
text2 + first),
last - first, FontWidth(screen),
&deltax);
curX += deltax;
}
old_wide = screen->fnt_wide;
old_high = screen->fnt_high;
screen->fnt_wide = FontWidth(screen);
screen->fnt_high = FontHeight(screen);
xtermDrawBoxChar(screen, ch, flags, gc,
curX, y - FontAscent(screen));
curX += FontWidth(screen);
screen->fnt_wide = old_wide;
screen->fnt_high = old_high;
first = last + 1;
}
}
if (last > first) {
xtermXftDrawString(screen->renderDraw,
getColor(values.foreground),
font, curX, y,
PAIRED_CHARS(text + first, text2 + first),
last - first, FontWidth(screen), NULL);
}
} else
#endif
{
xtermXftDrawString(screen->renderDraw,
getColor(values.foreground),
font, x, y, PAIRED_CHARS(text, text2),
len, FontWidth(screen), NULL);
}
if ((flags & UNDERLINE) && screen->underline) {
if (FontDescent(screen) > 1)
y++;
XDrawLine(screen->display, VWindow(screen), gc,
x, y, x + len * FontWidth(screen) - 1, y);
}
return x + len * FontWidth(screen);
}
#endif
#if OPT_DEC_CHRSET
if (CSET_DOUBLE(chrset)) {
GC gc2 = ((!IsIcon(screen) && screen->font_doublesize)
? xterm_DoubleGC(chrset, flags, gc)
: 0);
TRACE(("DRAWTEXT%c[%4d,%4d] (%d) %d:%.*s\n",
screen->cursor_state == OFF ? ' ' : '*',
y, x, chrset, len, (int) len, text));
if (gc2 != 0) {
XFontStruct *fs =
screen->double_fonts[xterm_Double_index(chrset, flags)].fs;
XRectangle rect, *rp = ▭
Cardinal nr = 1;
int adjust;
font_width *= 2;
flags |= DOUBLEWFONT;
rect.x = 0;
rect.y = 0;
rect.width = len * font_width;
rect.height = FontHeight(screen);
switch (chrset) {
case CSET_DHL_TOP:
rect.y = -(rect.height / 2);
y -= rect.y;
flags |= DOUBLEHFONT;
break;
case CSET_DHL_BOT:
rect.y = (rect.height / 2);
y -= rect.y;
flags |= DOUBLEHFONT;
break;
default:
nr = 0;
break;
}
if (nr != 0) {
adjust = fs->ascent
+ fs->descent
- (2 * FontHeight(screen));
rect.y -= adjust;
y += adjust;
}
if (nr)
XSetClipRectangles(screen->display, gc2,
x, y, rp, nr, YXBanded);
else
XSetClipMask(screen->display, gc2, None);
if (screen->fnt_prop
|| (fs->min_bounds.width != fs->max_bounds.width)
|| (fs->min_bounds.width != 2 * FontWidth(screen))) {
while (len--) {
x = drawXtermText(screen, flags, gc2,
x, y, 0,
PAIRED_CHARS(text++, text2++),
1, on_wide);
x += FontWidth(screen);
}
} else {
x = drawXtermText(screen, flags, gc2,
x, y, 0,
PAIRED_CHARS(text, text2),
len, on_wide);
x += len * FontWidth(screen);
}
TRACE(("drewtext [%4d,%4d]\n", y, x));
} else {
#if OPT_WIDE_CHARS
Char *wide = 0;
#endif
unsigned need = 2 * len;
Char *temp = (Char *) malloc(need);
int n = 0;
if_OPT_WIDE_CHARS(screen, {
wide = (Char *) malloc(need);
});
while (len--) {
if_OPT_WIDE_CHARS(screen, {
wide[n] = *text2++;
wide[n + 1] = 0;
});
temp[n++] = *text++;
temp[n++] = ' ';
}
x = drawXtermText(screen,
flags,
gc,
x, y,
0,
PAIRED_CHARS(temp, wide),
n,
on_wide);
free(temp);
if_OPT_WIDE_CHARS(screen, {
free(wide);
});
}
return x;
}
#endif
if (!(flags & CHARBYCHAR) && screen->fnt_prop) {
int adj, width;
GC fillGC = gc;
XFontStruct *fs = ((flags & (BOLD | BLINK))
? screen->fnt_bold
: screen->fnt_norm);
#define GC_PAIRS(a,b) \
if (gc == a) fillGC = b; \
if (gc == b) fillGC = a
if (gc == screen->cursorGC
|| gc == screen->reversecursorGC)
fillGC = screen->fillCursorGC;
GC_PAIRS(NormalGC(screen), ReverseGC(screen));
GC_PAIRS(NormalBoldGC(screen), ReverseBoldGC(screen));
if (!(flags & NOBACKGROUND))
XFillRectangle(screen->display, VWindow(screen), fillGC,
x, y, len * FontWidth(screen), FontHeight(screen));
while (len--) {
width = XTextWidth(fs, (char *) text, 1);
adj = (FontWidth(screen) - width) / 2;
(void) drawXtermText(screen, flags | NOBACKGROUND | CHARBYCHAR,
gc, x + adj, y, chrset,
PAIRED_CHARS(text++, text2++), 1, on_wide);
x += FontWidth(screen);
}
return x;
}
#if OPT_BOX_CHARS
#define DrawX(col) x + (col * (font_width))
#define DrawSegment(first,last) (void)drawXtermText(screen, flags|NOTRANSLATION, gc, DrawX(first), y, chrset, PAIRED_CHARS(text+first, text2+first), last-first, on_wide)
if (!(flags & NOTRANSLATION)
&& (!screen->fnt_boxes || screen->force_box_chars)) {
XFontStruct *font = ((flags & BOLD)
? screen->fnt_bold
: screen->fnt_norm);
Cardinal last, first = 0;
for (last = 0; last < len; last++) {
unsigned ch = text[last];
Boolean isMissing;
#if OPT_WIDE_CHARS
if (text2 != 0)
ch |= (text2[last] << 8);
isMissing = (ch != HIDDEN_CHAR)
&& (xtermMissingChar(ch,
((on_wide || iswide(ch)) && screen->fnt_dwd)
? screen->fnt_dwd
: font));
#else
isMissing = xtermMissingChar(ch, font);
#endif
if (isMissing) {
if (last > first)
DrawSegment(first, last);
xtermDrawBoxChar(screen, ch, flags, gc, DrawX(last), y);
first = last + 1;
}
}
if (last <= first)
return x + real_length * FontWidth(screen);
text += first;
#if OPT_WIDE_CHARS
text2 += first;
#endif
len = last - first;
flags |= NOTRANSLATION;
x = DrawX(first);
}
#endif
TRACE(("drawtext%c[%4d,%4d] (%d) %d:%s\n",
screen->cursor_state == OFF ? ' ' : '*',
y, x, chrset, len,
visibleChars(PAIRED_CHARS(text, text2), len)));
y += FontAscent(screen);
#if OPT_WIDE_CHARS
if (screen->wide_chars) {
int ascent_adjust = 0;
static XChar2b *sbuf;
static Cardinal slen;
Cardinal n;
int ch = text[0] | (text2[0] << 8);
int wideness = ((on_wide || iswide(ch) != 0)
&& (screen->fnt_dwd != NULL));
unsigned char *endtext = text + len;
if (slen < len) {
slen = (len + 1) * 2;
sbuf = (XChar2b *) XtRealloc((char *) sbuf, slen * sizeof(*sbuf));
}
for (n = 0; n < len; n++) {
sbuf[n].byte2 = *text;
sbuf[n].byte1 = *text2;
text++;
text2++;
if (wideness) {
while (text < endtext
&& *text == HIDDEN_HI
&& *text2 == HIDDEN_LO) {
text++;
text2++;
len--;
}
}
}
underline_len = len;
if (flags & (DOUBLEHFONT | DOUBLEWFONT)) {
;
} else if (wideness
&& (screen->fnt_dwd->fid || screen->fnt_dwdb->fid)) {
underline_len = real_length = len * 2;
if ((flags & (BOLD | BLINK)) != 0
&& screen->fnt_dwdb->fid) {
XSetFont(screen->display, gc, screen->fnt_dwdb->fid);
ascent_adjust = screen->fnt_dwdb->ascent - screen->fnt_norm->ascent;
} else {
XSetFont(screen->display, gc, screen->fnt_dwd->fid);
ascent_adjust = screen->fnt_dwd->ascent - screen->fnt_norm->ascent;
}
} else if ((flags & (BOLD | BLINK)) != 0
&& screen->fnt_bold->fid) {
XSetFont(screen->display, gc, screen->fnt_bold->fid);
} else {
XSetFont(screen->display, gc, screen->fnt_norm->fid);
}
if (flags & NOBACKGROUND)
XDrawString16(screen->display,
VWindow(screen), gc,
x, y + ascent_adjust,
sbuf, n);
else
XDrawImageString16(screen->display,
VWindow(screen), gc,
x, y + ascent_adjust,
sbuf, n);
if ((flags & (BOLD | BLINK)) && screen->enbolden) {
beginClipping(screen, gc, font_width, len);
XDrawString16(screen->display, VWindow(screen), gc,
x + 1, y + ascent_adjust, sbuf, n);
endClipping(screen, gc);
}
} else
#endif
{
if (flags & NOBACKGROUND)
XDrawString(screen->display, VWindow(screen), gc,
x, y, (char *) text, len);
else
XDrawImageString(screen->display, VWindow(screen), gc,
x, y, (char *) text, len);
underline_len = len;
if ((flags & (BOLD | BLINK)) && screen->enbolden) {
beginClipping(screen, gc, font_width, len);
XDrawString(screen->display, VWindow(screen), gc,
x + 1, y, (char *) text, len);
endClipping(screen, gc);
}
}
if ((flags & UNDERLINE) && screen->underline) {
if (FontDescent(screen) > 1)
y++;
XDrawLine(screen->display, VWindow(screen), gc,
x, y, x + underline_len * font_width - 1, y);
}
return x + real_length * FontWidth(screen);
}
GC
updatedXtermGC(TScreen * screen, int flags, int fg_bg, Bool hilite)
{
int my_fg = extract_fg(fg_bg, flags);
int my_bg = extract_bg(fg_bg, flags);
Pixel fg_pix = getXtermForeground(flags, my_fg);
Pixel bg_pix = getXtermBackground(flags, my_bg);
#if OPT_HIGHLIGHT_COLOR
Pixel hi_pix = screen->highlightcolor;
#endif
GC gc;
checkVeryBoldColors(flags, my_fg);
if (ReverseOrHilite(screen, flags, hilite)) {
if (flags & (BOLD | BLINK))
gc = ReverseBoldGC(screen);
else
gc = ReverseGC(screen);
#if OPT_HIGHLIGHT_COLOR
if (hi_pix != screen->foreground
&& hi_pix != fg_pix
&& hi_pix != bg_pix
&& hi_pix != term->dft_foreground) {
bg_pix = fg_pix;
fg_pix = hi_pix;
}
#endif
XSetForeground(screen->display, gc, bg_pix);
XSetBackground(screen->display, gc, fg_pix);
} else {
if (flags & (BOLD | BLINK))
gc = NormalBoldGC(screen);
else
gc = NormalGC(screen);
XSetForeground(screen->display, gc, fg_pix);
XSetBackground(screen->display, gc, bg_pix);
}
return gc;
}
void
resetXtermGC(TScreen * screen, int flags, Bool hilite)
{
Pixel fg_pix = getXtermForeground(flags, term->cur_foreground);
Pixel bg_pix = getXtermBackground(flags, term->cur_background);
GC gc;
checkVeryBoldColors(flags, term->cur_foreground);
if (ReverseOrHilite(screen, flags, hilite)) {
if (flags & (BOLD | BLINK))
gc = ReverseBoldGC(screen);
else
gc = ReverseGC(screen);
XSetForeground(screen->display, gc, bg_pix);
XSetBackground(screen->display, gc, fg_pix);
} else {
if (flags & (BOLD | BLINK))
gc = NormalBoldGC(screen);
else
gc = NormalGC(screen);
XSetForeground(screen->display, gc, fg_pix);
XSetBackground(screen->display, gc, bg_pix);
}
}
#if OPT_ISO_COLORS
int
extract_fg(unsigned color, unsigned flags)
{
int fg = (int) ExtractForeground(color);
if (term->screen.colorAttrMode
|| (fg == (int) ExtractBackground(color))) {
if (term->screen.colorULMode && (flags & UNDERLINE))
fg = COLOR_UL;
if (term->screen.colorBDMode && (flags & BOLD))
fg = COLOR_BD;
if (term->screen.colorBLMode && (flags & BLINK))
fg = COLOR_BL;
}
return fg;
}
int
extract_bg(unsigned color, unsigned flags)
{
int bg = (int) ExtractBackground(color);
if (term->screen.colorAttrMode
|| (bg == (int) ExtractForeground(color))) {
if (term->screen.colorRVMode && (flags & INVERSE))
bg = COLOR_RV;
}
return bg;
}
unsigned
makeColorPair(int fg, int bg)
{
unsigned my_bg = (bg >= 0) && (bg < NUM_ANSI_COLORS) ? (unsigned) bg : 0;
unsigned my_fg = (fg >= 0) && (fg < NUM_ANSI_COLORS) ? (unsigned) fg : my_bg;
#if OPT_EXT_COLORS
return (my_fg << 8) | my_bg;
#else
return (my_fg << 4) | my_bg;
#endif
}
void
ClearCurBackground(
TScreen * screen,
int top,
int left,
unsigned height,
unsigned width)
{
XSetWindowBackground(
screen->display,
VWindow(screen),
getXtermBackground(term->flags, term->cur_background));
XClearArea(screen->display, VWindow(screen),
left, top, width, height, FALSE);
XSetWindowBackground(
screen->display,
VWindow(screen),
getXtermBackground(term->flags, MAXCOLORS));
}
#endif
#if OPT_WIDE_CHARS
unsigned
getXtermCell(TScreen * screen, int row, int col)
{
unsigned ch = SCRN_BUF_CHARS(screen, row)[col];
if_OPT_WIDE_CHARS(screen, {
ch |= (SCRN_BUF_WIDEC(screen, row)[col] << 8);
});
return ch;
}
unsigned
getXtermCellComb1(TScreen * screen, int row, int col)
{
unsigned ch = SCRN_BUF_COM1L(screen, row)[col];
ch |= (SCRN_BUF_COM1H(screen, row)[col] << 8);
return ch;
}
unsigned
getXtermCellComb2(TScreen * screen, int row, int col)
{
unsigned ch = SCRN_BUF_COM2L(screen, row)[col];
ch |= (SCRN_BUF_COM2H(screen, row)[col] << 8);
return ch;
}
void
putXtermCell(TScreen * screen, int row, int col, int ch)
{
SCRN_BUF_CHARS(screen, row)[col] = ch;
if_OPT_WIDE_CHARS(screen, {
SCRN_BUF_WIDEC(screen, row)[col] = (ch >> 8);
SCRN_BUF_COM1L(screen, row)[col] = 0;
SCRN_BUF_COM1H(screen, row)[col] = 0;
SCRN_BUF_COM2L(screen, row)[col] = 0;
SCRN_BUF_COM2H(screen, row)[col] = 0;
});
}
void
addXtermCombining(TScreen * screen, int row, int col, unsigned ch)
{
if (!SCRN_BUF_COM1L(screen, row)[col]
&& !SCRN_BUF_COM1H(screen, row)[col]) {
SCRN_BUF_COM1L(screen, row)[col] = ch & 0xff;
SCRN_BUF_COM1H(screen, row)[col] = ch >> 8;
} else if (!SCRN_BUF_COM2H(screen, row)[col]) {
SCRN_BUF_COM2L(screen, row)[col] = ch & 0xff;
SCRN_BUF_COM2H(screen, row)[col] = ch >> 8;
}
}
#endif
#ifdef HAVE_CONFIG_H
#ifdef USE_MY_MEMMOVE
char *
my_memmove(char *s1, char *s2, size_t n)
{
if (n != 0) {
if ((s1 + n > s2) && (s2 + n > s1)) {
static char *bfr;
static size_t length;
size_t j;
if (length < n) {
length = (n * 3) / 2;
bfr = ((bfr != 0)
? realloc(bfr, length)
: malloc(length));
if (bfr == NULL)
SysError(ERROR_MMALLOC);
}
for (j = 0; j < n; j++)
bfr[j] = s2[j];
s2 = bfr;
}
while (n-- != 0)
s1[n] = s2[n];
}
return s1;
}
#endif
#ifndef HAVE_STRERROR
char *
my_strerror(int n)
{
extern char *sys_errlist[];
extern int sys_nerr;
if (n > 0 && n < sys_nerr)
return sys_errlist[n];
return "?";
}
#endif
#endif
int
char2lower(int ch)
{
if (isascii(ch) && isupper(ch)) {
#ifdef _tolower
ch = _tolower(ch);
#else
ch = tolower(ch);
#endif
}
return ch;
}
void
update_keyboard_type(void)
{
update_delete_del();
update_old_fkeys();
update_hp_fkeys();
update_sco_fkeys();
update_sun_fkeys();
update_sun_kbd();
}
void
set_keyboard_type(xtermKeyboardType type, Bool set)
{
xtermKeyboardType save = term->keyboard.type;
if (set) {
term->keyboard.type = type;
} else {
term->keyboard.type = keyboardIsDefault;
}
if (save != term->keyboard.type) {
update_keyboard_type();
}
}
void
toggle_keyboard_type(xtermKeyboardType type)
{
xtermKeyboardType save = term->keyboard.type;
if (term->keyboard.type == type) {
term->keyboard.type = keyboardIsDefault;
} else {
term->keyboard.type = type;
}
if (save != term->keyboard.type) {
update_keyboard_type();
}
}
void
init_keyboard_type(xtermKeyboardType type, Bool set)
{
static Bool wasSet = False;
if (set) {
if (wasSet) {
fprintf(stderr, "Conflicting keyboard type option (%d/%d)\n",
term->keyboard.type, type);
}
term->keyboard.type = type;
wasSet = True;
}
}