--- rxvt-unicode/src/screen.C 2011/11/15 19:54:30 1.403 +++ rxvt-unicode/src/screen.C 2022/08/08 09:47:56 1.468 @@ -4,10 +4,11 @@ * * Copyright (c) 1997-2001 Geoff Wing * Copyright (c) 2003-2007 Marc Lehmann + * Copyright (c) 2015 Emanuele Giaquinta * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -30,8 +31,6 @@ #include -#include "salloc.C" // HACK, should be a separate compile! - static inline void fill_text (text_t *start, text_t value, int len) { @@ -98,11 +97,11 @@ /* Fill part/all of a line with blanks. */ void -rxvt_term::scr_blank_line (line_t &l, unsigned int col, unsigned int width, rend_t efs) const NOTHROW +rxvt_term::scr_blank_line (line_t &l, unsigned int col, unsigned int width, rend_t efs) const noexcept { - if (!l.t) + if (!l.valid ()) { - lalloc (l); + l.alloc (); col = 0; width = ncol; } @@ -110,7 +109,7 @@ l.touch (); efs &= ~RS_baseattrMask; // remove italic etc. fontstyles - efs = SET_FONT (efs, FONTSET (efs)->find_font (' ')); + efs = SET_FONT (efs, FONTSET (efs)->find_space_font ()); text_t *et = l.t + col; rend_t *er = l.r + col; @@ -125,7 +124,7 @@ /* ------------------------------------------------------------------------- */ /* Fill a full line with blanks - make sure it is allocated first */ void -rxvt_term::scr_blank_screen_mem (line_t &l, rend_t efs) const NOTHROW +rxvt_term::scr_blank_screen_mem (line_t &l, rend_t efs) const noexcept { scr_blank_line (l, 0, ncol, efs); @@ -135,14 +134,14 @@ // nuke a single wide character at the given column void -rxvt_term::scr_kill_char (line_t &l, int col) const NOTHROW +rxvt_term::scr_kill_char (line_t &l, int col) const noexcept { // find begin while (col > 0 && l.t[col] == NOCHAR) col--; rend_t rend = l.r[col] & ~RS_baseattrMask; - rend = SET_FONT (rend, FONTSET (rend)->find_font (' ')); + rend = SET_FONT (rend, FONTSET (rend)->find_space_font ()); l.touch (); @@ -154,11 +153,65 @@ } while (col < ncol && l.t[col] == NOCHAR); } +// set the rendition of a single wide character beginning at the given column +void +rxvt_term::scr_set_char_rend (line_t &l, int col, rend_t rend) +{ + do { + l.r[col] = rend; + col++; + } while (col < ncol && l.t[col] == NOCHAR); +} + /* ------------------------------------------------------------------------- * * SCREEN INITIALISATION * * ------------------------------------------------------------------------- */ void +rxvt_term::scr_alloc () noexcept +{ + int tsize = sizeof (text_t) * ncol; + int rsize = sizeof (rend_t) * ncol; + + // we assume that rend_t size is a sufficient alignment + // factor for text_t and line_t values, and we only + // need to adjust tsize. + tsize = (tsize + sizeof (rend_t) - 1); + tsize -= tsize % sizeof (rend_t); + + int all_rows = total_rows + nrow + nrow; + + chunk_size = (sizeof (line_t) + rsize + tsize) * all_rows; + chunk = chunk_alloc (chunk_size, 0); + + char *base = (char *)chunk + sizeof (line_t) * all_rows; + + for (int row = 0; row < all_rows; ++row) + { + line_t &l = ((line_t *)chunk) [row]; + + l.t = (text_t *)base; base += tsize; + l.r = (rend_t *)base; base += rsize; + l.l = -1; + l.f = 0; + } + + drawn_buf = (line_t *)chunk; + swap_buf = drawn_buf + nrow; + row_buf = swap_buf + nrow; +} + +void +rxvt_term::copy_line (line_t &dst, line_t &src) +{ + scr_blank_screen_mem (dst, DEFAULT_RSTYLE); + dst.l = min (src.l, ncol); + memcpy (dst.t, src.t, sizeof (text_t) * dst.l); + memcpy (dst.r, src.r, sizeof (rend_t) * dst.l); + dst.f = src.f; +} + +void ecb_cold rxvt_term::scr_reset () { #if ENABLE_OVERLAY @@ -194,28 +247,19 @@ screen.tscroll = 0; screen.bscroll = nrow - 1; - if (!row_buf) + void *prev_chunk = chunk; + size_t prev_chunk_size = chunk_size; + line_t *prev_drawn_buf = drawn_buf; + line_t *prev_swap_buf = swap_buf; + line_t *prev_row_buf = row_buf; + + scr_alloc (); + + if (!prev_row_buf) { - /* - * first time called so just malloc everything: don't rely on realloc - */ top_row = 0; term_start = 0; - talloc = new rxvt_salloc (ncol * sizeof (text_t)); - ralloc = new rxvt_salloc (ncol * sizeof (rend_t)); - - row_buf = (line_t *)rxvt_calloc (total_rows , sizeof (line_t)); - drawn_buf = (line_t *)rxvt_calloc (nrow , sizeof (line_t)); - swap_buf = (line_t *)rxvt_calloc (nrow , sizeof (line_t)); - - for (int row = nrow; row--; ) - { - scr_blank_screen_mem (ROW (row), DEFAULT_RSTYLE); - scr_blank_screen_mem (swap_buf [row], DEFAULT_RSTYLE); - scr_blank_screen_mem (drawn_buf[row], DEFAULT_RSTYLE); - } - memset (charsets, 'B', sizeof (charsets)); rstyle = DEFAULT_RSTYLE; screen.flags = Screen_DefaultFlags; @@ -247,43 +291,24 @@ * add or delete rows as appropriate */ - rxvt_salloc *old_ta = talloc; talloc = new rxvt_salloc (ncol * sizeof (text_t)); - rxvt_salloc *old_ra = ralloc; ralloc = new rxvt_salloc (ncol * sizeof (rend_t)); - -#if 0 - if (nrow < prev_nrow) - { - for (int row = nrow; row < prev_nrow; row++) - { - lfree (swap_buf [row]); - lfree (drawn_buf[row]); - } - } -#endif - - drawn_buf = (line_t *)rxvt_realloc (drawn_buf, nrow * sizeof (line_t)); - swap_buf = (line_t *)rxvt_realloc (swap_buf , nrow * sizeof (line_t)); + int common_col = min (prev_ncol, ncol); + // resize swap_buf, blank drawn_buf for (int row = min (nrow, prev_nrow); row--; ) { - lresize (drawn_buf[row]); - lresize (swap_buf [row]); - } + scr_blank_screen_mem (drawn_buf [row], DEFAULT_RSTYLE); + memcpy (drawn_buf [row].t, prev_drawn_buf [row].t, sizeof (text_t) * common_col); + memcpy (drawn_buf [row].r, prev_drawn_buf [row].r, sizeof (rend_t) * common_col); - for (int row = prev_nrow; row < nrow; row++) - { - swap_buf [row].clear (); scr_blank_screen_mem (swap_buf [row], DEFAULT_RSTYLE); - drawn_buf[row].clear (); scr_blank_screen_mem (drawn_buf[row], DEFAULT_RSTYLE); + copy_line (swap_buf [row], prev_swap_buf [row]); } - line_t *old_buf = row_buf; - row_buf = (line_t *)rxvt_calloc (total_rows, sizeof (line_t)); - int p = MOD (term_start + prev_nrow, prev_total_rows); // previous row int pend = MOD (term_start + top_row , prev_total_rows); int q = total_rows; // rewrapped row - if (top_row) +#if ENABLE_FRILLS + if ((rewrap_always || top_row) && !rewrap_never) { // Re-wrap lines. This is rather ugly, possibly because I am too dumb // to come up with a lean and mean algorithm. @@ -295,11 +320,11 @@ do { p = MOD (p - 1, prev_total_rows); - assert (old_buf [MOD (p, prev_total_rows)].t); + assert (prev_row_buf [MOD (p, prev_total_rows)].t); int plines = 1; - int llen = old_buf [MOD (p, prev_total_rows)].l; + int llen = prev_row_buf [MOD (p, prev_total_rows)].l; - while (p != pend && old_buf [MOD (p - 1, prev_total_rows)].is_longer ()) + while (p != pend && prev_row_buf [MOD (p - 1, prev_total_rows)].is_longer ()) { p = MOD (p - 1, prev_total_rows); @@ -322,7 +347,7 @@ for (int qrow = q; qlines--; qrow++) { qline = row_buf + qrow; - lalloc (*qline); + qline->alloc (); // redundant with next line qline->l = ncol; qline->is_longer (1); @@ -347,7 +372,7 @@ if (prow == ocur.row) screen.cur.row = q - (total_rows - nrow); - line_t &pline = old_buf [prow]; + line_t &pline = prev_row_buf [prow]; int len = min (min (prev_ncol - pcol, ncol - qcol), llen - lofs); @@ -373,34 +398,36 @@ scr_blank_screen_mem (ROW (--top_row), DEFAULT_RSTYLE); } else +#endif { - // if no scrollback exists (yet), wing, instead of wrap - - for (int row = min (nrow, prev_nrow); row--; ) + // wing, instead of wrap + do { - line_t &pline = old_buf [MOD (term_start + row, prev_total_rows)]; - line_t &qline = row_buf [row]; - - qline = pline; - lresize (qline); - } + p = MOD (p - 1, prev_total_rows); + q--; - for (int row = prev_nrow; row < nrow; row++) - { - row_buf [row].clear (); scr_blank_screen_mem (row_buf [row], DEFAULT_RSTYLE); + copy_line (row_buf [q], prev_row_buf [p]); } + while (p != pend); - term_start = 0; + screen.cur.row += nrow - prev_nrow; + term_start = total_rows - nrow; } - free (old_buf); - delete old_ta; - delete old_ra; - clamp_it (screen.cur.row, 0, nrow - 1); clamp_it (screen.cur.col, 0, ncol - 1); } + // ensure drawn_buf, swap_buf and terminal rows are all initialized + for (int row = nrow; row--; ) + { + if (!ROW (row).valid ()) scr_blank_screen_mem (ROW (row), DEFAULT_RSTYLE); + if (!swap_buf [row].valid ()) scr_blank_screen_mem (swap_buf [row], DEFAULT_RSTYLE); + if (!drawn_buf [row].valid ()) scr_blank_screen_mem (drawn_buf [row], DEFAULT_RSTYLE); + } + + chunk_free (prev_chunk, prev_chunk_size); + free (tabs); tabs = (char *)rxvt_malloc (ncol); @@ -417,36 +444,26 @@ HOOK_INVOKE ((this, HOOK_RESET, DT_END)); } -/* ------------------------------------------------------------------------- */ -/* - * Free everything. That way malloc debugging can find leakage. - */ -void -rxvt_term::scr_release () NOTHROW +void ecb_cold +rxvt_term::scr_release () noexcept { - if (row_buf) - { - delete talloc; talloc = 0; - delete ralloc; ralloc = 0; + chunk_free (chunk, chunk_size); + chunk = 0; + row_buf = 0; - free (row_buf); - free (swap_buf); - free (drawn_buf); - row_buf = 0; // signal that we freed all the arrays above - - free (tabs); - tabs = 0; - } + free (tabs); + tabs = 0; } /* ------------------------------------------------------------------------- */ /* * Hard/Soft reset */ -void +void ecb_cold rxvt_term::scr_poweron () { scr_release (); + prev_nrow = prev_ncol = 0; rvideo_mode = false; scr_soft_reset (); @@ -456,8 +473,8 @@ scr_refresh (); } -void -rxvt_term::scr_soft_reset () +void ecb_cold +rxvt_term::scr_soft_reset () noexcept { /* only affects modes, nothing drastic such as clearing the screen */ #if ENABLE_OVERLAY @@ -481,7 +498,7 @@ * XTERM_SEQ: Restore cursor: ESC 8 */ void -rxvt_term::scr_cursor (cursor_mode mode) NOTHROW +rxvt_term::scr_cursor (cursor_mode mode) noexcept { screen_t *s; @@ -522,7 +539,7 @@ } void -rxvt_term::scr_swap_screen () +rxvt_term::scr_swap_screen () noexcept { if (!option (Opt_secondaryScreen)) return; @@ -551,7 +568,12 @@ want_refresh = 1; view_start = 0; - selection_check (2); /* check for boundary cross */ + /* check for boundary cross */ + row_col_t pos; + pos.row = pos.col = 0; + if (ROWCOL_IS_BEFORE (selection.beg, pos) + && ROWCOL_IS_AFTER (selection.end, pos)) + CLEAR_SELECTION (); current_screen = scrn; @@ -575,7 +597,7 @@ // clear WrapNext indicator, solidifying position on next line void -rxvt_term::scr_do_wrap () NOTHROW +rxvt_term::scr_do_wrap () noexcept { if (!(screen.flags & Screen_WrapNext)) return; @@ -595,9 +617,9 @@ * Change the colour for following text */ void -rxvt_term::scr_color (unsigned int color, int fgbg) NOTHROW +rxvt_term::scr_color (unsigned int color, int fgbg) noexcept { - if (!IN_RANGE_INC (color, minCOLOR, maxTermCOLOR)) + if (!IN_RANGE_INC (color, minCOLOR, maxTermCOLOR24)) color = fgbg; if (fgbg == Color_fg) @@ -611,7 +633,7 @@ * Change the rendition style for following text */ void -rxvt_term::scr_rendition (int set, int style) NOTHROW +rxvt_term::scr_rendition (int set, int style) noexcept { if (set) rstyle |= style; @@ -627,8 +649,8 @@ * count positive ==> scroll up * count negative ==> scroll down */ -int -rxvt_term::scr_scroll_text (int row1, int row2, int count) NOTHROW +int ecb_hot +rxvt_term::scr_scroll_text (int row1, int row2, int count) noexcept { if (count == 0 || (row1 > row2)) return 0; @@ -698,7 +720,7 @@ if (option (Opt_scrollWithBuffer) && view_start != 0 && view_start != -saveLines) - scr_page (UP, count); + scr_page (count); if (SHOULD_INVOKE (HOOK_SCROLL_BACK)) HOOK_INVOKE ((this, HOOK_SCROLL_BACK, DT_INT, count, DT_INT, top_row, DT_END)); @@ -771,8 +793,8 @@ /* * Add text given in of length to screen struct */ -void -rxvt_term::scr_add_lines (const wchar_t *str, int len, int minlines) NOTHROW +void ecb_hot +rxvt_term::scr_add_lines (const wchar_t *str, int len, int minlines) noexcept { if (len <= 0) /* sanity */ return; @@ -994,8 +1016,8 @@ && ROW(screen.cur.row - 1).is_longer ()) { linep = &ROW(screen.cur.row - 1); - tp = line->t + ncol - 1; - rp = line->r + ncol - 1; + tp = linep->t + ncol - 1; + rp = linep->r + ncol - 1; } else continue; @@ -1028,7 +1050,7 @@ * XTERM_SEQ: CTRL-H */ void -rxvt_term::scr_backspace () NOTHROW +rxvt_term::scr_backspace () noexcept { if (screen.cur.col == 0) { @@ -1055,7 +1077,7 @@ * XTERM_SEQ: CTRL-I */ void -rxvt_term::scr_tab (int count, bool ht) NOTHROW +rxvt_term::scr_tab (int count, bool ht) noexcept { int i, x; @@ -1131,8 +1153,8 @@ * in that row right. Clear left column. */ #if !ENABLE_MINIMAL -void -rxvt_term::scr_backindex () NOTHROW +void ecb_cold +rxvt_term::scr_backindex () noexcept { if (screen.cur.col > 0) scr_gotorc (0, -1, R_RELATIVE | C_RELATIVE); @@ -1148,8 +1170,8 @@ * in that row left. Clear right column. */ #if !ENABLE_MINIMAL -void -rxvt_term::scr_forwardindex () NOTHROW +void ecb_cold +rxvt_term::scr_forwardindex () noexcept { if (screen.cur.col < ncol - 1) scr_gotorc (0, 1, R_RELATIVE | C_RELATIVE); @@ -1172,7 +1194,7 @@ * Goto Row/Column */ void -rxvt_term::scr_gotorc (int row, int col, int relative) NOTHROW +rxvt_term::scr_gotorc (int row, int col, int relative) noexcept { want_refresh = 1; ZERO_SCROLLBACK (); @@ -1221,22 +1243,18 @@ * direction should be UP or DN */ void -rxvt_term::scr_index (enum page_dirn direction) NOTHROW +rxvt_term::scr_index (enum page_dirn direction) noexcept { - int dirn; - want_refresh = 1; ZERO_SCROLLBACK (); - dirn = ((direction == UP) ? 1 : -1); - screen.flags &= ~Screen_WrapNext; if ((screen.cur.row == screen.bscroll && direction == UP) || (screen.cur.row == screen.tscroll && direction == DN)) - scr_scroll_text (screen.tscroll, screen.bscroll, dirn); + scr_scroll_text (screen.tscroll, screen.bscroll, direction); else - screen.cur.row += dirn; + screen.cur.row += direction; clamp_it (screen.cur.row, 0, nrow - 1); selection_check (0); @@ -1251,7 +1269,7 @@ * extension: clear to right unless wrapped: ESC [ 3 K */ void -rxvt_term::scr_erase_line (int mode) NOTHROW +rxvt_term::scr_erase_line (int mode) noexcept { unsigned int col, num; @@ -1309,13 +1327,13 @@ /* ------------------------------------------------------------------------- */ /* - * Erase part of whole of the screen + * Erase part or whole of the screen * XTERM_SEQ: Clear screen after cursor : ESC [ 0 J * XTERM_SEQ: Clear screen before cursor: ESC [ 1 J * XTERM_SEQ: Clear whole screen : ESC [ 2 J */ void -rxvt_term::scr_erase_screen (int mode) NOTHROW +rxvt_term::scr_erase_screen (int mode) noexcept { int num; int32_t row; @@ -1328,19 +1346,16 @@ switch (mode) { case 0: /* erase to end of screen */ - selection_check (1); scr_erase_line (0); row = screen.cur.row + 1; /* possible OOB */ num = nrow - row; break; case 1: /* erase to beginning of screen */ - selection_check (3); scr_erase_line (1); row = 0; num = screen.cur.row; break; case 2: /* erase whole screen */ - selection_check (3); row = 0; num = nrow; break; @@ -1367,7 +1382,7 @@ if (mapped) XClearArea (dpy, vt, 0, - Row2Pixel (row - view_start), (unsigned int)width, + Row2Pixel (row - view_start), (unsigned int)vt_width, (unsigned int)Height2Pixel (num), False); } else @@ -1380,7 +1395,7 @@ XChangeGC (dpy, gc, GCForeground, &gcvalue); XFillRectangle (dpy, vt, gc, 0, Row2Pixel (row - view_start), - (unsigned int)width, + (unsigned int)vt_width, (unsigned int)Height2Pixel (num)); gcvalue.foreground = pix_colors[Color_fg]; XChangeGC (dpy, gc, GCForeground, &gcvalue); @@ -1398,7 +1413,7 @@ #if !ENABLE_MINIMAL void -rxvt_term::scr_erase_savelines () NOTHROW +rxvt_term::scr_erase_savelines () noexcept { want_refresh = 1; ZERO_SCROLLBACK (); @@ -1412,8 +1427,8 @@ * Fill the screen with `E's * XTERM_SEQ: Screen Alignment Test: ESC # 8 */ -void -rxvt_term::scr_E () NOTHROW +void ecb_cold +rxvt_term::scr_E () noexcept { rend_t fs; @@ -1421,7 +1436,11 @@ ZERO_SCROLLBACK (); num_scr_allow = 0; - selection_check (3); + + row_col_t pos; + pos.row = pos.col = 0; + if (ROWCOL_IS_AFTER (selection.end, pos)) + CLEAR_SELECTION (); fs = SET_FONT (rstyle, FONTSET (rstyle)->find_font ('E')); for (int row = nrow; row--; ) @@ -1444,7 +1463,7 @@ * Insert/Delete lines */ void -rxvt_term::scr_insdel_lines (int count, int insdel) NOTHROW +rxvt_term::scr_insdel_lines (int count, int insdel) noexcept { int end; @@ -1474,7 +1493,7 @@ * Insert/Delete characters from the current position */ void -rxvt_term::scr_insdel_chars (int count, int insdel) NOTHROW +rxvt_term::scr_insdel_chars (int count, int insdel) noexcept { want_refresh = 1; ZERO_SCROLLBACK (); @@ -1582,8 +1601,8 @@ * Set the scrolling region * XTERM_SEQ: Set region - inclusive: ESC [ ; r */ -void -rxvt_term::scr_scroll_region (int top, int bot) NOTHROW +void ecb_cold +rxvt_term::scr_scroll_region (int top, int bot) noexcept { max_it (top, 0); min_it (bot, nrow - 1); @@ -1602,8 +1621,8 @@ * XTERM_SEQ: Make cursor visible : ESC [ ? 25 h * XTERM_SEQ: Make cursor invisible: ESC [ ? 25 l */ -void -rxvt_term::scr_cursor_visible (int mode) NOTHROW +void ecb_cold +rxvt_term::scr_cursor_visible (int mode) noexcept { want_refresh = 1; @@ -1619,8 +1638,8 @@ * XTERM_SEQ: Set Wraparound : ESC [ ? 7 h * XTERM_SEQ: Unset Wraparound: ESC [ ? 7 l */ -void -rxvt_term::scr_autowrap (int mode) NOTHROW +void ecb_cold +rxvt_term::scr_autowrap (int mode) noexcept { if (mode) screen.flags |= Screen_Autowrap; @@ -1638,8 +1657,8 @@ * XTERM_SEQ: Set Absolute: ESC [ ? 6 h * XTERM_SEQ: Set Relative: ESC [ ? 6 l */ -void -rxvt_term::scr_relative_origin (int mode) NOTHROW +void ecb_cold +rxvt_term::scr_relative_origin (int mode) noexcept { if (mode) screen.flags |= Screen_Relative; @@ -1655,8 +1674,8 @@ * XTERM_SEQ: Set Insert mode : ESC [ ? 4 h * XTERM_SEQ: Set Replace mode: ESC [ ? 4 l */ -void -rxvt_term::scr_insert_mode (int mode) NOTHROW +void ecb_cold +rxvt_term::scr_insert_mode (int mode) noexcept { if (mode) screen.flags |= Screen_Insert; @@ -1671,8 +1690,8 @@ * XTERM_SEQ: Clear tab at current column: ESC [ 0 g * XTERM_SEQ: Clear all tabs : ESC [ 3 g */ -void -rxvt_term::scr_set_tab (int mode) NOTHROW +void ecb_cold +rxvt_term::scr_set_tab (int mode) noexcept { if (mode < 0) memset (tabs, 0, ncol); @@ -1687,7 +1706,7 @@ * XTERM_SEQ: Normal video : ESC [ ? 5 l */ void -rxvt_term::scr_rvideo_mode (bool on) NOTHROW +rxvt_term::scr_rvideo_mode (bool on) noexcept { rvideo_mode = on; @@ -1699,9 +1718,17 @@ { rvideo_state = on; +#if OFF_FOCUS_FADING + if (rs[Rs_fade]) + { + ::swap (pix_colors_focused[Color_fg], pix_colors_focused[Color_bg]); + ::swap (pix_colors_unfocused[Color_fg], pix_colors_unfocused[Color_bg]); + } + else +#endif ::swap (pix_colors[Color_fg], pix_colors[Color_bg]); -#ifdef HAVE_BG_PIXMAP - if (bg_pixmap == None) +#ifdef HAVE_IMG + if (bg_img == 0) #endif XSetWindowBackground (dpy, vt, pix_colors[Color_bg]); @@ -1720,8 +1747,8 @@ * Report current cursor position * XTERM_SEQ: Report position: ESC [ 6 n */ -void -rxvt_term::scr_report_position () NOTHROW +void ecb_cold +rxvt_term::scr_report_position () noexcept { tt_printf ("\033[%d;%dR", screen.cur.row + 1, screen.cur.col + 1); } @@ -1733,8 +1760,8 @@ /* * Set font style */ -void -rxvt_term::set_font_style () NOTHROW +void ecb_cold +rxvt_term::set_font_style () noexcept { #if 0 switch (charsets [screen.charset]) @@ -1765,8 +1792,8 @@ * XTERM_SEQ: Invoke G2 character set: ESC N * XTERM_SEQ: Invoke G3 character set: ESC O */ -void -rxvt_term::scr_charset_choose (int set) NOTHROW +void ecb_cold +rxvt_term::scr_charset_choose (int set) noexcept { screen.charset = set; set_font_style (); @@ -1782,7 +1809,7 @@ * See set_font_style for possible values for */ void -rxvt_term::scr_charset_set (int set, unsigned int ch) NOTHROW +rxvt_term::scr_charset_set (int set, unsigned int ch) noexcept { charsets[set] = (unsigned char)ch; set_font_style (); @@ -1796,8 +1823,8 @@ /* * refresh matching text. */ -bool -rxvt_term::scr_refresh_rend (rend_t mask, rend_t value) NOTHROW +bool ecb_cold +rxvt_term::scr_refresh_rend (rend_t mask, rend_t value) noexcept { bool found = false; @@ -1825,8 +1852,8 @@ RC_COUNT }; -void -rxvt_term::scr_expose (int x, int y, int ewidth, int eheight, bool refresh) NOTHROW +void ecb_hot +rxvt_term::scr_expose (int x, int y, int ewidth, int eheight, bool refresh) noexcept { int i; row_col_t rc[RC_COUNT]; @@ -1870,9 +1897,9 @@ * Refresh the entire screen */ void -rxvt_term::scr_touch (bool refresh) NOTHROW +rxvt_term::scr_touch (bool refresh) noexcept { - scr_expose (0, 0, width, height, refresh); + scr_expose (0, 0, vt_width, vt_height, refresh); } /* ------------------------------------------------------------------------- */ @@ -1881,9 +1908,10 @@ * the top of the screen */ void -rxvt_term::scr_move_to (int y, int len) NOTHROW +rxvt_term::scr_move_to (int y, int len) noexcept { - scr_changeview ((top_row - nrow) * (len - y) / len + (nrow - 1)); + // lerp (y, 0, len, top_row, nrow - 1) + scr_changeview (top_row + (nrow - 1 - top_row) * y / len); } /* ------------------------------------------------------------------------- */ @@ -1892,17 +1920,13 @@ * direction should be UP or DN */ bool -rxvt_term::scr_page (enum page_dirn direction, int nlines) NOTHROW +rxvt_term::scr_page (int nlines) noexcept { - int new_view_start = - direction == UP ? view_start - nlines - : view_start + nlines; - - return scr_changeview (new_view_start); + return scr_changeview (view_start - nlines); } bool -rxvt_term::scr_changeview (int new_view_start) NOTHROW +rxvt_term::scr_changeview (int new_view_start) noexcept { clamp_it (new_view_start, top_row, 0); @@ -1930,7 +1954,7 @@ /* ------------------------------------------------------------------------- */ void -rxvt_term::scr_bell () NOTHROW +rxvt_term::scr_bell () noexcept { #ifndef NO_BELL @@ -1961,8 +1985,8 @@ } /* ------------------------------------------------------------------------- */ -void -rxvt_term::scr_printscreen (int fullhist) NOTHROW +void ecb_cold +rxvt_term::scr_printscreen (int fullhist) noexcept { #ifdef PRINTPIPE int nrows, row_start; @@ -2020,18 +2044,17 @@ * drawn_text/drawn_rend contain the screen information before the update. * screen.text/screen.rend contain what the screen will change to. */ -void -rxvt_term::scr_refresh () NOTHROW +void ecb_hot +rxvt_term::scr_refresh () noexcept { int16_t col, row, /* column/row we're processing */ ocrow; /* old cursor row */ int i; /* tmp */ -#ifndef NO_CURSORCOLOR - rend_t cc1; /* store colours at cursor position (s) */ -#endif - rend_t *crp; // cursor rendition pointer rend_t ccol1, /* Cursor colour */ ccol2; /* Cursor colour2 */ + rend_t cur_rend; + int cur_col; + int cursorwidth; want_refresh = 0; /* screen is current */ @@ -2044,9 +2067,9 @@ refresh_count = 0; unsigned int old_screen_flags = screen.flags; - char have_bg = 0; -#ifdef HAVE_BG_PIXMAP - have_bg = bg_pixmap != None; + bool have_bg = 0; +#ifdef HAVE_IMG + have_bg = bg_img != 0; #endif ocrow = oldcursor.row; /* is there an old outline cursor on screen? */ @@ -2066,8 +2089,6 @@ * C: set the cursor character (s) */ { - bool setoldcursor; - #ifdef CURSOR_BLINK if (hidden_cursor) showcursor = 0; @@ -2080,10 +2101,15 @@ while (col && ROW(screen.cur.row).t[col] == NOCHAR) col--; - crp = &ROW(screen.cur.row).r[col]; + cursorwidth = 1; + while (col + cursorwidth < ncol + && ROW(screen.cur.row).t[col + cursorwidth] == NOCHAR) + cursorwidth++; + + cur_rend = ROW(screen.cur.row).r[col]; + cur_col = col; #ifndef NO_CURSORCOLOR - cc1 = *crp & (RS_fgMask | RS_bgMask); if (ISSET_PIXCOLOR (Color_cursor)) ccol1 = Color_cursor; else @@ -2105,49 +2131,33 @@ ccol2 = Color_bg; #endif - if (focus) + if (focus && cursor_type == 0) { - if (option (Opt_cursorUnderline)) - *crp ^= RS_Uline; - else - { - *crp ^= RS_RVid; - *crp = SET_FGCOLOR (*crp, ccol1); - *crp = SET_BGCOLOR (*crp, ccol2); - } - } - } + rend_t rend = cur_rend; - /* make sure no outline cursor is left around */ - setoldcursor = 0; - if (ocrow != -1) - { - if (screen.cur.row - view_start != ocrow - || screen.cur.col != oldcursor.col) - { - if (ocrow < nrow - && oldcursor.col < ncol) - drawn_buf[ocrow].r[oldcursor.col] ^= (RS_RVid | RS_Uline); + rend ^= RS_RVid; + rend = SET_FGCOLOR (rend, ccol1); + rend = SET_BGCOLOR (rend, ccol2); - if (focus || !showcursor) - oldcursor.row = -1; - else - setoldcursor = 1; + scr_set_char_rend (ROW(screen.cur.row), cur_col, rend); } } - else if (!focus) - setoldcursor = 1; - if (setoldcursor) + /* make sure no outline cursor is left around */ + if (ocrow != -1 && ocrow < nrow && oldcursor.col < ncol) + drawn_buf[ocrow].r[oldcursor.col] ^= (RS_RVid | RS_Uline); + + // save the current cursor coordinates if the cursor is visible + // and either the window is unfocused or the cursor style is + // underline or vertical bar, so as to clear the outline cursor in + // the next refresh if the cursor moves or becomes invisible + if (showcursor && (!focus || cursor_type != 0) && screen.cur.row - view_start < nrow) { - if (screen.cur.row - view_start >= nrow) - oldcursor.row = -1; - else - { - oldcursor.row = screen.cur.row - view_start; - oldcursor.col = screen.cur.col; - } + oldcursor.row = screen.cur.row - view_start; + oldcursor.col = screen.cur.col; } + else + oldcursor.row = -1; } #ifndef NO_SLOW_LINK_SUPPORT @@ -2163,7 +2173,6 @@ int i = num_scr; int j; int len, wlen; - dLocal (int, num_scr); j = nrow; wlen = len = -1; @@ -2239,10 +2248,7 @@ for (col = 0; col < ncol; col++) { /* compare new text with old - if exactly the same then continue */ - if (stp[col] == dtp[col] /* Must match characters to skip. */ - && (RS_SAME (srp[col], drp[col]) /* Either rendition the same or */ - || (stp[col] == ' ' /* space w/ no background change */ - && GET_BGATTR (srp[col]) == GET_BGATTR (drp[col])))) + if (stp[col] == dtp[col] && RS_SAME (srp[col], drp[col])) continue; // redraw one or more characters @@ -2424,6 +2430,10 @@ if (ecb_unlikely (rend & RS_Uline && font->descent > 1 && fore != back)) { + if (showcursor && focus && row == screen.cur.row + && IN_RANGE_EXC (col, cur_col, cur_col + cursorwidth)) + XSetForeground (dpy, gc, pix_colors[ccol1]); + else #if ENABLE_FRILLS if (ISSET_PIXCOLOR (Color_underline)) XSetForeground (dpy, gc, pix_colors[Color_underline]); @@ -2445,40 +2455,34 @@ { if (focus) { - if (option (Opt_cursorUnderline)) - *crp ^= RS_Uline; - else - { - *crp ^= RS_RVid; -#ifndef NO_CURSORCOLOR - *crp = (*crp & ~ (RS_fgMask | RS_bgMask)) | cc1; -#endif + if (cursor_type == 0) + scr_set_char_rend (ROW(screen.cur.row), cur_col, cur_rend); + else if (oldcursor.row >= 0) + { + XSetForeground (dpy, gc, pix_colors[ccol1]); + if (cursor_type == 1) + XFillRectangle (dpy, vt, gc, + Col2Pixel (cur_col), + Row2Pixel (oldcursor.row + 1) - 2, + Width2Pixel (1), + 2); + else + XFillRectangle (dpy, vt, gc, + Col2Pixel (cur_col), + Row2Pixel (oldcursor.row), + 2, + Height2Pixel (1)); } } else if (oldcursor.row >= 0) { - int cursorwidth = 1; - int col = oldcursor.col; - - while (col && ROW(screen.cur.row).t[col] == NOCHAR) - col--; - - while (col + cursorwidth < ncol - && drawn_buf[oldcursor.row].t[col + cursorwidth] == NOCHAR) - cursorwidth++; - -#ifndef NO_CURSORCOLOR - if (ISSET_PIXCOLOR (Color_cursor)) - XSetForeground (dpy, gc, pix_colors[Color_cursor]); - else -#endif - XSetForeground (dpy, gc, pix_colors[ccol1]); + XSetForeground (dpy, gc, pix_colors[ccol1]); XDrawRectangle (dpy, vt, gc, - Col2Pixel (col), + Col2Pixel (cur_col), Row2Pixel (oldcursor.row), (unsigned int) (Width2Pixel (cursorwidth) - 1), - (unsigned int) (Height2Pixel (1) - lineSpace - 1)); + (unsigned int) (Height2Pixel (1) - 1)); } } @@ -2497,10 +2501,10 @@ num_scr_allow = 1; } -void -rxvt_term::scr_remap_chars (line_t &l) NOTHROW +void ecb_cold +rxvt_term::scr_remap_chars (line_t &l) noexcept { - if (!l.t) + if (!l.valid ()) return; l.touch (); // maybe a bit of an overkill, but it's not performance-relevant @@ -2509,8 +2513,8 @@ l.r[i] = SET_FONT (l.r[i], FONTSET (l.r[i])->find_font (l.t[i])); } -void -rxvt_term::scr_remap_chars () NOTHROW +void ecb_cold +rxvt_term::scr_remap_chars () noexcept { for (int i = total_rows; i--; ) scr_remap_chars (row_buf [i]); @@ -2522,18 +2526,18 @@ } } -void -rxvt_term::scr_recolour (bool refresh) NOTHROW +void ecb_cold +rxvt_term::scr_recolor (bool refresh) noexcept { bool transparent = false; -#ifdef HAVE_BG_PIXMAP - if (bg_pixmap != None) +#ifdef HAVE_IMG + if (bg_img != 0) { -# ifdef ENABLE_TRANSPARENCY +# if ENABLE_TRANSPARENCY if (bg_flags & BG_IS_TRANSPARENT) { - XSetWindowBackgroundPixmap (dpy, parent, bg_pixmap); + XSetWindowBackgroundPixmap (dpy, parent, bg_img->pm); XSetWindowBackgroundPixmap (dpy, vt, ParentRelative); transparent = true; @@ -2542,7 +2546,7 @@ # endif { XSetWindowBackground (dpy, parent, pix_colors[Color_border]); - XSetWindowBackgroundPixmap (dpy, vt, bg_pixmap); + XSetWindowBackgroundPixmap (dpy, vt, bg_img->pm); } } else @@ -2554,12 +2558,12 @@ XClearWindow (dpy, parent); - if (scrollBar.win) + if (scrollBar.state && scrollBar.win) { if (transparent) XSetWindowBackgroundPixmap (dpy, scrollBar.win, ParentRelative); else - XSetWindowBackground (dpy, scrollBar.win, pix_colors[Color_border]); + XSetWindowBackground (dpy, scrollBar.win, pix_colors[scrollBar.color ()]); scrollBar.state = SB_STATE_IDLE; scrollBar.show (0); } @@ -2574,7 +2578,7 @@ /* ------------------------------------------------------------------------- */ void -rxvt_term::scr_clear (bool really) NOTHROW +rxvt_term::scr_clear (bool really) noexcept { if (!mapped) return; @@ -2587,7 +2591,7 @@ } void -rxvt_term::scr_xor_rect (int beg_row, int beg_col, int end_row, int end_col, rend_t rstyle1, rend_t rstyle2) NOTHROW +rxvt_term::scr_xor_rect (int beg_row, int beg_col, int end_row, int end_col, rend_t rstyle1, rend_t rstyle2) noexcept { int view_end = view_start + nrow; int row, col; @@ -2609,7 +2613,7 @@ } void -rxvt_term::scr_xor_span (int beg_row, int beg_col, int end_row, int end_col, rend_t rstyle) NOTHROW +rxvt_term::scr_xor_span (int beg_row, int beg_col, int end_row, int end_col, rend_t rstyle) noexcept { int view_end = view_start + nrow; int row, col; @@ -2635,8 +2639,8 @@ } /* ------------------------------------------------------------------------- */ -void -rxvt_term::scr_reverse_selection () NOTHROW +void ecb_hot +rxvt_term::scr_reverse_selection () noexcept { if (selection.op && current_screen == selection.screen @@ -2662,28 +2666,10 @@ */ #if 0 void -rxvt_term::scr_dump (int fd) NOTHROW +rxvt_term::scr_dump (int fd) noexcept { - int row, wrote; - unsigned int width, towrite; - const char r1[] = "\n"; - - for (row = saveLines + top_row; - row < saveLines + nrow - 1; row++) - { - width = row_buf[row].l >= 0 ? row_buf[row].l - : ncol; - for (towrite = width; towrite; towrite -= wrote) - { - wrote = write (fd, & (row_buf[row].t[width - towrite]), - towrite); - if (wrote < 0) - return; /* XXX: death, no report */ - } - if (row_buf[row].l >= 0) - if (write (fd, r1, 1) <= 0) - return; /* XXX: death, no report */ - } + // if this method is needed, it can be implemented by factoring the + // relevant code in scr_printscreen } #endif @@ -2691,52 +2677,62 @@ * CHARACTER SELECTION * * ------------------------------------------------------------------------- */ void -rxvt_term::selection_check (int check_more) NOTHROW +rxvt_term::selection_check (int check_more) noexcept { if (!selection.op) return; - row_col_t pos; - pos.row = pos.col = 0; - if (!IN_RANGE_EXC (selection.beg.row, top_row, nrow) || !IN_RANGE_EXC (selection.mark.row, top_row, nrow) || !IN_RANGE_EXC (selection.end.row, top_row, nrow) || (check_more == 1 && current_screen == selection.screen && !ROWCOL_IS_BEFORE (screen.cur, selection.beg) - && ROWCOL_IS_BEFORE (screen.cur, selection.end)) - || (check_more == 2 - && ROWCOL_IS_BEFORE (selection.beg, pos) - && ROWCOL_IS_AFTER (selection.end, pos)) - || (check_more == 3 - && ROWCOL_IS_AFTER (selection.end, pos))) + && ROWCOL_IS_BEFORE (screen.cur, selection.end))) CLEAR_ALL_SELECTION (); } +void +rxvt_term::selection_changed () noexcept +{ + line_t &r1 = ROW (selection.beg.row); + while (selection.beg.col < r1.l && r1.t [selection.beg.col] == NOCHAR) + ++selection.beg.col; + + line_t &r2 = ROW (selection.end.row); + while (selection.end.col < r2.l && r2.t [selection.end.col] == NOCHAR) + ++selection.end.col; + + want_refresh = 1; +} + /* ------------------------------------------------------------------------- */ /* * Paste a selection direct to the command fd */ void -rxvt_term::tt_paste (char *data, unsigned int len) NOTHROW +rxvt_term::tt_paste (char *data, unsigned int len) noexcept { /* convert normal newline chars into common keyboard Return key sequence */ for (unsigned int i = 0; i < len; i++) if (data[i] == C0_LF) data[i] = C0_CR; - if (priv_modes & PrivMode_BracketPaste) - tt_printf ("\e[200~"); + #if ENABLE_FRILLS + if ((priv_modes & PrivMode_BracketPaste) && !option (Opt_disablePasteBrackets)) + tt_printf ("\x1b[200~"); + #endif tt_write (data, len); - if (priv_modes & PrivMode_BracketPaste) - tt_printf ("\e[201~"); + #if ENABLE_FRILLS + if ((priv_modes & PrivMode_BracketPaste) && !option (Opt_disablePasteBrackets)) + tt_printf ("\x1b[201~"); + #endif } void -rxvt_term::paste (char *data, unsigned int len) NOTHROW +rxvt_term::paste (char *data, unsigned int len) noexcept { if (HOOK_INVOKE ((this, HOOK_TT_PASTE, DT_STR_LEN, data, len, DT_END))) return; @@ -2752,7 +2748,7 @@ * EXT: button 2 release */ void -rxvt_term::selection_request (Time tm, int selnum) NOTHROW +rxvt_term::selection_request (Time tm, int selnum) noexcept { if (!selection_req) { @@ -2767,7 +2763,7 @@ * EXT: SelectionClear */ void -rxvt_term::selection_clear (bool clipboard) NOTHROW +rxvt_term::selection_clear (bool clipboard) noexcept { if (!clipboard) { @@ -2862,7 +2858,7 @@ #if ENABLE_COMBINING else if (IS_COMPOSE (*t)) { - int len = rxvt_composite.expand (*t, 0); + int len = rxvt_composite.expand (*t); extra -= (len - 1); @@ -2919,7 +2915,7 @@ } bool -rxvt_term::selection_grab (Time tm, bool clipboard) NOTHROW +rxvt_term::selection_grab (Time tm, bool clipboard) noexcept { Atom sel; @@ -2962,8 +2958,8 @@ * Mark or select text based upon number of clicks: 1, 2, or 3 * EXT: button 1 press */ -void -rxvt_term::selection_click (int clicks, int x, int y) NOTHROW +void ecb_cold +rxvt_term::selection_click (int clicks, int x, int y) noexcept { clicks = ((clicks - 1) % 3) + 1; selection.clicks = clicks; /* save clicks so extend will work */ @@ -2991,8 +2987,8 @@ /* * Mark a selection at the specified col/row */ -void -rxvt_term::selection_start_colrow (int col, int row) NOTHROW +void ecb_cold +rxvt_term::selection_start_colrow (int col, int row) noexcept { want_refresh = 1; @@ -3024,12 +3020,12 @@ */ /* what do we want: spaces/tabs are delimiters or cutchars or non-cutchars */ -#define DELIMIT_TEXT(x) \ +#define DELIMIT_TEXT(x) \ (unicode::is_space (x) ? 2 : (x) <= 0xff && !!strchr (rs[Rs_cutchars], (x))) #define DELIMIT_REND(x) 1 -void -rxvt_term::selection_delimit_word (enum page_dirn dirn, const row_col_t *mark, row_col_t *ret) NOTHROW +void ecb_cold +rxvt_term::selection_delimit_word (enum page_dirn dirn, const row_col_t *mark, row_col_t *ret) noexcept { int col, row, dirnadd, tcol, trow, w1, w2; row_col_t bound; @@ -3112,8 +3108,8 @@ * flag == 1 ==> button 3 press * flag == 2 ==> button 3 motion */ -void -rxvt_term::selection_extend (int x, int y, int flag) NOTHROW +void ecb_cold +rxvt_term::selection_extend (int x, int y, int flag) noexcept { int col = clamp (Pixel2Col (x), 0, ncol); int row = clamp (Pixel2Row (y), 0, nrow - 1); @@ -3148,16 +3144,14 @@ /* * Extend the selection to the specified col/row */ -void -rxvt_term::selection_extend_colrow (int32_t col, int32_t row, int button3, int buttonpress, int clickchange) NOTHROW +void ecb_cold +rxvt_term::selection_extend_colrow (int32_t col, int32_t row, int button3, int buttonpress, int clickchange) noexcept { row_col_t pos; enum { LEFT, RIGHT } closeto = RIGHT; - want_refresh = 1; - switch (selection.op) { case SELECTION_INIT: @@ -3346,11 +3340,13 @@ if (selection.rect && selection.beg.col > selection.end.col) ::swap (selection.beg.col, selection.end.col); #endif + + selection_changed (); } #if !ENABLE_MINIMAL -void -rxvt_term::selection_remove_trailing_spaces () NOTHROW +void ecb_cold +rxvt_term::selection_remove_trailing_spaces () noexcept { int32_t end_col, end_row; text_t *stp; @@ -3397,8 +3393,8 @@ * Double click on button 3 when already selected * EXT: button 3 double click */ -void -rxvt_term::selection_rotate (int x, int y) NOTHROW +void ecb_cold +rxvt_term::selection_rotate (int x, int y) noexcept { selection.clicks = selection.clicks % 3 + 1; selection_extend_colrow (Pixel2Col (x), Pixel2Row (y), 1, 0, 1); @@ -3409,8 +3405,8 @@ * Respond to a request for our current selection * EXT: SelectionRequest */ -void -rxvt_term::selection_send (const XSelectionRequestEvent &rq) NOTHROW +void ecb_cold +rxvt_term::selection_send (const XSelectionRequestEvent &rq) noexcept { Atom property = rq.property == None ? rq.target : rq.property; XSelectionEvent ev; @@ -3512,7 +3508,7 @@ } else { - cl = L""; + cl = (wchar_t *)L""; selectlen = 0; } @@ -3552,9 +3548,9 @@ } /* ------------------------------------------------------------------------- */ -#ifdef USE_XIM -void -rxvt_term::im_set_position (XPoint &pos) NOTHROW +#if USE_XIM +void ecb_cold +rxvt_term::im_set_position (XPoint &pos) noexcept { XWindowAttributes xwa; @@ -3567,7 +3563,7 @@ #if ENABLE_OVERLAY void -rxvt_term::scr_overlay_new (int x, int y, int w, int h) NOTHROW +rxvt_term::scr_overlay_new (int x, int y, int w, int h) noexcept { if (nrow < 1 || ncol < 1) return; @@ -3622,7 +3618,7 @@ } void -rxvt_term::scr_overlay_off () NOTHROW +rxvt_term::scr_overlay_off () noexcept { if (!ov.text) return; @@ -3640,7 +3636,7 @@ } void -rxvt_term::scr_overlay_set (int x, int y, text_t text, rend_t rend) NOTHROW +rxvt_term::scr_overlay_set (int x, int y, text_t text, rend_t rend) noexcept { if (!ov.text || x >= ov.w - 2 || y >= ov.h - 2) return; @@ -3652,14 +3648,14 @@ } void -rxvt_term::scr_overlay_set (int x, int y, const char *s) NOTHROW +rxvt_term::scr_overlay_set (int x, int y, const char *s) noexcept { while (*s) scr_overlay_set (x++, y, *s++); } void -rxvt_term::scr_overlay_set (int x, int y, const wchar_t *s) NOTHROW +rxvt_term::scr_overlay_set (int x, int y, const wchar_t *s) noexcept { while (*s) { @@ -3675,7 +3671,7 @@ } void -rxvt_term::scr_swap_overlay () NOTHROW +rxvt_term::scr_swap_overlay () noexcept { if (!ov.text) return;