--- rxvt-unicode/src/screen.C 2012/05/28 14:25:16 1.415 +++ rxvt-unicode/src/screen.C 2013/03/30 08:47:06 1.442 @@ -30,8 +30,6 @@ #include -#include "salloc.C" // HACK, should be a separate compile! - static inline void fill_text (text_t *start, text_t value, int len) { @@ -154,18 +152,28 @@ } 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 () +rxvt_term::scr_alloc () NOTHROW { int tsize = sizeof (text_t) * ncol; int rsize = sizeof (rend_t) * ncol; // we assume that rend_t size is a sufficient alignment - // factor for tetx_t and line_t values, and we only + // 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); @@ -173,7 +181,7 @@ int all_rows = total_rows + nrow + nrow; chunk_size = (sizeof (line_t) + rsize + tsize) * all_rows; - chunk = rxvt_malloc (chunk_size); + chunk = chunk_alloc (chunk_size, 0); char *base = (char *)chunk + sizeof (line_t) * all_rows; @@ -193,6 +201,16 @@ } 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 @@ -229,19 +247,15 @@ screen.bscroll = nrow - 1; 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; - int common_col = min (prev_ncol, ncol); - scr_alloc (); if (!prev_row_buf) { - /* - * first time called so just malloc everything: don't rely on realloc - */ top_row = 0; term_start = 0; @@ -276,15 +290,15 @@ * add or delete rows as appropriate */ + int common_col = min (prev_ncol, ncol); + for (int row = min (nrow, prev_nrow); row--; ) { scr_blank_screen_mem (drawn_buf [row], DEFAULT_RSTYLE); - scr_blank_screen_mem (swap_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); - memcpy (swap_buf [row].t, prev_swap_buf [row].t, sizeof (text_t) * common_col); - memcpy (swap_buf [row].r, prev_swap_buf [row].r, sizeof (rend_t) * common_col); + + copy_line (swap_buf [row], prev_swap_buf [row]); } int p = MOD (term_start + prev_nrow, prev_total_rows); // previous row @@ -389,10 +403,7 @@ line_t &src = prev_row_buf [MOD (term_start + row, prev_total_rows)]; line_t &dst = row_buf [row]; - scr_blank_screen_mem (dst, DEFAULT_RSTYLE); - - memcpy (dst.t, src.t, sizeof (text_t) * common_col); - memcpy (dst.r, src.r, sizeof (rend_t) * common_col); + copy_line (dst, src); } for (int row = prev_nrow; row < nrow; row++) @@ -412,7 +423,7 @@ if (!drawn_buf [row].valid ()) scr_blank_screen_mem (drawn_buf [row], DEFAULT_RSTYLE); } - free (prev_chunk); + chunk_free (prev_chunk, prev_chunk_size); free (tabs); tabs = (char *)rxvt_malloc (ncol); @@ -430,28 +441,26 @@ HOOK_INVOKE ((this, HOOK_RESET, DT_END)); } -/* ------------------------------------------------------------------------- */ -/* - * Free everything. That way malloc debugging can find leakage. - */ -void +void ecb_cold rxvt_term::scr_release () NOTHROW { - free (chunk); + chunk_free (chunk, chunk_size); + chunk = 0; + row_buf = 0; + free (tabs); + tabs = 0; } /* ------------------------------------------------------------------------- */ /* * Hard/Soft reset */ -void +void ecb_cold rxvt_term::scr_poweron () { scr_release (); - row_buf = 0; - tabs = 0; prev_nrow = prev_ncol = 0; rvideo_mode = false; scr_soft_reset (); @@ -461,7 +470,7 @@ scr_refresh (); } -void +void ecb_cold rxvt_term::scr_soft_reset () NOTHROW { /* only affects modes, nothing drastic such as clearing the screen */ @@ -637,7 +646,7 @@ * count positive ==> scroll up * count negative ==> scroll down */ -int +int ecb_hot rxvt_term::scr_scroll_text (int row1, int row2, int count) NOTHROW { if (count == 0 || (row1 > row2)) @@ -708,7 +717,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)); @@ -781,7 +790,7 @@ /* * Add text given in of length to screen struct */ -void +void ecb_hot rxvt_term::scr_add_lines (const wchar_t *str, int len, int minlines) NOTHROW { if (len <= 0) /* sanity */ @@ -1141,7 +1150,7 @@ * in that row right. Clear left column. */ #if !ENABLE_MINIMAL -void +void ecb_cold rxvt_term::scr_backindex () NOTHROW { if (screen.cur.col > 0) @@ -1158,7 +1167,7 @@ * in that row left. Clear right column. */ #if !ENABLE_MINIMAL -void +void ecb_cold rxvt_term::scr_forwardindex () NOTHROW { if (screen.cur.col < ncol - 1) @@ -1233,20 +1242,16 @@ void rxvt_term::scr_index (enum page_dirn direction) NOTHROW { - 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); @@ -1419,7 +1424,7 @@ * Fill the screen with `E's * XTERM_SEQ: Screen Alignment Test: ESC # 8 */ -void +void ecb_cold rxvt_term::scr_E () NOTHROW { rend_t fs; @@ -1593,7 +1598,7 @@ * Set the scrolling region * XTERM_SEQ: Set region - inclusive: ESC [ ; r */ -void +void ecb_cold rxvt_term::scr_scroll_region (int top, int bot) NOTHROW { max_it (top, 0); @@ -1613,7 +1618,7 @@ * XTERM_SEQ: Make cursor visible : ESC [ ? 25 h * XTERM_SEQ: Make cursor invisible: ESC [ ? 25 l */ -void +void ecb_cold rxvt_term::scr_cursor_visible (int mode) NOTHROW { want_refresh = 1; @@ -1630,7 +1635,7 @@ * XTERM_SEQ: Set Wraparound : ESC [ ? 7 h * XTERM_SEQ: Unset Wraparound: ESC [ ? 7 l */ -void +void ecb_cold rxvt_term::scr_autowrap (int mode) NOTHROW { if (mode) @@ -1649,7 +1654,7 @@ * XTERM_SEQ: Set Absolute: ESC [ ? 6 h * XTERM_SEQ: Set Relative: ESC [ ? 6 l */ -void +void ecb_cold rxvt_term::scr_relative_origin (int mode) NOTHROW { if (mode) @@ -1666,7 +1671,7 @@ * XTERM_SEQ: Set Insert mode : ESC [ ? 4 h * XTERM_SEQ: Set Replace mode: ESC [ ? 4 l */ -void +void ecb_cold rxvt_term::scr_insert_mode (int mode) NOTHROW { if (mode) @@ -1682,7 +1687,7 @@ * XTERM_SEQ: Clear tab at current column: ESC [ 0 g * XTERM_SEQ: Clear all tabs : ESC [ 3 g */ -void +void ecb_cold rxvt_term::scr_set_tab (int mode) NOTHROW { if (mode < 0) @@ -1711,8 +1716,8 @@ rvideo_state = on; ::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]); @@ -1731,7 +1736,7 @@ * Report current cursor position * XTERM_SEQ: Report position: ESC [ 6 n */ -void +void ecb_cold rxvt_term::scr_report_position () NOTHROW { tt_printf ("\033[%d;%dR", screen.cur.row + 1, screen.cur.col + 1); @@ -1744,7 +1749,7 @@ /* * Set font style */ -void +void ecb_cold rxvt_term::set_font_style () NOTHROW { #if 0 @@ -1776,7 +1781,7 @@ * XTERM_SEQ: Invoke G2 character set: ESC N * XTERM_SEQ: Invoke G3 character set: ESC O */ -void +void ecb_cold rxvt_term::scr_charset_choose (int set) NOTHROW { screen.charset = set; @@ -1807,7 +1812,7 @@ /* * refresh matching text. */ -bool +bool ecb_cold rxvt_term::scr_refresh_rend (rend_t mask, rend_t value) NOTHROW { bool found = false; @@ -1836,7 +1841,7 @@ RC_COUNT }; -void +void ecb_hot rxvt_term::scr_expose (int x, int y, int ewidth, int eheight, bool refresh) NOTHROW { int i; @@ -1903,13 +1908,9 @@ * direction should be UP or DN */ bool -rxvt_term::scr_page (enum page_dirn direction, int nlines) NOTHROW +rxvt_term::scr_page (int nlines) NOTHROW { - 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 @@ -1972,7 +1973,7 @@ } /* ------------------------------------------------------------------------- */ -void +void ecb_cold rxvt_term::scr_printscreen (int fullhist) NOTHROW { #ifdef PRINTPIPE @@ -2031,18 +2032,17 @@ * drawn_text/drawn_rend contain the screen information before the update. * screen.text/screen.rend contain what the screen will change to. */ -void +void ecb_hot rxvt_term::scr_refresh () NOTHROW { 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 */ @@ -2056,8 +2056,8 @@ unsigned int old_screen_flags = screen.flags; bool have_bg = 0; -#ifdef HAVE_BG_PIXMAP - have_bg = bg_pixmap != None; +#ifdef HAVE_IMG + have_bg = bg_img != 0; #endif ocrow = oldcursor.row; /* is there an old outline cursor on screen? */ @@ -2077,8 +2077,6 @@ * C: set the cursor character (s) */ { - bool setoldcursor; - #ifdef CURSOR_BLINK if (hidden_cursor) showcursor = 0; @@ -2091,10 +2089,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 @@ -2118,19 +2121,22 @@ if (focus) { + rend_t rend = cur_rend; + if (option (Opt_cursorUnderline)) - *crp ^= RS_Uline; + rend ^= RS_Uline; else { - *crp ^= RS_RVid; - *crp = SET_FGCOLOR (*crp, ccol1); - *crp = SET_BGCOLOR (*crp, ccol2); + rend ^= RS_RVid; + rend = SET_FGCOLOR (rend, ccol1); + rend = SET_BGCOLOR (rend, ccol2); } + + scr_set_char_rend (ROW(screen.cur.row), cur_col, rend); } } /* make sure no outline cursor is left around */ - setoldcursor = 0; if (ocrow != -1) { if (screen.cur.row - view_start != ocrow @@ -2139,26 +2145,19 @@ if (ocrow < nrow && oldcursor.col < ncol) drawn_buf[ocrow].r[oldcursor.col] ^= (RS_RVid | RS_Uline); - - if (focus || !showcursor) - oldcursor.row = -1; - else - setoldcursor = 1; } } - else if (!focus) - setoldcursor = 1; - if (setoldcursor) + // save the current cursor coordinates if the cursor is visible + // and the window is unfocused, so as to clear the outline cursor + // in the next refresh if the cursor moves + if (showcursor && !focus && 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 @@ -2434,6 +2433,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]); @@ -2454,38 +2457,13 @@ if (showcursor) { if (focus) - { - if (option (Opt_cursorUnderline)) - *crp ^= RS_Uline; - else - { - *crp ^= RS_RVid; -#ifndef NO_CURSORCOLOR - *crp = (*crp & ~ (RS_fgMask | RS_bgMask)) | cc1; -#endif - } - } + scr_set_char_rend (ROW(screen.cur.row), cur_col, cur_rend); 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) - 1)); @@ -2507,7 +2485,7 @@ num_scr_allow = 1; } -void +void ecb_cold rxvt_term::scr_remap_chars (line_t &l) NOTHROW { if (!l.valid ()) @@ -2519,7 +2497,7 @@ l.r[i] = SET_FONT (l.r[i], FONTSET (l.r[i])->find_font (l.t[i])); } -void +void ecb_cold rxvt_term::scr_remap_chars () NOTHROW { for (int i = total_rows; i--; ) @@ -2532,18 +2510,18 @@ } } -void +void ecb_cold rxvt_term::scr_recolour (bool refresh) NOTHROW { 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; @@ -2552,7 +2530,7 @@ # endif { XSetWindowBackground (dpy, parent, pix_colors[Color_border]); - XSetWindowBackgroundPixmap (dpy, vt, bg_pixmap); + XSetWindowBackgroundPixmap (dpy, vt, bg_img->pm); } } else @@ -2569,7 +2547,7 @@ 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); } @@ -2645,7 +2623,7 @@ } /* ------------------------------------------------------------------------- */ -void +void ecb_hot rxvt_term::scr_reverse_selection () NOTHROW { if (selection.op @@ -2698,6 +2676,20 @@ CLEAR_ALL_SELECTION (); } +void +rxvt_term::selection_changed () NOTHROW +{ + line_t &r1 = ROW (selection.beg.row); + while (selection.beg.col > 0 && 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 @@ -2946,7 +2938,7 @@ * Mark or select text based upon number of clicks: 1, 2, or 3 * EXT: button 1 press */ -void +void ecb_cold rxvt_term::selection_click (int clicks, int x, int y) NOTHROW { clicks = ((clicks - 1) % 3) + 1; @@ -2975,7 +2967,7 @@ /* * Mark a selection at the specified col/row */ -void +void ecb_cold rxvt_term::selection_start_colrow (int col, int row) NOTHROW { want_refresh = 1; @@ -3008,11 +3000,11 @@ */ /* 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 +void ecb_cold rxvt_term::selection_delimit_word (enum page_dirn dirn, const row_col_t *mark, row_col_t *ret) NOTHROW { int col, row, dirnadd, tcol, trow, w1, w2; @@ -3082,6 +3074,14 @@ if (dirn == DN) col++; /* put us on one past the end */ + else + { + // if the delimiter on the left has width > 1 col points to the + // first NOCHAR in the delimiter cell and so we must move it to the + // beginning of the next cell. + while (ROW(row).t[col] == NOCHAR) + col++; + } /* Poke the values back in */ ret->row = row; @@ -3096,7 +3096,7 @@ * flag == 1 ==> button 3 press * flag == 2 ==> button 3 motion */ -void +void ecb_cold rxvt_term::selection_extend (int x, int y, int flag) NOTHROW { int col = clamp (Pixel2Col (x), 0, ncol); @@ -3132,7 +3132,7 @@ /* * Extend the selection to the specified col/row */ -void +void ecb_cold rxvt_term::selection_extend_colrow (int32_t col, int32_t row, int button3, int buttonpress, int clickchange) NOTHROW { row_col_t pos; @@ -3140,8 +3140,6 @@ LEFT, RIGHT } closeto = RIGHT; - want_refresh = 1; - switch (selection.op) { case SELECTION_INIT: @@ -3330,10 +3328,12 @@ if (selection.rect && selection.beg.col > selection.end.col) ::swap (selection.beg.col, selection.end.col); #endif + + selection_changed (); } #if !ENABLE_MINIMAL -void +void ecb_cold rxvt_term::selection_remove_trailing_spaces () NOTHROW { int32_t end_col, end_row; @@ -3381,7 +3381,7 @@ * Double click on button 3 when already selected * EXT: button 3 double click */ -void +void ecb_cold rxvt_term::selection_rotate (int x, int y) NOTHROW { selection.clicks = selection.clicks % 3 + 1; @@ -3393,7 +3393,7 @@ * Respond to a request for our current selection * EXT: SelectionRequest */ -void +void ecb_cold rxvt_term::selection_send (const XSelectionRequestEvent &rq) NOTHROW { Atom property = rq.property == None ? rq.target : rq.property; @@ -3536,8 +3536,8 @@ } /* ------------------------------------------------------------------------- */ -#ifdef USE_XIM -void +#if USE_XIM +void ecb_cold rxvt_term::im_set_position (XPoint &pos) NOTHROW { XWindowAttributes xwa;