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-04-05 23:13:59.000000000 -0400 @@ -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:\ F8: ShowPopup()\n\ + F9: ToggleFullScreen()\n\ : SendRFBEvent()\n\ : SendRFBEvent()\n\ : 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,160 @@ ! Popup buttons ! -*popupButtonCount: 8 +*popupButtonCount: 28 *popup*button1.label: Dismiss popup -*popup*button1.translations: #override\n\ - ,: HidePopup() +*popup*button1.translations: #override\\n\ + ,: HidePopup() *popup*button2.label: Quit viewer -*popup*button2.translations: #override\n\ - ,: Quit() +*popup*button2.translations: #override\\n\ + ,: Quit() -*popup*button3.label: Full screen +*popup*button3.label: Full screen (also F9) *popup*button3.type: toggle -*popup*button3.translations: #override\n\ - : SetFullScreenState()\n\ - ,: toggle() HidePopup() ToggleFullScreen() +*popup*button3.translations: #override\\n\ + : SetFullScreenState()\\n\ + ,: toggle() ToggleFullScreen() HidePopup() *popup*button4.label: Clipboard: local -> remote -*popup*button4.translations: #override\n\ - ,: SelectionToVNC(always) HidePopup() +*popup*button4.translations: #override\\n\ + ,: SelectionToVNC(always) HidePopup() *popup*button5.label: Clipboard: local <- remote -*popup*button5.translations: #override\n\ - ,: SelectionFromVNC(always) HidePopup() +*popup*button5.translations: #override\\n\ + ,: SelectionFromVNC(always) HidePopup() *popup*button6.label: Request refresh -*popup*button6.translations: #override\n\ - ,: SendRFBEvent(fbupdate) HidePopup() +*popup*button6.translations: #override\\n\ + ,: SendRFBEvent(fbupdate) HidePopup() *popup*button7.label: Send ctrl-alt-del -*popup*button7.translations: #override\n\ - ,: 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\ + ,: 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\ - ,: SendRFBEvent(key,F8) HidePopup() +*popup*button8.translations: #override\\n\ + ,: SendRFBEvent(key,F8) HidePopup() + +*popup*button9.label: Send F9 +*popup*button9.translations: #override\\n\ + ,: SendRFBEvent(key,F9) HidePopup() + +*popup*button10.label: ViewOnly +*popup*button10.type: toggle +*popup*button10.translations: #override\\n\ + : SetViewOnlyState()\\n\ + ,: toggle() ToggleViewOnly() HidePopup() + +*popup*button11.label: Disable Bell +*popup*button11.type: toggle +*popup*button11.translations: #override\\n\ + : SetBellState()\\n\ + ,: toggle() ToggleBell() HidePopup() + +*popup*button12.label: Cursor Shape +*popup*button12.type: toggle +*popup*button12.translations: #override\\n\ + : SetCursorShapeState()\\n\ + ,: toggle() ToggleCursorShape() HidePopup() + +*popup*button13.label: X11 Cursor +*popup*button13.type: toggle +*popup*button13.translations: #override\\n\ + : SetX11CursorState()\\n\ + ,: toggle() ToggleX11Cursor() HidePopup() + +*popup*button14.label: Cursor Alphablend +*popup*button14.type: toggle +*popup*button14.translations: #override\\n\ + : SetCursorAlphaState()\\n\ + ,: toggle() ToggleCursorAlpha() HidePopup() + +*popup*button15.label: Toggle Tight/ZRLE +*popup*button15.type: toggle +*popup*button15.translations: #override\\n\ + : SetZRLEState()\\n\ + ,: toggle() ToggleTightZRLE() HidePopup() + +*popup*button16.label: Disable JPEG +*popup*button16.type: toggle +*popup*button16.translations: #override\\n\ + : SetNOJPEGState()\\n\ + ,: toggle() ToggleJPEG() HidePopup() + +*popup*button17.label: Prefer raw for localhost +*popup*button17.type: toggle +*popup*button17.translations: #override\\n\ + : SetRawLocalState()\\n\ + ,: toggle() ToggleRawLocal() HidePopup() + +*popup*button18.label: Full Color +*popup*button18.type: toggle +*popup*button18.translations: #override\\n\ + : SetFullColorState()\\n\ + ,: toggle() ToggleFullColor() HidePopup() + +*popup*button19.label: Grey Scale (16 & 8-bpp) +*popup*button19.type: toggle +*popup*button19.translations: #override\\n\ + : SetGreyScaleState()\\n\ + ,: toggle() ToggleGreyScale() HidePopup() + +*popup*button20.label: 16 bit color (BGR565) +*popup*button20.type: toggle +*popup*button20.translations: #override\\n\ + : Set16bppState()\\n\ + ,: toggle() Toggle16bpp() HidePopup() + +*popup*button21.label: 8 bit color (BGR233) +*popup*button21.type: toggle +*popup*button21.translations: #override\\n\ + : Set8bppState()\\n\ + ,: toggle() Toggle8bpp() HidePopup() + +*popup*button22.label: - 256 colors +*popup*button22.type: toggle +*popup*button22.translations: #override\\n\ + : Set256ColorsState()\\n\ + ,: toggle() Toggle256Colors() HidePopup() + +*popup*button23.label: - 64 colors +*popup*button23.type: toggle +*popup*button23.translations: #override\\n\ + : Set64ColorsState()\\n\ + ,: toggle() Toggle64Colors() HidePopup() + +*popup*button24.label: - 8 colors +*popup*button24.type: toggle +*popup*button24.translations: #override\\n\ + : Set8ColorsState()\\n\ + ,: toggle() Toggle8Colors() HidePopup() + +*popup*button25.label: Disable Remote Input +*popup*button25.type: toggle +*popup*button25.translations: #override\\n\ + : SetServerInputState()\\n\ + ,: toggle() ToggleServerInput() HidePopup() + +*popup*button26.label: Single Window +*popup*button26.type: toggle +*popup*button26.translations: #override\\n\ + : SetSingleWindowState()\\n\ + ,: toggle() ToggleSingleWindow() HidePopup() + +*popup*button27.label: Set 1/n Server Scale +*popup*button27.translations: #override\\n\ + ,: DoServerScale() HidePopup() + +*popup*button28.label: Text Chat +*popup*button28.type: toggle +*popup*button28.translations: #override\\n\ + : SetTextChatState()\\n\ + ,: 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-05-30 23:52:19.000000000 -0400 @@ -31,7 +31,7 @@ char *fallback_resources[] = { - "Vncviewer.title: TightVNC: %s", + "Vncviewer.title: SSVNC: %s - Press F8 for Menu", "Vncviewer.translations:\ : 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:\ - F8: ShowPopup()\\n\ + F8: ShowPopup()\\n\ + F9: ToggleFullScreen()\\n\ : SendRFBEvent()\\n\ : SendRFBEvent()\\n\ : SendRFBEvent()\\n\ @@ -64,17 +70,25 @@ "*passwordDialog.dialog.value.translations: #override\\n\ 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", + "*scaleN.title: 1/n scale", + "*scaleN*background: grey", + "*scaleN*font_old: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-*", + "*scaleN*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", + "*scaleN.buttonForm.Command.borderWidth: 0", + "*scaleN.buttonForm.Toggle.borderWidth: 0", + "*popup.translations: #override WM_PROTOCOLS: HidePopup()", "*popup.buttonForm.translations: #override\\n\ : SendRFBEvent() HidePopup()", - "*popupButtonCount: 8", + "*popupButtonCount: 29", "*popup*button1.label: Dismiss popup", "*popup*button1.translations: #override\\n\ @@ -84,7 +98,7 @@ "*popup*button2.translations: #override\\n\ ,: Quit()", - "*popup*button3.label: Full screen", + "*popup*button3.label: Full screen (also F9)", "*popup*button3.type: toggle", "*popup*button3.translations: #override\\n\ : SetFullScreenState()\\n\ @@ -115,9 +129,172 @@ "*popup*button8.translations: #override\\n\ ,: SendRFBEvent(key,F8) HidePopup()", + "*popup*button9.label: Send F9", + "*popup*button9.translations: #override\\n\ + ,: SendRFBEvent(key,F9) HidePopup()", + + "*popup*button10.label: ViewOnly", + "*popup*button10.type: toggle", + "*popup*button10.translations: #override\\n\ + : SetViewOnlyState()\\n\ + ,: toggle() ToggleViewOnly() HidePopup()", + + "*popup*button11.label: Disable Bell", + "*popup*button11.type: toggle", + "*popup*button11.translations: #override\\n\ + : SetBellState()\\n\ + ,: toggle() ToggleBell() HidePopup()", + + "*popup*button12.label: Cursor Shape", + "*popup*button12.type: toggle", + "*popup*button12.translations: #override\\n\ + : SetCursorShapeState()\\n\ + ,: toggle() ToggleCursorShape() HidePopup()", + + "*popup*button13.label: X11 Cursor", + "*popup*button13.type: toggle", + "*popup*button13.translations: #override\\n\ + : SetX11CursorState()\\n\ + ,: toggle() ToggleX11Cursor() HidePopup()", + + "*popup*button14.label: Cursor Alphablend", + "*popup*button14.type: toggle", + "*popup*button14.translations: #override\\n\ + : SetCursorAlphaState()\\n\ + ,: toggle() ToggleCursorAlpha() HidePopup()", + + "*popup*button15.label: Toggle Tight/ZRLE", + "*popup*button15.type: toggle", + "*popup*button15.translations: #override\\n\ + : SetZRLEState()\\n\ + ,: toggle() ToggleTightZRLE() HidePopup()", + + "*popup*button16.label: Disable JPEG", + "*popup*button16.type: toggle", + "*popup*button16.translations: #override\\n\ + : SetNOJPEGState()\\n\ + ,: toggle() ToggleJPEG() HidePopup()", + + "*popup*button17.label: Full Color", + "*popup*button17.type: toggle", + "*popup*button17.translations: #override\\n\ + : SetFullColorState()\\n\ + ,: toggle() ToggleFullColor() HidePopup()", + + "*popup*button18.label: Grey Scale (16 & 8-bpp)", + "*popup*button18.type: toggle", + "*popup*button18.translations: #override\\n\ + : SetGreyScaleState()\\n\ + ,: toggle() ToggleGreyScale() HidePopup()", + + "*popup*button19.label: 16 bit color (BGR565)", + "*popup*button19.type: toggle", + "*popup*button19.translations: #override\\n\ + : Set16bppState()\\n\ + ,: toggle() Toggle16bpp() HidePopup()", + + "*popup*button20.label: 8 bit color (BGR233)", + "*popup*button20.type: toggle", + "*popup*button20.translations: #override\\n\ + : Set8bppState()\\n\ + ,: toggle() Toggle8bpp() HidePopup()", + + "*popup*button21.label: - 256 colors", + "*popup*button21.type: toggle", + "*popup*button21.translations: #override\\n\ + : Set256ColorsState()\\n\ + ,: toggle() Toggle256Colors() HidePopup()", + + "*popup*button22.label: - 64 colors", + "*popup*button22.type: toggle", + "*popup*button22.translations: #override\\n\ + : Set64ColorsState()\\n\ + ,: toggle() Toggle64Colors() HidePopup()", + + "*popup*button23.label: - 8 colors", + "*popup*button23.type: toggle", + "*popup*button23.translations: #override\\n\ + : Set8ColorsState()\\n\ + ,: toggle() Toggle8Colors() HidePopup()", + + "*popup*button24.label: UltraVNC Extensions:", + "*popup*button24.translations: #override\\n\ + ,: HidePopup()", + + "*popup*button25.label: - Set 1/n Server Scale", + "*popup*button25.translations: #override\\n\ + ,: ShowScaleN() HidePopup()", + + "*popup*button26.label: - Text Chat", + "*popup*button26.type: toggle", + "*popup*button26.translations: #override\\n\ + : SetTextChatState()\\n\ + ,: toggle() ToggleTextChat() HidePopup()", + + "*popup*button27.label: - File Transfer", + "*popup*button27.type: toggle", + "*popup*button27.translations: #override\\n\ + : SetFileXferState()\\n\ + ,: toggle() ToggleFileXfer() HidePopup()", + + "*popup*button28.label: - Single Window", + "*popup*button28.type: toggle", + "*popup*button28.translations: #override\\n\ + : SetSingleWindowState()\\n\ + ,: toggle() ToggleSingleWindow() HidePopup()", + + "*popup*button29.label: - Disable Remote Input", + "*popup*button29.type: toggle", + "*popup*button29.translations: #override\\n\ + : SetServerInputState()\\n\ + ,: toggle() ToggleServerInput() HidePopup()", + + "*scaleN*button0.label: Dismiss", + "*scaleN*button0.translations: #override\\n\ + ,: HideScaleN()", + + "*scaleN*button1.label: 1/1", + "*scaleN*button1.translations: #override\\n\ + ,: SetScaleN(1) HideScaleN()", + + "*scaleN*button2.label: 1/2", + "*scaleN*button2.translations: #override\\n\ + ,: SetScaleN(2) HideScaleN()", + + "*scaleN*button3.label: 1/3", + "*scaleN*button3.translations: #override\\n\ + ,: SetScaleN(3) HideScaleN()", + + "*scaleN*button4.label: 1/4", + "*scaleN*button4.translations: #override\\n\ + ,: SetScaleN(4) HideScaleN()", + + "*scaleN*button5.label: 1/5", + "*scaleN*button5.translations: #override\\n\ + ,: SetScaleN(5) HideScaleN()", + + "*scaleN*button6.label: Other", + "*scaleN*button6.translations: #override\\n\ + ,: DoServerScale() HideScaleN()", + NULL }; +#if 0 + "*popup*button14.label: - ZRLE/ZWYRLE", + "*popup*button14.type: toggle", + "*popup*button14.translations: #override\\n\ + : SetZRLEState()\\n\ + ,: toggle() ToggleTightZRLE() HidePopup()", + + "*popup*button17.label: Prefer raw for localhost", + "*popup*button17.type: toggle", + "*popup*button17.translations: #override\\n\ + : SetRawLocalState()\\n\ + ,: toggle() ToggleRawLocal() HidePopup()", + +#endif + /* * vncServerHost and vncServerPort are set either from the command line or @@ -135,6 +312,7 @@ */ AppData appData; +AppData appDataNew; static XtResource appDataResourceList[] = { {"shareDesktop", "ShareDesktop", XtRBool, sizeof(Bool), @@ -155,14 +333,29 @@ {"userLogin", "UserLogin", XtRString, sizeof(String), XtOffsetOf(AppData, userLogin), XtRImmediate, (XtPointer) 0}, + {"unixPW", "UnixPW", XtRString, sizeof(String), + XtOffsetOf(AppData, unixPW), XtRImmediate, (XtPointer) 0}, + {"passwordDialog", "PasswordDialog", XtRBool, sizeof(Bool), XtOffsetOf(AppData, passwordDialog), XtRImmediate, (XtPointer) False}, {"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,9 +372,12 @@ {"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}, + {"termChat", "TermChat", XtRBool, sizeof(Bool), + XtOffsetOf(AppData, termChat), XtRImmediate, (XtPointer) False}, + {"wmDecorationWidth", "WmDecorationWidth", XtRInt, sizeof(int), XtOffsetOf(AppData, wmDecorationWidth), XtRImmediate, (XtPointer) 4}, @@ -206,8 +402,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 +419,55 @@ {"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}, + {"useBell", "UseBell", XtRBool, sizeof(Bool), + XtOffsetOf(AppData, useBell), XtRImmediate, (XtPointer) True}, + {"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}, + + {"fileActive", "FileActive", XtRBool, sizeof(Bool), + XtOffsetOf(AppData, fileActive), XtRImmediate, (XtPointer) False}, + + {"popupFix", "PopupFix", XtRBool, sizeof(Bool), + XtOffsetOf(AppData, popupFix), XtRImmediate, (XtPointer) False} }; @@ -242,8 +484,22 @@ {"-noraiseonbeep", "*raiseOnBeep", XrmoptionNoArg, "False"}, {"-passwd", "*passwordFile", XrmoptionSepArg, 0}, {"-user", "*userLogin", XrmoptionSepArg, 0}, + {"-unixpw", "*unixPW", 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 +509,19 @@ {"-nojpeg", "*enableJPEG", XrmoptionNoArg, "False"}, {"-nocursorshape", "*useRemoteCursor", XrmoptionNoArg, "False"}, {"-x11cursor", "*useX11Cursor", XrmoptionNoArg, "True"}, - {"-autopass", "*autoPass", XrmoptionNoArg, "True"} + {"-nobell", "*useBell", XrmoptionNoArg, "False"}, + {"-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"}, + {"-termchat", "*termChat", XrmoptionNoArg, "True"} }; @@ -268,6 +536,7 @@ {"SendRFBEvent", SendRFBEvent}, {"ShowPopup", ShowPopup}, {"HidePopup", HidePopup}, + {"HideScaleN", HideScaleN}, {"ToggleFullScreen", ToggleFullScreen}, {"SetFullScreenState", SetFullScreenState}, {"SelectionFromVNC", SelectionFromVNC}, @@ -277,6 +546,47 @@ {"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}, + {"ToggleBell", ToggleBell}, + {"ToggleRawLocal", ToggleRawLocal}, + {"ToggleServerInput", ToggleServerInput}, + {"ToggleSingleWindow", ToggleSingleWindow}, + {"ToggleTextChat", ToggleTextChat}, + {"ToggleFileXfer", ToggleFileXfer}, + {"DoServerScale", DoServerScale}, + {"ShowScaleN", ShowScaleN}, + {"SetScaleN", SetScaleN}, + {"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}, + {"SetBellState", SetBellState}, + {"SetRawLocalState", SetRawLocalState}, + {"SetServerInputState", SetServerInputState}, + {"SetSingleWindowState", SetSingleWindowState}, + {"SetTextChatState", SetTextChatState}, + {"SetFileXferState", SetFileXferState} }; @@ -302,8 +612,8 @@ void usage(void) { - fprintf(stderr, - "TightVNC viewer version 1.3dev7\n" + fprintf(stdout, + "TightVNC viewer version 1.3.9 (SSVNC)\n" "\n" "Usage: %s [] [][:]\n" " %s [] [][::]\n" @@ -332,10 +642,142 @@ " -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" + " -nobell Disable bell.\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" + " -termchat Do the UltraVNC chat in the terminal vncviewer is in\n" + " instead of in an independent window.\n" + "\n" + " -unixpw str Useful for logging into x11vnc in -unixpw mode. \"str\" is a\n" + " string that allows many ways to enter the Unix Username\n" + " and Unix Password. These characters: username, newline,\n" + " password, newline are sent to the VNC server after any VNC\n" + " authentication has taken place. Under x11vnc they are\n" + " used for the -unixpw login. Other VNC servers could do\n" + " something similar.\n" + "\n" + " You can also indicate \"str\" via the environment\n" + " variable SSVNC_UNIXPW.\n" + "\n" + " Note that the Escape key is actually sent first to tell\n" + " x11vnc to not echo the Unix Username back to the VNC\n" + " viewer. Set SSVNC_UNIXPW_NOESC=1 to override this.\n" + "\n" + " If str is \".\", then you are prompted at the command line\n" + " for the username and password in the normal way. If str is\n" + " \"-\" the stdin is read via getpass(3) for username@password.\n" + " Otherwise if str is a file, it is opened and the first line\n" + " read is taken as the Unix username and the 2nd as the\n" + " password. If str prefixed by \"rm:\" the file is removed\n" + " after reading. Otherwise, if str has a \"@\" character,\n" + " it is taken as username@password. Otherwise, the program\n" + " exits with an error. Got all that?\n" + "\n" + " New Popup actions:\n" + "\n" + " ViewOnly: ~ -viewonly\n" + " Disable Bell: ~ -nobell\n" + " Cursor Shape: ~ -nocursorshape\n" + " X11 Cursor: ~ -x11cursor\n" + " Cursor Alphablend: ~ -alpha\n" + " Toggle Tight/ZRLE: ~ -encodings ...\n" + " Disable JPEG: ~ -nojpeg\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" + " UltraVNC Extensions:\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.\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 /* @@ -350,6 +792,7 @@ int i; char *vncServerName, *colonPos; int len, portOffset; + int disp; /* Turn app resource specs into our appData structure for the rest of the program to use */ @@ -357,6 +800,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 +836,10 @@ return; } + if (appData.useBGR233 && appData.useBGR565) { + appData.useBGR233 = 0; + } + if (argc == 1) { vncServerName = DoServerDialog(); appData.passwordDialog = True; @@ -414,6 +878,13 @@ if (!len || strspn(colonPos + 1, "0123456789") != len) { usage(); } +#if 0 vncServerPort = atoi(colonPos + 1) + portOffset; +#else + disp = atoi(colonPos + 1); + if (portOffset != 0 && disp >= 100) + portOffset = 0; + vncServerPort = disp + portOffset; +#endif } } 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< 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< 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< $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 */ + 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-05-27 11:58:01.000000000 -0400 @@ -28,21 +28,29 @@ #include #endif +#include + GC gc; GC srcGC, dstGC; /* used for debugging copyrect */ Window desktopWin; -Cursor dotCursor; +Cursor dotCursor3 = None; +Cursor dotCursor4 = 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 +58,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,89 +147,303 @@ 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 - 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 * exist. It creates some GCs and sets the dot cursor. */ +void Xcursors(int set) { + if (dotCursor3 == None) { + dotCursor3 = CreateDotCursor(3); + } + if (dotCursor4 == None) { + dotCursor4 = CreateDotCursor(4); + } + if (set) { + XSetWindowAttributes attr; + unsigned long valuemask = 0; + + if (!appData.useX11Cursor) { + if (appData.viewOnly) { + attr.cursor = dotCursor4; + } else { + attr.cursor = dotCursor3; + } + valuemask |= CWCursor; + XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); + } + } +} + 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; + } + } - XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); + if (appData.useBackingstore) { + XtVaGetApplicationResources(desktop, (XtPointer)&attr.backing_store, + desktopBackingStoreResources, 1, NULL); + valuemask |= CWBackingStore; + } else { + attr.background_pixel = BlackPixel(dpy, DefaultScreen(dpy)); + valuemask |= CWBackPixel; + } + + Xcursors(0); + if (!appData.useX11Cursor) { + if (appData.viewOnly) { + attr.cursor = dotCursor4; + } else { + attr.cursor = dotCursor3; + } + 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 (dotCursor3 == None) { + dotCursor3 = CreateDotCursor(3); + dotCursor4 = CreateDotCursor(4); + } + if (appData.viewOnly) { + XDefineCursor(dpy, desktopWin, dotCursor4); + } else { + XDefineCursor(dpy, desktopWin, dotCursor3); + } + 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 +454,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 +517,13 @@ * button2 down, 3 for both, etc). */ +extern Bool selectingSingleWindow; + +extern Cursor dotCursor3; +extern Cursor dotCursor4; + +extern void set_server_scale(int); + void SendRFBEvent(Widget w, XEvent *ev, String *params, Cardinal *num_params) { @@ -208,12 +531,62 @@ char keyname[256]; int buttonMask, x, y; - if (appData.fullScreen && ev->type == MotionNotify) { - if (BumpScroll(ev)) - return; - } + if (appData.fullScreen && ev->type == MotionNotify) { + if (BumpScroll(ev)) { + return; + } + } + + if (selectingSingleWindow && ev->type == ButtonPress) { + selectingSingleWindow = False; + SendSingleWindow(ev->xbutton.x, ev->xbutton.y); + if (appData.viewOnly) { + XDefineCursor(dpy, desktopWin, dotCursor4); + } else { + XDefineCursor(dpy, desktopWin, dotCursor3); + } + return; + } - if (appData.viewOnly) return; + if (appData.viewOnly) { + int W = si.framebufferWidth; + int H = si.framebufferHeight; + if (*num_params != 0) { + if (strcasecmp(params[0],"fbupdate") == 0) { + SendFramebufferUpdateRequest(0, 0, W, H, False); + } + } + if (ev->type == ButtonRelease) { + XButtonEvent *b = (XButtonEvent *) ev; + if (b->state & Button3Mask) { + ShowPopup(w, ev, params, num_params); + } + } else if (ev->type == KeyRelease) { + XLookupString(&ev->xkey, keyname, 256, &ks, NULL); + if (ks == XK_1 || ks == XK_KP_1 || ks == XK_KP_End) { + set_server_scale(1); + } else if (ks == XK_2 || ks == XK_KP_2 || ks == XK_KP_Down) { + set_server_scale(2); + } else if (ks == XK_3 || ks == XK_KP_3 || ks == XK_KP_Next) { + set_server_scale(3); + } else if (ks == XK_4 || ks == XK_KP_4) { + set_server_scale(4); + } else if (ks == XK_5 || ks == XK_KP_5) { + set_server_scale(5); + } else if (ks == XK_6 || ks == XK_KP_6) { + set_server_scale(6); + } else if (ks == XK_r || ks == XK_R) { + SendFramebufferUpdateRequest(0, 0, W, H, False); + } else if (ks == XK_b || ks == XK_B) { + ToggleBell(w, ev, params, num_params); + } else if (ks == XK_f || ks == XK_F) { + Toggle8bpp(w, ev, params, num_params); + } else if (ks == XK_V) { + ToggleViewOnly(w, ev, params, num_params); + } + } + return; + } if (*num_params != 0) { if (strncasecmp(params[0],"key",3) == 0) { @@ -329,26 +702,157 @@ * CreateDotCursor. */ +#ifndef very_small_dot_cursor +static Cursor +CreateDotCursor(int which) +{ + Cursor cursor; + Pixmap src, msk; + static char srcBits3[] = { 0x00, 0x02, 0x00 }; + static char mskBits3[] = { 0x02, 0x07, 0x02 }; + static char srcBits4[] = { 0x00, 0x06, 0x06, 0x00 }; + static char mskBits4[] = { 0x06, 0x0f, 0x0f, 0x06 }; + XColor fg, bg; + + if (which == 3) { + src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits3, 3, 3); + msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits3, 3, 3); + } else { + src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits4, 4, 4); + msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits4, 4, 4); + } + 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; +} +#else 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; +} +#endif + +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; + } + + 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; + } + } - return cursor; + 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 +863,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 +902,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/misc.c vnc_unixsrc/vncviewer/misc.c --- vnc_unixsrc.orig/vncviewer/misc.c 2003-01-15 02:58:32.000000000 -0500 +++ vnc_unixsrc/vncviewer/misc.c 2007-05-26 13:29:19.000000000 -0400 @@ -287,6 +287,7 @@ if (appData.useShm) ShmCleanup(); #endif + fprintf(stderr,"\nVNC Viewer exiting.\n\n"); } static int 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-05-31 16:42:36.000000000 -0400 @@ -25,15 +25,44 @@ #include #include +#include #include Widget popup, fullScreenToggle; +static void popupFixer(Widget wid) { + 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(wid, XtGrabNone); + XtVaGetValues(wid, XtNheight, &ph, NULL); + if (y0 + (int) ph > dpyHeight) { + y0 = dpyHeight - (int) ph; + if (y0 < 0) { + y0 = 0; + } + } + XtMoveWidget(wid, x0, y0); +} + 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) { + popupFixer(popup); + } 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); } @@ -91,3 +120,292 @@ prevButton = button; } } + + +Widget scaleN; + +void +ShowScaleN(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + if (appData.popupFix) { + popupFixer(scaleN); + + } else { + XtMoveWidget(scaleN, event->xbutton.x_root, event->xbutton.y_root); + XtPopup(scaleN, XtGrabNone); + } + if (appData.grabAll) { + XRaiseWindow(dpy, XtWindow(scaleN)); + } + XSetWMProtocols(dpy, XtWindow(scaleN), &wmDeleteWindow, 1); +} + +void +HideScaleN(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XtPopdown(scaleN); +} + + +void +CreateScaleN() +{ + Widget buttonForm, button, prevButton = NULL; + int i; + char buttonName[32]; + String buttonType; + + scaleN = XtVaCreatePopupShell("scaleN", transientShellWidgetClass, toplevel, + NULL); + + buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, scaleN, + NULL); + + for (i = 0; i <= 6; i++) { + sprintf(buttonName, "button%d", i); + XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName, + "Button", resources, 1, NULL); + + button = XtVaCreateManagedWidget(buttonName, commandWidgetClass, + buttonForm, NULL); + XtVaSetValues(button, XtNfromVert, prevButton, + XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); + prevButton = button; + } +} + +int filexfer_sock = -1; +int filexfer_listen = -1; + +void HideFile(Widget w, XEvent *event, String *params, Cardinal *num_params) { + if (filexfer_sock >= 0) { + close(filexfer_sock); + filexfer_sock = -1; + } + if (filexfer_listen >= 0) { + close(filexfer_listen); + filexfer_listen = -1; + } +} + +extern int use_loopback; +time_t start_listen = 0; + +void ShowFile(Widget w, XEvent *event, String *params, Cardinal *num_params) { + int i, port0 = 7200, port, sock = -1; + char *cmd, *jar; + char fmt[] = "java -cp '%s' VncViewer HOST localhost PORT %d delayAuthPanel yes ignoreMSLogonCheck yes disableSSL yes ftpOnly yes graftFtp yes &"; + + if (getenv("SSVNC_ULTRA_FTP_JAR")) { + jar = getenv("SSVNC_ULTRA_FTP_JAR"); + cmd = (char *) malloc(strlen(fmt) + strlen(jar) + 10); + } else { + fprintf(stderr, "Cannot find UltraVNC FTP jar file.\n"); + return; + } + use_loopback = 1; + for (i = 0; i < 100; i++) { + port = port0 + i; + sock = ListenAtTcpPort(port); + if (sock >= 0) { + fprintf(stderr, "listening for filexfer on port: %d sock: %d\n", port, sock); + break; + } + } + use_loopback = 0; + if (sock >= 0) { + int st; + pid_t pid = fork(); + if (pid < 0) { + free(cmd); + return; + } else if (pid == 0) { + int i; + sprintf(cmd, fmt, jar, port); + for (i = 3; i < 100; i++) { + close(i); + } + fprintf(stderr, "\n-- Experimental UltraVNC File Transfer --\n\nRunning cmd:\n\n %s\n\n", cmd); + system(cmd); + exit(0); + } + waitpid(pid, &st, 0); + start_listen = time(NULL); + } + free(cmd); + filexfer_listen = sock; +} + +Widget chat, entry, text; + +static int chat_visible = 0; + +void +ShowChat(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + if (appData.termChat) { + return; + } + if (! chat_visible) { + XtPopup(chat, XtGrabNone); + chat_visible = 1; + XSetWMProtocols(dpy, XtWindow(chat), &wmDeleteWindow, 1); + XSync(dpy, False); + usleep(200 * 1000); + } +} + +void hidechat(void) { + if (appData.termChat) { + return; + } + if (chat_visible) { + XtPopdown(chat); + chat_visible = 0; + XSync(dpy, False); + usleep(200 * 1000); + } +} + +void HideChat(Widget w, XEvent *event, String *params, Cardinal *num_params) { + SendTextChatClose(); + hidechat(); +} + +void dismiss_proc(Widget w, XtPointer client_data, XtPointer call_data) { + SendTextChatClose(); + hidechat(); +} + +extern void printChat(char *, Bool); + +void CheckTextInput(void) { + Arg args[2]; + String str; + int len; + + if (appData.termChat) { + return; + } + + XtSetArg(args[0], XtNstring, &str); + XtGetValues(entry, args, 1); + if (str == NULL || str[0] == '\0') { + return; + } else { + len = strlen(str); + if (len <= 0) { + return; + } + if (str[len-1] == '\n') { + char *s = strdup(str); + if (s) { + SendTextChat(s); + printChat("Send: ", True); + printChat(s, True); + XtVaSetValues(entry, XtNtype, XawAsciiString, XtNstring, "", NULL); + free(s); + } + } + } +} + +void AppendChatInput0(char *in) { + Arg args[10]; + int n; + String str; + int len; + static char *s = NULL; + static int slen = -1; + XawTextPosition pos; + + fprintf(stderr, "AppendChatInput: in= '%s'\n", in); + + XtSetArg(args[0], XtNstring, &str); + XtGetValues(text, args, 1); + fprintf(stderr, "AppendChatInput: str='%s'\n", str); + + len = strlen(str) + strlen(in); + + if (slen <= len) { + slen = 2 * (len + 10); + if (s) free(s); + s = (char *) malloc(slen+1); + } + + s[0] = '\0'; + strcat(s, str); + strcat(s, in); + fprintf(stderr, "AppendChatInput s= '%s'\n", s); + pos = (XawTextPosition) (len-1); + n = 0; + XtSetArg(args[n], XtNtype, XawAsciiString); n++; + XtSetArg(args[n], XtNstring, s); n++; + XtSetArg(args[n], XtNdisplayPosition, pos); n++; + XtSetArg(args[n], XtNinsertPosition, pos); n++; + XtSetValues(text, args, n); + fprintf(stderr, "AppendChatInput done\n"); +} + +void AppendChatInput(char *in) { + int len; + XawTextPosition beg, end; + static XawTextPosition pos = 0; + XawTextBlock txt; + + if (appData.termChat) { + return; + } + + XawTextSetInsertionPoint(text, pos); + beg = XawTextGetInsertionPoint(text); + end = beg; + //fprintf(stderr, "AppendChatInput: pos=%d in= '%s'\n", beg, in); + + txt.firstPos = 0; + txt.length = strlen(in); + txt.ptr = in; + txt.format = FMT8BIT; + + XawTextReplace(text, beg, end, &txt); + XawTextSetInsertionPoint(text, beg + txt.length); + + pos = XawTextGetInsertionPoint(text); + //fprintf(stderr, "AppendChatInput done pos=%d\n", pos); +} + +static char errorbuf[1] = {0}; + +void CreateChat(void) { + + Widget myform, dismiss; + int i, n; + Dimension w = 400, h = 300; + Dimension x = 33, y = 33; + Arg args[10]; + + chat = XtVaCreatePopupShell("chat", topLevelShellWidgetClass, toplevel, XtNmappedWhenManaged, False, NULL); + + myform = XtVaCreateManagedWidget("myform", formWidgetClass, chat, NULL); + + text = XtVaCreateManagedWidget("text", asciiTextWidgetClass, myform, + XtNresize, XawtextResizeBoth, XtNresizable, True, XtNwrap, XawtextWrapWord, + XtNscrollHorizontal, XawtextScrollNever, XtNscrollVertical, XawtextScrollAlways, + XtNwidth, w, XtNheight, h, XtNdisplayCaret, False, + XtNeditType, XawtextAppend, XtNtype, XawAsciiString, + XtNuseStringInPlace, False, NULL); + + entry = XtVaCreateManagedWidget("entry", asciiTextWidgetClass, myform, + XtNresize, XawtextResizeWidth, XtNresizable, True, XtNwrap, XawtextWrapWord, + XtNscrollHorizontal, XawtextScrollNever, XtNscrollVertical, XawtextScrollNever, + XtNheight, 20, XtNwidth, 400, XtNfromVert, text, + XtNdisplayCaret, True, XtNeditType, XawtextEdit, NULL); + + dismiss = XtVaCreateManagedWidget("dismiss", commandWidgetClass, myform, XtNlabel, "Close Chat", XtNfromVert, entry, NULL); + + AppendChatInput(""); + + XtAddCallback(dismiss, XtNcallback, dismiss_proc, NULL); + + XtRealizeWidget(chat); +} 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, ") { + 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-06-02 20:37:25.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,10 @@ int compressedLen); +int sent_FBU = 0; +int skip_XtUpdate = 0; +int skip_XtUpdateAll = 0; + int rfbsock; char *desktopName; rfbPixelFormat myFormat; @@ -177,6 +200,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 +213,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,211 +238,228 @@ 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, "\nConnected 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\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\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; } /* - * Read security type from the server (protocol version 3.3) + * Read security type from the server (protocol 3.3) */ 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; } /* - * Select security type from the server's list (protocol version 3.7) + * Select security type from the server's list (protocol 3.7) */ 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 +494,9 @@ return True; } +static char *restart_session_pw = NULL; +static int restart_session_len = 0; + /* * Negotiate authentication scheme (protocol version 3.7t) @@ -459,56 +505,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\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 +570,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, "\nPerforming 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("VNC 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\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\n"); + break; + case rfbVncAuthFailed: + fprintf(stderr, "VNC authentication failed\n\n"); + return False; + case rfbVncAuthTooMany: + fprintf(stderr, "VNC authentication failed - too many tries\n\n"); + return False; + default: + fprintf(stderr, "Unknown VNC authentication result: %d\n\n", + (int)authResult); + return False; + } - return True; + return True; } /* @@ -602,68 +670,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, "\nPerforming 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("VNC 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\n"); + break; + case rfbVncAuthFailed: + fprintf(stderr, "Authentication failed\n\n"); + return False; + case rfbVncAuthTooMany: + fprintf(stderr, "Authentication failed - too many tries\n\n"); + return False; + default: + fprintf(stderr, "Unknown authentication result: %d\n\n", + (int)authResult); + return False; + } - return True; + return True; } @@ -675,19 +746,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 +772,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 +802,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 +813,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 +832,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 +859,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 +885,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 +894,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 +911,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 +937,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,10 +964,11 @@ Bool SendIncrementalFramebufferUpdateRequest() { - return SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, - si.framebufferHeight, True); + return SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, + si.framebufferHeight, True); } +time_t last_filexfer = 0; /* * SendFramebufferUpdateRequest. @@ -880,19 +977,35 @@ 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); + if (appData.fileActive) { + if (time(NULL) < last_filexfer + 2) { +// fprintf(stderr, "skip SendFramebufferUpdateRequest: %d - %d\n", last_filexfer, time(NULL)); +// return True; + x = y = 0; + w = h = 1; + } + } - if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) - return False; + 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; + } - return True; + if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) { + return False; + } + + return True; } @@ -903,19 +1016,27 @@ Bool SendPointerEvent(int x, int y, int buttonMask) { - rfbPointerEventMsg pe; + rfbPointerEventMsg pe; + + if (appData.fileActive) { + if (time(NULL) < last_filexfer + 2) { + //fprintf(stderr, "skip SendPointerEvent: %d - %d\n", last_filexfer, time(NULL)); + return True; + } + } + + pe.type = rfbPointerEvent; + pe.buttonMask = buttonMask; + if (x < 0) x = 0; + if (y < 0) y = 0; - 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); + if (!appData.useX11Cursor) { + SoftCursorMove(x, y); + } + + pe.x = Swap16IfLE(x); + pe.y = Swap16IfLE(y); + return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg); } @@ -926,12 +1047,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 +1063,661 @@ 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; + rfbSetScaleMsg ssc; + if (nfac < 0 || nfac > 100) { + return True; + } - if (!ReadFromRFBServer((char *)&msg, 1)) - return False; + ssc.type = rfbSetScale; + ssc.scale = nfac; + return WriteExact(rfbsock, (char *)&ssc, sz_rfbSetScaleMsg); +} - switch (msg.type) { +Bool +SendServerInput(Bool enabled) +{ + rfbSetServerInputMsg sim; - case rfbSetColourMapEntries: - { - int i; - CARD16 rgb[3]; - XColor xc; + sim.type = rfbSetServerInput; + sim.status = enabled; + return WriteExact(rfbsock, (char *)&sim, sz_rfbSetServerInputMsg); +} - if (!ReadFromRFBServer(((char *)&msg) + 1, - sz_rfbSetColourMapEntriesMsg - 1)) - return False; +Bool +SendSingleWindow(int x, int y) +{ + rfbSetSWMsg sw; - msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); - msg.scme.nColours = Swap16IfLE(msg.scme.nColours); + fprintf(stderr, "SendSingleWindow: %d %d\n", x, y); - 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, "SendTextChat: %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 double do_fb_update; +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); +} + +/* common dtime() activities: */ +double dtime0(double *t_old) { + *t_old = 0.0; + return dtime(t_old); +} + +double dnow(void) { + double t; + return dtime0(&t); +} + +extern int filexfer_sock; +extern int filexfer_listen; + +static char fxfer[65536]; +extern void CheckFileXfer(void); + +Bool HandleFileXfer(void) { + unsigned char hdr[12]; + unsigned int len; + + int rfbDirContentRequest = 1; + int rfbDirPacket = 2; // Full directory name or full file name. + int rfbFileTransferRequest = 3; + int rfbFileHeader = 4; + int rfbFilePacket = 5; // One slice of the file + int rfbEndOfFile = 6; + int rfbAbortFileTransfer = 7; + int rfbFileTransferOffer = 8; + int rfbFileAcceptHeader = 9; // The server accepts or rejects the file + int rfbCommand = 10; + int rfbCommandReturn = 11; + int rfbFileChecksums = 12; + + int rfbRDirContent = 1; // Request a Server Directory contents + int rfbRDrivesList = 2; // Request the server's drives list + + int rfbADirectory = 1; // Reception of a directory name + int rfbAFile = 2; // Reception of a file name + int rfbADrivesList = 3; // Reception of a list of drives + int rfbADirCreate = 4; // Response to a create dir command + int rfbADirDelete = 5; // Response to a delete dir command + int rfbAFileCreate = 6; // Response to a create file command + int rfbAFileDelete = 7; // Response to a delete file command + + int rfbCDirCreate = 1; // Request the server to create the given directory + int rfbCDirDelete = 2; // Request the server to delete the given directory + int rfbCFileCreate = 3; // Request the server to create the given file + int rfbCFileDelete = 4; // Request the server to delete the given file + + int rfbRErrorUnknownCmd = 1; // Unknown FileTransfer command. + int rfbRErrorCmd = 0xFFFFFFFF; - rect.encoding = Swap32IfLE(rect.encoding); - if (rect.encoding == rfbEncodingLastRect) - break; + int db = 0; - 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; - } + last_filexfer = time(NULL); + //fprintf(stderr, "last_filexfer-1: %d\n", last_filexfer); - if (rect.encoding == rfbEncodingPointerPos) { - if (!HandleCursorPos(rect.r.x, rect.r.y)) { - return False; + if (filexfer_sock < 0) { + return True; } - 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; + hdr[0] = rfbFileTransfer; + skip_XtUpdateAll = 1; + if (!ReadFromRFBServer(&hdr[1], 11)) { + skip_XtUpdateAll = 0; + return False; + } + write(filexfer_sock, hdr, 12); + if (db) fprintf(stderr, "Got rfbFileTransfer hdr\n"); + if (db) write(2, hdr, 12); + if (db) fprintf(stderr, "\n"); + + len = (hdr[8] << 24) | (hdr[9] << 16) | (hdr[10] << 8) | hdr[11]; + if (db) fprintf(stderr, "Got rfbFileTransfer: len %d\n", len); + if (len > 0) { + if (!ReadFromRFBServer(fxfer, len)) { + skip_XtUpdateAll = 0; + return False; + } + if (db) write(2, fxfer, len); + if (db) fprintf(stderr, "\n"); + write(filexfer_sock, fxfer, len); } + len = (hdr[4] << 24) | (hdr[5] << 16) | (hdr[6] << 8) | hdr[7]; + if (hdr[1] == rfbFileHeader && len != rfbRErrorCmd) { + if (db) fprintf(stderr, "Got rfbFileTransfer: rfbFileHeader\n"); + len = 4; + if (!ReadFromRFBServer(fxfer, len)) { + skip_XtUpdateAll = 0; + return False; + } + if (db) write(2, fxfer, len); + if (db) fprintf(stderr, "\n"); + write(filexfer_sock, fxfer, len); + } + if (db) fprintf(stderr, "Got rfbFileTransfer done.\n"); + skip_XtUpdateAll = 0; - if (rect.r.h * rect.r.w == 0) { - fprintf(stderr,"Zero size rect - ignoring\n"); - continue; - } + CheckFileXfer(); + return True; +} + +/* + * HandleRFBServerMessage. + */ - /* 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); - switch (rect.encoding) { +Bool +HandleRFBServerMessage() +{ + int db = 0; + rfbServerToClientMsg msg; - case rfbEncodingRaw: + if (!ReadFromRFBServer((char *)&msg, 1)) { + return False; + } - bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8; - linesToRead = BUFFER_SIZE / bytesPerLine; + if (msg.type == rfbFileTransfer) { + return HandleFileXfer(); + } - while (rect.r.h > 0) { - if (linesToRead > rect.r.h) - linesToRead = rect.r.h; + switch (msg.type) { - if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) - return False; + case rfbSetColourMapEntries: + { + int i; + CARD16 rgb[3]; + XColor xc; - CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, - linesToRead); + if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbSetColourMapEntriesMsg - 1)) { + return False; + } - rect.r.h -= linesToRead; - rect.r.y += linesToRead; + msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); + msg.scme.nColours = Swap16IfLE(msg.scme.nColours); + 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); } + break; + } - 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); + 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()); + + int skip_incFBU = 0; + sent_FBU = -1; + + 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< do_fb_update + 1.1) { + do_fb_update = 0.0; + SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, + si.framebufferHeight, False); + } } - 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 +1725,149 @@ 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; + + if (appData.useBell) { + 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: + if (appData.termChat) { + printChat("\n*ChatOpen*\n\nSend: ", True); + } else { + printChat("\n*ChatOpen*\n", True); + } + appData.chatActive = True; + break; + case rfbTextChatClose: + printChat("\n*ChatClose*\n", False); + appData.chatActive = False; + break; + case rfbTextChatFinished: + printChat("\n*ChatFinished*\n", False); + 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; + } + if (appData.fileActive) { + if (filexfer_sock < 0 && filexfer_listen < 0) { + appData.fileActive = False; + } else { + CheckFileXfer(); + } + } + + return True; } @@ -1296,12 +1887,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 +1907,7 @@ #include "hextile.c" #include "zlib.c" #include "tight.c" +#include "zrle.c" #undef BPP #define BPP 32 #include "rre.c" @@ -1316,6 +1915,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 +1966,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 +2071,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-12-15 21:08:14.000000000 -0500 @@ -63,15 +63,216 @@ XtRemoveInput(*id); } +extern int skip_XtUpdate; +extern int skip_XtUpdateAll; +extern int filexfer_sock, filexfer_listen; +extern time_t start_listen; +extern void CheckTextInput(void); +extern time_t last_filexfer; + +static char fxfer[65536]; +int fxfer_size = 65536; + +void CheckFileXfer() { + fd_set fds; + struct timeval tv; + int i, icnt = 0, igot = 0, bytes0 = 0, bytes = 0, grace = 0, n, list = 0; + int db = 0; + + if (!appData.fileActive || (filexfer_sock < 0 && filexfer_listen < 0)) { + return; + } + + if (filexfer_listen >= 0 && time(NULL) > start_listen + 10) { + fprintf(stderr, "filexfer closing aging listen socket.\n"); + close(filexfer_listen); + filexfer_listen = -1; + return; + } +//fprintf(stderr, "In CheckFileXfer\n"); + + if (filexfer_listen >=0) { + n = filexfer_listen; + list = 1; + } else { + n = filexfer_sock; + } + + while (1) { + icnt++; + 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)) { + if (list) { + if (filexfer_sock >= 0) { + fprintf(stderr, "filexfer close stale(?) filexfer_sock.\n"); + close(filexfer_sock); + filexfer_sock = -1; + } + filexfer_sock = AcceptTcpConnection(filexfer_listen); + if (filexfer_listen >= 0) { + fprintf(stderr, "filexfer accept OK.\n"); + close(filexfer_listen); + filexfer_listen = -1; + } else { + fprintf(stderr, "filexfer accept failed.\n"); + } + break; + } else { + ssize_t rn; + unsigned char hdr[12]; + unsigned int len; + if (db) fprintf(stderr, "try read filexfer...\n"); +#if 1 + rn = read(n, fxfer, 1*8192); + if (0 || db) fprintf(stderr, "filexfer read[%d] %d.\n", icnt, rn); + if (rn < 0) { + fprintf(stderr, "filexfer bad read: %d\n", errno); + break; + } else if (rn == 0) { + fprintf(stderr, "filexfer gone.\n"); + close(n); + filexfer_sock = -1; + last_filexfer = time(NULL); + //fprintf(stderr, "last_filexfer-2a: %d\n", last_filexfer); + return; + } else if (rn > 0) { + if (db) write(2, fxfer, rn); + if (db) fprintf(stderr, "\n"); + bytes += rn; + last_filexfer = time(NULL); + //fprintf(stderr, "last_filexfer-2b: %d\n", last_filexfer); + if (!WriteExact(rfbsock, fxfer, rn)) { + return; + } + igot = 1; + } +#else + // not working, not always 7 msg type. + rn = read(n, hdr, 12); + if (db) fprintf(stderr, "filexfer read %d.\n", rn); + if (rn == 0) { + fprintf(stderr, "filexfer gone.\n"); + close(n); + filexfer_sock = -1; + last_filexfer = time(NULL); + return; + } + if (rn == 12) { + len = (hdr[8] << 24) | (hdr[9] << 16) | (hdr[10] << 8) | hdr[11]; + if (db) fprintf(stderr, "n=%d len=%d\n", rn, len); + if (db) write(2, hdr, rn); + if (db) fprintf(stderr, "\n"); + WriteExact(rfbsock, hdr, rn); + if (len > 0) { + rn = read(len, fxfer, len); + if (!WriteExact(rfbsock, fxfer, len)) { + last_filexfer = time(NULL); + return; + } + if (db) write(2, fxfer, len); + } + if (db) fprintf(stderr, "\n"); + } else { + if (db) fprintf(stderr, "bad rn: %d\n", rn); + } + igot = 1; +#endif + } + } + } else { + if (bytes >= 8192) { + int ok = 0; + if (bytes0 == 0) { + ok = 1; + } else if (bytes >= bytes0 + 12) { + ok = 1; + } else if (grace < 20) { + ok = 1; + } + if (ok) { + grace++; + bytes0 = bytes; + //fprintf(stderr, "grace: %d\n", grace); + usleep(10 * 1000); + continue; + } + } + break; + } + } + if (igot) { + last_filexfer = time(NULL); + //fprintf(stderr, "last_filexfer-2c: %d\n", last_filexfer); + } + return; +} + static void ProcessXtEvents() { - rfbsockReady = False; - XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask, - rfbsockReadyCallback, NULL); - while (!rfbsockReady) { - XtAppProcessEvent(appContext, XtIMAll); - } + int y; + if (skip_XtUpdateAll) { + return; + } + if (appData.chatActive) { + fd_set fds; + struct timeval tv; + int i, igot = -1, n = fileno(stdin); + char strs[100][512]; + char buf[rfbTextMaxSize]; + + if (appData.termChat) { + 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) printChat("Send: "); + } else { + CheckTextInput(); + } + } + if (skip_XtUpdate) { + return; + } + +//fprintf(stderr, "XtAppAddInput: "); + rfbsockReady = False; + XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask, + rfbsockReadyCallback, NULL); + + while (!rfbsockReady) { +//fprintf(stderr, "."); + XtAppProcessEvent(appContext, XtIMAll); + } +//fprintf(stderr, " done.\n"); } Bool @@ -203,6 +404,8 @@ struct sockaddr_in addr; int one = 1; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = host; @@ -245,6 +448,8 @@ int sock, port; struct sockaddr_in addr; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; @@ -272,6 +477,8 @@ * ListenAtTcpPort starts listening at the given TCP port. */ +int use_loopback = 0; + int ListenAtTcpPort(int port) { @@ -279,10 +486,16 @@ struct sockaddr_in addr; int one = 1; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = INADDR_ANY; + if (getenv("VNCVIEWER_LISTEN_LOCALHOST") || use_loopback) { + 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/tunnel.c vnc_unixsrc/vncviewer/tunnel.c --- vnc_unixsrc.orig/vncviewer/tunnel.c 2003-07-31 04:03:49.000000000 -0400 +++ vnc_unixsrc/vncviewer/tunnel.c 2007-05-08 21:28:01.000000000 -0400 @@ -132,6 +132,7 @@ { char *colonPos; int len, portOffset; + int disp; if (tunnelArgIndex >= *pargc - 2) usage(); @@ -153,7 +154,14 @@ if (!len || strspn(colonPos, "-0123456789") != len) { usage(); } +#if 0 *remotePort = atoi(colonPos) + portOffset; +#else + disp = atoi(colonPos); + if (portOffset != 0 && disp >= 100) + portOffset = 0; + *remotePort = disp + portOffset; +#endif } sprintf(lastArgv, "localhost::%d", localPort); 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-05-25 23:22:17.000000000 -0400 @@ -0,0 +1,529 @@ +'\" 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 +.\" +.\" 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 (SSVNC) OPTIONS +.TP +Enhanced TightVNC Viewer (SSVNC) 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\-grey\fR +Use a grey scale for the 16- and 8\fB\-bpp\fR modes. +.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 for x11vnc \fB\-ncache\fR mode (\fB\-ycrop\fR), +default is very narrow: 2 pixels, it is narrow to +avoid distraction in \fB\-ycrop\fR mode. +.TP +\fB\-nobell\fR +Disable bell. +.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\fR, \fB\-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\fB\-enable\fR it put +Option "Backingstore" +in the Device section of /etc/X11/xorg.conf. +In \fB\-bs\fR mode with no X server backingstore, whenever an +area of the screen is re\fB\-exposed\fR it must go out to the +VNC server to retrieve the pixels. This is too slow. +In \fB\-nobs\fR 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\-termchat\fR +Do the UltraVNC chat in the terminal vncviewer is in +instead of in an independent window. +.TP +\fB\-unixpw str\fR +Useful for logging into x11vnc in -unixpw mode. "str" is a +string that allows many ways to enter the Unix Username +and Unix Password. These characters: username, newline, +password, newline are sent to the VNC server after any VNC +authentication has taken place. Under x11vnc they are +used for the -unixpw login. Other VNC servers could do +something similar. +You can also indicate "str" via the environment +variable SSVNC_UNIXPW. +Note that the Escape key is actually sent first to tell +x11vnc to not echo the Unix Username back to the VNC +viewer. Set SSVNC_UNIXPW_NOESC=1 to override this. +If str is ".", then you are prompted at the command line +for the username and password in the normal way. If str is +"-" the stdin is read via getpass(3) for username@password. +Otherwise if str is a file, it is opened and the first line +read is taken as the Unix username and the 2nd as the +password. If str prefixed by "rm:" the file is removed +after reading. Otherwise, if str has a "@" character, +it is taken as username@password. Otherwise, the program +exits with an error. Got all that? +.TP +\fB New Popup actions:\fR + + ViewOnly: ~ -viewonly + Disable Bell: ~ -nobell + Cursor Shape: ~ -nocursorshape + X11 Cursor: ~ -x11cursor + Cursor Alphablend: ~ -alpha + Toggle Tight/ZRLE: ~ -encodings ... + Disable JPEG: ~ -nojpeg + 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) ~ -16bpp / -bgr565 + 8 bit color (BGR233) ~ -bgr233 + 256 colors ~ -bgr233 default # of colors. + 64 colors ~ -bgr222 / -use64 + 8 colors ~ -bgr111 / -use8 + + UltraVNC Extensions: + Disable Remote Input Ultravnc ext. Try to prevent input and + viewing of monitor at physical display. + Single Window Ultravnc ext. Grab and view 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. + + 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 , +.br +Terran Melconian , +.br +Tim Waugh , +.br +Constantin Kaplinsky 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-05-31 15:18:09.000000000 -0400 @@ -22,6 +22,7 @@ */ #include "vncviewer.h" +#include char *programName; XtAppContext appContext; @@ -29,11 +30,168 @@ 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++; + } +} + +#include +#include +#include + +void unixpw(char *instr) { + char *str, *q, *infile = NULL; + FILE *in; + int i, rmfile = 0; + struct stat sb; + int N = 99; + char username[100], passwd[100]; + + for (i=0; i<100; i++) { + username[i] = '\0'; + passwd[i] = '\0'; + } + + if (instr == NULL) { + return; + } else if (!strcmp(instr, "")) { + return; + } + + str = strdup(instr); + + if (strstr(str, "rm:") == str) { + rmfile = 1; + infile = str + strlen("rm:"); + } else if (stat(str, &sb) == 0) { + infile = str; + } + if (!strcmp(str, ".")) { + char *p; + fprintf(stderr, "\nUnix Username: "); + if (fgets(username, N, stdin) == NULL) { + exit(1); + } + p = getpass("Unix Password: "); + if (! p) { + exit(1); + } + strncpy(passwd, p, N); + fprintf(stderr, "\n"); + + } else if (!strcmp(str, "-")) { + char *p, *q; + p = getpass("unixuser@unixpasswd "); + if (! p) { + exit(1); + } + q = strchr(p, '@'); + if (! q) { + exit(1); + } + *q = '\0'; + strncpy(username, q, N); + strncpy(passwd, q+1, N); + + } else if (infile) { + in = fopen(infile, "r"); + if (in == NULL) { + fprintf(stderr, "failed to open -unixpw file.\n"); + exit(1); + } + if (fgets(username, N, in) == NULL) { + exit(1); + } + if (fgets(passwd, N, in) == NULL) { + exit(1); + } + fclose(in); + fprintf(stderr, "read username@passwd from file: %s\n", infile); + if (rmfile) { + fprintf(stderr, "deleting username@passwd file: %s\n", infile); + unlink(infile); + } + } else if (strchr(str, '@')) { + char *q = strchr(str, '@'); + *q = '\0'; + strncpy(username, str, N); + strncpy(passwd, q+1, N); + } else { + exit(1); + } + + free(str); + + if (! getenv("SSVNC_UNIXPW_NOESC")) { + SendKeyEvent(XK_Escape, 1); + SendKeyEvent(XK_Escape, 0); + } + + q = username; + while (*q != '\0' && *q != '\n') { + char c = *q; + if (c >= 0x20 && c <= 0x07e) { + KeySym ks = (KeySym) c; + SendKeyEvent(ks, 1); + SendKeyEvent(ks, 0); + } + q++; + } + + SendKeyEvent(XK_Return, 1); + SendKeyEvent(XK_Return, 0); + + q = passwd; + while (*q != '\0' && *q != '\n') { + char c = *q; + if (c >= 0x20 && c <= 0x07e) { + KeySym ks = (KeySym) c; + SendKeyEvent(ks, 1); + SendKeyEvent(ks, 0); + } + q++; + } + + SendKeyEvent(XK_Return, 1); + SendKeyEvent(XK_Return, 0); +} + 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 +203,834 @@ 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; + if (save_sbw > 0) { + set_sbwidth(save_sbw); + } else { + 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); + } + if (appData.unixPW != NULL) { + unixpw(appData.unixPW); + } else if (getenv("SSVNC_UNIXPW")) { + unixpw(getenv("SSVNC_UNIXPW")); + } /* 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(); + CreateScaleN(); + CreateChat(); /* 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; +int do_fb_update = 0.0; +static void schedule_format_change(void) { + do_format_change = 1; + do_cursor_change = 0; +} +extern double dnow(void); +static void schedule_fb_update(void) { + do_fb_update = dnow(); +} +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"); + } + Xcursors(1); +} + +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 +ToggleBell(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.useBell) { + appData.useBell = False; + fprintf(stderr, "useBell: off\n"); + } else { + appData.useBell = True; + fprintf(stderr, "useBell: on\n"); + } +} + +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); + } +} + +Bool _sw1_ = False; /* XXX this is a weird bug... */ +Bool _sw2_ = False; +Bool _sw3_ = False; +Bool selectingSingleWindow = False; + +extern Cursor bogoCursor; + +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; + selectingSingleWindow = True; + fprintf(stderr, "singleWindow: on\n"); + if (bogoCursor != None) { + XDefineCursor(dpy, desktopWin, bogoCursor); + } + } +} + +void raiseme(void); +void AppendChatInput(char *); + +void printChat(char *str, Bool raise) { + if (appData.termChat) { + if (raise) { + raiseme(); + } + fprintf(stderr, str); + } else { + if (raise) { + ShowChat(); + } + AppendChatInput(str); + } +} + +void +ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.chatActive) { + printChat("\n*SentClose*\n\n", False); + SendTextChatClose(); + HideChat(); + appData.chatActive= False; + } else { + ShowChat(); + SendTextChatOpen(); + if (appData.termChat) { + printChat("\n*SentOpen*\n\nSend: ", True); + } else { + printChat("\n*SentOpen*\n", True); + } + appData.chatActive = True; + } +} + +void +ToggleFileXfer(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.fileActive) { + HideFile(w, ev, params, num_params); + appData.fileActive= False; + } else { + ShowFile(w, ev, params, num_params); + appData.fileActive = True; + } +} + +static int fooHandler(Display *dpy, XErrorEvent *error) { + return 0; +} + +void raiseme(void) { + if (appData.termChat && 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); + } + } +} + +void set_server_scale(int n) { + if (n >= 1 && n < 100) { + int w = si.framebufferWidth; + int h = si.framebufferHeight; + appData.serverScale = n; + SendServerScale(n); + SendFramebufferUpdateRequest(0, 0, w, h, False); + schedule_fb_update(); + } +} + +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); + set_server_scale(n); + } +} + +void +SetScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (*num_params != 0) { + int n = atoi(params[0]); + set_server_scale(n); + } +} + +void +GotChatText(char *str, int len) +{ + static char *b = NULL; + static int blen = -1; + int i; + if (appData.termChat) { + printChat("\nChat: ", True); + } else { + printChat("Chat: ", True); + } + + if (len < 0) len = 0; + + if (blen < len+1) { + if (b) free(b); + blen = 2 * (len + 10); + b = (char *) malloc(blen); + } + + for (i=0; i < len; i++) { + b[i] = str[i]; + } + b[len] = '\0'; + printChat(b, True); + + if (appData.termChat) { + if (strstr(str, "\n")) { + printChat("Send: ", True); + } else { + printChat("\nSend: ", True); + } + } +} + +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); + } +} - Cleanup(); +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); + } +} - return 0; +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 +SetBellState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.useBell) + XtVaSetValues(w, XtNstate, False, NULL); + else + XtVaSetValues(w, XtNstate, True, 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); +} + +void +SetFileXferState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.fileActive) + 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-05-30 23:52:07.000000000 -0400 @@ -68,51 +68,73 @@ /* 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; + Bool termChat; + + int wmDecorationWidth; + int wmDecorationHeight; + + char *userLogin; + char *unixPW; + + 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 useBell; + Bool autoPass; + + Bool serverInput; + Bool singleWindow; + int serverScale; + Bool chatActive; + Bool fileActive; } AppData; extern AppData appData; +extern AppData appDataNew; extern char *fallback_resources[]; extern char vncServerHost[]; @@ -130,10 +152,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(); @@ -157,11 +180,18 @@ extern void DesktopInitBeforeRealization(); extern void DesktopInitAfterRealization(); +extern void Xcursors(int set); 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, @@ -207,6 +237,10 @@ Cardinal *num_params); extern void CreatePopup(); +extern void HideScaleN(Widget w, XEvent *event, String *params, + Cardinal *num_params); +extern void CreateScaleN(); + /* rfbproto.c */ extern int rfbsock; @@ -229,6 +263,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 +284,9 @@ /* shm.c */ -extern XImage *CreateShmImage(); +extern XImage *CreateShmImage(int do_ycrop); extern void ShmCleanup(); +extern Bool UsingShm(); /* sockets.c */ @@ -271,3 +315,50 @@ 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 ToggleBell(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 ShowScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleFileXfer(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleTermTextChat(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 SetBellState(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); +extern void SetTermTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetFileXferState(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-05-25 23:22:17.000000000 -0400 @@ -168,6 +168,153 @@ \fB\-autopass\fR Read a plain-text password from stdin. This option affects only the standard VNC authentication. + +.SH Enhanced TightVNC Viewer (SSVNC) OPTIONS +.TP +Enhanced TightVNC Viewer (SSVNC) 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\-grey\fR +Use a grey scale for the 16- and 8\fB\-bpp\fR modes. +.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 for x11vnc \fB\-ncache\fR mode (\fB\-ycrop\fR), +default is very narrow: 2 pixels, it is narrow to +avoid distraction in \fB\-ycrop\fR mode. +.TP +\fB\-nobell\fR +Disable bell. +.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\fR, \fB\-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\fB\-enable\fR it put +Option "Backingstore" +in the Device section of /etc/X11/xorg.conf. +In \fB\-bs\fR mode with no X server backingstore, whenever an +area of the screen is re\fB\-exposed\fR it must go out to the +VNC server to retrieve the pixels. This is too slow. +In \fB\-nobs\fR 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\-termchat\fR +Do the UltraVNC chat in the terminal vncviewer is in +instead of in an independent window. +.TP +\fB\-unixpw str\fR +Useful for logging into x11vnc in -unixpw mode. "str" is a +string that allows many ways to enter the Unix Username +and Unix Password. These characters: username, newline, +password, newline are sent to the VNC server after any VNC +authentication has taken place. Under x11vnc they are +used for the -unixpw login. Other VNC servers could do +something similar. +You can also indicate "str" via the environment +variable SSVNC_UNIXPW. +Note that the Escape key is actually sent first to tell +x11vnc to not echo the Unix Username back to the VNC +viewer. Set SSVNC_UNIXPW_NOESC=1 to override this. +If str is ".", then you are prompted at the command line +for the username and password in the normal way. If str is +"-" the stdin is read via getpass(3) for username@password. +Otherwise if str is a file, it is opened and the first line +read is taken as the Unix username and the 2nd as the +password. If str prefixed by "rm:" the file is removed +after reading. Otherwise, if str has a "@" character, +it is taken as username@password. Otherwise, the program +exits with an error. Got all that? +.TP +\fB New Popup actions:\fR + + ViewOnly: ~ -viewonly + Disable Bell: ~ -nobell + Cursor Shape: ~ -nocursorshape + X11 Cursor: ~ -x11cursor + Cursor Alphablend: ~ -alpha + Toggle Tight/ZRLE: ~ -encodings ... + Disable JPEG: ~ -nojpeg + 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) ~ -16bpp / -bgr565 + 8 bit color (BGR233) ~ -bgr233 + 256 colors ~ -bgr233 default # of colors. + 64 colors ~ -bgr222 / -use64 + 8 colors ~ -bgr111 / -use8 + + UltraVNC Extensions: + Disable Remote Input Ultravnc ext. Try to prevent input and + viewing of monitor at physical display. + Single Window Ultravnc ext. Grab and view 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. + + 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; jrw)?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; ibuffer_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<buffer_length) + return -5; + + /* read palette */ + for(i=0; i>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(jbuffer_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(j0) { +# 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=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(j0) { +# 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 + +/* __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 + +#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 +#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 +#include + +#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+1))*s; + s -= 2; + ofs = (4<>1; + } + if( r & 0x02 ){ + pH += (s>>1)*width; + } + for( y=0; y 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<>1; + } + if( r & 0x02 ){ + pH += (s>>1)*width; + } + for( y=0; y=0; l-- ){ + pTop = pBuf; + pEnd = pBuf+width; + s = 1< 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<>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<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 1server messages. */ @@ -1241,4 +1329,9 @@ rfbFileDownloadCancelMsg fdc; rfbFileUploadFailedMsg fuf; rfbFileCreateDirRequestMsg fcdr; + rfbSetScaleMsg ssc; + rfbPalmVNCSetScaleFactorMsg pssf; + rfbSetServerInputMsg sim; + rfbSetSWMsg sw; + rfbTextChatMsg tc; } rfbClientToServerMsg;