--- rxvt-unicode/src/screen.C 2008/11/04 13:30:41 1.312 +++ rxvt-unicode/src/screen.C 2008/11/05 00:01:01 1.324 @@ -134,6 +134,25 @@ l.f = 0; } +// nuke a single wide character at the given column +void +rxvt_term::scr_kill_char (line_t &l, int col) const NOTHROW +{ + // 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 (' ')); + + // found start, nuke + do { + l.t[col] = ' '; + l.r[col] = rend; + col++; + } while (col < ncol && l.t[col] == NOCHAR); +} + /* ------------------------------------------------------------------------- * * SCREEN INITIALISATION * * ------------------------------------------------------------------------- */ @@ -141,11 +160,8 @@ void rxvt_term::scr_reset () { -#if ENABLE_OVERLAY - scr_overlay_off (); -#endif + scr_soft_reset (); - rvideo_mode = false; view_start = 0; num_scr = 0; @@ -158,9 +174,6 @@ if (ncol == prev_ncol && nrow == prev_nrow) return; - if (current_screen != PRIMARY) - scr_swap_screen (); - // we need at least two lines for wrapping to work correctly while (nrow + saveLines < 2) { @@ -382,8 +395,6 @@ clamp_it (screen.cur.row, 0, nrow - 1); clamp_it (screen.cur.col, 0, ncol - 1); - - free (tabs); } CLEAR_ALL_SELECTION (); @@ -391,14 +402,6 @@ prev_nrow = nrow; prev_ncol = ncol; - tabs = (char *)rxvt_malloc (ncol); - - for (int col = ncol; --col; ) - tabs [col] = col % TABSIZE == 0; - - if (current_screen != PRIMARY) - scr_swap_screen (); - tt_winch (); HOOK_INVOKE ((this, HOOK_RESET, DT_END)); @@ -419,15 +422,16 @@ free (row_buf); free (swap_buf); free (drawn_buf); - free (tabs); + row_buf = 0; // signal that we freed all the arrays above - row_buf = 0; // signal that we freed all the arrays + free (tabs); + tabs = 0; } } /* ------------------------------------------------------------------------- */ /* - * Hard reset + * Hard/Soft reset */ void rxvt_term::scr_poweron () @@ -440,6 +444,30 @@ scr_refresh (); } +void +rxvt_term::scr_soft_reset () +{ + /* only affects modes, nothing drastic such as clearing the screen */ +#if ENABLE_OVERLAY + scr_overlay_off (); +#endif + + rvideo_mode = false; + + if (current_screen != PRIMARY) + scr_swap_screen (); + + free (tabs); + tabs = (char *)rxvt_malloc (ncol); + + for (int col = ncol; --col; ) + tabs [col] = col % TABSIZE == 0; + + scr_scroll_region (0, MAX_ROWS - 1); + scr_rendition (0, ~RS_None); + scr_insert_mode (0); +} + /* ------------------------------------------------------------------------- * * PROCESS SCREEN COMMANDS * * ------------------------------------------------------------------------- */ @@ -882,30 +910,15 @@ || (screen.cur.col < ncol - 1 && line->t[screen.cur.col + 1] == NOCHAR) )) - { - int col = screen.cur.col; - - // find begin - while (col > 0 && line->t[col] == NOCHAR) - col--; - - rend_t rend = SET_FONT (line->r[col], FONTSET (line->r[col])->find_font (' ')); - - // found begin, nuke - do { - line->t[col] = ' '; - line->r[col] = rend; - col++; - } while (col < ncol && line->t[col] == NOCHAR); - } + scr_kill_char (*line, screen.cur.col); rend_t rend = SET_FONT (rstyle, FONTSET (rstyle)->find_font (c)); // if the character doesn't fit into the remaining columns... if (expect_false (screen.cur.col > ncol - width && ncol >= width)) { - // ...output spaces - c = ' '; + // ... artificially enlargen the previous one + c = NOCHAR; // and try the same character next loop iteration --str; } @@ -1331,36 +1344,43 @@ min_it (num, nrow - row); - /*TODO: the xlceararea/xfillrectangle below don't take scroll offste into account, ask mikachu for details */ + // TODO: the code below does not work when view_start != 0 + // the workaround is to disable the clear and use a normal refresh + // when view_start != 0. mysterious. if (rstyle & (RS_RVid | RS_Uline)) ren = (rend_t) ~RS_None; else if (GET_BASEBG (rstyle) == Color_bg) { ren = DEFAULT_RSTYLE; - if (mapped) + if (mapped && !view_start) XClearArea (dpy, vt, 0, - Row2Pixel (row), (unsigned int)width, + Row2Pixel (row - view_start), (unsigned int)width, (unsigned int)Height2Pixel (num), False); } else { ren = rstyle & (RS_fgMask | RS_bgMask); - gcvalue.foreground = pix_colors[bgcolor_of (rstyle)]; - XChangeGC (dpy, gc, GCForeground, &gcvalue); - XFillRectangle (dpy, vt, gc, - 0, Row2Pixel (row), - (unsigned int)width, - (unsigned int)Height2Pixel (num)); - gcvalue.foreground = pix_colors[Color_fg]; - XChangeGC (dpy, gc, GCForeground, &gcvalue); + if (mapped && !view_start) + { + gcvalue.foreground = pix_colors[bgcolor_of (rstyle)]; + XChangeGC (dpy, gc, GCForeground, &gcvalue); + XFillRectangle (dpy, vt, gc, + 0, Row2Pixel (row - view_start), + (unsigned int)width, + (unsigned int)Height2Pixel (num)); + gcvalue.foreground = pix_colors[Color_fg]; + XChangeGC (dpy, gc, GCForeground, &gcvalue); + } } for (; num--; row++) { scr_blank_screen_mem (ROW(row), rstyle); - scr_blank_line (drawn_buf [row], 0, ncol, ren); + + if (!view_start) + scr_blank_line (drawn_buf [row], 0, ncol, ren); } } @@ -1444,9 +1464,6 @@ void rxvt_term::scr_insdel_chars (int count, int insdel) NOTHROW { - int col, row; - rend_t tr; - want_refresh = 1; ZERO_SCROLLBACK (); @@ -1458,24 +1475,31 @@ selection_check (1); min_it (count, ncol - screen.cur.col); - row = screen.cur.row; + int row = screen.cur.row; line_t *line = &ROW(row); line->touch (); line->is_longer (0); + // nuke wide spanning the start + if (line->t[screen.cur.col] == NOCHAR) + scr_kill_char (*line, screen.cur.col); + switch (insdel) { case INSERT: - for (col = ncol - 1; (col - count) >= screen.cur.col; col--) + line->l = min (line->l + count, ncol); + + if (line->t[screen.cur.col] == NOCHAR) + scr_kill_char (*line, screen.cur.col); + + for (int col = ncol - 1; (col - count) >= screen.cur.col; col--) { line->t[col] = line->t[col - count]; line->r[col] = line->r[col - count]; } - line->l = min (line->l + count, ncol); - if (selection.op && current_screen == selection.screen && ROWCOL_IN_ROW_AT_OR_AFTER (selection.beg, screen.cur)) { @@ -1499,20 +1523,28 @@ selection_check (1); screen.cur.col -= count; + // nuke wide char after the end + if (screen.cur.col + count < ncol && line->t[screen.cur.col + count] == NOCHAR) + scr_kill_char (*line, screen.cur.col + count); + scr_blank_line (*line, screen.cur.col, count, rstyle); break; case DELETE: - tr = line->r[ncol - 1] & (RS_fgMask | RS_bgMask | RS_baseattrMask); + line->l = max (line->l - count, 0); + + // nuke wide char spanning the end + if (screen.cur.col + count < ncol && line->t[screen.cur.col + count] == NOCHAR) + scr_kill_char (*line, screen.cur.col + count); - for (col = screen.cur.col; (col + count) < ncol; col++) + for (int col = screen.cur.col; (col + count) < ncol; col++) { line->t[col] = line->t[col + count]; line->r[col] = line->r[col + count]; } - line->l = max (line->l - count, 0); - scr_blank_line (*line, ncol - count, count, tr); + scr_blank_line (*line, ncol - count, count, + line->r[ncol - 1] & (RS_fgMask | RS_bgMask | RS_baseattrMask)); if (selection.op && current_screen == selection.screen && ROWCOL_IN_ROW_AT_OR_AFTER (selection.beg, screen.cur))