*** empty log message ***
authorroot <root>
Mon, 13 Dec 2004 01:29:03 +0000 (01:29 +0000)
committerroot <root>
Mon, 13 Dec 2004 01:29:03 +0000 (01:29 +0000)
Changes
src/command.C
src/main.C
src/rxvt.h
src/screen.C

diff --git a/Changes b/Changes
index 60d7d3c..28a1ef8 100644 (file)
--- a/Changes
+++ b/Changes
@@ -2,9 +2,7 @@ Lines marked with "xterm:" indicate either xterm features ported to rxvt
 or changed rxvt behaviour to make it more compatible to xterm (usually
 xfree86's xterm).
 
-TODO: underline colour changes?
 TODO: read property sequence is broken with respect to utf-8 etc.
-TODO: +ssc -ssr seems to scroll at wrong time, scrolling up the empty sec. scr.
 FEAT: hotkey font resizing
 FEAT: searchable backlog
 FEAT: meta-tagging of data by regex (my dream project)
@@ -13,7 +11,11 @@ FEAT: double-click: more intelligent (urls etc.)
 FEAT: OnTheSpot editing.
 FEAT: tabbed windows
 
-4.4
+       - completely re-wrote selection pasting. This should fix
+          garbled incomplete characters at 32k boundaries and too-short
+          INCR selections.
+
+4.4  Sun Dec 12 22:10:06 CET 2004
        - rewrote handling of default-char width.
         - implement _NET_WM_NAME et al., and also use UTF8_STRING
           for the xterm property esc. sequence. Allows i18n window
index aef23f4..e79ab86 100644 (file)
@@ -1338,7 +1338,7 @@ rxvt_term::x_cb (XEvent &ev)
                                &data);
             set_string_property (XA_CUT_BUFFER0, data);
             XFree (data);
-            selection_paste (display->root, XA_CUT_BUFFER0, True);
+            selection_paste (display->root, XA_CUT_BUFFER0, true);
             XSetInputFocus (display->display, display->root, RevertToNone, CurrentTime);
           }
 #endif                         /* OFFIX_DND */
@@ -1470,8 +1470,7 @@ rxvt_term::x_cb (XEvent &ev)
 
       case SelectionNotify:
         if (selection_wait == Sel_normal)
-          selection_paste (ev.xselection.requestor,
-                           ev.xselection.property, True);
+          selection_paste (ev.xselection.requestor, ev.xselection.property, true);
         break;
 
       case SelectionRequest:
index 76795d0..942089f 100644 (file)
@@ -261,9 +261,7 @@ rxvt_term::~rxvt_term ()
   free (env_term);
   free (env_colorfgbg);
   free (locale);
-#if 0
-  free (codeset);
-#endif
+  free (incr_buf);
 
   delete envv;
   delete argv;
index cd53960..e2d5595 100644 (file)
@@ -1104,6 +1104,8 @@ struct rxvt_term : zero_initialized, rxvt_vars {
   Time            selection_time,
                   selection_request_time;
   pid_t           cmd_pid;    /* process id of child */
+  char *          incr_buf;
+  size_t          incr_buf_size, incr_buf_fill;
 /* ---------- */
   Cursor          leftptr_cursor;
 #ifdef POINTER_BLANK
@@ -1450,7 +1452,7 @@ struct rxvt_term : zero_initialized, rxvt_vars {
   void scr_reverse_selection ();
   void scr_dump (int fd);
   void selection_check (int check_more);
-  int selection_paste (Window win, Atom prop, bool delete_prop);
+  void selection_paste (Window win, Atom prop, bool delete_prop);
   void selection_property (Window win, Atom prop);
   void selection_request (Time tm, int x, int y);
   int selection_request_other (Atom target, int selnum);
index f232beb..e0d7dbc 100644 (file)
@@ -41,7 +41,8 @@ inline void fill_text (text_t *start, text_t value, int len)
 }
 
 /* ------------------------------------------------------------------------- */
-#define PROP_SIZE               16384
+#define PROP_SIZE               256*1024
+#define PASTE_SIZE             32768
 #define TABSIZE                 8       /* default tab size */
 
 /* ------------------------------------------------------------------------- *
@@ -602,8 +603,7 @@ rxvt_term::scr_change_screen (int scrn)
   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;
 }
@@ -2661,12 +2661,12 @@ void
 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++)
@@ -2684,13 +2684,9 @@ rxvt_term::paste (const unsigned char *data, unsigned int len)
  * 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))
@@ -2713,36 +2709,83 @@ rxvt_term::selection_paste (Window win, Atom prop, bool delete_prop)
             selection_type = 0;
         }
 
-      return 0;
+      return;
     }
 
-  for (;;)
+  unsigned long bytes_after;
+  XTextProperty ct;
+
+  if (XGetWindowProperty (display->display, win, prop,
+                          0, (long)(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;
+      unsigned long bytes_after2;
+
+      if (XGetWindowProperty (display->display, win, prop,
+                              ct.nitems / 4, (long) (bytes_after + 3) / 4,
+                              delete_prop, AnyPropertyType,
+                              &ct2.encoding, &ct2.format,
+                              &ct2.nitems, &bytes_after2,
+                              &ct2.value) != Success)
+        goto bailout;
+
+      // realloc should be compatible to XFree, here, and elsewhere, too
+      ct.value = (unsigned char *)realloc (ct.value, ct.nitems + bytes_after);
+      memcpy (ct.value + ct.nitems, ct2.value, ct2.nitems);
+      ct.nitems += ct2.nitems;
+
+      XFree (ct2.value);
+    }
+  else if (delete_prop)
+    XDeleteProperty (display->display, win, prop);
+
+  if (ct.value == 0)
+    goto bailout;
+
+  if (ct.encoding == xa[XA_INCR])
+    {
+      // INCR selection, start handshake
+      if (!delete_prop)
+        XDeleteProperty (display->display, win, prop);
 
-      if (ct.value == NULL)
-        continue;
+      selection_wait = Sel_incr;
+      incr_buf_fill = 0;
+      incr_ev.start (NOW + 10);
 
-      if (ct.nitems == 0)
+      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
             {
               /*
@@ -2752,54 +2795,58 @@ rxvt_term::selection_paste (Window win, Atom prop, bool delete_prop)
               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 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])
+      while (incr_buf_fill + ct.nitems > incr_buf_size)
         {
-          wchar_t *w = rxvt_utf8towcs ((const char *)ct.value, ct.nitems);
-          char *s = rxvt_wcstombs (w);
+          incr_buf_size = incr_buf_size ? incr_buf_size * 2 : 128*1024;
+          incr_buf = (char *)realloc (incr_buf, incr_buf_size);
+        }
 
-          // TODO: strlen == only the first element will be converted. well...
-          paste ((unsigned char *)s, strlen (s));
+      memcpy (incr_buf + incr_buf_fill, ct.value, ct.nitems);
+      incr_buf_fill += ct.nitems;
 
-          free (s);
-          free (w);
-        }
-      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]));
+      goto bailout;
+    }
 
-          XFreeStringList (cl);
-        }
-      else
-        paste (ct.value, ct.nitems);
+  char **cl;
+  int cr;
 
-      if (bytes_after == 0)
-        break;
+#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]));
 
-      XFree (ct.value);
+      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
@@ -2807,25 +2854,19 @@ rxvt_term::incr_cb (time_watcher &w)
 {
   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);
 }
 
 /* ------------------------------------------------------------------------- */
@@ -2872,8 +2913,8 @@ rxvt_term::selection_request (Time tm, int x, int y)
         }
     }
 
-  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