vncconfig_unix directory merged with VNC 4.1.1 code.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/branches/merge-with-vnc-4.1.1@527 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/vncconfig_unix/Makefile.in b/vncconfig_unix/Makefile.in
index 58277c3..4891fcd 100644
--- a/vncconfig_unix/Makefile.in
+++ b/vncconfig_unix/Makefile.in
@@ -1,7 +1,7 @@
 
-SRCS = vncExt.c vncconfig.cxx
+SRCS = vncExt.c vncconfig.cxx QueryConnectDialog.cxx
 
-OBJS = vncExt.o vncconfig.o
+OBJS = vncExt.o vncconfig.o QueryConnectDialog.o
 
 program = vncconfig
 
diff --git a/vncconfig_unix/buildtime.c b/vncconfig_unix/buildtime.c
index a96031c..3f4c369 100644
--- a/vncconfig_unix/buildtime.c
+++ b/vncconfig_unix/buildtime.c
@@ -1,5 +1,5 @@
-/* Copyright (C) 2002-2003 RealVNC Ltd.  All Rights Reserved.
- *    
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
diff --git a/vncconfig_unix/vncExt.c b/vncconfig_unix/vncExt.c
index ac1dab3..ff5532b 100644
--- a/vncconfig_unix/vncExt.c
+++ b/vncconfig_unix/vncExt.c
@@ -1,5 +1,5 @@
-/* Copyright (C) 2002-2003 RealVNC Ltd.  All Rights Reserved.
- *    
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -18,6 +18,7 @@
 #include <stdio.h>
 
 #define NEED_REPLIES
+#include <X11/Xlib.h>
 #include <X11/Xlibint.h>
 #define _VNCEXT_PROTO_
 #include "vncExt.h"
@@ -26,6 +27,8 @@
                                                   xEvent* w);
 static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e,
                                                     xEvent* w);
+static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e,
+                                                 xEvent* w);
 
 static Bool extensionInited = False;
 static XExtCodes* codes = 0;
@@ -40,6 +43,8 @@
                      XVncExtClientCutTextNotifyWireToEvent);
     XESetWireToEvent(dpy, codes->first_event + VncExtSelectionChangeNotify,
                      XVncExtSelectionChangeNotifyWireToEvent);
+    XESetWireToEvent(dpy, codes->first_event + VncExtQueryConnectNotify,
+                     XVncExtQueryConnectNotifyWireToEvent);
   }
   return codes != 0;
 }
@@ -286,6 +291,55 @@
   return rep.success;
 }
 
+Bool XVncExtGetQueryConnect(Display* dpy, char** addr, char** user,
+                            int* timeout, void** opaqueId)
+{
+  xVncExtGetQueryConnectReq* req;
+  xVncExtGetQueryConnectReply rep;
+
+  if (!checkExtension(dpy)) return False;
+
+  LockDisplay(dpy);
+  GetReq(VncExtGetQueryConnect, req);
+  req->reqType = codes->major_opcode;
+  req->vncExtReqType = X_VncExtGetQueryConnect;
+  if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+    UnlockDisplay(dpy);
+    SyncHandle();
+    return False;
+  }
+  UnlockDisplay(dpy);
+  SyncHandle();
+
+  *addr = Xmalloc(rep.addrLen+1);
+  _XReadPad(dpy, *addr, rep.addrLen);
+  (*addr)[rep.addrLen] = 0;
+  *user = Xmalloc(rep.userLen+1);
+  _XReadPad(dpy, *user, rep.userLen);
+  (*user)[rep.userLen] = 0;
+  *timeout = rep.timeout;
+  *opaqueId = (void*)rep.opaqueId;
+  return True;
+}
+
+Bool XVncExtApproveConnect(Display* dpy, void* opaqueId, int approve)
+{
+  xVncExtApproveConnectReq* req;
+
+  if (!checkExtension(dpy)) return False;
+
+  LockDisplay(dpy);
+  GetReq(VncExtApproveConnect, req);
+  req->reqType = codes->major_opcode;
+  req->vncExtReqType = X_VncExtApproveConnect;
+  req->approve = approve;
+  req->opaqueId = (CARD32)opaqueId;
+  UnlockDisplay(dpy);
+  SyncHandle();
+  return True;
+}
+
+
 static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e,
                                                   xEvent* w)
 {
@@ -314,3 +368,17 @@
   ev->selection = wire->selection;
   return True;
 }
+
+static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e,
+                                                    xEvent* w)
+{
+  XVncExtQueryConnectEvent* ev = (XVncExtQueryConnectEvent*)e;
+  xVncExtQueryConnectNotifyEvent* wire
+    = (xVncExtQueryConnectNotifyEvent*)w;
+  ev->type = wire->type & 0x7f;
+  ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
+  ev->send_event = (wire->type & 0x80) != 0;
+  ev->display = dpy;
+  ev->window = wire->window;
+  return True;
+}
diff --git a/vncconfig_unix/vncExt.h b/vncconfig_unix/vncExt.h
index de69f4e..f1502c4 100644
--- a/vncconfig_unix/vncExt.h
+++ b/vncconfig_unix/vncExt.h
@@ -1,5 +1,5 @@
-/* Copyright (C) 2002-2003 RealVNC Ltd.  All Rights Reserved.
- *    
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -30,13 +30,17 @@
 #define X_VncExtGetClientCutText 5
 #define X_VncExtSelectInput 6
 #define X_VncExtConnect 7
+#define X_VncExtGetQueryConnect 8
+#define X_VncExtApproveConnect 9
 
 #define VncExtClientCutTextNotify 0
 #define VncExtSelectionChangeNotify 1
+#define VncExtQueryConnectNotify 2
 #define VncExtClientCutTextMask (1 << VncExtClientCutTextNotify)
 #define VncExtSelectionChangeMask (1 << VncExtSelectionChangeNotify)
+#define VncExtQueryConnectMask (1 << VncExtQueryConnectNotify)
 
-#define VncExtNumberEvents 2
+#define VncExtNumberEvents 3
 #define VncExtNumberErrors 0
 
 #ifndef _VNCEXT_SERVER_
@@ -51,6 +55,10 @@
 Bool XVncExtGetClientCutText(Display* dpy, char** str, int* len);
 Bool XVncExtSelectInput(Display* dpy, Window w, int mask);
 Bool XVncExtConnect(Display* dpy, char* hostAndPort);
+Bool XVncExtGetQueryConnect(Display* dpy, char** addr,
+                            char** user, int* timeout, void** opaqueId);
+Bool XVncExtApproveConnect(Display* dpy, void* opaqueId, int approve);
+
 
 typedef struct {
   int type;
@@ -70,6 +78,14 @@
   Atom selection;
 } XVncExtSelectionChangeEvent;
 
+typedef struct {
+  int type;
+  unsigned long serial;
+  Bool send_event;
+  Display *display;
+  Window window;
+} XVncExtQueryConnectEvent;
+
 #endif
 
 #ifdef _VNCEXT_PROTO_
@@ -243,6 +259,40 @@
 
 
 typedef struct {
+  CARD8 reqType;       /* always VncExtReqCode */
+  CARD8 vncExtReqType; /* always VncExtGetQueryConnect */
+  CARD16 length B16;
+} xVncExtGetQueryConnectReq;
+#define sz_xVncExtGetQueryConnectReq 4
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 addrLen B32;
+ CARD32 userLen B32;
+ CARD32 timeout B32;
+ CARD32 opaqueId B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+} xVncExtGetQueryConnectReply;
+#define sz_xVncExtGetQueryConnectReply 32
+
+typedef struct {
+  CARD8 reqType;       /* always VncExtReqCode */
+  CARD8 vncExtReqType; /* always VncExtApproveConnect */
+  CARD16 length B16;
+  CARD8 approve;
+  CARD8 pad0;
+  CARD16 pad1;
+  CARD32 opaqueId B32;
+} xVncExtApproveConnectReq;
+#define sz_xVncExtApproveConnectReq 12
+
+
+
+typedef struct {
   BYTE type;    /* always eventBase + VncExtClientCutTextNotify */
   BYTE pad0;
   CARD16 sequenceNumber B16;
@@ -270,6 +320,20 @@
 } xVncExtSelectionChangeNotifyEvent;
 #define sz_xVncExtSelectionChangeNotifyEvent 32
 
+typedef struct {
+  BYTE type;    /* always eventBase + VncExtQueryConnectNotify */
+  BYTE pad0;
+  CARD16 sequenceNumber B16;
+  CARD32 window B32;
+  CARD32 pad6 B32;
+  CARD32 pad1 B32;
+  CARD32 pad2 B32;
+  CARD32 pad3 B32;
+  CARD32 pad4 B32;
+  CARD32 pad5 B32;
+} xVncExtQueryConnectNotifyEvent;
+#define sz_xVncExtQueryConnectNotifyEvent 32
+
 #endif
 
 #ifdef __cplusplus
diff --git a/vncconfig_unix/vncconfig.cxx b/vncconfig_unix/vncconfig.cxx
index e707ffb..c901d19 100644
--- a/vncconfig_unix/vncconfig.cxx
+++ b/vncconfig_unix/vncconfig.cxx
@@ -1,5 +1,5 @@
-/* Copyright (C) 2002-2004 RealVNC Ltd.  All Rights Reserved.
- *    
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -38,8 +38,11 @@
 #include <rfb/Configuration.h>
 #include <rfb/Logger_stdio.h>
 #include <rfb/LogWriter.h>
+#include <rfb/Timer.h>
 #include "TXWindow.h"
 #include "TXCheckbox.h"
+#include "TXLabel.h"
+#include "QueryConnectDialog.h"
 
 using namespace rfb;
 
@@ -48,6 +51,16 @@
 StringParameter displayname("display", "The X display", "");
 BoolParameter noWindow("nowin", "Don't display a window", 0);
 BoolParameter iconic("iconic", "Start with window iconified", 0);
+BoolParameter sendPrimary("SendPrimary", "Send the PRIMARY as well as the "
+                          "CLIPBOARD selection", true);
+IntParameter pollTime("poll",
+                      "How often to poll for clipboard changes in ms", 0);
+
+inline const char* selectionName(Atom sel) {
+  if (sel == xaCLIPBOARD) return "CLIPBOARD";
+  if (sel == XA_PRIMARY) return "PRIMARY";
+  return "unknown";
+}
 
 #define ACCEPT_CUT_TEXT "AcceptCutText"
 #define SEND_CUT_TEXT "SendCutText"
@@ -67,14 +80,20 @@
 
 class VncConfigWindow : public TXWindow, public TXEventHandler,
                         public TXDeleteWindowCallback,
-                        public TXCheckboxCallback {
+                        public TXCheckboxCallback,
+                        public rfb::Timer::Callback,
+                        public QueryResultCallback {
 public:
   VncConfigWindow(Display* dpy)
-    : TXWindow(dpy, 300, 100), clientCutText(0), clientCutTextLen(0),
+    : TXWindow(dpy, 300, 100), cutText(0), cutTextLen(0),
       acceptClipboard(dpy, "Accept clipboard from viewers", this, false, this),
       sendClipboard(dpy, "Send clipboard to viewers", this, false, this),
-      sendPrimary(dpy, "Send primary selection to viewers", this, false, this)
+      sendPrimaryCB(dpy, "Send primary selection to viewers", this,false,this),
+      pollTimer(this),
+      queryConnectDialog(0)
   {
+    selection[0] = selection[1] = 0;
+    selectionLen[0] = selectionLen[1] = 0;
     int y = yPad;
     acceptClipboard.move(xPad, y);
     acceptClipboard.checked(getBoolParam(dpy, ACCEPT_CUT_TEXT));
@@ -82,14 +101,22 @@
     sendClipboard.move(xPad, y);
     sendClipboard.checked(getBoolParam(dpy, SEND_CUT_TEXT));
     y += sendClipboard.height();
-    sendPrimary.move(xPad, y);
-    sendPrimary.checked(true);
-    sendPrimary.disabled(!sendClipboard.checked());
-    y += sendPrimary.height();
+    sendPrimaryCB.move(xPad, y);
+    sendPrimaryCB.checked(sendPrimary);
+    sendPrimaryCB.disabled(!sendClipboard.checked());
+    y += sendPrimaryCB.height();
     setEventHandler(this);
     toplevel("VNC config", this, 0, 0, 0, iconic);
     XVncExtSelectInput(dpy, win(),
-                       VncExtClientCutTextMask|VncExtSelectionChangeMask);
+                       VncExtClientCutTextMask|
+                       VncExtSelectionChangeMask|
+                       VncExtQueryConnectMask);
+    XConvertSelection(dpy, XA_PRIMARY, XA_STRING,
+                      XA_PRIMARY, win(), CurrentTime);
+    XConvertSelection(dpy, xaCLIPBOARD, XA_STRING,
+                      xaCLIPBOARD, win(), CurrentTime);
+    if (pollTime != 0)
+      pollTimer.start(pollTime);
   }
 
   // handleEvent(). If we get a ClientCutTextNotify event from Xvnc, set the
@@ -101,28 +128,55 @@
     if (acceptClipboard.checked()) {
       if (ev->type == vncExtEventBase + VncExtClientCutTextNotify) {
         XVncExtClientCutTextEvent* cutEv = (XVncExtClientCutTextEvent*)ev;
-        if (clientCutText)
-          XFree(clientCutText);
-        clientCutText = 0;
-        if (XVncExtGetClientCutText(dpy, &clientCutText, &clientCutTextLen)) {
-          vlog.debug("Got client cut text");
-          XStoreBytes(dpy, clientCutText, clientCutTextLen);
+        if (cutText)
+          XFree(cutText);
+        cutText = 0;
+        if (XVncExtGetClientCutText(dpy, &cutText, &cutTextLen)) {
+          vlog.debug("Got client cut text: '%.*s%s'",
+                     cutTextLen<9?cutTextLen:8, cutText,
+                     cutTextLen<9?"":"...");
+          XStoreBytes(dpy, cutText, cutTextLen);
           ownSelection(XA_PRIMARY, cutEv->time);
           ownSelection(xaCLIPBOARD, cutEv->time);
+          delete [] selection[0];
+          delete [] selection[1];
+          selection[0] = selection[1] = 0;
+          selectionLen[0] = selectionLen[1] = 0;
         }
       }
     }
     if (sendClipboard.checked()) {
       if (ev->type == vncExtEventBase + VncExtSelectionChangeNotify) {
+        vlog.debug("selection change event");
         XVncExtSelectionChangeEvent* selEv = (XVncExtSelectionChangeEvent*)ev;
         if (selEv->selection == xaCLIPBOARD ||
-            (selEv->selection == XA_PRIMARY && sendPrimary.checked())) {
+            (selEv->selection == XA_PRIMARY && sendPrimaryCB.checked())) {
           if (!selectionOwner(selEv->selection))
             XConvertSelection(dpy, selEv->selection, XA_STRING,
                               selEv->selection, win(), CurrentTime);
         }
       }
     }
+    if (ev->type == vncExtEventBase + VncExtQueryConnectNotify) {
+       vlog.debug("query connection event");
+       if (queryConnectDialog)
+         delete queryConnectDialog;
+       queryConnectDialog = 0;
+       char* qcAddress;
+       char* qcUser;
+       int qcTimeout;
+       if (XVncExtGetQueryConnect(dpy, &qcAddress, &qcUser,
+                                  &qcTimeout, &queryConnectId)) {
+         if (qcTimeout)
+           queryConnectDialog = new QueryConnectDialog(dpy, qcAddress,
+                                                       qcUser, qcTimeout,
+                                                       this);
+         if (queryConnectDialog)
+           queryConnectDialog->map();
+         XFree(qcAddress);
+         XFree(qcUser);
+       }
+    }
   }
   
 
@@ -131,11 +185,11 @@
   // into the requested property.  TXWindow will handle the rest.
   bool selectionRequest(Window requestor, Atom selection, Atom property)
   {
-    if (clientCutText)
+    if (cutText)
       XChangeProperty(dpy, requestor, property, XA_STRING, 8,
-                      PropModeReplace, (unsigned char*)clientCutText,
-                      clientCutTextLen);
-    return clientCutText;
+                      PropModeReplace, (unsigned char*)cutText,
+                      cutTextLen);
+    return cutText;
   }
 
   // selectionNotify() is called when we have requested the selection from the
@@ -147,8 +201,26 @@
       return;
 
     if (data && format == 8) {
-      vlog.debug("setting selection as server cut text");
-      XVncExtSetServerCutText(dpy, (char*)data, nitems);
+      int i = (ev->selection == XA_PRIMARY ? 0 : 1);
+      if (selectionLen[i] == nitems && memcmp(selection[i], data, nitems) == 0)
+        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()
+      memcpy(cutText, data, nitems);
+      cutTextLen = nitems;
+      vlog.debug("sending %s selection as server cut text: '%.*s%s'",
+                 selectionName(ev->selection),cutTextLen<9?cutTextLen:8,
+                 cutText, cutTextLen<9?"":"...");
+      XVncExtSetServerCutText(dpy, cutText, cutTextLen);
     }
   }
 
@@ -165,28 +237,61 @@
     } else if (checkbox == &sendClipboard) {
       XVncExtSetParam(dpy, (sendClipboard.checked()
                             ? SEND_CUT_TEXT "=1" : SEND_CUT_TEXT "=0"));
-      sendPrimary.disabled(!sendClipboard.checked());
+      sendPrimaryCB.disabled(!sendClipboard.checked());
     }
   }
 
+  // rfb::Timer::Callback interface
+  virtual bool handleTimeout(rfb::Timer* timer) {
+    if (sendPrimaryCB.checked() && !selectionOwner(XA_PRIMARY))
+      XConvertSelection(dpy, XA_PRIMARY, XA_STRING,
+                        XA_PRIMARY, win(), CurrentTime);
+    if (!selectionOwner(xaCLIPBOARD))
+      XConvertSelection(dpy, xaCLIPBOARD, XA_STRING,
+                        xaCLIPBOARD, win(), CurrentTime);
+    return true;
+  }
+
+  // QueryResultCallback interface
+  virtual void queryApproved() {
+    XVncExtApproveConnect(dpy, queryConnectId, 1);
+  }
+  virtual void queryRejected() {
+    XVncExtApproveConnect(dpy, queryConnectId, 0);
+  }
+
 private:
-  char* clientCutText;
-  int clientCutTextLen;
-  TXCheckbox acceptClipboard, sendClipboard, sendPrimary;
+  char* cutText;
+  int cutTextLen;
+  char* selection[2];
+  int selectionLen[2];
+  TXCheckbox acceptClipboard, sendClipboard, sendPrimaryCB;
+  rfb::Timer pollTimer;
+
+  QueryConnectDialog* queryConnectDialog;
+  void* queryConnectId;
 };
 
 static void usage()
 {
-  fprintf(stderr,"usage: %s [-display <display>] [-nowin] [-iconic]\n",
+  fprintf(stderr,"usage: %s [parameters]\n",
           programName);
-  fprintf(stderr,"       %s [-display <display>] -connect <host>[:<port>]\n",
+  fprintf(stderr,"       %s [parameters] -connect <host>[:<port>]\n",
           programName);
-  fprintf(stderr,"       %s [-display <display>] -disconnect\n", programName);
-  fprintf(stderr,"       %s [-display <display>] [-set] <param>=<value> ...\n",
+  fprintf(stderr,"       %s [parameters] -disconnect\n", programName);
+  fprintf(stderr,"       %s [parameters] [-set] <Xvnc-param>=<value> ...\n",
           programName);
-  fprintf(stderr,"       %s [-display <display>] -list\n", programName);
-  fprintf(stderr,"       %s [-display <display>] -get <param>\n", programName);
-  fprintf(stderr,"       %s [-display <display>] -desc <param>\n",programName);
+  fprintf(stderr,"       %s [parameters] -list\n", programName);
+  fprintf(stderr,"       %s [parameters] -get <param>\n", programName);
+  fprintf(stderr,"       %s [parameters] -desc <param>\n",programName);
+  fprintf(stderr,"\n"
+          "Parameters can be turned on with -<param> or off with -<param>=0\n"
+          "Parameters which take a value can be specified as "
+          "-<param> <value>\n"
+          "Other valid forms are <param>=<value> -<param>=<value> "
+          "--<param>=<value>\n"
+          "Parameter names are case-insensitive.  The parameters are:\n\n");
+  Configuration::listParams(79, 14);
   exit(1);
 }
 
@@ -295,11 +400,31 @@
     if (!noWindow) w.map();
 
     while (true) {
+      struct timeval tv;
+      struct timeval* tvp = 0;
+
+      // Process any incoming X events
       TXWindow::handleXEvents(dpy);
+      
+      // Process expired timers and get the time until the next one
+      int timeoutMs = Timer::checkTimeouts();
+      if (timeoutMs) {
+        tv.tv_sec = timeoutMs / 1000;
+        tv.tv_usec = (timeoutMs % 1000) * 1000;
+        tvp = &tv;
+      }
+      
+      // If there are X requests pending then poll, don't wait!
+      if (XPending(dpy)) {
+        tv.tv_usec = tv.tv_sec = 0;
+        tvp = &tv;
+      }
+      
+      // Wait for X events, VNC traffic, or the next timer expiry
       fd_set rfds;
       FD_ZERO(&rfds);
       FD_SET(ConnectionNumber(dpy), &rfds);
-      int n = select(FD_SETSIZE, &rfds, 0, 0, 0);
+      int n = select(FD_SETSIZE, &rfds, 0, 0, tvp);
       if (n < 0) throw rdr::SystemException("select",errno);
     }
 
diff --git a/vncconfig_unix/vncconfig.man b/vncconfig_unix/vncconfig.man
index 33f7d49..e24753d 100644
--- a/vncconfig_unix/vncconfig.man
+++ b/vncconfig_unix/vncconfig.man
@@ -1,34 +1,35 @@
-.TH vncconfig 1 "30 December 2004" "TightVNC" "Virtual Network Computing"
+.TH vncconfig 1 "17 Apr 2006" "TightVNC" "Virtual Network Computing"
 .SH NAME
 vncconfig \- configure and control a VNC server
 .SH SYNOPSIS
 .B vncconfig
-[\fB\-display\fP \fIXdisplay\fP] [\fB\-nowin\fP] [\fB\-iconic\fP]
+.RI [ parameters ] 
 .br
 .B vncconfig
-[\fB\-display\fP \fIXdisplay\fP]
+.RI [ parameters ] 
 .B \-connect
 .IR host [: port ]
 .br
 .B vncconfig
-[\fB\-display\fP \fIXdisplay\fP]
+.RI [ parameters ] 
 .B \-disconnect
 .br
 .B vncconfig
-[\fB\-display\fP \fIXdisplay\fP]
-.IR param = value " ..."
+.RI [ parameters ] 
+.RB [ -set ] 
+.IR Xvnc-param = value " ..."
 .br
 .B vncconfig
-[\fB\-display\fP \fIXdisplay\fP]
+.RI [ parameters ] 
 .B \-list
 .br
 .B vncconfig
-[\fB\-display\fP \fIXdisplay\fP]
-\fB\-get\fP \fIparam\fP
+.RI [ parameters ] 
+\fB\-get\fP \fIXvnc-param\fP
 .br
 .B vncconfig
-[\fB\-display\fP \fIXdisplay\fP]
-\fB\-desc\fP \fIparam\fP
+.RI [ parameters ] 
+\fB\-desc\fP \fIXvnc-param\fP
 .SH DESCRIPTION
 .B vncconfig
 is used to configure and control a running instance of Xvnc, or any other X
@@ -57,18 +58,6 @@
 
 .SH OPTIONS
 .TP
-.B \-display \fIXdisplay\fP
-Specifies the Xvnc server to control.
-
-.TP
-.B \-nowin
-When run as a "helper" app, don't put up a window.
-
-.TP
-.B \-iconic
-When run as a "helper" app, make the window iconified at startup.
-
-.TP
 .B \-connect \fIhost\fP[:\fIport\fP]
 Tells an Xvnc server to make a "reverse" connection to a listening VNC viewer
 (normally connections are made the other way round - the viewer connects to the
@@ -82,7 +71,7 @@
 displayed anywhere.
 
 .TP
-.IR param = value
+[\fB-set\fP] \fIXvnc-param\fP=\fIvalue\fP
 Sets an Xvnc parameter to the given value.  Note that some of Xvnc's parameters
 are read only once at startup so that changing them in this way may not have
 any effect.
@@ -92,13 +81,36 @@
 Lists all the parameters supported by Xvnc.
 
 .TP
-.B \-get \fIparam\fP
+.B \-get \fIXvnc-param\fP
 Prints the current value of the given Xvnc parameter.
 
 .TP
-.B \-desc \fIparam\fP
+.B \-desc \fIXvnc-param\fP
 Prints a short description of the given Xvnc parameter.
 
+.SH PARAMETERS
+.B vncconfig
+also has parameters of its own which can be set on the command line.  These
+should not be confused with Xvnc's parameters which are manipulated with the
+\fB-set\fP, \fB-get\fP, \fB-list\fP and \fB-desc\fP options.
+
+Parameters can be turned on with -\fIparam\fP or off with -\fIparam\fP=0.
+Parameters which take a value can be specified as -\fIparam\fP \fIvalue\fP.
+Other valid forms are \fIparam\fP\fB=\fP\fIvalue\fP -\fIparam\fP=\fIvalue\fP
+--\fIparam\fP=\fIvalue\fP.  Parameter names are case-insensitive.
+
+.TP
+.B \-display \fIXdisplay\fP
+Specifies the Xvnc server to control.
+
+.TP
+.B \-nowin
+When run as a "helper" app, don't put up a window.
+
+.TP
+.B \-iconic
+When run as a "helper" app, make the window iconified at startup.
+
 .SH SEE ALSO
 .BR vncpasswd (1),
 .BR vncviewer (1),