}
/* ------------------------------------------------------------------------- */
-#define PROP_SIZE 16384
+#define PROP_SIZE 256*1024
+#define PASTE_SIZE 32768
#define TABSIZE 8 /* default tab size */
/* ------------------------------------------------------------------------- *
else
#endif
if (options & Opt_secondaryScroll)
- //if (current_screen == PRIMARY)
- scr_scroll_text (0, prev_nrow - 1, prev_nrow, 0);
+ scr_scroll_text (0, prev_nrow - 1, prev_nrow, 0);
return scrn;
}
// characters have width -1 (DOH!) on GNU/Linux sometimes.
int width = c < 0x100 ? 1 : wcwidth (c);
- if (screen.flags & Screen_Insert)
- scr_insdel_chars (width, INSERT);
-
if (charsets[screen.charset] == '0') // DEC SPECIAL
{
// vt100 special graphics and line drawing
// 5f-7e standard vt100
// 40-5e rxvt extension for extra curses acs chars
- static uint16_t vt100_0[63] = { // 5f .. 7e
+ static uint16_t vt100_0[63] = { // 40 .. 7e
0x0000, 0x2191, 0x2193, 0x2192, 0x2190, 0x2588, 0x259a, 0x2603, // 40-47 hi mr. snowman!
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 48-4f
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 50-57
}
}
+ if (screen.flags & Screen_Insert)
+ scr_insdel_chars (width, INSERT);
+
if (width != 0)
{
// some utf-8 decoders decode surrogate characters.
while (--width > 0);
// pad with spaces when overwriting wide character with smaller one
- for (int c = screen.cur.col; c < last_col && stp[c] == NOCHAR; c++)
- {
- stp[c] = ' ';
- srp[c] = rend;
- }
+ if (!width)
+ for (int c = screen.cur.col; c < last_col && stp[c] == NOCHAR; c++)
+ {
+ stp[c] = ' ';
+ srp[c] = rend;
+ }
}
else if (width == 0)
{
font->draw (*TermWin.drawable, xpixel, ypixel, text, count, fore, back);
if (rend & RS_Uline && font->descent > 1 && fore != back)
- XDrawLine (display->display, drawBuffer, TermWin.gc,
- xpixel, ypixel + font->ascent + 1,
- xpixel + Width2Pixel (count) - 1, ypixel + font->ascent + 1);
+ {
+ XSetForeground (display->display, TermWin.gc, pix_colors[fore]);
+ XDrawLine (display->display, drawBuffer, TermWin.gc,
+ xpixel, ypixel + font->ascent + 1,
+ xpixel + Width2Pixel (count) - 1, ypixel + font->ascent + 1);
+ }
} /* for (col....) */
} /* for (row....) */
rxvt_term::paste (const unsigned char *data, unsigned int len)
{
unsigned int i, j, n;
- unsigned char *ds = (unsigned char *)rxvt_malloc (PROP_SIZE);
+ unsigned char *ds = (unsigned char *)rxvt_malloc (PASTE_SIZE);
/* convert normal newline chars into common keyboard Return key sequence */
- for (i = 0; i < len; i += PROP_SIZE)
+ for (i = 0; i < len; i += PASTE_SIZE)
{
- n = min (len - i, PROP_SIZE);
+ n = min (len - i, PASTE_SIZE);
memcpy (ds, data + i, n);
for (j = 0; j < n; j++)
* Respond to a notification that a primary selection has been sent
* EXT: SelectionNotify
*/
-int
+void
rxvt_term::selection_paste (Window win, Atom prop, bool delete_prop)
{
- long nread = 0;
- unsigned long bytes_after;
- XTextProperty ct;
-
if (prop == None) /* check for failed XConvertSelection */
{
if ((selection_type & Sel_CompoundText))
selection_type = 0;
}
- return 0;
+ return;
}
- for (;;)
+ unsigned long bytes_after;
+ XTextProperty ct;
+
+ if (XGetWindowProperty (display->display, win, prop,
+ 0, PROP_SIZE / 4,
+ delete_prop, AnyPropertyType,
+ &ct.encoding, &ct.format,
+ &ct.nitems, &bytes_after,
+ &ct.value) != Success)
{
- if (XGetWindowProperty (display->display, win, prop, (long) (nread / 4),
- (long) (PROP_SIZE / 4), delete_prop,
- AnyPropertyType, &ct.encoding, &ct.format,
- &ct.nitems, &bytes_after,
- &ct.value) != Success)
- break;
+ ct.value = 0;
+ goto bailout;
+ }
- if (ct.encoding == 0)
- break;
+ if (ct.encoding == None)
+ goto bailout;
- if (ct.encoding == xa[XA_INCR])
- {
- // INCR selection, start handshake
- XDeleteProperty (display->display, win, prop);
- selection_wait = Sel_incr;
- incr_ev.start (NOW + 10);
- break;
- }
+ if (bytes_after)
+ {
+ // fetch and append remaining data
+ XTextProperty ct2;
+
+ if (XGetWindowProperty (display->display, win, prop,
+ ct.nitems / 4, (bytes_after + 3) / 4,
+ delete_prop, AnyPropertyType,
+ &ct2.encoding, &ct2.format,
+ &ct2.nitems, &bytes_after,
+ &ct2.value) != Success)
+ goto bailout;
- if (ct.value == NULL)
- continue;
+ // realloc should be compatible to XFree, here, and elsewhere, too
+ ct.value = (unsigned char *)realloc (ct.value, ct.nitems + ct2.nitems + 1);
+ memcpy (ct.value + ct.nitems, ct2.value, ct2.nitems + 1);
+ ct.nitems += ct2.nitems;
- if (ct.nitems == 0)
+ XFree (ct2.value);
+ }
+
+ if (ct.value == 0)
+ goto bailout;
+
+ if (ct.encoding == xa[XA_INCR])
+ {
+ // INCR selection, start handshake
+ if (!delete_prop)
+ XDeleteProperty (display->display, win, prop);
+
+ selection_wait = Sel_incr;
+ incr_buf_fill = 0;
+ incr_ev.start (NOW + 10);
+
+ goto bailout;
+ }
+
+ if (ct.nitems == 0)
+ {
+ if (selection_wait == Sel_incr)
{
- if (selection_wait == Sel_normal && nread == 0
+ XFree (ct.value);
+
+ // finally complete, now paste the whole thing
+ selection_wait = Sel_normal;
+ ct.value = (unsigned char *)incr_buf;
+ ct.nitems = incr_buf_fill;
+ incr_buf = 0;
+ incr_buf_size = 0;
+ incr_ev.stop ();
+ }
+ else
+ {
+ if (selection_wait == Sel_normal
&& (win != display->root || prop != XA_CUT_BUFFER0)) // avoid recursion
{
/*
selection_paste (display->root, XA_CUT_BUFFER0, False);
}
- nread = -1; /* discount any previous stuff */
- break;
+ goto bailout;
}
+ }
+ else if (selection_wait == Sel_incr)
+ {
+ incr_ev.start (NOW + 10);
- nread += ct.nitems;
-
- char **cl;
- int cr;
- if (XmbTextPropertyToTextList (display->display, &ct, &cl, &cr) >= 0 && cl)
+ while (incr_buf_fill + ct.nitems > incr_buf_size)
{
- for (int i = 0; i < cr; i++)
- paste ((unsigned char *)cl[i], strlen (cl[i]));
-
- XFreeStringList (cl);
+ incr_buf_size = incr_buf_size ? incr_buf_size * 2 : 128*1024;
+ incr_buf = (char *)realloc (incr_buf, incr_buf_size);
}
- else
- paste (ct.value, ct.nitems);
- if (bytes_after == 0)
- break;
+ memcpy (incr_buf + incr_buf_fill, ct.value, ct.nitems);
+ incr_buf_fill += ct.nitems;
- XFree (ct.value);
+ goto bailout;
+ }
+
+ char **cl;
+ int cr;
+
+#if ENABLE_FRILLS
+ // xlib is horribly broken with respect to UTF8_STRING, and nobody cares to fix it
+ // so recode it manually
+ if (ct.encoding == xa[XA_UTF8_STRING])
+ {
+ wchar_t *w = rxvt_utf8towcs ((const char *)ct.value, ct.nitems);
+ char *s = rxvt_wcstombs (w);
+ free (w);
+ // TODO: strlen == only the first element will be converted. well...
+ paste ((unsigned char *)s, strlen (s));
+ free (s);
+ }
+ else
+#endif
+ if (XmbTextPropertyToTextList (display->display, &ct, &cl, &cr) >= 0
+ && cl)
+ {
+ for (int i = 0; i < cr; i++)
+ paste ((unsigned char *)cl[i], strlen (cl[i]));
+
+ XFreeStringList (cl);
}
+ else
+ paste (ct.value, ct.nitems); // paste raw
- if (ct.value)
- XFree (ct.value);
+bailout:
+ XFree (ct.value);
if (selection_wait == Sel_normal)
selection_wait = Sel_none;
-
- return (int)nread;
}
void
{
selection_wait = Sel_none;
+ incr_buf_size = 0;
+ free (incr_buf);
+
rxvt_warn ("data loss: timeout on INCR selection paste, ignoring.\n");
}
-/*
- * INCR support originally provided by Paul Sheer <psheer@obsidian.co.za>
- */
void
rxvt_term::selection_property (Window win, Atom prop)
{
if (prop == None || selection_wait != Sel_incr)
return;
- if (selection_paste (win, prop, 1) > 0)
- incr_ev.start (NOW + 10);
- else
- {
- selection_wait = Sel_none;
- incr_ev.stop ();
- }
+ selection_paste (win, prop, true);
}
/* ------------------------------------------------------------------------- */
if (selection_request_other (xa[XA_COMPOUND_TEXT], i))
return;
#endif
-
}
}
- selection_wait = Sel_none; /* don't loop in rxvt_selection_paste () */
- selection_paste (display->root, XA_CUT_BUFFER0, False);
+ selection_wait = Sel_none; /* don't loop in selection_paste () */
+ selection_paste (display->root, XA_CUT_BUFFER0, false);
}
int
if (XwcTextListToTextProperty (display->display, &selection.text, 1, XStringStyle, &ct) >= 0)
{
- XChangeProperty (display->display, display->root, XA_CUT_BUFFER0, XA_STRING, 8,
- PropModeReplace, ct.value, ct.nitems);
+ set_string_property (XA_CUT_BUFFER0, ct.value, ct.nitems);
XFree (ct.value);
}
#endif
rxvt_term::selection_send (const XSelectionRequestEvent &rq)
{
XSelectionEvent ev;
- XTextProperty ct;
- XICCEncodingStyle style;
- Atom target;
ev.type = SelectionNotify;
ev.property = None;
|| rq.target == xa[XA_UTF8_STRING]
)
{
+ XTextProperty ct;
+ Atom target = rq.target;
short freect = 0;
int selectlen;
wchar_t *cl;
-
- target = rq.target;
+ enum {
+ enc_string = XStringStyle,
+ enc_text = XStdICCTextStyle,
+ enc_compound_text = XCompoundTextStyle,
+#ifdef X_HAVE_UTF8_STRING
+ enc_utf8 = XUTF8StringStyle,
+#else
+ enc_utf8 = -1,
+#endif
+ } style;
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;
+ style = enc_string;
else if (target == xa[XA_TEXT])
- style = XStdICCTextStyle;
+ style = enc_text;
else if (target == xa[XA_COMPOUND_TEXT])
- style = XCompoundTextStyle;
-#if X_HAVE_UTF8_STRING
+ style = enc_compound_text;
+#if ENABLE_FRILLS
else if (target == xa[XA_UTF8_STRING])
- style = XUTF8StringStyle;
+ style = enc_utf8;
#endif
else
{
target = xa[XA_COMPOUND_TEXT];
- style = XCompoundTextStyle;
+ style = enc_compound_text;
}
if (selection.text)
selectlen = 0;
}
- // Xwc doesn't handle iso-10646 in wchar_t gracefully, so maybe recode it
- // manually for XUTF8StringStyle.
- if (XwcTextListToTextProperty (display->display, &cl, 1, style, &ct) >= 0)
+#if ENABLE_FRILLS
+ // xlib is horribly broken with respect to UTF8_STRING, and nobody cares to fix it
+ // so recode it manually
+ if (style == enc_utf8)
+ {
+ freect = 1;
+ ct.encoding = target;
+ ct.format = 8;
+ ct.value = (unsigned char *)rxvt_wcstoutf8 (cl, selectlen);
+ ct.nitems = strlen ((char *)ct.value);
+ }
+ else
+#endif
+ if (XwcTextListToTextProperty (display->display, &cl, 1, (XICCEncodingStyle) style, &ct) >= 0)
freect = 1;
else
{
/* if we failed to convert then send it raw */
ct.value = (unsigned char *)cl;
ct.nitems = selectlen;
+ ct.encoding = target;
}
XChangeProperty (display->display, rq.requestor, rq.property,
- target, 8, PropModeReplace,
+ ct.encoding, 8, PropModeReplace,
ct.value, (int)ct.nitems);
ev.property = rq.property;