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 2008-08-24 16:26:01.000000000 -0400 @@ -1,20 +1,22 @@ ! -! Application defaults file for vncviewer. +! Application defaults file for SSVNC vncviewer. +! +! N.B.: You will need to rename this file to be "Ssvnc" instead of "Vncviewer" ! ! ! The title of the main window. "%s" will be replaced by the desktop name. -! +! -Vncviewer.title: TightVNC: %s +Ssvnc.title: SSVNC: %s Press F8 for Menu ! ! Translations on the main window. ! -Vncviewer.translations:\ +Ssvnc.translations:\ : SelectionToVNC()\n\ : SelectionFromVNC() @@ -23,7 +25,7 @@ ! Uncomment to grab the keyboard in full-screen mode. ! -! Vncviewer.grabKeyboard: True +! Ssvnc.grabKeyboard: True ! @@ -43,6 +45,9 @@ *viewport.useRight: True *viewport*Scrollbar*thumb: None +*viewport.horizontal.height: 6 +*viewport.vertical.width: 6 + ! ! Default translations on desktop window. @@ -50,89 +55,591 @@ *desktop.baseTranslations:\ F8: ShowPopup()\n\ + F9: ToggleFullScreen()\n\ : SendRFBEvent()\n\ : SendRFBEvent()\n\ : SendRFBEvent()\n\ : SendRFBEvent()\n\ : SendRFBEvent() +*viewport.horizontal.translations: #override\n\ + Right: StartScroll(Forward)\n\ + Right: NotifyScroll(FullLength) EndScroll()\n\ + Left: StartScroll(Backward)\n\ + Left: NotifyScroll(FullLength) EndScroll()\n\ + Next: StartScroll(Forward)\n\ + Next: NotifyScroll(FullLength) EndScroll()\n\ + Prior: StartScroll(Backward)\n\ + Prior: NotifyScroll(FullLength) EndScroll()\n\ + z: StartScroll(Forward)\n\ + z: NotifyScroll(FullLength) EndScroll()\n\ + a: StartScroll(Backward)\n\ + a: NotifyScroll(FullLength) EndScroll()\n\ + f: StartScroll(Forward)\n\ + f: NotifyScroll(FullLength) EndScroll()\n\ + b: StartScroll(Backward)\n\ + b: NotifyScroll(FullLength) EndScroll()\n\ + Down: StartScroll(Forward)\n\ + Down: NotifyScroll(FullLength) EndScroll()\n\ + Up: StartScroll(Backward)\n\ + Up: NotifyScroll(FullLength) EndScroll() + +*viewport.vertical.translations: #override\n\ + Down: StartScroll(Forward)\n\ + Down: NotifyScroll(FullLength) EndScroll()\n\ + Up: StartScroll(Backward)\n\ + Up: NotifyScroll(FullLength) EndScroll()\n\ + Next: StartScroll(Forward)\n\ + Next: NotifyScroll(FullLength) EndScroll()\n\ + Prior: StartScroll(Backward)\n\ + Prior: NotifyScroll(FullLength) EndScroll()\n\ + z: StartScroll(Forward)\n\ + z: NotifyScroll(FullLength) EndScroll()\n\ + a: StartScroll(Backward)\n\ + a: NotifyScroll(FullLength) EndScroll()\n\ + f: StartScroll(Forward)\n\ + f: NotifyScroll(FullLength) EndScroll()\n\ + b: StartScroll(Backward)\n\ + b: NotifyScroll(FullLength) EndScroll()\n\ + Right: StartScroll(Forward)\n\ + Right: NotifyScroll(FullLength) EndScroll()\n\ + Left: StartScroll(Backward)\n\ + Left: NotifyScroll(FullLength) EndScroll() + ! ! Dialog boxes ! *serverDialog.dialog.label: VNC server: + *serverDialog.dialog.value: + *serverDialog.dialog.value.translations: #override\n\ - Return: ServerDialogDone() + Return: ServerDialogDone() + +*ycropDialog.dialog.label: Y Crop (max-height in pixels): + +*ycropDialog.dialog.value: + +*ycropDialog.dialog.value.translations: #override\n\ + Return: YCropDialogDone() + +*scbarDialog.dialog.label: Scroll Bars width: + +*scbarDialog.dialog.value: + +*scbarDialog.dialog.value.translations: #override\n\ + Return: ScbarDialogDone() + +*scaleDialog.dialog.label: Integer n for 1/n server scaling: + +*scaleDialog.dialog.value: + +*scaleDialog.dialog.value.translations: #override\n\ + Return: ScaleDialogDone() *passwordDialog.dialog.label: Password: + *passwordDialog.dialog.value: + *passwordDialog.dialog.value.AsciiSink.echo: False + *passwordDialog.dialog.value.translations: #override\n\ - Return: PasswordDialogDone() + Return: PasswordDialogDone() ! ! Popup window appearance ! -*popup.title: TightVNC popup +*popup.title: SSVNC popup + *popup*background: grey -*popup*font: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-* -*popup.buttonForm.Command.borderWidth: 0 -*popup.buttonForm.Toggle.borderWidth: 0 + +*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: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* + +*scaleN.buttonForm.Command.borderWidth: 0 + +*scaleN.buttonForm.Toggle.borderWidth: 0 + +*quality.title: quality + +*quality*background: grey + +*quality*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* + +*quality.buttonForm.Command.borderWidth: 0 + +*quality.buttonForm.Toggle.borderWidth: 0 + +*compress.title: compress + +*compress*background: grey + +*compress*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* + +*compress.buttonForm.Command.borderWidth: 0 + +*compress.buttonForm.Toggle.borderWidth: 0 + ! ! Translations on popup window - send key presses through ! *popup.translations: #override WM_PROTOCOLS: HidePopup() + *popup.buttonForm.translations: #override\n\ - : SendRFBEvent() HidePopup() + : SendRFBEvent() HidePopup() ! ! Popup buttons ! -*popupButtonCount: 8 +*popupButtonCount: 38 + +*popupButtonBreak: 19 *popup*button1.label: Dismiss popup + *popup*button1.translations: #override\n\ - ,: HidePopup() + ,: HidePopup() *popup*button2.label: Quit viewer + *popup*button2.translations: #override\n\ - ,: Quit() + ,: Quit() + +*popup*button3.label: Full screen (also F9) -*popup*button3.label: Full screen *popup*button3.type: toggle + *popup*button3.translations: #override\n\ - : SetFullScreenState()\n\ - ,: toggle() HidePopup() ToggleFullScreen() + : SetFullScreenState()\n\ + ,: toggle() ToggleFullScreen() HidePopup() *popup*button4.label: Clipboard: local -> remote + *popup*button4.translations: #override\n\ - ,: SelectionToVNC(always) HidePopup() + ,: SelectionToVNC(always) HidePopup() *popup*button5.label: Clipboard: local <- remote + *popup*button5.translations: #override\n\ - ,: SelectionFromVNC(always) HidePopup() + ,: SelectionFromVNC(always) HidePopup() *popup*button6.label: Request refresh + *popup*button6.translations: #override\n\ - ,: SendRFBEvent(fbupdate) HidePopup() + ,: 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() + ,: 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() + ,: 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: Toggle ZRLE/ZYWRLE + +*popup*button16.type: toggle + +*popup*button16.translations: #override\n\ + : SetZYWRLEState()\n\ + ,: toggle() ToggleZRLEZYWRLE() HidePopup() + +*popup*button17.label: Quality Level + +*popup*button17.translations: #override\n\ + ,: HidePopup() ShowQuality() + +*popup*button18.label: Compress Level + +*popup*button18.translations: #override\n\ + ,: HidePopup() ShowCompress() + +*popup*button19.label: Disable JPEG + +*popup*button19.type: toggle + +*popup*button19.translations: #override\n\ + : SetNOJPEGState()\n\ + ,: toggle() ToggleJPEG() HidePopup() + +*popup*button20.label: Full Color + +*popup*button20.type: toggle + +*popup*button20.translations: #override\n\ + : SetFullColorState()\n\ + ,: toggle() ToggleFullColor() HidePopup() + +*popup*button21.label: Grey Scale (16 & 8-bpp) + +*popup*button21.type: toggle + +*popup*button21.translations: #override\n\ + : SetGreyScaleState()\n\ + ,: toggle() ToggleGreyScale() HidePopup() + +*popup*button22.label: 16 bit color (BGR565) + +*popup*button22.type: toggle + +*popup*button22.translations: #override\n\ + : Set16bppState()\n\ + ,: toggle() Toggle16bpp() HidePopup() + +*popup*button23.label: 8 bit color (BGR233) + +*popup*button23.type: toggle + +*popup*button23.translations: #override\n\ + : Set8bppState()\n\ + ,: toggle() Toggle8bpp() HidePopup() + +*popup*button24.label: - 256 colors + +*popup*button24.type: toggle + +*popup*button24.translations: #override\n\ + : Set256ColorsState()\n\ + ,: toggle() Toggle256Colors() HidePopup() + +*popup*button25.label: - 64 colors + +*popup*button25.type: toggle + +*popup*button25.translations: #override\n\ + : Set64ColorsState()\n\ + ,: toggle() Toggle64Colors() HidePopup() + +*popup*button26.label: - 8 colors + +*popup*button26.type: toggle + +*popup*button26.translations: #override\n\ + : Set8ColorsState()\n\ + ,: toggle() Toggle8Colors() HidePopup() + +*popup*button27.label: Set Y Crop (y-max) + +*popup*button27.translations: #override\n\ + ,: HidePopup() SetYCrop() + +*popup*button28.label: Set Scrollbar Width + +*popup*button28.translations: #override\n\ + ,: HidePopup() SetScbar() + +*popup*button29.label: UltraVNC Extensions: + +*popup*button29.translations: #override\n\ + ,: HidePopup() + +*popup*button30.label: - Set 1/n Server Scale + +*popup*button30.translations: #override\n\ + ,: HidePopup() ShowScaleN() + +*popup*button31.label: - Text Chat + +*popup*button31.type: toggle + +*popup*button31.translations: #override\n\ + : SetTextChatState()\n\ + ,: toggle() ToggleTextChat() HidePopup() + +*popup*button32.label: - File Transfer + +*popup*button32.type: toggle + +*popup*button32.translations: #override\n\ + : SetFileXferState()\n\ + ,: toggle() ToggleFileXfer() HidePopup() + +*popup*button33.label: - Single Window + +*popup*button33.type: toggle + +*popup*button33.translations: #override\n\ + : SetSingleWindowState()\n\ + ,: toggle() ToggleSingleWindow() HidePopup() + +*popup*button34.label: - Disable Remote Input + +*popup*button34.type: toggle + +*popup*button34.translations: #override\n\ + : SetServerInputState()\n\ + ,: toggle() ToggleServerInput() HidePopup() + +*popup*button35.label: + +*popup*button36.label: + +*popup*button37.label: + +*popup*button38.label: + +*scaleN*button0.label: Dismiss + +*scaleN*button0.translations: #override\n\ + ,: HideScaleN() + +*scaleN*button1.label: 1/1 + +*scaleN*button1.translations: #override\n\ + : SetScaleNState(1)\n\ + ,: SetScaleN(1) HideScaleN() + +*scaleN*button2.label: 1/2 + +*scaleN*button2.translations: #override\n\ + : SetScaleNState(2)\n\ + ,: SetScaleN(2) HideScaleN() + +*scaleN*button3.label: 1/3 + +*scaleN*button3.translations: #override\n\ + : SetScaleNState(3)\n\ + ,: SetScaleN(3) HideScaleN() + +*scaleN*button4.label: 1/4 + +*scaleN*button4.translations: #override\n\ + : SetScaleNState(4)\n\ + ,: SetScaleN(4) HideScaleN() + +*scaleN*button5.label: 1/5 + +*scaleN*button5.translations: #override\n\ + : SetScaleNState(5)\n\ + ,: SetScaleN(5) HideScaleN() + +*scaleN*button6.label: Other + +*scaleN*button6.translations: #override\n\ + : SetScaleNState(6)\n\ + ,: HideScaleN() DoServerScale() + +*quality*buttonD.label: Dismiss + +*quality*buttonD.translations: #override\n\ + ,: HideQuality() + +*quality*button0.label: 0 + +*quality*button0.type: toggle + +*quality*button0.translations: #override\n\ + : SetQualityState(0)\n\ + ,: SetQuality(0) HideQuality() + +*quality*button1.label: 1 + +*quality*button1.type: toggle + +*quality*button1.translations: #override\n\ + : SetQualityState(1)\n\ + ,: SetQuality(1) HideQuality() + +*quality*button2.label: 2 + +*quality*button2.type: toggle + +*quality*button2.translations: #override\n\ + : SetQualityState(2)\n\ + ,: SetQuality(2) HideQuality() + +*quality*button3.label: 3 + +*quality*button3.type: toggle + +*quality*button3.translations: #override\n\ + : SetQualityState(3)\n\ + ,: SetQuality(3) HideQuality() + +*quality*button4.label: 4 + +*quality*button4.type: toggle + +*quality*button4.translations: #override\n\ + : SetQualityState(4)\n\ + ,: SetQuality(4) HideQuality() + +*quality*button5.label: 5 + +*quality*button5.type: toggle + +*quality*button5.translations: #override\n\ + : SetQualityState(5)\n\ + ,: SetQuality(5) HideQuality() + +*quality*button6.label: 6 + +*quality*button6.type: toggle + +*quality*button6.translations: #override\n\ + : SetQualityState(6)\n\ + ,: SetQuality(6) HideQuality() + +*quality*button7.label: 7 + +*quality*button7.type: toggle + +*quality*button7.translations: #override\n\ + : SetQualityState(7)\n\ + ,: SetQuality(7) HideQuality() + +*quality*button8.label: 8 + +*quality*button8.type: toggle + +*quality*button8.translations: #override\n\ + : SetQualityState(8)\n\ + ,: SetQuality(8) HideQuality() + +*quality*button9.label: 9 + +*quality*button9.type: toggle + +*quality*button9.translations: #override\n\ + : SetQualityState(9)\n\ + ,: SetQuality(9) HideQuality() + +*compress*buttonD.label: Dismiss + +*compress*buttonD.translations: #override\n\ + ,: HideCompress() + +*compress*button0.label: 0 + +*compress*button0.translations: #override\n\ + : SetCompressState(0)\n\ + ,: SetCompress(0) HideCompress() + +*compress*button1.label: 1 + +*compress*button1.translations: #override\n\ + : SetCompressState(1)\n\ + ,: SetCompress(1) HideCompress() + +*compress*button2.label: 2 + +*compress*button2.translations: #override\n\ + : SetCompressState(2)\n\ + ,: SetCompress(2) HideCompress() + +*compress*button3.label: 3 + +*compress*button3.translations: #override\n\ + : SetCompressState(3)\n\ + ,: SetCompress(3) HideCompress() + +*compress*button4.label: 4 + +*compress*button4.translations: #override\n\ + : SetCompressState(4)\n\ + ,: SetCompress(4) HideCompress() + +*compress*button5.label: 5 + +*compress*button5.translations: #override\n\ + : SetCompressState(5)\n\ + ,: SetCompress(5) HideCompress() + +*compress*button6.label: 6 + +*compress*button6.translations: #override\n\ + : SetCompressState(6)\n\ + ,: SetCompress(6) HideCompress() + +*compress*button7.label: 7 + +*compress*button7.translations: #override\n\ + : SetCompressState(7)\n\ + ,: SetCompress(7) HideCompress() + +*compress*button8.label: 8 + +*compress*button8.translations: #override\n\ + : SetCompressState(8)\n\ + ,: SetCompress(8) HideCompress() + +*compress*button9.label: 9 + +*compress*button9.translations: #override\n\ + : SetCompressState(9)\n\ + ,: SetCompress(9) HideCompress() + 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 2008-09-14 14:27:29.000000000 -0400 @@ -31,9 +31,9 @@ char *fallback_resources[] = { - "Vncviewer.title: TightVNC: %s", + "Ssvnc.title: SSVNC: %s - Press F8 for Menu", - "Vncviewer.translations:\ + "Ssvnc.translations:\ : SelectionToVNC()\\n\ : SelectionFromVNC()", @@ -45,8 +45,58 @@ "*viewport.useRight: True", "*viewport*Scrollbar*thumb: None", + "*viewport.horizontal.height: 6 ", + "*viewport.vertical.width: 6 ", + "ssvnc*viewport.horizontal.height: 6 ", + "ssvnc*viewport.vertical.width: 6 ", + + "*viewport.horizontal.translations: #override\\n\ + Right: StartScroll(Forward)\\n\ + Right: NotifyScroll(FullLength) EndScroll()\\n\ + Left: StartScroll(Backward)\\n\ + Left: NotifyScroll(FullLength) EndScroll()\\n\ + Next: StartScroll(Forward)\\n\ + Next: NotifyScroll(FullLength) EndScroll()\\n\ + Prior: StartScroll(Backward)\\n\ + Prior: NotifyScroll(FullLength) EndScroll()\\n\ + z: StartScroll(Forward)\\n\ + z: NotifyScroll(FullLength) EndScroll()\\n\ + a: StartScroll(Backward)\\n\ + a: NotifyScroll(FullLength) EndScroll()\\n\ + f: StartScroll(Forward)\\n\ + f: NotifyScroll(FullLength) EndScroll()\\n\ + b: StartScroll(Backward)\\n\ + b: NotifyScroll(FullLength) EndScroll()\\n\ + Down: StartScroll(Forward)\\n\ + Down: NotifyScroll(FullLength) EndScroll()\\n\ + Up: StartScroll(Backward)\\n\ + Up: NotifyScroll(FullLength) EndScroll()", + + "*viewport.vertical.translations: #override\\n\ + Down: StartScroll(Forward)\\n\ + Down: NotifyScroll(FullLength) EndScroll()\\n\ + Up: StartScroll(Backward)\\n\ + Up: NotifyScroll(FullLength) EndScroll()\\n\ + Next: StartScroll(Forward)\\n\ + Next: NotifyScroll(FullLength) EndScroll()\\n\ + Prior: StartScroll(Backward)\\n\ + Prior: NotifyScroll(FullLength) EndScroll()\\n\ + z: StartScroll(Forward)\\n\ + z: NotifyScroll(FullLength) EndScroll()\\n\ + a: StartScroll(Backward)\\n\ + a: NotifyScroll(FullLength) EndScroll()\\n\ + f: StartScroll(Forward)\\n\ + f: NotifyScroll(FullLength) EndScroll()\\n\ + b: StartScroll(Backward)\\n\ + b: NotifyScroll(FullLength) EndScroll()\\n\ + Right: StartScroll(Forward)\\n\ + Right: NotifyScroll(FullLength) EndScroll()\\n\ + Left: StartScroll(Backward)\\n\ + Left: NotifyScroll(FullLength) EndScroll()", + "*desktop.baseTranslations:\ - F8: ShowPopup()\\n\ + F8: ShowPopup()\\n\ + F9: ToggleFullScreen()\\n\ : SendRFBEvent()\\n\ : SendRFBEvent()\\n\ : SendRFBEvent()\\n\ @@ -58,23 +108,58 @@ "*serverDialog.dialog.value.translations: #override\\n\ Return: ServerDialogDone()", + "*ycropDialog.dialog.label: Y Crop (max-height in pixels):", + "*ycropDialog.dialog.value:", + "*ycropDialog.dialog.value.translations: #override\\n\ + Return: YCropDialogDone()", + + "*scbarDialog.dialog.label: Scroll Bars width:", + "*scbarDialog.dialog.value:", + "*scbarDialog.dialog.value.translations: #override\\n\ + Return: ScbarDialogDone()", + + "*scaleDialog.dialog.label: Integer n for 1/n server scaling:", + "*scaleDialog.dialog.value:", + "*scaleDialog.dialog.value.translations: #override\\n\ + Return: ScaleDialogDone()", + "*passwordDialog.dialog.label: Password:", "*passwordDialog.dialog.value:", "*passwordDialog.dialog.value.AsciiSink.echo: False", "*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.buttonForm.Command.borderWidth: 0", - "*popup.buttonForm.Toggle.borderWidth: 0", + "*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: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", + "*scaleN.buttonForm.Command.borderWidth: 0", + "*scaleN.buttonForm.Toggle.borderWidth: 0", + + "*quality.title: quality", + "*quality*background: grey", + "*quality*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", + "*quality.buttonForm.Command.borderWidth: 0", + "*quality.buttonForm.Toggle.borderWidth: 0", + + "*compress.title: compress", + "*compress*background: grey", + "*compress*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", + "*compress.buttonForm.Command.borderWidth: 0", + "*compress.buttonForm.Toggle.borderWidth: 0", "*popup.translations: #override WM_PROTOCOLS: HidePopup()", "*popup.buttonForm.translations: #override\\n\ : SendRFBEvent() HidePopup()", - "*popupButtonCount: 8", + "*popupButtonCount: 38", + "*popupButtonBreak: 19", "*popup*button1.label: Dismiss popup", "*popup*button1.translations: #override\\n\ @@ -84,7 +169,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\ @@ -105,16 +190,315 @@ "*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()", + 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*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: Toggle ZRLE/ZYWRLE", + "*popup*button16.type: toggle", + "*popup*button16.translations: #override\\n\ + : SetZYWRLEState()\\n\ + ,: toggle() ToggleZRLEZYWRLE() HidePopup()", + + "*popup*button17.label: Quality Level", + "*popup*button17.translations: #override\\n\ + ,: HidePopup() ShowQuality()", + + "*popup*button18.label: Compress Level", + "*popup*button18.translations: #override\\n\ + ,: HidePopup() ShowCompress()", + + "*popup*button19.label: Disable JPEG", + "*popup*button19.type: toggle", + "*popup*button19.translations: #override\\n\ + : SetNOJPEGState()\\n\ + ,: toggle() ToggleJPEG() HidePopup()", + + "*popup*button20.label: Full Color", + "*popup*button20.type: toggle", + "*popup*button20.translations: #override\\n\ + : SetFullColorState()\\n\ + ,: toggle() ToggleFullColor() HidePopup()", + + "*popup*button21.label: Grey Scale (16 & 8-bpp)", + "*popup*button21.type: toggle", + "*popup*button21.translations: #override\\n\ + : SetGreyScaleState()\\n\ + ,: toggle() ToggleGreyScale() HidePopup()", + + "*popup*button22.label: 16 bit color (BGR565)", + "*popup*button22.type: toggle", + "*popup*button22.translations: #override\\n\ + : Set16bppState()\\n\ + ,: toggle() Toggle16bpp() HidePopup()", + + "*popup*button23.label: 8 bit color (BGR233)", + "*popup*button23.type: toggle", + "*popup*button23.translations: #override\\n\ + : Set8bppState()\\n\ + ,: toggle() Toggle8bpp() HidePopup()", + + "*popup*button24.label: - 256 colors", + "*popup*button24.type: toggle", + "*popup*button24.translations: #override\\n\ + : Set256ColorsState()\\n\ + ,: toggle() Toggle256Colors() HidePopup()", + + "*popup*button25.label: - 64 colors", + "*popup*button25.type: toggle", + "*popup*button25.translations: #override\\n\ + : Set64ColorsState()\\n\ + ,: toggle() Toggle64Colors() HidePopup()", + + "*popup*button26.label: - 8 colors", + "*popup*button26.type: toggle", + "*popup*button26.translations: #override\\n\ + : Set8ColorsState()\\n\ + ,: toggle() Toggle8Colors() HidePopup()", + + "*popup*button27.label: Set Y Crop (y-max)", + "*popup*button27.translations: #override\\n\ + ,: HidePopup() SetYCrop()", + + "*popup*button28.label: Set Scrollbar Width", + "*popup*button28.translations: #override\\n\ + ,: HidePopup() SetScbar()", + + "*popup*button29.label: UltraVNC Extensions:", + "*popup*button29.translations: #override\\n\ + ,: HidePopup()", + + "*popup*button30.label: - Set 1/n Server Scale", + "*popup*button30.translations: #override\\n\ + ,: HidePopup() ShowScaleN()", + + "*popup*button31.label: - Text Chat", + "*popup*button31.type: toggle", + "*popup*button31.translations: #override\\n\ + : SetTextChatState()\\n\ + ,: toggle() ToggleTextChat() HidePopup()", + + "*popup*button32.label: - File Transfer", + "*popup*button32.type: toggle", + "*popup*button32.translations: #override\\n\ + : SetFileXferState()\\n\ + ,: toggle() ToggleFileXfer() HidePopup()", + + "*popup*button33.label: - Single Window", + "*popup*button33.type: toggle", + "*popup*button33.translations: #override\\n\ + : SetSingleWindowState()\\n\ + ,: toggle() ToggleSingleWindow() HidePopup()", + + "*popup*button34.label: - Disable Remote Input", + "*popup*button34.type: toggle", + "*popup*button34.translations: #override\\n\ + : SetServerInputState()\\n\ + ,: toggle() ToggleServerInput() HidePopup()", + + "*popup*button35.label:", + "*popup*button36.label:", + "*popup*button37.label:", + "*popup*button38.label:", + + "*scaleN*button0.label: Dismiss", + "*scaleN*button0.translations: #override\\n\ + ,: HideScaleN()", + + "*scaleN*button1.label: 1/1", + "*scaleN*button1.translations: #override\\n\ + : SetScaleNState(1)\\n\ + ,: SetScaleN(1) HideScaleN()", + + "*scaleN*button2.label: 1/2", + "*scaleN*button2.translations: #override\\n\ + : SetScaleNState(2)\\n\ + ,: SetScaleN(2) HideScaleN()", + + "*scaleN*button3.label: 1/3", + "*scaleN*button3.translations: #override\\n\ + : SetScaleNState(3)\\n\ + ,: SetScaleN(3) HideScaleN()", + + "*scaleN*button4.label: 1/4", + "*scaleN*button4.translations: #override\\n\ + : SetScaleNState(4)\\n\ + ,: SetScaleN(4) HideScaleN()", + + "*scaleN*button5.label: 1/5", + "*scaleN*button5.translations: #override\\n\ + : SetScaleNState(5)\\n\ + ,: SetScaleN(5) HideScaleN()", + + "*scaleN*button6.label: Other", + "*scaleN*button6.translations: #override\\n\ + : SetScaleNState(6)\\n\ + ,: HideScaleN() DoServerScale()", + + "*quality*buttonD.label: Dismiss", + "*quality*buttonD.translations: #override\\n\ + ,: HideQuality()", + + "*quality*button0.label: 0", + "*quality*button0.type: toggle", + "*quality*button0.translations: #override\\n\ + : SetQualityState(0)\\n\ + ,: SetQuality(0) HideQuality()", + + "*quality*button1.label: 1", + "*quality*button1.type: toggle", + "*quality*button1.translations: #override\\n\ + : SetQualityState(1)\\n\ + ,: SetQuality(1) HideQuality()", + + "*quality*button2.label: 2", + "*quality*button2.type: toggle", + "*quality*button2.translations: #override\\n\ + : SetQualityState(2)\\n\ + ,: SetQuality(2) HideQuality()", + + "*quality*button3.label: 3", + "*quality*button3.type: toggle", + "*quality*button3.translations: #override\\n\ + : SetQualityState(3)\\n\ + ,: SetQuality(3) HideQuality()", + + "*quality*button4.label: 4", + "*quality*button4.type: toggle", + "*quality*button4.translations: #override\\n\ + : SetQualityState(4)\\n\ + ,: SetQuality(4) HideQuality()", + + "*quality*button5.label: 5", + "*quality*button5.type: toggle", + "*quality*button5.translations: #override\\n\ + : SetQualityState(5)\\n\ + ,: SetQuality(5) HideQuality()", + + "*quality*button6.label: 6", + "*quality*button6.type: toggle", + "*quality*button6.translations: #override\\n\ + : SetQualityState(6)\\n\ + ,: SetQuality(6) HideQuality()", + + "*quality*button7.label: 7", + "*quality*button7.type: toggle", + "*quality*button7.translations: #override\\n\ + : SetQualityState(7)\\n\ + ,: SetQuality(7) HideQuality()", + + "*quality*button8.label: 8", + "*quality*button8.type: toggle", + "*quality*button8.translations: #override\\n\ + : SetQualityState(8)\\n\ + ,: SetQuality(8) HideQuality()", + + "*quality*button9.label: 9", + "*quality*button9.type: toggle", + "*quality*button9.translations: #override\\n\ + : SetQualityState(9)\\n\ + ,: SetQuality(9) HideQuality()", + + "*compress*buttonD.label: Dismiss", + "*compress*buttonD.translations: #override\\n\ + ,: HideCompress()", + + "*compress*button0.label: 0", + "*compress*button0.translations: #override\\n\ + : SetCompressState(0)\\n\ + ,: SetCompress(0) HideCompress()", + + "*compress*button1.label: 1", + "*compress*button1.translations: #override\\n\ + : SetCompressState(1)\\n\ + ,: SetCompress(1) HideCompress()", + + "*compress*button2.label: 2", + "*compress*button2.translations: #override\\n\ + : SetCompressState(2)\\n\ + ,: SetCompress(2) HideCompress()", + + "*compress*button3.label: 3", + "*compress*button3.translations: #override\\n\ + : SetCompressState(3)\\n\ + ,: SetCompress(3) HideCompress()", + + "*compress*button4.label: 4", + "*compress*button4.translations: #override\\n\ + : SetCompressState(4)\\n\ + ,: SetCompress(4) HideCompress()", + + "*compress*button5.label: 5", + "*compress*button5.translations: #override\\n\ + : SetCompressState(5)\\n\ + ,: SetCompress(5) HideCompress()", + + "*compress*button6.label: 6", + "*compress*button6.translations: #override\\n\ + : SetCompressState(6)\\n\ + ,: SetCompress(6) HideCompress()", + + "*compress*button7.label: 7", + "*compress*button7.translations: #override\\n\ + : SetCompressState(7)\\n\ + ,: SetCompress(7) HideCompress()", + + "*compress*button8.label: 8", + "*compress*button8.translations: #override\\n\ + : SetCompressState(8)\\n\ + ,: SetCompress(8) HideCompress()", + + "*compress*button9.label: 9", + "*compress*button9.translations: #override\\n\ + : SetCompressState(9)\\n\ + ,: SetCompress(9) HideCompress()", + NULL }; @@ -124,7 +508,7 @@ * from a dialog box. */ -char vncServerHost[256]; +char vncServerHost[1024]; int vncServerPort = 0; @@ -135,6 +519,7 @@ */ AppData appData; +AppData appDataNew; static XtResource appDataResourceList[] = { {"shareDesktop", "ShareDesktop", XtRBool, sizeof(Bool), @@ -155,14 +540,38 @@ {"userLogin", "UserLogin", XtRString, sizeof(String), XtOffsetOf(AppData, userLogin), XtRImmediate, (XtPointer) 0}, + {"unixPW", "UnixPW", XtRString, sizeof(String), + XtOffsetOf(AppData, unixPW), XtRImmediate, (XtPointer) 0}, + + {"repeaterUltra", "RepeaterUltra", XtRString, sizeof(String), + XtOffsetOf(AppData, repeaterUltra), XtRImmediate, (XtPointer) 0}, + + {"ultraDSM", "UltraDSM", XtRBool, sizeof(Bool), + XtOffsetOf(AppData, ultraDSM), XtRImmediate, (XtPointer) False}, + + {"rfbVersion", "RfbVersion", XtRString, sizeof(String), + XtOffsetOf(AppData, rfbVersion), 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 +588,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}, @@ -191,6 +603,9 @@ {"popupButtonCount", "PopupButtonCount", XtRInt, sizeof(int), XtOffsetOf(AppData, popupButtonCount), XtRImmediate, (XtPointer) 0}, + {"popupButtonBreak", "PopupButtonBreak", XtRInt, sizeof(int), + XtOffsetOf(AppData, popupButtonBreak), XtRImmediate, (XtPointer) 0}, + {"debug", "Debug", XtRBool, sizeof(Bool), XtOffsetOf(AppData, debug), XtRImmediate, (XtPointer) False}, @@ -206,8 +621,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 +638,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 +703,26 @@ {"-noraiseonbeep", "*raiseOnBeep", XrmoptionNoArg, "False"}, {"-passwd", "*passwordFile", XrmoptionSepArg, 0}, {"-user", "*userLogin", XrmoptionSepArg, 0}, + {"-unixpw", "*unixPW", XrmoptionSepArg, 0}, + {"-repeater", "*repeaterUltra", XrmoptionSepArg, 0}, + {"-ultradsm", "*ultraDSM", XrmoptionNoArg, "True"}, + {"-rfbversion", "*rfbVersion", 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}, + {"-env", "*envDummy", 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 +732,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,15 +759,77 @@ {"SendRFBEvent", SendRFBEvent}, {"ShowPopup", ShowPopup}, {"HidePopup", HidePopup}, + {"HideScaleN", HideScaleN}, + {"HideQuality", HideQuality}, + {"HideCompress", HideCompress}, {"ToggleFullScreen", ToggleFullScreen}, + {"JumpLeft", JumpLeft}, + {"JumpRight", JumpRight}, + {"JumpUp", JumpUp}, + {"JumpDown", JumpDown}, {"SetFullScreenState", SetFullScreenState}, {"SelectionFromVNC", SelectionFromVNC}, {"SelectionToVNC", SelectionToVNC}, {"ServerDialogDone", ServerDialogDone}, + {"YCropDialogDone", YCropDialogDone}, + {"ScbarDialogDone", ScbarDialogDone}, + {"ScaleDialogDone", ScaleDialogDone}, {"PasswordDialogDone", PasswordDialogDone}, {"Pause", Pause}, {"RunCommand", RunCommand}, {"Quit", Quit}, + {"Toggle8bpp", Toggle8bpp}, + {"Toggle16bpp", Toggle16bpp}, + {"ToggleFullColor", ToggleFullColor}, + {"Toggle256Colors", Toggle256Colors}, + {"Toggle64Colors", Toggle64Colors}, + {"Toggle8Colors", Toggle8Colors}, + {"ToggleGreyScale", ToggleGreyScale}, + {"ToggleTightZRLE", ToggleTightZRLE}, + {"ToggleZRLEZYWRLE", ToggleZRLEZYWRLE}, + {"ToggleViewOnly", ToggleViewOnly}, + {"ToggleJPEG", ToggleJPEG}, + {"ToggleCursorShape", ToggleCursorShape}, + {"ToggleCursorAlpha", ToggleCursorAlpha}, + {"ToggleX11Cursor", ToggleX11Cursor}, + {"ToggleBell", ToggleBell}, + {"ToggleRawLocal", ToggleRawLocal}, + {"ToggleServerInput", ToggleServerInput}, + {"ToggleSingleWindow", ToggleSingleWindow}, + {"ToggleTextChat", ToggleTextChat}, + {"ToggleFileXfer", ToggleFileXfer}, + {"DoServerScale", DoServerScale}, + {"SetYCrop", SetYCrop}, + {"SetScbar", SetScbar}, + {"ShowScaleN", ShowScaleN}, + {"ShowQuality", ShowQuality}, + {"ShowCompress", ShowCompress}, + {"SetScaleN", SetScaleN}, + {"SetQuality", SetQuality}, + {"SetCompress", SetCompress}, + {"Set8bppState", Set8bppState}, + {"Set16bppState", Set16bppState}, + {"SetFullColorState", SetFullColorState}, + {"Set256ColorsState", Set256ColorsState}, + {"Set64ColorsState", Set64ColorsState}, + {"Set8ColorsState", Set8ColorsState}, + {"SetGreyScaleState", SetGreyScaleState}, + {"SetZRLEState", SetZRLEState}, + {"SetZYWRLEState", SetZYWRLEState}, + {"SetNOJPEGState", SetNOJPEGState}, + {"SetScaleNState", SetScaleNState}, + {"SetQualityState", SetQualityState}, + {"SetCompressState", SetCompressState}, + {"SetViewOnlyState", SetViewOnlyState}, + {"SetCursorShapeState", SetCursorShapeState}, + {"SetCursorAlphaState", SetCursorAlphaState}, + {"SetX11CursorState", SetX11CursorState}, + {"SetBellState", SetBellState}, + {"SetRawLocalState", SetRawLocalState}, + {"SetServerInputState", SetServerInputState}, + {"SetSingleWindowState", SetSingleWindowState}, + {"SetTextChatState", SetTextChatState}, + {"SetFileXferState", SetFileXferState} }; @@ -302,11 +855,13 @@ void usage(void) { - fprintf(stderr, - "TightVNC viewer version 1.3dev7\n" + fprintf(stdout, + "SSVNC Viewer (based on TightVNC viewer version 1.3.9)\n" "\n" "Usage: %s [] [][:]\n" " %s [] [][::]\n" + " %s [] exec=[CMD ARGS...]\n" + " %s [] /path/to/unix/socket\n" " %s [] -listen []\n" " %s -help\n" "\n" @@ -332,10 +887,209 @@ " -autopass\n" "\n" "Option names may be abbreviated, e.g. -bgr instead of -bgr233.\n" - "See the manual page for more information." - "\n", programName, programName, programName, programName); + "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 and ZYWRLE encodings are now supported.\n" + "\n" + " Note: F9 is shortcut to Toggle FullScreen mode.\n" + "\n" + " Note: In -listen mode set the env var. SSVNC_MULTIPLE_LISTEN=1\n" + " to allow more than one incoming VNC server at a time.\n" + " This is the same as -multilisten described below. Set\n" + " SSVNC_MULTIPLE_LISTEN=MAX:n to allow no more than \"n\"\n" + " simultaneous reverse connections.\n" + "\n" + " Note: If the host:port is specified as \"exec=command args...\"\n" + " then instead of making a TCP/IP socket connection to the\n" + " remote VNC server, \"command args...\" is executed and the\n" + " viewer is attached to its stdio. This enables tunnelling\n" + " established via an external command, e.g. an stunnel(8)\n" + " that does not involve a listening socket. This mode does\n" + " not work for -listen reverse connections.\n" + "\n" + " Note: If the host:port contains a '/' it is interpreted as a\n" + " unix-domain socket (AF_LOCAL insead of AF_INET)\n" + "\n" + " -multilisten As in -listen (reverse connection listening) except\n" + " allow more than one incoming VNC server to be connected\n" + " at a time. The default for -listen of only one at a\n" + " time tries to play it safe by not allowing anyone on\n" + " the network to put (many) desktops on your screen over\n" + " a long window of time. Use -multilisten for no limit.\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" + " -repeater str This is for use with UltraVNC repeater proxy described\n" + " here: http://www.uvnc.com/addons/repeater.html. The \"str\"\n" + " is the ID string to be sent to the repeater. E.g. ID:1234\n" + " It can also be the hostname and port or display of the VNC\n" + " server, e.g. 12.34.56.78:0 or snoopy.com:1. Note that when\n" + " using -repeater, the host:dpy on the cmdline is the repeater\n" + " server, NOT the VNC server. The repeater will connect you.\n" + "\n" + " Example: vncviewer ... -repeater ID:3333 repeat.host:5900\n" + " Example: vncviewer ... -repeater vhost:0 repeat.host:5900\n" + "\n" + " Use, e.g., '-repeater SCIII=ID:3210' if the repeater is a\n" + " Single Click III (SSL) repeater (repeater_SSL.exe) and you\n" + " are passing the SSL part of the connection through stunnel,\n" + " socat, etc. This way the magic UltraVNC string 'testB'\n" + " needed to work with the repeater is sent to it.\n" + "\n" + " -rfbversion str Set the advertised RFB version. E.g.: -rfbversion 3.6\n" + " For some servers, e.g. UltraVNC this needs to be done.\n" + "\n" + " -ultradsm UltraVNC has symmetric private key encryption DSM plugins:\n" + " http://www.uvnc.com/features/encryption.html. It is assumed\n" + " you are using a unix program (e.g. our ultravnc_dsm_helper)\n" + " to encrypt and decrypt the UltraVNC DSM stream. IN ADDITION\n" + " TO THAT supply -ultradsm to tell THIS viewer to modify the\n" + " RFB data sent so as to work with the UltraVNC Server. For\n" + " some reason, each RFB msg type must be sent twice under DSM.\n" + "\n" + " -env VAR=VALUE To save writing a shell script to set environment variables,\n" + " specify as many as you need on the command line. For\n" + " example, -env SSVNC_MULTIPLE_LISTEN=MAX:5 -env EDITOR=vi\n" + "\n" + " -printres Print out the Ssvnc X resources (appdefaults) and then exit\n" + " You can save them to a file and customize them (e.g. the\n" + " keybindings and Popup menu) Then point to the file via\n" + " XENVIRONMENT or XAPPLRESDIR.\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" + " Toggle ZRLE/ZYWRLE: ~ -encodings zywrle...\n" + " Quality Level ~ -quality (both Tight and ZYWRLE)\n" + " Compress Level ~ -compresslevel\n" + " Disable JPEG: ~ -nojpeg (Tight)\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" + " Set Y Crop (y-max) ~ -ycrop\n" + " Set Scrollbar Width ~ -sbwidth\n" + "\n" + " UltraVNC Extensions:\n" + "\n" + " Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n.\n" + " Text Chat Ultravnc ext. Do Text Chat.\n" + " File Transfer Ultravnc ext. File xfer via Java helper.\n" + " Single Window Ultravnc ext. Grab and view a single window.\n" + " (select then click on the window you want).\n" + " Disable Remote Input Ultravnc ext. Try to prevent input and\n" + " viewing of monitor at physical display.\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, programName, programName); exit(1); } +#if 0 + " -nooverride Do not apply OverrideRedirect in fullscreen mode.\n" +#endif /* @@ -350,6 +1104,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 +1112,29 @@ 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; + } + } + if (getenv("VNCVIEWER_ULTRADSM")) { + appData.ultraDSM = True; + } + if (getenv("SSVNC_ULTRA_DSM") && strcmp(getenv("SSVNC_ULTRA_DSM"), "")) { + appData.ultraDSM = True; + } + + /* Add our actions to the actions table so they can be used in widget resource specs */ @@ -376,6 +1154,10 @@ return; } + if (appData.useBGR233 && appData.useBGR565) { + appData.useBGR233 = 0; + } + if (argc == 1) { vncServerName = DoServerDialog(); appData.passwordDialog = True; @@ -390,13 +1172,23 @@ usage(); } + if (strlen(vncServerName) > 255) { fprintf(stderr,"VNC server name too long\n"); exit(1); } colonPos = strchr(vncServerName, ':'); - if (colonPos == NULL) { + if (strstr(vncServerName, "exec=") == vncServerName) { + /* special exec-external-command case */ + strcpy(vncServerHost, vncServerName); + vncServerPort = SERVER_PORT_OFFSET; + if (! appData.ultraDSM) { + if (strstr(vncServerName, "ultravnc_dsm_helper")) { + appData.ultraDSM = True; + } + } + } else if (colonPos == NULL) { /* No colon -- use default port number */ strcpy(vncServerHost, vncServerName); vncServerPort = SERVER_PORT_OFFSET; @@ -414,6 +1206,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 2008-09-05 19:12:25.000000000 -0400 @@ -28,21 +28,40 @@ #include #endif +/* we don't have Xvlib working yet... not all cards supply RGB @ 32bpp */ +#define XVLIB__dont +#ifdef XVLIB +#include +XvImage *xv_image; +XvPortID xv_port = None; +int xv_width = 640; +int xv_height = 480; +#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 +69,138 @@ }, }; +#ifdef XVLIB +void setup_xv(void) { + int a, p, f; + int num_adaptors; + XvAdaptorInfo *adaptor_info; + XvImageFormatValues *formats, *format = NULL; + int nformats; + + if (xv_port != None) { + return; + } + XvQueryAdaptors (dpy, RootWindow(dpy, DefaultScreen(dpy)), &num_adaptors, &adaptor_info); + for (a = 0; a < num_adaptors; a++) { + fprintf(stderr, "Adapator \"%s\" has %d ports\n", + adaptor_info[a].name, + adaptor_info[a].num_ports); + } + for (a = 0; a < num_adaptors; a++) { + for (p = 0; a < adaptor_info[a].num_ports; p++) { + if (XvGrabPort(dpy, adaptor_info[a].base_id + p, CurrentTime) == Success) { + xv_port = adaptor_info[a].base_id + p; + break; + } + } + } + formats = XvListImageFormats (dpy, xv_port, &nformats); + for (f=0; f < nformats; f++) { +fprintf(stderr, "f=%d\n", f); +fprintf(stderr, "formats[f].type: %d\n", formats[f].type); +fprintf(stderr, "formats[f].format: %d\n", formats[f].format); +fprintf(stderr, "formats[f].bits_per_pixel: %d\n", formats[f].bits_per_pixel); +fprintf(stderr, "formats[f].num_planes: %d\n", formats[f].num_planes); +fprintf(stderr, "formats[f].scanline_order: %d\n", formats[f].scanline_order); +fprintf(stderr, "formats[f].component_order: %s\n", formats[f].component_order); + if (formats[f].type != XvRGB) continue; + if (formats[f].format != XvPacked) continue; + if (formats[f].bits_per_pixel != 32) continue; + if (formats[f].num_planes != 1) continue; + if (formats[f].scanline_order != XvTopToBottom) continue; + if (strcmp (formats[f].component_order, "BGRX") != 0) continue; + format = &formats[f]; + break; + } +// fprintf(stderr, "y_sample_bits %d u_sample_bits %d v_sample_bits %d\n", +// format->y_sample_bits, format->u_sample_bits, format->v_sample_bits); +// fprintf(stderr, "component_order: %s\n", format->component_order); + + xv_image = XvCreateImage (dpy, xv_port, format->id, NULL, si.framebufferWidth, si.framebufferHeight); +} +#endif + +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 +210,320 @@ void DesktopInitBeforeRealization() { - int i; + int i; - form = XtVaCreateManagedWidget("form", formWidgetClass, toplevel, - XtNborderWidth, 0, - XtNdefaultDistance, 0, NULL); + form = XtVaCreateManagedWidget("form", formWidgetClass, toplevel, + XtNborderWidth, 0, XtNdefaultDistance, 0, NULL); - viewport = XtVaCreateManagedWidget("viewport", viewportWidgetClass, form, - XtNborderWidth, 0, - NULL); + viewport = XtVaCreateManagedWidget("viewport", viewportWidgetClass, form, + XtNborderWidth, 0, NULL); - desktop = XtVaCreateManagedWidget("desktop", coreWidgetClass, viewport, - XtNborderWidth, 0, - 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; - XtVaSetValues(desktop, XtNwidth, si.framebufferWidth, - XtNheight, si.framebufferHeight, NULL); + for (i = 0; i < 256; i++) { + modifierPressed[i] = False; + } - XtAddEventHandler(desktop, LeaveWindowMask|ExposureMask, - True, HandleBasicDesktopEvent, NULL); + create_image(); +} - for (i = 0; i < 256; i++) - modifierPressed[i] = False; +static Widget scrollbar_y = NULL; - image = NULL; +static int xsst = 2; +#include -#ifdef MITSHM - if (appData.useShm) { - image = CreateShmImage(); - if (!image) - 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); - } - } +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; + } + } + + 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(); +} - XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); +void put_image(int src_x, int src_y, int dst_x, int dst_y, int width, + int height) { + +#ifdef XVLIB + if (xv_width > 0) { + if (xv_port == None) { + setup_xv(); + } + if (xv_port != None) { + double ratw = (double) xv_width / si.framebufferWidth; + double rath = (double) xv_height / si.framebufferHeight; + XvPutImage(dpy, xv_port, desktopWin, gc, xv_image, + src_x, src_y, width, height, + (int) ratw * dst_x, (int) rath * dst_y, + (int) ratw * width, (int) rath * height); + return; + } + } +#endif + +#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 +534,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 +597,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 +611,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 +782,161 @@ * 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 + +int skip_maybe_sync = 0; +void maybe_sync(int width, int height) { + static int singles = 0; + if (skip_maybe_sync) { + return; + } + 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 +947,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 +986,228 @@ 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; + +fprintf(stderr, "ReDoDesktop: ycrop: %d\n", appData.yCrop); + + 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/dialogs.c vnc_unixsrc/vncviewer/dialogs.c --- vnc_unixsrc.orig/vncviewer/dialogs.c 2000-10-26 15:19:19.000000000 -0400 +++ vnc_unixsrc/vncviewer/dialogs.c 2008-02-16 19:04:46.000000000 -0500 @@ -26,6 +26,208 @@ static Bool serverDialogDone = False; static Bool passwordDialogDone = False; +static Bool ycropDialogDone = False; +static Bool scbarDialogDone = False; +static Bool scaleDialogDone = False; +static Bool qualityDialogDone = False; +static Bool compressDialogDone = False; + +extern void popupFixer(Widget wid); + +void +YCropDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + ycropDialogDone = True; +} + +char * +DoYCropDialog() +{ + Widget pshell, dialog; + char *ycropValue; + char *valueString; + + pshell = XtVaCreatePopupShell("ycropDialog", transientShellWidgetClass, + toplevel, NULL); + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); + + XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, + HeightOfScreen(XtScreen(pshell))*2/5); + XtPopup(pshell, XtGrabNonexclusive); + XtRealizeWidget(pshell); + + if (appData.popupFix) { + popupFixer(pshell); + } + + ycropDialogDone = False; + + while (!ycropDialogDone) { + XtAppProcessEvent(appContext, XtIMAll); + } + + valueString = XawDialogGetValueString(dialog); + ycropValue = XtNewString(valueString); + + XtPopdown(pshell); + return ycropValue; +} + +void +ScbarDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + scbarDialogDone = True; +} + +char * +DoScbarDialog() +{ + Widget pshell, dialog; + char *scbarValue; + char *valueString; + + pshell = XtVaCreatePopupShell("scbarDialog", transientShellWidgetClass, + toplevel, NULL); + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); + + XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, + HeightOfScreen(XtScreen(pshell))*2/5); + XtPopup(pshell, XtGrabNonexclusive); + XtRealizeWidget(pshell); + + if (appData.popupFix) { + popupFixer(pshell); + } + + scbarDialogDone = False; + + while (!scbarDialogDone) { + XtAppProcessEvent(appContext, XtIMAll); + } + + valueString = XawDialogGetValueString(dialog); + scbarValue = XtNewString(valueString); + + XtPopdown(pshell); + return scbarValue; +} + +void +ScaleDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + scaleDialogDone = True; +} + +char * +DoScaleDialog() +{ + Widget pshell, dialog; + char *scaleValue; + char *valueString; + + pshell = XtVaCreatePopupShell("scaleDialog", transientShellWidgetClass, + toplevel, NULL); + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); + + XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, + HeightOfScreen(XtScreen(pshell))*2/5); + XtPopup(pshell, XtGrabNonexclusive); + XtRealizeWidget(pshell); + + if (appData.popupFix) { + popupFixer(pshell); + } + + scaleDialogDone = False; + + while (!scaleDialogDone) { + XtAppProcessEvent(appContext, XtIMAll); + } + + valueString = XawDialogGetValueString(dialog); + scaleValue = XtNewString(valueString); + + XtPopdown(pshell); + return scaleValue; +} + +void +QualityDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + qualityDialogDone = True; +} + +char * +DoQualityDialog() +{ + Widget pshell, dialog; + char *qualityValue; + char *valueString; + + pshell = XtVaCreatePopupShell("qualityDialog", transientShellWidgetClass, + toplevel, NULL); + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); + + XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, + HeightOfScreen(XtScreen(pshell))*2/5); + XtPopup(pshell, XtGrabNonexclusive); + XtRealizeWidget(pshell); + + if (appData.popupFix) { + popupFixer(pshell); + } + + qualityDialogDone = False; + + while (!qualityDialogDone) { + XtAppProcessEvent(appContext, XtIMAll); + } + + valueString = XawDialogGetValueString(dialog); + qualityValue = XtNewString(valueString); + + XtPopdown(pshell); + return qualityValue; +} + +void +CompressDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + compressDialogDone = True; +} + +char * +DoCompressDialog() +{ + Widget pshell, dialog; + char *compressValue; + char *valueString; + + pshell = XtVaCreatePopupShell("compressDialog", transientShellWidgetClass, + toplevel, NULL); + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); + + XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, + HeightOfScreen(XtScreen(pshell))*2/5); + XtPopup(pshell, XtGrabNonexclusive); + XtRealizeWidget(pshell); + + if (appData.popupFix) { + popupFixer(pshell); + } + + compressDialogDone = False; + + while (!compressDialogDone) { + XtAppProcessEvent(appContext, XtIMAll); + } + + valueString = XawDialogGetValueString(dialog); + compressValue = XtNewString(valueString); + + XtPopdown(pshell); + return compressValue; +} void ServerDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) @@ -49,6 +251,10 @@ XtPopup(pshell, XtGrabNonexclusive); XtRealizeWidget(pshell); + if (appData.popupFix) { + popupFixer(pshell); + } + serverDialogDone = False; while (!serverDialogDone) { @@ -85,6 +291,10 @@ XtPopup(pshell, XtGrabNonexclusive); XtRealizeWidget(pshell); + if (appData.popupFix) { + popupFixer(pshell); + } + passwordDialogDone = False; while (!passwordDialogDone) { 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 2008-02-22 09:03:22.000000000 -0500 @@ -27,7 +27,9 @@ #include static Bool DoBumpScroll(); +static Bool DoJumpScroll(); static void BumpScrollTimerCallback(XtPointer clientData, XtIntervalId *id); +static void JumpScrollTimerCallback(XtPointer clientData, XtIntervalId *id); static XtIntervalId timer; static Bool timerSet = False; static Bool scrollLeft, scrollRight, scrollUp, scrollDown; @@ -85,10 +87,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 +111,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 +142,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 +157,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 +184,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 +272,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 +306,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 +416,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; @@ -375,3 +448,115 @@ { DoBumpScroll(); } + +/* not working: */ + +Bool +JumpScroll(int up, int vert) { + scrollLeft = scrollRight = scrollUp = scrollDown = False; + + + if (appData.fullScreen) { + return True; + } + fprintf(stderr, "JumpScroll(%d, %d)\n", up, vert); + + if (vert) { + if (up) { + scrollUp = True; + } else { + scrollDown = True; + } + } else { + if (up) { + scrollRight = True; + } else { + scrollLeft = True; + } + } + + if (scrollLeft || scrollRight || scrollUp || scrollDown) { + if (timerSet) { + return True; + } + + XtVaGetValues(desktop, XtNx, &desktopX, XtNy, &desktopY, NULL); + desktopX = -desktopX; + desktopY = -desktopY; + return DoJumpScroll(); + } + + if (timerSet) { + XtRemoveTimeOut(timer); + timerSet = False; + } + + return False; +} + +static Bool +DoJumpScroll() { + int oldx = desktopX, oldy = desktopY; + int jumpH = si.framebufferWidth / 4; + int jumpV = si.framebufferHeight / 4; + + if (scrollRight) { + if (desktopX < si.framebufferWidth - dpyWidth) { + desktopX += jumpH; + if (desktopX > si.framebufferWidth - dpyWidth) + desktopX = si.framebufferWidth - dpyWidth; + } + } else if (scrollLeft) { + if (desktopX > 0) { + desktopX -= jumpH; + if (desktopX < 0) + desktopX = 0; + } + } + + if (scrollDown) { + if (appData.yCrop > 0 && desktopY + dpyHeight >= appData.yCrop) { + ; + } else if (desktopY < si.framebufferHeight - dpyHeight) { + desktopY += jumpV; + if (desktopY > si.framebufferHeight - dpyHeight) + desktopY = si.framebufferHeight - dpyHeight; + } + } else if (scrollUp) { + if (desktopY > 0) { + desktopY -= jumpV; + if (desktopY < 0) + desktopY = 0; + } + } + + if (oldx != desktopX || oldy != desktopY) { + XawViewportSetCoordinates(viewport, desktopX, desktopY); + timer = XtAppAddTimeOut(appContext, appData.bumpScrollTime, + JumpScrollTimerCallback, NULL); + timerSet = True; + return True; + } + + timerSet = False; + return False; +} + +static void +JumpScrollTimerCallback(XtPointer clientData, XtIntervalId *id) { + DoJumpScroll(); +} +void JumpRight(Widget w, XEvent *ev, String *params, Cardinal *num_params) { + JumpScroll(1, 0); +} +void JumpLeft(Widget w, XEvent *ev, String *params, Cardinal *num_params) { + JumpScroll(0, 0); +} +void JumpUp(Widget w, XEvent *ev, String *params, Cardinal *num_params) { + JumpScroll(1, 1); +} +void JumpDown(Widget w, XEvent *ev, String *params, Cardinal *num_params) { + JumpScroll(0, 1); +} + + diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/h2html.pl vnc_unixsrc/vncviewer/h2html.pl --- vnc_unixsrc.orig/vncviewer/h2html.pl 1969-12-31 19:00:00.000000000 -0500 +++ vnc_unixsrc/vncviewer/h2html.pl 2008-08-30 20:34:45.000000000 -0400 @@ -0,0 +1,10 @@ +#!/usr/bin/perl + +open(HELP, "./vncviewer -help|"); + +while () { + $_ =~ s/&/&/g; + $_ =~ s//>/g; + print; +} 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 2008-09-07 11:23:30.000000000 -0400 @@ -58,6 +58,8 @@ int n; int i; char *displayname = NULL; + int children = 0; + int totalconn = 0, maxconn = 0; listenSpecified = True; @@ -111,20 +113,36 @@ 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); + /* this will only work if X events drives this loop -- they don't */ + if (getenv("SSVNC_MAX_LISTEN")) { + maxconn = atoi(getenv("SSVNC_MAX_LISTEN")); + } + while (True) { /* reap any zombies */ int status, pid; - while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0); + while ((pid = wait3(&status, WNOHANG, (struct rusage *)0))>0) { + if (pid > 0 && children > 0) { + children--; + /* this will only work if X events drives this loop -- they don't */ + if (maxconn > 0 && totalconn >= maxconn) { + fprintf(stderr,"%s -listen: Finished final connection %d\n", + programName, maxconn); + exit(0); + } + } + } /* discard any X events */ while (XCheckIfEvent(d, &ev, AllXEventsPredicate, NULL)) @@ -132,12 +150,24 @@ 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); + while ((pid = wait3(&status, WNOHANG, (struct rusage *)0))>0) { + if (pid > 0 && children > 0) { + children--; + if (maxconn > 0 && totalconn >= maxconn) { + fprintf(stderr,"%s -listen: Finished final connection %d\n", + programName, maxconn); + exit(0); + } + } + } + +#if 0 if (FD_ISSET(flashSocket, &fds)) { sock = AcceptTcpConnection(flashSocket); @@ -151,11 +181,48 @@ } close(sock); } +#endif if (FD_ISSET(listenSocket, &fds)) { - rfbsock = AcceptTcpConnection(listenSocket); - if (rfbsock < 0) exit(1); - if (!SetNonBlocking(rfbsock)) exit(1); + int multi_ok = 0; + char *sml = getenv("SSVNC_MULTIPLE_LISTEN"); + + rfbsock = AcceptTcpConnection(listenSocket); + + if (sml != NULL) { + if (strstr(sml, "MAX:") == sml || strstr(sml, "max:") == sml) { + char *q = strchr(sml, ':'); + int maxc = atoi(q+1); + if (maxc == 0 && strcmp(q+1, "0")) { + maxc = -99; + } + if (maxc < 0) { + fprintf(stderr, "invalid SSVNC_MULTIPLE_LISTEN=MAX:n, %s, must be 0 or positive, using 1\n", sml); + } else if (maxc == 0) { + multi_ok = 1; + } else if (children < maxc) { + multi_ok = 1; + } + } else if (strcmp(sml, "") && strcmp(sml, "0")) { + multi_ok = 1; + } + } + + if (rfbsock < 0) exit(1); + if (!SetNonBlocking(rfbsock)) exit(1); + + if (children > 0 && !multi_ok) { + fprintf(stderr,"\n"); + fprintf(stderr,"%s: denying extra incoming connection (%d already)\n", + programName, children); + fprintf(stderr,"%s: to override: use '-multilisten' or set SSVNC_MULTIPLE_LISTEN=1\n", + programName); + fprintf(stderr,"\n"); + close(rfbsock); + rfbsock = -1; + continue; + } + totalconn++; XCloseDisplay(d); @@ -175,6 +242,7 @@ default: /* parent - go round and listen again */ + children++; close(rfbsock); if (!(d = XOpenDisplay(displayname))) { fprintf(stderr,"%s: unable to open display %s\n", @@ -182,6 +250,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 2008-09-14 10:34:39.000000000 -0400 @@ -25,15 +25,44 @@ #include #include +#include #include Widget popup, fullScreenToggle; +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); } @@ -52,42 +81,464 @@ }; void -CreatePopup() +CreatePopup() { + Widget buttonForm1, buttonForm2, twoForm, button, prevButton = NULL; + int i; + char buttonName[12]; + String buttonType; + + popup = XtVaCreatePopupShell("popup", transientShellWidgetClass, toplevel, NULL); + + twoForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, popup, NULL); + buttonForm1 = XtVaCreateManagedWidget("buttonForm", formWidgetClass, twoForm, NULL); + buttonForm2 = XtVaCreateManagedWidget("buttonForm", formWidgetClass, twoForm, XtNfromHoriz, (XtArgVal) buttonForm1, NULL); + + if (appData.popupButtonCount > 100) { + fprintf(stderr,"Too many popup buttons\n"); + exit(1); + } + + for (i = 1; i <= appData.popupButtonCount; i++) { + Widget bform; + sprintf(buttonName, "button%d", i); + + if (i <= appData.popupButtonBreak) { + bform = buttonForm1; + } else { + if (i == appData.popupButtonBreak+1) { + prevButton = NULL; + } + bform = buttonForm2; + } + XtVaGetSubresources(bform, (XtPointer)&buttonType, buttonName, "Button", resources, 1, NULL); + + if (strcmp(buttonType, "command") == 0) { + button = XtVaCreateManagedWidget(buttonName, commandWidgetClass, bform, NULL); + XtVaSetValues(button, XtNfromVert, prevButton, XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); + } else if (strcmp(buttonType, "toggle") == 0) { + button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, bform, NULL); + XtVaSetValues(button, XtNfromVert, prevButton, XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); + } else { + fprintf(stderr,"unknown button type '%s'\n", buttonType); + } + 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[12]; + char buttonName[32]; String buttonType; - popup = XtVaCreatePopupShell("popup", transientShellWidgetClass, toplevel, + scaleN = XtVaCreatePopupShell("scaleN", transientShellWidgetClass, toplevel, NULL); - buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, popup, + buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, scaleN, NULL); - if (appData.popupButtonCount > 100) { - fprintf(stderr,"Too many popup buttons\n"); - exit(1); - } - - for (i = 1; i <= appData.popupButtonCount; i++) { + for (i = 0; i <= 6; i++) { sprintf(buttonName, "button%d", i); XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName, "Button", resources, 1, NULL); - if (strcmp(buttonType, "command") == 0) { - button = XtVaCreateManagedWidget(buttonName, commandWidgetClass, + button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, buttonForm, NULL); - XtVaSetValues(button, XtNfromVert, prevButton, + XtVaSetValues(button, XtNfromVert, prevButton, XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); - } else if (strcmp(buttonType, "toggle") == 0) { - button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, + prevButton = button; + } +} + +Widget qualityW; + +void +ShowQuality(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + if (appData.popupFix) { + popupFixer(qualityW); + + } else { + XtMoveWidget(qualityW, event->xbutton.x_root, event->xbutton.y_root); + XtPopup(qualityW, XtGrabNone); + } + if (appData.grabAll) { + XRaiseWindow(dpy, XtWindow(qualityW)); + } + XSetWMProtocols(dpy, XtWindow(qualityW), &wmDeleteWindow, 1); +} + +void +HideQuality(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XtPopdown(qualityW); +} + + +void +CreateQuality() +{ + Widget buttonForm, button, prevButton = NULL; + int i; + char buttonName[32]; + String buttonType; + + qualityW = XtVaCreatePopupShell("quality", transientShellWidgetClass, toplevel, + NULL); + + buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, qualityW, + NULL); + + for (i = -1; i <= 9; i++) { + if (i < 0) { + sprintf(buttonName, "buttonD"); + } else { + sprintf(buttonName, "button%d", i); + } + XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName, + "Button", resources, 1, NULL); + + button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, buttonForm, NULL); - XtVaSetValues(button, XtNfromVert, prevButton, + XtVaSetValues(button, XtNfromVert, prevButton, XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); + prevButton = button; + } +} + +Widget compressW; + +void +ShowCompress(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + if (appData.popupFix) { + popupFixer(compressW); + + } else { + XtMoveWidget(compressW, event->xbutton.x_root, event->xbutton.y_root); + XtPopup(compressW, XtGrabNone); + } + if (appData.grabAll) { + XRaiseWindow(dpy, XtWindow(compressW)); + } + XSetWMProtocols(dpy, XtWindow(compressW), &wmDeleteWindow, 1); +} + +void +HideCompress(Widget w, XEvent *event, String *params, Cardinal *num_params) +{ + XtPopdown(compressW); +} + + +void +CreateCompress() +{ + Widget buttonForm, button, prevButton = NULL; + int i; + char buttonName[32]; + String buttonType; + + compressW = XtVaCreatePopupShell("compress", transientShellWidgetClass, toplevel, + NULL); + + buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, compressW, + NULL); + + for (i = -1; i <= 9; i++) { + if (i < 0) { + sprintf(buttonName, "buttonD"); } else { - fprintf(stderr,"unknown button type '%s'\n",buttonType); + sprintf(buttonName, "button%d", i); } + XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName, + "Button", resources, 1, NULL); + + button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, + 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; +pid_t java_helper = 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 dsmActive no &"; + + if (getenv("SSVNC_ULTRA_FTP_JAR")) { + jar = getenv("SSVNC_ULTRA_FTP_JAR"); + cmd = (char *) malloc(strlen(fmt) + strlen(jar) + 100); + } 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); + if (appData.ultraDSM) { + char *q = strstr(cmd, "dsmActive"); + if (q) { + q = strstr(q, "no "); + if (q) { + q[0] = 'y'; + q[1] = 'e'; + q[2] = 's'; + } + } + } + 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); + } + fprintf(stderr, "java helper pid is: %d\n", (int) pid); + waitpid(pid, &st, 0); + java_helper = pid; + 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, XtNeditType, XawtextEdit, + 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 2008-02-17 13:32:34.000000000 -0500 @@ -0,0 +1,20 @@ +#!/usr/bin/perl + +$ok = 0; + +open(A, ") { + if (/popupButtonCount:/) { + $on = 1; + } elsif (/^\s*NULL/) { + $on = 0; + } + next unless $on; + chomp; + last if /NULL/; + $_ =~ 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 2008-09-05 19:51:24.000000000 -0400 +++ vnc_unixsrc/vncviewer/rfbproto.c 2008-09-13 18:00:27.000000000 -0400 @@ -23,6 +23,7 @@ * rfbproto.c - functions to deal with client side of RFB protocol. */ +#include #include #include #include @@ -57,6 +58,44 @@ 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 HandleZRLE15(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; + +#define sz_rfbZRLEHeader 4 + +#define rfbZRLETileWidth 64 +#define rfbZRLETileHeight 64 + +#define DO_ZYWRLE 1 + +#if DO_ZYWRLE + +#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]; + +#include "zrlepalettehelper.h" +static zrlePaletteHelper paletteHelper; + +#endif /* ZRLE_ONCE */ +#endif /* DO_ZYWRLE */ + static void ReadConnFailedReason(void); static long ReadCompactLen (void); @@ -67,6 +106,11 @@ static void JpegSetSrcManager(j_decompress_ptr cinfo, CARD8 *compressedData, int compressedLen); +extern int currentMsg; + +int sent_FBU = 0; +int skip_XtUpdate = 0; +int skip_XtUpdateAll = 0; int rfbsock; char *desktopName; @@ -177,6 +221,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 +234,104 @@ Bool ConnectToRFBServer(const char *hostname, int port) { - unsigned int host; - - if (!StringToIPAddr(hostname, &host)) { - fprintf(stderr,"Couldn't convert '%s' to host address\n", hostname); - return False; - } - - rfbsock = ConnectToTcpAddr(host, port); + unsigned int host; + char *q, *cmd = NULL; + Bool setnb; + struct stat sb; + + if (strstr(hostname, "exec=") == hostname) { + cmd = strdup(hostname); + q = strchr(cmd, '='); + *q = ' '; + if (getenv("SSVNC_BASEDIR")) { + char *base = getenv("SSVNC_BASEDIR"); + char *newcmd = (char *)malloc(strlen(base) + strlen(cmd) + 1000); + sprintf(newcmd, "%s/unwrap.so", base); + if (stat(newcmd, &sb) == 0) { +#if (defined(__MACH__) && defined(__APPLE__)) + sprintf(newcmd, "DYLD_FORCE_FLAT_NAMESPACE=1; export DYLD_FORCE_FLAT_NAMESPACE; DYLD_INSERT_LIBRARIES='%s/unwrap.so'; export DYLD_INSERT_LIBRARIES; %s", base, cmd); +#else + sprintf(newcmd, "LD_PRELOAD='%s/unwrap.so'; export LD_PRELOAD; %s", base, cmd); +#endif + cmd = newcmd; + } + } + } - if (rfbsock < 0) { - fprintf(stderr,"Unable to connect to VNC server\n"); - return False; - } + if (cmd != NULL) { + int sfd[2]; + pid_t pid; + + fprintf(stderr, "exec-cmd: %s\n", cmd); + + if (! SocketPair(sfd)) { + return False; + } + if (0) { + fprintf(stderr, "sfd: %d %d\n", sfd[0], sfd[1]); + fflush(stderr); + } + + pid = fork(); + if (pid == -1) { + perror("fork"); + return False; + } + if (pid == 0) { + char *args[4]; + int d; + args[0] = "/bin/sh"; + args[1] = "-c"; + args[2] = cmd; + args[3] = NULL; + + close(sfd[1]); + dup2(sfd[0], 0); + dup2(sfd[0], 1); + for (d=3; d < 256; d++) { + if (d != sfd[0]) { + close(d); + } + } + execvp(args[0], args); + perror("exec"); + exit(1); + } else { + close(sfd[0]); + rfbsock = sfd[1]; + } + if (rfbsock < 0) { + fprintf(stderr,"Unable to connect to exec'd command: %s\n", cmd); + return False; + } + } else if (strchr(hostname, '/') && stat(hostname, &sb) == 0) { + /* assume unix domain socket */ + char *thost = strdup(hostname); + + rfbsock = ConnectToUnixSocket(thost); + free(thost); + + if (rfbsock < 0) { + fprintf(stderr,"Unable to connect to VNC server (unix-domain socket: %s)\n", hostname); + return False; + } + + } else { + if (!StringToIPAddr(hostname, &host)) { + fprintf(stderr,"Couldn't convert '%s' to host address\n", hostname); + return False; + } + + rfbsock = ConnectToTcpAddr(host, port); + + if (rfbsock < 0) { + fprintf(stderr,"Unable to connect to VNC server (%s:%d)\n", hostname, port); + return False; + } + } - return SetNonBlocking(rfbsock); + setnb = SetNonBlocking(rfbsock); + return setnb; } @@ -212,211 +342,301 @@ 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 (strstr(pv, "ID:") == pv) { + ; + } else if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) { + if (strstr(pv, "test") == pv) { + /* now some hacks for ultraVNC SC III (SSL) ... testA, etc */ + int i; + char *se = NULL; + + fprintf(stderr,"Trying UltraVNC Single Click III workaround: %s\n", pv); + for (i=0; i < 7 ; i++) { + pv[i] = pv[i+5]; + } + if (!ReadFromRFBServer(pv+7, 5)) { + return False; + } + + se = getenv("STUNNEL_EXTRA_OPTS"); + if (se == NULL) { + se = getenv("STUNNEL_EXTRA_OPTS_USER"); + } + if (se != NULL) { + if (strstr(se, "options")) { + if (strstr(se, "ALL") || strstr(se, "DONT_INSERT_EMPTY_FRAGMENTS")) { + ; /* good */ + } else { + se = NULL; + } + } else { + se = NULL; + } + } + if (se == NULL) { + fprintf(stderr, "\n"); + fprintf(stderr, "***************************************************************\n"); + fprintf(stderr, "To work around UltraVNC SC III SSL dropping after a few minutes\n"); + fprintf(stderr, "you may need to set STUNNEL_EXTRA_OPTS_USER='options = ALL'.\n"); + fprintf(stderr, "Or select 'UltraVNC Single Click III Bug' in the SSVNC GUI.\n"); + fprintf(stderr, "***************************************************************\n"); + fprintf(stderr, "\n"); + } + if (strstr(pv, "ID:") == pv) { + goto check_ID_string; + } + if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) == 2) { + goto ultra_vnc_nonsense; + } + } + fprintf(stderr,"Not a valid VNC server: '%s'\n", pv); + 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; - } + check_ID_string: + if (strstr(pv, "ID:") == pv) { + char tmp[256]; + fprintf(stderr, "UltraVNC Repeater string detected: %s\n", pv); + fprintf(stderr, "Pretending to be UltraVNC repeater: reading 250 bytes...\n\n"); + if (!ReadFromRFBServer(tmp, 250 - 12)) { + return False; + } + if (!ReadFromRFBServer(pv, 12)) { + return False; + } + if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) { + fprintf(stderr,"Not a valid VNC server: '%s'\n", pv); + return False; + } + } - fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n", - viewer_major, viewer_minor); + ultra_vnc_nonsense: + fprintf(stderr,"Proto: %s\n", pv); - sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor); + viewer_major = rfbProtocolMajorVersion; - if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) - return False; + if (appData.rfbVersion != NULL && sscanf(appData.rfbVersion, "%d.%d", &viewer_major, &viewer_minor) == 2) { + fprintf(stderr,"Setting RFB version to %d.%d from -rfbversion.\n", viewer_major, viewer_minor); + } else if (server_major == 3 && (server_minor == 14 || server_minor == 16)) { + /* hack for UltraVNC Single Click. They misuse rfb proto version */ + fprintf(stderr,"Setting RFB version to 3.3 for UltraVNC Single Click.\n"); + viewer_minor = rfbProtocolFallbackMinorVersion; + } else 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; + } - /* Read or select the security type. */ - if (viewer_minor == rfbProtocolMinorVersion) { - secType = SelectSecurityType(); - } else { - secType = ReadSecurityType(); - } - if (secType == rfbSecTypeInvalid) - return False; + fprintf(stderr, "\nConnected to RFB server, using protocol version %d.%d\n", viewer_major, viewer_minor); - 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; - } + sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor); - ci.shared = (appData.shareDesktop ? 1 : 0); + if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) { + return False; + } - if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) - return False; + /* Read or select the security type. */ + if (viewer_minor == rfbProtocolMinorVersion) { + secType = SelectSecurityType(); + } else { + secType = ReadSecurityType(); + } + if (secType == rfbSecTypeInvalid) { + return False; + } - if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg)) - 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; + } - 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; - } + ci.shared = (appData.shareDesktop ? 1 : 0); - if (!ReadFromRFBServer(desktopName, si.nameLength)) return False; + if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) { + return False; + } - desktopName[si.nameLength] = 0; + if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg)) { + return False; + } - fprintf(stderr,"Desktop name \"%s\"\n",desktopName); + 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; + } - fprintf(stderr,"VNC server default format:\n"); - PrintPixelFormat(&si.format); + if (!ReadFromRFBServer(desktopName, si.nameLength)) { + return False; + } - if (tightVncProtocol) { - /* Read interaction capabilities (protocol 3.7t) */ - if (!ReadInteractionCaps()) - return False; - } + desktopName[si.nameLength] = 0; - return True; + fprintf(stderr,"Desktop name \"%s\"\n\n", desktopName); + + fprintf(stderr,"VNC server default format:\n"); + PrintPixelFormat(&si.format); + + if (tightVncProtocol) { + /* Read interaction capabilities (protocol 3.7t) */ + if (!ReadInteractionCaps()) { + return False; + } + } + + 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; + } + } - free(secTypes); + /* 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); - 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 +671,9 @@ return True; } +static char *restart_session_pw = NULL; +static int restart_session_len = 0; + /* * Negotiate authentication scheme (protocol version 3.7t) @@ -459,56 +682,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 +747,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 +847,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 +923,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 +949,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 +979,11 @@ Bool requestCompressLevel = False; Bool requestQualityLevel = False; Bool requestLastRectEncoding = False; + Bool requestNewFBSizeEncoding = True; + Bool requestTextChatEncoding = True; + int dsm = 0; + +// fprintf(stderr, "SetFormatAndEncodings: sent_FBU state: %2d\n", sent_FBU); spf.type = rfbSetPixelFormat; spf.format = myFormat; @@ -736,12 +991,18 @@ spf.format.greenMax = Swap16IfLE(spf.format.greenMax); spf.format.blueMax = Swap16IfLE(spf.format.blueMax); + + currentMsg = rfbSetPixelFormat; if (!WriteExact(rfbsock, (char *)&spf, sz_rfbSetPixelFormatMsg)) return False; se->type = rfbSetEncodings; se->nEncodings = 0; + if (appData.ultraDSM) { + dsm = 1; + } + if (appData.encodingsString) { char *encStr = appData.encodingsString; int encStrLen; @@ -754,11 +1015,17 @@ 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) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect); - } else if (strncasecmp(encStr,"tight",encStrLen) == 0) { + } else if (strncasecmp(encStr,"tight",encStrLen) == 0 && !dsm) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight); requestLastRectEncoding = True; if (appData.compressLevel >= 0 && appData.compressLevel <= 9) @@ -767,16 +1034,33 @@ requestQualityLevel = True; } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile); - } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) { + } else if (strncasecmp(encStr,"zlib",encStrLen) == 0 && !dsm) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib); if (appData.compressLevel >= 0 && appData.compressLevel <= 9) requestCompressLevel = True; - } else if (strncasecmp(encStr,"corre",encStrLen) == 0) { + } else if (strncasecmp(encStr,"corre",encStrLen) == 0 && !dsm) { 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); +#if DO_ZYWRLE + } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) { + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE); + requestQualityLevel = True; + if (appData.qualityLevel < 3) { + zywrle_level = 3; + } else if (appData.qualityLevel < 6) { + zywrle_level = 2; + } else { + zywrle_level = 1; + } +#endif } else { fprintf(stderr,"Unknown encoding '%.*s'\n",encStrLen,encStr); + if (dsm && strstr(encStr, "tight") == encStr) fprintf(stderr, "tight encoding does not yet work with ultraDSM, skipping it.\n"); + if (dsm && strstr(encStr, "corre") == encStr) fprintf(stderr, "corre encoding does not yet work with ultraDSM, skipping it.\n"); + if (dsm && strstr(encStr, "zlib" ) == encStr) fprintf(stderr, "zlib encoding does not yet work with ultraDSM, skipping it.\n"); } encStr = nextEncStr; @@ -797,7 +1081,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 +1090,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 { @@ -818,13 +1106,15 @@ } encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect); - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight); + if (!dsm) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight); + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZRLE); + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE); encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile); - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib); - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE); + if (!dsm) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib); + if (!dsm) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE); encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE); - if (appData.compressLevel >= 0 && appData.compressLevel <= 9) { + if (!dsm && appData.compressLevel >= 0 && appData.compressLevel <= 9) { encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); } else if (!tunnelSpecified) { @@ -835,7 +1125,7 @@ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCompressLevel1); } - if (appData.enableJPEG) { + if (!dsm && appData.enableJPEG) { if (appData.qualityLevel < 0 || appData.qualityLevel > 9) appData.qualityLevel = 5; encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + @@ -844,18 +1134,35 @@ 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; - se->nEncodings = Swap16IfLE(se->nEncodings); + if (!appData.ultraDSM) { + se->nEncodings = Swap16IfLE(se->nEncodings); - if (!WriteExact(rfbsock, buf, len)) return False; + if (!WriteExact(rfbsock, buf, len)) return False; + } else { + /* for UltraVNC encryption DSM we have to send each encoding separately (why?) */ + int i, errs = 0, nenc = se->nEncodings; + + se->nEncodings = Swap16IfLE(se->nEncodings); + + currentMsg = rfbSetEncodings; + if (!WriteExact(rfbsock, buf, sz_rfbSetEncodingsMsg)) errs++; + for (i=0; i < nenc; i++) { + if (!WriteExact(rfbsock, (char *)&encs[i], sizeof(CARD32))) errs++; + } + if (errs) return False; + } return True; } @@ -868,31 +1175,110 @@ 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; +int delay_filexfer = 3; +extern void CheckFileXfer(void); +extern int rfbsock_is_ready(void); + + +// fprintf(stderr, "skip SendFramebufferUpdateRequest: %d - %d\n", last_filexfer, time(NULL)); +#if 0 +int ready; +if (0) { + ready = rfbsock_is_ready(); + if (db) fprintf(stderr, "rsir: %d\n", ready); + if (ready) { + int r = (int) HandleRFBServerMessage(); + if (db) fprintf(stderr, "hrsm: %d\n", r); + + } + if (db) fprintf(stderr, "CFX: C ****\n"); + CheckFileXfer(); + return True; +} +if (db) { + ready = rfbsock_is_ready(); + fprintf(stderr, "rsir: %d\n", ready); } +#endif +// x = y = 0; +// w = h = 1; + +static int dyn = -1; +extern int filexfer_sock; +extern int filexfer_listen; /* * SendFramebufferUpdateRequest. */ - Bool SendFramebufferUpdateRequest(int x, int y, int w, int h, Bool incremental) { - rfbFramebufferUpdateRequestMsg fur; + rfbFramebufferUpdateRequestMsg fur; + static int db = -1; - 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 (db < 0) { + if (getenv("SSVNC_DEBUG_RECTS")) { + db = atoi(getenv("SSVNC_DEBUG_RECTS")); + } else { + db = 0; + } + } - if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) - return False; + if (db) fprintf(stderr, "SendFramebufferUpdateRequest(%d, %d, %d, %d, incremental=%d)\n", x, y, w, h, (int) incremental); - return True; + if (dyn < 0) { + struct stat sb; + if (getenv("USER") && !strcmp(getenv("USER"), "runge")) { + if (stat("/tmp/nodyn", &sb) == 0) { + putenv("NOFTFBUPDATES=1"); + unlink("/tmp/nodyn"); + } + } + if (getenv("NOFTFBUPDATES")) { + dyn = 0; + } else { + dyn = 1; + } + } + + if (appData.fileActive && filexfer_sock >= 0) { + static int first = 1; + if (first) { + fprintf(stderr, "SFU: dynamic fb updates during filexfer: %d\n", dyn); + first = 0; + } +if (db > 2 || 0) fprintf(stderr, "A sfur: %d %d %d %d d_last: %d\n", x, y, w, h, (int) (time(NULL) - last_filexfer)); + if (!dyn || time(NULL) < last_filexfer + delay_filexfer) { + return True; + } + } +if (db > 1) fprintf(stderr, "B sfur: %d %d %d %d\n", x, y, w, h); + + fur.type = rfbFramebufferUpdateRequest; + fur.incremental = incremental ? 1 : 0; + fur.x = Swap16IfLE(x); + fur.y = Swap16IfLE(y); + fur.w = Swap16IfLE(w); + fur.h = Swap16IfLE(h); + + if (incremental) { + sent_FBU = 1; + } else { + sent_FBU = 2; + } + + currentMsg = rfbFramebufferUpdateRequest; + if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) { + return False; + } + + return True; } @@ -903,19 +1289,28 @@ Bool SendPointerEvent(int x, int y, int buttonMask) { - rfbPointerEventMsg pe; + rfbPointerEventMsg pe; + + if (appData.fileActive) { + if (!dyn || time(NULL) < last_filexfer + delay_filexfer) { + //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; - - if (!appData.useX11Cursor) - SoftCursorMove(x, y); - - pe.x = Swap16IfLE(x); - pe.y = Swap16IfLE(y); - return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg); + 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); + currentMsg = rfbPointerEvent; + return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg); } @@ -926,12 +1321,20 @@ Bool SendKeyEvent(CARD32 key, Bool down) { - rfbKeyEventMsg ke; + rfbKeyEventMsg ke; + + if (appData.fileActive) { + if (!dyn || time(NULL) < last_filexfer + delay_filexfer) { + //fprintf(stderr, "skip SendPointerEvent: %d - %d\n", last_filexfer, time(NULL)); + return True; + } + } - 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); + currentMsg = rfbKeyEvent; + return WriteExact(rfbsock, (char *)&ke, sz_rfbKeyEventMsg); } @@ -942,281 +1345,860 @@ 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.fileActive) { + if (!dyn || time(NULL) < last_filexfer + delay_filexfer) { + // ultravnc java viewer lets this one through. + return True; + } + } + + if (appData.viewOnly) { + return True; + } + + cct.type = rfbClientCutText; + cct.length = Swap32IfLE(len); + currentMsg = rfbClientCutText; + return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) && + WriteExact(rfbsock, str, len)); } +static int ultra_scale = 0; -/* - * HandleRFBServerMessage. - */ +Bool +SendServerScale(int nfac) +{ + rfbSetScaleMsg ssc; + if (nfac < 0 || nfac > 100) { + return True; + } + + ultra_scale = nfac; + ssc.type = rfbSetScale; + ssc.scale = nfac; + currentMsg = rfbSetScale; + return WriteExact(rfbsock, (char *)&ssc, sz_rfbSetScaleMsg); +} Bool -HandleRFBServerMessage() +SendServerInput(Bool enabled) { - rfbServerToClientMsg msg; + rfbSetServerInputMsg sim; - if (!ReadFromRFBServer((char *)&msg, 1)) - return False; + sim.type = rfbSetServerInput; + sim.status = enabled; + currentMsg = rfbSetServerInput; + return WriteExact(rfbsock, (char *)&sim, sz_rfbSetServerInputMsg); +} - switch (msg.type) { +Bool +SendSingleWindow(int x, int y) +{ + static int w_old = -1, h_old = -1; + rfbSetSWMsg sw; - case rfbSetColourMapEntries: - { - int i; - CARD16 rgb[3]; - XColor xc; + fprintf(stderr, "SendSingleWindow: %d %d\n", x, y); - if (!ReadFromRFBServer(((char *)&msg) + 1, - sz_rfbSetColourMapEntriesMsg - 1)) - return False; + if (x == -1 && y == -1) { + sw.type = rfbSetSW; + sw.x = Swap16IfLE(1); + sw.y = Swap16IfLE(1); + if (w_old > 0) { + si.framebufferWidth = w_old; + si.framebufferHeight = h_old; + ReDoDesktop(); + } + w_old = h_old = -1; + } else { + sw.type = rfbSetSW; + sw.x = Swap16IfLE(x); + sw.y = Swap16IfLE(y); + w_old = si.framebufferWidth; + h_old = si.framebufferHeight; + + } + sw.status = True; + currentMsg = rfbSetSW; + return WriteExact(rfbsock, (char *)&sw, sz_rfbSetSWMsg); +} - msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); - msg.scme.nColours = Swap16IfLE(msg.scme.nColours); +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; + } + currentMsg = rfbTextChat; + return WriteExact(rfbsock, str, strlen(str)); +} - 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); - } +extern void raiseme(int force); - break; - } +Bool +SendTextChatOpen(void) +{ + raiseme(0); + rfbTextChatMsg chat; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = Swap32IfLE(rfbTextChatOpen); + return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg); +} - case rfbFramebufferUpdate: - { - rfbFramebufferUpdateRectHeader rect; - int linesToRead; - int bytesPerLine; - int i; - int usecs; +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); +} - if (!ReadFromRFBServer(((char *)&msg.fu) + 1, - sz_rfbFramebufferUpdateMsg - 1)) - 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); +} + +static char fxfer[65536]; + +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; + + int db = 0; + +#if 0 + if (filexfer_sock < 0) { + return True; + } + // instead, we read and discard the ft msg data. +#endif - msg.fu.nRects = Swap16IfLE(msg.fu.nRects); +//fprintf(stderr, "In HandleFileXfer\n"); - for (i = 0; i < msg.fu.nRects; i++) { - if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) - return False; + last_filexfer = time(NULL); + //fprintf(stderr, "last_filexfer-1: %d\n", last_filexfer); - rect.encoding = Swap32IfLE(rect.encoding); - if (rect.encoding == rfbEncodingLastRect) - break; + // load first byte to send to Java be the FT msg number: + hdr[0] = rfbFileTransfer; - 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; + // this is to avoid XtAppProcessEvent() calls induce by our ReadFromRFBServer calls below: + skip_XtUpdateAll = 1; + if (!ReadFromRFBServer(&hdr[1], 11)) { + skip_XtUpdateAll = 0; + return False; + } + if (filexfer_sock >= 0) { + write(filexfer_sock, hdr, 12); + } else { + fprintf(stderr, "filexfer_sock closed, discarding 12 bytes\n"); + } + if (db) fprintf(stderr, "\n"); + if (db) fprintf(stderr, "Got rfbFileTransfer hdr\n"); + if (db > 1) write(2, hdr, 12); + + if (db) { + int i; + fprintf(stderr, "HFX HDR:"); + for (i=0; i < 12; i++) { + fprintf(stderr, " %d", (int) hdr[i]); + } + fprintf(stderr, "\n"); } - continue; - } - if (rect.encoding == rfbEncodingPointerPos) { - if (!HandleCursorPos(rect.r.x, rect.r.y)) { - return False; + if (hdr[1] == rfbEndOfFile) { + goto read_no_more; + } else if (hdr[1] == rfbAbortFileTransfer) { + goto read_no_more; } - 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; + len = (hdr[8] << 24) | (hdr[9] << 16) | (hdr[10] << 8) | hdr[11]; + if (db) fprintf(stderr, "Got rfbFileTransfer: len1 %u\n", len); + if (len > 0) { + if (!ReadFromRFBServer(fxfer, len)) { + skip_XtUpdateAll = 0; + return False; + } + if (db > 1) write(2, fxfer, len); + if (db && 0) fprintf(stderr, "\n"); + if (filexfer_sock >= 0) { + write(filexfer_sock, fxfer, len); + } else { + fprintf(stderr, "filexfer_sock closed, discarding %d bytes\n", len); + } } - if (rect.r.h * rect.r.w == 0) { - fprintf(stderr,"Zero size rect - ignoring\n"); - continue; - } + /* not used! */ + len = (hdr[4] << 24) | (hdr[5] << 16) | (hdr[6] << 8) | hdr[7]; + if (db) fprintf(stderr, "Got rfbFileTransfer: len2 %u\n", len); + + 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 > 1) write(2, fxfer, len); + if (db && 0) fprintf(stderr, "\n"); + if (filexfer_sock >= 0) { + write(filexfer_sock, fxfer, len); + } else { + fprintf(stderr, "filexfer_sock closed, discarding %d bytes\n", len); + } + } - /* 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); + read_no_more: - switch (rect.encoding) { + if (filexfer_sock < 0) { + int stop = 0; + static time_t last_stop = 0; +#if 0 + // this isn't working + if (hdr[1] == rfbFilePacket || hdr[1] == rfbFileHeader) { + fprintf(stderr, "filexfer_sock closed, trying to abort receive\n"); + stop = 1; + } +#endif + if (stop && time(NULL) > last_stop+1) { + unsigned char rpl[12]; + int k; + rpl[0] = rfbFileTransfer; + rpl[1] = rfbAbortFileTransfer; + for (k=2; k < 12; k++) { + rpl[k] = 0; + } + WriteExact(rfbsock, rpl, 12); + last_stop = time(NULL); + } + } - case rfbEncodingRaw: + if (db) fprintf(stderr, "Got rfbFileTransfer done.\n"); + skip_XtUpdateAll = 0; - bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8; - linesToRead = BUFFER_SIZE / bytesPerLine; + if (db) fprintf(stderr, "CFX: B\n"); + CheckFileXfer(); +//fprintf(stderr, "Out HandleFileXfer\n"); + return True; +} - while (rect.r.h > 0) { - if (linesToRead > rect.r.h) - linesToRead = rect.r.h; +/* + * HandleRFBServerMessage. + */ - if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) - return False; - CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, - linesToRead); +Bool +HandleRFBServerMessage() +{ + static int db = -1; + rfbServerToClientMsg msg; - rect.r.h -= linesToRead; - rect.r.y += linesToRead; + if (db < 0) { + if (getenv("DEBUG_RFB_SMSG")) { + db = 1; + } else { + db = 0; + } + } + if (!ReadFromRFBServer((char *)&msg, 1)) { + return False; } - break; + if (appData.ultraDSM) { + if (!ReadFromRFBServer((char *)&msg, 1)) { + return False; + } + } + +//fprintf(stderr, "msg.type: %d\n", msg.type); - case rfbEncodingCopyRect: - { - rfbCopyRect cr; - - if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) - return False; - - cr.srcX = Swap16IfLE(cr.srcX); - cr.srcY = Swap16IfLE(cr.srcY); - - /* If RichCursor encoding is used, we should extend our - "cursor lock area" (previously set to destination - rectangle) to the source rectangle as well. */ - SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h); - - if (appData.copyRectDelay != 0) { - XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, - rect.r.w, rect.r.h); - XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, - rect.r.w, rect.r.h); - XSync(dpy,False); - usleep(appData.copyRectDelay * 1000); - XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, - rect.r.w, rect.r.h); - XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, - rect.r.w, rect.r.h); + if (msg.type == rfbFileTransfer) { + return HandleFileXfer(); } - XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY, - rect.r.w, rect.r.h, rect.r.x, rect.r.y); + switch (msg.type) { - break; - } + case rfbSetColourMapEntries: + { + int i; + CARD16 rgb[3]; + XColor xc; - 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; + if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbSetColourMapEntriesMsg - 1)) { + return False; } - 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; - } + msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); + msg.scme.nColours = Swap16IfLE(msg.scme.nColours); - 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; + 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 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; + 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; + static int rdb = -1; + + if (db) fprintf(stderr, "FBU-0: %.6f\n", dnow()); + if (rdb < 0) { + if (getenv("SSVNC_DEBUG_RECTS")) { + rdb = atoi(getenv("SSVNC_DEBUG_RECTS")); + } else { + rdb = 0; + } } - break; - } - case rfbEncodingTight: - { - switch (myFormat.bitsPerPixel) { - case 8: - if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; - case 16: - if (!HandleTight16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; - case 32: - if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; + int skip_incFBU = 0; + sent_FBU = -1; + + if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) { + return False; } - break; - } - default: - fprintf(stderr,"Unknown rect encoding %d\n", - (int)rect.encoding); - return False; - } + msg.fu.nRects = Swap16IfLE(msg.fu.nRects); - /* Now we may discard "soft cursor locks". */ - SoftCursorUnlockScreen(); - } + 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 (0) fprintf(stderr, "CursorPos: %d %d / %d %d\n", rect.r.x, rect.r.y, rect.r.w, rect.r.h); + if (ultra_scale > 0) { + int f = ultra_scale; + if (!HandleCursorPos(rect.r.x/f, rect.r.y/f)) { + return False; + } + } else { + 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 (rdb) fprintf(stderr,"Rect: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); + + if (appData.ultraDSM) { + /* + * What a huge mess the UltraVNC DSM plugin is!!! + * We read and ignore their little "this much data" hint... + */ + switch (rect.encoding) + { + case rfbEncodingRaw: + case rfbEncodingRRE: + case rfbEncodingCoRRE: + case rfbEncodingHextile: + //case rfbEncodingUltra: +// case rfbEncodingZlib: + //case rfbEncodingXOR_Zlib: + //case rfbEncodingXORMultiColor_Zlib: + //case rfbEncodingXORMonoColor_Zlib: + //case rfbEncodingSolidColor: + case rfbEncodingTight: + case rfbEncodingZlibHex: + case rfbEncodingZRLE: + case rfbEncodingZYWRLE: + { + CARD32 discard; + ReadFromRFBServer((char *)&discard, sizeof(CARD32)); + } + break; + } + } + + 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) encoding=%d\n", + rect.r.w, rect.r.h, rect.r.x, rect.r.y, rect.encoding); + return False; + } + + if (rect.r.h * rect.r.w == 0) { + fprintf(stderr,"*** Warning *** Zero size rect: %dx%d+%d+%d encoding=%d\n", + rect.r.w, rect.r.h, rect.r.x, rect.r.y, rect.encoding); + if (0) 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 DO_ZYWRLE + zywrle_level = 0; + case rfbEncodingZYWRLE: +#endif + { + 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 (myFormat.greenMax > 0x1f) { + if (!HandleZRLE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { + return False; + } + } else { + if (!HandleZRLE15(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); + } + } #ifdef MITSHM /* if using shared memory PutImage, make sure that the X server has @@ -1224,59 +2206,165 @@ mainly to avoid copyrect using invalid screen contents - not sure if we'd need it otherwise. */ - if (appData.useShm) - XSync(dpy, False); + if (appData.useShm) { + XSync(dpy, False); + } else #endif + { + XSync(dpy, False); + } + + if (skip_XtUpdate || skip_incFBU) { + ; + } else if (!SendIncrementalFramebufferUpdateRequest()) { + return False; + } - if (!SendIncrementalFramebufferUpdateRequest()) - return False; - - break; + break; } case rfbBell: { - Window toplevelWin; + Window toplevelWin; - XBell(dpy, 0); + if (appData.useBell) { + 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 rfbResizeFrameBuffer: + { + rfbResizeFrameBufferMsg rsmsg; + if (!ReadFromRFBServer(((char *)&rsmsg) + 1, sz_rfbResizeFrameBufferMsg - 1)) { + return False; + } + si.framebufferWidth = Swap16IfLE(rsmsg.framebufferWidth); + si.framebufferHeight = Swap16IfLE(rsmsg.framebufferHeight); + fprintf(stderr,"UltraVNC ReSize: %dx%d\n", si.framebufferWidth, si.framebufferHeight); + ReDoDesktop(); + break; + } - return True; + 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); + + 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; + SendFramebufferUpdateRequest(0, 0, 1, 1, False); + } else { +//fprintf(stderr, "CFX: A\n"); + CheckFileXfer(); + } + } + + return True; } @@ -1296,26 +2384,47 @@ #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" #include "corre.c" #include "hextile.c" #include "zlib.c" #include "tight.c" +#include "zrle.c" +#define REALBPP 15 +#include "zrle.c" #undef BPP + #define BPP 32 #include "rre.c" #include "corre.c" #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 +2467,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) { @@ -1462,4 +2571,3 @@ cinfo->src = &jpegSrcManager; } - 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 2008-09-14 10:28:56.000000000 -0400 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -56,22 +57,339 @@ */ static Bool rfbsockReady = False; +static Bool xfrsockReady = False; +static XtInputId rfbsockId = 0; +static XtInputId xfrsockId = 0; +static int do_rfbsockId = 0; +static int do_xfrsockId = 0; + static void rfbsockReadyCallback(XtPointer clientData, int *fd, XtInputId *id) { - rfbsockReady = True; - XtRemoveInput(*id); + rfbsockReady = True; +// XtRemoveInput(*id); + XtRemoveInput(rfbsockId); + if (do_xfrsockId) { + XtRemoveInput(xfrsockId); + } +} + +static void +xfrsockReadyCallback(XtPointer clientData, int *fd, XtInputId *id) +{ + xfrsockReady = True; + XtRemoveInput(xfrsockId); + if (do_rfbsockId) { + XtRemoveInput(rfbsockId); + } +} + + +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; + +int rfbsock_is_ready(void) { + fd_set fds; + struct timeval tv; + + if (rfbsock < 0) { + return 0; + } + FD_ZERO(&fds); + FD_SET(rfbsock,&fds); + tv.tv_sec = 0; + tv.tv_usec = 0; + if (select(rfbsock+1, &fds, NULL, NULL, &tv) > 0) { + if (FD_ISSET(rfbsock, &fds)) { + return 1; + } + } + return 0; +} + +time_t filexfer_start = 0; + +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 + 30) { + 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_sock >= 0) { + fprintf(stderr, "filexfer accept OK.\n"); + close(filexfer_listen); + filexfer_listen = -1; + filexfer_start = last_filexfer = time(NULL); + } 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 (db) { + int i; + fprintf(stderr, "CFX HDR:"); + for (i=0; i < 12; i++) { + fprintf(stderr, " %d", (int) fxfer[i]); + } + fprintf(stderr, " ?\n"); } + 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); + appData.fileActive = False; + SendFramebufferUpdateRequest(0, 0, 1, 1, False); + return; + } else if (rn > 0) { + if (db > 1) 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 (0) { + /* WE TRY TO FIX THIS IN THE JAVA NOW */ + if (appData.ultraDSM) { + unsigned char msg = rfbFileTransfer; + unsigned char hdc = (unsigned char) fxfer[0]; + if (msg == hdc) { + /* cross your fingers... */ + WriteExact(rfbsock, (char *)&msg, 1); + } + } + } + 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 > 1) 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 > 1) 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); + // forgot that this is about... + usleep(10 * 1000); + continue; + } + } + break; + } + } + if (igot) { + last_filexfer = time(NULL); + //fprintf(stderr, "last_filexfer-2c: %d\n", last_filexfer); + } +//fprintf(stderr, "Out CheckFileXfer\n"); + return; +} + +static time_t time_mark; +extern int delay_filexfer; +#include static void ProcessXtEvents() { - rfbsockReady = False; - XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask, - rfbsockReadyCallback, NULL); - while (!rfbsockReady) { - XtAppProcessEvent(appContext, XtIMAll); - } + int y, db = 0; + static int dyn = -1; + + if (dyn < 0) { + struct stat sb; + if (getenv("USER") && !strcmp(getenv("USER"), "runge")) { + if (stat("/tmp/nodyn", &sb) == 0) { + putenv("NOFTFBUPDATES=1"); + unlink("/tmp/nodyn"); + } + } + if (getenv("NOFTFBUPDATES")) { + dyn = 0; + } else { + dyn = 1; + } + } + + 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; + } + + rfbsockReady = False; + xfrsockReady = False; + do_rfbsockId = 1; + rfbsockId = XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask, + rfbsockReadyCallback, NULL); + + do_xfrsockId = 0; + if (filexfer_sock >= 0) { + do_xfrsockId = 1; + xfrsockId = XtAppAddInput(appContext, filexfer_sock, (XtPointer)XtInputReadMask, + xfrsockReadyCallback, NULL); + } + + time_mark = time(NULL); + + if (appData.fileActive) { + static int first = 1; + if (first) { + fprintf(stderr, "PXT: dynamic fb updates during filexfer: %d\n", dyn); + first = 0; + } + } + + if (db) fprintf(stderr, "XtAppAddInput: "); + while (!rfbsockReady && !xfrsockReady) { + int w = si.framebufferWidth; + int h = si.framebufferHeight; + if (db) fprintf(stderr, "."); + if (dyn && filexfer_sock >= 0 && time(NULL) > time_mark + delay_filexfer) { + SendFramebufferUpdateRequest(0, 0, w, h, False); + } + XtAppProcessEvent(appContext, XtIMAll); + } + if (db) fprintf(stderr, " done. r: %d x: %d\n", rfbsockReady, xfrsockReady); + + if (xfrsockReady) { + CheckFileXfer(); + } } Bool @@ -151,6 +469,8 @@ } +int currentMsg = -1; + /* * Write an exact number of bytes, and don't return until you've sent them. */ @@ -158,37 +478,81 @@ Bool WriteExact(int sock, char *buf, int n) { - fd_set fds; - int i = 0; - int j; - - while (i < n) { - j = write(sock, buf + i, (n - i)); - if (j <= 0) { - if (j < 0) { - if (errno == EWOULDBLOCK || errno == EAGAIN) { - FD_ZERO(&fds); - FD_SET(rfbsock,&fds); + fd_set fds; + int i = 0; + int j; + + if (appData.ultraDSM && currentMsg >= 0) { + /* this is for goofy UltraVNC DSM send RFB msg char twice: */ + unsigned char msg = (unsigned char) currentMsg; + currentMsg = -1; + if (!WriteExact(sock, (char *)&msg, sizeof(msg))) { + return False; + } + } + currentMsg = -1; - if (select(rfbsock+1, NULL, &fds, NULL, NULL) <= 0) { - fprintf(stderr,programName); - perror(": select"); - return False; - } - j = 0; - } else { - fprintf(stderr,programName); - perror(": write"); - return False; + while (i < n) { + j = write(sock, buf + i, (n - i)); + if (j <= 0) { + if (j < 0) { + if (errno == EWOULDBLOCK || errno == EAGAIN) { + FD_ZERO(&fds); + FD_SET(rfbsock,&fds); + + if (select(rfbsock+1, NULL, &fds, NULL, NULL) <= 0) { + fprintf(stderr,programName); + perror(": select"); + return False; + } + j = 0; + } else { + fprintf(stderr,programName); + perror(": write"); + return False; + } + } else { + fprintf(stderr,"%s: write failed\n",programName); + return False; + } + } + i += j; } - } else { - fprintf(stderr,"%s: write failed\n",programName); - return False; - } - } - i += j; - } - return True; + return True; +} + +int +ConnectToUnixSocket(char *file) { + int sock; + struct sockaddr_un addr; + int i; + + memset(&addr, 0, sizeof(struct sockaddr_un)); + + addr.sun_family = AF_UNIX; + + for (i=0; i < 108; i++) { + addr.sun_path[i] = file[i]; + if (file[i] == '\0') { + break; + } + } + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + fprintf(stderr,programName); + perror(": ConnectToUnixSocket: socket"); + return -1; + } + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + fprintf(stderr, programName); + perror(": ConnectToUnixSocket: connect"); + close(sock); + return -1; + } + + return sock; } @@ -203,6 +567,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; @@ -232,7 +598,22 @@ return sock; } +Bool SocketPair(int fd[2]) { + if (socketpair(PF_UNIX, SOCK_STREAM, AF_UNIX, fd) == -1) { + perror("socketpair"); + return False; + } + return True; +} +Bool SetNoDelay(int sock) { + const int one = 1; + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { + perror("setsockopt"); + return False; + } + return True; +} /* * FindFreeTcpPort tries to find unused TCP port in the range @@ -245,6 +626,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 +655,8 @@ * ListenAtTcpPort starts listening at the given TCP port. */ +int use_loopback = 0; + int ListenAtTcpPort(int port) { @@ -279,10 +664,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.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 2008-09-09 00:08:07.000000000 -0400 @@ -22,6 +22,7 @@ */ #include "vncviewer.h" +#include char *programName; XtAppContext appContext; @@ -29,11 +30,179 @@ 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\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, p, 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]; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-env") == 0) { + if (i+1 < argc) { + char *estr = argv[i+1]; + if (strchr(estr, '=')) { + putenv(estr); + } + } + } + } /* 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 +214,1235 @@ 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], "-multilisten") == 0) { + putenv("SSVNC_MULTIPLE_LISTEN=1"); + 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 (strcmp(argv[i], "-printres") == 0 || strcmp(argv[i], "-res") == 0) { + int j = 0; + fprintf(stdout, "\n! Ssvnc fallback X resources:\n\n"); + while (1) { + char *p = fallback_resources[j++]; + int k = 0; + if (p == NULL) break; + while (*p != '\0') { + fprintf(stdout, "%c", *p); + if (k > 0 && *p == 'n' && *(p-1) == '\\') { + fprintf(stdout, "\\\n"); + } + p++; k++; + } + fprintf(stdout, "\n\n"); + } + exit(0); + } + } + + 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, "Ssvnc", 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 (appData.repeaterUltra == NULL) { + if (getenv("SSVNC_REPEATER") != NULL) { + appData.repeaterUltra = strdup(getenv("SSVNC_REPEATER")); + } + } + + if (!listenSpecified) { + if (!ConnectToRFBServer(vncServerHost, vncServerPort)) { + exit(1); + } + if (appData.repeaterUltra != NULL) { + char tmp[256]; + if (strstr(appData.repeaterUltra, "SCIII=") == appData.repeaterUltra) { + appData.repeaterUltra = strdup(appData.repeaterUltra + strlen("SCIII=")); + fprintf(stderr, "sending 'testB' to ultravnc SC III SSL repeater...\n"); + WriteExact(rfbsock, "testB" , 5); + } + if (ReadFromRFBServer(tmp, 12)) { + tmp[12] = '\0'; + fprintf(stderr, "repeater 1st proto line: '%s'\n", tmp); + if (strstr(tmp, "RFB 000.000") == tmp) { + int i; + for (i=0; i<256; i++) { + tmp[i] = '\0'; + } + for (i=0; i<250; i++) { + if (i >= strlen(appData.repeaterUltra)) { + break; + } + tmp[i] = appData.repeaterUltra[i]; + } + fprintf(stderr, "sending '%s' to repeater...\n", tmp); + WriteExact(rfbsock, tmp, 250); + } + } else { + fprintf(stderr, "repeater NO proto line!\n"); + } + } + } /* 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(); + CreateQuality(); + CreateCompress(); + 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; + appDataNew.qualityLevel = appData.qualityLevel; + appDataNew.compressLevel = appData.compressLevel; +} +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; + appData.qualityLevel = appDataNew.qualityLevel; + appData.compressLevel = appDataNew.compressLevel; +} + +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; +static Bool usingZYWRLE = False; +extern int skip_maybe_sync; + +void +ToggleTightZRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + char prefTight[] = "copyrect tight zrle zywrle zlib hextile corre rre raw"; + char prefZRLE[] = "copyrect zrle zywrle 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 *t, *z; + static int first = 1; + t = strstr(appData.encodingsString, "tight"); + z = strstr(appData.encodingsString, "zrle"); + if (first && usingZRLE) { + appDataNew.encodingsString = strdup(prefTight); + usingZRLE = False; + usingZYWRLE = False; + } else if (! t) { + appDataNew.encodingsString = strdup(prefZRLE); + usingZRLE = True; + fprintf(stderr, "prefer: ZRLE\n"); + } else if (! z) { + appDataNew.encodingsString = strdup(prefTight); + usingZRLE = False; + usingZYWRLE = False; + skip_maybe_sync = 0; + fprintf(stderr, "prefer: Tight\n"); + } else { + if (t < z) { + appDataNew.encodingsString = strdup(prefZRLE); + usingZRLE = True; + fprintf(stderr, "prefer: ZRLE\n"); + } else { + appDataNew.encodingsString = strdup(prefTight); + usingZRLE = False; + usingZYWRLE = False; + skip_maybe_sync = 0; + fprintf(stderr, "prefer: Tight\n"); + } + } + first = 0; + } + schedule_format_change(); +} + +void +ToggleZRLEZYWRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + char prefZYWRLE[] = "copyrect zywrle zrle tight zlib hextile corre rre raw"; + char prefZRLE[] = "copyrect zrle zywrle tight zlib hextile corre rre raw"; + init_format_change(); + usingZRLE = True; + if (! appData.encodingsString) { + appDataNew.encodingsString = strdup(prefZYWRLE); + usingZYWRLE = True; + fprintf(stderr, "prefer: ZYWRLE\n"); + } else { + char *z, *w; + w = strstr(appData.encodingsString, "zywrle"); + z = strstr(appData.encodingsString, "zrle"); + if (usingZYWRLE) { + appDataNew.encodingsString = strdup(prefZRLE); + fprintf(stderr, "prefer: ZRLE\n"); + usingZYWRLE = False; + skip_maybe_sync = 0; + } else { + appDataNew.encodingsString = strdup(prefZYWRLE); + fprintf(stderr, "prefer: ZYWRLE\n"); + usingZYWRLE = True; + } + } + 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(int force); +void AppendChatInput(char *); + +void printChat(char *str, Bool raise) { + if (appData.termChat) { + if (raise) { + raiseme(0); + } + 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; + } +} + +extern int filexfer_sock; +extern pid_t java_helper; +#define KILLJAVA +#ifdef KILLJAVA +#include +#endif + +void +ToggleFileXfer(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.fileActive) { + //HideFile(w, ev, params, num_params); + //appData.fileActive = False; +#ifndef KILLJAVA + if (filexfer_sock >= 0) { + close(filexfer_sock); + } +#else + if (java_helper != 0) { + int i; + for (i=1; i<=5; i++) { + pid_t p = java_helper + i; + fprintf(stderr, "trying to kill java helper: %d\n", p); + if (kill(p, SIGTERM) == 0) { + java_helper = 0; + break; + } + } + } +#endif + } else { + ShowFile(w, ev, params, num_params); + appData.fileActive = True; + } +} + +static int fooHandler(Display *dpy, XErrorEvent *error) { + return 0; +} + +void raiseme(int force) { + if ((force || 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); + if (0) SendFramebufferUpdateRequest(0, 0, w, h, False); + schedule_fb_update(); + } +} + +void +DoServerScale(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + char str[100], *s, *q; + int n; + if (1) { + s = DoScaleDialog(); + } else { + raiseme(1); + fprintf(stderr, "\n\n\a\nEnter integer n for 1/n server scaling: "); + str[0] = '\0'; + fgets(str, 100, stdin); + s = str; + q = strstr(str, "\n"); + if (q) *q = '\0'; + } + if (s[0] != '\0') { + n = atoi(s); + set_server_scale(n); + } +} + +void set_server_quality(int n) { + fprintf(stderr, "set_quality: %d\n", n); + if (n >= 0 && n <= 9) { + int w = si.framebufferWidth; + int h = si.framebufferHeight; + init_format_change(); + appDataNew.qualityLevel = n; + SendFramebufferUpdateRequest(0, 0, w, h, False); + schedule_format_change(); + } +} + +void +DoServerQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + char str[100], *s, *q; + int n; + if (1) { + s = DoQualityDialog(); + } else { + raiseme(1); + fprintf(stderr, "\n\n\a\nEnter integer 1 <= n <= 9 for quality setting: "); + str[0] = '\0'; + fgets(str, 100, stdin); + s = str; + q = strstr(str, "\n"); + if (q) *q = '\0'; + } + if (s[0] != '\0') { + n = atoi(s); + set_server_quality(n); + } +} + +void set_server_compress(int n) { + fprintf(stderr, "set_compress: %d\n", n); + if (n >= 0 && n <= 9) { + int w = si.framebufferWidth; + int h = si.framebufferHeight; + init_format_change(); + appDataNew.compressLevel = n; + SendFramebufferUpdateRequest(0, 0, w, h, False); + schedule_format_change(); + } +} + +void +DoServerCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + char str[100], *s, *q; + int n; + if (1) { + s = DoCompressDialog(); + } else { + raiseme(1); + fprintf(stderr, "\n\n\a\nEnter integer 1 <= n <= 9 for compress level setting: "); + str[0] = '\0'; + fgets(str, 100, stdin); + s = str; + q = strstr(str, "\n"); + if (q) *q = '\0'; + } + if (s[0] != '\0') { + n = atoi(s); + set_server_compress(n); + } +} + - Cleanup(); +void set_ycrop(int n) { + if (n >= 1) { + int w = si.framebufferWidth; + int h = si.framebufferHeight; + appData.yCrop = n; + ReDoDesktop(); + SendFramebufferUpdateRequest(0, 0, w, h, False); + schedule_fb_update(); + } +} + +void +SetYCrop(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + char str[100], *q, *s; + int n; + if (1) { + s = DoYCropDialog(); + } else { + raiseme(1); + fprintf(stderr, "\n\n\a\nEnter pixel size n -ycrop maximum y-height: "); + str[0] = '\0'; + fgets(str, 100, stdin); + s = str; + q = strstr(str, "\n"); + if (q) *q = '\0'; + } + if (s[0] != '\0') { + n = atoi(s); + set_ycrop(n); + } +} - return 0; +void set_scbar(int n) { + if (n >= 1) { + int w = si.framebufferWidth; + int h = si.framebufferHeight; +fprintf(stderr, "set_scbat: %d\n", n); + appData.sbWidth = n; + ReDoDesktop(); + SendFramebufferUpdateRequest(0, 0, w, h, False); + schedule_fb_update(); + } +} + +void +SetScbar(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + char str[100], *q, *s; + int n; + if (1) { + s = DoScbarDialog(); + } else { + raiseme(1); + fprintf(stderr, "\n\n\a\nEnter pixel size n scrollbar width: "); + str[0] = '\0'; + fgets(str, 100, stdin); + s = str; + q = strstr(str, "\n"); + if (q) *q = '\0'; + } + if (s[0] != '\0') { + n = atoi(s); + set_scbar(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 +SetQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (*num_params != 0) { + int n = atoi(params[0]); + set_server_quality(n); + } +} + +void +SetCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (*num_params != 0) { + int n = atoi(params[0]); + set_server_compress(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 +SetQualityState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (*num_params != 0) { + int n = atoi(params[0]); + if (appData.qualityLevel == n) { + XtVaSetValues(w, XtNstate, True, NULL); + } else { + XtVaSetValues(w, XtNstate, False, NULL); + } + } +} + +void +SetCompressState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (*num_params != 0) { + int n = atoi(params[0]); + if (appData.compressLevel == n) { + XtVaSetValues(w, XtNstate, True, NULL); + } else { + XtVaSetValues(w, XtNstate, False, NULL); + } + } +} + +void +SetScaleNState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (*num_params != 0) { + int n = atoi(params[0]); + if (appData.serverScale == n || (appData.serverScale >= 6 && n >= 6)) { + XtVaSetValues(w, XtNstate, True, NULL); + } else { + XtVaSetValues(w, XtNstate, False, NULL); + } + } +} + +void +Set8bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.useBGR233) { + XtVaSetValues(w, XtNstate, True, NULL); + if (b16 != NULL) XtVaSetValues(b16, XtNstate, False, NULL); + if (bfull != NULL) XtVaSetValues(bfull, XtNstate, False, NULL); + } else { + XtVaSetValues(w, XtNstate, False, NULL); + } +} + +void +Set16bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.useBGR565) { + XtVaSetValues(w, XtNstate, True, NULL); + if (b8 != NULL) XtVaSetValues(b8, XtNstate, False, NULL); + if (bfull != NULL) XtVaSetValues(bfull, XtNstate, False, NULL); + } else { + XtVaSetValues(w, XtNstate, False, NULL); + } +} + +void +SetFullColorState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.useBGR565 || appData.useBGR233) { + XtVaSetValues(w, XtNstate, False, NULL); + } else { + XtVaSetValues(w, XtNstate, True, NULL); + if (b8 != NULL) XtVaSetValues(b8, XtNstate, False, NULL); + if (b16 != NULL) XtVaSetValues(b16, XtNstate, False, NULL); + } +} + +void +Set256ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.useBGR233 == 256) { + XtVaSetValues(w, XtNstate, True, NULL); + if (w64 != NULL) XtVaSetValues(w64 , XtNstate, False, NULL); + if (w8 != NULL) XtVaSetValues(w8 , XtNstate, False, NULL); + } else { + XtVaSetValues(w, XtNstate, False, NULL); + } +} + +void +Set64ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.useBGR233 == 64) { + XtVaSetValues(w, XtNstate, True, NULL); + if (w256 != NULL) XtVaSetValues(w256, XtNstate, False, NULL); + if (w8 != NULL) XtVaSetValues(w8 , XtNstate, False, NULL); + } else { + XtVaSetValues(w, XtNstate, False, NULL); + } +} + +void +Set8ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.useBGR233 == 8) { + XtVaSetValues(w, XtNstate, True, NULL); + if (w256 != NULL) XtVaSetValues(w256, XtNstate, False, NULL); + if (w64 != NULL) XtVaSetValues(w64 , XtNstate, False, NULL); + } else { + XtVaSetValues(w, XtNstate, False, NULL); + } +} + +void +SetGreyScaleState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (appData.useGreyScale) { + XtVaSetValues(w, XtNstate, True, NULL); + } else { + XtVaSetValues(w, XtNstate, False, NULL); + } +} + +void +SetZRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + static int first = 1; + if (first && appData.encodingsString) { + char *t, *z, *w; + t = strstr(appData.encodingsString, "tight"); + z = strstr(appData.encodingsString, "zrle"); + w = strstr(appData.encodingsString, "zywrle"); + if (t) { + if (z) { + if (w) { + if (t < z && t < w) { + usingZRLE = False; + } else { + usingZRLE = True; + } + if (z < w) { + usingZYWRLE = False; + } else { + usingZYWRLE = True; + } + } else { + if (t < z) { + usingZRLE = False; + } else { + usingZRLE = True; + } + usingZYWRLE = False; + } + } else { + if (w) { + if (t < w) { + usingZRLE = False; + } else { + usingZRLE = True; + } + usingZYWRLE = True; + } else { + usingZRLE = False; + usingZYWRLE = False; + } + } + } else { + if (z) { + if (w) { + usingZRLE = True; + if (z < w) { + usingZYWRLE = False; + } else { + usingZYWRLE = True; + } + } else { + usingZRLE = True; + usingZYWRLE = False; + } + } else { + if (w) { + usingZRLE = True; + usingZYWRLE = True; + } else { + usingZRLE = False; + usingZYWRLE = False; + } + } + } + } + first = 0; + + if (usingZRLE) + XtVaSetValues(w, XtNstate, True, NULL); + else + XtVaSetValues(w, XtNstate, False, NULL); +} + +void +SetZYWRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ + if (usingZYWRLE) + 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 2008-09-13 13:54:01.000000000 -0400 @@ -51,7 +51,7 @@ (((l) & 0x0000ff00) << 8) | \ (((l) & 0x000000ff) << 24)) : (l)) -#define MAX_ENCODINGS 20 +#define MAX_ENCODINGS 24 #define FLASH_PORT_OFFSET 5400 #define LISTEN_PORT_OFFSET 5500 @@ -68,51 +68,77 @@ /* 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 *repeaterUltra; + Bool ultraDSM; + char *rfbVersion; + + char *passwordFile; + Bool passwordDialog; + + int rawDelay; + int copyRectDelay; + + int yCrop; + int sbWidth; + Bool useCursorAlpha; + Bool useRawLocal; + + Bool debug; + + int popupButtonCount; + int popupButtonBreak; + + 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 +156,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,13 +184,40 @@ 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 YCropDialogDone(Widget w, XEvent *event, String *params, + Cardinal *num_params); +extern char *DoYCropDialog(); + +extern void ScbarDialogDone(Widget w, XEvent *event, String *params, + Cardinal *num_params); +extern char *DoScbarDialog(); + +extern void ScaleDialogDone(Widget w, XEvent *event, String *params, + Cardinal *num_params); +extern char *DoScaleDialog(); + +extern void QualityDialogDone(Widget w, XEvent *event, String *params, + Cardinal *num_params); +extern char *DoQualityDialog(); + +extern void CompressDialogDone(Widget w, XEvent *event, String *params, + Cardinal *num_params); +extern char *DoCompressDialog(); + extern void ServerDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params); extern char *DoServerDialog(); @@ -181,6 +235,11 @@ extern void FullScreenOn(); extern void FullScreenOff(); +extern void JumpLeft(Widget w, XEvent *event, String *params, Cardinal *num_params); +extern void JumpRight(Widget w, XEvent *event, String *params, Cardinal *num_params); +extern void JumpUp(Widget w, XEvent *event, String *params, Cardinal *num_params); +extern void JumpDown(Widget w, XEvent *event, String *params, Cardinal *num_params); + /* listen.c */ extern void listenForIncomingConnections(); @@ -207,6 +266,18 @@ Cardinal *num_params); extern void CreatePopup(); +extern void HideScaleN(Widget w, XEvent *event, String *params, + Cardinal *num_params); +extern void CreateScaleN(); + +extern void HideQuality(Widget w, XEvent *event, String *params, + Cardinal *num_params); +extern void CreateQuality(); + +extern void HideCompress(Widget w, XEvent *event, String *params, + Cardinal *num_params); +extern void CreateCompress(); + /* rfbproto.c */ extern int rfbsock; @@ -229,6 +300,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 +321,9 @@ /* shm.c */ -extern XImage *CreateShmImage(); +extern XImage *CreateShmImage(int do_ycrop); extern void ShmCleanup(); +extern Bool UsingShm(); /* sockets.c */ @@ -253,8 +334,11 @@ extern int FindFreeTcpPort(void); extern int ListenAtTcpPort(int port); extern int ConnectToTcpAddr(unsigned int host, int port); +extern int ConnectToUnixSocket(char *file); extern int AcceptTcpConnection(int listenSock); extern Bool SetNonBlocking(int sock); +extern Bool SetNoDelay(int sock); +extern Bool SocketPair(int fd[2]); extern int StringToIPAddr(const char *str, unsigned int *addr); extern Bool SameMachine(int sock); @@ -271,3 +355,63 @@ 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 ToggleZRLEZYWRLE(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 DoServerQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void DoServerCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetYCrop(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetScbar(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ShowScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ShowQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ShowCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetCompress(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 SetScaleNState(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetQualityState(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetCompressState(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 SetZYWRLEState(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 2008-09-14 14:32:53.000000000 -0400 @@ -5,38 +5,51 @@ .\" Copyright (C) 1998 Marcus.Brinkmann@ruhr-uni-bochum.de .\" Copyright (C) 2000,2001 Red Hat, Inc. .\" Copyright (C) 2001-2003 Constantin Kaplinsky +.\" Copyright (C) 2006-2008 Karl J. Runge .\" .\" 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" +.TH ssvncviewer 1 "August 2008" "" "SSVNC" .SH NAME -vncviewer \- an X viewer client for VNC +ssvncviewer \- an X viewer client for VNC .SH SYNOPSIS -.B vncviewer +.B ssvncviewer .RI [\| options \|] .RI [\| host \|][\| :display \|] .br -.B vncviewer +.B ssvncviewer .RI [\| options \|] .RI [\| host \|][\| ::port \|] .br -.B vncviewer +.B ssvncviewer +.RI [\| options \|] +.RI exec=[\| cmd+args... \|] +.br +.B ssvncviewer +.RI [\| options \|] +.RI /path/to/unix/socket +.br +.B ssvncviewer .RI [\| options \|] .IR \-listen .RI [\| display \|] .br -.B vncviewer +.B ssvncviewer .IR \-help .br .SH DESCRIPTION -.B vncviewer +.B ssvncviewer 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 +as \fBXvnc\fR, WinVNC, or \fBx11vnc\fR, allowing you to control desktop environment of a different machine. +ssvncviewer is an enhanced version of the tightvnc unix viewer that can +take advantage of features in the \fBx11vnc\fR and UltraVNC VNC servers. +See below for the description of these features. + You can use F8 to display a pop\-up utility menu. Press F8 twice to pass single F8 to the remote side. .SH OPTIONS @@ -168,6 +181,227 @@ \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 and ZYWRLE encodings are now supported. +.TP +Note: F9 is shortcut to Toggle FullScreen mode. +.TP +Note: In -listen mode set the env var. SSVNC_MULTIPLE_LISTEN=1 +to allow more than one incoming VNC server at a time. +This is the same as -multilisten described below. Set +SSVNC_MULTIPLE_LISTEN=MAX:n to allow no more than "n" +simultaneous reverse connections. +.TP +Note: If the host:port is specified as "exec=command args..." +then instead of making a TCP/IP socket connection to the +remote VNC server, "command args..." is executed and the +viewer is attached to its stdio. This enables tunnelling +established via an external command, e.g. an stunnel(8) +that does not involve a listening socket. +This mode does not work for -listen reverse connections. +.TP +Note: If the host:port contains a '/' it is interpreted as a +unix-domain socket (AF_LOCAL insead of AF_INET) +.TP +\fB\-multilisten\fR +As in -listen (reverse connection listening) except +allow more than one incoming VNC server to be connected +at a time. The default for -listen of only one at a +time tries to play it safe by not allowing anyone on +the network to put (many) desktops on your screen over +a long window of time. Use -multilisten for no limit. +.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\fR \fIstr\fR +Useful for logging into x11vnc in \fB\-unixpw\fR 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 \fB\-unixpw\fR 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-repeater\fR \fIstr\fR +This is for use with UltraVNC repeater proxy described +here: http://www.uvnc.com/addons/repeater.html. The "str" +is the ID string to be sent to the repeater. E.g. ID:1234 +It can also be the hostname and port or display of the VNC +server, e.g. 12.34.56.78:0 or snoopy.com:1. Note that when +using -repeater, the host:dpy on the cmdline is the repeater +server, NOT the VNC server. The repeater will connect you. + +Example: vncviewer ... -repeater ID:3333 repeat.host:5900 + +Example: vncviewer ... -repeater vhost:0 repeat.host:5900 + +Use, e.g., '-repeater SCIII=ID:3210' if the repeater is a +Single Click III (SSL) repeater (repeater_SSL.exe) and you +are passing the SSL part of the connection through stunnel, socat, etc. +This way the magic UltraVNC string 'testB' needed to work with the +repeater is sent to it. +.TP +\fB-rfbversion\fR \fIstr\fR +Set the advertised RFB version. E.g.: -rfbversion 3.6 For some +servers, e.g. UltraVNC this needs to be done. +.TP +\fB-ultradsm\fR +UltraVNC has symmetric private encryption DSM plugins. See +http://www.uvnc.com/features/encryption.html. It is assumed +you are using a unix program (e.g. our ultravnc_dsm_helper) to +encrypt and decrypt the UltraVNC DSM stream. IN ADDITION TO +THAT supply -ultradsm to tell THIS viewer to modify the RFB +data sent so as to work with the UltraVNC Server. For some +reason, each RFB msg type must be sent twice under DSM. +.TP +\fB-env\fR \fIVAR=VALUE\fR +To save writing a shell script to set environment +variables, specify as many as you need on the command line. For example, +-env SSVNC_MULTIPLE_LISTEN=MAX:5 -env EDITOR=vi +.TP +\fB\-printres\fR +Print out the Ssvnc X resources (appdefaults) and +then exit. You can save them to a file and customize them (e.g. the +keybindings and Popup menu) Then point to the file via +XENVIRONMENT or XAPPLRESDIR. +.TP +\fB New Popup actions:\fR + + ViewOnly: ~ -viewonly + Disable Bell: ~ -nobell + Cursor Shape: ~ -nocursorshape + X11 Cursor: ~ -x11cursor + Cursor Alphablend: ~ -alpha + Toggle Tight/ZRLE: ~ -encodings ... + Toggle ZRLE/ZYWRLE: ~ -encodings zywrle... + Quality Level ~ -quality (both Tight and ZYWRLE) + Compress Level ~ -compresslevel + Disable JPEG: ~ -nojpeg (Tight) + Full Color ~ as many colors as local screen allows. + Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes. + 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 + Set Y Crop (y-max) ~ -ycrop + Set Scrollbar Width ~ -sbwidth + + UltraVNC Extensions: + + Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. + Text Chat Ultravnc ext. Do Text Chat. + File Transfer Ultravnc ext. File xfer via Java helper. + Single Window Ultravnc ext. Grab a single window. + (click on the window you want). + Disable Remote Input Ultravnc ext. Try to prevent input and + viewing of monitor at physical display. + + 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. @@ -238,6 +472,15 @@ \-quality and \-nojpeg options above). Tight encoding is usually the best choice for low\-bandwidth network environments (e.g. slow modem connections). +.TP +.B ZRLE +The SSVNC viewer has ported the RealVNC (www.realvnc.com) ZRLE encoding +to the unix tightvnc viewer. +.TP +.B ZYWRLE +The SSVNC viewer has ported the Hitachi lossy wavelet based ZRLE +encoding from http://mobile.hitachi-system.co.jp/publications/ZYWRLE/ +to the unix tightvnc viewer. .SH RESOURCES X resources that \fBvncviewer\fR knows about, aside from the normal Xt resources, are as follows: @@ -364,8 +607,8 @@ .B %R remote TCP port number. .SH SEE ALSO -\fBvncserver\fR(1), \fBXvnc\fR(1), \fBvncpasswd\fR(1), -\fBvncconnect\fR(1), \fBssh\fR(1) +\fBvncserver\fR(1), \fBx11vnc\fR(1), \fBssvnc\fR(1), \fBXvnc\fR(1), \fBvncpasswd\fR(1), +\fBvncconnect\fR(1), \fBssh\fR(1), http://www.karlrunge.com/x11vnc, http://www.karlrunge.com/x11vnc/ssvnc.html .SH AUTHORS Original VNC was developed in AT&T Laboratories Cambridge. TightVNC additions was implemented by Constantin Kaplinsky. Many other people @@ -380,3 +623,5 @@ Tim Waugh , .br Constantin Kaplinsky +.br +Karl Runge 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 2008-02-17 10:34:45.000000000 -0500 @@ -0,0 +1,616 @@ +/* + * 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); \ + } \ + } + +#if defined(__sparc) || defined(__sparc__) || defined(__ppc__) || defined(__POWERPC__) || defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) +#define IS_BIG_ENDIAN 1 +#else +#define IS_BIG_ENDIAN 0 +#endif + +#if DO_ZYWRLE + +#define ENDIAN_LITTLE 0 +#define ENDIAN_BIG 1 +#define ENDIAN_NO 2 +#if IS_BIG_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_BIG +#else +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#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 +#define __RFB_CONCAT3E(a,b,c) CONCAT3E(a,b,c) +#define __RFB_CONCAT2E(a,b) CONCAT2E(a,b) +#undef CPIXEL +#if REALBPP != BPP +#if UNCOMP == 0 +#define CPIXEL REALBPP +#elif UNCOMP>0 +#define CPIXEL CONCAT2E(REALBPP,Down) +#else +#define CPIXEL CONCAT2E(REALBPP,Up) +#endif +#endif +#define PIXEL_T CARDBPP +#if BPP!=8 +#define ZYWRLE_DECODE 1 +#include "zywrletemplate.c" +#endif +#undef CPIXEL + +#endif /* DO_ZYWRLE */ + +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 BPP == 32 && IS_BIG_ENDIAN +# define UncompressCPixel(p) ( (*p << myFormat.redShift) | (*(p+1) << myFormat.greenShift) | (*(p+2) << myFormat.blueShift) ) +# else +# if UNCOMP>0 +# define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)>>UNCOMP) +# else +# define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)<<(-(UNCOMP))) +# endif +# endif +#else +# define UncompressCPixel(pointer) (*(CARDBPP*)pointer) +#endif + +extern XImage *image; +extern int skip_maybe_sync; + +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 * BPP/8) { + if(frameBuffer) { + free(frameBuffer); + } + frameBufferLen = w * h * BPP/8 * 2; + frameBuffer = (unsigned char *) malloc(frameBufferLen); + } + +zywrle_top: + type = *buffer; + buffer++; + switch(type) { + case 0: /* raw */ + { +#if DO_ZYWRLE && BPP != 8 + if (zywrle_level > 0 && !(zywrle_level & 0x80) ) { + zywrle_level |= 0x80; + goto zywrle_top; + } else +#endif + { +#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; + } + } + +#if DO_ZYWRLE && BPP != 8 + if (zywrle_level & 0x80) { + int th, tx; + int widthInBytes = w * BPP / 8; + int scrWidthInBytes; + char *scr, *buf; + static CARDBPP *ptmp = NULL; + static int ptmp_len = 0; + + if (w * h > ptmp_len) { + ptmp_len = w * h; + if (ptmp_len < rfbZRLETileWidth*rfbZRLETileHeight) { + ptmp_len = rfbZRLETileWidth*rfbZRLETileHeight; + } + if (ptmp) { + free(ptmp); + } + ptmp = (CARDBPP *) malloc(ptmp_len * sizeof(CARDBPP)); + } + + zywrle_level &= 0x7F; + // Reverse copy: screen to buf/ptmp: + // make this CopyDataFromScreen() or something. + if (!appData.useBGR565) { + scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8; + scr = image->data + y * scrWidthInBytes + x * myFormat.bitsPerPixel / 8; + buf = (char *) ptmp; + + for (th = 0; th < h; th++) { + memcpy(buf, scr, widthInBytes); + buf += widthInBytes; + scr += scrWidthInBytes; + } + } else { + scrWidthInBytes = si.framebufferWidth * 4; + scr = image->data + y * scrWidthInBytes + x * 4; + buf = (char *) ptmp; + + for (th = 0; th < h; th++) { + for (tx = 0; tx < w; tx++) { + unsigned long pix = *((unsigned int *)scr + tx); + unsigned int r1 = (pix & 0xff0000) >> 16; + unsigned int g1 = (pix & 0x00ff00) >> 8; + unsigned int b1 = (pix & 0x0000ff) >> 0; + int r2, g2, b2, idx; + int rok = 0, gok = 0, bok = 0, is0, sh = 10; + r2 = (31 * r1)/255; + g2 = (63 * g1)/255; + b2 = (31 * b1)/255; + for (is0 = 0; is0 < sh; is0++) { + int is, i, t; + for (i = 0; i < 2; i++) { + if (i == 0) { + is = -is0; + } else { + is = +is0; + } + if (!rok) { + t = r2 + is; + if (r1 == (255 * t)/31) { + r2 = t; rok = 1; + } + } + if (!gok) { + t = g2 + is; + if (g1 == (255 * t)/63) { + g2 = t; gok = 1; + } + } + if (!bok) { + t = b2 + is; + if (b1 == (255 * t)/31) { + b2 = t; bok = 1; + } + } + } + if (rok && gok && bok) { + break; + } + } + idx = (r2 << 11) | (g2 << 5) | (b2 << 0); + *((CARDBPP *)buf + tx) = (CARDBPP) idx; + } + buf += widthInBytes; + scr += scrWidthInBytes; + } + } + ZYWRLE_SYNTHESIZE((PIXEL_T *)ptmp, (PIXEL_T *)ptmp, w, h, w, zywrle_level, zywrleBuf ); + skip_maybe_sync = 1; + + if (appData.yCrop > 0) { + skip_maybe_sync = 0; + } + CopyDataToScreen((char *)ptmp, x, y, w, h); + + } +#endif + + return buffer-buffer_copy; +} + +#undef CARDBPP +#undef CARDREALBPP +#undef HandleZRLE +#undef HandleZRLETile +#undef UncompressCPixel +#undef REALBPP + +#undef UNCOMP + +#undef FillRectangle +#undef IS_BIG_ENDIAN 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 2008-02-15 23:33:13.000000000 -0500 @@ -0,0 +1,824 @@ + +/******************************************************************** + * * + * 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. + ********************************************************************/ + +/* Change Log: + V0.02 : 2008/02/04 : Fix mis encode/decode when width != scanline + (Thanks Johannes Schindelin, author of LibVNC + Server/Client) + V0.01 : 2007/02/06 : Initial release +*/ + +/* #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 < height / s; y++) { + for (x = 0; x < width / s; x++) { + /* + these are same following code. + pH[x] = pH[x] / (~pM[x]+1) * (~pM[x]+1); + ( round pH[x] with pM[x] bit ) + '&' operator isn't 'round' but is 'floor'. + So, we must offset when pH[x] is negative. + */ + if (((signed char*)pH)[0] & 0x80) + ((signed char*)pH)[0] += ~((signed char*)pM)[0]; + if (((signed char*)pH)[1] & 0x80) + ((signed char*)pH)[1] += ~((signed char*)pM)[1]; + if (((signed char*)pH)[2] & 0x80) + ((signed char*)pH)[2] += ~((signed char*)pM)[2]; + *pH &= *pM; + pH += s; + } + pH += (s-1)*width; + } + } +} +# else +/* + Type B:Non liner quantization filter. + + Coefficients have Gaussian curve and smaller value which is + large part of coefficients isn't more important than larger value. + So, I use filter of Non liner quantize/dequantize table. + In general, Non liner quantize formula is explained as following. + + y=f(x) = sign(x)*round( ((abs(x)/(2^7))^ r )* 2^(bo-1) )*2^(8-bo) + x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi) + ( r:power coefficient bi:effective MSB in input bo:effective MSB in output ) + + r < 1.0 : Smaller value is more important than larger value. + r > 1.0 : Larger value is more important than smaller value. + r = 1.0 : Liner quantization which is same with EZW style. + + r = 0.75 is famous non liner quantization used in MP3 audio codec. + In contrast to audio data, larger value is important in wavelet coefficients. + So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ). + + As compared with EZW style liner quantization, this filter tended to be + more sharp edge and be more compression rate but be more blocking noise and be less quality. + Especially, the surface of graphic objects has distinguishable noise in middle quality mode. + + We need only quantized-dequantized(filtered) value rather than quantized value itself + because all values are packed or palette-lized in later ZRLE section. + This lead us not to need to modify client decoder when we change + the filtering procedure in future. + Client only decodes coefficients given by encoder. +*/ +static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l) +{ + int r, s; + int x, y; + int* pH; + const signed char** pM; + + pM = zywrleParam[level-1][l]; + s = 2<>1; + if (r & 0x02) + pH += (s>>1)*width; + for (y = 0; y < height / s; y++) { + for (x = 0; x < width / s; x++) { + ((signed char*)pH)[0] = pM[0][((unsigned char*)pH)[0]]; + ((signed char*)pH)[1] = pM[1][((unsigned char*)pH)[1]]; + ((signed char*)pH)[2] = pM[2][((unsigned char*)pH)[2]]; + pH += s; + } + pH += (s-1)*width; + } + } +} +# endif + +static InlineX void Wavelet(int* pBuf, int width, int height, int level) +{ + int l, s; + int* pTop; + int* pEnd; + + for (l = 0; l < level; l++) { + pTop = pBuf; + pEnd = pBuf+height*width; + s = width<= 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 INC_PTR(data) \ + data++; \ + if( data-pData >= (w+uw) ){ \ + data += scanline-(w+uw); \ + pData = data; \ + } + +#define ZYWRLE_TRANSFER_COEFF(pBuf,data,r,w,h,scanline,level,TRANS) \ + pH = pBuf; \ + s = 2<>1; \ + if (r & 0x02) \ + pH += (s>>1)*w; \ + pEnd = pH+h*w; \ + while (pH < pEnd) { \ + pLine = pH+w; \ + while (pH < pLine) { \ + TRANS \ + INC_PTR(data) \ + pH += s; \ + } \ + pH += (s-1)*w; \ + } + +#define ZYWRLE_PACK_COEFF(pBuf,data,r,width,height,scanline,level) \ + ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_COEFF(pH,R,G,B);ZYWRLE_SAVE_PIXEL(data,R,G,B);) + +#define ZYWRLE_UNPACK_COEFF(pBuf,data,r,width,height,scanline,level) \ + ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,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 = pBuf + (w+uw)*(h+uh); \ + while (pTop < pEnd) { \ + TRANS \ + INC_PTR(data) \ + pTop++; \ + } + +#define ZYWRLE_LOAD_UNALIGN(data,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 +1035,8 @@ rfbFileDownloadDataMsg fdd; rfbFileUploadCancelMsg fuc; rfbFileDownloadFailedMsg fdf; + rfbRestartConnectionMsg rc; + rfbTextChatMsg tc; } rfbServerToClientMsg; @@ -1221,6 +1290,41 @@ #define sz_rfbFileCreateDirRequestMsg 4 +/* ultra */ +typedef struct _rfbSetScaleMsg { + CARD8 type; /* always rfbSetScale */ + CARD8 scale; /* Scale value 1server messages. */ @@ -1241,4 +1345,9 @@ rfbFileDownloadCancelMsg fdc; rfbFileUploadFailedMsg fuf; rfbFileCreateDirRequestMsg fcdr; + rfbSetScaleMsg ssc; + rfbPalmVNCSetScaleFactorMsg pssf; + rfbSetServerInputMsg sim; + rfbSetSWMsg sw; + rfbTextChatMsg tc; } rfbClientToServerMsg;