Index: tigervnc_svn/unix/tx/TXWindow.cxx
===================================================================
--- tigervnc_svn/unix/tx/TXWindow.cxx	(revision 4782)
+++ tigervnc_svn/unix/tx/TXWindow.cxx	(working copy)
@@ -30,7 +30,7 @@
 
 Atom wmProtocols, wmDeleteWindow, wmTakeFocus;
 Atom xaTIMESTAMP, xaTARGETS, xaSELECTION_TIME, xaSELECTION_STRING;
-Atom xaCLIPBOARD;
+Atom xaCLIPBOARD, xaINCR;
 unsigned long TXWindow::black, TXWindow::white;
 unsigned long TXWindow::defaultFg, TXWindow::defaultBg;
 unsigned long TXWindow::lightBg, TXWindow::darkBg;
@@ -57,6 +57,7 @@
   xaSELECTION_TIME = XInternAtom(dpy, "SELECTION_TIME", False);
   xaSELECTION_STRING = XInternAtom(dpy, "SELECTION_STRING", False);
   xaCLIPBOARD = XInternAtom(dpy, "CLIPBOARD", False);
+  xaINCR = XInternAtom(dpy, "INCR", False);
   XColor cols[6];
   cols[0].red = cols[0].green = cols[0].blue = 0x0000;
   cols[1].red = cols[1].green = cols[1].blue = 0xbbbb;
@@ -412,20 +413,68 @@
     if (ev->xselection.property != None) {
       Atom type;
       int format;
-      unsigned long nitems, after;
-      unsigned char *data;
-      XGetWindowProperty(dpy, win(), ev->xselection.property, 0, 16384, True,
-                         AnyPropertyType, &type, &format,
-                         &nitems, &after, &data);
+      unsigned long nitems = 0, after;
+      unsigned char *data = 0;
+
+      XGetWindowProperty(dpy, win(), ev->xselection.property, 
+          0, 0, False,
+          AnyPropertyType, &type, &format,
+          &nitems, &after, &data);
+      XFree(data);
+      data = 0;
+
+      // dont get the INCR values
+      if (type != None && type != xaINCR && after) {
+        XGetWindowProperty(dpy, win(), ev->xselection.property, 
+            0, (after + 3) / 4, False,
+            AnyPropertyType, &type, &format,
+            &nitems, &after, &data);
+      }
+
       if (type != None) {
         selectionNotify(&ev->xselection, type, format, nitems, data);
-        XFree(data);
-        break;
       }
+
+      XFree(data);
+      XDeleteProperty(dpy, win(), ev->xselection.property);
+      XFlush(dpy);
     }
-    selectionNotify(&ev->xselection, 0, 0, 0, 0);
+    else {
+      selectionNotify(&ev->xselection, 0, 0, 0, 0);
+    }
     break;
 
+  case PropertyNotify:
+    if (ev->xproperty.state == PropertyNewValue) {
+      Atom type;
+      int format;
+      unsigned long nitems = 0, after;
+      unsigned char *data = 0;
+
+      XGetWindowProperty(dpy, win(), ev->xproperty.atom, 
+          0, 0, False,
+          AnyPropertyType, &type, &format,
+          &nitems, &after, &data);
+      XFree(data);
+      data = 0;
+
+      if (type != None && type != xaINCR && after) {
+        XGetWindowProperty(dpy, win(), ev->xproperty.atom, 
+            0, (after + 3) / 4, False,
+            AnyPropertyType, &type, &format,
+            &nitems, &after, &data);
+      }
+
+      if (type != None) {
+        propertyNotify(&ev->xproperty, type, format, nitems, 
+            data);
+      }
+      XFree(data);
+      XDeleteProperty(dpy, win(), ev->xproperty.atom);
+      XFlush(dpy);
+    }
+    break;
+
   case SelectionRequest:
     {
       XSelectionEvent se;
Index: tigervnc_svn/unix/tx/TXWindow.h
===================================================================
--- tigervnc_svn/unix/tx/TXWindow.h	(revision 4782)
+++ tigervnc_svn/unix/tx/TXWindow.h	(working copy)
@@ -136,6 +136,11 @@
   // window manager.
   virtual void takeFocus(Time time) {}
 
+  // propertyNotify() is called when the selection owner has replied to a
+  // request for information about a selection from the selection owner.
+  virtual void propertyNotify(XPropertyEvent* ev, Atom type, int format,
+                              int nitems, void* data) {}
+
   // selectionNotify() is called when the selection owner has replied to a
   // request for information about a selection from the selection owner.
   virtual void selectionNotify(XSelectionEvent* ev, Atom type, int format,
@@ -208,6 +213,6 @@
 
 extern Atom wmProtocols, wmDeleteWindow, wmTakeFocus;
 extern Atom xaTIMESTAMP, xaTARGETS, xaSELECTION_TIME, xaSELECTION_STRING;
-extern Atom xaCLIPBOARD;
+extern Atom xaCLIPBOARD, xaINCR;
 
 #endif
Index: tigervnc_svn/unix/vncconfig/vncExt.c
===================================================================
--- tigervnc_svn/unix/vncconfig/vncExt.c	(revision 4782)
+++ tigervnc_svn/unix/vncconfig/vncExt.c	(working copy)
@@ -208,6 +208,7 @@
 Bool XVncExtSetServerCutText(Display* dpy, const char* str, int len)
 {
   xVncExtSetServerCutTextReq* req;
+  int words;
 
   if (!checkExtension(dpy)) return False;
 
@@ -215,8 +216,9 @@
   GetReq(VncExtSetServerCutText, req);
   req->reqType = codes->major_opcode;
   req->vncExtReqType = X_VncExtSetServerCutText;
-  req->length += (len + 3) >> 2;
   req->textLen = len;
+  words = (len + 3) >> 2;
+  SetReqLen(req, words, 0);
   Data(dpy, str, len);
   UnlockDisplay(dpy);
   SyncHandle();
Index: tigervnc_svn/unix/vncconfig/vncconfig.cxx
===================================================================
--- tigervnc_svn/unix/vncconfig/vncconfig.cxx	(revision 4782)
+++ tigervnc_svn/unix/vncconfig/vncconfig.cxx	(working copy)
@@ -94,6 +94,7 @@
   {
     selection[0] = selection[1] = 0;
     selectionLen[0] = selectionLen[1] = 0;
+    incremental[0] = incremental[1] = false;
     int y = yPad;
     acceptClipboard.move(xPad, y);
     acceptClipboard.checked(getBoolParam(dpy, ACCEPT_CUT_TEXT));
@@ -107,6 +108,7 @@
     y += sendPrimaryCB.height();
     setEventHandler(this);
     toplevel("VNC config", this, 0, 0, 0, iconic);
+    XSelectInput(dpy, win(), PropertyChangeMask);
     XVncExtSelectInput(dpy, win(),
                        VncExtClientCutTextMask|
                        VncExtSelectionChangeMask|
@@ -142,6 +144,7 @@
           delete [] selection[1];
           selection[0] = selection[1] = 0;
           selectionLen[0] = selectionLen[1] = 0;
+          incremental[0] = incremental[1] = false;
         }
       }
     }
@@ -197,21 +200,35 @@
   void selectionNotify(XSelectionEvent* ev, Atom type, int format,
                        int nitems, void* data)
   {
-    if (ev->requestor != win() || ev->target != XA_STRING)
+    int i = (ev->property == XA_PRIMARY ? 0 : 1);
+    // incremental data come through propertyNotify
+    if (ev->requestor != win() || ev->target != XA_STRING || incremental[i])
       return;
 
-    if (data && format == 8) {
-      int i = (ev->selection == XA_PRIMARY ? 0 : 1);
-      if (selectionLen[i] == nitems && memcmp(selection[i], data, nitems) == 0)
+    if (type == xaINCR) {
+      // switch to incremental mode
+      if (selection[i]) {
+        delete [] selection[i];
+        selection[i] = 0;
+      }
+      selectionLen[i] = 0;
+      incremental[i] = true;
+      return;
+    }
+
+    if (data && format == 8 ) {
+      incremental[i] = false;
+
+      if (selectionLen[i] == nitems &&
+          memcmp(selection[i], data, nitems) == 0) {
+        vlog.debug("ignoring duplicate cut text");
         return;
+      }
+
       delete [] selection[i];
       selection[i] = new char[nitems];
       memcpy(selection[i], data, nitems);
       selectionLen[i] = nitems;
-      if (cutTextLen == nitems && memcmp(cutText, data, nitems) == 0) {
-        vlog.debug("ignoring duplicate cut text");
-        return;
-      }
       if (cutText)
         XFree(cutText);
       cutText = (char*)malloc(nitems); // assuming XFree() same as free()
@@ -224,6 +241,63 @@
     }
   }
 
+  // property update
+  void propertyNotify(XPropertyEvent* ev, Atom type, int format,
+                       int nitems, void* data)
+  {
+    int i = (ev->atom == XA_PRIMARY ? 0 : 1);
+
+    if (ev->window != win() ||
+       (ev->atom != XA_PRIMARY && ev->atom != xaCLIPBOARD))
+      return;
+
+    if (type == xaINCR) {
+      // switch to incremental mode
+      if (selection[i]) {
+        delete [] selection[i];
+        selection[i] = 0;
+      }
+      selectionLen[i] = 0;
+      incremental[i] = true;
+      return;
+    }
+
+    if (format == 8 ) {
+      // continued?
+      if (data && nitems) {
+        char * newselection = new char[selectionLen[i] + nitems];
+
+        if (selection[i]) {
+          if (incremental[i])
+            memcpy(newselection, selection[i], selectionLen[i]);
+          else
+            selectionLen[i] = 0;
+          delete [] selection[i];
+        }
+
+        memcpy(newselection + selectionLen[i], data, nitems);
+        selection[i] = newselection;
+        selectionLen[i] += nitems;
+      } else {
+        // end of mode
+        incremental[i] = false;
+      }
+
+      if (!incremental[i]) {
+        if (cutText)
+          XFree(cutText);
+        // assuming XFree() same as free()
+        cutText = (char*)malloc(selectionLen[i]);
+        memcpy(cutText, selection[i], selectionLen[i]);
+        cutTextLen = selectionLen[i];
+        vlog.debug("sending %s selection as server cut text: '%.*s%s'",
+                   selectionName(ev->atom),cutTextLen<9?cutTextLen:8,
+                   cutText, cutTextLen<9?"":"...");
+        XVncExtSetServerCutText(dpy, cutText, cutTextLen);
+      }
+    }
+  }
+
   // TXDeleteWindowCallback method
   virtual void deleteWindow(TXWindow* w) {
     exit(1);
@@ -265,6 +339,7 @@
   int cutTextLen;
   char* selection[2];
   int selectionLen[2];
+  bool incremental[2];
   TXCheckbox acceptClipboard, sendClipboard, sendPrimaryCB;
   rfb::Timer pollTimer;
 
Index: tigervnc_svn/common/rfb/ConnParams.h
===================================================================
--- tigervnc_svn/common/rfb/ConnParams.h	(revision 4782)
+++ tigervnc_svn/common/rfb/ConnParams.h	(working copy)
@@ -88,6 +88,8 @@
     int fineQualityLevel;
     JPEG_SUBSAMP subsampling;
 
+    rdr::U32 maxCutTextSize;
+
   private:
 
     PixelFormat pf_;
Index: tigervnc_svn/common/rfb/ConnParams.cxx
===================================================================
--- tigervnc_svn/common/rfb/ConnParams.cxx	(revision 4782)
+++ tigervnc_svn/common/rfb/ConnParams.cxx	(working copy)
@@ -38,7 +38,8 @@
     noJpeg(false), qualityLevel(-1), fineQualityLevel(-1),
     subsampling(SUBSAMP_UNDEFINED),
     name_(0), nEncodings_(0), encodings_(0),
-    currentEncoding_(encodingRaw), verStrPos(0)
+    currentEncoding_(encodingRaw), verStrPos(0),
+    maxCutTextSize(256*1024)
 {
   setName("");
 }
Index: tigervnc_svn/common/rfb/CMsgReader.cxx
===================================================================
--- tigervnc_svn/common/rfb/CMsgReader.cxx	(revision 4782)
+++ tigervnc_svn/common/rfb/CMsgReader.cxx	(working copy)
@@ -61,9 +61,10 @@
 {
   is->skip(3);
   rdr::U32 len = is->readU32();
-  if (len > 256*1024) {
+  if (len > handler->cp.maxCutTextSize) {
     is->skip(len);
-    fprintf(stderr,"cut text too long (%d bytes) - ignoring\n",len);
+    fprintf(stderr,"cut text too long (%d bytes vs max %d) - ignoring\n",len,
+            handler->cp.maxCutTextSize);
     return;
   }
   CharArray ca(len+1);
Index: tigervnc_svn/common/rfb/SMsgReader.cxx
===================================================================
--- tigervnc_svn/common/rfb/SMsgReader.cxx	(revision 4782)
+++ tigervnc_svn/common/rfb/SMsgReader.cxx	(working copy)
@@ -90,7 +90,8 @@
   int len = is->readU32();
   if (len > maxCutText) {
     is->skip(len);
-    vlog.error("Cut text too long (%d bytes) - ignoring", len);
+    vlog.error("Cut text too long (%d bytes vs max %d) - ignoring", len,
+               (int) maxCutText);
     return;
   }
   CharArray ca(len+1);
Index: tigervnc_svn/vncviewer/parameters.cxx
===================================================================
--- tigervnc_svn/vncviewer/parameters.cxx	(revision 4782)
+++ tigervnc_svn/vncviewer/parameters.cxx	(working copy)
@@ -95,3 +95,7 @@
                                    "to the server when in full screen mode.",
                                    true);
 
+IntParameter maxServerCutText("MaxServerCutText",
+                              "Maximum clipboard copy from the server",
+                              256 * 1024);
+
Index: tigervnc_svn/vncviewer/OptionsDialog.cxx
===================================================================
--- tigervnc_svn/vncviewer/OptionsDialog.cxx	(revision 4782)
+++ tigervnc_svn/vncviewer/OptionsDialog.cxx	(working copy)
@@ -261,6 +261,7 @@
   sendClipboardCheckbox->value(sendClipboard);
   sendPrimaryCheckbox->value(sendPrimary);
   systemKeysCheckbox->value(fullscreenSystemKeys);
+  maxCutTextInput->value(maxServerCutText.getValueStr());
 
   menuKeyChoice->value(0);
 
@@ -349,6 +350,7 @@
   sendClipboard.setParam(sendClipboardCheckbox->value());
   sendPrimary.setParam(sendPrimaryCheckbox->value());
   fullscreenSystemKeys.setParam(systemKeysCheckbox->value());
+  maxServerCutText.setParam(maxCutTextInput->value());
 
   if (menuKeyChoice->value() == 0)
     menuKey.setParam("");
@@ -654,8 +656,15 @@
                                                          CHECK_MIN_WIDTH,
                                                          CHECK_HEIGHT,
                                                          _("Accept clipboard from server")));
+  acceptClipboardCheckbox->callback(this->handleAcceptServerClipboard, this);
   ty += CHECK_HEIGHT + TIGHT_MARGIN;
 
+  maxCutTextInput = new Fl_Int_Input(tx + INDENT, ty,
+                                     gui_str_len("4294967296"), INPUT_HEIGHT,
+                                     _("Maximum server cut text size"));
+  maxCutTextInput->align(FL_ALIGN_RIGHT);
+  ty += INPUT_HEIGHT + TIGHT_MARGIN;
+
   sendClipboardCheckbox = new Fl_Check_Button(LBLRIGHT(tx, ty,
                                                        CHECK_MIN_WIDTH,
                                                        CHECK_HEIGHT,
@@ -768,7 +777,17 @@
   }
 }
 
+void OptionsDialog::handleAcceptServerClipboard(Fl_Widget *widget, void *data)
+{  OptionsDialog *dialog = (OptionsDialog*)data;
 
+  if (dialog->acceptClipboardCheckbox->value()) {
+    dialog->maxCutTextInput->activate();
+  } else {
+    dialog->maxCutTextInput->deactivate();
+  }
+
+}
+
 void OptionsDialog::handleCancel(Fl_Widget *widget, void *data)
 {
   OptionsDialog *dialog = (OptionsDialog*)data;
Index: tigervnc_svn/vncviewer/parameters.h
===================================================================
--- tigervnc_svn/vncviewer/parameters.h	(revision 4782)
+++ tigervnc_svn/vncviewer/parameters.h	(working copy)
@@ -51,4 +51,6 @@
 
 extern rfb::BoolParameter fullscreenSystemKeys;
 
+extern rfb::IntParameter maxServerCutText;
+
 #endif
Index: tigervnc_svn/vncviewer/OptionsDialog.h
===================================================================
--- tigervnc_svn/vncviewer/OptionsDialog.h	(revision 4782)
+++ tigervnc_svn/vncviewer/OptionsDialog.h	(working copy)
@@ -57,6 +57,8 @@
   static void handleJpeg(Fl_Widget *widget, void *data);
 
   static void handleX509(Fl_Widget *widget, void *data);
+  
+  static void handleAcceptServerClipboard(Fl_Widget *widget, void *data);
 
   static void handleCancel(Fl_Widget *widget, void *data);
   static void handleOK(Fl_Widget *widget, void *data);
@@ -103,6 +105,7 @@
   Fl_Check_Button *sendClipboardCheckbox;
   Fl_Check_Button *sendPrimaryCheckbox;
   Fl_Check_Button *systemKeysCheckbox;
+  Fl_Int_Input *maxCutTextInput;
   Fl_Choice *menuKeyChoice;
 
   /* Misc. */
Index: tigervnc_svn/vncviewer/CConn.cxx
===================================================================
--- tigervnc_svn/vncviewer/CConn.cxx	(revision 4782)
+++ tigervnc_svn/vncviewer/CConn.cxx	(working copy)
@@ -90,6 +90,8 @@
   cp.noJpeg = noJpeg;
   cp.qualityLevel = qualityLevel;
 
+  cp.maxCutTextSize = maxServerCutText;
+
   try {
     getHostAndPort(vncServerName, &serverHost, &serverPort);
 
@@ -609,4 +611,6 @@
 
   if (!pf.equal(self->cp.pf()))
     self->formatChange = true;
+
+  self->cp.maxCutTextSize = maxServerCutText;
 }
