diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/Vncviewer vnc_unixsrc/vncviewer/Vncviewer
--- vnc_unixsrc.orig/vncviewer/Vncviewer	2003-02-07 05:30:57.000000000 -0500
+++ vnc_unixsrc/vncviewer/Vncviewer	2007-02-18 19:52:59.000000000 -0500
@@ -5,9 +5,9 @@
 
 !
 ! The title of the main window.  "%s" will be replaced by the desktop name.
-! 
+!
 
-Vncviewer.title: TightVNC: %s
+Vncviewer.title: SSVNC: %s Press F8 for Menu
 
 
 !
@@ -50,6 +50,7 @@
 
 *desktop.baseTranslations:\
   <Key>F8: ShowPopup()\n\
+  <Key>F9: ToggleFullScreen()\n\
   <ButtonPress>: SendRFBEvent()\n\
   <ButtonRelease>: SendRFBEvent()\n\
   <Motion>: SendRFBEvent()\n\
@@ -77,9 +78,9 @@
 ! Popup window appearance
 !
 
-*popup.title: TightVNC popup
+*popup.title: SSVNC popup
 *popup*background: grey
-*popup*font: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-*
+*popup*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*
 *popup.buttonForm.Command.borderWidth: 0
 *popup.buttonForm.Toggle.borderWidth: 0
 
@@ -96,43 +97,154 @@
 ! Popup buttons
 !
 
-*popupButtonCount: 8
+*popupButtonCount: 27
 
 *popup*button1.label: Dismiss popup
-*popup*button1.translations: #override\n\
-  <Btn1Down>,<Btn1Up>: HidePopup()
+*popup*button1.translations: #override\\n\
+     <Btn1Down>,<Btn1Up>: HidePopup()
 
 *popup*button2.label: Quit viewer
-*popup*button2.translations: #override\n\
-  <Btn1Down>,<Btn1Up>: Quit()
+*popup*button2.translations: #override\\n\
+     <Btn1Down>,<Btn1Up>: Quit()
 
-*popup*button3.label: Full screen
+*popup*button3.label: Full screen  (also F9)
 *popup*button3.type: toggle
-*popup*button3.translations: #override\n\
-  <Visible>: SetFullScreenState()\n\
-  <Btn1Down>,<Btn1Up>: toggle() HidePopup() ToggleFullScreen()
+*popup*button3.translations: #override\\n\
+     <Visible>: SetFullScreenState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleFullScreen() HidePopup()
 
 *popup*button4.label: Clipboard: local -> remote
-*popup*button4.translations: #override\n\
-  <Btn1Down>,<Btn1Up>: SelectionToVNC(always) HidePopup()
+*popup*button4.translations: #override\\n\
+     <Btn1Down>,<Btn1Up>: SelectionToVNC(always) HidePopup()
 
 *popup*button5.label: Clipboard: local <- remote
-*popup*button5.translations: #override\n\
-  <Btn1Down>,<Btn1Up>: SelectionFromVNC(always) HidePopup()
+*popup*button5.translations: #override\\n\
+     <Btn1Down>,<Btn1Up>: SelectionFromVNC(always) HidePopup()
 
 *popup*button6.label: Request refresh
-*popup*button6.translations: #override\n\
-  <Btn1Down>,<Btn1Up>: SendRFBEvent(fbupdate) HidePopup()
+*popup*button6.translations: #override\\n\
+     <Btn1Down>,<Btn1Up>: SendRFBEvent(fbupdate) HidePopup()
 
 *popup*button7.label: Send ctrl-alt-del
-*popup*button7.translations: #override\n\
-  <Btn1Down>,<Btn1Up>: SendRFBEvent(keydown,Control_L)\
-                       SendRFBEvent(keydown,Alt_L)\
-                       SendRFBEvent(key,Delete)\
-                       SendRFBEvent(keyup,Alt_L)\
-                       SendRFBEvent(keyup,Control_L)\
-                       HidePopup()
+*popup*button7.translations: #override\\n\
+     <Btn1Down>,<Btn1Up>: SendRFBEvent(keydown,Control_L)\
+                          SendRFBEvent(keydown,Alt_L)\
+                          SendRFBEvent(key,Delete)\
+                          SendRFBEvent(keyup,Alt_L)\
+                          SendRFBEvent(keyup,Control_L)\
+                          HidePopup()
 
 *popup*button8.label: Send F8
-*popup*button8.translations: #override\n\
-  <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup()
+*popup*button8.translations: #override\\n\
+     <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup()
+
+*popup*button9.label: Send F9
+*popup*button9.translations: #override\\n\
+     <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F9) HidePopup()
+
+*popup*button10.label: ViewOnly
+*popup*button10.type: toggle
+*popup*button10.translations: #override\\n\
+     <Visible>: SetViewOnlyState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleViewOnly() HidePopup()
+
+*popup*button11.label: Cursor Shape
+*popup*button11.type: toggle
+*popup*button11.translations: #override\\n\
+     <Visible>: SetCursorShapeState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleCursorShape() HidePopup()
+
+*popup*button12.label: X11 Cursor
+*popup*button12.type: toggle
+*popup*button12.translations: #override\\n\
+     <Visible>: SetX11CursorState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleX11Cursor() HidePopup()
+
+*popup*button13.label: Cursor Alphablend
+*popup*button13.type: toggle
+*popup*button13.translations: #override\\n\
+     <Visible>: SetCursorAlphaState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleCursorAlpha() HidePopup()
+
+*popup*button14.label: Toggle Tight/ZRLE
+*popup*button14.type: toggle
+*popup*button14.translations: #override\\n\
+     <Visible>: SetZRLEState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleTightZRLE() HidePopup()
+
+*popup*button15.label: Disable JPEG
+*popup*button15.type: toggle
+*popup*button15.translations: #override\\n\
+     <Visible>: SetNOJPEGState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleJPEG() HidePopup()
+
+*popup*button16.label: Prefer raw for localhost
+*popup*button16.type: toggle
+*popup*button16.translations: #override\\n\
+     <Visible>: SetRawLocalState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleRawLocal() HidePopup()
+
+*popup*button17.label: Full Color
+*popup*button17.type: toggle
+*popup*button17.translations: #override\\n\
+     <Visible>: SetFullColorState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleFullColor() HidePopup()
+
+*popup*button18.label: Grey Scale (16 & 8-bpp)
+*popup*button18.type: toggle
+*popup*button18.translations: #override\\n\
+     <Visible>: SetGreyScaleState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleGreyScale() HidePopup()
+
+*popup*button19.label: 16 bit color (BGR565)
+*popup*button19.type: toggle
+*popup*button19.translations: #override\\n\
+     <Visible>: Set16bppState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() Toggle16bpp() HidePopup()
+
+*popup*button20.label: 8   bit color (BGR233)
+*popup*button20.type: toggle
+*popup*button20.translations: #override\\n\
+     <Visible>: Set8bppState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() Toggle8bpp() HidePopup()
+
+*popup*button21.label: -     256 colors
+*popup*button21.type: toggle
+*popup*button21.translations: #override\\n\
+     <Visible>: Set256ColorsState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() Toggle256Colors() HidePopup()
+
+*popup*button22.label: -       64 colors
+*popup*button22.type: toggle
+*popup*button22.translations: #override\\n\
+     <Visible>: Set64ColorsState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() Toggle64Colors() HidePopup()
+
+*popup*button23.label: -         8 colors
+*popup*button23.type: toggle
+*popup*button23.translations: #override\\n\
+     <Visible>: Set8ColorsState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() Toggle8Colors() HidePopup()
+
+*popup*button24.label: Disable Remote Input
+*popup*button24.type: toggle
+*popup*button24.translations: #override\\n\
+     <Visible>: SetServerInputState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleServerInput() HidePopup()
+
+*popup*button25.label: Single Window
+*popup*button25.type: toggle
+*popup*button25.translations: #override\\n\
+     <Visible>: SetSingleWindowState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleSingleWindow() HidePopup()
+
+*popup*button26.label: Set 1/n Server Scale
+*popup*button26.translations: #override\\n\
+     <Btn1Down>,<Btn1Up>: DoServerScale() HidePopup()
+
+*popup*button27.label: Text Chat
+*popup*button27.type: toggle
+*popup*button27.translations: #override\\n\
+     <Visible>: SetTextChatState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleTextChat() HidePopup()
+
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/vncviewer/argsresources.c
--- vnc_unixsrc.orig/vncviewer/argsresources.c	2007-02-04 17:10:31.000000000 -0500
+++ vnc_unixsrc/vncviewer/argsresources.c	2007-03-20 10:10:59.000000000 -0400
@@ -31,7 +31,7 @@
 
 char *fallback_resources[] = {
 
-  "Vncviewer.title: TightVNC: %s",
+  "Vncviewer.title: SSVNC: %s - Press F8 for Menu",
 
   "Vncviewer.translations:\
     <Enter>: SelectionToVNC()\\n\
@@ -45,8 +45,14 @@
   "*viewport.useRight: True",
   "*viewport*Scrollbar*thumb: None",
 
+           "*viewport.horizontal.height:   6 ",
+              "*viewport.vertical.width:   6 ",
+  "vncviewer*viewport.horizontal.height:   6 ",
+     "vncviewer*viewport.vertical.width:   6 ",
+
   "*desktop.baseTranslations:\
-     <Key>F8: ShowPopup()\\n\
+     <Key>F8:  ShowPopup()\\n\
+     <Key>F9:  ToggleFullScreen()\\n\
      <ButtonPress>: SendRFBEvent()\\n\
      <ButtonRelease>: SendRFBEvent()\\n\
      <Motion>: SendRFBEvent()\\n\
@@ -64,9 +70,10 @@
   "*passwordDialog.dialog.value.translations: #override\\n\
      <Key>Return: PasswordDialogDone()",
 
-  "*popup.title: TightVNC popup",
+  "*popup.title: SSVNC popup",
   "*popup*background: grey",
-  "*popup*font: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-*",
+  "*popup*font_old: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-*",
+  "*popup*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*",
   "*popup.buttonForm.Command.borderWidth: 0",
   "*popup.buttonForm.Toggle.borderWidth: 0",
 
@@ -74,7 +81,7 @@
   "*popup.buttonForm.translations: #override\\n\
      <KeyPress>: SendRFBEvent() HidePopup()",
 
-  "*popupButtonCount: 8",
+  "*popupButtonCount: 27",
 
   "*popup*button1.label: Dismiss popup",
   "*popup*button1.translations: #override\\n\
@@ -84,7 +91,7 @@
   "*popup*button2.translations: #override\\n\
      <Btn1Down>,<Btn1Up>: Quit()",
 
-  "*popup*button3.label: Full screen",
+  "*popup*button3.label: Full screen  (also F9)",
   "*popup*button3.type: toggle",
   "*popup*button3.translations: #override\\n\
      <Visible>: SetFullScreenState()\\n\
@@ -115,9 +122,127 @@
   "*popup*button8.translations: #override\\n\
      <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup()",
 
+  "*popup*button9.label: Send F9",
+  "*popup*button9.translations: #override\\n\
+     <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F9) HidePopup()",
+
+  "*popup*button10.label: ViewOnly",
+  "*popup*button10.type: toggle",
+  "*popup*button10.translations: #override\\n\
+     <Visible>: SetViewOnlyState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleViewOnly() HidePopup()",
+
+  "*popup*button11.label: Cursor Shape",
+  "*popup*button11.type: toggle",
+  "*popup*button11.translations: #override\\n\
+     <Visible>: SetCursorShapeState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleCursorShape() HidePopup()",
+
+  "*popup*button12.label: X11 Cursor",
+  "*popup*button12.type: toggle",
+  "*popup*button12.translations: #override\\n\
+     <Visible>: SetX11CursorState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleX11Cursor() HidePopup()",
+
+  "*popup*button13.label: Cursor Alphablend",
+  "*popup*button13.type: toggle",
+  "*popup*button13.translations: #override\\n\
+     <Visible>: SetCursorAlphaState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleCursorAlpha() HidePopup()",
+
+  "*popup*button14.label: Toggle Tight/ZRLE",
+  "*popup*button14.type: toggle",
+  "*popup*button14.translations: #override\\n\
+     <Visible>: SetZRLEState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleTightZRLE() HidePopup()",
+
+  "*popup*button15.label: Disable JPEG",
+  "*popup*button15.type: toggle",
+  "*popup*button15.translations: #override\\n\
+     <Visible>: SetNOJPEGState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleJPEG() HidePopup()",
+
+  "*popup*button16.label: Prefer raw for localhost",
+  "*popup*button16.type: toggle",
+  "*popup*button16.translations: #override\\n\
+     <Visible>: SetRawLocalState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleRawLocal() HidePopup()",
+
+  "*popup*button17.label: Full Color",
+  "*popup*button17.type: toggle",
+  "*popup*button17.translations: #override\\n\
+     <Visible>: SetFullColorState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleFullColor() HidePopup()",
+
+  "*popup*button18.label: Grey Scale (16 & 8-bpp)",
+  "*popup*button18.type: toggle",
+  "*popup*button18.translations: #override\\n\
+     <Visible>: SetGreyScaleState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleGreyScale() HidePopup()",
+
+  "*popup*button19.label: 16 bit color (BGR565)",
+  "*popup*button19.type: toggle",
+  "*popup*button19.translations: #override\\n\
+     <Visible>: Set16bppState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() Toggle16bpp() HidePopup()",
+
+  "*popup*button20.label: 8   bit color (BGR233)",
+  "*popup*button20.type: toggle",
+  "*popup*button20.translations: #override\\n\
+     <Visible>: Set8bppState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() Toggle8bpp() HidePopup()",
+
+  "*popup*button21.label: -     256 colors",
+  "*popup*button21.type: toggle",
+  "*popup*button21.translations: #override\\n\
+     <Visible>: Set256ColorsState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() Toggle256Colors() HidePopup()",
+
+  "*popup*button22.label: -       64 colors",
+  "*popup*button22.type: toggle",
+  "*popup*button22.translations: #override\\n\
+     <Visible>: Set64ColorsState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() Toggle64Colors() HidePopup()",
+
+  "*popup*button23.label: -         8 colors",
+  "*popup*button23.type: toggle",
+  "*popup*button23.translations: #override\\n\
+     <Visible>: Set8ColorsState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() Toggle8Colors() HidePopup()",
+
+  "*popup*button24.label: Disable Remote Input",
+  "*popup*button24.type: toggle",
+  "*popup*button24.translations: #override\\n\
+     <Visible>: SetServerInputState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleServerInput() HidePopup()",
+
+  "*popup*button25.label: Single Window",
+  "*popup*button25.type: toggle",
+  "*popup*button25.translations: #override\\n\
+     <Visible>: SetSingleWindowState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleSingleWindow() HidePopup()",
+
+  "*popup*button26.label: Set 1/n Server Scale",
+  "*popup*button26.translations: #override\\n\
+     <Btn1Down>,<Btn1Up>: DoServerScale() HidePopup()",
+
+  "*popup*button27.label: Text Chat",
+  "*popup*button27.type: toggle",
+  "*popup*button27.translations: #override\\n\
+     <Visible>: SetTextChatState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleTextChat() HidePopup()",
+
   NULL
 };
 
+#if 0
+  "*popup*button14.label: -     ZRLE/ZWYRLE",
+  "*popup*button14.type: toggle",
+  "*popup*button14.translations: #override\\n\
+     <Visible>: SetZRLEState()\\n\
+     <Btn1Down>,<Btn1Up>: toggle() ToggleTightZRLE() HidePopup()",
+#endif
+
 
 /*
  * vncServerHost and vncServerPort are set either from the command line or
@@ -135,6 +260,7 @@
  */
 
 AppData appData;
+AppData appDataNew;
 
 static XtResource appDataResourceList[] = {
   {"shareDesktop", "ShareDesktop", XtRBool, sizeof(Bool),
@@ -161,8 +287,20 @@
   {"encodings", "Encodings", XtRString, sizeof(String),
    XtOffsetOf(AppData, encodingsString), XtRImmediate, (XtPointer) 0},
 
-  {"useBGR233", "UseBGR233", XtRBool, sizeof(Bool),
-   XtOffsetOf(AppData, useBGR233), XtRImmediate, (XtPointer) False},
+  {"useBGR233", "UseBGR233", XtRInt, sizeof(int),
+   XtOffsetOf(AppData, useBGR233), XtRImmediate, (XtPointer) 0},
+
+  {"useBGR565", "UseBGR565", XtRBool, sizeof(Bool),
+   XtOffsetOf(AppData, useBGR565), XtRImmediate, (XtPointer) False},
+
+  {"useGreyScale", "UseGreyScale", XtRBool, sizeof(Bool),
+   XtOffsetOf(AppData, useGreyScale), XtRImmediate, (XtPointer) False},
+
+  {"yCrop", "yCrop", XtRInt, sizeof(int),
+   XtOffsetOf(AppData, yCrop), XtRImmediate, (XtPointer) 0},
+
+  {"sbWidth", "sbWidth", XtRInt, sizeof(int),
+   XtOffsetOf(AppData, sbWidth), XtRImmediate, (XtPointer) 2},
 
   {"nColours", "NColours", XtRInt, sizeof(int),
    XtOffsetOf(AppData, nColours), XtRImmediate, (XtPointer) 256},
@@ -179,7 +317,7 @@
   {"requestedDepth", "RequestedDepth", XtRInt, sizeof(int),
    XtOffsetOf(AppData, requestedDepth), XtRImmediate, (XtPointer) 0},
 
-  {"useSharedMemory", "UseSharedMemory", XtRBool, sizeof(Bool),
+  {"useShm", "UseShm", XtRBool, sizeof(Bool),
    XtOffsetOf(AppData, useShm), XtRImmediate, (XtPointer) True},
 
   {"wmDecorationWidth", "WmDecorationWidth", XtRInt, sizeof(int),
@@ -206,8 +344,13 @@
   {"bumpScrollPixels", "BumpScrollPixels", XtRInt, sizeof(int),
    XtOffsetOf(AppData, bumpScrollPixels), XtRImmediate, (XtPointer) 20},
 
+#if 0
   {"compressLevel", "CompressionLevel", XtRInt, sizeof(int),
    XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) -1},
+#endif
+
+  {"compressLevel", "CompressionLevel", XtRInt, sizeof(int),
+   XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) 7},
 
   {"qualityLevel", "QualityLevel", XtRInt, sizeof(int),
    XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) 6},
@@ -218,14 +361,49 @@
   {"useRemoteCursor", "UseRemoteCursor", XtRBool, sizeof(Bool),
    XtOffsetOf(AppData, useRemoteCursor), XtRImmediate, (XtPointer) True},
 
+  {"useCursorAlpha", "UseCursorAlpha", XtRBool, sizeof(Bool),
+   XtOffsetOf(AppData, useCursorAlpha), XtRImmediate, (XtPointer) False},
+
+  {"useRawLocal", "UseRawLocal", XtRBool, sizeof(Bool),
+   XtOffsetOf(AppData, useRawLocal), XtRImmediate, (XtPointer) False},
+
   {"useX11Cursor", "UseX11Cursor", XtRBool, sizeof(Bool),
    XtOffsetOf(AppData, useX11Cursor), XtRImmediate, (XtPointer) False},
 
   {"grabKeyboard", "GrabKeyboard", XtRBool, sizeof(Bool),
-   XtOffsetOf(AppData, grabKeyboard), XtRImmediate, (XtPointer) False},
+   XtOffsetOf(AppData, grabKeyboard), XtRImmediate, (XtPointer) True},
 
   {"autoPass", "AutoPass", XtRBool, sizeof(Bool),
-   XtOffsetOf(AppData, autoPass), XtRImmediate, (XtPointer) False}
+   XtOffsetOf(AppData, autoPass), XtRImmediate, (XtPointer) False},
+
+  {"grabAll", "GrabAll", XtRBool, sizeof(Bool),
+   XtOffsetOf(AppData, grabAll), XtRImmediate, (XtPointer) False},
+
+#if 0
+  {"useBackingstore", "UseBackingstore", XtRBool, sizeof(Bool),
+   XtOffsetOf(AppData, useBackingstore), XtRImmediate, (XtPointer) True},
+#else
+  {"useBackingstore", "UseBackingstore", XtRBool, sizeof(Bool),
+   XtOffsetOf(AppData, useBackingstore), XtRImmediate, (XtPointer) False},
+#endif
+
+  {"overrideRedir", "OverrideRedir", XtRBool, sizeof(Bool),
+   XtOffsetOf(AppData, overrideRedir), XtRImmediate, (XtPointer) True},
+
+  {"serverInput", "ServerInput", XtRBool, sizeof(Bool),
+   XtOffsetOf(AppData, serverInput), XtRImmediate, (XtPointer) True},
+
+  {"singleWindow", "SingleWindow", XtRBool, sizeof(Bool),
+   XtOffsetOf(AppData, singleWindow), XtRImmediate, (XtPointer) False},
+
+  {"serverScale", "ServerScale", XtRInt, sizeof(int),
+   XtOffsetOf(AppData, serverScale), XtRImmediate, (XtPointer) 1},
+
+  {"chatActive", "ChatActive", XtRBool, sizeof(Bool),
+   XtOffsetOf(AppData, chatActive), XtRImmediate, (XtPointer) False},
+
+  {"popupFix", "PopupFix", XtRBool, sizeof(Bool),
+   XtOffsetOf(AppData, popupFix), XtRImmediate, (XtPointer) False}
 };
 
 
@@ -243,7 +421,20 @@
   {"-passwd",        "*passwordFile",       XrmoptionSepArg, 0},
   {"-user",          "*userLogin",          XrmoptionSepArg, 0},
   {"-encodings",     "*encodings",          XrmoptionSepArg, 0},
-  {"-bgr233",        "*useBGR233",          XrmoptionNoArg,  "True"},
+  {"-bgr233",        "*useBGR233",          XrmoptionNoArg,  "256"},
+  {"-use64",         "*useBGR233",          XrmoptionNoArg,   "64"},
+  {"-bgr222",        "*useBGR233",          XrmoptionNoArg,   "64"},
+  {"-use8",          "*useBGR233",          XrmoptionNoArg,    "8"},
+  {"-bgr111",        "*useBGR233",          XrmoptionNoArg,    "8"},
+  {"-16bpp",         "*useBGR565",          XrmoptionNoArg,  "True"},
+  {"-bgr565",        "*useBGR565",          XrmoptionNoArg,  "True"},
+  {"-grey",          "*useGreyScale",       XrmoptionNoArg,  "True"},
+  {"-gray",          "*useGreyScale",       XrmoptionNoArg,  "True"},
+  {"-sbwidth",       "*sbwidth",            XrmoptionSepArg, 0},
+  {"-ycrop",         "*yCrop",              XrmoptionSepArg, 0},
+  {"-sbwidth",       "*sbwidth",            XrmoptionSepArg, 0},
+  {"-rawlocal",      "*useRawLocal",        XrmoptionNoArg,  "True"},
+  {"-alpha",         "*useCursorAlpha",     XrmoptionNoArg,  "True"},
   {"-owncmap",       "*forceOwnCmap",       XrmoptionNoArg,  "True"},
   {"-truecolor",     "*forceTrueColour",    XrmoptionNoArg,  "True"},
   {"-truecolour",    "*forceTrueColour",    XrmoptionNoArg,  "True"},
@@ -253,7 +444,17 @@
   {"-nojpeg",        "*enableJPEG",         XrmoptionNoArg,  "False"},
   {"-nocursorshape", "*useRemoteCursor",    XrmoptionNoArg,  "False"},
   {"-x11cursor",     "*useX11Cursor",       XrmoptionNoArg,  "True"},
-  {"-autopass",      "*autoPass",           XrmoptionNoArg,  "True"}
+  {"-autopass",      "*autoPass",           XrmoptionNoArg,  "True"},
+  {"-graball",       "*grabAll",            XrmoptionNoArg,  "True"},
+  {"-grabkbd",       "*grabKeyboard",       XrmoptionNoArg,  "True"},
+  {"-nograbkbd",     "*grabKeyboard",       XrmoptionNoArg,  "False"},
+  {"-grabkeyboard",  "*grabKeyboard",       XrmoptionNoArg,  "True"},
+  {"-nograbkeyboard","*grabKeyboard",       XrmoptionNoArg,  "False"},
+  {"-nooverride",    "*overrideRedir",      XrmoptionNoArg,  "False"},
+  {"-bs",            "*useBackingstore",    XrmoptionNoArg,  "True"},
+  {"-nobs",          "*useBackingstore",    XrmoptionNoArg,  "False"},
+  {"-popupfix",      "*popupFix",           XrmoptionNoArg,  "True"},
+  {"-noshm",         "*useShm",             XrmoptionNoArg,  "False"}
 
 };
 
@@ -277,6 +478,41 @@
     {"Pause", Pause},
     {"RunCommand", RunCommand},
     {"Quit", Quit},
+    {"Toggle8bpp", Toggle8bpp},
+    {"Toggle16bpp", Toggle16bpp},
+    {"ToggleFullColor", ToggleFullColor},
+    {"Toggle256Colors", Toggle256Colors},
+    {"Toggle64Colors", Toggle64Colors},
+    {"Toggle8Colors", Toggle8Colors},
+    {"ToggleGreyScale", ToggleGreyScale},
+    {"ToggleTightZRLE", ToggleTightZRLE},
+    {"ToggleViewOnly", ToggleViewOnly},
+    {"ToggleJPEG", ToggleJPEG},
+    {"ToggleCursorShape", ToggleCursorShape},
+    {"ToggleCursorAlpha", ToggleCursorAlpha},
+    {"ToggleX11Cursor", ToggleX11Cursor},
+    {"ToggleRawLocal", ToggleRawLocal},
+    {"ToggleServerInput", ToggleServerInput},
+    {"ToggleSingleWindow", ToggleSingleWindow},
+    {"ToggleTextChat", ToggleTextChat},
+    {"DoServerScale", DoServerScale},
+    {"Set8bppState", Set8bppState},
+    {"Set16bppState", Set16bppState},
+    {"SetFullColorState", SetFullColorState},
+    {"Set256ColorsState", Set256ColorsState},
+    {"Set64ColorsState", Set64ColorsState},
+    {"Set8ColorsState", Set8ColorsState},
+    {"SetGreyScaleState", SetGreyScaleState},
+    {"SetZRLEState", SetZRLEState},
+    {"SetNOJPEGState", SetNOJPEGState},
+    {"SetViewOnlyState", SetViewOnlyState},
+    {"SetCursorShapeState", SetCursorShapeState},
+    {"SetCursorAlphaState", SetCursorAlphaState},
+    {"SetX11CursorState", SetX11CursorState},
+    {"SetRawLocalState", SetRawLocalState},
+    {"SetServerInputState", SetServerInputState},
+    {"SetSingleWindowState", SetSingleWindowState},
+    {"SetTextChatState", SetTextChatState},
 };
 
 
@@ -302,8 +538,8 @@
 void
 usage(void)
 {
-  fprintf(stderr,
-	  "TightVNC viewer version 1.3dev7\n"
+  fprintf(stdout,
+	  "TightVNC viewer version 1.3dev7 (SSVNC)\n"
 	  "\n"
 	  "Usage: %s [<OPTIONS>] [<HOST>][:<DISPLAY#>]\n"
 	  "       %s [<OPTIONS>] [<HOST>][::<PORT#>]\n"
@@ -332,10 +568,110 @@
 	  "        -autopass\n"
 	  "\n"
 	  "Option names may be abbreviated, e.g. -bgr instead of -bgr233.\n"
-	  "See the manual page for more information."
+	  "See the manual page for more information.\n"
+	  "\n"
+	  "\n"
+	  "Enhanced TightVNC viewer (SSVNC) options:\n"
+	  "\n"
+	  "   URL http://www.karlrunge.com/x11vnc/ssvnc.html\n"
+	  "\n"
+	  "   Note: ZRLE encoding is now supported.\n"
+	  "\n"
+	  "   Note: F9 is shortcut to Toggle FullScreen mode.\n"
+	  "\n"
+	  "        -use64      In -bgr233 mode, use 64 colors instead of 256.\n"
+	  "        -bgr222     Same as -use64.\n"
+	  "\n"
+	  "        -use8       In -bgr233 mode, use 8 colors instead of 256.\n"
+	  "        -bgr111     Same as -use8.\n"
+	  "\n"
+	  "        -16bpp      If the vnc viewer X display is depth 24 at 32bpp\n"
+	  "                    request a 16bpp format from the VNC server to cut\n"
+	  "                    network traffic by up to 2X, then tranlate the\n"
+	  "                    pixels to 32bpp locally.\n"
+	  "        -bgr565     Same as -16bpp.\n"
+	  "\n"
+	  "        -grey       Use a grey scale for the 16- and 8-bpp modes.\n"
+	  "\n"
+	  "        -alpha      Use alphablending transparency for local cursors\n"
+	  "                    requires: x11vnc server, both client and server\n"
+          "                    must be 32bpp and same endianness.\n"
+	  "\n"
+	  "        -ycrop n    Only show the top n rows of the framebuffer.  For\n"
+	  "                    use with x11vnc -ncache client caching option\n"
+	  "                    to help \"hide\" the pixel cache region.\n"
+	  "                    Use a negative value (e.g. -1) for autodetection.\n"
+	  "                    Autodetection will always take place if the remote\n"
+	  "                    fb height is more than 2 times the width.\n"
+	  "\n"
+	  "        -sbwidth n  Scrollbar width for x11vnc -ncache mode (-ycrop),\n"
+          "                    default is very narrow: 2 pixels, it is narrow to\n"
+          "                    avoid distraction in -ycrop mode.\n"
+	  "\n"
+	  "        -rawlocal   Prefer raw encoding for localhost, default is\n"
+	  "                    no, i.e. assumes you have a SSH tunnel instead.\n"
+	  "\n"
+	  "        -graball    Grab the entire X server when in fullscreen mode,\n"
+	  "                    needed by some old window managers like fvwm2.\n"
+	  "        -popupfix   Warp the popup back to the pointer position,\n"
+	  "                    needed by some old window managers like fvwm2.\n"
+	  "\n"
+	  "        -grabkbd    Grab the X keyboard when in fullscreen mode,\n"
+	  "                    needed by some window managers. Same as -grabkeyboard.\n"
+	  "                    -grabkbd is the default, use -nograbkbd to disable.\n"
+	  "\n"
+	  "        -bs, -nobs  Whether or not to use X server Backingstore for the\n"
+	  "                    main viewer window.  The default is to not, mainly\n"
+	  "                    because most Linux, etc, systems X servers disable\n"
+	  "                    *all* Backingstore by default.  To re-enable it put\n"
+	  "\n"
+	  "                        Option \"Backingstore\"\n"
+	  "\n"
+	  "                    in the Device section of /etc/X11/xorg.conf.\n"
+	  "                    In -bs mode with no X server backingstore, whenever an\n"
+	  "                    area of the screen is re-exposed it must go out to the\n"
+	  "                    VNC server to retrieve the pixels. This is too slow.\n"
+	  "\n"
+	  "                    In -nobs mode, memory is allocated by the viewer to\n"
+	  "                    provide its own backing of the main viewer window. This\n"
+	  "                    actually makes some activities faster (changes in large\n"
+	  "                    regions) but can appear to \"flash\" too much.\n"
+	  "\n"
+	  "        -noshm      Disable use of MIT shared memory extension (not recommended)\n"
+	  "\n"
+	  "   New Popup actions:\n"
+	  "\n"
+	  "        Cursor Shape:            ~ -nocursorshape\n"
+	  "        X11 Cursor:              ~ -x11cursor\n"
+	  "        Cursor Alphablend:       ~ -alpha\n"
+	  "        Disable JPEG:            ~ -nojpeg\n"
+	  "        Prefer raw for localhost ~ -rawlocal\n"
+	  "        Full Color                 as many colors as local screen allows.\n"
+	  "        Grey scale (16 & 8-bpp)  ~ -grey, for low colors 16/8bpp modes only.\n"
+	  "        16 bit color (BGR565)    ~ -16bpp / -bgr565\n"
+	  "        8  bit color (BGR233)    ~ -bgr233\n"
+	  "        256 colors               ~ -bgr233 default # of colors.\n"
+	  "         64 colors               ~ -bgr222 / -use64\n"
+	  "          8 colors               ~ -bgr111 / -use8\n"
+	  "\n"
+	  "        Disable Remote Input       Ultravnc ext. Try to prevent input and\n"
+	  "                                   viewing of monitor at physical display.\n"
+	  "        Single Window              Ultravnc ext. Grab and view a single window.\n"
+	  "                                   (click on the window you want).\n"
+	  "        Set 1/n Server Scale       Ultravnc ext. Scale desktop by 1/n.\n"
+	  "                                   prompt is from the terminal.\n"
+	  "        Text Chat                  Ultravnc ext. Do Text Chat, currently\n"
+	  "                                   input via the terminal (no window).\n"
+	  "\n"
+	  "        Note: the Ultravnc extensions only apply to servers that support\n"
+	  "              them.  x11vnc/libvncserver supports some of them.\n"
+	  "\n"
 	  "\n", programName, programName, programName, programName);
   exit(1);
 }
+#if 0
+	  "        -nooverride Do not apply OverrideRedirect in fullscreen mode.\n"
+#endif
 
 
 /*
@@ -357,6 +693,23 @@
   XtGetApplicationResources(toplevel, &appData, appDataResourceList,
 			    XtNumber(appDataResourceList), 0, 0);
 
+	if (getenv("VNCVIEWER_ALPHABLEND")) {
+		appData.useCursorAlpha = True;
+	}
+	if (getenv("VNCVIEWER_POPUP_FIX")) {
+		appData.popupFix = True;
+	}
+	if (getenv("VNCVIEWER_GRAB_SERVER")) {
+		appData.grabAll = True;
+	}
+	if (getenv("VNCVIEWER_YCROP")) {
+		int n = atoi(getenv("VNCVIEWER_YCROP"));
+		if (n != 0) {
+			appData.yCrop = n;
+		}
+	}
+
+
   /* Add our actions to the actions table so they can be used in widget
      resource specs */
 
@@ -376,6 +729,10 @@
     return;
   }
 
+	if (appData.useBGR233 && appData.useBGR565) {
+		appData.useBGR233 = 0;
+	}
+
   if (argc == 1) {
     vncServerName = DoServerDialog();
     appData.passwordDialog = True;
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewer/colour.c
--- vnc_unixsrc.orig/vncviewer/colour.c	2002-04-30 09:07:31.000000000 -0400
+++ vnc_unixsrc/vncviewer/colour.c	2007-03-22 21:36:12.000000000 -0400
@@ -31,9 +31,12 @@
 #define BGR233_SIZE 256
 unsigned long BGR233ToPixel[BGR233_SIZE];
 
+#define BGR565_SIZE 65536
+unsigned long BGR565ToPixel[BGR565_SIZE];
+
 Colormap cmap;
 Visual *vis;
-unsigned int visdepth, visbpp;
+unsigned int visdepth, visbpp, isLSB;
 Bool allocColorFailed = False;
 
 static int nBGR233ColoursAllocated;
@@ -45,6 +48,8 @@
 static void AllocateExactBGR233Colours();
 static Bool AllocateBGR233Colour(int r, int g, int b);
 
+static void SetupBGR565Map();
+
 
 /*
  * SetVisualAndCmap() deals with the wonderful world of X "visuals" (which are
@@ -97,6 +102,44 @@
   visbpp = GetBPPForDepth(visdepth);
   cmap = DefaultColormap(dpy,DefaultScreen(dpy));
 
+  if (ImageByteOrder(dpy) == LSBFirst) {
+  	isLSB = 1;
+  } else {
+  	isLSB = 0;
+  }
+  if (visbpp == 24) {
+  	if (!appData.useBGR233) {
+  		fprintf(stderr, "Warning: for 24bpp enabling -bgr565 -- Don't use FullColor!\n"); 
+  		appData.useBGR565 = True;
+  	} else {
+  		fprintf(stderr, "Warning: for 24bpp using -bgr233 -- Don't use FullColor!\n"); 
+  	}
+  }
+
+  if (appData.useBGR565) {
+  	if (visdepth < 24 || visbpp < 24 || vis->class != TrueColor) {
+  		fprintf(stderr, "disabling -16bpp BGR565 on non-depth 24 machine\n"); 
+		appData.useBGR565 = False;
+  	} else {
+		myFormat.bitsPerPixel = 16;
+		myFormat.depth = 16;
+		myFormat.trueColour = 1;
+		myFormat.bigEndian = 0;
+		myFormat.redMax   = 31;
+		myFormat.greenMax = 63;
+		myFormat.blueMax  = 31;
+		myFormat.redShift   = 11;
+		myFormat.greenShift = 5;
+		myFormat.blueShift  = 0;
+
+		fprintf(stderr, "Using default colormap and translating from BGR565 (65536 colors).  Pixel format:\n");
+		PrintPixelFormat(&myFormat);
+
+		SetupBGR565Map();
+		return;
+  	}
+  }
+
   if (!appData.useBGR233 && (vis->class == TrueColor)) {
 
     myFormat.bitsPerPixel = visbpp;
@@ -116,21 +159,42 @@
     return;
   }
 
-  appData.useBGR233 = True;
+  if (appData.useBGR233 == 0) {
+	appData.useBGR233 = 256;
+  }
 
   myFormat.bitsPerPixel = 8;
   myFormat.depth = 8;
   myFormat.trueColour = 1;
   myFormat.bigEndian = 0;
-  myFormat.redMax = 7;
+  myFormat.redMax   = 7;
   myFormat.greenMax = 7;
-  myFormat.blueMax = 3;
-  myFormat.redShift = 0;
+  myFormat.blueMax  = 3;
+  myFormat.redShift   = 0;
   myFormat.greenShift = 3;
-  myFormat.blueShift = 6;
+  myFormat.blueShift  = 6;
+
+	if (appData.useBGR233 == 64) {
+		/* BGR222 */
+		myFormat.redMax   = 3;
+		myFormat.greenMax = 3;
+		myFormat.blueMax  = 3;
+		myFormat.redShift   = 0;
+		myFormat.greenShift = 2;
+		myFormat.blueShift  = 4;
+	}
+	if (appData.useBGR233 == 8) {
+		/* BGR111 */
+		myFormat.redMax   = 2;
+		myFormat.greenMax = 2;
+		myFormat.blueMax  = 2;
+		myFormat.redShift   = 0;
+		myFormat.greenShift = 1;
+		myFormat.blueShift  = 2;
+	}
 
   fprintf(stderr,
-       "Using default colormap and translating from BGR233.  Pixel format:\n");
+       "Using default colormap and translating from BGR233 (%d colors).  Pixel format:\n", appData.useBGR233);
   PrintPixelFormat(&myFormat);
 
   SetupBGR233Map();
@@ -282,8 +346,12 @@
   XFree(format);
 
   if (bpp != 1 && bpp != 8 && bpp != 16 && bpp != 32) {
-    fprintf(stderr,"Can't cope with %d bits-per-pixel.  Sorry.\n", bpp);
-    exit(1);
+	if (bpp == 24) {
+		fprintf(stderr,"Warning: 24 bits-per-pixel may have problems...\n");
+	} else {
+		fprintf(stderr,"Can't cope with %d bits-per-pixel.  Sorry.\n", bpp);
+		exit(1);
+	}
   }
 
   return bpp;
@@ -394,16 +462,43 @@
     for (r = 0; r < 8; r++) {
       for (g = 0; g < 8; g++) {
 	for (b = 0; b < 4; b++) {
-	  if (BGR233ToPixel[(b<<6) | (g<<3) | r] == INVALID_PIXEL) {
+		int bs = 6, gs = 3, rs = 0;
+		int bm = 3, gm = 7, rm = 7;
+		if (appData.useBGR233 == 64) {
+			bs = 4; gs = 2; rs = 0;
+			bm = 3; gm = 3; rm = 3;
+		}
+		if (appData.useBGR233 == 8) {
+			bs = 2; gs = 1; rs = 0;
+			bm = 1; gm = 1; rm = 1;
+		}
+		if ((b > bm || g > gm || r > rm)) {
+			continue;
+		}
+	  if (BGR233ToPixel[(b<<bs) | (g<<gs) | (r<<rs)] == INVALID_PIXEL) {
 
 	    unsigned long minDistance = ULONG_MAX;
 
 	    for (i = 0; i < cmapSize; i++) {
 	      if (exactBGR233[i] || shared[i]) {
-		unsigned long distance
-		  = (abs(cmapEntry[i].red - r * 65535 / 7)
-		     + abs(cmapEntry[i].green - g * 65535 / 7)
-		     + abs(cmapEntry[i].blue - b * 65535 / 3));
+		unsigned long distance;
+		int r1, g1, b1;
+		if (appData.useGreyScale) {
+			int ave;
+			ave = (r + g + 2*b)/3;
+			r1 = ave;
+			g1 = ave;
+			b1 = ave/2;
+		} else {
+			r1 = r;
+			g1 = g;
+			b1 = b;
+		}
+		distance
+		  = (  abs(cmapEntry[i].red   - r1 * 65535 / rm)
+		     + abs(cmapEntry[i].green - g1 * 65535 / gm)
+		     + abs(cmapEntry[i].blue  - b1 * 65535 / bm));
+
 
 		if (distance < minDistance) {
 		  minDistance = distance;
@@ -412,7 +507,7 @@
 	      }
 	    }
 
-	    BGR233ToPixel[(b<<6) | (g<<3) | r] = nearestPixel;
+	    BGR233ToPixel[(b<<bs) | (g<<gs) | (r<<rs)] = nearestPixel;
 	    if (shared[nearestPixel] && !usedAsNearest[nearestPixel])
 	      nSharedUsed++;
 	    usedAsNearest[nearestPixel] = True;
@@ -433,6 +528,53 @@
   }
 }
 
+static void
+SetupBGR565Map()
+{
+  int r, g, b;
+  int r2, g2, b2;
+  long i, idx;
+  int cnt = 0;
+  unsigned long pixel = 0;
+
+    for (r = 0; r < 32; r++) {
+      for (g = 0; g < 64; g++) {
+	for (b = 0; b < 32; b++) {
+		int bs = 0, gs = 5, rs = 11;
+		int bm = 31, gm = 63, rm = 31;
+		if ((b > bm || g > gm || r > rm)) {
+			continue;
+		}
+		r2 = (255 * r) / rm;
+		g2 = (255 * g) / gm;
+		b2 = (255 * b) / bm;
+
+		pixel = (r2 << 16) | (g2 << 8) | (b2 << 0);
+		if (appData.useGreyScale) {
+			int ave;
+			int r1, g1, b1;
+			ave = (2*r + g + 2*b)/3;
+			r1 = ave/2;
+			g1 = ave;
+			b1 = ave/2;
+
+			r2 = (255 * r1) / rm;
+			g2 = (255 * g1) / gm;
+			b2 = (255 * b1) / bm;
+
+			pixel = (r2 << 16) | (g2 << 8) | (b2 << 0);
+		}
+
+		idx = (b<<bs) | (g<<gs) | (r<<rs);
+		if (0) fprintf(stderr, "cnt: %5d idx: %5d pixel: 0x%08x\n", cnt, idx, pixel);
+		BGR565ToPixel[idx] = pixel;
+		cnt++;
+	}
+      }
+    }
+}
+
+
 
 /*
  * AllocateExactBGR233Colours() attempts to allocate each of the colours in the
@@ -484,8 +626,13 @@
     ri = rn;
     for (gi = 0; gi < gn; gi++) {
       for (bi = 0; bi < bn; bi++) {
-	if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi]))
-	  return;
+	if (appData.useBGR233 == 64 && (bv[bi] > 3 || gv[gi] > 3 || rv[ri] > 3)) {
+		nBGR233ColoursAllocated++;
+	} else if (appData.useBGR233 == 8 && (bv[bi] > 1 || gv[gi] > 1 || rv[ri] > 1)) {
+		nBGR233ColoursAllocated++;
+	} else if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) {
+		return;
+	}
       }
     }
     rn++;
@@ -496,8 +643,13 @@
     gi = gn;
     for (ri = 0; ri < rn; ri++) {
       for (bi = 0; bi < bn; bi++) {
-	if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi]))
-	  return;
+	if (appData.useBGR233 == 64 && (bv[bi] > 3 || gv[gi] > 3 || rv[ri] > 3)) {
+		nBGR233ColoursAllocated++;
+	} else if (appData.useBGR233 == 8 && (bv[bi] > 1 || gv[gi] > 1 || rv[ri] > 1)) {
+		nBGR233ColoursAllocated++;
+	} else if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) {
+	  	return;
+	}
       }
     }
     gn++;
@@ -507,8 +659,13 @@
       bi = bn;
       for (ri = 0; ri < rn; ri++) {
 	for (gi = 0; gi < gn; gi++) {
-	  if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi]))
-	    return;
+	  if (appData.useBGR233 == 64 && (bv[bi] > 3 || gv[gi] > 3 || rv[ri] > 3)) {
+		nBGR233ColoursAllocated++;
+	  } else if (appData.useBGR233 == 8 && (bv[bi] > 1 || gv[gi] > 1 || rv[ri] > 1)) {
+		nBGR233ColoursAllocated++;
+	  } else if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) {
+	    	return;
+	  }
 	}
       }
       bn++;
@@ -529,18 +686,36 @@
 AllocateBGR233Colour(int r, int g, int b)
 {
   XColor c;
+	int bs = 6, gs = 3, rs = 0;
+	int bm = 3, gm = 7, rm = 7;
 
   if (nBGR233ColoursAllocated >= appData.nColours)
     return False;
 
-  c.red = r * 65535 / 7;
-  c.green = g * 65535 / 7;
-  c.blue = b * 65535 / 3;
+	if (appData.useBGR233 == 64) {
+		bs = 4; gs = 2, rs = 0;
+		bm = 3; gm = 3; rm = 3;
+	}
+	if (appData.useBGR233 == 8) {
+		bs = 2; gs = 1, rs = 0;
+		bm = 1; gm = 1; rm = 1;
+	}
+
+	c.red =   r * 65535 / rm;
+	c.green = g * 65535 / gm;
+	c.blue =  b * 65535 / bm;
+	if (appData.useGreyScale) {
+		int ave;
+		ave = (c.red + c.green + c.blue)/3;
+		c.red   = ave;
+		c.green = ave;
+		c.blue  = ave;
+	}
 
   if (!XAllocColor(dpy, cmap, &c))
     return False;
 
-  BGR233ToPixel[(b<<6) | (g<<3) | r] = c.pixel;
+  BGR233ToPixel[(b<<bs) | (g<<gs) | r] = c.pixel;
 
   nBGR233ColoursAllocated++;
 
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/corre.c vnc_unixsrc/vncviewer/corre.c
--- vnc_unixsrc.orig/vncviewer/corre.c	2000-06-11 08:00:53.000000000 -0400
+++ vnc_unixsrc/vncviewer/corre.c	2007-02-17 22:50:15.000000000 -0500
@@ -29,6 +29,18 @@
 #define HandleCoRREBPP CONCAT2E(HandleCoRRE,BPP)
 #define CARDBPP CONCAT2E(CARD,BPP)
 
+#define FillRectangle(x, y, w, h, color)  \
+	{ \
+		XGCValues _gcv; \
+		_gcv.foreground = color; \
+		if (!appData.useBackingstore) { \
+			FillScreen(x, y, w, h, _gcv.foreground); \
+		} else { \
+			XChangeGC(dpy, gc, GCForeground, &_gcv); \
+			XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \
+		} \
+	}
+
 static Bool
 HandleCoRREBPP (int rx, int ry, int rw, int rh)
 {
@@ -50,11 +62,19 @@
 #if (BPP == 8)
     gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix);
 #else
+#if (BPP == 16)
+    gcv.foreground = (appData.useBGR565 ? BGR565ToPixel[pix] : pix);
+#else
     gcv.foreground = pix;
 #endif
+#endif
 
+#if 0
     XChangeGC(dpy, gc, GCForeground, &gcv);
     XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
+#else
+    FillRectangle(rx, ry, rw, rh, gcv.foreground);
+#endif
 
     if (!ReadFromRFBServer(buffer, hdr.nSubrects * (4 + (BPP / 8))))
 	return False;
@@ -72,12 +92,22 @@
 #if (BPP == 8)
 	gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix);
 #else
+#if (BPP == 16)
+	gcv.foreground = (appData.useBGR565 ? BGR565ToPixel[pix] : pix);
+#else
 	gcv.foreground = pix;
 #endif
+#endif
 
+#if 0
 	XChangeGC(dpy, gc, GCForeground, &gcv);
 	XFillRectangle(dpy, desktopWin, gc, rx + x, ry + y, w, h);
+#else
+	FillRectangle(rx + x, ry + y, w, h, gcv.foreground);
+#endif
     }
 
     return True;
 }
+
+#undef FillRectangle
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cp_it vnc_unixsrc/vncviewer/cp_it
--- vnc_unixsrc.orig/vncviewer/cp_it	1969-12-31 19:00:00.000000000 -0500
+++ vnc_unixsrc/vncviewer/cp_it	2007-03-24 10:05:16.000000000 -0400
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+dest=/dist/bin/vncviewerz-1.3dev5-resize
+suc "cp -p $dest $dest.back; mv $dest $dest.unlink; mv $dest.back $dest; rm $dest.unlink"
+strip ./vncviewer
+cat ./vncviewer > $dest
+touch -r ./vncviewer $dest 
+yy=/dist/src/apps/VNC/etc/libvncserver_cvs/expts/etv/ssvnc/bin/Linux.i686/vncviewer
+mv $yy $yy.unlink
+cp -p ./vncviewer $yy
+cp -p ./vncviewer $HOME/etv_col/Linux.i686
+chmod 755 $yy
+rm -f $yy.unlink
+ls -l ./vncviewer $dest $yy $HOME/etv_col/Linux.i686/vncviewer
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewer/cursor.c
--- vnc_unixsrc.orig/vncviewer/cursor.c	2003-01-15 04:46:52.000000000 -0500
+++ vnc_unixsrc/vncviewer/cursor.c	2007-03-17 22:48:34.000000000 -0400
@@ -39,7 +39,7 @@
 
 static Bool prevSoftCursorSet = False;
 static Pixmap rcSavedArea;
-static CARD8 *rcSource, *rcMask;
+static CARD8 *rcSource = NULL, *rcMask;
 static int rcHotX, rcHotY, rcWidth, rcHeight;
 static int rcCursorX = 0, rcCursorY = 0;
 static int rcLockX, rcLockY, rcLockWidth, rcLockHeight;
@@ -48,8 +48,8 @@
 static Bool SoftCursorInLockedArea(void);
 static void SoftCursorCopyArea(int oper);
 static void SoftCursorDraw(void);
-static void FreeSoftCursor(void);
-static void FreeX11Cursor();
+void FreeSoftCursor(void);
+void FreeX11Cursor();
 
 /* Copied from Xvnc/lib/font/util/utilbitmap.c */
 static unsigned char _reverse_byte[0x100] = {
@@ -195,6 +195,7 @@
   buf = malloc(bytesMaskData);
   if (buf == NULL) {
     free(rcSource);
+    rcSource = NULL;
     return False;
   }
 
@@ -209,6 +210,7 @@
     /* Read and convert background and foreground colors. */
     if (!ReadFromRFBServer((char *)&rgb, sz_rfbXCursorColors)) {
       free(rcSource);
+      rcSource = NULL;
       free(buf);
       return False;
     }
@@ -218,6 +220,7 @@
     /* Read 1bpp pixel data into a temporary buffer. */
     if (!ReadFromRFBServer(buf, bytesMaskData)) {
       free(rcSource);
+      rcSource = NULL;
       free(buf);
       return False;
     }
@@ -257,6 +260,7 @@
 
     if (!ReadFromRFBServer((char *)rcSource, width * height * bytesPerPixel)) {
       free(rcSource);
+      rcSource = NULL;
       free(buf);
       return False;
     }
@@ -267,6 +271,7 @@
 
   if (!ReadFromRFBServer(buf, bytesMaskData)) {
     free(rcSource);
+    rcSource = NULL;
     free(buf);
     return False;
   }
@@ -274,6 +279,7 @@
   rcMask = malloc(width * height);
   if (rcMask == NULL) {
     free(rcSource);
+    rcSource = NULL;
     free(buf);
     return False;
   }
@@ -429,41 +435,63 @@
 	  rcLockY + rcLockHeight > rcCursorY - rcHotY);
 }
 
+extern XImage *image;
+
 static void SoftCursorCopyArea(int oper)
 {
-  int x, y, w, h;
+	int x, y, w, h;
 
-  x = rcCursorX - rcHotX;
-  y = rcCursorY - rcHotY;
-  if (x >= si.framebufferWidth || y >= si.framebufferHeight)
-    return;
+	x = rcCursorX - rcHotX;
+	y = rcCursorY - rcHotY;
+	if (x >= si.framebufferWidth || y >= si.framebufferHeight) {
+		return;
+	}
 
-  w = rcWidth;
-  h = rcHeight;
-  if (x < 0) {
-    w += x;
-    x = 0;
-  } else if (x + w > si.framebufferWidth) {
-    w = si.framebufferWidth - x;
-  }
-  if (y < 0) {
-    h += y;
-    y = 0;
-  } else if (y + h > si.framebufferHeight) {
-    h = si.framebufferHeight - y;
-  }
+	w = rcWidth;
+	h = rcHeight;
+	if (x < 0) {
+		w += x;
+		x = 0;
+	} else if (x + w > si.framebufferWidth) {
+		w = si.framebufferWidth - x;
+	}
+	if (y < 0) {
+		h += y;
+		y = 0;
+	} else if (y + h > si.framebufferHeight) {
+		h = si.framebufferHeight - y;
+	}
 
-  if (oper == OPER_SAVE) {
-    /* Save screen area in memory. */
+	if (oper == OPER_SAVE) {
+		/* Save screen area in memory. */
+//fprintf(stderr, "OPER_SAVE\n");
+#if 0
 #ifdef MITSHM
-    if (appData.useShm)
-      XSync(dpy, False);
+		if (appData.useShm) {
+			XSync(dpy, False);
+		} else 
 #endif
-    XCopyArea(dpy, desktopWin, rcSavedArea, gc, x, y, w, h, 0, 0);
-  } else {
-    /* Restore screen area. */
-    XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y);
-  }
+		{
+			XSync(dpy, False);
+		}
+#endif
+		if (appData.useBackingstore) {
+			XSync(dpy, False);
+			XCopyArea(dpy, desktopWin, rcSavedArea, gc, x, y, w, h, 0, 0);
+		} else {
+			XPutImage(dpy, rcSavedArea, gc, image, x, y, 0, 0, w, h);
+		}
+	} else {
+//fprintf(stderr, "OPER_RESTORE\n");
+		/* Restore screen area. */
+		if (appData.useBackingstore) {
+			XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y);
+			XGetSubImage(dpy, rcSavedArea, 0, 0, w, h, AllPlanes, ZPixmap, image, x, y);
+		} else {
+			XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y);
+			XGetSubImage(dpy, rcSavedArea, 0, 0, w, h, AllPlanes, ZPixmap, image, x, y);
+		}
+	}
 }
 
 static void SoftCursorDraw(void)
@@ -472,6 +500,139 @@
   int offset, bytesPerPixel;
   char *pos;
 
+#define alphahack
+#ifdef alphahack
+  /* hack to have cursor transparency at 32bpp <runge@karlrunge.com> */
+  int alphablend = 0;
+
+  if (!rcSource) {
+  	return;
+  }
+
+  if (appData.useCursorAlpha) {
+  	alphablend = 1;
+  }
+
+  bytesPerPixel = myFormat.bitsPerPixel / 8;
+
+  if (alphablend && bytesPerPixel == 4) {
+	unsigned long pixel, put, *upos, *upix;
+	int got_alpha = 0, rsX, rsY, rsW, rsH;
+	static XImage *alpha_image = NULL;
+	static int iwidth = 128;
+
+	if (! alpha_image) {
+		/* watch out for tiny fb (rare) */
+		if (iwidth > si.framebufferWidth) {
+			iwidth = si.framebufferWidth;
+		}
+		if (iwidth > si.framebufferHeight) {
+			iwidth = si.framebufferHeight;
+		}
+
+		/* initialize an XImage with a chunk of desktopWin */
+		alpha_image = XGetImage(dpy, desktopWin, 0, 0, iwidth, iwidth,
+		    AllPlanes, ZPixmap);
+	}
+
+	/* first check if there is any non-zero alpha channel data at all: */
+	for (y = 0; y < rcHeight; y++) {
+		for (x = 0; x < rcWidth; x++) {
+			int alpha;
+
+			offset = y * rcWidth + x;
+			pos = (char *)&rcSource[offset * bytesPerPixel];
+
+			upos = (unsigned long *) pos;
+			alpha = (*upos & 0xff000000) >> 24;
+			if (alpha) {
+				got_alpha = 1;
+				break;
+			}
+		}
+		if (got_alpha) {
+			break;
+		}
+	}
+
+	if (!got_alpha) {
+		/* no alpha channel data, fallback to the old way */
+		goto oldway;
+	}
+
+	/* load the saved fb patch in to image (faster way?) */
+	XGetSubImage(dpy, rcSavedArea, 0, 0, rcWidth, rcHeight,
+	    AllPlanes, ZPixmap, alpha_image, 0, 0);
+	upix = (unsigned long *)alpha_image->data;
+
+	/* if the richcursor is clipped, the fb patch will be smaller */
+	rsW = rcWidth;
+	rsX = 0;	/* used to denote a shift from the left side */
+	x = rcCursorX - rcHotX;
+	if (x < 0) {
+		rsW += x;
+		rsX = -x;
+	} else if (x + rsW > si.framebufferWidth) {
+		rsW = si.framebufferWidth - x;
+	}
+	rsH = rcHeight;
+	rsY = 0;	/* used to denote a shift from the top side */
+	y = rcCursorY - rcHotY;
+	if (y < 0) {
+		rsH += y;
+		rsY = -y;
+	} else if (y + rsH > si.framebufferHeight) {
+		rsH = si.framebufferHeight - y;
+	}
+
+	/*
+	 * now loop over the cursor data, blend in the fb values,
+	 * and then overwrite the fb (CopyDataToScreen())
+	 */
+	for (y = 0; y < rcHeight; y++) {
+		y0 = rcCursorY - rcHotY + y;
+		if (y0 < 0 || y0 >= si.framebufferHeight) {
+			continue;	/* clipped */
+		}
+		for (x = 0; x < rcWidth; x++) {
+			int alpha, color_curs, color_fb, i;
+
+			x0 = rcCursorX - rcHotX + x;
+			if (x0 < 0 || x0 >= si.framebufferWidth) {
+				continue;	/* clipped */
+			}
+
+			offset = y * rcWidth + x;
+			pos = (char *)&rcSource[offset * bytesPerPixel];
+
+			/* extract secret alpha byte from rich cursor: */
+			upos = (unsigned long *) pos;
+			alpha = (*upos & 0xff000000) >> 24;	/* XXX MSB? */
+
+			/* extract the pixel from the fb: */
+			pixel = *(upix + (y-rsY)*iwidth + (x-rsX));
+
+			put = 0;
+			/* for simplicity, blend all 4 bytes */
+			for (i = 0; i < 4; i++) {
+				int sh = i*8;
+				color_curs = ((0xff << sh) & *upos) >> sh;
+				color_fb   = ((0xff << sh) & pixel) >> sh;
+
+				/* XXX assumes pre-multipled color_curs */
+				color_fb = color_curs
+				    + ((0xff - alpha) * color_fb)/0xff;
+				put |= color_fb << sh;
+			}
+			/* place in the fb: */
+	    		CopyDataToScreen((char *)&put, x0, y0, 1, 1);
+		}
+	}
+	return;
+  }
+oldway:
+#endif
+
   bytesPerPixel = myFormat.bitsPerPixel / 8;
 
   /* FIXME: Speed optimization is possible. */
@@ -490,25 +651,26 @@
       }
     }
   }
+	XSync(dpy, False);
 }
 
-static void FreeSoftCursor(void)
+void FreeSoftCursor(void)
 {
-  if (prevSoftCursorSet) {
-    SoftCursorCopyArea(OPER_RESTORE);
-    XFreePixmap(dpy, rcSavedArea);
-    free(rcSource);
-    free(rcMask);
-    prevSoftCursorSet = False;
-  }
+	if (prevSoftCursorSet) {
+		SoftCursorCopyArea(OPER_RESTORE);
+		XFreePixmap(dpy, rcSavedArea);
+		free(rcSource);
+		rcSource = NULL;
+		free(rcMask);
+		prevSoftCursorSet = False;
+	}
 }
 
 
-static void FreeX11Cursor()
+void FreeX11Cursor()
 {
-  if (prevXCursorSet) {
-    XFreeCursor(dpy, prevXCursor);
-    prevXCursorSet = False;
-  }
+	if (prevXCursorSet) {
+		XFreeCursor(dpy, prevXCursor);
+		prevXCursorSet = False;
+	}
 }
-
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncviewer/desktop.c
--- vnc_unixsrc.orig/vncviewer/desktop.c	2004-05-28 13:29:29.000000000 -0400
+++ vnc_unixsrc/vncviewer/desktop.c	2007-03-24 10:18:42.000000000 -0400
@@ -28,21 +28,28 @@
 #include <X11/extensions/XShm.h>
 #endif
 
+#include <X11/cursorfont.h>
+
 GC gc;
 GC srcGC, dstGC; /* used for debugging copyrect */
 Window desktopWin;
-Cursor dotCursor;
+Cursor dotCursor = None;
+Cursor bogoCursor = None;
 Widget form, viewport, desktop;
 
 static Bool modifierPressed[256];
 
-static XImage *image = NULL;
+XImage *image = NULL;
+XImage *image_ycrop = NULL;
 
 static Cursor CreateDotCursor();
+static Cursor CreateBogoCursor();
 static void CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width,int height);
 static void HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev,
 				    Boolean *cont);
 
+static void CopyBGR565ToScreen(CARD16 *buf, int x, int y, int width,int height);
+
 static XtResource desktopBackingStoreResources[] = {
   {
     XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof(int), 0,
@@ -50,6 +57,86 @@
   },
 };
 
+void create_image() {
+	image = NULL;
+	image_ycrop = NULL;
+
+//fprintf(stderr, "useShm: %d\n", appData.useShm);
+
+#ifdef MITSHM
+	if (appData.useShm) {
+		image = CreateShmImage(0);
+		if (!image) {
+			if (appData.yCrop > 0) {
+				image_ycrop = CreateShmImage(1);
+				if (!image_ycrop) {
+					appData.useShm = False;
+				} else {
+					fprintf(stderr, "created smaller image_ycrop "
+					    "shm image\n");
+				}
+			} else {
+				appData.useShm = False;
+			}
+		}
+	}
+#endif
+
+	if (!image) {
+		image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
+		    si.framebufferWidth, si.framebufferHeight, BitmapPad(dpy), 0);
+
+		image->data = malloc(image->bytes_per_line * image->height);
+		if (!image->data) {
+			fprintf(stderr,"malloc failed\n");
+			exit(1);
+		} else {
+			fprintf(stderr, "created non-shm image\n");
+		}
+	}
+}
+
+int old_width = 0;
+int old_height = 0;
+
+int guessCrop(void) {
+	int w = si.framebufferWidth;
+
+	if (w == 320) {
+		return 240;
+	} else if (w == 400) {
+		return 300;
+	} else if (w == 640) {
+		return 480;
+	} else if (w == 800) {
+		return 600;
+	} else if (w == 1024) {
+		return 768;
+	} else if (w == 1152) {
+		return 864;
+	} else if (w == 1280) {
+		return 1024;
+	} else if (w == 1600) {
+		return 1200;
+	} else if (w == 1920) {
+		return 1200;
+	} else {
+		int h = (3 * w) / 4;
+		return h;
+	}
+}
+
+void check_tall(void) {
+	if (! appData.yCrop) {
+		int w = si.framebufferWidth;
+		int h = si.framebufferHeight;
+		if (h > 2 * w) {
+			fprintf(stderr, "Tall display (%dx%d) suspect 'x11vnc -ncache' mode,\n", w, h);
+			fprintf(stderr, "  setting auto -ycrop detection.\n", w, h);
+			appData.yCrop = -1;
+		}
+	}
+}
 
 /*
  * DesktopInitBeforeRealization creates the "desktop" widget and the viewport
@@ -59,52 +146,157 @@
 void
 DesktopInitBeforeRealization()
 {
-  int i;
-
-  form = XtVaCreateManagedWidget("form", formWidgetClass, toplevel,
-				 XtNborderWidth, 0,
-				 XtNdefaultDistance, 0, NULL);
+	int i;
 
-  viewport = XtVaCreateManagedWidget("viewport", viewportWidgetClass, form,
-				     XtNborderWidth, 0,
-				     NULL);
+	form = XtVaCreateManagedWidget("form", formWidgetClass, toplevel,
+	    XtNborderWidth, 0, XtNdefaultDistance, 0, NULL);
 
-  desktop = XtVaCreateManagedWidget("desktop", coreWidgetClass, viewport,
-				    XtNborderWidth, 0,
-				    NULL);
+	viewport = XtVaCreateManagedWidget("viewport", viewportWidgetClass, form,
+	    XtNborderWidth, 0, NULL);
 
-  XtVaSetValues(desktop, XtNwidth, si.framebufferWidth,
-		XtNheight, si.framebufferHeight, NULL);
+	desktop = XtVaCreateManagedWidget("desktop", coreWidgetClass, viewport,
+	    XtNborderWidth, 0, NULL);
+
+	XtVaSetValues(desktop, XtNwidth, si.framebufferWidth,
+	    XtNheight, si.framebufferHeight, NULL);
+
+	XtAddEventHandler(desktop, LeaveWindowMask|ExposureMask,
+	    True, HandleBasicDesktopEvent, NULL);
+
+
+	check_tall();
+	
+	if (appData.yCrop) {
+		int wm, hm;
+		if (appData.yCrop < 0) {
+			appData.yCrop = guessCrop();
+			fprintf(stderr, "Set -ycrop to: %d\n", appData.yCrop);
+		}
+		hm = appData.yCrop;
+		if (0 && appData.sbWidth <= 6 && appData.sbWidth > 0) {
+			hm += appData.sbWidth;
+		}
+		XtVaSetValues(toplevel, XtNmaxHeight, hm, NULL);
+		XtVaSetValues(form,     XtNmaxHeight, hm, NULL);
+		XtVaSetValues(viewport, XtNforceBars, False, NULL);
+	}
+	old_width  = si.framebufferWidth;
+	old_height = si.framebufferHeight;
 
-  XtAddEventHandler(desktop, LeaveWindowMask|ExposureMask,
-		    True, HandleBasicDesktopEvent, NULL);
+	for (i = 0; i < 256; i++) {
+		modifierPressed[i] = False;
+	}
 
-  for (i = 0; i < 256; i++)
-    modifierPressed[i] = False;
+	create_image();
+}
 
-  image = NULL;
+static Widget scrollbar_y = NULL;
 
-#ifdef MITSHM
-  if (appData.useShm) {
-    image = CreateShmImage();
-    if (!image)
-      appData.useShm = False;
-  }
-#endif
+static int xsst = 2;
+#include <X11/Xaw/Scrollbar.h>
 
-  if (!image) {
-    image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
-			 si.framebufferWidth, si.framebufferHeight,
-			 BitmapPad(dpy), 0);
-
-    image->data = malloc(image->bytes_per_line * image->height);
-    if (!image->data) {
-      fprintf(stderr,"malloc failed\n");
-      exit(1);
-    }
-  }
+static XtCallbackProc Scrolled(Widget w, XtPointer closure, XtPointer call_data) {
+	Position x, y;
+	XtVaGetValues(desktop, XtNx, &x, XtNy, &y, NULL);
+	if (0) fprintf(stderr, "scrolled by %d pixels x=%d y=%d\n", (int) call_data, x, y);
+	if (xsst == 2) {
+		x = 0;
+		y = 0;
+		XtVaSetValues(desktop, XtNx, x, XtNy, y, NULL);
+	} else if (xsst) {
+		XawScrollbarSetThumb(w, 0.0, 0.0);
+	} else {
+		float t = 0.0;
+		XtVaSetValues(w, XtNtopOfThumb, &t, NULL);
+	}
 }
+static XtCallbackProc Jumped(Widget w, XtPointer closure, XtPointer call_data) {
+	float top = *((float *) call_data);
+	Position x, y;
+	XtVaGetValues(desktop, XtNx, &x, XtNy, &y, NULL);
+	if (0) fprintf(stderr, "thumb value: %.4f x=%d y=%d\n", top, x, y);
+	if (top > 0.01) {
+		if (xsst == 2) {
+			x = 0;
+			y = 0;
+			XtVaSetValues(desktop, XtNx, x, XtNy, y, NULL);
+		} else if (xsst) {
+			XawScrollbarSetThumb(w, 0.0, 0.0);
+		} else {
+			float t = 0.0, s = 1.0;
+			XtVaSetValues(w, XtNtopOfThumb, *(XtArgVal*)&t, XtNshown, *(XtArgVal*)&s, NULL);
+		}
+	}
+}
+
+
+extern double dnow(void);
+
+void check_things() {
+	static int installed_callback = 0;
+	static int first = 1;
+	static double last_scrollbar = 0.0;
+	int w = si.framebufferWidth;
+	int h = si.framebufferHeight;
+	double now = dnow();
+	static double last = 0;
+
+	if (first) {
+		first = 0;
+		SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False);
+	}
+	if (appData.yCrop > 0 && appData.yCrop < dpyHeight && h > 2*w && now > last_scrollbar + 0.25) {
+		Widget wv, wh, wc;
+		Position x0, y0;
+		Position x1, y1;
+		Dimension w0, h0, b0;
+		Dimension w1, h1, b1;
+		Dimension w2, h2, b2;
+		
+		wc = XtNameToWidget(viewport, "clip");
+		wv = XtNameToWidget(viewport, "vertical");
+		wh = XtNameToWidget(viewport, "horizontal");
+		if (wc && wv && wh) {
+			int doit = 1;
+			int sb = appData.sbWidth;
+			XtVaGetValues(wv, XtNwidth, &w0, XtNheight, &h0, XtNborderWidth, &b0, XtNx, &x0, XtNy, &y0, NULL);
+			XtVaGetValues(wh, XtNwidth, &w1, XtNheight, &h1, XtNborderWidth, &b1, XtNx, &x1, XtNy, &y1, NULL);
+			XtVaGetValues(wc, XtNwidth, &w2, XtNheight, &h2, XtNborderWidth, &b2, NULL);
+			if (!sb) {
+				sb = 2;
+			}
+			if (w0 != sb || h1 != sb) {
+				fprintf(stderr, "Very tall (-ncache) fb, setting scrollbar thickness to: %d pixels\n", sb);
+				
+				XtUnmanageChild(wv);
+				XtUnmanageChild(wh);
+				XtUnmanageChild(wc);
+
+				XtVaSetValues(wv, XtNwidth, sb,  XtNx, x0 + (w0 - sb), NULL);
+				XtVaSetValues(wh, XtNheight, sb, XtNy, y1 + (h1 - sb), NULL);
+				w2 = w2 + (w0 - sb);
+				h2 = h2 + (h1 - sb);
+				if (w2 > 10 && h2 > 10) {
+					XtVaSetValues(wc, XtNwidth, w2, XtNheight, h2, NULL);
+				}
+
+				XtManageChild(wv);
+				XtManageChild(wh);
+				XtManageChild(wc);
+			}
+		}
+		last_scrollbar = dnow();
+	}
+	
+	if (now <= last + 1.0) {
+		return;
+	}
+
+	dpyWidth  = WidthOfScreen(DefaultScreenOfDisplay(dpy));
+	dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy));
 
+	last = dnow();
+}
 
 /*
  * DesktopInitAfterRealization does things which require the X windows to
@@ -114,34 +306,110 @@
 void
 DesktopInitAfterRealization()
 {
-  XGCValues gcv;
-  XSetWindowAttributes attr;
-  unsigned long valuemask;
-
-  desktopWin = XtWindow(desktop);
-
-  gc = XCreateGC(dpy,desktopWin,0,NULL);
-
-  gcv.function = GXxor;
-  gcv.foreground = 0x0f0f0f0f;
-  srcGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv);
-  gcv.foreground = 0xf0f0f0f0;
-  dstGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv);
-
-  XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
-		 NULL, 0);
-
-  XtVaGetApplicationResources(desktop, (XtPointer)&attr.backing_store,
-			      desktopBackingStoreResources, 1, NULL);
-  valuemask = CWBackingStore;
-
-  if (!appData.useX11Cursor) {
-    dotCursor = CreateDotCursor();
-    attr.cursor = dotCursor;    
-    valuemask |= CWCursor;
-  }
+	XGCValues gcv;
+	XSetWindowAttributes attr;
+	XWindowAttributes gattr;
+	unsigned long valuemask = 0;
+
+	desktopWin = XtWindow(desktop);
+
+	gc = XCreateGC(dpy,desktopWin,0,NULL);
+
+	gcv.function = GXxor;
+	gcv.foreground = 0x0f0f0f0f;
+	srcGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv);
+	gcv.foreground = 0xf0f0f0f0;
+	dstGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv);
+
+	XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
+	    NULL, 0);
+
+	if (appData.useBackingstore) {
+		Screen *s = DefaultScreenOfDisplay(dpy);
+		if (DoesBackingStore(s) != Always) {
+			fprintf(stderr, "X server does not do backingstore, disabling it.\n");
+			appData.useBackingstore = False;
+		}
+	}
+
+	if (appData.useBackingstore) {
+		XtVaGetApplicationResources(desktop, (XtPointer)&attr.backing_store,
+		    desktopBackingStoreResources, 1, NULL);
+		valuemask |= CWBackingStore;
+	} else {
+		attr.background_pixel = BlackPixel(dpy, DefaultScreen(dpy));
+		valuemask |= CWBackPixel;
+	}
 
-  XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr);
+	if (!appData.useX11Cursor) {
+		dotCursor = CreateDotCursor();
+		attr.cursor = dotCursor;    
+		valuemask |= CWCursor;
+	}
+	bogoCursor = XCreateFontCursor(dpy, XC_bogosity);
+
+	XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr);
+	if (XGetWindowAttributes(dpy, desktopWin, &gattr)) {
+#if 0
+		fprintf(stderr, "desktopWin backingstore: %d save_under: %d\n", gattr.backing_store, gattr.save_under);
+#endif
+	}
+	fprintf(stderr, "\n");
+}
+
+extern void FreeX11Cursor(void);
+extern void FreeSoftCursor(void);
+
+void
+DesktopCursorOff()
+{
+	XSetWindowAttributes attr;
+	unsigned long valuemask;
+
+	if (dotCursor == None) {
+		dotCursor = CreateDotCursor();
+	}
+	XDefineCursor(dpy, desktopWin, dotCursor);
+	FreeX11Cursor();
+	FreeSoftCursor();
+}
+
+void put_image(int src_x, int src_y, int dst_x, int dst_y, int width,
+    int height) {
+	
+#ifdef MITSHM
+	if (appData.useShm) {
+		if (image_ycrop == NULL) {
+//fprintf(stderr, "shm not image_ycrop\n");
+			XShmPutImage(dpy, desktopWin, gc, image, src_x, src_y,
+			    dst_x, dst_y, width, height, False);
+		} else if ((width < 32 && height < 32) || height > appData.yCrop) {
+//fprintf(stderr, "non-shmB image %d %d %d %d %d %d\n", src_x, src_y, dst_x, dst_y, width, height);
+			XPutImage(dpy, desktopWin, gc, image, src_x, src_y,
+			    dst_x, dst_y, width, height);
+		} else {
+			char *src, *dst;
+			int Bpp = image->bits_per_pixel / 8;
+			int Bpl  = image->bytes_per_line, h;
+			int Bpl2 = image_ycrop->bytes_per_line;
+			src = image->data + src_y * Bpl + src_x * Bpp;
+			dst = image_ycrop->data;
+			for (h = 0; h < height; h++) {
+				memcpy(dst, src, width * Bpp);
+				src += Bpl;
+				dst += Bpl2;
+			}
+//fprintf(stderr, "shm image_ycrop %d %d %d %d %d %d\n", 0, 0, dst_x, dst_y, width, height);
+			XShmPutImage(dpy, desktopWin, gc, image_ycrop, 0, 0,
+			    dst_x, dst_y, width, height, False);
+		}
+	} else
+#endif
+	{
+//fprintf(stderr, "non-shmA image %d %d %d %d %d %d\n", src_x, src_y, dst_x, dst_y, width, height);
+		XPutImage(dpy, desktopWin, gc, image, src_x, src_y,
+		   dst_x, dst_y, width, height);
+	}
 }
 
 
@@ -152,39 +420,53 @@
 static void
 HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont)
 {
-  int i;
+	int i, x, y, width, height;
 
-  switch (ev->type) {
 
+  switch (ev->type) {
   case Expose:
   case GraphicsExpose:
     /* sometimes due to scrollbars being added/removed we get an expose outside
        the actual desktop area.  Make sure we don't pass it on to the RFB
        server. */
+	x = ev->xexpose.x;
+	y = ev->xexpose.y;
+	width  = ev->xexpose.width;
+	height = ev->xexpose.height;
+
+//fprintf(stderr, "Expose: %dx%d+%d+%d\n", width, height, x, y);
+	if (x + width > si.framebufferWidth) {
+		width = si.framebufferWidth - x;
+		if (width <= 0) {
+			break;
+		}
+	}
 
-    if (ev->xexpose.x + ev->xexpose.width > si.framebufferWidth) {
-      ev->xexpose.width = si.framebufferWidth - ev->xexpose.x;
-      if (ev->xexpose.width <= 0) break;
-    }
-
-    if (ev->xexpose.y + ev->xexpose.height > si.framebufferHeight) {
-      ev->xexpose.height = si.framebufferHeight - ev->xexpose.y;
-      if (ev->xexpose.height <= 0) break;
-    }
+	if (y + height > si.framebufferHeight) {
+		height = si.framebufferHeight - y;
+		if (height <= 0) {
+			break;
+		}
+	}
 
-    SendFramebufferUpdateRequest(ev->xexpose.x, ev->xexpose.y,
-				 ev->xexpose.width, ev->xexpose.height, False);
-    break;
+	if (appData.useBackingstore) {
+		SendFramebufferUpdateRequest(x, y, width, height, False);
+	} else {
+		put_image(x, y, x, y, width, height);
+		XSync(dpy, False);
+	}
+	break;
 
   case LeaveNotify:
-    for (i = 0; i < 256; i++) {
-      if (modifierPressed[i]) {
-	SendKeyEvent(XKeycodeToKeysym(dpy, i, 0), False);
-	modifierPressed[i] = False;
-      }
-    }
-    break;
+	for (i = 0; i < 256; i++) {
+		if (modifierPressed[i]) {
+			SendKeyEvent(XKeycodeToKeysym(dpy, i, 0), False);
+			modifierPressed[i] = False;
+		}
+	}
+	break;
   }
+	check_things();
 }
 
 
@@ -201,6 +483,9 @@
  * button2 down, 3 for both, etc).
  */
 
+extern Bool selectingSingleWindow;
+extern Cursor dotCursor;
+
 void
 SendRFBEvent(Widget w, XEvent *ev, String *params, Cardinal *num_params)
 {
@@ -213,6 +498,13 @@
       return;
   }
 
+	if (selectingSingleWindow && ev->type == ButtonPress) {
+		selectingSingleWindow = False;
+		SendSingleWindow(ev->xbutton.x, ev->xbutton.y);
+		XDefineCursor(dpy, desktopWin, dotCursor);
+		return;
+	}
+
   if (appData.viewOnly) return;
 
   if (*num_params != 0) {
@@ -332,23 +624,123 @@
 static Cursor
 CreateDotCursor()
 {
-  Cursor cursor;
-  Pixmap src, msk;
-  static char srcBits[] = { 0, 14,14,14, 0 };
-  static char mskBits[] = { 14,31,31,31,14 };
-  XColor fg, bg;
-
-  src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits, 5, 5);
-  msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits, 5, 5);
-  XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "black",
-		   &fg, &fg);
-  XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "white",
-		   &bg, &bg);
-  cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 2, 2);
-  XFreePixmap(dpy, src);
-  XFreePixmap(dpy, msk);
+	Cursor cursor;
+	Pixmap src, msk;
+	static char srcBits[] = { 0, 14, 0 };
+	static char mskBits[] = { 14,31,14 };
+	XColor fg, bg;
+
+	src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits, 3, 3);
+	msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits, 3, 3);
+	XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "black",
+	    &fg, &fg);
+	XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "white",
+	    &bg, &bg);
+	cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 1, 1);
+	XFreePixmap(dpy, src);
+	XFreePixmap(dpy, msk);
+
+	return cursor;
+}
+
+void maybe_sync(int width, int height) {
+	static int singles = 0;
+	if (width > 1 || height > 1) {
+		XSync(dpy, False);
+		singles = 0;
+	} else {
+		if (++singles >= 32) {
+			singles = 0;
+			XSync(dpy, False);
+		}
+	}
+}
+/*
+ * FillImage.
+ */
+
+void
+FillScreen(int x, int y, int width, int height, unsigned long fill)
+{
+	int bpp = image->bits_per_pixel;
+	int Bpp = image->bits_per_pixel / 8;
+	int Bpl = image->bytes_per_line;
+	int h, widthInBytes = width * Bpp;
+	static char *buf = NULL;
+	static int buflen = 0;
+	unsigned char  *ucp;
+	unsigned short *usp;
+	unsigned int   *uip;
+	char *scr;
+	int b0, b1, b2;
+
+//fprintf(stderr, "FillImage bpp=%d %04dx%04d+%04d+%04d -- 0x%x\n", bpp, width, height, x, y, fill);
+
+	if (widthInBytes > buflen || !buf)  {
+		if (buf) {
+			free(buf);
+		}
+		buflen = widthInBytes * 2;
+		buf = (char *)malloc(buflen); 
+	}
+	ucp = (unsigned char*) buf;
+	usp = (unsigned short*) buf;
+	uip = (unsigned int*) buf;
+
+	if (isLSB) {
+		b0 = 0; b1 = 1; b2 = 2;
+	} else {
+		b0 = 2; b1 = 1; b2 = 0;
+	}
 
-  return cursor;
+	for (h = 0; h < width; h++) {
+		if (bpp == 8) {
+			*(ucp+h) = (unsigned char)  fill;
+		} else if (bpp == 16) {
+			*(usp+h) = (unsigned short) fill;
+		} else if (bpp == 24) {
+			*(ucp + 3*h + b0) = (unsigned char) ((fill & 0x0000ff) >> 0);
+			*(ucp + 3*h + b1) = (unsigned char) ((fill & 0x00ff00) >> 8);
+			*(ucp + 3*h + b2) = (unsigned char) ((fill & 0xff0000) >> 16);
+		} else if (bpp == 32) {
+			*(uip+h) = (unsigned int)   fill;
+		}
+	}
+
+	scr = image->data + y * Bpl + x * Bpp;
+
+	for (h = 0; h < height; h++) {
+		memcpy(scr, buf, widthInBytes);
+		scr += Bpl;
+	}
+	put_image(x, y, x, y, width, height);
+	maybe_sync(width, height);
+}
+
+void copy_rect(int x, int y, int width, int height, int src_x, int src_y) {
+	char *src, *dst;
+	int i;
+	int Bpp = image->bits_per_pixel / 8;
+	int Bpl = image->bytes_per_line;
+
+//fprintf(stderr, "copy_rect: %04dx%04d+%04d+%04d -- %04d %04d Bpp=%d Bpl=%d\n", width, height, x, y, src_x, src_y, Bpp, Bpl);
+	if (y < src_y) {
+		src = image->data + src_y * Bpl + src_x * Bpp;
+		dst = image->data +     y * Bpl +     x * Bpp;
+		for (i = 0; i < height; i++)  {
+			memmove(dst, src, Bpp * width); 
+			src += Bpl;
+			dst += Bpl;
+		}
+	} else {
+		src = image->data + (src_y + height - 1) * Bpl + src_x * Bpp;
+		dst = image->data + (y     + height - 1) * Bpl +     x * Bpp;
+		for (i = 0; i < height; i++)  {
+			memmove(dst, src, Bpp * width); 
+			src -= Bpl;
+			dst -= Bpl;
+		}
+	}
 }
 
 
@@ -359,38 +751,35 @@
 void
 CopyDataToScreen(char *buf, int x, int y, int width, int height)
 {
-  if (appData.rawDelay != 0) {
-    XFillRectangle(dpy, desktopWin, gc, x, y, width, height);
-
-    XSync(dpy,False);
-
-    usleep(appData.rawDelay * 1000);
-  }
+	if (appData.rawDelay != 0) {
+		XFillRectangle(dpy, desktopWin, gc, x, y, width, height);
+		XSync(dpy,False);
+		usleep(appData.rawDelay * 1000);
+	}
 
-  if (!appData.useBGR233) {
-    int h;
-    int widthInBytes = width * myFormat.bitsPerPixel / 8;
-    int scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8;
-
-    char *scr = (image->data + y * scrWidthInBytes
-		 + x * myFormat.bitsPerPixel / 8);
-
-    for (h = 0; h < height; h++) {
-      memcpy(scr, buf, widthInBytes);
-      buf += widthInBytes;
-      scr += scrWidthInBytes;
-    }
-  } else {
-    CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height);
-  }
+	if (appData.useBGR233) {
+		CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height);
+	} else if (appData.useBGR565) {
+		CopyBGR565ToScreen((CARD16 *)buf, x, y, width, height);
+	} else {
+		int h;
+		int widthInBytes = width * myFormat.bitsPerPixel / 8;
+		int scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8;
+
+		char *scr = (image->data + y * scrWidthInBytes
+		    + x * myFormat.bitsPerPixel / 8);
+
+//fprintf(stderr, "CopyDataToScreen %dx%d+%d+%d\n", width, height, x, y);
+
+		for (h = 0; h < height; h++) {
+			memcpy(scr, buf, widthInBytes);
+			buf += widthInBytes;
+			scr += scrWidthInBytes;
+		}
+	}
 
-#ifdef MITSHM
-  if (appData.useShm) {
-    XShmPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height, False);
-    return;
-  }
-#endif
-  XPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height);
+	put_image(x, y, x, y, width, height);
+	maybe_sync(width, height);
 }
 
 
@@ -401,62 +790,226 @@
 static void
 CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width, int height)
 {
-  int p, q;
-  int xoff = 7 - (x & 7);
-  int xcur;
-  int fbwb = si.framebufferWidth / 8;
-  CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8;
-  CARD8 *scrt;
-  CARD8 *scr8 = ((CARD8 *)image->data) + y * si.framebufferWidth + x;
-  CARD16 *scr16 = ((CARD16 *)image->data) + y * si.framebufferWidth + x;
-  CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x;
+	int p, q;
+	int xoff = 7 - (x & 7);
+	int xcur;
+	int fbwb = si.framebufferWidth / 8;
+	CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8;
+	CARD8 *scrt;
+	CARD8  *scr8  = ( (CARD8 *)image->data) + y * si.framebufferWidth + x;
+	CARD16 *scr16 = ((CARD16 *)image->data) + y * si.framebufferWidth + x;
+	CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x;
+	int b0, b1, b2;
 
-  switch (visbpp) {
+	switch (visbpp) {
 
     /* thanks to Chris Hooper for single bpp support */
 
-  case 1:
-    for (q = 0; q < height; q++) {
-      xcur = xoff;
-      scrt = scr1;
-      for (p = 0; p < width; p++) {
-	*scrt = ((*scrt & ~(1 << xcur))
-		 | (BGR233ToPixel[*(buf++)] << xcur));
-
-	if (xcur-- == 0) {
-	  xcur = 7;
-	  scrt++;
+	case 1:
+		for (q = 0; q < height; q++) {
+			xcur = xoff;
+			scrt = scr1;
+			for (p = 0; p < width; p++) {
+				*scrt = ((*scrt & ~(1 << xcur))
+					 | (BGR233ToPixel[*(buf++)] << xcur));
+
+				if (xcur-- == 0) {
+					xcur = 7;
+					scrt++;
+				}
+			}
+			scr1 += fbwb;
+		}
+		break;
+
+	case 8:
+		for (q = 0; q < height; q++) {
+			for (p = 0; p < width; p++) {
+				*(scr8++) = BGR233ToPixel[*(buf++)];
+			}
+			scr8 += si.framebufferWidth - width;
+		}
+		break;
+
+	case 16:
+		for (q = 0; q < height; q++) {
+			for (p = 0; p < width; p++) {
+				*(scr16++) = BGR233ToPixel[*(buf++)];
+			}
+			scr16 += si.framebufferWidth - width;
+		}
+		break;
+
+	case 24:
+		if (isLSB) {
+			b0 = 0; b1 = 1; b2 = 2;
+		} else {
+			b0 = 2; b1 = 1; b2 = 0;
+		}
+		scr8  = ((CARD8 *)image->data) + (y * si.framebufferWidth + x) * 3;
+		for (q = 0; q < height; q++) {
+			for (p = 0; p < width; p++) {
+				CARD32 v = BGR233ToPixel[*(buf++)];
+				*(scr8 + b0) = (unsigned char) ((v & 0x0000ff) >> 0);
+				*(scr8 + b1) = (unsigned char) ((v & 0x00ff00) >> 8);
+				*(scr8 + b2) = (unsigned char) ((v & 0xff0000) >> 16);
+				scr8 += 3;
+			}
+			scr8 += (si.framebufferWidth - width) * 3;
+		}
+		break;
+
+	case 32:
+		for (q = 0; q < height; q++) {
+			for (p = 0; p < width; p++) {
+				*(scr32++) = BGR233ToPixel[*(buf++)];
+			}
+			scr32 += si.framebufferWidth - width;
+		}
+		break;
 	}
-      }
-      scr1 += fbwb;
-    }
-    break;
+}
 
-  case 8:
-    for (q = 0; q < height; q++) {
-      for (p = 0; p < width; p++) {
-	*(scr8++) = BGR233ToPixel[*(buf++)];
-      }
-      scr8 += si.framebufferWidth - width;
-    }
-    break;
+static void
+BGR565_24bpp(CARD16 *buf, int x, int y, int width, int height)
+{
+	int p, q;
+	int b0, b1, b2;
+	unsigned char *scr= (unsigned char *)image->data + (y * si.framebufferWidth + x) * 3;
+
+	if (isLSB) {
+		b0 = 0; b1 = 1; b2 = 2;
+	} else {
+		b0 = 2; b1 = 1; b2 = 0;
+	}
 
-  case 16:
-    for (q = 0; q < height; q++) {
-      for (p = 0; p < width; p++) {
-	*(scr16++) = BGR233ToPixel[*(buf++)];
-      }
-      scr16 += si.framebufferWidth - width;
-    }
-    break;
+	/*  case 24: */
+	for (q = 0; q < height; q++) {
+		for (p = 0; p < width; p++) {
+			CARD32 v = BGR565ToPixel[*(buf++)];
+			*(scr + b0) = (unsigned char) ((v & 0x0000ff) >> 0);
+			*(scr + b1) = (unsigned char) ((v & 0x00ff00) >> 8);
+			*(scr + b2) = (unsigned char) ((v & 0xff0000) >> 16);
+			scr += 3;
+		}
+		scr += (si.framebufferWidth - width) * 3;
+	}
+}
 
-  case 32:
-    for (q = 0; q < height; q++) {
-      for (p = 0; p < width; p++) {
-	*(scr32++) = BGR233ToPixel[*(buf++)];
-      }
-      scr32 += si.framebufferWidth - width;
-    }
-    break;
-  }
+static void
+CopyBGR565ToScreen(CARD16 *buf, int x, int y, int width, int height)
+{
+	int p, q;
+	CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x;
+
+	if (visbpp == 24) {
+		BGR565_24bpp(buf, x, y, width, height);
+		return;
+	}
+
+	/*  case 32: */
+	for (q = 0; q < height; q++) {
+		for (p = 0; p < width; p++) {
+			*(scr32++) = BGR565ToPixel[*(buf++)];
+		}
+		scr32 += si.framebufferWidth - width;
+	}
+}
+
+static void reset_image(void) {
+	if (UsingShm()) {
+		ShmCleanup();
+	}
+	if (image && image->data) {
+		XDestroyImage(image);
+	}
+	image = NULL;
+	if (image_ycrop && image_ycrop->data) {
+		XDestroyImage(image_ycrop);
+	}
+	image_ycrop = NULL;
+	create_image();
+	XFlush(dpy);
+}
+
+void ReDoDesktop(void) {
+	int w, h, x, y, dw, dh;
+
+	check_tall();
+	if (appData.yCrop) {
+		if (appData.yCrop < 0 || old_width <= 0) {
+			appData.yCrop = guessCrop();
+			fprintf(stderr, "Set -ycrop to: %d\n", appData.yCrop);
+		} else {
+			int w1 = si.framebufferWidth;
+			int w0 = old_width;
+			appData.yCrop = (w1 * appData.yCrop) / old_width;
+			if (appData.yCrop <= 100)  {
+				appData.yCrop = guessCrop();
+				fprintf(stderr, "Set small -ycrop to: %d\n", appData.yCrop);
+			}
+		}
+		fprintf(stderr, "Using -ycrop: %d\n", appData.yCrop);
+	}
+	old_width  = si.framebufferWidth;
+	old_height = si.framebufferHeight;
+
+	if (appData.fullScreen) {
+		if (image && image->data) {
+			int len;
+			int h = image->height;
+			int w = image->width;
+			len = image->bytes_per_line * image->height;
+			/* black out window first: */
+			memset(image->data, 0, len);
+  			XPutImage(dpy, XtWindow(desktop), gc, image, 0, 0, 0, 0, w, h);
+			XFlush(dpy);
+		}
+		XtResizeWidget(desktop, si.framebufferWidth, si.framebufferHeight, 0);
+		XSync(dpy, False);
+		usleep(100*1000);
+		FullScreenOn();
+		XSync(dpy, False);
+		usleep(100*1000);
+		reset_image();
+		return;
+	}
+
+	dw = appData.wmDecorationWidth;
+	dh = appData.wmDecorationHeight;
+
+	w = si.framebufferWidth;
+	h = si.framebufferHeight;
+	if (appData.yCrop > 0) {
+		h = appData.yCrop;
+		if (0 && appData.sbWidth <= 6 && appData.sbWidth > 0) {
+			h += appData.sbWidth;
+		}
+	}
+
+	if (w + dw >= dpyWidth) {
+		w = dpyWidth - dw;
+	}
+	if (h + dh >= dpyHeight) {
+		h = dpyHeight - dh;
+	}
+
+	XtVaSetValues(toplevel, XtNmaxWidth, w, XtNmaxHeight, h, NULL);
+
+	XtVaSetValues(desktop, XtNwidth, si.framebufferWidth,
+	    XtNheight, si.framebufferHeight, NULL);
+
+	x = (dpyWidth  - w - dw)/2;
+	y = (dpyHeight - h - dh)/2;
+
+	XtResizeWidget(desktop, si.framebufferWidth, si.framebufferHeight, 0);
+
+	if (appData.yCrop > 0) {
+		XtVaSetValues(toplevel, XtNmaxHeight, appData.yCrop, NULL);
+		XtVaSetValues(form,     XtNmaxHeight, appData.yCrop, NULL);
+	}
+
+	XtConfigureWidget(toplevel, x + dw, y + dh, w, h, 0);
+
+	reset_image();
 }
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/fullscreen.c vnc_unixsrc/vncviewer/fullscreen.c
--- vnc_unixsrc.orig/vncviewer/fullscreen.c	2003-10-09 05:23:49.000000000 -0400
+++ vnc_unixsrc/vncviewer/fullscreen.c	2007-02-17 16:32:23.000000000 -0500
@@ -85,10 +85,14 @@
   Dimension oldViewportWidth, oldViewportHeight, clipWidth, clipHeight;
   Position viewportX, viewportY;
 
+  Bool fsAlready = appData.fullScreen, toobig = False;
+
   appData.fullScreen = True;
 
   if (si.framebufferWidth > dpyWidth || si.framebufferHeight > dpyHeight) {
+    int eff_height = si.framebufferHeight;
 
+    toobig = True;
     XtVaSetValues(viewport, XtNforceBars, True, NULL);
     XtVaGetValues(viewport, XtNwidth, &oldViewportWidth,
 		  XtNheight, &oldViewportHeight, NULL);
@@ -105,16 +109,23 @@
       toplevelWidth = dpyWidth;
     }
 
-    if (si.framebufferHeight > dpyHeight) {
+    if (appData.yCrop > 0) {
+	eff_height = appData.yCrop;
+    }
+
+    if (eff_height > dpyHeight) {
       viewportHeight = toplevelHeight = dpyHeight + scrollbarHeight;
     } else {
-      viewportHeight = si.framebufferHeight + scrollbarHeight;
+      viewportHeight = eff_height + scrollbarHeight;
       toplevelHeight = dpyHeight;
     }
 
   } else {
     viewportWidth = si.framebufferWidth;
     viewportHeight = si.framebufferHeight;
+	if (appData.yCrop > 0) {
+		viewportHeight = appData.yCrop;
+	}
     toplevelWidth = dpyWidth;
     toplevelHeight = dpyHeight;
   }
@@ -129,7 +140,12 @@
      reparenting our window to the root.  The window manager will get a
      ReparentNotify and hopefully clean up its frame window. */
 
+if (! fsAlready) {
+  XUnmapWindow(dpy, XtWindow(toplevel));
   XtVaSetValues(toplevel, XtNoverrideRedirect, True, NULL);
+  XtVaSetValues(viewport, XtNoverrideRedirect, True, NULL);
+  XtVaSetValues(desktop,  XtNoverrideRedirect, True, NULL);
+  XtVaSetValues(popup,    XtNoverrideRedirect, True, NULL);
 
   XReparentWindow(dpy, XtWindow(toplevel), DefaultRootWindow(dpy), 0, 0);
 
@@ -139,6 +155,8 @@
      with XReparentWindow. The last XSync seems to prevent losing
      focus, but I don't know why. */
   XSync(dpy, False);
+XMapWindow(dpy, XtWindow(toplevel));
+XRaiseWindow(dpy, XtWindow(toplevel));
   XMoveWindow(dpy, XtWindow(toplevel), 0, 0);
   XSync(dpy, False);
 
@@ -164,25 +182,67 @@
 
   XtManageChild(viewport);
 
-  /* Now we can set "toplevel" to its proper size. */
+} else {
+	XSync(dpy, False);
+}
 
+  /* Now we can set "toplevel" to its proper size. */
   XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0);
 
-  /* Set the popup to overrideRedirect too */
+if (fsAlready) {
+  XtResizeWidget(viewport, viewportWidth, viewportHeight, 0);
+  if (! toobig) {
+	XtVaSetValues(viewport, XtNforceBars, False, NULL);
+  }
+  XMoveWindow(dpy, XtWindow(viewport), viewportX, viewportY);
+  XSync(dpy, False);
+}
 
-  XtVaSetValues(popup, XtNoverrideRedirect, True, NULL);
+  /* Set the popup to overrideRedirect too */
 
   /* Try to get the input focus. */
 
+#if 0
   XSetInputFocus(dpy, DefaultRootWindow(dpy), RevertToPointerRoot,
 		 CurrentTime);
+#else
+  XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot,
+                 CurrentTime);
+#endif
+
 
   /* Optionally, grab the keyboard. */
 
-  if (appData.grabKeyboard &&
-      XtGrabKeyboard(desktop, True, GrabModeAsync,
-		     GrabModeAsync, CurrentTime) != GrabSuccess) {
-    fprintf(stderr, "XtGrabKeyboard() failed.\n");
+#define FORCE_UP \
+	XSync(dpy, False); \
+	XUnmapWindow(dpy, XtWindow(toplevel)); \
+	XSync(dpy, False); \
+	XMapWindow(dpy, XtWindow(toplevel)); \
+	XRaiseWindow(dpy, XtWindow(toplevel)); \
+	XSync(dpy, False);
+
+  if (appData.grabKeyboard && XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) {
+	fprintf(stderr, "XtGrabKeyboard() failed.\n");
+	XSync(dpy, False);
+	usleep(200 * 1000);
+	FORCE_UP
+
+  	if (XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) {
+		fprintf(stderr, "XtGrabKeyboard() failed again.\n");
+		usleep(200 * 1000);
+		XSync(dpy, True);
+  		if (XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) {
+			fprintf(stderr, "XtGrabKeyboard() failed 3rd time.\n");
+		} else {
+			fprintf(stderr, "XtGrabKeyboard() OK 3rd try.\n");
+		}
+	} else {
+		fprintf(stderr, "XtGrabKeyboard() OK 2nd try.\n");
+	}
+	XRaiseWindow(dpy, XtWindow(toplevel));
+  } else if (appData.grabAll) { /* runge bot of FullScreenOn */
+        fprintf(stderr, "calling XGrabServer(dpy)\n");
+        XGrabServer(dpy);       
   }
 }
 
@@ -210,8 +270,14 @@
 
   appData.fullScreen = False;
 
-  if (appData.grabKeyboard)
-    XtUngrabKeyboard(desktop, CurrentTime);
+
+  if (appData.grabAll) { /* runge top of FullScreenOff */
+        fprintf(stderr, "calling XUngrabServer(dpy)\n");
+        XUngrabServer(dpy);     
+  }
+  if (appData.grabKeyboard) {
+	XtUngrabKeyboard(desktop, CurrentTime);
+  }
 
   XtUnmapWidget(toplevel);
 
@@ -238,6 +304,9 @@
   XtManageChild(viewport);
 
   XtVaSetValues(toplevel, XtNoverrideRedirect, False, NULL);
+  XtVaSetValues(viewport, XtNoverrideRedirect, False, NULL);
+  XtVaSetValues(desktop,  XtNoverrideRedirect, False, NULL);
+  XtVaSetValues(popup,    XtNoverrideRedirect, False, NULL);
 
   if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth)
     toplevelWidth = dpyWidth - appData.wmDecorationWidth;
@@ -345,7 +414,9 @@
   }
 
   if (scrollDown) {
-    if (desktopY < si.framebufferHeight - dpyHeight) {
+    if (appData.yCrop > 0 && desktopY + dpyHeight >= appData.yCrop) {
+	;
+    } else if (desktopY < si.framebufferHeight - dpyHeight) {
       desktopY += appData.bumpScrollPixels;
       if (desktopY > si.framebufferHeight - dpyHeight)
 	desktopY = si.framebufferHeight - dpyHeight;
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/hextile.c vnc_unixsrc/vncviewer/hextile.c
--- vnc_unixsrc.orig/vncviewer/hextile.c	2007-02-17 22:33:46.000000000 -0500
+++ vnc_unixsrc/vncviewer/hextile.c	2007-02-17 22:48:39.000000000 -0500
@@ -30,6 +30,18 @@
 #define CARDBPP CONCAT2E(CARD,BPP)
 #define GET_PIXEL CONCAT2E(GET_PIXEL,BPP)
 
+#define FillRectangle(x, y, w, h, color)  \
+	{ \
+		XGCValues _gcv; \
+		_gcv.foreground = color; \
+		if (!appData.useBackingstore) { \
+			FillScreen(x, y, w, h, _gcv.foreground); \
+		} else { \
+			XChangeGC(dpy, gc, GCForeground, &_gcv); \
+			XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \
+		} \
+	}
+
 static Bool
 HandleHextileBPP (int rx, int ry, int rw, int rh)
 {
@@ -66,14 +78,25 @@
 	  return False;
 
 #if (BPP == 8)
-      if (appData.useBGR233)
+      if (appData.useBGR233) {
 	gcv.foreground = BGR233ToPixel[bg];
-      else
+      } else
 #endif
+#if (BPP == 16)
+      if (appData.useBGR565) {
+	gcv.foreground = BGR565ToPixel[bg];
+      } else
+#endif
+      {
 	gcv.foreground = bg;
+      }
 
-      XChangeGC(dpy, gc, GCForeground, &gcv);
-      XFillRectangle(dpy, desktopWin, gc, x, y, w, h);
+#if 0
+	XChangeGC(dpy, gc, GCForeground, &gcv);
+	XFillRectangle(dpy, desktopWin, gc, x, y, w, h);
+#else
+	FillRectangle(x, y, w, h, gcv.foreground);
+#endif
 
       if (subencoding & rfbHextileForegroundSpecified)
 	if (!ReadFromRFBServer((char *)&fg, sizeof(fg)))
@@ -101,14 +124,25 @@
 	  sh = rfbHextileExtractH(*ptr);
 	  ptr++;
 #if (BPP == 8)
-	  if (appData.useBGR233)
+	  if (appData.useBGR233) {
 	    gcv.foreground = BGR233ToPixel[fg];
-	  else
+	  } else
+#endif
+#if (BPP == 16)
+	  if (appData.useBGR565) {
+	    gcv.foreground = BGR565ToPixel[fg];
+	  } else
 #endif
+	  {
 	    gcv.foreground = fg;
+	  }
 
-	  XChangeGC(dpy, gc, GCForeground, &gcv);
-	  XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh);
+#if 0
+          XChangeGC(dpy, gc, GCForeground, &gcv);
+          XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh);
+#else
+	  FillRectangle(x+sx, y+sy, sw, sh, gcv.foreground);
+#endif
 	}
 
       } else {
@@ -116,13 +150,22 @@
 	  return False;
 
 #if (BPP == 8)
-	if (appData.useBGR233)
+	if (appData.useBGR233) {
 	  gcv.foreground = BGR233ToPixel[fg];
-	else
+	} else
 #endif
+#if (BPP == 16)
+        if (appData.useBGR565) {
+          gcv.foreground = BGR565ToPixel[fg];
+	} else
+#endif
+	{
 	  gcv.foreground = fg;
+	}
 
+#if 0
 	XChangeGC(dpy, gc, GCForeground, &gcv);
+#endif
 
 	for (i = 0; i < nSubrects; i++) {
 	  sx = rfbHextileExtractX(*ptr);
@@ -131,7 +174,11 @@
 	  sw = rfbHextileExtractW(*ptr);
 	  sh = rfbHextileExtractH(*ptr);
 	  ptr++;
+#if 0
 	  XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh);
+#else
+	  FillRectangle(x+sx, y+sy, sw, sh, gcv.foreground);
+#endif
 	}
       }
     }
@@ -139,3 +186,5 @@
 
   return True;
 }
+
+#undef FillRectangle
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/listen.c vnc_unixsrc/vncviewer/listen.c
--- vnc_unixsrc.orig/vncviewer/listen.c	2001-01-16 03:07:57.000000000 -0500
+++ vnc_unixsrc/vncviewer/listen.c	2007-03-23 22:30:46.000000000 -0400
@@ -111,13 +111,14 @@
   getFlashFont(d);
 
   listenSocket = ListenAtTcpPort(listenPort);
-  flashSocket = ListenAtTcpPort(flashPort);
+//flashSocket = ListenAtTcpPort(flashPort);
+  flashSocket = 1234;
 
   if ((listenSocket < 0) || (flashSocket < 0)) exit(1);
 
-  fprintf(stderr,"%s -listen: Listening on port %d (flash port %d)\n",
-	  programName,listenPort,flashPort);
-  fprintf(stderr,"%s -listen: Command line errors are not reported until "
+  fprintf(stderr,"%s -listen: Listening on port %d\n",
+	  programName,listenPort);
+  fprintf(stderr,"%s -listen: Cmdline errors are not reported until "
 	  "a connection comes in.\n", programName);
 
   while (True) {
@@ -132,12 +133,13 @@
 
     FD_ZERO(&fds); 
 
-    FD_SET(flashSocket, &fds);
+//  FD_SET(flashSocket, &fds);
     FD_SET(listenSocket, &fds);
     FD_SET(ConnectionNumber(d), &fds);
 
     select(FD_SETSIZE, &fds, NULL, NULL, NULL);
 
+#if 0
     if (FD_ISSET(flashSocket, &fds)) {
 
       sock = AcceptTcpConnection(flashSocket);
@@ -151,6 +153,7 @@
       }
       close(sock);
     }
+#endif
 
     if (FD_ISSET(listenSocket, &fds)) {
       rfbsock = AcceptTcpConnection(listenSocket);
@@ -182,6 +185,10 @@
 	  exit(1);
 	}
 	getFlashFont(d);
+	fprintf(stderr,"\n\n%s -listen: Listening on port %d\n",
+	    programName,listenPort);
+	fprintf(stderr,"%s -listen: Cmdline errors are not reported until "
+	    "a connection comes in.\n\n", programName);
 	break;
       }
     }
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer/popup.c
--- vnc_unixsrc.orig/vncviewer/popup.c	2000-06-11 08:00:53.000000000 -0400
+++ vnc_unixsrc/vncviewer/popup.c	2007-02-04 11:14:45.000000000 -0500
@@ -32,8 +32,33 @@
 void
 ShowPopup(Widget w, XEvent *event, String *params, Cardinal *num_params)
 {
-  XtMoveWidget(popup, event->xbutton.x_root, event->xbutton.y_root);
-  XtPopup(popup, XtGrabNone);
+  if (appData.popupFix) {
+	Window rr, cr; 
+	unsigned int m;
+  	int x0 = 500, y0 = 500;
+	int xr, yr, wxr, wyr;
+	Dimension ph;
+	if (XQueryPointer(dpy, DefaultRootWindow(dpy), &rr, &cr, &xr, &yr, &wxr, &wyr, &m)) {
+		x0 = xr;
+		y0 = yr;
+	}
+  	XtPopup(popup, XtGrabNone);
+	XtVaGetValues(popup, XtNheight, &ph, NULL);
+	if (0) fprintf(stderr, "%d %d %d\n", y0, (int) ph, dpyHeight);
+	if (y0 + (int) ph > dpyHeight) {
+		y0 = dpyHeight - (int) ph;
+		if (y0 < 0) {
+			y0 = 0;
+		}
+	}
+	XtMoveWidget(popup, x0, y0);
+  } else {
+	XtMoveWidget(popup, event->xbutton.x_root, event->xbutton.y_root);
+  	XtPopup(popup, XtGrabNone);
+  }
+  if (appData.grabAll) {
+  	XRaiseWindow(dpy, XtWindow(popup));
+  }
   XSetWMProtocols(dpy, XtWindow(popup), &wmDeleteWindow, 1);
 }
 
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup_ad vnc_unixsrc/vncviewer/popup_ad
--- vnc_unixsrc.orig/vncviewer/popup_ad	1969-12-31 19:00:00.000000000 -0500
+++ vnc_unixsrc/vncviewer/popup_ad	2007-02-18 19:52:31.000000000 -0500
@@ -0,0 +1,19 @@
+#!/usr/bin/perl
+
+$ok = 0;
+
+open(A, "<argsresources.c") || die;
+
+while (<A>) {
+	if (/popupButtonCount:/) {
+		$on = 1;
+	} elsif (/^\s*NULL/) {
+		$on = 0;
+	}
+	next unless $on;
+	chomp;
+	$_ =~ s/^\s*"//;
+	$_ =~ s/",//;
+	$_ .= "\n" unless $_ =~ /\n/;
+	print;
+}
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncviewer/rfbproto.c
--- vnc_unixsrc.orig/vncviewer/rfbproto.c	2004-03-11 13:14:39.000000000 -0500
+++ vnc_unixsrc/vncviewer/rfbproto.c	2007-03-23 22:17:11.000000000 -0400
@@ -57,6 +57,25 @@
 static Bool HandleTight16(int rx, int ry, int rw, int rh);
 static Bool HandleTight32(int rx, int ry, int rw, int rh);
 
+/* runge add zrle */
+static Bool HandleZRLE8(int rx, int ry, int rw, int rh);
+static Bool HandleZRLE16(int rx, int ry, int rw, int rh);
+static Bool HandleZRLE24(int rx, int ry, int rw, int rh);
+static Bool HandleZRLE24Up(int rx, int ry, int rw, int rh);
+static Bool HandleZRLE24Down(int rx, int ry, int rw, int rh);
+static Bool HandleZRLE32(int rx, int ry, int rw, int rh);
+
+typedef struct {
+    unsigned long length;
+} rfbZRLEHeader;
+
+long zywrle;
+
+#define sz_rfbZRLEHeader 4
+
+#define rfbZRLETileWidth 64
+#define rfbZRLETileHeight 64
+
 static void ReadConnFailedReason(void);
 static long ReadCompactLen (void);
 
@@ -68,6 +87,9 @@
                               int compressedLen);
 
 
+int sent_FBU = 0;
+int skip_XtUpdate = 0;
+
 int rfbsock;
 char *desktopName;
 rfbPixelFormat myFormat;
@@ -177,6 +199,9 @@
 	  sig_rfbEncodingPointerPos, "Pointer position update");
   CapsAdd(encodingCaps, rfbEncodingLastRect, rfbTightVncVendor,
 	  sig_rfbEncodingLastRect, "LastRect protocol extension");
+
+  CapsAdd(encodingCaps, rfbEncodingNewFBSize, rfbTightVncVendor,
+	  sig_rfbEncodingNewFBSize, "New FB size protocol extension");
 }
 
 
@@ -187,21 +212,21 @@
 Bool
 ConnectToRFBServer(const char *hostname, int port)
 {
-  unsigned int host;
+	unsigned int host;
 
-  if (!StringToIPAddr(hostname, &host)) {
-    fprintf(stderr,"Couldn't convert '%s' to host address\n", hostname);
-    return False;
-  }
+	if (!StringToIPAddr(hostname, &host)) {
+		fprintf(stderr,"Couldn't convert '%s' to host address\n", hostname);
+		return False;
+	}
 
-  rfbsock = ConnectToTcpAddr(host, port);
+	rfbsock = ConnectToTcpAddr(host, port);
 
-  if (rfbsock < 0) {
-    fprintf(stderr,"Unable to connect to VNC server\n");
-    return False;
-  }
+	if (rfbsock < 0) {
+		fprintf(stderr,"Unable to connect to VNC server\n");
+		return False;
+	}
 
-  return SetNonBlocking(rfbsock);
+	return SetNonBlocking(rfbsock);
 }
 
 
@@ -212,117 +237,127 @@
 Bool
 InitialiseRFBConnection(void)
 {
-  rfbProtocolVersionMsg pv;
-  int server_major, server_minor;
-  int viewer_major, viewer_minor;
-  rfbClientInitMsg ci;
-  int secType;
+	rfbProtocolVersionMsg pv;
+	int server_major, server_minor;
+	int viewer_major, viewer_minor;
+	rfbClientInitMsg ci;
+	int secType;
 
-  /* if the connection is immediately closed, don't report anything, so
-       that pmw's monitor can make test connections */
+	/* if the connection is immediately closed, don't report anything, so
+	   that pmw's monitor can make test connections */
 
-  if (listenSpecified)
-    errorMessageOnReadFailure = False;
+	if (listenSpecified) {
+		errorMessageOnReadFailure = False;
+	}
 
-  if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg))
-    return False;
+	if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) {
+		return False;
+	}
 
-  errorMessageOnReadFailure = True;
+	errorMessageOnReadFailure = True;
 
-  pv[sz_rfbProtocolVersionMsg] = 0;
+	pv[sz_rfbProtocolVersionMsg] = 0;
 
-  if (sscanf(pv, rfbProtocolVersionFormat,
-	     &server_major, &server_minor) != 2) {
-    fprintf(stderr,"Not a valid VNC server\n");
-    return False;
-  }
+	if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) {
+		fprintf(stderr,"Not a valid VNC server\n");
+		return False;
+	}
 
-  viewer_major = rfbProtocolMajorVersion;
-  if (server_major == 3 && server_minor >= rfbProtocolMinorVersion) {
-    /* the server supports at least the standard protocol 3.7 */
-    viewer_minor = rfbProtocolMinorVersion;
-  } else {
-    /* any other server version, request the standard 3.3 */
-    viewer_minor = rfbProtocolFallbackMinorVersion;
-  }
+	viewer_major = rfbProtocolMajorVersion;
+	if (server_major == 3 && server_minor >= rfbProtocolMinorVersion) {
+		/* the server supports at least the standard protocol 3.7 */
+		viewer_minor = rfbProtocolMinorVersion;
+	} else {
+		/* any other server version, request the standard 3.3 */
+		viewer_minor = rfbProtocolFallbackMinorVersion;
+	}
 
-  fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n",
-	  viewer_major, viewer_minor);
+	fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n", viewer_major, viewer_minor);
 
-  sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor);
+	sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor);
 
-  if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg))
-    return False;
+	if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) {
+		return False;
+	}
 
-  /* Read or select the security type. */
-  if (viewer_minor == rfbProtocolMinorVersion) {
-    secType = SelectSecurityType();
-  } else {
-    secType = ReadSecurityType();
-  }
-  if (secType == rfbSecTypeInvalid)
-    return False;
+	/* Read or select the security type. */
+	if (viewer_minor == rfbProtocolMinorVersion) {
+		secType = SelectSecurityType();
+	} else {
+		secType = ReadSecurityType();
+	}
+	if (secType == rfbSecTypeInvalid) {
+		return False;
+	}
 
-  switch (secType) {
-  case rfbSecTypeNone:
-    fprintf(stderr, "No authentication needed\n");
-    break;
-  case rfbSecTypeVncAuth:
-    if (!AuthenticateVNC())
-      return False;
-    break;
-  case rfbSecTypeTight:
-    tightVncProtocol = True;
-    InitCapabilities();
-    if (!SetupTunneling())
-      return False;
-    if (!PerformAuthenticationTight())
-      return False;
-    break;
-  default:                      /* should never happen */
-    fprintf(stderr, "Internal error: Invalid security type\n");
-    return False;
-  }
+	switch (secType) {
+		case rfbSecTypeNone:
+			fprintf(stderr, "No authentication needed\n");
+			break;
+		case rfbSecTypeVncAuth:
+			if (!AuthenticateVNC()) {
+				return False;
+			}
+			break;
+		case rfbSecTypeTight:
+			tightVncProtocol = True;
+			InitCapabilities();
+			if (!SetupTunneling()) {
+				return False;
+			}
+			if (!PerformAuthenticationTight()) {
+				return False;
+			}
+			break;
+		default:                      /* should never happen */
+			fprintf(stderr, "Internal error: Invalid security type\n");
+			return False;
+	}
 
-  ci.shared = (appData.shareDesktop ? 1 : 0);
+	ci.shared = (appData.shareDesktop ? 1 : 0);
 
-  if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg))
-    return False;
+	if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) {
+		return False;
+	}
 
-  if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg))
-    return False;
+	if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg)) {
+		return False;
+	}
 
-  si.framebufferWidth = Swap16IfLE(si.framebufferWidth);
-  si.framebufferHeight = Swap16IfLE(si.framebufferHeight);
-  si.format.redMax = Swap16IfLE(si.format.redMax);
-  si.format.greenMax = Swap16IfLE(si.format.greenMax);
-  si.format.blueMax = Swap16IfLE(si.format.blueMax);
-  si.nameLength = Swap32IfLE(si.nameLength);
-
-  /* FIXME: Check arguments to malloc() calls. */
-  desktopName = malloc(si.nameLength + 1);
-  if (!desktopName) {
-    fprintf(stderr, "Error allocating memory for desktop name, %lu bytes\n",
-            (unsigned long)si.nameLength);
-    return False;
-  }
+	si.framebufferWidth = Swap16IfLE(si.framebufferWidth);
+	si.framebufferHeight = Swap16IfLE(si.framebufferHeight);
+	si.format.redMax = Swap16IfLE(si.format.redMax);
+	si.format.greenMax = Swap16IfLE(si.format.greenMax);
+	si.format.blueMax = Swap16IfLE(si.format.blueMax);
+	si.nameLength = Swap32IfLE(si.nameLength);
+
+	/* FIXME: Check arguments to malloc() calls. */
+	desktopName = malloc(si.nameLength + 1);
+	if (!desktopName) {
+		fprintf(stderr, "Error allocating memory for desktop name, %lu bytes\n",
+		    (unsigned long)si.nameLength);
+		return False;
+	}
 
-  if (!ReadFromRFBServer(desktopName, si.nameLength)) return False;
+	if (!ReadFromRFBServer(desktopName, si.nameLength)) {
+		return False;
+	}
 
-  desktopName[si.nameLength] = 0;
+	desktopName[si.nameLength] = 0;
 
-  fprintf(stderr,"Desktop name \"%s\"\n",desktopName);
+	fprintf(stderr,"Desktop name \"%s\"\n",desktopName);
 
-  fprintf(stderr,"VNC server default format:\n");
-  PrintPixelFormat(&si.format);
+	fprintf(stderr,"VNC server default format:\n");
+	PrintPixelFormat(&si.format);
 
-  if (tightVncProtocol) {
-    /* Read interaction capabilities (protocol 3.7t) */
-    if (!ReadInteractionCaps())
-      return False;
-  }
+	if (tightVncProtocol) {
+		/* Read interaction capabilities (protocol 3.7t) */
+		if (!ReadInteractionCaps()) {
+			return False;
+		}
+	}
 
-  return True;
+	return True;
 }
 
 
@@ -333,26 +368,27 @@
 static int
 ReadSecurityType(void)
 {
-  CARD32 secType;
+	CARD32 secType;
 
-  /* Read the security type */
-  if (!ReadFromRFBServer((char *)&secType, sizeof(secType)))
-    return rfbSecTypeInvalid;
+	/* Read the security type */
+	if (!ReadFromRFBServer((char *)&secType, sizeof(secType))) {
+		return rfbSecTypeInvalid;
+	}
 
-  secType = Swap32IfLE(secType);
+	secType = Swap32IfLE(secType);
 
-  if (secType == rfbSecTypeInvalid) {
-    ReadConnFailedReason();
-    return rfbSecTypeInvalid;
-  }
+	if (secType == rfbSecTypeInvalid) {
+		ReadConnFailedReason();
+		return rfbSecTypeInvalid;
+	}
 
-  if (secType != rfbSecTypeNone && secType != rfbSecTypeVncAuth) {
-    fprintf(stderr, "Unknown security type from RFB server: %d\n",
-            (int)secType);
-    return rfbSecTypeInvalid;
-  }
+	if (secType != rfbSecTypeNone && secType != rfbSecTypeVncAuth) {
+		fprintf(stderr, "Unknown security type from RFB server: %d\n",
+		    (int)secType);
+		return rfbSecTypeInvalid;
+	}
 
-  return (int)secType;
+	return (int)secType;
 }
 
 
@@ -363,60 +399,66 @@
 static int
 SelectSecurityType(void)
 {
-  CARD8 nSecTypes;
-  char *secTypeNames[] = {"None", "VncAuth"};
-  CARD8 knownSecTypes[] = {rfbSecTypeNone, rfbSecTypeVncAuth};
-  int nKnownSecTypes = sizeof(knownSecTypes);
-  CARD8 *secTypes;
-  CARD8 secType = rfbSecTypeInvalid;
-  int i, j;
-
-  /* Read the list of secutiry types. */
-  if (!ReadFromRFBServer((char *)&nSecTypes, sizeof(nSecTypes)))
-    return rfbSecTypeInvalid;
-
-  if (nSecTypes == 0) {
-    ReadConnFailedReason();
-    return rfbSecTypeInvalid;
-  }
+	CARD8 nSecTypes;
+	char *secTypeNames[] = {"None", "VncAuth"};
+	CARD8 knownSecTypes[] = {rfbSecTypeNone, rfbSecTypeVncAuth};
+	int nKnownSecTypes = sizeof(knownSecTypes);
+	CARD8 *secTypes;
+	CARD8 secType = rfbSecTypeInvalid;
+	int i, j;
+
+	/* Read the list of secutiry types. */
+	if (!ReadFromRFBServer((char *)&nSecTypes, sizeof(nSecTypes))) {
+		return rfbSecTypeInvalid;
+	}
 
-  secTypes = malloc(nSecTypes);
-  if (!ReadFromRFBServer((char *)secTypes, nSecTypes))
-    return rfbSecTypeInvalid;
-
-  /* Find out if the server supports TightVNC protocol extensions */
-  for (j = 0; j < (int)nSecTypes; j++) {
-    if (secTypes[j] == rfbSecTypeTight) {
-      free(secTypes);
-      secType = rfbSecTypeTight;
-      if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType)))
-        return rfbSecTypeInvalid;
-      fprintf(stderr, "Enabling TightVNC protocol extensions\n");
-      return rfbSecTypeTight;
-    }
-  }
+	if (nSecTypes == 0) {
+		ReadConnFailedReason();
+		return rfbSecTypeInvalid;
+	}
 
-  /* Find first supported security type */
-  for (j = 0; j < (int)nSecTypes; j++) {
-    for (i = 0; i < nKnownSecTypes; i++) {
-      if (secTypes[j] == knownSecTypes[i]) {
-        secType = secTypes[j];
-        if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) {
-          free(secTypes);
-          return rfbSecTypeInvalid;
-        }
-        break;
-      }
-    }
-    if (secType != rfbSecTypeInvalid) break;
-  }
+	secTypes = malloc(nSecTypes);
+	if (!ReadFromRFBServer((char *)secTypes, nSecTypes)) {
+		return rfbSecTypeInvalid;
+	}
+
+	/* Find out if the server supports TightVNC protocol extensions */
+	for (j = 0; j < (int)nSecTypes; j++) {
+		if (secTypes[j] == rfbSecTypeTight) {
+			free(secTypes);
+			secType = rfbSecTypeTight;
+			if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) {
+				return rfbSecTypeInvalid;
+			}
+			fprintf(stderr, "Enabling TightVNC protocol extensions\n");
+			return rfbSecTypeTight;
+		}
+	}
+
+	/* Find first supported security type */
+	for (j = 0; j < (int)nSecTypes; j++) {
+		for (i = 0; i < nKnownSecTypes; i++) {
+			if (secTypes[j] == knownSecTypes[i]) {
+				secType = secTypes[j];
+				if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) {
+				  free(secTypes);
+				  return rfbSecTypeInvalid;
+				}
+				break;
+				}
+		}
+		if (secType != rfbSecTypeInvalid) {
+			break;
+		}
+	}
 
-  free(secTypes);
+	free(secTypes);
 
-  if (secType == rfbSecTypeInvalid)
-    fprintf(stderr, "Server did not offer supported security type\n");
+	if (secType == rfbSecTypeInvalid) {
+		fprintf(stderr, "Server did not offer supported security type\n");
+	}
 
-  return (int)secType;
+	return (int)secType;
 }
 
 
@@ -451,6 +493,9 @@
   return True;
 }
 
+static char *restart_session_pw = NULL;
+static int restart_session_len = 0;
+
 
 /*
  * Negotiate authentication scheme (protocol version 3.7t)
@@ -459,56 +504,61 @@
 static Bool
 PerformAuthenticationTight(void)
 {
-  rfbAuthenticationCapsMsg caps;
-  CARD32 authScheme;
-  int i;
+	rfbAuthenticationCapsMsg caps;
+	CARD32 authScheme;
+	int i;
 
-  /* In the protocol version 3.7t, the server informs us about supported
-     authentication schemes. Here we read this information. */
+	/* In the protocol version 3.7t, the server informs us about supported
+	authentication schemes. Here we read this information. */
 
-  if (!ReadFromRFBServer((char *)&caps, sz_rfbAuthenticationCapsMsg))
-    return False;
+	if (!ReadFromRFBServer((char *)&caps, sz_rfbAuthenticationCapsMsg)) {
+		return False;
+	}
 
-  caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes);
+	caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes);
 
-  if (!caps.nAuthTypes) {
-    fprintf(stderr, "No authentication needed\n");
-    return True;
-  }
+	if (!caps.nAuthTypes) {
+		fprintf(stderr, "No authentication needed\n");
+		return True;
+	}
 
-  if (!ReadCapabilityList(authCaps, caps.nAuthTypes))
-    return False;
+	if (!ReadCapabilityList(authCaps, caps.nAuthTypes)) {
+		return False;
+	}
 
-  /* Prefer Unix login authentication if a user name was given. */
-  if (appData.userLogin && CapsIsEnabled(authCaps, rfbAuthUnixLogin)) {
-    authScheme = Swap32IfLE(rfbAuthUnixLogin);
-    if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme)))
-      return False;
-    return AuthenticateUnixLogin();
-  }
+	/* Prefer Unix login authentication if a user name was given. */
+	if (appData.userLogin && CapsIsEnabled(authCaps, rfbAuthUnixLogin)) {
+		authScheme = Swap32IfLE(rfbAuthUnixLogin);
+		if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) {
+			return False;
+		}
+		return AuthenticateUnixLogin();
+	}
 
-  /* Otherwise, try server's preferred authentication scheme. */
-  for (i = 0; i < CapsNumEnabled(authCaps); i++) {
-    authScheme = CapsGetByOrder(authCaps, i);
-    if (authScheme != rfbAuthUnixLogin && authScheme != rfbAuthVNC)
-      continue;                 /* unknown scheme - cannot use it */
-    authScheme = Swap32IfLE(authScheme);
-    if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme)))
-      return False;
-    authScheme = Swap32IfLE(authScheme); /* convert it back */
-    if (authScheme == rfbAuthUnixLogin) {
-      return AuthenticateUnixLogin();
-    } else if (authScheme == rfbAuthVNC) {
-      return AuthenticateVNC();
-    } else {
-      /* Should never happen. */
-      fprintf(stderr, "Assertion failed: unknown authentication scheme\n");
-      return False;
-    }
-  }
+	/* Otherwise, try server's preferred authentication scheme. */
+	for (i = 0; i < CapsNumEnabled(authCaps); i++) {
+		authScheme = CapsGetByOrder(authCaps, i);
+		if (authScheme != rfbAuthUnixLogin && authScheme != rfbAuthVNC) {
+			continue;                 /* unknown scheme - cannot use it */
+		}
+		authScheme = Swap32IfLE(authScheme);
+		if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) {
+			return False;
+		}
+		authScheme = Swap32IfLE(authScheme); /* convert it back */
+		if (authScheme == rfbAuthUnixLogin) {
+			return AuthenticateUnixLogin();
+		} else if (authScheme == rfbAuthVNC) {
+			return AuthenticateVNC();
+		} else {
+			/* Should never happen. */
+			fprintf(stderr, "Assertion failed: unknown authentication scheme\n");
+			return False;
+		}
+	}
 
-  fprintf(stderr, "No suitable authentication schemes offered by server\n");
-  return False;
+	fprintf(stderr, "No suitable authentication schemes offered by server\n");
+	return False;
 }
 
 
@@ -519,80 +569,97 @@
 static Bool
 AuthenticateVNC(void)
 {
-  CARD32 authScheme, authResult;
-  CARD8 challenge[CHALLENGESIZE];
-  char *passwd;
-  char  buffer[64];
-  char* cstatus;
-  int   len;
+	CARD32 authScheme, authResult;
+	CARD8 challenge[CHALLENGESIZE];
+	char *passwd = NULL;
+	char  buffer[64];
+	char* cstatus;
+	int   len;
+	int restart = 0;
 
-  fprintf(stderr, "Performing standard VNC authentication\n");
+	fprintf(stderr, "Performing standard VNC authentication\n");
 
-  if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE))
-    return False;
+	if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) {
+		return False;
+	}
 
-  if (appData.passwordFile) {
-    passwd = vncDecryptPasswdFromFile(appData.passwordFile);
-    if (!passwd) {
-      fprintf(stderr, "Cannot read valid password from file \"%s\"\n",
-	      appData.passwordFile);
-      return False;
-    }
-  } else if (appData.autoPass) {
-    passwd = buffer;
-    cstatus = fgets(buffer, sizeof buffer, stdin);
-    if (cstatus == NULL)
-       buffer[0] = '\0';
-    else
-    {
-       len = strlen(buffer);
-       if (len > 0 && buffer[len - 1] == '\n')
-	  buffer[len - 1] = '\0';
-    }
-  } else if (appData.passwordDialog) {
-    passwd = DoPasswordDialog();
-  } else {
-    passwd = getpass("Password: ");
-  }
+	if (restart_session_pw != NULL) {
+		passwd = restart_session_pw;	
+		restart_session_pw = NULL;
+		restart = 1;
+	} else if (appData.passwordFile) {
+		passwd = vncDecryptPasswdFromFile(appData.passwordFile);
+		if (!passwd) {
+			fprintf(stderr, "Cannot read valid password from file \"%s\"\n",
+			      appData.passwordFile);
+			return False;
+		}
+	} else if (appData.autoPass) {
+		passwd = buffer;
+		cstatus = fgets(buffer, sizeof buffer, stdin);
+		if (cstatus == NULL) {
+			buffer[0] = '\0';
+		} else {
+			len = strlen(buffer);
+			if (len > 0 && buffer[len - 1] == '\n') {
+				buffer[len - 1] = '\0';
+			}
+		}
+	} else if (appData.passwordDialog) {
+		passwd = DoPasswordDialog();
+	} else {
+		passwd = getpass("Password: ");
+	}
 
-  if (!passwd || strlen(passwd) == 0) {
-    fprintf(stderr, "Reading password failed\n");
-    return False;
-  }
-  if (strlen(passwd) > 8) {
-    passwd[8] = '\0';
-  }
+	if (restart) {
+#define EN0 0
+#define DE1 1
+		unsigned char s_fixedkey[8] = {23,82,107,6,35,78,88,7};
+		deskey(s_fixedkey, DE1);
+		des(passwd, passwd);
+	} else {
+		if (!passwd || strlen(passwd) == 0) {
+			fprintf(stderr, "Reading password failed\n");
+			return False;
+		}
+		if (strlen(passwd) > 8) {
+			passwd[8] = '\0';
+		}
+	}
+	vncEncryptBytes(challenge, passwd);
+	
 
-  vncEncryptBytes(challenge, passwd);
 
-  /* Lose the password from memory */
-  memset(passwd, '\0', strlen(passwd));
+//	/* Lose the password from memory */
+//	memset(passwd, '\0', strlen(passwd));
 
-  if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE))
-    return False;
+	if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) {
+		return False;
+	}
 
-  if (!ReadFromRFBServer((char *)&authResult, 4))
-    return False;
+	if (!ReadFromRFBServer((char *)&authResult, 4)) {
+		return False;
+	}
 
-  authResult = Swap32IfLE(authResult);
+	authResult = Swap32IfLE(authResult);
 
-  switch (authResult) {
-  case rfbVncAuthOK:
-    fprintf(stderr, "VNC authentication succeeded\n");
-    break;
-  case rfbVncAuthFailed:
-    fprintf(stderr, "VNC authentication failed\n");
-    return False;
-  case rfbVncAuthTooMany:
-    fprintf(stderr, "VNC authentication failed - too many tries\n");
-    return False;
-  default:
-    fprintf(stderr, "Unknown VNC authentication result: %d\n",
-	    (int)authResult);
-    return False;
-  }
+	switch (authResult) {
+	case rfbVncAuthOK:
+		fprintf(stderr, "VNC authentication succeeded\n");
+		break;
+	case rfbVncAuthFailed:
+		fprintf(stderr, "VNC authentication failed\n");
+		return False;
+	case rfbVncAuthTooMany:
+		fprintf(stderr, "VNC authentication failed - too many tries\n");
+		return False;
+	default:
+		fprintf(stderr, "Unknown VNC authentication result: %d\n",
+		    (int)authResult);
+		return False;
+	}
 
-  return True;
+	return True;
 }
 
 /*
@@ -602,68 +669,71 @@
 static Bool
 AuthenticateUnixLogin(void)
 {
-  CARD32 loginLen, passwdLen, authResult;
-  char *login;
-  char *passwd;
-  struct passwd *ps;
-
-  fprintf(stderr, "Performing Unix login-style authentication\n");
-
-  if (appData.userLogin) {
-    login = appData.userLogin;
-  } else {
-    ps = getpwuid(getuid());
-    login = ps->pw_name;
-  }
+	CARD32 loginLen, passwdLen, authResult;
+	char *login;
+	char *passwd;
+	struct passwd *ps;
+
+	fprintf(stderr, "Performing Unix login-style authentication\n");
+
+	if (appData.userLogin) {
+		login = appData.userLogin;
+	} else {
+		ps = getpwuid(getuid());
+		login = ps->pw_name;
+	}
 
-  fprintf(stderr, "Using user name \"%s\"\n", login);
+	fprintf(stderr, "Using user name \"%s\"\n", login);
 
-  if (appData.passwordDialog) {
-    passwd = DoPasswordDialog();
-  } else {
-    passwd = getpass("Password: ");
-  }
-  if (!passwd || strlen(passwd) == 0) {
-    fprintf(stderr, "Reading password failed\n");
-    return False;
-  }
+	if (appData.passwordDialog) {
+		passwd = DoPasswordDialog();
+	} else {
+		passwd = getpass("Password: ");
+	}
+	if (!passwd || strlen(passwd) == 0) {
+		fprintf(stderr, "Reading password failed\n");
+		return False;
+	}
 
-  loginLen = Swap32IfLE((CARD32)strlen(login));
-  passwdLen = Swap32IfLE((CARD32)strlen(passwd));
+	loginLen = Swap32IfLE((CARD32)strlen(login));
+	passwdLen = Swap32IfLE((CARD32)strlen(passwd));
 
-  if (!WriteExact(rfbsock, (char *)&loginLen, sizeof(loginLen)) ||
-      !WriteExact(rfbsock, (char *)&passwdLen, sizeof(passwdLen)))
-    return False;
+	if (!WriteExact(rfbsock, (char *)&loginLen, sizeof(loginLen)) ||
+	    !WriteExact(rfbsock, (char *)&passwdLen, sizeof(passwdLen))) {
+		return False;
+	}
 
-  if (!WriteExact(rfbsock, login, strlen(login)) ||
-      !WriteExact(rfbsock, passwd, strlen(passwd)))
-    return False;
+	if (!WriteExact(rfbsock, login, strlen(login)) ||
+	    !WriteExact(rfbsock, passwd, strlen(passwd))) {
+		return False;
+	}
 
-  /* Lose the password from memory */
-  memset(passwd, '\0', strlen(passwd));
+//	/* Lose the password from memory */
+//	memset(passwd, '\0', strlen(passwd));
 
-  if (!ReadFromRFBServer((char *)&authResult, sizeof(authResult)))
-    return False;
+	if (!ReadFromRFBServer((char *)&authResult, sizeof(authResult))) {
+		return False;
+	}
 
-  authResult = Swap32IfLE(authResult);
+	authResult = Swap32IfLE(authResult);
 
-  switch (authResult) {
-  case rfbVncAuthOK:
-    fprintf(stderr, "Authentication succeeded\n");
-    break;
-  case rfbVncAuthFailed:
-    fprintf(stderr, "Authentication failed\n");
-    return False;
-  case rfbVncAuthTooMany:
-    fprintf(stderr, "Authentication failed - too many tries\n");
-    return False;
-  default:
-    fprintf(stderr, "Unknown authentication result: %d\n",
-	    (int)authResult);
-    return False;
-  }
+	switch (authResult) {
+	case rfbVncAuthOK:
+		fprintf(stderr, "Authentication succeeded\n");
+		break;
+	case rfbVncAuthFailed:
+		fprintf(stderr, "Authentication failed\n");
+		return False;
+	case rfbVncAuthTooMany:
+		fprintf(stderr, "Authentication failed - too many tries\n");
+		return False;
+	default:
+		fprintf(stderr, "Unknown authentication result: %d\n",
+		    (int)authResult);
+		return False;
+	}
 
-  return True;
+	return True;
 }
 
 
@@ -675,19 +745,20 @@
 static Bool
 ReadInteractionCaps(void)
 {
-  rfbInteractionCapsMsg intr_caps;
+	rfbInteractionCapsMsg intr_caps;
 
-  /* Read the counts of list items following */
-  if (!ReadFromRFBServer((char *)&intr_caps, sz_rfbInteractionCapsMsg))
-    return False;
-  intr_caps.nServerMessageTypes = Swap16IfLE(intr_caps.nServerMessageTypes);
-  intr_caps.nClientMessageTypes = Swap16IfLE(intr_caps.nClientMessageTypes);
-  intr_caps.nEncodingTypes = Swap16IfLE(intr_caps.nEncodingTypes);
-
-  /* Read the lists of server- and client-initiated messages */
-  return (ReadCapabilityList(serverMsgCaps, intr_caps.nServerMessageTypes) &&
-	  ReadCapabilityList(clientMsgCaps, intr_caps.nClientMessageTypes) &&
-	  ReadCapabilityList(encodingCaps, intr_caps.nEncodingTypes));
+	/* Read the counts of list items following */
+	if (!ReadFromRFBServer((char *)&intr_caps, sz_rfbInteractionCapsMsg)) {
+		return False;
+	}
+	intr_caps.nServerMessageTypes = Swap16IfLE(intr_caps.nServerMessageTypes);
+	intr_caps.nClientMessageTypes = Swap16IfLE(intr_caps.nClientMessageTypes);
+	intr_caps.nEncodingTypes = Swap16IfLE(intr_caps.nEncodingTypes);
+
+	/* Read the lists of server- and client-initiated messages */
+	return (ReadCapabilityList(serverMsgCaps, intr_caps.nServerMessageTypes) &&
+		ReadCapabilityList(clientMsgCaps, intr_caps.nClientMessageTypes) &&
+		ReadCapabilityList(encodingCaps, intr_caps.nEncodingTypes));
 }
 
 
@@ -700,17 +771,18 @@
 static Bool
 ReadCapabilityList(CapsContainer *caps, int count)
 {
-  rfbCapabilityInfo msginfo;
-  int i;
+	rfbCapabilityInfo msginfo;
+	int i;
 
-  for (i = 0; i < count; i++) {
-    if (!ReadFromRFBServer((char *)&msginfo, sz_rfbCapabilityInfo))
-      return False;
-    msginfo.code = Swap32IfLE(msginfo.code);
-    CapsEnable(caps, &msginfo);
-  }
+	for (i = 0; i < count; i++) {
+		if (!ReadFromRFBServer((char *)&msginfo, sz_rfbCapabilityInfo)) {
+			return False;
+		}
+		msginfo.code = Swap32IfLE(msginfo.code);
+		CapsEnable(caps, &msginfo);
+	}
 
-  return True;
+	return True;
 }
 
 
@@ -729,6 +801,10 @@
   Bool requestCompressLevel = False;
   Bool requestQualityLevel = False;
   Bool requestLastRectEncoding = False;
+  Bool requestNewFBSizeEncoding = True;
+  Bool requestTextChatEncoding = True;
+
+//  fprintf(stderr, "SetFormatAndEncodings: sent_FBU state: %2d\n", sent_FBU);
 
   spf.type = rfbSetPixelFormat;
   spf.format = myFormat;
@@ -736,6 +812,7 @@
   spf.format.greenMax = Swap16IfLE(spf.format.greenMax);
   spf.format.blueMax = Swap16IfLE(spf.format.blueMax);
 
+
   if (!WriteExact(rfbsock, (char *)&spf, sz_rfbSetPixelFormatMsg))
     return False;
 
@@ -754,6 +831,12 @@
 	encStrLen = strlen(encStr);
       }
 
+if (getenv("DEBUG_SETFORMAT")) {
+	fprintf(stderr, "encs: ");
+	write(2, encStr, encStrLen);
+	fprintf(stderr, "\n");
+}
+
       if (strncasecmp(encStr,"raw",encStrLen) == 0) {
 	encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw);
       } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) {
@@ -775,6 +858,10 @@
 	encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE);
       } else if (strncasecmp(encStr,"rre",encStrLen) == 0) {
 	encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE);
+      } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) {
+	encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZRLE);
+      } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) {
+	encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE);
       } else {
 	fprintf(stderr,"Unknown encoding '%.*s'\n",encStrLen,encStr);
       }
@@ -797,7 +884,7 @@
     if (appData.useRemoteCursor) {
       if (se->nEncodings < MAX_ENCODINGS)
 	encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
-      if (se->nEncodings < MAX_ENCODINGS)
+      if (se->nEncodings < MAX_ENCODINGS && !appData.useX11Cursor)
 	encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
       if (se->nEncodings < MAX_ENCODINGS)
 	encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos);
@@ -806,10 +893,14 @@
     if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) {
       encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect);
     }
+
+    if (se->nEncodings < MAX_ENCODINGS && requestNewFBSizeEncoding) {
+      encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize);
+    }
   }
   else {
     if (SameMachine(rfbsock)) {
-      if (!tunnelSpecified) {
+      if (!tunnelSpecified && appData.useRawLocal) {
 	fprintf(stderr,"Same machine: preferring raw encoding\n");
 	encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw);
       } else {
@@ -819,6 +910,7 @@
 
     encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect);
     encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight);
+    encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZRLE);
     encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile);
     encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib);
     encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE);
@@ -844,11 +936,14 @@
 
     if (appData.useRemoteCursor) {
       encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
-      encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
+      if (!appData.useX11Cursor) {
+      	encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
+      }
       encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos);
     }
 
     encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect);
+    encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize);
   }
 
   len = sz_rfbSetEncodingsMsg + se->nEncodings * 4;
@@ -868,8 +963,8 @@
 Bool
 SendIncrementalFramebufferUpdateRequest()
 {
-  return SendFramebufferUpdateRequest(0, 0, si.framebufferWidth,
-				      si.framebufferHeight, True);
+	return SendFramebufferUpdateRequest(0, 0, si.framebufferWidth,
+	    si.framebufferHeight, True);
 }
 
 
@@ -880,19 +975,26 @@
 Bool
 SendFramebufferUpdateRequest(int x, int y, int w, int h, Bool incremental)
 {
-  rfbFramebufferUpdateRequestMsg fur;
+	rfbFramebufferUpdateRequestMsg fur;
 
-  fur.type = rfbFramebufferUpdateRequest;
-  fur.incremental = incremental ? 1 : 0;
-  fur.x = Swap16IfLE(x);
-  fur.y = Swap16IfLE(y);
-  fur.w = Swap16IfLE(w);
-  fur.h = Swap16IfLE(h);
+	fur.type = rfbFramebufferUpdateRequest;
+	fur.incremental = incremental ? 1 : 0;
+	fur.x = Swap16IfLE(x);
+	fur.y = Swap16IfLE(y);
+	fur.w = Swap16IfLE(w);
+	fur.h = Swap16IfLE(h);
+
+	if (incremental) {
+		sent_FBU = 1;
+	} else {
+		sent_FBU = 2;
+	}
 
-  if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg))
-    return False;
+	if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) {
+		return False;
+	}
 
-  return True;
+	return True;
 }
 
 
@@ -903,19 +1005,20 @@
 Bool
 SendPointerEvent(int x, int y, int buttonMask)
 {
-  rfbPointerEventMsg pe;
+	rfbPointerEventMsg pe;
+
+	pe.type = rfbPointerEvent;
+	pe.buttonMask = buttonMask;
+	if (x < 0) x = 0;
+	if (y < 0) y = 0;
+
+	if (!appData.useX11Cursor) {
+		SoftCursorMove(x, y);
+	}
 
-  pe.type = rfbPointerEvent;
-  pe.buttonMask = buttonMask;
-  if (x < 0) x = 0;
-  if (y < 0) y = 0;
-
-  if (!appData.useX11Cursor)
-    SoftCursorMove(x, y);
-
-  pe.x = Swap16IfLE(x);
-  pe.y = Swap16IfLE(y);
-  return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg);
+	pe.x = Swap16IfLE(x);
+	pe.y = Swap16IfLE(y);
+	return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg);
 }
 
 
@@ -926,12 +1029,12 @@
 Bool
 SendKeyEvent(CARD32 key, Bool down)
 {
-  rfbKeyEventMsg ke;
+	rfbKeyEventMsg ke;
 
-  ke.type = rfbKeyEvent;
-  ke.down = down ? 1 : 0;
-  ke.key = Swap32IfLE(key);
-  return WriteExact(rfbsock, (char *)&ke, sz_rfbKeyEventMsg);
+	ke.type = rfbKeyEvent;
+	ke.down = down ? 1 : 0;
+	ke.key = Swap32IfLE(key);
+	return WriteExact(rfbsock, (char *)&ke, sz_rfbKeyEventMsg);
 }
 
 
@@ -942,281 +1045,555 @@
 Bool
 SendClientCutText(char *str, int len)
 {
-  rfbClientCutTextMsg cct;
+	rfbClientCutTextMsg cct;
 
-  if (serverCutText)
-    free(serverCutText);
-  serverCutText = NULL;
-
-  cct.type = rfbClientCutText;
-  cct.length = Swap32IfLE(len);
-  return  (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) &&
-	   WriteExact(rfbsock, str, len));
-}
+	if (serverCutText) {
+		free(serverCutText);
+	}
+	serverCutText = NULL;
 
+	if (appData.viewOnly) {
+		return True;
+	}
 
-/*
- * HandleRFBServerMessage.
- */
+	cct.type = rfbClientCutText;
+	cct.length = Swap32IfLE(len);
+	return  (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) &&
+	    WriteExact(rfbsock, str, len));
+}
 
 Bool
-HandleRFBServerMessage()
+SendServerScale(int nfac)
 {
-  rfbServerToClientMsg msg;
-
-  if (!ReadFromRFBServer((char *)&msg, 1))
-    return False;
+	rfbSetScaleMsg ssc;
+	if (nfac < 0 || nfac > 100) {
+		return True;
+	}
 
-  switch (msg.type) {
+	ssc.type = rfbSetScale;
+	ssc.scale = nfac;
+	return WriteExact(rfbsock, (char *)&ssc, sz_rfbSetScaleMsg);
+}
 
-  case rfbSetColourMapEntries:
-  {
-    int i;
-    CARD16 rgb[3];
-    XColor xc;
+Bool
+SendServerInput(Bool enabled)
+{
+	rfbSetServerInputMsg sim;
 
-    if (!ReadFromRFBServer(((char *)&msg) + 1,
-			   sz_rfbSetColourMapEntriesMsg - 1))
-      return False;
+	sim.type = rfbSetServerInput;
+	sim.status = enabled;
+	return WriteExact(rfbsock, (char *)&sim, sz_rfbSetServerInputMsg);
+}
 
-    msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour);
-    msg.scme.nColours = Swap16IfLE(msg.scme.nColours);
+Bool
+SendSingleWindow(int x, int y)
+{
+	rfbSetSWMsg sw;
 
-    for (i = 0; i < msg.scme.nColours; i++) {
-      if (!ReadFromRFBServer((char *)rgb, 6))
-	return False;
-      xc.pixel = msg.scme.firstColour + i;
-      xc.red = Swap16IfLE(rgb[0]);
-      xc.green = Swap16IfLE(rgb[1]);
-      xc.blue = Swap16IfLE(rgb[2]);
-      xc.flags = DoRed|DoGreen|DoBlue;
-      XStoreColor(dpy, cmap, &xc);
-    }
+	if (x == -1 && y == -1)  {
+		sw.type = rfbSetSW;
+		sw.x = Swap16IfLE(1);
+		sw.y = Swap16IfLE(1);
+	} else {
+		sw.type = rfbSetSW;
+		sw.x = Swap16IfLE(x);
+		sw.y = Swap16IfLE(y);
+	}
+	sw.status = True;
+	return WriteExact(rfbsock, (char *)&sw, sz_rfbSetSWMsg);
+}
 
-    break;
-  }
+Bool
+SendTextChat(char *str)
+{
+	rfbTextChatMsg chat;
+	chat.type = rfbTextChat;
+	chat.pad1 = 0;
+	chat.pad2 = 0;
+	chat.length = (unsigned int) strlen(str);
+//fprintf(stderr, "Sending: %d %s\n", chat.length, str);
+	chat.length = Swap32IfLE(chat.length);
+	if (!WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg)) {
+		return False;
+	}
+	return WriteExact(rfbsock, str, strlen(str));
+}
 
-  case rfbFramebufferUpdate:
-  {
-    rfbFramebufferUpdateRectHeader rect;
-    int linesToRead;
-    int bytesPerLine;
-    int i;
-    int usecs;
+extern void raiseme(void);
 
-    if (!ReadFromRFBServer(((char *)&msg.fu) + 1,
-			   sz_rfbFramebufferUpdateMsg - 1))
-      return False;
+Bool
+SendTextChatOpen(void)
+{
+	raiseme();
+	rfbTextChatMsg chat;
+	chat.type = rfbTextChat;
+	chat.pad1 = 0;
+	chat.pad2 = 0;
+	chat.length = Swap32IfLE(rfbTextChatOpen);
+	return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg);
+}
 
-    msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
+Bool
+SendTextChatClose(void)
+{
+	rfbTextChatMsg chat;
+	chat.type = rfbTextChat;
+	chat.pad1 = 0;
+	chat.pad2 = 0;
+	chat.length = Swap32IfLE(rfbTextChatClose);
+	return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg);
+}
 
-    for (i = 0; i < msg.fu.nRects; i++) {
-      if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader))
-	return False;
+Bool
+SendTextChatFinished(void)
+{
+	rfbTextChatMsg chat;
+	chat.type = rfbTextChat;
+	chat.pad1 = 0;
+	chat.pad2 = 0;
+	chat.length = Swap32IfLE(rfbTextChatFinished);
+	return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg);
+}
+
+extern int do_format_change;
+extern int do_cursor_change;
+extern void cutover_format_change(void);
+
+double dtime(double *t_old) {
+        /* 
+         * usage: call with 0.0 to initialize, subsequent calls give
+         * the time difference since last call.
+         */
+        double t_now, dt;
+        struct timeval now;
+
+        gettimeofday(&now, NULL);
+        t_now = now.tv_sec + ( (double) now.tv_usec/1000000. );
+        if (*t_old == 0.0) {
+                *t_old = t_now;
+                return t_now;
+        }
+        dt = t_now - *t_old;
+        *t_old = t_now;
+        return(dt);
+}
 
-      rect.encoding = Swap32IfLE(rect.encoding);
-      if (rect.encoding == rfbEncodingLastRect)
-	break;
+/* common dtime() activities: */
+double dtime0(double *t_old) {
+        *t_old = 0.0;
+        return dtime(t_old);
+}
 
-      rect.r.x = Swap16IfLE(rect.r.x);
-      rect.r.y = Swap16IfLE(rect.r.y);
-      rect.r.w = Swap16IfLE(rect.r.w);
-      rect.r.h = Swap16IfLE(rect.r.h);
-
-      if (rect.encoding == rfbEncodingXCursor ||
-	  rect.encoding == rfbEncodingRichCursor) {
-	if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h,
-			      rect.encoding)) {
-	  return False;
-	}
-	continue;
-      }
+double dnow(void) {
+        double t;
+        return dtime0(&t);
+}
 
-      if (rect.encoding == rfbEncodingPointerPos) {
-	if (!HandleCursorPos(rect.r.x, rect.r.y)) {
-	  return False;
-	}
-	continue;
-      }
 
-      if ((rect.r.x + rect.r.w > si.framebufferWidth) ||
-	  (rect.r.y + rect.r.h > si.framebufferHeight))
-	{
-	  fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n",
-		  rect.r.w, rect.r.h, rect.r.x, rect.r.y);
-	  return False;
-	}
+/*
+ * HandleRFBServerMessage.
+ */
 
-      if (rect.r.h * rect.r.w == 0) {
-	fprintf(stderr,"Zero size rect - ignoring\n");
-	continue;
-      }
+Bool
+HandleRFBServerMessage()
+{
+	int db = 0;
+	rfbServerToClientMsg msg;
 
-      /* If RichCursor encoding is used, we should prevent collisions
-	 between framebuffer updates and cursor drawing operations. */
-      SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h);
+	if (!ReadFromRFBServer((char *)&msg, 1)) {
+		return False;
+	}
 
-      switch (rect.encoding) {
+    switch (msg.type) {
 
-      case rfbEncodingRaw:
+    case rfbSetColourMapEntries:
+    {
+	int i;
+	CARD16 rgb[3];
+	XColor xc;
 
-	bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8;
-	linesToRead = BUFFER_SIZE / bytesPerLine;
+	if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbSetColourMapEntriesMsg - 1)) {
+		return False;
+	}
 
-	while (rect.r.h > 0) {
-	  if (linesToRead > rect.r.h)
-	    linesToRead = rect.r.h;
+	msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour);
+	msg.scme.nColours = Swap16IfLE(msg.scme.nColours);
 
-	  if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead))
-	    return False;
+	for (i = 0; i < msg.scme.nColours; i++) {
+		if (!ReadFromRFBServer((char *)rgb, 6)) {
+			return False;
+		}
+		xc.pixel = msg.scme.firstColour + i;
+		xc.red = Swap16IfLE(rgb[0]);
+		xc.green = Swap16IfLE(rgb[1]);
+		xc.blue = Swap16IfLE(rgb[2]);
+		if (appData.useGreyScale) {
+			int ave = (xc.red + xc.green + xc.blue)/3;
+			xc.red   = ave;
+			xc.green = ave;
+			xc.blue  = ave;
+		}
+		xc.flags = DoRed|DoGreen|DoBlue;
+		XStoreColor(dpy, cmap, &xc);
+	}
 
-	  CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w,
-			   linesToRead);
+	break;
+    }
 
-	  rect.r.h -= linesToRead;
-	  rect.r.y += linesToRead;
+    case rfbFramebufferUpdate:
+    {
+	rfbFramebufferUpdateRectHeader rect;
+	int linesToRead;
+	int bytesPerLine;
+	int i;
+	int usecs;
+
+	int area_copyrect = 0;
+	int area_tight = 0;
+	int area_zrle = 0;
+	int area_raw = 0;
+	if (db) fprintf(stderr, "FBU-0:    %.6f\n", dnow());
 
-	}
-	break;
+	int skip_incFBU = 0;
+	sent_FBU = -1;
 
-      case rfbEncodingCopyRect:
-      {
-	rfbCopyRect cr;
-
-	if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect))
-	  return False;
-
-	cr.srcX = Swap16IfLE(cr.srcX);
-	cr.srcY = Swap16IfLE(cr.srcY);
-
-	/* If RichCursor encoding is used, we should extend our
-	   "cursor lock area" (previously set to destination
-	   rectangle) to the source rectangle as well. */
-	SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h);
-
-	if (appData.copyRectDelay != 0) {
-	  XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY,
-			 rect.r.w, rect.r.h);
-	  XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y,
-			 rect.r.w, rect.r.h);
-	  XSync(dpy,False);
-	  usleep(appData.copyRectDelay * 1000);
-	  XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y,
-			 rect.r.w, rect.r.h);
-	  XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY,
-			 rect.r.w, rect.r.h);
+	if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) {
+		return False;
 	}
 
-	XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY,
-		  rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+	msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
 
-	break;
-      }
+	for (i = 0; i < msg.fu.nRects; i++) {
+		if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) {
+			return False;
+		}
+
+		rect.encoding = Swap32IfLE(rect.encoding);
+		if (rect.encoding == rfbEncodingLastRect) {
+			break;
+		}
+
+		rect.r.x = Swap16IfLE(rect.r.x);
+		rect.r.y = Swap16IfLE(rect.r.y);
+		rect.r.w = Swap16IfLE(rect.r.w);
+		rect.r.h = Swap16IfLE(rect.r.h);
+
+		if (rect.encoding == rfbEncodingXCursor || rect.encoding == rfbEncodingRichCursor) {
+			if (db) fprintf(stderr, "FBU-Cur1  %.6f\n", dnow());
+			if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rect.encoding)) {
+				return False;
+			}
+			if (db) fprintf(stderr, "FBU-Cur2  %.6f\n", dnow());
+			continue;
+		}
+
+		if (rect.encoding == rfbEncodingPointerPos) {
+			if (db) fprintf(stderr, "FBU-Pos1  %.6f\n", dnow());
+			if (!HandleCursorPos(rect.r.x, rect.r.y)) {
+				return False;
+			}
+			if (db) fprintf(stderr, "FBU-Pos2  %.6f\n", dnow());
+			continue;
+		}
+		if (rect.encoding == rfbEncodingNewFBSize) {
+			fprintf(stderr,"New Size: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+			si.framebufferWidth = rect.r.w;
+			si.framebufferHeight = rect.r.h;
+			//fprintf(stderr, "si: %d %d\n", si.framebufferWidth, si.framebufferHeight);
+			ReDoDesktop();
+			continue;
+		}
+
+		if ((rect.r.x + rect.r.w > si.framebufferWidth) ||
+		    (rect.r.y + rect.r.h > si.framebufferHeight)) {
+			fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n",
+			rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+			return False;
+		}
+
+		if (rect.r.h * rect.r.w == 0) {
+			fprintf(stderr,"Zero size rect - ignoring\n");
+			continue;
+		}
+
+		/* If RichCursor encoding is used, we should prevent collisions
+		   between framebuffer updates and cursor drawing operations. */
+		if (db) fprintf(stderr, "FBU-SCL1  %.6f\n", dnow());
+
+		SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h);
+
+		if (db) fprintf(stderr, "FBU-SCL2  %.6f\n", dnow());
+
+		switch (rect.encoding) {
+
+		case rfbEncodingRaw:
+
+			bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8;
+			linesToRead = BUFFER_SIZE / bytesPerLine;
+
+			if (db) fprintf(stderr, "Raw:     %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+			area_raw += rect.r.w * rect.r.h;
+
+			while (rect.r.h > 0) {
+				if (linesToRead > rect.r.h) {
+					linesToRead = rect.r.h;
+				}
+
+				if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) {
+					return False;
+				}
+
+				CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, linesToRead);
+
+				rect.r.h -= linesToRead;
+				rect.r.y += linesToRead;
+			}
+			break;
+
+		case rfbEncodingCopyRect:
+		{
+			rfbCopyRect cr;
+
+			if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) {
+				return False;
+			}
+
+			cr.srcX = Swap16IfLE(cr.srcX);
+			cr.srcY = Swap16IfLE(cr.srcY);
+
+			if (db) fprintf(stderr, "Copy:    %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+			area_copyrect += rect.r.w * rect.r.h;
+
+			/* If RichCursor encoding is used, we should extend our
+			   "cursor lock area" (previously set to destination
+			   rectangle) to the source rectangle as well. */
+
+			if (db) fprintf(stderr, "FBU-SCL3  %.6f\n", dnow());
+
+			SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h);
+
+			if (db) fprintf(stderr, "FBU-SCL4  %.6f\n", dnow());
+
+			if (appData.copyRectDelay != 0) {
+				XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h);
+				XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
+				XSync(dpy,False);
+				usleep(appData.copyRectDelay * 1000);
+				XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
+				XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h);
+			}
+
+			if (db) fprintf(stderr, "FBU-CPA1  %.6f\n", dnow());
+			if (!appData.useBackingstore) {
+				copy_rect(rect.r.x, rect.r.y, rect.r.w, rect.r.h, cr.srcX, cr.srcY);
+				put_image(rect.r.x, rect.r.y, rect.r.x, rect.r.y, rect.r.w, rect.r.h);
+				XSync(dpy, False);
+			} else {
+				XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY,
+				    rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+			}
+			if (db) fprintf(stderr, "FBU-CPA2  %.6f\n", dnow());
+
+			break;
+		}
+
+		case rfbEncodingRRE:
+		{
+			switch (myFormat.bitsPerPixel) {
+			case 8:
+				if (!HandleRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			case 16:
+				if (!HandleRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			case 32:
+				if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			}
+			break;
+		}
+
+		case rfbEncodingCoRRE:
+		{
+			switch (myFormat.bitsPerPixel) {
+			case 8:
+				if (!HandleCoRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			case 16:
+				if (!HandleCoRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			case 32:
+				if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			}
+			break;
+		}
+
+		case rfbEncodingHextile:
+		{
+			switch (myFormat.bitsPerPixel) {
+			case 8:
+				if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			case 16:
+				if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			case 32:
+				if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			}
+			break;
+		}
+
+		case rfbEncodingZlib:
+		{
+			switch (myFormat.bitsPerPixel) {
+			case 8:
+				if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			case 16:
+				if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			case 32:
+				if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			}
+			break;
+		}
+
+		case rfbEncodingTight:
+		{
+			if (db) fprintf(stderr, "Tight:   %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+			area_tight += rect.r.w * rect.r.h;
+			if (db) fprintf(stderr, "FBU-TGH1  %.6f\n", dnow());
+
+			switch (myFormat.bitsPerPixel) {
+			case 8:
+				if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			case 16:
+				if (!HandleTight16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			case 32:
+				if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			}
+			if (db) fprintf(stderr, "FBU-TGH2  %.6f\n", dnow());
+			break;
+		}
+
+		/* runge adds zrle and zywrle: */
+		case rfbEncodingZRLE:
+		{
+			if (db) fprintf(stderr, "ZRLE:    %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+			area_zrle += rect.r.w * rect.r.h;
+			switch (myFormat.bitsPerPixel) {
+			case 8:
+				if (!HandleZRLE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			case 16:
+				if (!HandleZRLE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			case 32:
+			    {
+				unsigned int maxColor=(myFormat.redMax<<myFormat.redShift)|
+				    (myFormat.greenMax<<myFormat.greenShift)|
+				    (myFormat.blueMax<<myFormat.blueShift);
+				if ((myFormat.bigEndian && (maxColor&0xff)==0) || (!myFormat.bigEndian && (maxColor&0xff000000)==0)) {
+					if (!HandleZRLE24(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+						return False;
+					}
+				} else if (!myFormat.bigEndian && (maxColor&0xff)==0) {
+					if (!HandleZRLE24Up(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+						return False;
+					}
+				} else if (myFormat.bigEndian && (maxColor&0xff000000)==0) {
+					if (!HandleZRLE24Down(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+						return False;
+					}
+				} else if (!HandleZRLE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) {
+					return False;
+				}
+				break;
+			    }
+			}
+			break;
+		}
+
+		default:
+		fprintf(stderr,"Unknown rect encoding %d\n", (int)rect.encoding);
+		return False;
+		}
 
-      case rfbEncodingRRE:
-      {
-	switch (myFormat.bitsPerPixel) {
-	case 8:
-	  if (!HandleRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
-	case 16:
-	  if (!HandleRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
-	case 32:
-	  if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
-	}
-	break;
-      }
+		/* Now we may discard "soft cursor locks". */
+		if (db) fprintf(stderr, "FBU-SUL1  %.6f\n", dnow());
 
-      case rfbEncodingCoRRE:
-      {
-	switch (myFormat.bitsPerPixel) {
-	case 8:
-	  if (!HandleCoRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
-	case 16:
-	  if (!HandleCoRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
-	case 32:
-	  if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
-	}
-	break;
-      }
+		SoftCursorUnlockScreen();
 
-      case rfbEncodingHextile:
-      {
-	switch (myFormat.bitsPerPixel) {
-	case 8:
-	  if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
-	case 16:
-	  if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
-	case 32:
-	  if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
+		if (db) fprintf(stderr, "FBU-SUL2  %.6f\n", dnow());
 	}
-	break;
-      }
 
-      case rfbEncodingZlib:
-      {
-	switch (myFormat.bitsPerPixel) {
-	case 8:
-	  if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
-	case 16:
-	  if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
-	case 32:
-	  if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
+	if (1 || area_copyrect) {
+		if (db) fprintf(stderr, "FBU-XSN1  %.6f\n", dnow());
+		XSync(dpy, False);
+		if (db) fprintf(stderr, "FBU-XSN2  %.6f\n", dnow());
 	}
-	break;
-     }
-
-      case rfbEncodingTight:
-      {
-	switch (myFormat.bitsPerPixel) {
-	case 8:
-	  if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
-	case 16:
-	  if (!HandleTight16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
-	case 32:
-	  if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
-	    return False;
-	  break;
+	sent_FBU = 0;
+	/*
+	 * we need to be careful since Xt events are processed
+	 * usually in the middle of FBU.  So we do any scheduled ones now
+	 * which is pretty safe but not absolutely safe.
+         */
+	if (do_format_change) {
+		cutover_format_change();
+		do_format_change = 0;
+		SetVisualAndCmap();
+		SetFormatAndEncodings();
+		if (do_cursor_change) {
+			if (do_cursor_change == 1) {
+				DesktopCursorOff();
+			}
+			do_cursor_change = 0;
+		} else {
+			SendFramebufferUpdateRequest(0, 0, si.framebufferWidth,
+			    si.framebufferHeight, False);
+			skip_incFBU = 1;
+		}
 	}
-	break;
-      }
-
-      default:
-	fprintf(stderr,"Unknown rect encoding %d\n",
-		(int)rect.encoding);
-	return False;
-      }
-
-      /* Now we may discard "soft cursor locks". */
-      SoftCursorUnlockScreen();
-    }
 
 #ifdef MITSHM
     /* if using shared memory PutImage, make sure that the X server has
@@ -1224,59 +1601,138 @@
        mainly to avoid copyrect using invalid screen contents - not sure
        if we'd need it otherwise. */
 
-    if (appData.useShm)
-      XSync(dpy, False);
+	if (appData.useShm) {
+		XSync(dpy, False);
+	} else
 #endif
+	{
+		XSync(dpy, False);
+	}
+	
+	if (skip_XtUpdate || skip_incFBU) {
+		;
+	} else if (!SendIncrementalFramebufferUpdateRequest()) {
+		return False;
+	}
 
-    if (!SendIncrementalFramebufferUpdateRequest())
-      return False;
-
-    break;
+	break;
   }
 
   case rfbBell:
   {
-    Window toplevelWin;
+	Window toplevelWin;
 
-    XBell(dpy, 0);
+	XBell(dpy, 0);
 
-    if (appData.raiseOnBeep) {
-      toplevelWin = XtWindow(toplevel);
-      XMapRaised(dpy, toplevelWin);
+	if (appData.raiseOnBeep) {
+		toplevelWin = XtWindow(toplevel);
+		XMapRaised(dpy, toplevelWin);
+	}
+
+	break;
     }
 
-    break;
-  }
+    case rfbServerCutText:
+    {
+	if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbServerCutTextMsg - 1)) {
+		return False;
+	}
 
-  case rfbServerCutText:
-  {
-    if (!ReadFromRFBServer(((char *)&msg) + 1,
-			   sz_rfbServerCutTextMsg - 1))
-      return False;
+	msg.sct.length = Swap32IfLE(msg.sct.length);
 
-    msg.sct.length = Swap32IfLE(msg.sct.length);
+	if (serverCutText) {
+		free(serverCutText);
+	}
 
-    if (serverCutText)
-      free(serverCutText);
+	serverCutText = malloc(msg.sct.length+1);
 
-    serverCutText = malloc(msg.sct.length+1);
+	if (!ReadFromRFBServer(serverCutText, msg.sct.length)) {
+		return False;
+	}
 
-    if (!ReadFromRFBServer(serverCutText, msg.sct.length))
-      return False;
+	serverCutText[msg.sct.length] = 0;
 
-    serverCutText[msg.sct.length] = 0;
+	newServerCutText = True;
 
-    newServerCutText = True;
+	break;
+    }
 
-    break;
-  }
+    case rfbTextChat:
+    {
+	char *buffer = NULL;
+	if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbTextChatMsg - 1)) {
+		return False;
+	}
+	msg.tc.length = Swap32IfLE(msg.tc.length);
+	switch(msg.tc.length) {
+	case rfbTextChatOpen:
+		fprintf(stderr, "\n*ChatOpen*\n\nSend: ");
+		raiseme();
+		appData.chatActive = True;
+		break;
+	case rfbTextChatClose:
+		fprintf(stderr, "\n*ChatClose*\n");
+		raiseme();
+		appData.chatActive = False;
+		break;
+	case rfbTextChatFinished:
+		fprintf(stderr, "\n*ChatFinished*\n");
+		appData.chatActive = False;
+		break;
+	default:
+		buffer = (char *)malloc(msg.tc.length+1);
+		if (!ReadFromRFBServer(buffer, msg.tc.length)) {
+			free(buffer);
+			return False;
+		}
+		buffer[msg.tc.length] = '\0';
+		appData.chatActive = True;
+		GotChatText(buffer, msg.tc.length);
+		free(buffer);
+	}
+	break;
+    }
 
-  default:
-    fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type);
-    return False;
-  }
+    case rfbRestartConnection:
+    {
+	rfbRestartConnectionMsg rc;
+	int len;
+	char *rs_str;
+	char buf[5] = "\xff\xff\xff\xff";
+	fprintf(stderr, "rfbRestartConnection. type=%d\n", (int) rc.type);
+	if (!ReadFromRFBServer((char *)&rc + 1, sz_rfbRestartConnectionMsg - 1)) {
+		return False;
+	}
+	len = Swap32IfLE(rc.length);
+	fprintf(stderr, "rfbRestartConnection. pad1=%d\n", (int) rc.pad1);
+	fprintf(stderr, "rfbRestartConnection. pad2=%d\n", (int) rc.pad2);
+	fprintf(stderr, "rfbRestartConnection. len=%d\n", len);
+	if (len) {
+		rs_str = (char *)malloc(2*len);	
+		if (!ReadFromRFBServer(rs_str, len)) {
+			return False;
+		}
+		restart_session_pw = rs_str;
+		restart_session_len = len;
+	}
+	if (!WriteExact(rfbsock, buf, 4)) {
+		return False;
+	}
+	InitialiseRFBConnection();
+	SetVisualAndCmap();
+	SetFormatAndEncodings();
+	DesktopCursorOff();
+	SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False);
 
-  return True;
+	break;
+    }
+
+    default:
+	fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type);
+	return False;
+    }
+
+    return True;
 }
 
 
@@ -1296,12 +1752,19 @@
 #define CONCAT2(a,b) a##b
 #define CONCAT2E(a,b) CONCAT2(a,b)
 
+#define CONCAT3(a,b,c) a##b##c
+#define CONCAT3E(a,b,c) CONCAT3(a,b,c)
+
+static unsigned char* frameBuffer = NULL;
+static int frameBufferLen = 0;
+
 #define BPP 8
 #include "rre.c"
 #include "corre.c"
 #include "hextile.c"
 #include "zlib.c"
 #include "tight.c"
+#include "zrle.c"
 #undef BPP
 #define BPP 16
 #include "rre.c"
@@ -1309,6 +1772,7 @@
 #include "hextile.c"
 #include "zlib.c"
 #include "tight.c"
+#include "zrle.c"
 #undef BPP
 #define BPP 32
 #include "rre.c"
@@ -1316,6 +1780,15 @@
 #include "hextile.c"
 #include "zlib.c"
 #include "tight.c"
+#include "zrle.c"
+#define REALBPP 24
+#include "zrle.c"
+#define REALBPP 24
+#define UNCOMP 8
+#include "zrle.c"
+#define REALBPP 24
+#define UNCOMP -8
+#include "zrle.c"
 #undef BPP
 
 /*
@@ -1358,9 +1831,9 @@
 	    "  %s significant bit in each byte is leftmost on the screen.\n",
 	    (format->bigEndian ? "Most" : "Least"));
   } else {
-    fprintf(stderr,"  %d bits per pixel.\n",format->bitsPerPixel);
+    fprintf(stderr,"  %d bits per pixel.  ",format->bitsPerPixel);
     if (format->bitsPerPixel != 8) {
-      fprintf(stderr,"  %s significant byte first in each pixel.\n",
+      fprintf(stderr,"%s significant byte first in each pixel.\n",
 	      (format->bigEndian ? "Most" : "Least"));
     }
     if (format->trueColour) {
@@ -1463,3 +1936,115 @@
   cinfo->src = &jpegSrcManager;
 }
 
+#define DO_ZYWRLE 0
+#if DO_ZYWRLE
+
+#define ZYWRLE_ENDIAN ENDIAN_LITTLE
+
+#undef END_FIX
+#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
+#  define END_FIX LE
+#elif ZYWRLE_ENDIAN == ENDIAN_BIG
+#  define END_FIX BE
+#else
+#  define END_FIX NE
+#endif
+#define ZYWRLE_DECODE
+
+#ifndef __RFB_CONCAT2E
+#define __RFB_CONCAT2(a,b) a##b
+#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b)
+#endif
+
+#ifndef __RFB_CONCAT3E
+#define __RFB_CONCAT3(a,b,c) a##b##c
+#define __RFB_CONCAT3E(a,b,c) __RFB_CONCAT3(a,b,c)
+#endif
+
+#undef END_FIX
+#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
+#  define END_FIX LE
+#elif ZYWRLE_ENDIAN == ENDIAN_BIG
+#  define END_FIX BE
+#else
+#  define END_FIX NE
+#endif
+
+#include "zrletypes.h"
+#include "zrlepalettehelper.h"
+
+#if 0
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+
+#ifdef CPIXEL
+#define PIXEL_T __RFB_CONCAT3E(uint,BPP,_t)
+#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL)
+#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,CPIXEL,END_FIX)
+#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,CPIXEL,END_FIX)
+#define BPPOUT 24
+#elif BPP==15
+#define PIXEL_T __RFB_CONCAT3E(uint,16,_t)
+#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,16)
+#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
+#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
+#define BPPOUT 16
+#else
+#define PIXEL_T __RFB_CONCAT3E(uint,BPP,_t)
+#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP)
+#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
+#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
+#define BPPOUT BPP
+#endif
+
+#else
+
+#ifdef CPIXEL
+#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
+#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL)
+#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,CPIXEL,END_FIX)
+#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,CPIXEL,END_FIX)
+#define BPPOUT 24
+#elif BPP==15
+#define PIXEL_T __RFB_CONCAT2E(zrle_U,16)
+#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,16)
+#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
+#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
+#define BPPOUT 16
+#else
+#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
+#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP)
+#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
+#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
+#define BPPOUT BPP
+#endif
+
+#endif
+
+#ifndef ZRLE_ONCE
+#define ZRLE_ONCE
+
+static const int bitsPerPackedPixel[] = {
+  0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
+};
+
+int zywrle_level;
+int zywrleBuf[rfbZRLETileWidth*rfbZRLETileHeight];
+
+static zrlePaletteHelper paletteHelper;
+
+#endif /* ZRLE_ONCE */
+
+#if 0
+void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os);
+#endif
+
+#define BPP 16
+#include "zywrletemplate.c"
+#undef BPP
+#define BPP 32
+#include "zywrletemplate.c"
+#undef BPP
+
+#endif	/* DO_ZYWRLE */
+
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rre.c vnc_unixsrc/vncviewer/rre.c
--- vnc_unixsrc.orig/vncviewer/rre.c	2000-06-11 08:00:53.000000000 -0400
+++ vnc_unixsrc/vncviewer/rre.c	2007-02-17 22:52:24.000000000 -0500
@@ -29,6 +29,18 @@
 #define HandleRREBPP CONCAT2E(HandleRRE,BPP)
 #define CARDBPP CONCAT2E(CARD,BPP)
 
+#define FillRectangle(x, y, w, h, color)  \
+	{ \
+		XGCValues _gcv; \
+		_gcv.foreground = color; \
+		if (!appData.useBackingstore) { \
+			FillScreen(x, y, w, h, _gcv.foreground); \
+		} else { \
+			XChangeGC(dpy, gc, GCForeground, &_gcv); \
+			XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \
+		} \
+	}
+
 static Bool
 HandleRREBPP (int rx, int ry, int rw, int rh)
 {
@@ -49,11 +61,19 @@
 #if (BPP == 8)
   gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix);
 #else
+#if (BPP == 16)
+  gcv.foreground = (appData.useBGR565 ? BGR565ToPixel[pix] : pix);
+#else
   gcv.foreground = pix;
 #endif
+#endif
 
+#if 0
   XChangeGC(dpy, gc, GCForeground, &gcv);
   XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
+#else
+  FillRectangle(rx, ry, rw, rh, gcv.foreground);
+#endif
 
   for (i = 0; i < hdr.nSubrects; i++) {
     if (!ReadFromRFBServer((char *)&pix, sizeof(pix)))
@@ -70,13 +90,23 @@
 #if (BPP == 8)
     gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix);
 #else
+#if (BPP == 16)
+    gcv.foreground = (appData.useBGR565 ? BGR565ToPixel[pix] : pix);
+#else
     gcv.foreground = pix;
 #endif
+#endif
 
+#if 0
     XChangeGC(dpy, gc, GCForeground, &gcv);
     XFillRectangle(dpy, desktopWin, gc, rx + subrect.x, ry + subrect.y,
 		   subrect.w, subrect.h);
+#else
+    FillRectangle(rx + subrect.x, ry + subrect.y, subrect.w, subrect.h, gcv.foreground);
+#endif
   }
 
   return True;
 }
+
+#undef FillRectangle
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/shm.c
--- vnc_unixsrc.orig/vncviewer/shm.c	2000-06-11 08:00:53.000000000 -0400
+++ vnc_unixsrc/vncviewer/shm.c	2007-03-23 22:20:35.000000000 -0400
@@ -33,68 +33,80 @@
 void
 ShmCleanup()
 {
-  fprintf(stderr,"ShmCleanup called\n");
-  if (needShmCleanup) {
-    shmdt(shminfo.shmaddr);
-    shmctl(shminfo.shmid, IPC_RMID, 0);
-    needShmCleanup = False;
-  }
+	fprintf(stderr,"ShmCleanup called\n");
+	if (needShmCleanup) {
+		shmdt(shminfo.shmaddr);
+		shmctl(shminfo.shmid, IPC_RMID, 0);
+		needShmCleanup = False;
+	}
+}
+
+Bool UsingShm() {
+	return needShmCleanup;
 }
 
 static int
 ShmCreationXErrorHandler(Display *dpy, XErrorEvent *error)
 {
-  caughtShmError = True;
-  return 0;
+	caughtShmError = True;
+	return 0;
 }
 
 XImage *
-CreateShmImage()
+CreateShmImage(int do_ycrop)
 {
-  XImage *image;
-  XErrorHandler oldXErrorHandler;
-
-  if (!XShmQueryExtension(dpy))
-    return NULL;
-
-  image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo,
-			  si.framebufferWidth, si.framebufferHeight);
-  if (!image) return NULL;
-
-  shminfo.shmid = shmget(IPC_PRIVATE,
-			 image->bytes_per_line * image->height,
-			 IPC_CREAT|0777);
-
-  if (shminfo.shmid == -1) {
-    XDestroyImage(image);
-    return NULL;
-  }
-
-  shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0);
-
-  if (shminfo.shmaddr == (char *)-1) {
-    XDestroyImage(image);
-    shmctl(shminfo.shmid, IPC_RMID, 0);
-    return NULL;
-  }
-
-  shminfo.readOnly = True;
-
-  oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler);
-  XShmAttach(dpy, &shminfo);
-  XSync(dpy, False);
-  XSetErrorHandler(oldXErrorHandler);
-
-  if (caughtShmError) {
-    XDestroyImage(image);
-    shmdt(shminfo.shmaddr);
-    shmctl(shminfo.shmid, IPC_RMID, 0);
-    return NULL;
-  }
+	XImage *image;
+	XErrorHandler oldXErrorHandler;
+	int ymax = si.framebufferHeight;
+
+	if (!XShmQueryExtension(dpy)) {
+		return NULL;
+	}
+	if (!appData.useShm) {
+		return NULL;
+	}
+	if (do_ycrop) {
+		ymax = appData.yCrop;
+	}
+
+	image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo,
+	    si.framebufferWidth, ymax);
+	if (!image) {
+		return NULL;
+	}
+
+	shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT|0777);
+
+	if (shminfo.shmid == -1) {
+		XDestroyImage(image);
+		return NULL;
+	}
+
+	shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0);
+
+	if (shminfo.shmaddr == (char *)-1) {
+		XDestroyImage(image);
+		shmctl(shminfo.shmid, IPC_RMID, 0);
+		return NULL;
+	}
+
+	shminfo.readOnly = True;
+
+	oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler);
+	XShmAttach(dpy, &shminfo);
+	XSync(dpy, False);
+	XSetErrorHandler(oldXErrorHandler);
+
+	if (caughtShmError) {
+		XDestroyImage(image);
+		shmdt(shminfo.shmaddr);
+		shmctl(shminfo.shmid, IPC_RMID, 0);
+		return NULL;
+	}
 
-  needShmCleanup = True;
+	needShmCleanup = True;
 
-  fprintf(stderr,"Using shared memory PutImage\n");
+	fprintf(stderr,"Using shared memory (PutImage ycrop=%d)\n", do_ycrop);
 
-  return image;
+	return image;
 }
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/smake vnc_unixsrc/vncviewer/smake
--- vnc_unixsrc.orig/vncviewer/smake	1969-12-31 19:00:00.000000000 -0500
+++ vnc_unixsrc/vncviewer/smake	2007-02-19 12:28:05.000000000 -0500
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+PATH=`pwd`/../..:/usr/sfw/bin:/usr/ccs/bin:$PATH
+export PATH
+if [ "X$1" != "X" ]; then
+	"$@"
+else
+	make
+	strip vncviewer
+	ls -l vncviewer
+fi
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncviewer/sockets.c
--- vnc_unixsrc.orig/vncviewer/sockets.c	2001-01-14 22:54:18.000000000 -0500
+++ vnc_unixsrc/vncviewer/sockets.c	2007-03-23 21:23:15.000000000 -0400
@@ -63,15 +63,59 @@
   XtRemoveInput(*id);
 }
 
+extern int skip_XtUpdate;
+
 static void
 ProcessXtEvents()
 {
-  rfbsockReady = False;
-  XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask,
-		rfbsockReadyCallback, NULL);
-  while (!rfbsockReady) {
-    XtAppProcessEvent(appContext, XtIMAll);
-  }
+	if (appData.chatActive) {
+		fd_set fds;
+		struct timeval tv;
+		int i, igot = -1, n = fileno(stdin);
+		char strs[100][512];
+		char buf[rfbTextMaxSize];
+
+		for (i=0; i < 100; i++) {
+			FD_ZERO(&fds);
+			FD_SET(n,&fds);
+			tv.tv_sec = 0;
+			tv.tv_usec = 0;
+			if (select(n+1, &fds, NULL, NULL, &tv) > 0) {
+				if (FD_ISSET(n, &fds)) {
+					fgets(strs[i], 512, stdin);
+					igot = i;
+				} else {
+					break;
+				}
+			} else {
+				break;
+			}
+		}
+		buf[0] = '\0';
+		for (i=0; i <= igot; i++) {
+			if (strlen(buf) + strlen(strs[i]) < rfbTextMaxSize) {
+				strcat(buf, strs[i]);
+			} else {
+				SendTextChat(buf);
+				buf[0] = '0';
+			}
+		}
+		if (buf[0] != '\0') {
+			SendTextChat(buf);
+		}
+		if (igot >= 0) fprintf(stderr, "Send: ");
+	}
+	if (skip_XtUpdate) {
+		return;
+	}
+
+	rfbsockReady = False;
+	XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask,
+	    rfbsockReadyCallback, NULL);
+
+	while (!rfbsockReady) {
+		XtAppProcessEvent(appContext, XtIMAll);
+	}
 }
 
 Bool
@@ -283,6 +327,10 @@
   addr.sin_port = htons(port);
   addr.sin_addr.s_addr = INADDR_ANY;
 
+	if (getenv("VNCVIEWER_LISTEN_LOCALHOST")) {
+		addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+	}
+
   sock = socket(AF_INET, SOCK_STREAM, 0);
   if (sock < 0) {
     fprintf(stderr,programName);
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tight.c vnc_unixsrc/vncviewer/tight.c
--- vnc_unixsrc.orig/vncviewer/tight.c	2002-04-30 09:07:31.000000000 -0400
+++ vnc_unixsrc/vncviewer/tight.c	2007-02-17 22:08:20.000000000 -0500
@@ -129,14 +129,21 @@
 #endif
 
 #if (BPP == 8)
-    gcv.foreground = (appData.useBGR233) ?
-      BGR233ToPixel[fill_colour] : fill_colour;
+    gcv.foreground = (appData.useBGR233) ?  BGR233ToPixel[fill_colour] : fill_colour;
+#else
+#if (BPP == 16)
+    gcv.foreground = (appData.useBGR565) ?  BGR565ToPixel[fill_colour] : fill_colour;
 #else
     gcv.foreground = fill_colour;
 #endif
+#endif
 
-    XChangeGC(dpy, gc, GCForeground, &gcv);
-    XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
+	if (!appData.useBackingstore) {
+		FillScreen(rx, ry, rw, rh, gcv.foreground);
+	} else {
+		XChangeGC(dpy, gc, GCForeground, &gcv);
+		XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
+	}
     return True;
   }
 
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vncviewer/vncviewer._man
--- vnc_unixsrc.orig/vncviewer/vncviewer._man	1969-12-31 19:00:00.000000000 -0500
+++ vnc_unixsrc/vncviewer/vncviewer._man	2007-03-20 10:11:33.000000000 -0400
@@ -0,0 +1,497 @@
+'\" t
+.\" ** The above line should force tbl to be a preprocessor **
+.\" Man page for X vncviewer
+.\"
+.\" Copyright (C) 1998 Marcus.Brinkmann@ruhr-uni-bochum.de
+.\" Copyright (C) 2000,2001 Red Hat, Inc.
+.\" Copyright (C) 2001-2003 Constantin Kaplinsky <const@ce.cctpu.edu.ru>
+.\"
+.\" You may distribute under the terms of the GNU General Public
+.\" License as specified in the file LICENCE.TXT that comes with the
+.\" TightVNC distribution.
+.\"
+.TH vncviewer 1 "January 2003" "" "TightVNC"
+.SH NAME
+vncviewer \- an X viewer client for VNC
+.SH SYNOPSIS
+.B vncviewer
+.RI [\| options \|]
+.RI [\| host \|][\| :display \|]
+.br
+.B vncviewer
+.RI [\| options \|]
+.RI [\| host \|][\| ::port \|]
+.br
+.B vncviewer
+.RI [\| options \|]
+.IR \-listen
+.RI [\| display \|]
+.br
+.B vncviewer
+.IR \-help
+.br
+.SH DESCRIPTION
+.B vncviewer
+is an Xt\-based client application for the VNC (Virtual Network
+Computing) system. It can connect to any VNC\-compatible server such
+as \fBXvnc\fR or WinVNC, allowing you to control desktop environment
+of a different machine.
+
+You can use F8 to display a pop\-up utility menu. Press F8 twice to
+pass single F8 to the remote side.
+.SH OPTIONS
+.TP
+\fB\-help\fR
+Prints a short usage notice to stderr.
+.TP
+\fB\-listen\fR
+Make the viewer listen on port 5500+\fIdisplay\fR for reverse
+connections from a server. WinVNC supports reverse connections using
+the "Add New Client" menu option, or the \-connect command line
+option. \fBXvnc\fR requires the use of the helper program
+\fBvncconnect\fR.
+.TP
+\fB\-via\fR \fIgateway\fR
+Automatically create encrypted TCP tunnel to the \fIgateway\fR machine
+before connection, connect to the \fIhost\fR through that tunnel
+(TightVNC\-specific). By default, this option invokes SSH local port
+forwarding, assuming that SSH client binary can be accessed as
+/usr/bin/ssh. Note that when using the \fB\-via\fR option, the host
+machine name should be specified as known to the gateway machine, e.g. 
+"localhost" denotes the \fIgateway\fR, not the machine where vncviewer
+was launched. See the ENVIRONMENT section below for the information on
+configuring the \fB\-via\fR option.
+.TP
+\fB\-shared\fR
+When connecting, specify that a shared connection is requested. In
+TightVNC, this is the default mode, allowing you to share the desktop
+with other clients already using it.
+.TP
+\fB\-noshared\fR
+When connecting, specify that the session may not be shared. This
+would either disconnect other connected clients or refuse your
+connection, depending on the server configuration.
+.TP
+\fB\-viewonly\fR
+Disable transfer of mouse and keyboard events from the client to the
+server.
+.TP
+\fB\-fullscreen\fR
+Start in full\-screen mode. Please be aware that operating in
+full\-screen mode may confuse X window managers. Typically, such
+conflicts cause incorrect handling of input focus or make the viewer
+window disappear mysteriously. See the grabKeyboard setting in the
+RESOURCES section below for a method to solve input focus problem.
+.TP
+\fB\-noraiseonbeep\fR
+By default, the viewer shows and raises its window on remote beep
+(bell) event. This option disables such behaviour
+(TightVNC\-specific).
+.TP
+\fB\-user\fR \fIusername\fR
+User name for Unix login authentication. Default is to use current
+Unix user name. If this option was given, the viewer will prefer Unix
+login authentication over the standard VNC authentication.
+.TP
+\fB\-passwd\fR \fIpasswd\-file\fR
+File from which to get the password (as generated by the
+\fBvncpasswd\fR(1) program). This option affects only the standard VNC
+authentication.
+.TP
+\fB\-encodings\fR \fIencoding\-list\fR
+TightVNC supports several different compression methods to encode
+screen updates; this option specifies a set of them to use in order of
+preference. Encodings are specified separated with spaces, and must
+thus be enclosed in quotes if more than one is specified. Available
+encodings, in default order for a remote connection, are "copyrect
+tight hextile zlib corre rre raw". For a local connection (to the same
+machine), the default order to try is "raw copyrect tight hextile zlib
+corre rre". Raw encoding is always assumed as a last option if no
+other encoding can be used for some reason. For more information on
+encodings, see the section ENCODINGS below.
+.TP
+\fB\-bgr233\fR
+Always use the BGR233 format to encode pixel data. This reduces
+network traffic, but colors may be represented inaccurately. The
+bgr233 format is an 8\-bit "true color" format, with 2 bits blue, 3
+bits green, and 3 bits red.
+.TP
+\fB\-owncmap\fR
+Try to use a PseudoColor visual and a private colormap. This allows
+the VNC server to control the colormap.
+.TP
+\fB\-truecolour\fR, \fB\-truecolor\fR
+Try to use a TrueColor visual.
+.TP
+\fB\-depth\fR \fIdepth\fR
+On an X server which supports multiple TrueColor visuals of different
+depths, attempt to use the specified one (in bits per pixel); if
+successful, this depth will be requested from the VNC server.
+.TP
+\fB\-compresslevel \fIlevel\fR
+Use specified compression \fIlevel\fR (0..9) for "tight" and "zlib"
+encodings (TightVNC\-specific). Level 1 uses minimum of CPU time and
+achieves weak compression ratios, while level 9 offers best
+compression but is slow in terms of CPU time consumption on the server
+side. Use high levels with very slow network connections, and low
+levels when working over high\-speed LANs. It's not recommended to use
+compression level 0, reasonable choices start from the level 1.
+.TP
+\fB\-quality \fIlevel\fR
+Use the specified JPEG quality \fIlevel\fR (0..9) for the "tight"
+encoding (TightVNC\-specific). Quality level 0 denotes bad image
+quality but very impressive compression ratios, while level 9 offers
+very good image quality at lower compression ratios. Note that the
+"tight" encoder uses JPEG to encode only those screen areas that look
+suitable for lossy compression, so quality level 0 does not always
+mean unacceptable image quality.
+.TP
+\fB\-nojpeg\fR
+Disable lossy JPEG compression in Tight encoding (TightVNC\-specific). 
+Disabling JPEG compression is not a good idea in typical cases, as
+that makes the Tight encoder less efficient. You might want to use
+this option if it's absolutely necessary to achieve perfect image
+quality (see also the \fB\-quality\fR option).
+.TP
+\fB\-nocursorshape\fR
+Disable cursor shape updates, protocol extensions used to handle
+remote cursor movements locally on the client side
+(TightVNC\-specific). Using cursor shape updates decreases delays with
+remote cursor movements, and can improve bandwidth usage dramatically. 
+.TP
+\fB\-x11cursor\fR
+Use a real X11 cursor with X-style cursor shape updates, instead of
+drawing the remote cursor on the framebuffer. This option also
+disables the dot cursor, and disables cursor position updates in
+non-fullscreen mode.
+.TP
+\fB\-autopass\fR
+Read a plain-text password from stdin. This option affects only the
+standard VNC authentication.
+
+.SH Enhanced TightVNC Viewer OPTIONS
+.TP
+Enhanced TightVNC Viewer web page is located at:
+.TP
+http://www.karlrunge.com/x11vnc/ssvnc.html
+.TP
+Note: ZRLE encoding is now supported.
+.TP
+Note: F9 is shortcut to Toggle FullScreen mode.
+.TP
+\fB\-use64\fR
+In \fB\-bgr233\fR mode, use 64 colors instead of 256.
+.TP
+\fB\-bgr222\fR
+Same as \fB\-use64\fR.
+.TP
+\fB\-use8\fR
+In \fB\-bgr233\fR mode, use 8 colors instead of 256.
+.TP
+\fB\-bgr111\fR
+Same as \fB\-use8\fR.
+.TP
+\fB\-16bpp\fR
+If the vnc viewer X display is depth 24 at 32bpp
+request a 16bpp format from the VNC server to cut
+network traffic by up to 2X, then tranlate the
+pixels to 32bpp locally.
+.TP
+\fB\-bgr565\fR
+Same as \fB\-16bpp\fR.
+.TP
+\fB\-alpha\fR
+Use alphablending transparency for local cursors
+requires: x11vnc server, both client and server
+must be 32bpp and same endianness.
+.TP
+\fB\-ycrop\fR n
+Only show the top n rows of the framebuffer.  For
+use with x11vnc \fB\-ncache\fR client caching option
+to help "hide" the pixel cache region.
+Use a negative value (e.g. \fB\-1\fR) for autodetection.
+Autodetection will always take place if the remote
+fb height is more than 2 times the width.
+.TP
+\fB\-sbwidth\fR n
+Scrollbar width, default is very narrow: 2 pixels,
+it is narrow to avoid distraction in \fB\-ycrop\fR mode.
+.TP
+\fB\-rawlocal\fR
+Prefer raw encoding for localhost, default is
+no, i.e. assumes you have a SSH tunnel instead.
+.TP
+\fB\-graball\fR
+Grab the entire X server when in fullscreen mode,
+needed by some old window managers like fvwm2.
+.TP
+\fB\-popupfix\fR
+Warp the popup back to the pointer position,
+needed by some old window managers like fvwm2.
+.TP
+\fB\-grabkbd\fR
+Grab the X keyboard when in fullscreen mode,
+needed by some window managers. Same as \fB\-grabkeyboard\fR.
+\fB\-grabkbd\fR is the default, use \fB\-nograbkbd\fR to disable.
+.TP
+\fB\-bs/-nobs\fR
+Whether or not to use X server Backingstore for the
+main viewer window.  The default is to not, mainly
+because most Linux, etc, systems X servers disable
+*all* Backingstore by default.  To re-enable it put
+
+Option "Backingstore"
+
+in the Device section of /etc/X11/xorg.conf.
+In -bs mode with no X server backingstore, whenever an
+area of the screen is re-exposed it must go out to the
+VNC server to retrieve the pixels. This is too slow.
+
+In -nobs mode, memory is allocated by the viewer to
+provide its own backing of the main viewer window. This
+actually makes some activities faster (changes in large
+regions) but can appear to "flash" too much.
+.TP
+\fB\-noshm\fR
+Disable use of MIT shared memory extension (not recommended)
+.TP
+\fB New Popup actions:\fR
+
+ Cursor Shape:            ~ -nocursorshape
+ X11 Cursor:              ~ -x11cursor
+ Cursor Alphablend:       ~ -alpha
+ Disable JPEG:            ~ -nojpeg
+ Prefer raw for localhost ~ -rawlocal
+ Full Color                 as many colors as local screen allows.
+ Grey scale (16 & 8-bpp)  ~ -grey, for low colors 16/8bpp modes only.
+ 16 bit color (BGR565)    ~ -bgr565
+ 8  bit color (BGR233)    ~ -bgr233
+ 256 colors               ~ -bgr233 default # of colors.
+  64 colors               ~ -bgr222 / -use64
+   8 colors               ~ -bgr111 / -use8
+
+ 
+ Disable Remote Input       Ultravnc ext.  Try to prevent input and
+                            viewing of monitor at physical display.
+ Single Window              Ultravnc ext.  Grab and a single window.
+                            (click on the window you want).
+ Set 1/n Server Scale       Ultravnc ext.  Scale desktop by 1/n.
+                            prompt is from the terminal.
+ Text Chat                  Ultravnc ext.  Do Text Chat, currently
+                            input via the terminal (no window).
+ 
+ Note: the Ultravnc extensions only apply to servers that support
+       them.  x11vnc/libvncserver supports some of them.
+
+.SH ENCODINGS
+The server supplies information in whatever format is desired by the
+client, in order to make the client as easy as possible to implement. 
+If the client represents itself as able to use multiple formats, the
+server will choose one.
+
+.I Pixel format
+refers to the representation of an individual pixel. The most common
+formats are 24 and 16 bit "true\-color" values, and 8\-bit "color map"
+representations, where an arbitrary map converts the color number to
+RGB values.
+
+.I Encoding
+refers to how a rectangle of pixels are sent (all pixel information in
+VNC is sent as rectangles). All rectangles come with a header giving
+the location and size of the rectangle and an encoding type used by
+the data which follows. These types are listed below.
+.TP
+.B Raw
+The raw encoding simply sends width*height pixel values. All clients
+are required to support this encoding type. Raw is also the fastest
+when the server and viewer are on the same machine, as the connection
+speed is essentially infinite and raw encoding minimizes processing
+time.
+.TP
+.B CopyRect
+The Copy Rectangle encoding is efficient when something is being
+moved; the only data sent is the location of a rectangle from which
+data should be copied to the current location. Copyrect could also be
+used to efficiently transmit a repeated pattern.
+.TP
+.B RRE
+The Rise\-and\-Run\-length\-Encoding is basically a 2D version of
+run\-length encoding (RLE). In this encoding, a sequence of identical
+pixels are compressed to a single value and repeat count. In VNC, this
+is implemented with a background color, and then specifications of an
+arbitrary number of subrectangles and color for each. This is an
+efficient encoding for large blocks of constant color.
+.TP
+.B CoRRE
+This is a minor variation on RRE, using a maximum of 255x255 pixel
+rectangles. This allows for single\-byte values to be used, reducing
+packet size. This is in general more efficient, because the savings
+from sending 1\-byte values generally outweighs the losses from the
+(relatively rare) cases where very large regions are painted the same
+color.
+.TP
+.B Hextile
+Here, rectangles are split up in to 16x16 tiles, which are sent in a
+predetermined order. The data within the tiles is sent either raw or
+as a variant on RRE. Hextile encoding is usually the best choice for
+using in high\-speed network environments (e.g. Ethernet local\-area
+networks).
+.TP
+.B Zlib
+Zlib is a very simple encoding that uses zlib library to compress raw
+pixel data. This encoding achieves good compression, but consumes a
+lot of CPU time. Support for this encoding is provided for
+compatibility with VNC servers that might not understand Tight
+encoding which is more efficient than Zlib in nearly all real\-life
+situations.
+.TP
+.B Tight
+Like Zlib encoding, Tight encoding uses zlib library to compress the
+pixel data, but it pre\-processes data to maximize compression ratios,
+and to minimize CPU usage on compression. Also, JPEG compression may
+be used to encode color\-rich screen areas (see the description of
+\-quality and \-nojpeg options above). Tight encoding is usually the
+best choice for low\-bandwidth network environments (e.g. slow modem
+connections).
+.SH RESOURCES
+X resources that \fBvncviewer\fR knows about, aside from the
+normal Xt resources, are as follows:
+.TP
+.B shareDesktop
+Equivalent of \fB\-shared\fR/\fB\-noshared\fR options. Default true.
+.TP
+.B viewOnly
+Equivalent of \fB\-viewonly\fR option. Default false.
+.TP
+.B fullScreen
+Equivalent of \fB\-fullscreen\fR option. Default false.
+.TP
+.B grabKeyboard
+Grab keyboard in full-screen mode. This can help to solve problems
+with losing keyboard focus. Default false.
+.TP
+.B raiseOnBeep
+Equivalent of \fB\-noraiseonbeep\fR option, when set to false. Default
+true.
+.TP
+.B passwordFile
+Equivalent of \fB\-passwd\fR option.
+.TP
+.B userLogin
+Equivalent of \fB\-user\fR option.
+.TP
+.B passwordDialog
+Whether to use a dialog box to get the password (true) or get it from
+the tty (false). Irrelevant if \fBpasswordFile\fR is set. Default
+false.
+.TP
+.B encodings
+Equivalent of \fB\-encodings\fR option.
+.TP
+.B compressLevel
+Equivalent of \fB\-compresslevel\fR option (TightVNC\-specific).
+.TP
+.B qualityLevel
+Equivalent of \fB\-quality\fR option (TightVNC\-specific).
+.TP
+.B enableJPEG
+Equivalent of \fB\-nojpeg\fR option, when set to false. Default true.
+.TP
+.B useRemoteCursor
+Equivalent of \fB\-nocursorshape\fR option, when set to false
+(TightVNC\-specific). Default true.
+.TP
+.B useBGR233
+Equivalent of \fB\-bgr233\fR option. Default false.
+.TP
+.B nColours
+When using BGR233, try to allocate this many "exact" colors from the
+BGR233 color cube. When using a shared colormap, setting this resource
+lower leaves more colors for other X clients. Irrelevant when using
+truecolor. Default is 256 (i.e. all of them).
+.TP
+.B useSharedColours
+If the number of "exact" BGR233 colors successfully allocated is less
+than 256 then the rest are filled in using the "nearest" colors
+available. This resource says whether to only use the "exact" BGR233
+colors for this purpose, or whether to use other clients' "shared"
+colors as well. Default true (i.e. use other clients' colors).
+.TP
+.B forceOwnCmap
+Equivalent of \fB\-owncmap\fR option. Default false.
+.TP
+.B forceTrueColour
+Equivalent of \fB\-truecolour\fR option. Default false.
+.TP
+.B requestedDepth
+Equivalent of \fB\-depth\fR option.
+.TP
+.B useSharedMemory
+Use MIT shared memory extension if on the same machine as the X
+server. Default true.
+.TP
+.B wmDecorationWidth, wmDecorationHeight
+The total width and height taken up by window manager decorations.
+This is used to calculate the maximum size of the VNC viewer window. 
+Default is width 4, height 24.
+.TP
+.B bumpScrollTime, bumpScrollPixels
+When in full screen mode and the VNC desktop is bigger than the X
+display, scrolling happens whenever the mouse hits the edge of the
+screen. The maximum speed of scrolling is bumpScrollPixels pixels
+every bumpScrollTime milliseconds. The actual speed of scrolling will
+be slower than this, of course, depending on how fast your machine is. 
+Default 20 pixels every 25 milliseconds.
+.TP
+.B popupButtonCount
+The number of buttons in the popup window. See the README file for
+more information on how to customize the buttons.
+.TP
+.B debug
+For debugging. Default false.
+.TP
+.B rawDelay, copyRectDelay
+For debugging, see the README file for details. Default 0 (off).
+.SH ENVIRONMENT
+When started with the \fB\-via\fR option, vncviewer reads the
+\fBVNC_VIA_CMD\fR environment variable, expands patterns beginning
+with the "%" character, and executes result as a command assuming that
+it would create TCP tunnel that should be used for VNC connection. If
+not set, this environment variable defaults to "/usr/bin/ssh -f -L
+%L:%H:%R %G sleep 20".
+
+The following patterns are recognized in the \fBVNC_VIA_CMD\fR (note
+that all the patterns %G, %H, %L and %R must be present in the command
+template):
+.TP
+.B %%
+A literal "%";
+.TP
+.B %G
+gateway host name;
+.TP
+.B %H
+remote VNC host name, as known to the gateway;
+.TP
+.B %L
+local TCP port number;
+.TP
+.B %R
+remote TCP port number.
+.SH SEE ALSO
+\fBvncserver\fR(1), \fBXvnc\fR(1), \fBvncpasswd\fR(1),
+\fBvncconnect\fR(1), \fBssh\fR(1)
+.SH AUTHORS
+Original VNC was developed in AT&T Laboratories Cambridge. TightVNC
+additions was implemented by Constantin Kaplinsky. Many other people
+participated in development, testing and support.
+
+\fBMan page authors:\fR
+.br
+Marcus Brinkmann <Marcus.Brinkmann@ruhr-uni-bochum.de>,
+.br
+Terran Melconian <terran@consistent.org>,
+.br
+Tim Waugh <twaugh@redhat.com>,
+.br
+Constantin Kaplinsky <const@ce.cctpu.edu.ru>
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncviewer/vncviewer.c
--- vnc_unixsrc.orig/vncviewer/vncviewer.c	2004-01-13 09:22:05.000000000 -0500
+++ vnc_unixsrc/vncviewer/vncviewer.c	2007-02-18 18:45:43.000000000 -0500
@@ -22,6 +22,7 @@
  */
 
 #include "vncviewer.h"
+#include <X11/Xaw/Toggle.h>
 
 char *programName;
 XtAppContext appContext;
@@ -29,11 +30,47 @@
 
 Widget toplevel;
 
+void set_sbwidth(int sbw) {
+	char *q, *p, t[5];
+	int i, k, N = 4;
+	int db = 0;
+
+	if (sbw < 1) {
+		sbw = 2;
+	} else if (sbw > 100) {
+		sbw = 100;
+	}
+	if (db) fprintf(stderr, "sbw: %d\n", sbw);
+
+	sprintf(t, "%4d", sbw);
+	k = 0;
+	while (fallback_resources[k] != NULL) {
+		q = strstr(fallback_resources[k], "horizontal.height: ");
+		if (!q) {
+			q = strstr(fallback_resources[k], "vertical.width: ");
+		}
+		if (q) {
+			p = strdup(fallback_resources[k]);
+			q = strstr(p, ":   ");
+			if (q) {
+				q++;
+				q++;
+				for (i=0; i < N; i++) {
+					*(q+i) = t[i];
+				}
+				fallback_resources[k] = p;
+				if (db) fprintf(stderr, "res: %s\n", p);
+			}
+		}
+		k++;
+	}
+}
+
 int
 main(int argc, char **argv)
 {
-  int i;
-  programName = argv[0];
+	int i, save_sbw;
+	programName = argv[0];
 
   /* The -listen option is used to make us a daemon process which listens for
      incoming connections from servers, rather than actively connecting to a
@@ -45,89 +82,718 @@
      listenForIncomingConnections() returns, setting the listenSpecified
      flag. */
 
-  for (i = 1; i < argc; i++) {
-    if (strcmp(argv[i], "-listen") == 0) {
-      listenForIncomingConnections(&argc, argv, i);
-      break;
-    }
-    if (strcmp(argv[i], "-tunnel") == 0 || strcmp(argv[i], "-via") == 0) {
-      if (!createTunnel(&argc, argv, i))
-	exit(1);
-      break;
-    }
-  }
+	for (i = 1; i < argc; i++) {
+		if (strcmp(argv[i], "-listen") == 0) {
+			listenForIncomingConnections(&argc, argv, i);
+			break;
+		}
+		if (strcmp(argv[i], "-tunnel") == 0 || strcmp(argv[i], "-via") == 0) {
+			if (!createTunnel(&argc, argv, i)) {
+				exit(1);
+			}
+			break;
+		}
+	}
+
+	if (argc > 1 && strstr(argv[1], "-h") == argv[1]) {
+		usage();
+		return 0;
+	}
 
   /* Call the main Xt initialisation function.  It parses command-line options,
      generating appropriate resource specs, and makes a connection to the X
      display. */
 
-  toplevel = XtVaAppInitialize(&appContext, "Vncviewer",
-			       cmdLineOptions, numCmdLineOptions,
-			       &argc, argv, fallback_resources,
-			       XtNborderWidth, 0, NULL);
+	appData.sbWidth = 0;
+	if (getenv("VNCVIEWER_SBWIDTH")) {
+		int sbw = atoi(getenv("VNCVIEWER_SBWIDTH"));
+		if (sbw > 0) {
+			appData.sbWidth = sbw;
+		}
+	}
+	if (appData.sbWidth == 0) {
+		int i, sbw = 0;
+		for (i = 1; i < argc - 1; i++) {
+			if (!strcmp(argv[i], "-sbwidth")) {
+				sbw = atoi(argv[i+1]);
+			}
+		}
+		if (sbw > 0) {
+			appData.sbWidth = sbw;
+		}
+	}
+	save_sbw = appData.sbWidth;
+	set_sbwidth(6);
+
+	toplevel = XtVaAppInitialize(&appContext, "Vncviewer", cmdLineOptions,
+	    numCmdLineOptions, &argc, argv, fallback_resources,
+	    XtNborderWidth, 0, NULL);
 
-  dpy = XtDisplay(toplevel);
+	dpy = XtDisplay(toplevel);
 
   /* Interpret resource specs and process any remaining command-line arguments
      (i.e. the VNC server name).  If the server name isn't specified on the
      command line, getArgsAndResources() will pop up a dialog box and wait
      for one to be entered. */
 
-  GetArgsAndResources(argc, argv);
+	GetArgsAndResources(argc, argv);
+
+	if (save_sbw) {
+		appData.sbWidth = save_sbw;
+	}
 
   /* Unless we accepted an incoming connection, make a TCP connection to the
      given VNC server */
 
-  if (!listenSpecified) {
-    if (!ConnectToRFBServer(vncServerHost, vncServerPort)) exit(1);
-  }
+	if (!listenSpecified) {
+		if (!ConnectToRFBServer(vncServerHost, vncServerPort)) {
+			exit(1);
+		}
+	}
 
   /* Initialise the VNC connection, including reading the password */
 
-  if (!InitialiseRFBConnection()) exit(1);
+	if (!InitialiseRFBConnection()) {
+		exit(1);
+	}
 
   /* Create the "popup" widget - this won't actually appear on the screen until
      some user-defined event causes the "ShowPopup" action to be invoked */
 
-  CreatePopup();
+	CreatePopup();
 
   /* Find the best pixel format and X visual/colormap to use */
 
-  SetVisualAndCmap();
+	SetVisualAndCmap();
 
   /* Create the "desktop" widget, and perform initialisation which needs doing
      before the widgets are realized */
 
-  ToplevelInitBeforeRealization();
+	ToplevelInitBeforeRealization();
 
-  DesktopInitBeforeRealization();
+	DesktopInitBeforeRealization();
 
   /* "Realize" all the widgets, i.e. actually create and map their X windows */
 
-  XtRealizeWidget(toplevel);
+	XtRealizeWidget(toplevel);
 
   /* Perform initialisation that needs doing after realization, now that the X
      windows exist */
 
-  InitialiseSelection();
+	InitialiseSelection();
 
-  ToplevelInitAfterRealization();
+	ToplevelInitAfterRealization();
 
-  DesktopInitAfterRealization();
+	DesktopInitAfterRealization();
 
   /* Tell the VNC server which pixel format and encodings we want to use */
 
-  SetFormatAndEncodings();
+	SetFormatAndEncodings();
 
   /* Now enter the main loop, processing VNC messages.  X events will
      automatically be processed whenever the VNC connection is idle. */
 
-  while (1) {
-    if (!HandleRFBServerMessage())
-      break;
-  }
+	while (1) {
+		if (!HandleRFBServerMessage()) {
+			break;
+		}
+	}
+
+	Cleanup();
+
+	return 0;
+}
+
+/*
+ * Toggle8bpp
+ */
+
+static int last_ncolors = 0;
+static int save_useBGR233 = 0;
+static Bool save_useBGR565 = False;
+
+static Widget b8    = NULL;
+static Widget b16   = NULL;
+static Widget bfull = NULL;
+
+int do_format_change = 0;
+int do_cursor_change = 0;
+static void schedule_format_change(void) {
+	do_format_change = 1;
+	do_cursor_change = 0;
+}
+static void init_format_change(void) {
+	appDataNew.useBGR233       = appData.useBGR233;
+	appDataNew.useBGR565       = appData.useBGR565;
+	appDataNew.useGreyScale    = appData.useGreyScale;
+	appDataNew.enableJPEG      = appData.enableJPEG;
+	appDataNew.encodingsString = appData.encodingsString;
+	appDataNew.useRemoteCursor = appData.useRemoteCursor;
+	appDataNew.useX11Cursor    = appData.useX11Cursor;
+	appDataNew.useRawLocal     = appData.useRawLocal;
+}
+void cutover_format_change(void) {
+	appData.useBGR233       = appDataNew.useBGR233;
+	appData.useBGR565       = appDataNew.useBGR565;
+	appData.useGreyScale    = appDataNew.useGreyScale;
+	appData.enableJPEG      = appDataNew.enableJPEG;
+	appData.encodingsString = appDataNew.encodingsString;
+	appData.useRemoteCursor = appDataNew.useRemoteCursor;
+	appData.useX11Cursor    = appDataNew.useX11Cursor;
+	appData.useRawLocal     = appDataNew.useRawLocal;
+}
+
+void
+Toggle8bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	fprintf(stderr, "Toggle8bpp: %d\n", appData.useBGR233);
+	b8 = w;
+	init_format_change();
+	if (appData.useBGR233) {
+		last_ncolors = appData.useBGR233;
+		appDataNew.useBGR233 = 0;
+		appDataNew.useBGR565 = save_useBGR565;
+		fprintf(stderr, "8bpp: off\n");
+	} else {
+		if (!last_ncolors) last_ncolors = 256;
+		appDataNew.useBGR233 = last_ncolors;
+		save_useBGR565 = appData.useBGR565;
+		appDataNew.useBGR565 = False;
+		fprintf(stderr, "8bpp: on (%d colors)\n", appDataNew.useBGR233);
+	}
+	schedule_format_change();
+}
+
+
+void
+Toggle16bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	fprintf(stderr, "Toggle16bpp: %d\n", appData.useBGR565);
+	b16 = w;
+	init_format_change();
+	if (appData.useBGR565) {
+		appDataNew.useBGR565 = False;
+		appDataNew.useBGR233 = save_useBGR233;
+		fprintf(stderr, "16bpp: off\n");
+	} else {
+		appDataNew.useBGR565 = True;
+		save_useBGR233 = appData.useBGR233;
+		appDataNew.useBGR233 = 0;
+		fprintf(stderr, "16bpp: on\n");
+	}
+	schedule_format_change();
+}
+
+void
+ToggleFullColor(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	fprintf(stderr, "ToggleFullColor\n");
+	bfull = w;
+	init_format_change();
+	if (appData.useBGR565 || appData.useBGR233) {
+		save_useBGR565 = appData.useBGR565;
+		appDataNew.useBGR565 = False;
+		save_useBGR233 = appData.useBGR233;
+		appDataNew.useBGR233 = 0;
+		fprintf(stderr, "FullColor: on\n");
+	} else {
+		if (save_useBGR565) {
+			appDataNew.useBGR565 = True;
+			appDataNew.useBGR233 = 0;
+			fprintf(stderr, "FullColor off -> 16bpp.\n");
+		} else {
+			appDataNew.useBGR565 = False;
+			if (!save_useBGR233) save_useBGR233 = 256;
+			appDataNew.useBGR233 = save_useBGR233;
+			fprintf(stderr, "FullColor off -> 8bpp.\n");
+		}
+	}
+	schedule_format_change();
+}
+
+/*
+ * ToggleNColors
+ */
+
+static Widget w256 = NULL;
+static Widget w64  = NULL;
+static Widget w8   = NULL;
+
+void
+Toggle256Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	w256 = w;
+	if (appData.useBGR233 != 256) {
+		fprintf(stderr, "256 colors: on\n");
+		init_format_change();
+		last_ncolors = appDataNew.useBGR233 = 256;
+		save_useBGR565 = appData.useBGR565;
+		appDataNew.useBGR565 = False;
+		schedule_format_change();
+	}
+}
+
+void
+Toggle64Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	w64 = w;
+	if (appData.useBGR233 != 64) {
+		fprintf(stderr, "64 colors: on\n");
+		init_format_change();
+		last_ncolors = appDataNew.useBGR233 = 64;
+		save_useBGR565 = appData.useBGR565;
+		appDataNew.useBGR565 = False;
+		schedule_format_change();
+	}
+}
+
+void
+Toggle8Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	w8 = w;
+	if (appData.useBGR233 != 8) {
+		fprintf(stderr, "8 colors: on\n");
+		init_format_change();
+		last_ncolors = appDataNew.useBGR233 = 8;
+		save_useBGR565 = appData.useBGR565;
+		appDataNew.useBGR565 = False;
+		schedule_format_change();
+	}
+}
+
+void
+ToggleGreyScale(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	fprintf(stderr, "ToggleGreyScale\n");
+	init_format_change();
+	if (appData.useGreyScale) {
+		appDataNew.useGreyScale = False;
+		fprintf(stderr, "greyscale: off\n");
+	} else {
+		appDataNew.useGreyScale = True;
+		fprintf(stderr, "greyscale: on\n");
+	}
+	schedule_format_change();
+}
+
+/*
+ * ToggleJPEG
+ */
+
+void
+ToggleJPEG(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	init_format_change();
+	if (appData.enableJPEG) {
+		appDataNew.enableJPEG = False;
+		fprintf(stderr, "JPEG: off\n");
+	} else {
+		appDataNew.enableJPEG = True;
+		fprintf(stderr, "JPEG: on\n");
+	}
+	schedule_format_change();
+}
+
+/*
+ * ToggleTightZRLE
+ */
+
+static Bool usingZRLE = False;
+
+void
+ToggleTightZRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	char prefTight[] = "copyrect tight zrle zlib hextile corre rre raw";
+	char prefZRLE[]  = "copyrect zrle tight zlib hextile corre rre raw";
+	init_format_change();
+	if (! appData.encodingsString) {
+		appDataNew.encodingsString = strdup(prefZRLE);
+		usingZRLE = True;
+		fprintf(stderr, "prefer: ZRLE\n");
+	} else {
+		char *p, *q;
+		p = strstr(appData.encodingsString, "tight");
+		q = strstr(appData.encodingsString, "zrle");
+		if (! p) {
+			appDataNew.encodingsString = strdup(prefZRLE);
+			usingZRLE = True;
+			fprintf(stderr, "prefer: ZRLE\n");
+		} else if (! q) {
+			appDataNew.encodingsString = strdup(prefTight);
+			usingZRLE = False;
+			fprintf(stderr, "prefer: Tight\n");
+		} else {
+			if (p < q) {
+				appDataNew.encodingsString = strdup(prefZRLE);
+				usingZRLE = True;
+				fprintf(stderr, "prefer: ZRLE\n");
+			} else {
+				appDataNew.encodingsString = strdup(prefTight);
+				usingZRLE = False;
+				fprintf(stderr, "prefer: Tight\n");
+			}
+		}
+	}
+	schedule_format_change();
+}
+
+/*
+ * ToggleViewOnly
+ */
+
+void
+ToggleViewOnly(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	if (appData.viewOnly) {
+		appData.viewOnly = False;
+		fprintf(stderr, "viewonly: off\n");
+	} else {
+		appData.viewOnly = True;
+		fprintf(stderr, "viewonly: on\n");
+	}
+}
+
+void
+ToggleCursorShape(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	init_format_change();
+	if (appData.useRemoteCursor) {
+		appDataNew.useRemoteCursor = False;
+		fprintf(stderr, "useRemoteCursor: off\n");
+	} else {
+		appDataNew.useRemoteCursor = True;
+		fprintf(stderr, "useRemoteCursor: on\n");
+	}
+	schedule_format_change();
+	if (!appDataNew.useRemoteCursor) {
+		do_cursor_change = 1;
+	} else {
+		do_cursor_change = -1;
+	}
+}
+
+void
+ToggleCursorAlpha(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	if (appData.useCursorAlpha) {
+		appData.useCursorAlpha = False;
+		fprintf(stderr, "useCursorAlpha: off\n");
+	} else {
+		appData.useCursorAlpha = True;
+		fprintf(stderr, "useCursorAlpha: on\n");
+	}
+}
+
+void
+ToggleX11Cursor(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	init_format_change();
+	if (appData.useX11Cursor) {
+		appDataNew.useX11Cursor = False;
+		fprintf(stderr, "useX11Cursor: off\n");
+	} else {
+		appDataNew.useX11Cursor = True;
+		fprintf(stderr, "useX11Cursor: on\n");
+	}
+	schedule_format_change();
+	do_cursor_change = 1;
+}
+
+void
+ToggleRawLocal(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	init_format_change();
+	if (appData.useRawLocal) {
+		appDataNew.useRawLocal = False;
+		fprintf(stderr, "useRawLocal: off\n");
+	} else {
+		appDataNew.useRawLocal = True;
+		fprintf(stderr, "useRawLocal: on\n");
+	}
+	schedule_format_change();
+}
+
+void
+ToggleServerInput(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	if (appData.serverInput) {
+		appData.serverInput= False;
+		fprintf(stderr, "serverInput: off\n");
+		SendServerInput(True);
+	} else {
+		appData.serverInput = True;
+		fprintf(stderr, "serverInput: on\n");
+		SendServerInput(False);
+	}
+}
+
+extern Cursor bogoCursor;
+Bool selectingSingleWindow = False;
 
-  Cleanup();
+void
+ToggleSingleWindow(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	if (appData.singleWindow) {
+		appData.singleWindow= False;
+		fprintf(stderr, "singleWindow: off\n");
+		SendSingleWindow(-1, -1);
+	} else {
+		appData.singleWindow = True;
+		fprintf(stderr, "singleWindow: on\n");
+		selectingSingleWindow = True;
+		if (bogoCursor != None) {
+			XDefineCursor(dpy, desktopWin, bogoCursor);
+		}
+	}
+}
+
+void raiseme(void);
+
+void
+ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	if (appData.chatActive) {
+		SendTextChatClose();
+		appData.chatActive= False;
+		fprintf(stderr, "\n*SentClose*\n\n");
+	} else {
+		SendTextChatOpen();
+		raiseme();
+		fprintf(stderr, "\n*SentOpen*\n\nSend: ");
+		appData.chatActive = True;
+	}
+}
+
+static int fooHandler(Display *dpy, XErrorEvent *error) {
+	return 0;
+}
+
+void raiseme(void) {
+	if (getenv("WINDOWID")) {
+		unsigned long w;
+		if (sscanf(getenv("WINDOWID"), "%lu", &w) == 1)  {
+			;
+		} else if (sscanf(getenv("WINDOWID"), "0x%lx", &w) == 1)  {
+			;
+		} else {
+			w = 0;
+		}
+		if (w != 0) {
+			XErrorHandler old = XSetErrorHandler(fooHandler);
+			XMapRaised(dpy, (Window) w);
+			XSync(dpy, False);
+			XSetErrorHandler(old);
+		}
+	}
+}
 
-  return 0;
+void
+DoServerScale(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	char str[100], *q;
+	int n;
+	raiseme();
+	fprintf(stderr, "\n\n\a\nEnter integer n for 1/n server scaling: ");
+	str[0] = '\0';
+	fgets(str, 100, stdin); 
+	q = strstr(str, "\n");
+	if (q) *q = '\0';
+	if (str[0] != '\0') {
+		n = atoi(str);
+		if (n >= 1 && n < 100) {
+			appData.serverScale = n;
+			SendServerScale(n);
+			SendFramebufferUpdateRequest(0, 0, si.framebufferWidth,
+			    si.framebufferHeight, False);
+		}
+	}
+}
+
+void
+GotChatText(char *str, int len)
+{
+	raiseme();
+	fprintf(stderr, "\nChat: ");
+	write(2, str, len);
+	if (strstr(str, "\n")) {
+		fprintf(stderr, "Send: ");
+	} else {
+		fprintf(stderr, "\nSend: ");
+	}
+}
+
+void
+SetViewOnlyState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+  if (appData.viewOnly)
+    XtVaSetValues(w, XtNstate, True, NULL);
+  else
+    XtVaSetValues(w, XtNstate, False, NULL);
+}
+
+void
+SetNOJPEGState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+  if (appData.enableJPEG)
+    XtVaSetValues(w, XtNstate, False, NULL);
+  else
+    XtVaSetValues(w, XtNstate, True, NULL);
+}
+
+void
+Set8bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	if (appData.useBGR233) {
+		XtVaSetValues(w, XtNstate, True, NULL);
+		if (b16   != NULL) XtVaSetValues(b16,   XtNstate, False, NULL);
+		if (bfull != NULL) XtVaSetValues(bfull, XtNstate, False, NULL);
+	} else {
+		XtVaSetValues(w, XtNstate, False, NULL);
+	}
+}
+
+void
+Set16bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	if (appData.useBGR565) {
+		XtVaSetValues(w, XtNstate, True, NULL);
+		if (b8    != NULL) XtVaSetValues(b8,    XtNstate, False, NULL);
+		if (bfull != NULL) XtVaSetValues(bfull, XtNstate, False, NULL);
+	} else {
+		XtVaSetValues(w, XtNstate, False, NULL);
+	}
+}
+
+void
+SetFullColorState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	if (appData.useBGR565 || appData.useBGR233) {
+		XtVaSetValues(w, XtNstate, False, NULL);
+	} else {
+		XtVaSetValues(w, XtNstate, True, NULL);
+		if (b8  != NULL) XtVaSetValues(b8,  XtNstate, False, NULL);
+		if (b16 != NULL) XtVaSetValues(b16, XtNstate, False, NULL);
+	}
+}
+
+void
+Set256ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	if (appData.useBGR233 == 256) {
+		XtVaSetValues(w, XtNstate, True, NULL);
+		if (w64  != NULL) XtVaSetValues(w64 , XtNstate, False, NULL);
+		if (w8   != NULL) XtVaSetValues(w8  , XtNstate, False, NULL);
+	} else {
+		XtVaSetValues(w, XtNstate, False, NULL);
+	}
+}
+
+void
+Set64ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	if (appData.useBGR233 == 64) {
+		XtVaSetValues(w, XtNstate, True, NULL);
+		if (w256 != NULL) XtVaSetValues(w256, XtNstate, False, NULL);
+		if (w8   != NULL) XtVaSetValues(w8  , XtNstate, False, NULL);
+	} else {
+		XtVaSetValues(w, XtNstate, False, NULL);
+	}
 }
+
+void
+Set8ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	if (appData.useBGR233 == 8) {
+		XtVaSetValues(w, XtNstate, True, NULL);
+		if (w256 != NULL) XtVaSetValues(w256, XtNstate, False, NULL);
+		if (w64  != NULL) XtVaSetValues(w64 , XtNstate, False, NULL);
+	} else {
+		XtVaSetValues(w, XtNstate, False, NULL);
+	}
+}
+
+void
+SetGreyScaleState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+	if (appData.useGreyScale) {
+		XtVaSetValues(w, XtNstate, True, NULL);
+	} else {
+		XtVaSetValues(w, XtNstate, False, NULL);
+	}
+}
+
+void
+SetZRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+  if (usingZRLE)
+    XtVaSetValues(w, XtNstate, True, NULL);
+  else
+    XtVaSetValues(w, XtNstate, False, NULL);
+}
+
+void
+SetCursorShapeState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+  if (appData.useRemoteCursor)
+    XtVaSetValues(w, XtNstate, True, NULL);
+  else
+    XtVaSetValues(w, XtNstate, False, NULL);
+}
+
+void
+SetCursorAlphaState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+  if (appData.useCursorAlpha)
+    XtVaSetValues(w, XtNstate, True, NULL);
+  else
+    XtVaSetValues(w, XtNstate, False, NULL);
+}
+
+void
+SetX11CursorState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+  if (appData.useX11Cursor)
+    XtVaSetValues(w, XtNstate, True, NULL);
+  else
+    XtVaSetValues(w, XtNstate, False, NULL);
+}
+
+void
+SetRawLocalState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+  if (appData.useRawLocal)
+    XtVaSetValues(w, XtNstate, True, NULL);
+  else
+    XtVaSetValues(w, XtNstate, False, NULL);
+}
+
+void
+SetServerInputState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+  if (!appData.serverInput)
+    XtVaSetValues(w, XtNstate, True, NULL);
+  else
+    XtVaSetValues(w, XtNstate, False, NULL);
+}
+
+void
+SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+  if (appData.singleWindow)
+    XtVaSetValues(w, XtNstate, True, NULL);
+  else
+    XtVaSetValues(w, XtNstate, False, NULL);
+}
+
+void
+SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+  if (appData.chatActive)
+    XtVaSetValues(w, XtNstate, True, NULL);
+  else
+    XtVaSetValues(w, XtNstate, False, NULL);
+}
+
+
+
+
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncviewer/vncviewer.h
--- vnc_unixsrc.orig/vncviewer/vncviewer.h	2004-03-11 13:14:40.000000000 -0500
+++ vnc_unixsrc/vncviewer/vncviewer.h	2007-03-22 20:54:06.000000000 -0400
@@ -68,51 +68,69 @@
 /* argsresources.c */
 
 typedef struct {
-  Bool shareDesktop;
-  Bool viewOnly;
-  Bool fullScreen;
-  Bool grabKeyboard;
-  Bool raiseOnBeep;
-
-  String encodingsString;
-
-  Bool useBGR233;
-  int nColours;
-  Bool useSharedColours;
-  Bool forceOwnCmap;
-  Bool forceTrueColour;
-  int requestedDepth;
-
-  Bool useShm;
-
-  int wmDecorationWidth;
-  int wmDecorationHeight;
-
-  char *userLogin;
-
-  char *passwordFile;
-  Bool passwordDialog;
-
-  int rawDelay;
-  int copyRectDelay;
-
-  Bool debug;
-
-  int popupButtonCount;
-
-  int bumpScrollTime;
-  int bumpScrollPixels;
-
-  int compressLevel;
-  int qualityLevel;
-  Bool enableJPEG;
-  Bool useRemoteCursor;
-  Bool useX11Cursor;
-  Bool autoPass;
+	Bool shareDesktop;
+	Bool viewOnly;
+	Bool fullScreen;
+	Bool grabKeyboard;
+	Bool raiseOnBeep;
+
+	String encodingsString;
+
+	int useBGR233;
+	int nColours;
+	Bool useSharedColours;
+	Bool forceOwnCmap;
+	Bool forceTrueColour;
+	int requestedDepth;
+	Bool useBGR565;
+	Bool useGreyScale;
+
+	Bool grabAll;
+	Bool useBackingstore;
+	Bool overrideRedir;
+	Bool popupFix;
+
+	Bool useShm;
+
+	int wmDecorationWidth;
+	int wmDecorationHeight;
+
+	char *userLogin;
+
+	char *passwordFile;
+	Bool passwordDialog;
+
+	int rawDelay;
+	int copyRectDelay;
+
+	int yCrop;
+	int sbWidth;
+	Bool useCursorAlpha;
+	Bool useRawLocal;
+
+	Bool debug;
+
+	int popupButtonCount;
+
+	int bumpScrollTime;
+	int bumpScrollPixels;
+
+	int compressLevel;
+	int qualityLevel;
+	Bool enableJPEG;
+	Bool useRemoteCursor;
+	Bool useX11Cursor;
+	Bool autoPass;
+
+	Bool serverInput;
+	Bool singleWindow;
+	int serverScale;
+	Bool chatActive;
 
 } AppData;
 
 extern AppData appData;
+extern AppData appDataNew;
 
 extern char *fallback_resources[];
 extern char vncServerHost[];
@@ -130,10 +148,11 @@
 /* colour.c */
 
 extern unsigned long BGR233ToPixel[];
+extern unsigned long BGR565ToPixel[];
 
 extern Colormap cmap;
 extern Visual *vis;
-extern unsigned int visdepth, visbpp;
+extern unsigned int visdepth, visbpp, isLSB;
 
 extern void SetVisualAndCmap();
 
@@ -160,8 +179,14 @@
 extern void SendRFBEvent(Widget w, XEvent *event, String *params,
 			 Cardinal *num_params);
 extern void CopyDataToScreen(char *buf, int x, int y, int width, int height);
+extern void FillScreen(int x, int y, int width, int height, unsigned long fill);
 extern void SynchroniseScreen();
 
+extern void ReDoDesktop();
+extern void DesktopCursorOff();
+extern void put_image(int x1, int y1, int x2, int y2, int width, int height);
+extern void copy_rect(int x, int y, int width, int height, int src_x, int src_y);
+
 /* dialogs.c */
 
 extern void ServerDialogDone(Widget w, XEvent *event, String *params,
@@ -229,6 +254,15 @@
 extern Bool SendClientCutText(char *str, int len);
 extern Bool HandleRFBServerMessage();
 
+extern Bool SendServerInput(Bool enabled);
+extern Bool SendSingleWindow(int x, int y);
+extern Bool SendServerScale(int n);
+
+extern Bool SendTextChat(char *str);
+extern Bool SendTextChatOpen(void);
+extern Bool SendTextChatClose(void);
+extern Bool SendTextChatFinish(void);
+
 extern void PrintPixelFormat(rfbPixelFormat *format);
 
 /* selection.c */
@@ -241,8 +275,9 @@
 
 /* shm.c */
 
-extern XImage *CreateShmImage();
+extern XImage *CreateShmImage(int do_ycrop);
 extern void ShmCleanup();
+extern Bool UsingShm();
 
 /* sockets.c */
 
@@ -271,3 +306,42 @@
 extern XtAppContext appContext;
 extern Display* dpy;
 extern Widget toplevel;
+
+extern void GotChatText(char *str, int len);
+
+extern void Toggle8bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Toggle16bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleFullColor(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Toggle256Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Toggle64Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Toggle8Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleGreyScale(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleTightZRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleViewOnly(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleJPEG(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleCursorShape(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleCursorAlpha(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleX11Cursor(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleRawLocal(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleServerInput(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleSingleWindow(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void DoServerScale(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+
+extern void SetViewOnlyState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetNOJPEGState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Set8bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Set16bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetFullColorState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Set256ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Set64ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Set8ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetGreyScaleState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetZRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetCursorShapeState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetCursorAlphaState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetX11CursorState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetRawLocalState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetServerInputState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vncviewer/vncviewer.man
--- vnc_unixsrc.orig/vncviewer/vncviewer.man	2004-03-11 13:14:40.000000000 -0500
+++ vnc_unixsrc/vncviewer/vncviewer.man	2007-03-20 10:11:33.000000000 -0400
@@ -168,6 +168,121 @@
 \fB\-autopass\fR
 Read a plain-text password from stdin. This option affects only the
 standard VNC authentication.
+
+.SH Enhanced TightVNC Viewer OPTIONS
+.TP
+Enhanced TightVNC Viewer web page is located at:
+.TP
+http://www.karlrunge.com/x11vnc/ssvnc.html
+.TP
+Note: ZRLE encoding is now supported.
+.TP
+Note: F9 is shortcut to Toggle FullScreen mode.
+.TP
+\fB\-use64\fR
+In \fB\-bgr233\fR mode, use 64 colors instead of 256.
+.TP
+\fB\-bgr222\fR
+Same as \fB\-use64\fR.
+.TP
+\fB\-use8\fR
+In \fB\-bgr233\fR mode, use 8 colors instead of 256.
+.TP
+\fB\-bgr111\fR
+Same as \fB\-use8\fR.
+.TP
+\fB\-16bpp\fR
+If the vnc viewer X display is depth 24 at 32bpp
+request a 16bpp format from the VNC server to cut
+network traffic by up to 2X, then tranlate the
+pixels to 32bpp locally.
+.TP
+\fB\-bgr565\fR
+Same as \fB\-16bpp\fR.
+.TP
+\fB\-alpha\fR
+Use alphablending transparency for local cursors
+requires: x11vnc server, both client and server
+must be 32bpp and same endianness.
+.TP
+\fB\-ycrop\fR n
+Only show the top n rows of the framebuffer.  For
+use with x11vnc \fB\-ncache\fR client caching option
+to help "hide" the pixel cache region.
+Use a negative value (e.g. \fB\-1\fR) for autodetection.
+Autodetection will always take place if the remote
+fb height is more than 2 times the width.
+.TP
+\fB\-sbwidth\fR n
+Scrollbar width, default is very narrow: 2 pixels,
+it is narrow to avoid distraction in \fB\-ycrop\fR mode.
+.TP
+\fB\-rawlocal\fR
+Prefer raw encoding for localhost, default is
+no, i.e. assumes you have a SSH tunnel instead.
+.TP
+\fB\-graball\fR
+Grab the entire X server when in fullscreen mode,
+needed by some old window managers like fvwm2.
+.TP
+\fB\-popupfix\fR
+Warp the popup back to the pointer position,
+needed by some old window managers like fvwm2.
+.TP
+\fB\-grabkbd\fR
+Grab the X keyboard when in fullscreen mode,
+needed by some window managers. Same as \fB\-grabkeyboard\fR.
+\fB\-grabkbd\fR is the default, use \fB\-nograbkbd\fR to disable.
+.TP
+\fB\-bs/-nobs\fR
+Whether or not to use X server Backingstore for the
+main viewer window.  The default is to not, mainly
+because most Linux, etc, systems X servers disable
+*all* Backingstore by default.  To re-enable it put
+
+Option "Backingstore"
+
+in the Device section of /etc/X11/xorg.conf.
+In -bs mode with no X server backingstore, whenever an
+area of the screen is re-exposed it must go out to the
+VNC server to retrieve the pixels. This is too slow.
+
+In -nobs mode, memory is allocated by the viewer to
+provide its own backing of the main viewer window. This
+actually makes some activities faster (changes in large
+regions) but can appear to "flash" too much.
+.TP
+\fB\-noshm\fR
+Disable use of MIT shared memory extension (not recommended)
+.TP
+\fB New Popup actions:\fR
+
+ Cursor Shape:            ~ -nocursorshape
+ X11 Cursor:              ~ -x11cursor
+ Cursor Alphablend:       ~ -alpha
+ Disable JPEG:            ~ -nojpeg
+ Prefer raw for localhost ~ -rawlocal
+ Full Color                 as many colors as local screen allows.
+ Grey scale (16 & 8-bpp)  ~ -grey, for low colors 16/8bpp modes only.
+ 16 bit color (BGR565)    ~ -bgr565
+ 8  bit color (BGR233)    ~ -bgr233
+ 256 colors               ~ -bgr233 default # of colors.
+  64 colors               ~ -bgr222 / -use64
+   8 colors               ~ -bgr111 / -use8
+
+ 
+ Disable Remote Input       Ultravnc ext.  Try to prevent input and
+                            viewing of monitor at physical display.
+ Single Window              Ultravnc ext.  Grab and a single window.
+                            (click on the window you want).
+ Set 1/n Server Scale       Ultravnc ext.  Scale desktop by 1/n.
+                            prompt is from the terminal.
+ Text Chat                  Ultravnc ext.  Do Text Chat, currently
+                            input via the terminal (no window).
+ 
+ Note: the Ultravnc extensions only apply to servers that support
+       them.  x11vnc/libvncserver supports some of them.
+
 .SH ENCODINGS
 The server supplies information in whatever format is desired by the
 client, in order to make the client as easy as possible to implement. 
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrle.c vnc_unixsrc/vncviewer/zrle.c
--- vnc_unixsrc.orig/vncviewer/zrle.c	2007-02-04 18:59:50.000000000 -0500
+++ vnc_unixsrc/vncviewer/zrle.c	2007-02-17 22:36:37.000000000 -0500
@@ -0,0 +1,455 @@
+/*
+ *  Copyright (C) 2005 Johannes E. Schindelin.  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
+ *  (at your option) any later version.
+ *
+ *  This software is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ *  USA.
+ */
+
+/*
+ * zrle.c - handle zrle encoding.
+ *
+ * This file shouldn't be compiled directly.  It is included multiple times by
+ * rfbproto.c, each time with a different definition of the macro BPP.  For
+ * each value of BPP, this file defines a function which handles an zrle
+ * encoded rectangle with BPP bits per pixel.
+ */
+
+#ifndef REALBPP
+#define REALBPP BPP
+#endif
+
+#if !defined(UNCOMP) || UNCOMP==0
+#define HandleZRLE CONCAT2E(HandleZRLE,REALBPP)
+#define HandleZRLETile CONCAT2E(HandleZRLETile,REALBPP)
+#elif UNCOMP>0
+#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Down)
+#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Down)
+#else
+#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Up)
+#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Up)
+#endif
+#undef CARDBPP
+#undef CARDREALBPP
+#define CARDBPP CONCAT2E(CARD, BPP)
+#define CARDREALBPP CONCAT2E(CARD,REALBPP)
+
+#define FillRectangle(x, y, w, h, color)  \
+	{ \
+		XGCValues _gcv; \
+		_gcv.foreground = color; \
+		if (!appData.useBackingstore) { \
+			FillScreen(x, y, w, h, _gcv.foreground); \
+		} else { \
+			XChangeGC(dpy, gc, GCForeground, &_gcv); \
+			XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \
+		} \
+	}
+
+static int HandleZRLETile(
+	unsigned char* buffer,size_t buffer_length,
+	int x,int y,int w,int h);
+
+static Bool
+HandleZRLE (int rx, int ry, int rw, int rh)
+{
+	rfbZRLEHeader header;
+	int remaining;
+	int inflateResult;
+	int toRead;
+	int min_buffer_size = rw * rh * (REALBPP / 8) * 2;
+
+	/* First make sure we have a large enough raw buffer to hold the
+	 * decompressed data.  In practice, with a fixed REALBPP, fixed frame
+	 * buffer size and the first update containing the entire frame
+	 * buffer, this buffer allocation should only happen once, on the
+	 * first update.
+	 */
+	if ( raw_buffer_size < min_buffer_size) {
+
+		if ( raw_buffer != NULL ) {
+
+			free( raw_buffer );
+
+		}
+
+		raw_buffer_size = min_buffer_size;
+		raw_buffer = (char*) malloc( raw_buffer_size );
+
+	}
+
+	if (!ReadFromRFBServer((char *)&header, sz_rfbZRLEHeader))
+		return False;
+
+	remaining = Swap32IfLE(header.length);
+
+	/* Need to initialize the decompressor state. */
+	decompStream.next_in   = ( Bytef * )buffer;
+	decompStream.avail_in  = 0;
+	decompStream.next_out  = ( Bytef * )raw_buffer;
+	decompStream.avail_out = raw_buffer_size;
+	decompStream.data_type = Z_BINARY;
+
+	/* Initialize the decompression stream structures on the first invocation. */
+	if ( decompStreamInited == False ) {
+
+		inflateResult = inflateInit( &decompStream );
+
+		if ( inflateResult != Z_OK ) {
+			fprintf(stderr, 
+					"inflateInit returned error: %d, msg: %s\n",
+					inflateResult,
+					decompStream.msg);
+			return False;
+		}
+
+		decompStreamInited = True;
+
+	}
+
+	inflateResult = Z_OK;
+
+	/* Process buffer full of data until no more to process, or
+	 * some type of inflater error, or Z_STREAM_END.
+	 */
+	while (( remaining > 0 ) &&
+			( inflateResult == Z_OK )) {
+
+		if ( remaining > BUFFER_SIZE ) {
+			toRead = BUFFER_SIZE;
+		}
+		else {
+			toRead = remaining;
+		}
+
+		/* Fill the buffer, obtaining data from the server. */
+		if (!ReadFromRFBServer(buffer,toRead))
+			return False;
+
+		decompStream.next_in  = ( Bytef * )buffer;
+		decompStream.avail_in = toRead;
+
+		/* Need to uncompress buffer full. */
+		inflateResult = inflate( &decompStream, Z_SYNC_FLUSH );
+
+		/* We never supply a dictionary for compression. */
+		if ( inflateResult == Z_NEED_DICT ) {
+			fprintf(stderr, "zlib inflate needs a dictionary!\n");
+			return False;
+		}
+		if ( inflateResult < 0 ) {
+			fprintf(stderr, 
+					"zlib inflate returned error: %d, msg: %s\n",
+					inflateResult,
+					decompStream.msg);
+			return False;
+		}
+
+		/* Result buffer allocated to be at least large enough.  We should
+		 * never run out of space!
+		 */
+		if (( decompStream.avail_in > 0 ) &&
+				( decompStream.avail_out <= 0 )) {
+			fprintf(stderr, "zlib inflate ran out of space!\n");
+			return False;
+		}
+
+		remaining -= toRead;
+
+	} /* while ( remaining > 0 ) */
+
+	if ( inflateResult == Z_OK ) {
+		void* buf=raw_buffer;
+		int i,j;
+
+		remaining = raw_buffer_size-decompStream.avail_out;
+
+		for(j=0; j<rh; j+=rfbZRLETileHeight)
+			for(i=0; i<rw; i+=rfbZRLETileWidth) {
+				int subWidth=(i+rfbZRLETileWidth>rw)?rw-i:rfbZRLETileWidth;
+				int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight;
+				int result=HandleZRLETile(buf,remaining,rx+i,ry+j,subWidth,subHeight);
+
+				if(result<0) {
+					fprintf(stderr, "ZRLE decoding failed (%d)\n",result);
+return True;
+					return False;
+				}
+
+				buf+=result;
+				remaining-=result;
+			}
+	}
+	else {
+
+		fprintf(stderr, 
+				"zlib inflate returned error: %d, msg: %s\n",
+				inflateResult,
+				decompStream.msg);
+		return False;
+
+	}
+
+	return True;
+}
+
+#if REALBPP!=BPP && defined(UNCOMP) && UNCOMP!=0
+#if UNCOMP>0
+#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)>>UNCOMP)
+#else
+#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)<<(-(UNCOMP)))
+#endif
+#else
+#define UncompressCPixel(pointer) (*(CARDBPP*)pointer)
+#endif
+
+static int HandleZRLETile(
+		unsigned char* buffer,size_t buffer_length,
+		int x,int y,int w,int h) {
+	unsigned char* buffer_copy = buffer;
+	unsigned char* buffer_end = buffer+buffer_length;
+	unsigned char type;
+
+	if(buffer_length<1)
+		return -2;
+
+	if (frameBufferLen < w * h * REALBPP/8) {
+		if(frameBuffer) {
+			free(frameBuffer);
+		}
+		frameBufferLen = w * h * REALBPP/8 * 2;
+		frameBuffer = (unsigned char *) malloc(frameBufferLen);
+	}
+
+	type = *buffer;
+	buffer++;
+	switch(type) {
+		case 0: /* raw */
+		{
+#if REALBPP!=BPP
+			int m0 = 0, i,j;
+
+			if(1+w*h*REALBPP/8>buffer_length) {
+				fprintf(stderr, "expected %d bytes, got only %d (%dx%d)\n",1+w*h*REALBPP/8,buffer_length,w,h);
+				return -3;
+			}
+
+			for(j=y*si.framebufferWidth; j<(y+h)*si.framebufferWidth; j+=si.framebufferWidth) {
+				for(i=x; i<x+w; i++,buffer+=REALBPP/8) {
+#  if 0
+					((CARDBPP*)frameBuffer)[j+i] = UncompressCPixel(buffer);
+					/* alt */
+					CARDBPP color = UncompressCPixel(buffer);
+					CopyDataToScreen((char *)&color, i, j/si.framebufferWidth, 1, 1);
+#  else
+					((CARDBPP*)frameBuffer)[m0++] = UncompressCPixel(buffer);
+#  endif
+				}
+			}
+			CopyDataToScreen((char *)frameBuffer, x, y, w, h);
+if (0) fprintf(stderr, "cha1: %dx%d+%d+%d\n", w, h, x, y);
+
+#else
+#  if 0
+			CopyRectangle(buffer, x, y, w, h);
+#  else
+			CopyDataToScreen((char *)buffer, x, y, w, h);
+#  endif
+			buffer+=w*h*REALBPP/8;
+#endif
+			break;
+		}
+		case 1: /* solid */
+		{
+			CARDBPP color = UncompressCPixel(buffer);
+
+			if(1+REALBPP/8>buffer_length)
+				return -4;
+				
+			if ((BPP == 8 && appData.useBGR233) || (BPP == 16 && appData.useBGR565)) {
+				int m0;
+				for (m0=0; m0 < w*h; m0++) {
+					((CARDBPP*)frameBuffer)[m0] = color;
+				}
+				CopyDataToScreen((char *)frameBuffer, x, y, w, h);
+			} else {
+				FillRectangle(x, y, w, h, color);
+			}
+if (0) fprintf(stderr, "cha2: %dx%d+%d+%d\n", w, h, x, y);
+
+			buffer+=REALBPP/8;
+
+			break;
+		}
+		case 2 ... 127: /* packed Palette */
+		{
+			CARDBPP palette[16];
+			int m0, i,j,shift,
+				bpp=(type>4?(type>16?8:4):(type>2?2:1)),
+				mask=(1<<bpp)-1,
+				divider=(8/bpp);
+
+			if(1+type*REALBPP/8+((w+divider-1)/divider)*h>buffer_length)
+				return -5;
+
+			/* read palette */
+			for(i=0; i<type; i++,buffer+=REALBPP/8)
+				palette[i] = UncompressCPixel(buffer);
+
+			m0 = 0;
+			/* read palettized pixels */
+			for(j=y*si.framebufferWidth; j<(y+h)*si.framebufferWidth; j+=si.framebufferWidth) {
+				for(i=x,shift=8-bpp; i<x+w; i++) {
+#  if 0
+					((CARDBPP*)frameBuffer)[j+i] = palette[((*buffer)>>shift)&mask];
+					/* alt */
+					CARDBPP color = palette[((*buffer)>>shift)&mask];
+					CopyDataToScreen((char *)&color, i, j/si.framebufferWidth, 1, 1);
+#  else
+					((CARDBPP*)frameBuffer)[m0++] = palette[((*buffer)>>shift)&mask];
+#  endif
+					shift-=bpp;
+					if(shift<0) {
+						shift=8-bpp;
+						buffer++;
+					}
+				}
+				if(shift<8-bpp)
+					buffer++;
+			}
+			CopyDataToScreen((char *)frameBuffer, x, y, w, h);
+if (0) fprintf(stderr, "cha3: %dx%d+%d+%d\n", w, h, x, y);
+
+			break;
+		}
+		/* case 17 ... 127: not used, but valid */
+		case 128: /* plain RLE */
+		{
+			int m0=0, i=0,j=0;
+			while(j<h) {
+				int color,length;
+				/* read color */
+				if(buffer+REALBPP/8+1>buffer_end)
+					return -7;
+				color = UncompressCPixel(buffer);
+				buffer+=REALBPP/8;
+				/* read run length */
+				length=1;
+				while(*buffer==0xff) {
+					if(buffer+1>=buffer_end)
+						return -8;
+					length+=*buffer;
+					buffer++;
+				}
+				length+=*buffer;
+				buffer++;
+				while(j<h && length>0) {
+#  if 0
+					((CARDBPP*)frameBuffer)[(y+j)*si.framebufferWidth+x+i] = color;
+					/* alt */
+					CopyDataToScreen((char *)&color, x+i, y+j, 1, 1);
+#  else
+					((CARDBPP*)frameBuffer)[m0++] = color;
+#  endif
+					length--;
+					i++;
+					if(i>=w) {
+						i=0;
+						j++;
+					}
+				}
+				if(length>0)
+					fprintf(stderr, "Warning: possible ZRLE corruption\n");
+			}
+			CopyDataToScreen((char *)frameBuffer, x, y, w, h);
+if (0) fprintf(stderr, "cha4: %dx%d+%d+%d\n", w, h, x, y);
+
+			break;
+		}
+		case 129: /* unused */
+		{
+			return -8;
+		}
+		case 130 ... 255: /* palette RLE */
+		{
+			CARDBPP palette[128];
+			int m0 = 0, i,j;
+
+			if(2+(type-128)*REALBPP/8>buffer_length)
+				return -9;
+
+			/* read palette */
+			for(i=0; i<type-128; i++,buffer+=REALBPP/8)
+				palette[i] = UncompressCPixel(buffer);
+			/* read palettized pixels */
+			i=j=0;
+			while(j<h) {
+				int color,length;
+				/* read color */
+				if(buffer>=buffer_end)
+					return -10;
+				color = palette[(*buffer)&0x7f];
+				length=1;
+				if(*buffer&0x80) {
+					if(buffer+1>=buffer_end)
+						return -11;
+					buffer++;
+					/* read run length */
+					while(*buffer==0xff) {
+						if(buffer+1>=buffer_end)
+							return -8;
+						length+=*buffer;
+						buffer++;
+					}
+					length+=*buffer;
+				}
+				buffer++;
+				while(j<h && length>0) {
+#  if 0
+					((CARDBPP*)frameBuffer)[(y+j)*si.framebufferWidth+x+i] = color;
+					/* alt */
+					CopyDataToScreen((char *)&color, x+i, y+j, 1, 1);
+#  else
+					((CARDBPP*)frameBuffer)[m0++] = color;
+#  endif
+					length--;
+					i++;
+					if(i>=w) {
+						i=0;
+						j++;
+					}
+				}
+				if(length>0)
+					fprintf(stderr, "Warning: possible ZRLE corruption\n");
+			}
+			CopyDataToScreen((char *)frameBuffer, x, y, w, h);
+if (0) fprintf(stderr, "cha5: %dx%d+%d+%d\n", w, h, x, y);
+
+			break;
+		}
+	}
+
+	return buffer-buffer_copy;	
+}
+
+#undef CARDBPP
+#undef CARDREALBPP
+#undef HandleZRLE
+#undef HandleZRLETile
+#undef UncompressCPixel
+#undef REALBPP
+
+#undef UNCOMP
+
+#undef FillRectangle
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrleencodetemplate.c vnc_unixsrc/vncviewer/zrleencodetemplate.c
--- vnc_unixsrc.orig/vncviewer/zrleencodetemplate.c	1969-12-31 19:00:00.000000000 -0500
+++ vnc_unixsrc/vncviewer/zrleencodetemplate.c	2007-02-04 23:18:09.000000000 -0500
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2002 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+/*
+ * Before including this file, you must define a number of CPP macros.
+ *
+ * BPP should be 8, 16 or 32 depending on the bits per pixel.
+ * GET_IMAGE_INTO_BUF should be some code which gets a rectangle of pixel data
+ * into the given buffer.  EXTRA_ARGS can be defined to pass any other
+ * arguments needed by GET_IMAGE_INTO_BUF.
+ *
+ * Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel
+ * bigger than the largest tile of pixel data, since the ZRLE encoding
+ * algorithm writes to the position one past the end of the pixel data.
+ */
+
+#include "zrleoutstream.h"
+#include "zrlepalettehelper.h"
+#include <assert.h>
+
+/* __RFB_CONCAT2 concatenates its two arguments.  __RFB_CONCAT2E does the same
+   but also expands its arguments if they are macros */
+
+#ifndef __RFB_CONCAT2E
+#define __RFB_CONCAT2(a,b) a##b
+#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b)
+#endif
+
+#ifndef __RFB_CONCAT3E
+#define __RFB_CONCAT3(a,b,c) a##b##c
+#define __RFB_CONCAT3E(a,b,c) __RFB_CONCAT3(a,b,c)
+#endif
+
+#undef END_FIX
+#if ZYWRLE_ENDIAN == ENDIAN_LITTLE
+#  define END_FIX LE
+#elif ZYWRLE_ENDIAN == ENDIAN_BIG
+#  define END_FIX BE
+#else
+#  define END_FIX NE
+#endif
+
+#ifdef CPIXEL
+#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
+#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL)
+#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,CPIXEL,END_FIX)
+#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,CPIXEL,END_FIX)
+#define BPPOUT 24
+#elif BPP==15
+#define PIXEL_T __RFB_CONCAT2E(zrle_U,16)
+#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,16)
+#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
+#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
+#define BPPOUT 16
+#else
+#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP)
+#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP)
+#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX)
+#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX)
+#define BPPOUT BPP
+#endif
+
+#ifndef ZRLE_ONCE
+#define ZRLE_ONCE
+
+static const int bitsPerPackedPixel[] = {
+  0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
+};
+
+int zywrle_level;
+int zywrleBuf[rfbZRLETileWidth*rfbZRLETileHeight];
+
+static zrlePaletteHelper paletteHelper;
+
+#endif /* ZRLE_ONCE */
+
+void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os);
+
+#if BPP!=8
+#define ZYWRLE_ENCODE
+#include "zywrletemplate.c"
+#endif
+
+static void ZRLE_ENCODE (int x, int y, int w, int h,
+		  zrleOutStream* os, void* buf
+                  EXTRA_ARGS
+                  )
+{
+  int ty;
+  for (ty = y; ty < y+h; ty += rfbZRLETileHeight) {
+    int tx, th = rfbZRLETileHeight;
+    if (th > y+h-ty) th = y+h-ty;
+    for (tx = x; tx < x+w; tx += rfbZRLETileWidth) {
+      int tw = rfbZRLETileWidth;
+      if (tw > x+w-tx) tw = x+w-tx;
+
+      GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf);
+
+      ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, os);
+    }
+  }
+  zrleOutStreamFlush(os);
+}
+
+
+void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os)
+{
+  /* First find the palette and the number of runs */
+
+  zrlePaletteHelper *ph;
+
+  int runs = 0;
+  int singlePixels = 0;
+
+  rfbBool useRle;
+  rfbBool usePalette;
+
+  int estimatedBytes;
+  int plainRleBytes;
+  int i;
+
+  PIXEL_T* ptr = data;
+  PIXEL_T* end = ptr + h * w;
+  *end = ~*(end-1); /* one past the end is different so the while loop ends */
+
+  ph = &paletteHelper;
+  zrlePaletteHelperInit(ph);
+
+  while (ptr < end) {
+    PIXEL_T pix = *ptr;
+    if (*++ptr != pix) {
+      singlePixels++;
+    } else {
+      while (*++ptr == pix) ;
+      runs++;
+    }
+    zrlePaletteHelperInsert(ph, pix);
+  }
+
+  /* Solid tile is a special case */
+
+  if (ph->size == 1) {
+    zrleOutStreamWriteU8(os, 1);
+    zrleOutStreamWRITE_PIXEL(os, ph->palette[0]);
+    return;
+  }
+
+  /* Try to work out whether to use RLE and/or a palette.  We do this by
+     estimating the number of bytes which will be generated and picking the
+     method which results in the fewest bytes.  Of course this may not result
+     in the fewest bytes after compression... */
+
+  useRle = FALSE;
+  usePalette = FALSE;
+
+  estimatedBytes = w * h * (BPPOUT/8); /* start assuming raw */
+
+#if BPP!=8
+  if( (zywrle_level>0)&& !(zywrle_level & 0x80) ){
+	  estimatedBytes >>= zywrle_level;
+  }
+#endif
+
+  plainRleBytes = ((BPPOUT/8)+1) * (runs + singlePixels);
+
+  if (plainRleBytes < estimatedBytes) {
+    useRle = TRUE;
+    estimatedBytes = plainRleBytes;
+  }
+
+  if (ph->size < 128) {
+    int paletteRleBytes = (BPPOUT/8) * ph->size + 2 * runs + singlePixels;
+
+    if (paletteRleBytes < estimatedBytes) {
+      useRle = TRUE;
+      usePalette = TRUE;
+      estimatedBytes = paletteRleBytes;
+    }
+
+    if (ph->size < 17) {
+      int packedBytes = ((BPPOUT/8) * ph->size +
+                         w * h * bitsPerPackedPixel[ph->size-1] / 8);
+
+      if (packedBytes < estimatedBytes) {
+        useRle = FALSE;
+        usePalette = TRUE;
+        estimatedBytes = packedBytes;
+      }
+    }
+  }
+
+  if (!usePalette) ph->size = 0;
+
+  zrleOutStreamWriteU8(os, (useRle ? 128 : 0) | ph->size);
+
+  for (i = 0; i < ph->size; i++) {
+    zrleOutStreamWRITE_PIXEL(os, ph->palette[i]);
+  }
+
+  if (useRle) {
+
+    PIXEL_T* ptr = data;
+    PIXEL_T* end = ptr + w * h;
+    PIXEL_T* runStart;
+    PIXEL_T pix;
+    while (ptr < end) {
+      int len;
+      runStart = ptr;
+      pix = *ptr++;
+      while (*ptr == pix && ptr < end)
+        ptr++;
+      len = ptr - runStart;
+      if (len <= 2 && usePalette) {
+        int index = zrlePaletteHelperLookup(ph, pix);
+        if (len == 2)
+          zrleOutStreamWriteU8(os, index);
+        zrleOutStreamWriteU8(os, index);
+        continue;
+      }
+      if (usePalette) {
+        int index = zrlePaletteHelperLookup(ph, pix);
+        zrleOutStreamWriteU8(os, index | 128);
+      } else {
+        zrleOutStreamWRITE_PIXEL(os, pix);
+      }
+      len -= 1;
+      while (len >= 255) {
+        zrleOutStreamWriteU8(os, 255);
+        len -= 255;
+      }
+      zrleOutStreamWriteU8(os, len);
+    }
+
+  } else {
+
+    /* no RLE */
+
+    if (usePalette) {
+      int bppp;
+      PIXEL_T* ptr = data;
+
+      /* packed pixels */
+
+      assert (ph->size < 17);
+
+      bppp = bitsPerPackedPixel[ph->size-1];
+
+      for (i = 0; i < h; i++) {
+        zrle_U8 nbits = 0;
+        zrle_U8 byte = 0;
+
+        PIXEL_T* eol = ptr + w;
+
+        while (ptr < eol) {
+          PIXEL_T pix = *ptr++;
+          zrle_U8 index = zrlePaletteHelperLookup(ph, pix);
+          byte = (byte << bppp) | index;
+          nbits += bppp;
+          if (nbits >= 8) {
+            zrleOutStreamWriteU8(os, byte);
+            nbits = 0;
+          }
+        }
+        if (nbits > 0) {
+          byte <<= 8 - nbits;
+          zrleOutStreamWriteU8(os, byte);
+        }
+      }
+    } else {
+
+      /* raw */
+
+#if BPP!=8
+      if( (zywrle_level>0)&& !(zywrle_level & 0x80) ){
+		  ZYWRLE_ANALYZE( data, data, w, h, w, zywrle_level, zywrleBuf );
+		  zywrle_level |= 0x80;
+		  ZRLE_ENCODE_TILE( data, w, h, os );
+		  zywrle_level &= 0x7F;
+	  }else
+#endif
+	{
+#ifdef CPIXEL
+      PIXEL_T *ptr;
+      for (ptr = data; ptr < data+w*h; ptr++) {
+        zrleOutStreamWRITE_PIXEL(os, *ptr);
+      }
+#else
+        zrleOutStreamWriteBytes(os, (zrle_U8 *)data, w*h*(BPP/8));
+#endif
+	  }
+    }
+  }
+}
+
+#undef PIXEL_T
+#undef zrleOutStreamWRITE_PIXEL
+#undef ZRLE_ENCODE
+#undef ZRLE_ENCODE_TILE
+#undef ZYWRLE_ENCODE_TILE
+#undef BPPOUT
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrleoutstream.c vnc_unixsrc/vncviewer/zrleoutstream.c
--- vnc_unixsrc.orig/vncviewer/zrleoutstream.c	1969-12-31 19:00:00.000000000 -0500
+++ vnc_unixsrc/vncviewer/zrleoutstream.c	2005-05-15 10:57:54.000000000 -0400
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2002 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#include "zrleoutstream.h"
+#include <stdlib.h>
+
+#define ZRLE_IN_BUFFER_SIZE  16384
+#define ZRLE_OUT_BUFFER_SIZE 1024
+#undef  ZRLE_DEBUG
+
+static rfbBool zrleBufferAlloc(zrleBuffer *buffer, int size)
+{
+  buffer->ptr = buffer->start = malloc(size);
+  if (buffer->start == NULL) {
+    buffer->end = NULL;
+    return FALSE;
+  }
+
+  buffer->end = buffer->start + size;
+
+  return TRUE;
+}
+
+static void zrleBufferFree(zrleBuffer *buffer)
+{
+  if (buffer->start)
+    free(buffer->start);
+  buffer->start = buffer->ptr = buffer->end = NULL;
+}
+
+static rfbBool zrleBufferGrow(zrleBuffer *buffer, int size)
+{
+  int offset;
+
+  size  += buffer->end - buffer->start;
+  offset = ZRLE_BUFFER_LENGTH (buffer);
+
+  buffer->start = realloc(buffer->start, size);
+  if (!buffer->start) {
+    return FALSE;
+  }
+
+  buffer->end = buffer->start + size;
+  buffer->ptr = buffer->start + offset;
+
+  return TRUE;
+}
+
+zrleOutStream *zrleOutStreamNew(void)
+{
+  zrleOutStream *os;
+
+  os = malloc(sizeof(zrleOutStream));
+  if (os == NULL)
+    return NULL;
+
+  if (!zrleBufferAlloc(&os->in, ZRLE_IN_BUFFER_SIZE)) {
+    free(os);
+    return NULL;
+  }
+
+  if (!zrleBufferAlloc(&os->out, ZRLE_OUT_BUFFER_SIZE)) {
+    zrleBufferFree(&os->in);
+    free(os);
+    return NULL;
+  }
+
+  os->zs.zalloc = Z_NULL;
+  os->zs.zfree  = Z_NULL;
+  os->zs.opaque = Z_NULL;
+  if (deflateInit(&os->zs, Z_DEFAULT_COMPRESSION) != Z_OK) {
+    zrleBufferFree(&os->in);
+    free(os);
+    return NULL;
+  }
+
+  return os;
+}
+
+void zrleOutStreamFree (zrleOutStream *os)
+{
+  deflateEnd(&os->zs);
+  zrleBufferFree(&os->in);
+  zrleBufferFree(&os->out);
+  free(os);
+}
+
+rfbBool zrleOutStreamFlush(zrleOutStream *os)
+{
+  os->zs.next_in = os->in.start;
+  os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in);
+  
+#ifdef ZRLE_DEBUG
+  rfbLog("zrleOutStreamFlush: avail_in %d\n", os->zs.avail_in);
+#endif
+
+  while (os->zs.avail_in != 0) {
+    do {
+      int ret;
+
+      if (os->out.ptr >= os->out.end &&
+	  !zrleBufferGrow(&os->out, os->out.end - os->out.start)) {
+	rfbLog("zrleOutStreamFlush: failed to grow output buffer\n");
+	return FALSE;
+      }
+
+      os->zs.next_out = os->out.ptr;
+      os->zs.avail_out = os->out.end - os->out.ptr;
+
+#ifdef ZRLE_DEBUG
+      rfbLog("zrleOutStreamFlush: calling deflate, avail_in %d, avail_out %d\n",
+	     os->zs.avail_in, os->zs.avail_out);
+#endif 
+
+      if ((ret = deflate(&os->zs, Z_SYNC_FLUSH)) != Z_OK) {
+	rfbLog("zrleOutStreamFlush: deflate failed with error code %d\n", ret);
+	return FALSE;
+      }
+
+#ifdef ZRLE_DEBUG
+      rfbLog("zrleOutStreamFlush: after deflate: %d bytes\n",
+	     os->zs.next_out - os->out.ptr);
+#endif
+
+      os->out.ptr = os->zs.next_out;
+    } while (os->zs.avail_out == 0);
+  }
+
+  os->in.ptr = os->in.start;
+ 
+  return TRUE;
+}
+
+static int zrleOutStreamOverrun(zrleOutStream *os,
+				int            size)
+{
+#ifdef ZRLE_DEBUG
+  rfbLog("zrleOutStreamOverrun\n");
+#endif
+
+  while (os->in.end - os->in.ptr < size && os->in.ptr > os->in.start) {
+    os->zs.next_in = os->in.start;
+    os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in);
+
+    do {
+      int ret;
+
+      if (os->out.ptr >= os->out.end &&
+	  !zrleBufferGrow(&os->out, os->out.end - os->out.start)) {
+	rfbLog("zrleOutStreamOverrun: failed to grow output buffer\n");
+	return FALSE;
+      }
+
+      os->zs.next_out = os->out.ptr;
+      os->zs.avail_out = os->out.end - os->out.ptr;
+
+#ifdef ZRLE_DEBUG
+      rfbLog("zrleOutStreamOverrun: calling deflate, avail_in %d, avail_out %d\n",
+	     os->zs.avail_in, os->zs.avail_out);
+#endif
+
+      if ((ret = deflate(&os->zs, 0)) != Z_OK) {
+	rfbLog("zrleOutStreamOverrun: deflate failed with error code %d\n", ret);
+	return 0;
+      }
+
+#ifdef ZRLE_DEBUG
+      rfbLog("zrleOutStreamOverrun: after deflate: %d bytes\n",
+	     os->zs.next_out - os->out.ptr);
+#endif
+
+      os->out.ptr = os->zs.next_out;
+    } while (os->zs.avail_out == 0);
+
+    /* output buffer not full */
+
+    if (os->zs.avail_in == 0) {
+      os->in.ptr = os->in.start;
+    } else {
+      /* but didn't consume all the data?  try shifting what's left to the
+       * start of the buffer.
+       */
+      rfbLog("zrleOutStreamOverrun: out buf not full, but in data not consumed\n");
+      memmove(os->in.start, os->zs.next_in, os->in.ptr - os->zs.next_in);
+      os->in.ptr -= os->zs.next_in - os->in.start;
+    }
+  }
+
+  if (size > os->in.end - os->in.ptr)
+    size = os->in.end - os->in.ptr;
+
+  return size;
+}
+
+static int zrleOutStreamCheck(zrleOutStream *os, int size)
+{
+  if (os->in.ptr + size > os->in.end) {
+    return zrleOutStreamOverrun(os, size);
+  }
+  return size;
+}
+
+void zrleOutStreamWriteBytes(zrleOutStream *os,
+			     const zrle_U8 *data,
+			     int            length)
+{
+  const zrle_U8* dataEnd = data + length;
+  while (data < dataEnd) {
+    int n = zrleOutStreamCheck(os, dataEnd - data);
+    memcpy(os->in.ptr, data, n);
+    os->in.ptr += n;
+    data += n;
+  }
+}
+
+void zrleOutStreamWriteU8(zrleOutStream *os, zrle_U8 u)
+{
+  zrleOutStreamCheck(os, 1);
+  *os->in.ptr++ = u;
+}
+
+void zrleOutStreamWriteOpaque8(zrleOutStream *os, zrle_U8 u)
+{
+  zrleOutStreamCheck(os, 1);
+  *os->in.ptr++ = u;
+}
+
+void zrleOutStreamWriteOpaque16 (zrleOutStream *os, zrle_U16 u)
+{
+  zrleOutStreamCheck(os, 2);
+  *os->in.ptr++ = ((zrle_U8*)&u)[0];
+  *os->in.ptr++ = ((zrle_U8*)&u)[1];
+}
+
+void zrleOutStreamWriteOpaque32 (zrleOutStream *os, zrle_U32 u)
+{
+  zrleOutStreamCheck(os, 4);
+  *os->in.ptr++ = ((zrle_U8*)&u)[0];
+  *os->in.ptr++ = ((zrle_U8*)&u)[1];
+  *os->in.ptr++ = ((zrle_U8*)&u)[2];
+  *os->in.ptr++ = ((zrle_U8*)&u)[3];
+}
+
+void zrleOutStreamWriteOpaque24A(zrleOutStream *os, zrle_U32 u)
+{
+  zrleOutStreamCheck(os, 3);
+  *os->in.ptr++ = ((zrle_U8*)&u)[0];
+  *os->in.ptr++ = ((zrle_U8*)&u)[1];
+  *os->in.ptr++ = ((zrle_U8*)&u)[2];
+}
+
+void zrleOutStreamWriteOpaque24B(zrleOutStream *os, zrle_U32 u)
+{
+  zrleOutStreamCheck(os, 3);
+  *os->in.ptr++ = ((zrle_U8*)&u)[1];
+  *os->in.ptr++ = ((zrle_U8*)&u)[2];
+  *os->in.ptr++ = ((zrle_U8*)&u)[3];
+}
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrleoutstream.h vnc_unixsrc/vncviewer/zrleoutstream.h
--- vnc_unixsrc.orig/vncviewer/zrleoutstream.h	1969-12-31 19:00:00.000000000 -0500
+++ vnc_unixsrc/vncviewer/zrleoutstream.h	2004-05-25 06:05:15.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2002 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#ifndef __ZRLE_OUT_STREAM_H__
+#define __ZRLE_OUT_STREAM_H__
+
+#include <zlib.h>
+#include "zrletypes.h"
+#include "rfb/rfb.h"
+
+typedef struct {
+  zrle_U8 *start;
+  zrle_U8 *ptr;
+  zrle_U8 *end;
+} zrleBuffer;
+
+typedef struct {
+  zrleBuffer in;
+  zrleBuffer out;
+
+  z_stream   zs;
+} zrleOutStream;
+
+#define ZRLE_BUFFER_LENGTH(b) ((b)->ptr - (b)->start)
+
+zrleOutStream *zrleOutStreamNew           (void);
+void           zrleOutStreamFree          (zrleOutStream *os);
+rfbBool        zrleOutStreamFlush         (zrleOutStream *os);
+void           zrleOutStreamWriteBytes    (zrleOutStream *os,
+					   const zrle_U8 *data,
+					   int            length);
+void           zrleOutStreamWriteU8       (zrleOutStream *os,
+					   zrle_U8        u);
+void           zrleOutStreamWriteOpaque8  (zrleOutStream *os,
+					   zrle_U8        u);
+void           zrleOutStreamWriteOpaque16 (zrleOutStream *os,
+					   zrle_U16       u);
+void           zrleOutStreamWriteOpaque32 (zrleOutStream *os,
+					   zrle_U32       u);
+void           zrleOutStreamWriteOpaque24A(zrleOutStream *os,
+					   zrle_U32       u);
+void           zrleOutStreamWriteOpaque24B(zrleOutStream *os,
+					   zrle_U32       u);
+
+#endif /* __ZRLE_OUT_STREAM_H__ */
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrlepalettehelper.c vnc_unixsrc/vncviewer/zrlepalettehelper.c
--- vnc_unixsrc.orig/vncviewer/zrlepalettehelper.c	1969-12-31 19:00:00.000000000 -0500
+++ vnc_unixsrc/vncviewer/zrlepalettehelper.c	2004-05-25 06:05:15.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2002 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#include "zrlepalettehelper.h"
+#include <assert.h>
+#include <string.h>
+
+#define ZRLE_HASH(pix) (((pix) ^ ((pix) >> 17)) & 4095)
+
+void zrlePaletteHelperInit(zrlePaletteHelper *helper)
+{
+  memset(helper->palette, 0, sizeof(helper->palette));
+  memset(helper->index, 255, sizeof(helper->index));
+  memset(helper->key, 0, sizeof(helper->key));
+  helper->size = 0;
+}
+
+void zrlePaletteHelperInsert(zrlePaletteHelper *helper, zrle_U32 pix)
+{
+  if (helper->size < ZRLE_PALETTE_MAX_SIZE) {
+    int i = ZRLE_HASH(pix);
+
+    while (helper->index[i] != 255 && helper->key[i] != pix)
+      i++;
+    if (helper->index[i] != 255) return;
+
+    helper->index[i] = helper->size;
+    helper->key[i] = pix;
+    helper->palette[helper->size] = pix;
+  }
+  helper->size++;
+}
+
+int zrlePaletteHelperLookup(zrlePaletteHelper *helper, zrle_U32 pix)
+{
+  int i = ZRLE_HASH(pix);
+
+  assert(helper->size <= ZRLE_PALETTE_MAX_SIZE);
+  
+  while (helper->index[i] != 255 && helper->key[i] != pix)
+    i++;
+  if (helper->index[i] != 255) return helper->index[i];
+
+  return -1;
+}
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrlepalettehelper.h vnc_unixsrc/vncviewer/zrlepalettehelper.h
--- vnc_unixsrc.orig/vncviewer/zrlepalettehelper.h	1969-12-31 19:00:00.000000000 -0500
+++ vnc_unixsrc/vncviewer/zrlepalettehelper.h	2004-05-25 06:05:15.000000000 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2002 RealVNC Ltd.  All Rights Reserved.
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+/*
+ * The PaletteHelper class helps us build up the palette from pixel data by
+ * storing a reverse index using a simple hash-table
+ */
+
+#ifndef __ZRLE_PALETTE_HELPER_H__
+#define __ZRLE_PALETTE_HELPER_H__
+
+#include "zrletypes.h"
+
+#define ZRLE_PALETTE_MAX_SIZE 127
+
+typedef struct {
+  zrle_U32  palette[ZRLE_PALETTE_MAX_SIZE];
+  zrle_U8   index[ZRLE_PALETTE_MAX_SIZE + 4096];
+  zrle_U32  key[ZRLE_PALETTE_MAX_SIZE + 4096];
+  int       size;
+} zrlePaletteHelper;
+
+void zrlePaletteHelperInit  (zrlePaletteHelper *helper);
+void zrlePaletteHelperInsert(zrlePaletteHelper *helper,
+			     zrle_U32           pix);
+int  zrlePaletteHelperLookup(zrlePaletteHelper *helper,
+			     zrle_U32           pix);
+
+#endif /* __ZRLE_PALETTE_HELPER_H__ */
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrletypes.h vnc_unixsrc/vncviewer/zrletypes.h
--- vnc_unixsrc.orig/vncviewer/zrletypes.h	1969-12-31 19:00:00.000000000 -0500
+++ vnc_unixsrc/vncviewer/zrletypes.h	2004-05-25 06:05:15.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2002 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
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+#ifndef __ZRLE_TYPES_H__
+#define __ZRLE_TYPES_H__
+
+typedef unsigned char  zrle_U8;
+typedef unsigned short zrle_U16;
+typedef unsigned int   zrle_U32;
+typedef signed char    zrle_S8;
+typedef signed short   zrle_S16;
+typedef signed int     zrle_S32;
+
+#endif /* __ZRLE_TYPES_H__ */
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zywrletemplate.c vnc_unixsrc/vncviewer/zywrletemplate.c
--- vnc_unixsrc.orig/vncviewer/zywrletemplate.c	1969-12-31 19:00:00.000000000 -0500
+++ vnc_unixsrc/vncviewer/zywrletemplate.c	2007-02-04 23:24:16.000000000 -0500
@@ -0,0 +1,804 @@
+
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE.         *
+ *                                                                  *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * GOVERNED BY A FOLLOWING BSD-STYLE SOURCE LICENSE.                *
+ * PLEASE READ THESE TERMS BEFORE DISTRIBUTING.                     *
+ *                                                                  *
+ * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006         *
+ * BY Hitachi Systems & Services, Ltd.                              *
+ * (Noriaki Yamazaki, Research & Developement Center)               *                                                                 *
+ *                                                                  *
+ ********************************************************************
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Hitachi Systems & Services, Ltd. nor 
+the names of its contributors may be used to endorse or promote 
+products derived from this software without specific prior written
+permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************/
+
+//#define ZYWRLE_ENCODE
+//#define ZYWRLE_DECODE
+#define ZYWRLE_QUANTIZE
+
+//[References]
+// PLHarr:
+//   Senecal, J. G., P. Lindstrom, M. A. Duchaineau, and K. I. Joy, "An Improved N-Bit to N-Bit Reversible Haar-Like Transform," Pacific Graphics 2004, October 2004, pp. 371-380.
+// EZW:
+//   Shapiro, JM: Embedded Image Coding Using Zerotrees of Wavelet Coefficients, IEEE Trans. Signal. Process., Vol.41, pp.3445-3462 (1993). 
+
+
+// Template Macro stuffs.
+#undef ZYWRLE_ANALYZE
+#undef ZYWRLE_SYNTHESIZE
+#define ZYWRLE_ANALYZE __RFB_CONCAT3E(zywrleAnalyze,BPP,END_FIX)
+#define ZYWRLE_SYNTHESIZE __RFB_CONCAT3E(zywrleSynthesize,BPP,END_FIX)
+
+#define ZYWRLE_RGBYUV __RFB_CONCAT3E(zywrleRGBYUV,BPP,END_FIX)
+#define ZYWRLE_YUVRGB __RFB_CONCAT3E(zywrleYUVRGB,BPP,END_FIX)
+#define ZYWRLE_YMASK __RFB_CONCAT2E(ZYWRLE_YMASK,BPP)
+#define ZYWRLE_UVMASK __RFB_CONCAT2E(ZYWRLE_UVMASK,BPP)
+#define ZYWRLE_LOAD_PIXEL __RFB_CONCAT2E(ZYWRLE_LOAD_PIXEL,BPP)
+#define ZYWRLE_SAVE_PIXEL __RFB_CONCAT2E(ZYWRLE_SAVE_PIXEL,BPP)
+
+// Packing/Unpacking pixel stuffs.
+//   Endian conversion stuffs.
+#undef S_0
+#undef S_1
+#undef L_0
+#undef L_1
+#undef L_2
+#if ZYWRLE_ENDIAN == ENDIAN_BIG
+#  define S_0	1
+#  define S_1	0
+#  define L_0	3
+#  define L_1	2
+#  define L_2	1
+#else
+#  define S_0	0
+#  define S_1	1
+#  define L_0	0
+#  define L_1	1
+#  define L_2	2
+#endif
+
+//   Load/Save pixel stuffs.
+#define ZYWRLE_YMASK15  0xFFFFFFF8
+#define ZYWRLE_UVMASK15 0xFFFFFFF8
+#define ZYWRLE_LOAD_PIXEL15(pSrc,R,G,B) { \
+	R =  (((unsigned char*)pSrc)[S_1]<< 1)& 0xF8;	\
+	G = ((((unsigned char*)pSrc)[S_1]<< 6)|(((unsigned char*)pSrc)[S_0]>> 2))& 0xF8;	\
+	B =  (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8;	\
+}
+#define ZYWRLE_SAVE_PIXEL15(pDst,R,G,B) { \
+	R &= 0xF8;	\
+	G &= 0xF8;	\
+	B &= 0xF8;	\
+	((unsigned char*)pDst)[S_1] = (unsigned char)( (R>>1)|(G>>6)       );	\
+	((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<2))& 0xFF);	\
+}
+#define ZYWRLE_YMASK16  0xFFFFFFFC
+#define ZYWRLE_UVMASK16 0xFFFFFFF8
+#define ZYWRLE_LOAD_PIXEL16(pSrc,R,G,B) { \
+	R =   ((unsigned char*)pSrc)[S_1]     & 0xF8;	\
+	G = ((((unsigned char*)pSrc)[S_1]<< 5)|(((unsigned char*)pSrc)[S_0]>> 3))& 0xFC;	\
+	B =  (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8;	\
+}
+#define ZYWRLE_SAVE_PIXEL16(pDst,R,G,B) { \
+	R &= 0xF8;	\
+	G &= 0xFC;	\
+	B &= 0xF8;	\
+	((unsigned char*)pDst)[S_1] = (unsigned char)(  R    |(G>>5)       );	\
+	((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<3))& 0xFF);	\
+}
+#define ZYWRLE_YMASK32  0xFFFFFFFF
+#define ZYWRLE_UVMASK32 0xFFFFFFFF
+#define ZYWRLE_LOAD_PIXEL32(pSrc,R,G,B) { \
+	R = ((unsigned char*)pSrc)[L_2];	\
+	G = ((unsigned char*)pSrc)[L_1];	\
+	B = ((unsigned char*)pSrc)[L_0];	\
+}
+#define ZYWRLE_SAVE_PIXEL32(pDst,R,G,B) { \
+	((unsigned char*)pDst)[L_2] = (unsigned char)R;	\
+	((unsigned char*)pDst)[L_1] = (unsigned char)G;	\
+	((unsigned char*)pDst)[L_0] = (unsigned char)B;	\
+}
+
+#ifndef ZYWRLE_ONCE
+#define ZYWRLE_ONCE
+
+#ifdef WIN32
+#define InlineX __inline
+#else
+#define InlineX inline
+#endif
+
+#ifdef ZYWRLE_ENCODE
+// Tables for Coefficients filtering.
+#  ifndef ZYWRLE_QUANTIZE
+// Type A:lower bit omitting of EZW style.
+const static unsigned int zywrleParam[3][3]={
+	{0x0000F000,0x00000000,0x00000000},
+	{0x0000C000,0x00F0F0F0,0x00000000},
+	{0x0000C000,0x00C0C0C0,0x00F0F0F0},
+//	{0x0000FF00,0x00000000,0x00000000},
+//	{0x0000FF00,0x00FFFFFF,0x00000000},
+//	{0x0000FF00,0x00FFFFFF,0x00FFFFFF},
+};
+#  else
+// Type B:Non liner quantization filter.
+static const signed char zywrleConv[4][256]={
+{	// bi=5, bo=5 r=0.0:PSNR=24.849
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+},
+{	// bi=5, bo=5 r=2.0:PSNR=74.031
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 32, 
+	32, 32, 32, 32, 32, 32, 32, 32, 
+	32, 32, 32, 32, 32, 32, 32, 32, 
+	48, 48, 48, 48, 48, 48, 48, 48, 
+	48, 48, 48, 56, 56, 56, 56, 56, 
+	56, 56, 56, 56, 64, 64, 64, 64, 
+	64, 64, 64, 64, 72, 72, 72, 72, 
+	72, 72, 72, 72, 80, 80, 80, 80, 
+	80, 80, 88, 88, 88, 88, 88, 88, 
+	88, 88, 88, 88, 88, 88, 96, 96, 
+	96, 96, 96, 104, 104, 104, 104, 104, 
+	104, 104, 104, 104, 104, 112, 112, 112, 
+	112, 112, 112, 112, 112, 112, 120, 120, 
+	120, 120, 120, 120, 120, 120, 120, 120, 
+	0, -120, -120, -120, -120, -120, -120, -120, 
+	-120, -120, -120, -112, -112, -112, -112, -112, 
+	-112, -112, -112, -112, -104, -104, -104, -104, 
+	-104, -104, -104, -104, -104, -104, -96, -96, 
+	-96, -96, -96, -88, -88, -88, -88, -88, 
+	-88, -88, -88, -88, -88, -88, -88, -80, 
+	-80, -80, -80, -80, -80, -72, -72, -72, 
+	-72, -72, -72, -72, -72, -64, -64, -64, 
+	-64, -64, -64, -64, -64, -56, -56, -56, 
+	-56, -56, -56, -56, -56, -56, -48, -48, 
+	-48, -48, -48, -48, -48, -48, -48, -48, 
+	-48, -32, -32, -32, -32, -32, -32, -32, 
+	-32, -32, -32, -32, -32, -32, -32, -32, 
+	-32, -32, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+},
+{	// bi=5, bo=4 r=2.0:PSNR=64.441
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	48, 48, 48, 48, 48, 48, 48, 48, 
+	48, 48, 48, 48, 48, 48, 48, 48, 
+	48, 48, 48, 48, 48, 48, 48, 48, 
+	64, 64, 64, 64, 64, 64, 64, 64, 
+	64, 64, 64, 64, 64, 64, 64, 64, 
+	80, 80, 80, 80, 80, 80, 80, 80, 
+	80, 80, 80, 80, 80, 88, 88, 88, 
+	88, 88, 88, 88, 88, 88, 88, 88, 
+	104, 104, 104, 104, 104, 104, 104, 104, 
+	104, 104, 104, 112, 112, 112, 112, 112, 
+	112, 112, 112, 112, 120, 120, 120, 120, 
+	120, 120, 120, 120, 120, 120, 120, 120, 
+	0, -120, -120, -120, -120, -120, -120, -120, 
+	-120, -120, -120, -120, -120, -112, -112, -112, 
+	-112, -112, -112, -112, -112, -112, -104, -104, 
+	-104, -104, -104, -104, -104, -104, -104, -104, 
+	-104, -88, -88, -88, -88, -88, -88, -88, 
+	-88, -88, -88, -88, -80, -80, -80, -80, 
+	-80, -80, -80, -80, -80, -80, -80, -80, 
+	-80, -64, -64, -64, -64, -64, -64, -64, 
+	-64, -64, -64, -64, -64, -64, -64, -64, 
+	-64, -48, -48, -48, -48, -48, -48, -48, 
+	-48, -48, -48, -48, -48, -48, -48, -48, 
+	-48, -48, -48, -48, -48, -48, -48, -48, 
+	-48, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+},
+{	// bi=5, bo=2 r=2.0:PSNR=43.175
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	88, 88, 88, 88, 88, 88, 88, 88, 
+	88, 88, 88, 88, 88, 88, 88, 88, 
+	88, 88, 88, 88, 88, 88, 88, 88, 
+	88, 88, 88, 88, 88, 88, 88, 88, 
+	88, 88, 88, 88, 88, 88, 88, 88, 
+	88, 88, 88, 88, 88, 88, 88, 88, 
+	88, 88, 88, 88, 88, 88, 88, 88, 
+	88, 88, 88, 88, 88, 88, 88, 88, 
+	0, -88, -88, -88, -88, -88, -88, -88, 
+	-88, -88, -88, -88, -88, -88, -88, -88, 
+	-88, -88, -88, -88, -88, -88, -88, -88, 
+	-88, -88, -88, -88, -88, -88, -88, -88, 
+	-88, -88, -88, -88, -88, -88, -88, -88, 
+	-88, -88, -88, -88, -88, -88, -88, -88, 
+	-88, -88, -88, -88, -88, -88, -88, -88, 
+	-88, -88, -88, -88, -88, -88, -88, -88, 
+	-88, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+	0, 0, 0, 0, 0, 0, 0, 0, 
+}
+};
+const static signed char* zywrleParam[3][3][3]={
+	{{zywrleConv[0],zywrleConv[2],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}},
+	{{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}},
+	{{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[2],zywrleConv[2],zywrleConv[2]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]}},
+};
+#  endif
+#endif
+
+static InlineX void Harr( signed char* pX0, signed char* pX1 ){
+	// Piecewise-Linear Harr(PLHarr)
+	int X0=(int)*pX0, X1=(int)*pX1;
+	int orgX0=X0, orgX1=X1;
+	if( (X0^X1)&0x80 ){
+		// differ sign
+		X1 += X0;
+		if( ((X1^orgX1)&0x80)==0 ){
+			// |X1| > |X0|
+			X0 -= X1;	// H = -B
+		}
+	}else{
+		// same sign
+		X0 -= X1;
+		if( ((X0^orgX0)&0x80)==0 ){
+			// |X0| > |X1|
+			X1 += X0;	// L = A
+		}
+	}
+	*pX0 = (signed char)X1;
+	*pX1 = (signed char)X0;
+}
+// 1D-Wavelet transform.
+//
+// In coefficients array, the famous 'pyramid' decomposition is well used.
+//
+// 1D Model:
+//   |L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0
+//   |L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1
+//
+// But this method needs line buffer because H/L is different position from X0/X1.
+// So, I used 'interleave' decomposition instead of it.
+//
+// 1D Model:
+//   |L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0
+//   |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1
+//
+// In this method, H/L and X0/X1 is always same position.
+// This lead us to more speed and less memory.
+// Of cause, the result of both method is quite same
+// because it's only difference that coefficient position.
+
+static InlineX void WaveletLevel( int* data, int size, int l, int SkipPixel ){
+	int s, ofs;
+	signed char* pX0;
+	signed char* end;
+
+	pX0 = (signed char*)data;
+	s = (8<<l)*SkipPixel;
+	end = pX0+(size>>(l+1))*s;
+	s -= 2;
+	ofs = (4<<l)*SkipPixel;
+	while( pX0 < end ){
+		Harr( pX0, pX0+ofs );
+		pX0++;
+		Harr( pX0, pX0+ofs );
+		pX0++;
+		Harr( pX0, pX0+ofs );
+		pX0 += s;
+	}
+}
+#define InvWaveletLevel(d,s,l,pix) WaveletLevel(d,s,l,pix)
+
+#ifdef ZYWRLE_ENCODE
+#  ifndef ZYWRLE_QUANTIZE
+// Type A:lower bit omitting of EZW style.
+static InlineX void FilterWaveletSquare( int* pBuf, int width, int height, int level, int l ){
+	int r, s;
+	int x, y;
+	int* pH;
+	const unsigned int* pM;
+
+	pM = &(zywrleParam[level-1][l]);
+	s = 2<<l;
+	for( r=1; r<4; r++ ){
+		pH   = pBuf;
+		if( r & 0x01 ){
+			pH +=  s>>1;
+		}
+		if( r & 0x02 ){
+			pH += (s>>1)*width;
+		}
+		for( y=0; y<height/s; y++ ){
+			for( x=0; x<width/s; x++ ){
+				// these are same following code.
+				//     pH[x] = pH[x] / (~pM[x]+1) * (~pM[x]+1);
+				//     ( round pH[x] with pM[x] bit )
+				// '&' operator isn't 'round' but is 'floor'.
+				// So, we must offset when pH[x] is negative.
+				if( ((signed char*)pH)[0] & 0x80 ){
+					((signed char*)pH)[0] += ~((signed char*)pM)[0];
+				}
+				if( ((signed char*)pH)[1] & 0x80 ){
+					((signed char*)pH)[1] += ~((signed char*)pM)[1];
+				}
+				if( ((signed char*)pH)[2] & 0x80 ){
+					((signed char*)pH)[2] += ~((signed char*)pM)[2];
+				}
+				*pH &= *pM;
+				pH += s;
+			}
+			pH += (s-1)*width;
+		}
+	}
+}
+#  else
+// Type B:Non liner quantization filter.
+//
+// Coefficients have Gaussian curve and smaller value which is 
+// large part of coefficients isn't more important than larger value.
+// So, I use filter of Non liner quantize/dequantize table.
+// In general, Non liner quantize formula is explained as following.
+//
+//    y=f(x)   = sign(x)*round( ((abs(x)/(2^7))^ r   )* 2^(bo-1) )*2^(8-bo)
+//    x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi)
+// ( r:power coefficient  bi:effective MSB in input  bo:effective MSB in output )
+//
+//   r < 1.0 : Smaller value is more important than larger value.
+//   r > 1.0 : Larger value is more important than smaller value.
+//   r = 1.0 : Liner quantization which is same with EZW style.
+//
+// r = 0.75 is famous non liner quantization used in MP3 audio codec.
+// In contrast to audio data, larger value is important in wavelet coefficients.
+// So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ).
+//
+// As compared with EZW style liner quantization, this filter tended to be 
+// more sharp edge and be more compression rate but be more blocking noise and be less quality.
+// Especially, the surface of graphic objects has distinguishable noise in middle quality mode.
+//
+// We need only quantized-dequantized(filtered) value rather than quantized value itself
+// because all values are packed or palette-lized in later ZRLE section.
+// This lead us not to need to modify client decoder when we change
+// the filtering procedure in future.
+// Client only decodes coefficients given by encoder.
+static InlineX void FilterWaveletSquare( int* pBuf, int width, int height, int level, int l ){
+	int r, s;
+	int x, y;
+	int* pH;
+	const signed char** pM;
+
+	pM = zywrleParam[level-1][l];
+	s = 2<<l;
+	for( r=1; r<4; r++ ){
+		pH   = pBuf;
+		if( r & 0x01 ){
+			pH +=  s>>1;
+		}
+		if( r & 0x02 ){
+			pH += (s>>1)*width;
+		}
+		for( y=0; y<height/s; y++ ){
+			for( x=0; x<width/s; x++ ){
+				((signed char*)pH)[0] = pM[0][((unsigned char*)pH)[0]];
+				((signed char*)pH)[1] = pM[1][((unsigned char*)pH)[1]];
+				((signed char*)pH)[2] = pM[2][((unsigned char*)pH)[2]];
+				pH += s;
+			}
+			pH += (s-1)*width;
+		}
+	}
+}
+#  endif
+
+static InlineX void Wavelet( int* pBuf, int width, int height, int level ){
+	int l, s;
+	int* pTop;
+	int* pEnd;
+
+	for( l=0; l<level; l++ ){
+		pTop = pBuf;
+		pEnd = pBuf+height*width;
+		s = width<<l;
+		while( pTop < pEnd ){
+			WaveletLevel( pTop, width, l, 1 );
+			pTop += s;
+		}
+		pTop = pBuf;
+		pEnd = pBuf+width;
+		s = 1<<l;
+		while( pTop < pEnd ){
+			WaveletLevel( pTop, height,l, width );
+			pTop += s;
+		}
+		FilterWaveletSquare( pBuf, width, height, level, l );
+	}
+}
+#endif
+#ifdef ZYWRLE_DECODE
+static InlineX void InvWavelet( int* pBuf, int width, int height, int level ){
+	int l, s;
+	int* pTop;
+	int* pEnd;
+
+	for( l=level-1; l>=0; l-- ){
+		pTop = pBuf;
+		pEnd = pBuf+width;
+		s = 1<<l;
+		while( pTop < pEnd ){
+			InvWaveletLevel( pTop, height,l, width );
+			pTop += s;
+		}
+		pTop = pBuf;
+		pEnd = pBuf+height*width;
+		s = width<<l;
+		while( pTop < pEnd ){
+			InvWaveletLevel( pTop, width, l, 1 );
+			pTop += s;
+		}
+	}
+}
+#endif
+
+// Load/Save coefficients stuffs.
+// Coefficients manages as 24 bits little-endian pixel.
+#define ZYWRLE_LOAD_COEFF(pSrc,R,G,B) { \
+	R = ((signed char*)pSrc)[2];	\
+	G = ((signed char*)pSrc)[1];	\
+	B = ((signed char*)pSrc)[0];	\
+}
+#define ZYWRLE_SAVE_COEFF(pDst,R,G,B) { \
+	((signed char*)pDst)[2] = (signed char)R;	\
+	((signed char*)pDst)[1] = (signed char)G;	\
+	((signed char*)pDst)[0] = (signed char)B;	\
+}
+
+// RGB <=> YUV conversion stuffs.
+// YUV coversion is explained as following formula in strict meaning:
+//   Y =  0.299R + 0.587G + 0.114B (   0<=Y<=255)
+//   U = -0.169R - 0.331G + 0.500B (-128<=U<=127)
+//   V =  0.500R - 0.419G - 0.081B (-128<=V<=127)
+// 
+// I use simple conversion RCT(reversible color transform) which is described 
+// in JPEG-2000 specification.
+//   Y = (R + 2G + B)/4 (   0<=Y<=255)
+//   U = B-G (-256<=U<=255)
+//   V = R-G (-256<=V<=255)
+
+#define ROUND(x) (((x)<0)?0:(((x)>255)?255:(x)))
+	// RCT is N-bit RGB to N-bit Y and N+1-bit UV.
+	// For make Same N-bit, UV is lossy.
+	// More exact PLHarr, we reduce to odd range(-127<=x<=127).
+#define ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ymask,uvmask) { \
+	Y = (R+(G<<1)+B)>>2;	\
+	U =  B-G;	\
+	V =  R-G;	\
+	Y -= 128;	\
+	U >>= 1;	\
+	V >>= 1;	\
+	Y &= ymask;	\
+	U &= uvmask;	\
+	V &= uvmask;	\
+	if( Y == -128 ){	\
+		Y += (0xFFFFFFFF-ymask+1);	\
+	}	\
+	if( U == -128 ){	\
+		U += (0xFFFFFFFF-uvmask+1);	\
+	}	\
+	if( V == -128 ){	\
+		V += (0xFFFFFFFF-uvmask+1);	\
+	}	\
+}
+#define ZYWRLE_YUVRGB1(R,G,B,Y,U,V) { \
+	Y += 128;	\
+	U <<= 1;	\
+	V <<= 1;	\
+	G = Y-((U+V)>>2);	\
+	B = U+G;	\
+	R = V+G;	\
+	G = ROUND(G);	\
+	B = ROUND(B);	\
+	R = ROUND(R);	\
+}
+
+// coefficient packing/unpacking stuffs.
+// Wavelet transform makes 4 sub coefficient image from 1 original image.
+//
+// model with pyramid decomposition:
+//   +------+------+
+//   |      |      |
+//   |  L   |  Hx  |
+//   |      |      |
+//   +------+------+
+//   |      |      |
+//   |  H   |  Hxy |
+//   |      |      |
+//   +------+------+
+//
+// So, we must transfer each sub images individually in strict meaning.
+// But at least ZRLE meaning, following one decompositon image is same as
+// avobe individual sub image. I use this format.
+// (Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L)
+//  for simplified procedure for any wavelet level.)
+//
+//   +------+------+
+//   |      L      |
+//   +------+------+
+//   |      Hx     |
+//   +------+------+
+//   |      Hy     |
+//   +------+------+
+//   |      Hxy    |
+//   +------+------+
+
+#define ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,level,TRANS)	\
+	pH = pBuf;	\
+	s = 2<<level;	\
+	if( r & 0x01 ){	\
+		pH +=  s>>1;	\
+	}	\
+	if( r & 0x02 ){	\
+		pH += (s>>1)*width;	\
+	}	\
+	pEnd = pH+height*width;	\
+	while( pH < pEnd ){	\
+		pLine = pH+width;	\
+		while( pH < pLine ){	\
+			TRANS	\
+			data++;	\
+			pH += s;	\
+		}	\
+		pH += (s-1)*width;	\
+	}
+
+#define ZYWRLE_PACK_COEFF(pBuf,data,r,width,height,level)	\
+	ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,level,ZYWRLE_LOAD_COEFF(pH,R,G,B);ZYWRLE_SAVE_PIXEL(data,R,G,B);)
+
+#define ZYWRLE_UNPACK_COEFF(pBuf,data,r,width,height,level)	\
+	ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,level,ZYWRLE_LOAD_PIXEL(data,R,G,B);ZYWRLE_SAVE_COEFF(pH,R,G,B);)
+
+#define ZYWRLE_SAVE_UNALIGN(data,TRANS)	\
+	pTop = pBuf+w*h;	\
+	pEnd = pTop + (w+uw)*(h+uh)-w*h;	\
+	while( pTop < pEnd ){	\
+		TRANS	\
+		data++;	\
+		pTop++;	\
+	}
+
+#define ZYWRLE_LOAD_UNALIGN(data,pData,TRANS)	\
+	pTop = pBuf+w*h;	\
+	if( uw ){	\
+		pData=         data + w;	\
+		pEnd = (int*)(pData+ h*scanline);	\
+		while( pData < (PIXEL_T*)pEnd ){	\
+			pLine = (int*)(pData + uw);	\
+			while( pData < (PIXEL_T*)pLine ){	\
+				TRANS	\
+				pData++;	\
+				pTop++;	\
+			}	\
+			pData += scanline-uw;	\
+		}	\
+	}	\
+	if( uh ){	\
+		pData=         data +  h*scanline;	\
+		pEnd = (int*)(pData+ uh*scanline);	\
+		while( pData < (PIXEL_T*)pEnd ){	\
+			pLine = (int*)(pData + w);	\
+			while( pData < (PIXEL_T*)pLine ){	\
+				TRANS	\
+				pData++;	\
+				pTop++;	\
+			}	\
+			pData += scanline-w;	\
+		}	\
+	}	\
+	if( uw && uh ){	\
+		pData=         data + w+ h*scanline;	\
+		pEnd = (int*)(pData+   uh*scanline);	\
+		while( pData < (PIXEL_T*)pEnd ){	\
+			pLine = (int*)(pData + uw);	\
+			while( pData < (PIXEL_T*)pLine ){	\
+				TRANS	\
+				pData++;	\
+				pTop++;	\
+			}	\
+			pData += scanline-uw;	\
+		}	\
+	}
+
+static InlineX void zywrleCalcSize( int* pW, int* pH, int level ){
+	*pW &= ~((1<<level)-1);
+	*pH &= ~((1<<level)-1);
+}
+
+#endif // ZYWRLE_ONCE
+
+#ifndef CPIXEL
+#ifdef ZYWRLE_ENCODE
+static InlineX void ZYWRLE_RGBYUV( int* pBuf, PIXEL_T* data, int width, int height, int scanline ){
+	int R, G, B;
+	int Y, U, V;
+	int* pLine;
+	int* pEnd;
+	pEnd = pBuf+height*width;
+	while( pBuf < pEnd ){
+		pLine = pBuf+width;
+		while( pBuf < pLine ){
+			ZYWRLE_LOAD_PIXEL(data,R,G,B);
+			ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ZYWRLE_YMASK,ZYWRLE_UVMASK);
+			ZYWRLE_SAVE_COEFF(pBuf,V,Y,U);
+			pBuf++;
+			data++;
+		}
+		data += scanline-width;
+	}
+}
+#endif
+#ifdef ZYWRLE_DECODE
+static InlineX void ZYWRLE_YUVRGB( int* pBuf, PIXEL_T* data, int width, int height, int scanline ){
+	int R, G, B;
+	int Y, U, V;
+	int* pLine;
+	int* pEnd;
+	pEnd = pBuf+height*width;
+	while( pBuf < pEnd ){
+		pLine = pBuf+width;
+		while( pBuf < pLine ){
+			ZYWRLE_LOAD_COEFF(pBuf,V,Y,U);
+			ZYWRLE_YUVRGB1(R,G,B,Y,U,V);
+			ZYWRLE_SAVE_PIXEL(data,R,G,B);
+			pBuf++;
+			data++;
+		}
+		data += scanline-width;
+	}
+}
+#endif
+
+#ifdef ZYWRLE_ENCODE
+PIXEL_T* ZYWRLE_ANALYZE ( PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf ){
+	int l;
+	int uw = w;
+	int uh = h;
+	int* pTop;
+	int* pEnd;
+	int* pLine;
+	PIXEL_T* pSrc;
+	int R, G, B;
+	int s;
+	int* pH;
+
+	zywrleCalcSize( &w, &h, level );
+	if( (w==0)||(h==0) ){
+		return NULL;
+	}
+	uw -= w;
+	uh -= h;
+
+	ZYWRLE_LOAD_UNALIGN(src,pSrc,*(PIXEL_T*)pTop=*pSrc;)
+	ZYWRLE_RGBYUV( pBuf, src, w, h, scanline );
+	Wavelet( pBuf, w, h, level );
+	for( l=0; l<level; l++ ){
+		ZYWRLE_PACK_COEFF( pBuf, dst, 3, w, h, l );
+		ZYWRLE_PACK_COEFF( pBuf, dst, 2, w, h, l );
+		ZYWRLE_PACK_COEFF( pBuf, dst, 1, w, h, l );
+		if( l == level-1 ){
+			ZYWRLE_PACK_COEFF( pBuf, dst, 0, w, h, l );
+		}
+	}
+	ZYWRLE_SAVE_UNALIGN(dst,*dst=*(PIXEL_T*)pTop;)
+	return dst;
+}
+#endif
+#ifdef ZYWRLE_DECODE
+PIXEL_T* ZYWRLE_SYNTHESIZE ( PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf ){
+	int l;
+	int uw = w;
+	int uh = h;
+	int* pTop;
+	int* pEnd;
+	int* pLine;
+	PIXEL_T* pDst;
+	int R, G, B;
+	int s;
+	int* pH;
+
+	zywrleCalcSize( &w, &h, level );
+	if( (w==0)||(h==0) ){
+		return NULL;
+	}
+	uw -= w;
+	uh -= h;
+
+	for( l=0; l<level; l++ ){
+		ZYWRLE_UNPACK_COEFF( pBuf, src, 3, w, h, l );
+		ZYWRLE_UNPACK_COEFF( pBuf, src, 2, w, h, l );
+		ZYWRLE_UNPACK_COEFF( pBuf, src, 1, w, h, l );
+		if( l == level-1 ){
+			ZYWRLE_UNPACK_COEFF( pBuf, src, 0, w, h, l );
+		}
+	}
+	ZYWRLE_SAVE_UNALIGN(src,*(PIXEL_T*)pTop=*src;)
+	InvWavelet( pBuf, w, h, level );
+	ZYWRLE_YUVRGB( pBuf, dst, w, h, scanline );
+	ZYWRLE_LOAD_UNALIGN(dst,pDst,*pDst=*(PIXEL_T*)pTop;)
+	return src;
+}
+#endif
+#endif  // CPIXEL
+
+#undef ZYWRLE_RGBYUV
+#undef ZYWRLE_YUVRGB
+#undef ZYWRLE_LOAD_PIXEL
+#undef ZYWRLE_SAVE_PIXEL
diff -Naur vnc_unixsrc.orig/include/rfbproto.h vnc_unixsrc/include/rfbproto.h
--- vnc_unixsrc.orig/include/rfbproto.h	2004-05-27 03:02:02.000000000 -0400
+++ vnc_unixsrc/include/rfbproto.h	2007-02-18 13:04:35.000000000 -0500
@@ -381,6 +381,10 @@
 #define rfbBell 2
 #define rfbServerCutText 3
 
+
+/* http://sourceforge.net/projects/vncsessmgr */
+#define rfbRestartConnection 82
+
 #define rfbFileListData 130
 #define rfbFileDownloadData 131
 #define rfbFileUploadCancel 132
@@ -403,6 +407,18 @@
 #define rfbPointerEvent 5
 #define rfbClientCutText 6
 
+/* ultra */
+
+#define rfbFileTransfer 7
+#define rfbSetScale 8
+#define rfbSetServerInput 9
+#define rfbSetSW 10
+#define rfbTextChat 11
+#define rfbKeyFrameRequest 12
+#define rfbPalmVNCSetScaleFactor 0xF
+
+
+
 #define rfbFileListRequest 130
 #define rfbFileDownloadRequest 131
 #define rfbFileUploadRequest 132
@@ -435,6 +451,11 @@
 #define rfbEncodingTight     7
 #define rfbEncodingZlibHex   8
 
+#define rfbEncodingZRLE 16
+// nyama/2006/08/02:new YUV-Wavlet lossy codec based on ZRLE (ZYWRLE)
+#define rfbEncodingZYWRLE 17
+
+
 /* signatures for basic encoding types */
 #define sig_rfbEncodingRaw       "RAW_____"
 #define sig_rfbEncodingCopyRect  "COPYRECT"
@@ -955,6 +976,36 @@
 #define sz_rfbFileDownloadFailedMsg 4
 
 /*-----------------------------------------------------------------------------
+ * RestartConnection - the server has restarted the client connection.
+ */
+
+typedef struct _rfbRestartConnectionMsg {
+    CARD8 type;			/* always rfbRestartConnection */
+    CARD8 pad1;
+    CARD16 pad2;
+    CARD32 length;
+    /* followed by char text[length] */
+} rfbRestartConnectionMsg;
+
+#define sz_rfbRestartConnectionMsg 8
+
+
+typedef struct _rfbTextChatMsg {
+    CARD8 type;                 /* always rfbTextChat */
+    CARD8 pad1;         // Could be used later as an additionnal param
+    CARD16 pad2;                // Could be used later as text offset, for instance
+    CARD32 length;      // Specific values for Open, close, finished (-1, -2, -3)
+    /* followed by char text[length] */
+} rfbTextChatMsg;
+
+#define sz_rfbTextChatMsg 8
+
+#define rfbTextMaxSize          4096
+#define rfbTextChatOpen         0xFFFFFFFF 
+#define rfbTextChatClose        0xFFFFFFFE  
+#define rfbTextChatFinished 0xFFFFFFFD  
+
+/*-----------------------------------------------------------------------------
  * Union of all server->client messages.
  */
 
@@ -968,6 +1019,8 @@
     rfbFileDownloadDataMsg fdd;
     rfbFileUploadCancelMsg fuc;
     rfbFileDownloadFailedMsg fdf;
+    rfbRestartConnectionMsg rc;
+	rfbTextChatMsg tc;
 } rfbServerToClientMsg;
 
 
@@ -1221,6 +1274,41 @@
 
 #define sz_rfbFileCreateDirRequestMsg 4
 
+/* ultra */
+typedef struct _rfbSetScaleMsg {
+    CARD8 type;                 /* always rfbSetScale */
+    CARD8 scale;                /* Scale value 1<sv<n */
+    CARD16 pad;
+} rfbSetScaleMsg;
+
+#define sz_rfbSetScaleMsg 4
+
+typedef struct {
+    CARD8 type;                 /* always rfbSetScaleFactor */
+
+    CARD8 scale;                /* Scale factor (positive non-zero integer) */
+    CARD16 pad2;
+} rfbPalmVNCSetScaleFactorMsg;
+
+#define sz_rfbPalmVNCSetScaleFactorMsg (4)
+
+typedef struct _rfbSetServerInputMsg {
+    CARD8 type;                 /* always rfbSetServerInputMsg */
+    CARD8 status;               /* on or off */
+    CARD16 pad;
+} rfbSetServerInputMsg;
+
+#define sz_rfbSetServerInputMsg 4
+
+typedef struct _rfbSetSWMsg {
+    CARD8 type;                 /* always rfbSetSW */
+    CARD8 status;
+    CARD16 x;
+    CARD16 y;
+} rfbSetSWMsg;
+
+#define sz_rfbSetSWMsg 6
+
 /*-----------------------------------------------------------------------------
  * Union of all client->server messages.
  */
@@ -1241,4 +1329,9 @@
     rfbFileDownloadCancelMsg fdc;
     rfbFileUploadFailedMsg fuf;
     rfbFileCreateDirRequestMsg fcdr;
+	rfbSetScaleMsg ssc;
+	rfbPalmVNCSetScaleFactorMsg pssf;
+	rfbSetServerInputMsg sim;
+	rfbSetSWMsg sw;
+	rfbTextChatMsg tc;
 } rfbClientToServerMsg;
