--- rxvt-unicode/src/screen.C 2003/12/18 13:33:03 1.11 +++ rxvt-unicode/src/screen.C 2004/01/29 23:26:01 1.19 @@ -1,7 +1,6 @@ /*--------------------------------*-C-*--------------------------------------* * File: screen.c *---------------------------------------------------------------------------* - * $Id: screen.C,v 1.11 2003/12/18 13:33:03 pcg Exp $ * * Copyright (c) 1997-2001 Geoff Wing * @@ -291,7 +290,7 @@ /* add rows */ scr_reset_realloc (); /* realloc _first_ */ - TermWin.ncol = prev_ncol; // save b/c scr_blank_screen_mem uses this + TermWin.ncol = prev_ncol; // save b/c scr_blank_screen_mem uses this k = min (TermWin.nscrolled, nrow - prev_nrow); @@ -449,8 +448,8 @@ } #endif - delete talloc; - delete ralloc; + delete talloc; talloc = 0; + delete ralloc; ralloc = 0; free (screen.text); free (screen.tlen); @@ -901,39 +900,35 @@ } rend_t rend = SET_FONT (R->rstyle, R->TermWin.fontset->find_font (c)); + // rely on wcwidth to tell us the character width, at least for non-ascii + int width = c <= 128 ? 1 : wcwidth (c); - stp[R->screen.cur.col] = c; - srp[R->screen.cur.col] = rend; - - if (c > 255) - { - // rely on wcwidth to tell us the character width, at least for non iso-8859-1 - int width = wcwidth (c); - - if (width > 1) - { - while (--width > 0 && R->screen.cur.col < last_col - 1) - { - - srp[R->screen.cur.col] |= RS_wide; + // width -1 characters (e.g. combining chars) are ignored currently. + if (width > 0) + do + { + stp[R->screen.cur.col] = c; + srp[R->screen.cur.col] = rend; - R->screen.cur.col++; - stp[R->screen.cur.col] = NOCHAR; - srp[R->screen.cur.col] = rend; - } - } - } + if (R->screen.cur.col < last_col - 1) + R->screen.cur.col++; + else + { + R->screen.tlen[row] = last_col; + if (R->screen.flags & Screen_Autowrap) + R->screen.flags |= Screen_WrapNext; + break; + } - if (R->screen.cur.col < last_col - 1) - R->screen.cur.col++; - else { - R->screen.tlen[row] = last_col; - if (R->screen.flags & Screen_Autowrap) - R->screen.flags |= Screen_WrapNext; - } + c = NOCHAR; + } + while (--width > 0); + else + 1; /* handle combining character etc. here. */ } + if (R->screen.tlen[row] != -1) /* XXX: think about this */ - MAX_IT(R->screen.tlen[row], R->screen.cur.col); + MAX_IT(R->screen.tlen[row], R->screen.cur.col); /* * If we wrote anywhere in the selected area, kill the selection @@ -1652,29 +1647,32 @@ /* ------------------------------------------------------------------------- * - * GRAPHICS COLOURS * + * MAJOR SCREEN MANIPULATION * * ------------------------------------------------------------------------- */ -#ifdef RXVT_GRAPHICS -/* EXTPROTO */ -int -rxvt_scr_get_fgcolor(pR) +/* + * refresh matching text. + */ +bool +rxvt_term::scr_refresh_rend (rend_t mask, rend_t value) { - return GET_FGCOLOR(R->rstyle); -} + bool found = false; -/* ------------------------------------------------------------------------- */ -/* EXTPROTO */ -int -rxvt_scr_get_bgcolor(pR) -{ - return GET_BGCOLOR(R->rstyle); + for (int i = 0; i < TermWin.nrow; i++) + { + int col = 0; + rend_t *drp = drawn_rend [i]; + + for (; col < TermWin.ncol; col++, drp++) + if ((*drp & mask) == value) + { + found = true; + *drp = ~value; + } + } + + return found; } -#endif - -/* ------------------------------------------------------------------------- * - * MAJOR SCREEN MANIPULATION * - * ------------------------------------------------------------------------- */ /* * Refresh an area @@ -1861,15 +1859,6 @@ * R->screen.text/R->screen.rend contain what the screen will change to. */ -#if defined (NO_BRIGHTCOLOR) || defined (VERYBOLD) -# define MONO_BOLD(x) ((x) & (RS_Bold|RS_Blink)) -# define MONO_BOLD_FG(x, fg) MONO_BOLD(x) -#else -# define MONO_BOLD(x) \ - (((x) & (RS_Bold | RS_fgMask)) == (RS_Bold | Color_fg)) -# define MONO_BOLD_FG(x, fg) (((x) & RS_Bold) && (fg) == Color_fg) -#endif - #define FONT_WIDTH(X, Y) \ (X)->per_char[(Y) - (X)->min_char_or_byte2].width #define FONT_RBEAR(X, Y) \ @@ -1885,13 +1874,8 @@ unsigned char clearfirst, /* first character writes before cell */ clearlast, /* last character writes beyond cell */ must_clear, /* use draw_string not draw_image_string */ -#ifndef NO_BOLDFONT - bfont, /* we've changed font to bold font */ -#endif rvid, /* reverse video this position */ - wbyte, /* we're in multibyte */ showcursor; /* show the cursor */ - int fore, back; /* desired foreground/background */ int16_t col, row, /* column/row we're processing */ ocrow; /* old cursor row */ int cursorwidth; @@ -1903,7 +1887,6 @@ #endif rend_t *drp, *srp; /* drawn-rend-pointer, screen-rend-pointer */ text_t *dtp, *stp; /* drawn-text-pointer, screen-text-pointer */ - char *buffer; /* local copy of buffer */ if (refresh_type == NO_REFRESH || !TermWin.mapped) return; @@ -1911,10 +1894,7 @@ /* * A: set up vars */ - clearfirst = clearlast = must_clear = wbyte = 0; -#ifndef NO_BOLDFONT - bfont = 0; -#endif + clearfirst = clearlast = must_clear = 0; if (currmaxcol < TermWin.ncol) { @@ -1923,7 +1903,6 @@ sizeof(char) * (currmaxcol + 1) * MB_CUR_MAX); } - buffer = buffer; refresh_count = 0; row_offset = TermWin.saveLines - TermWin.view_start; @@ -1942,14 +1921,14 @@ #endif ocrow = oldcursor.row; /* is there an old outline cursor on screen? */ -/* - * B: reverse any characters which are selected - */ + /* + * B: reverse any characters which are selected + */ rxvt_scr_reverse_selection (this); -/* - * C: set the cursor character(s) - */ + /* + * C: set the cursor character(s) + */ { unsigned char setoldcursor; rend_t ccol1, /* Cursor colour */ @@ -1996,9 +1975,6 @@ *srp = SET_BGCOLOR(*srp, ccol2); #endif } - - while (IS_WIDE (*srp)) - cursorwidth++, srp++; } /* make sure no outline cursor is left around */ @@ -2028,10 +2004,10 @@ } #ifndef NO_SLOW_LINK_SUPPORT -/* - * D: CopyArea pass - very useful for slower links - * This has been deliberately kept simple. - */ + /* + * D: CopyArea pass - very useful for slower links + * This has been deliberately kept simple. + */ i = num_scr; if (refresh_type == FAST_REFRESH && num_scr_allow && i && abs(i) < TermWin.nrow && !must_clear) @@ -2096,9 +2072,9 @@ } #endif -/* - * E: main pass across every character - */ + /* + * E: main pass across every character + */ for (row = 0; row < TermWin.nrow; row++) { stp = screen.text[row + row_offset]; @@ -2106,9 +2082,9 @@ dtp = drawn_text[row]; drp = drawn_rend[row]; -/* - * E2: OK, now the real pass - */ + /* + * E2: OK, now the real pass + */ int ypixel = (int)Row2Pixel(row); for (col = 0; col < TermWin.ncol; col++) @@ -2151,7 +2127,7 @@ continue; } - if (((rend ^ srp[col]) & ~RS_wide) != 0) + if (rend != srp[col]) break; count++; @@ -2173,16 +2149,28 @@ col--; /* went one too far. move back */ count -= i; /* dump any matching trailing chars */ -/* - * Determine the attributes for the string - */ - int fid = GET_FONT(rend); - fore = GET_FGCOLOR(rend); - back = GET_BGCOLOR(rend); - rend = GET_ATTR(rend); - - rvid = (rend & RS_RVid) ? 1 : 0; -#ifdef OPTION_HC + /* + * Determine the attributes for the string + */ + int fid = GET_FONT (rend); + int fore = GET_FGCOLOR (rend); // desired foreground + int back = GET_BGCOLOR (rend); // desired background + + rend = GET_ATTR (rend); + + rvid = !!(rend & RS_RVid); +#ifdef TEXT_BLINK + if (rend & RS_Blink) + { + if (!text_blink_ev.active) + { + text_blink_ev.start (NOW + TEXT_BLINK_INTERVAL); + hidden_text = 0; + } + else if (hidden_text) + fore = back; + } +#elif OPTION_HC if (!rvid && (rend & RS_Blink)) { if (Xdepth > 2 && ISSET_PIXCOLOR (this, Color_HC)) @@ -2207,27 +2195,22 @@ #ifndef NO_BOLD_UNDERLINE_REVERSE else if (rend & RS_Bold) { - if (Xdepth > 2 && ISSET_PIXCOLOR (this, Color_BD)) - { + if (Xdepth > 2) + if (ISSET_PIXCOLOR (this, Color_BD)) fore = Color_BD; -# ifndef VERYBOLD - rend &= ~RS_Bold; /* we've taken care of it */ -# endif - } + else + fore = Color_White; } else if (rend & RS_Uline) { if (Xdepth > 2 && ISSET_PIXCOLOR (this, Color_UL)) - { - fore = Color_UL; - rend &= ~RS_Uline; /* we've taken care of it */ - } + fore = Color_UL; } #endif -/* - * Actually do the drawing of the string here - */ + /* + * Actually do the drawing of the string here + */ rxvt_font *font = (*TermWin.fontset)[fid]; if (back == Color_bg) @@ -2257,9 +2240,9 @@ } /* for (col....) */ } /* for (row....) */ -/* - * G: cleanup cursor and display outline cursor if necessary - */ + /* + * G: cleanup cursor and display outline cursor if necessary + */ if (showcursor) { if (TermWin.focus) { srp = &(screen.rend[screen.cur.row + TermWin.saveLines] @@ -2282,14 +2265,15 @@ (unsigned int)(Height2Pixel(1) - TermWin.lineSpace - 1)); } } -/* - * H: cleanup selection - */ + + /* + * H: cleanup selection + */ rxvt_scr_reverse_selection (this); -/* - * I: other general cleanup - */ + /* + * I: other general cleanup + */ if (clearfirst && TermWin.int_bwidth) /* * clear the whole screen height, note that width == 0 is treated @@ -2491,8 +2475,6 @@ long nread = 0; unsigned long bytes_after; XTextProperty ct; - int dummy_count; - char **cl; D_SELECT((stderr, "rxvt_selection_paste(%08lx, %lu, %d), wait=%2x", win, (unsigned long)prop, (int)delete_prop, R->selection_wait)); @@ -2507,6 +2489,17 @@ rxvt_selection_request_other(aR_ XA_STRING, selnum); } + if ((R->selection_type & Sel_UTF8String)) + { + int selnum = R->selection_type & Sel_whereMask; + + R->selection_type = Sel_CompoundText; + if (selnum != Sel_direct) + rxvt_selection_request_other(aR_ R->xa[XA_COMPOUND_TEXT], selnum); + else + R->selection_type = 0; + } + return 0; } @@ -2549,10 +2542,15 @@ } nread += ct.nitems; + + char **cl; + int cr; if (XmbTextPropertyToTextList (R->Xdisplay, &ct, &cl, - &dummy_count) == Success && cl) + &cr) >= 0 && cl) { - R->paste ((unsigned char *)cl[0], STRLEN (cl[0])); + for (int i = 0; i < cr; i++) + R->paste ((unsigned char *)cl[i], STRLEN (cl[i])); + XFreeStringList (cl); } else @@ -2577,10 +2575,9 @@ void rxvt_term::incr_cb (time_watcher &w) { - w.stop (); selection_wait = Sel_none; - rxvt_print_error("data loss: timeout on INCR selection paste"); + rxvt_print_error ("data loss: timeout on INCR selection paste"); } /* @@ -2656,9 +2653,15 @@ R->selection_request_time = tm; R->selection_wait = Sel_normal; for (i = Sel_Primary; i <= Sel_Clipboard; i++) { +#if X_HAVE_UTF8_STRING + R->selection_type = Sel_UTF8String; + if (rxvt_selection_request_other(aR_ R->xa[XA_UTF8_STRING], i)) + return; +#else R->selection_type = Sel_CompoundText; if (rxvt_selection_request_other(aR_ R->xa[XA_COMPOUND_TEXT], i)) return; +#endif } } R->selection_wait = Sel_none; /* don't loop in rxvt_selection_paste() */ @@ -2800,11 +2803,12 @@ return; } - // due to MB_MAX_CUR, selection wastage is usually high + // due to MB_MAX_CUR, selection wastage is usually high, so realloc if (str - (char *)new_selection_text > 1024) new_selection_text = (unsigned char *)rxvt_realloc (new_selection_text, i + 1); R->selection.len = i; + if (R->selection.text) free (R->selection.text); @@ -2813,8 +2817,23 @@ XSetSelectionOwner(R->Xdisplay, XA_PRIMARY, R->TermWin.vt, tm); if (XGetSelectionOwner(R->Xdisplay, XA_PRIMARY) != R->TermWin.vt) rxvt_print_error("can't get primary selection"); - XChangeProperty(R->Xdisplay, Xroot, XA_CUT_BUFFER0, XA_STRING, 8, - PropModeReplace, R->selection.text, (int)R->selection.len); + + + { + XTextProperty ct; + char *cl = (char *)R->selection.text; + + if (XmbTextListToTextProperty(R->Xdisplay, &cl, 1, XStringStyle, &ct) >= 0) + { + XChangeProperty(R->Xdisplay, Xroot, XA_CUT_BUFFER0, XA_STRING, 8, + PropModeReplace, ct.value, ct.nitems); + XFree (ct.value); + } + else + XChangeProperty(R->Xdisplay, Xroot, XA_CUT_BUFFER0, XA_STRING, 8, + PropModeReplace, R->selection.text, (int)R->selection.len); + } + R->selection_time = tm; D_SELECT((stderr, "rxvt_selection_make(): R->selection.len=%d", R->selection.len)); } @@ -3276,7 +3295,7 @@ * that is exactly 32 bits wide, because a format of 64 is not allowed by * the X11 protocol. */ -typedef CARD32 Atom32; +typedef CARD32 Atom32; /* ------------------------------------------------------------------------- */ /* @@ -3288,15 +3307,9 @@ rxvt_selection_send(pR_ const XSelectionRequestEvent *rq) { XSelectionEvent ev; -#ifdef USE_XIM - Atom32 target_list[4]; -#else - Atom32 target_list[3]; -#endif - Atom target; - XTextProperty ct; + XTextProperty ct; XICCEncodingStyle style; - char *cl[2], dummy[1]; + Atom target; ev.type = SelectionNotify; ev.property = None; @@ -3307,16 +3320,20 @@ ev.time = rq->time; if (rq->target == R->xa[XA_TARGETS]) { - target_list[0] = (Atom32) R->xa[XA_TARGETS]; - target_list[1] = (Atom32) XA_STRING; - target_list[2] = (Atom32) R->xa[XA_TEXT]; -#ifdef USE_XIM - target_list[3] = (Atom32) R->xa[XA_COMPOUND_TEXT]; + Atom32 target_list[5]; + Atom32 *target = target_list; + + *target++ = (Atom32) R->xa[XA_TARGETS]; + *target++ = (Atom32) XA_STRING; + *target++ = (Atom32) R->xa[XA_TEXT]; + *target++ = (Atom32) R->xa[XA_COMPOUND_TEXT]; +#if X_HAVE_UTF8_STRING + *target++ = (Atom32) R->xa[XA_UTF8_STRING]; #endif XChangeProperty(R->Xdisplay, rq->requestor, rq->property, XA_ATOM, (8 * sizeof(target_list[0])), PropModeReplace, (unsigned char *)target_list, - (sizeof(target_list) / sizeof(target_list[0]))); + target - target_list); ev.property = rq->property; } else if (rq->target == R->xa[XA_MULTIPLE]) { /* TODO: Handle MULTIPLE */ @@ -3326,50 +3343,58 @@ (unsigned char *)&R->selection_time, 1); ev.property = rq->property; } else if (rq->target == XA_STRING + || rq->target == R->xa[XA_TEXT] || rq->target == R->xa[XA_COMPOUND_TEXT] - || rq->target == R->xa[XA_TEXT]) { -#ifdef USE_XIM - short freect = 0; + || rq->target == R->xa[XA_UTF8_STRING] + ) { + short freect = 0; + int selectlen; + char *cl; + + target = rq->target; + + if (target == XA_STRING) + // we actually don't do XA_STRING, but who cares, as i18n clients + // will ask for another format anyways. + style = XStringStyle; + else if (target == R->xa[XA_TEXT]) + style = XTextStyle; + else if (target == R->xa[XA_COMPOUND_TEXT]) + style = XCompoundTextStyle; +#if X_HAVE_UTF8_STRING + else if (target == R->xa[XA_UTF8_STRING]) + style = XUTF8StringStyle; #endif - int selectlen; - -#ifdef USE_XIM - if (rq->target != XA_STRING) { + else + { target = R->xa[XA_COMPOUND_TEXT]; - style = (rq->target == R->xa[XA_COMPOUND_TEXT]) - ? XCompoundTextStyle : XStdICCTextStyle; - } else -#endif - { - target = XA_STRING; - style = XStringStyle; - } + style = XCompoundTextStyle; + } + if (R->selection.text) { - cl[0] = (char *)R->selection.text; + cl = (char *)R->selection.text; selectlen = R->selection.len; } else { - cl[0] = dummy; - *dummy = '\0'; + cl = ""; selectlen = 0; } -#ifdef USE_XIM - if (XmbTextListToTextProperty(R->Xdisplay, cl, 1, style, &ct) - == Success) /* if we failed to convert then send it raw */ + + if (XmbTextListToTextProperty(R->Xdisplay, &cl, 1, style, &ct) >= 0) freect = 1; else -#endif - { - ct.value = (unsigned char *)cl[0]; + { + /* if we failed to convert then send it raw */ + ct.value = (unsigned char *)cl; ct.nitems = selectlen; - } + } + XChangeProperty(R->Xdisplay, rq->requestor, rq->property, target, 8, PropModeReplace, ct.value, (int)ct.nitems); ev.property = rq->property; -#ifdef USE_XIM + if (freect) - XFree(ct.value); -#endif + XFree (ct.value); } XSendEvent(R->Xdisplay, rq->requestor, False, 0L, (XEvent *)&ev); }