diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/programs/xterm/screen.c | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2 nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip |
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz
Keywords:
Imported nx-X11-3.1.0-1.tar.gz
into Git repository
Diffstat (limited to 'nx-X11/programs/xterm/screen.c')
-rw-r--r-- | nx-X11/programs/xterm/screen.c | 1853 |
1 files changed, 1853 insertions, 0 deletions
diff --git a/nx-X11/programs/xterm/screen.c b/nx-X11/programs/xterm/screen.c new file mode 100644 index 000000000..09712218f --- /dev/null +++ b/nx-X11/programs/xterm/screen.c @@ -0,0 +1,1853 @@ +/* $XTermId: screen.c,v 1.184 2005/11/03 13:17:28 tom Exp $ */ + +/* + * $Xorg: screen.c,v 1.3 2000/08/17 19:55:09 cpqbld Exp $ + */ + +/* + * Copyright 1999-2004,2005 by Thomas E. Dickey + * + * All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the + * sale, use or other dealings in this Software without prior written + * authorization. + * + * + * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + * + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Digital Equipment + * Corporation not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior permission. + * + * + * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* $XFree86: xc/programs/xterm/screen.c,v 3.73 2005/11/03 13:17:28 dickey Exp $ */ + +/* screen.c */ + +#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) + +/* + * Allocates memory for a 2-dimensional array of chars and returns a pointer + * thereto. Each line is formed from a set of char arrays, with an index + * (i.e., the ScrnBuf type). The first pointer in the index is reserved for + * per-line flags, and does not point to data. + * + * After the per-line flags, we have a series of pointers to char arrays: The + * first one is the actual character array, the second one is the attributes, + * the third is the foreground and background colors, and the fourth denotes + * the character set. + * + * We store it all as pointers, because of alignment considerations, together + * with the intention of being able to change the total number of pointers per + * row according to whether the user wants color or not. + */ +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; /* per-line flags */ + k += BUF_HEAD; + for (j = BUF_HEAD; j < MAX_PTRS; j++) { + base[k++] = tmp; + tmp += ncol; + } + } + + return (base); +} + +/* + * This is called when the screen is resized. + * Returns the number of lines the text was moved down (neg for up). + * (Return value only necessary with SouthWestGravity.) + */ +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; + + /* + * Special case if oldcol == ncol - straight forward realloc and + * update of the additional lines in sbuf + * + * FIXME: this is a good idea, but doesn't seem to be implemented. + * -gildea + */ + + /* + * realloc sbuf, the pointers to all the lines. + * If the screen shrinks, remove lines off the top of the buffer + * if resizeGravity resource says to do so. + */ + if (nrow < oldrow + && term->misc.resizeGravity == SouthWestGravity) { + /* Remove lines off the top of the buffer if necessary. */ + move_up = (oldrow - nrow) + - (term->screen.max_row - term->screen.cur_row); + if (move_up < 0) + move_up = 0; + /* Overlapping memmove here! */ + 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; + + /* + * create the new buffer space and copy old buffer contents there + * line by line. + */ + 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 data down to bottom of expanded screen */ + 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; + } + } + + /* + * update the pointers in sbuf + */ + 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; + } + } + + /* Now free the old buffer */ + free(oldbuf); + + return move_down ? move_down : -move_up; /* convert to rows */ +} + +#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) /* nothing */ +#endif + +/* + * This function reallocates memory if changing the number of Buf offsets. + * The code is based on Reallocate(). + */ +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; + /* + * As there are 2 buffers (allbuf, altbuf), we cannot change num_ptrs in + * this function. However MAX_PTRS and BUF_PTRS depend on num_ptrs so + * change it now and restore the value when done. + */ + 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); + } + + /* + * update the pointers in sbuf + */ + 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; + } + } + + /* Now free the old buffer and restore num_ptrs */ + free(oldbuf); + dump_screen("after", *sbuf, *sbufaddr, nrow, ncol); + + term->num_ptrs = old_max_ptrs; +} + +/* + * This function dynamically adds support for wide-characters. + */ +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 + +/* + * Disown the selection and repaint the area that is highlighted so it is no + * longer highlighted. + */ +void +ScrnDisownSelection(TScreen * screen) +{ + if (ScrnHaveSelection(screen)) { + DisownSelection(term); + } +} + +/* + * Writes str into buf at screen's current row and column. Characters are set + * to match flags. + */ +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 + + /* write blanks if we're writing invisible text */ + if (flags & INVISIBLE) { + memset(chars, ' ', length); + } else { + memcpy(chars, str, length); /* This can stand for the present. If it + is wrong, we will scribble over it */ + } + +#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; + } + /* if we are overwriting the right hand half of a + wide character, make the other half vanish */ + 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; + } + /* if we are overwriting the left hand half of a + wide character, make the other half vanish */ + } + + 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 we are overwriting the right hand half of a + wide character, make the other half vanish */ + if (chars[length] == HIDDEN_LO && char2[length] == HIDDEN_HI && + iswide(starcol2 | (char2[length - 1] << 8))) { + chars[length] = ERROR_1; + char2[length] = ERROR_2; + } + /* if we are overwriting the left hand half of a + wide character, make the other half vanish */ + 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); + }); +} + +/* + * Saves pointers to the n lines beginning at sb + where, and clears the lines + */ +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); + + /* save n lines at where */ + memcpy((char *) screen->save_ptr, + (char *) &sb[MAX_PTRS * where], + len); + + /* clear contents of old rows */ + 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); +} + +/* + * Inserts n blank lines at sb + where, treating last as a bottom margin. + * size is the size of each entry in sb. + */ +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); + + /* save n lines at bottom */ + ScrnClearLines(screen, sb, (last -= n - 1), n, size); + + /* + * WARNING, overlapping copy operation. Move down lines (pointers). + * + * +----|---------|--------+ + * + * is copied in the array to: + * + * +--------|---------|----+ + */ + assert(last >= where); + memmove((char *) &sb[MAX_PTRS * (where + n)], + (char *) &sb[MAX_PTRS * where], + MAX_PTRS * sizeof(char *) * (last - where)); + + /* reuse storage for new lines at where */ + memcpy((char *) &sb[MAX_PTRS * where], + (char *) screen->save_ptr, + len); +} + +/* + * Deletes n lines at sb + where, treating last as a bottom margin. + * size is the size of each entry in sb. + */ +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); + + /* move up lines */ + memmove((char *) &sb[MAX_PTRS * where], + (char *) &sb[MAX_PTRS * (where + n)], + MAX_PTRS * sizeof(char *) * ((last -= n - 1) - where)); + + /* reuse storage for new bottom lines */ + memcpy((char *) &sb[MAX_PTRS * last], + (char *) screen->save_ptr, + MAX_PTRS * sizeof(char *) * n); +} + +/* + * Inserts n blanks in screen at current row, col. Size is the size of each + * row. + */ +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); /* make sure the bit isn't moved */ + 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); +} + +/* + * Deletes n characters at current row, col. + */ +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); +} + +/* + * Repaints the area enclosed by the parameters. + * Requires: (toprow, leftcol), (toprow + nrows, leftcol + ncols) are + * coordinates of characters in screen; + * nrows and ncols positive. + * all dimensions are based on single-characters. + */ +void +ScrnRefresh(TScreen * screen, + int toprow, + int leftcol, + int nrows, + int ncols, + Bool force) /* ... leading/trailing spaces */ +{ + 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, { + /* This fixes an infinite recursion bug, that leads + to display anomalies. It seems to be related to + problems with the selection. */ + if (recurse < 3) { + /* adjust to redraw all of a widechar if we just wanted + to draw the right hand half */ + 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 + /* + * Temporarily change dimensions to double-sized characters so + * we can reuse the recursion on this function. + */ + if (CSET_DOUBLE(*cb)) { + col /= 2; + maxcol /= 2; + } +#endif + /* + * If row does not intersect selection; don't hilite blanks. + */ + 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 { + /* row intersects selection; split into pieces of single type */ + 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 we're highlighting because the user is doing cut/paste, + * trim the trailing blanks from the highlighted region so we're + * showing the actual extent of the text that'll be cut. If + * we're selecting a blank line, we'll highlight one column + * anyway. + * + * We don't do this if the mouse-hilite mode is set because that + * would be too confusing. + * + * The default if the highlightSelection resource isn't set will + * highlight the whole width of the terminal, which is easy to + * see, but harder to use (because trailing blanks aren't as + * apparent). + */ + 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--; + } + + /* remaining piece should be hilited */ + hilite = True; + } + + if (col > maxcol) + continue; + + /* + * Go back to double-sized character dimensions if the line has + * double-width characters. Note that 'hi_col' is already in the + * right units. + */ + 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); + /* this combines them, then splits them again. but + extract_fg does more, so seems reasonable */ + 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 we're in color mode, reset the various GC's to the current + * screen foreground and background so that other functions (e.g., + * ClearRight) will get the correct colors. + */ + 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--; +} + +/* + * Call this wrapper to ScrnRefresh() when the data has changed. If the + * refresh region overlaps the selection, we will release the primary selection. + */ +void +ScrnUpdate(TScreen * screen, + int toprow, + int leftcol, + int nrows, + int ncols, + Bool force) /* ... leading/trailing spaces */ +{ + if (ScrnHaveSelection(screen) + && (toprow <= screen->endHRow) + && (toprow + nrows - 1 >= screen->startHRow)) { + ScrnDisownSelection(screen); + } + ScrnRefresh(screen, toprow, leftcol, nrows, ncols, force); +} + +/* + * Sets the rows first though last of the buffer of screen to spaces. + * Requires first <= last; first, last are rows of screen->buf. + */ +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); + }); + } +} + +/* + Resizes screen: + 1. If new window would have fractional characters, sets window size so as to + discard fractional characters and returns -1. + Minimum screen size is 1 X 1. + Note that this causes another ExposeWindow event. + 2. Enlarges screen->buf if necessary. New space is appended to the bottom + and to the right + 3. Reduces screen->buf if necessary. Old space is removed from the bottom + and from the right + 4. Cursor is positioned as closely to its former position as possible + 5. Sets screen->max_row and screen->max_col to reflect new size + 6. Maintains the inner border (and clears the border on the screen). + 7. Clears origin mode and sets scrolling region to be entire screen. + 8. Returns 0 + */ +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); + + /* clear the right and bottom internal border because of NorthWest + gravity might have left junk on the right and bottom edges */ + if (width >= FullWidth(screen)) { + XClearArea(screen->display, tw, + FullWidth(screen), 0, /* right edge */ + 0, (unsigned) height, /* from top to bottom */ + False); + } + if (height >= FullHeight(screen)) { + XClearArea(screen->display, tw, + 0, FullHeight(screen), /* bottom */ + (unsigned) width, 0, /* all across the bottom */ + 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; + + /* update buffers if the screen has changed size */ + 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) + /* swap buffer pointers back to make all this hair work */ + 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); /* put the pointers back */ + } + + /* adjust scrolling region */ + 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); /* nothing has changed at all */ + + 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 /* NO_ACTIVE_ICON */ + +#ifdef TTYSIZE_STRUCT + /* Set tty's idea of window size */ + 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 /* SIGWINCH */ + +#else + TRACE(("ScreenResize cannot do anything to pty\n")); +#endif /* TTYSIZE_STRUCT */ + return (0); +} + +/* + * Return true if any character cell starting at [row,col], for len-cells is + * nonnull. + */ +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; +} + +/* + * Copy the rectangle boundaries into a struct, providing default values as + * needed. + */ +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); +} + +/* + * Fills a rectangle with the given character and video-attributes. + */ +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 +/* + * Copies the source rectangle to the target location, including video + * attributes. + * + * This implementation ignores page numbers. + * + * The reference manual does not indicate if it handles overlapping copy + * properly - so we make a local copy of the source rectangle first, then apply + * the target from that. + */ +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); + } + } +} + +/* + * Modifies the video-attributes only - so selection is unaffected. + */ +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); + } +} + +/* + * Resets characters to space, except where prohibited by DECSCA. Video + * attributes are untouched. + */ +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 /* OPT_DEC_RECTOPS */ |