diff options
Diffstat (limited to 'x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch')
-rw-r--r-- | x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch | 24370 |
1 files changed, 0 insertions, 24370 deletions
diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch deleted file mode 100644 index e37dd31..0000000 --- a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch +++ /dev/null @@ -1,24370 +0,0 @@ -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:\ - <Enter>: SelectionToVNC()\n\ - <Leave>: 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:\ - <Key>F8: ShowPopup()\n\ -+ <Key>F9: ToggleFullScreen()\n\ - <ButtonPress>: SendRFBEvent()\n\ - <ButtonRelease>: SendRFBEvent()\n\ - <Motion>: SendRFBEvent()\n\ - <KeyPress>: SendRFBEvent()\n\ - <KeyRelease>: SendRFBEvent() - -+*viewport.horizontal.translations: #override\n\ -+ <KeyPress>Right: StartScroll(Forward)\n\ -+ <KeyRelease>Right: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>Left: StartScroll(Backward)\n\ -+ <KeyRelease>Left: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>Next: StartScroll(Forward)\n\ -+ <KeyRelease>Next: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>Prior: StartScroll(Backward)\n\ -+ <KeyRelease>Prior: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>z: StartScroll(Forward)\n\ -+ <KeyRelease>z: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>a: StartScroll(Backward)\n\ -+ <KeyRelease>a: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>f: StartScroll(Forward)\n\ -+ <KeyRelease>f: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>b: StartScroll(Backward)\n\ -+ <KeyRelease>b: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>Down: StartScroll(Forward)\n\ -+ <KeyRelease>Down: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>Up: StartScroll(Backward)\n\ -+ <KeyRelease>Up: NotifyScroll(FullLength) EndScroll() -+ -+*viewport.vertical.translations: #override\n\ -+ <KeyPress>Down: StartScroll(Forward)\n\ -+ <KeyRelease>Down: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>Up: StartScroll(Backward)\n\ -+ <KeyRelease>Up: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>Next: StartScroll(Forward)\n\ -+ <KeyRelease>Next: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>Prior: StartScroll(Backward)\n\ -+ <KeyRelease>Prior: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>z: StartScroll(Forward)\n\ -+ <KeyRelease>z: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>a: StartScroll(Backward)\n\ -+ <KeyRelease>a: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>f: StartScroll(Forward)\n\ -+ <KeyRelease>f: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>b: StartScroll(Backward)\n\ -+ <KeyRelease>b: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>Right: StartScroll(Forward)\n\ -+ <KeyRelease>Right: NotifyScroll(FullLength) EndScroll()\n\ -+ <KeyPress>Left: StartScroll(Backward)\n\ -+ <KeyRelease>Left: NotifyScroll(FullLength) EndScroll() -+ - - ! - ! Dialog boxes - ! - - *serverDialog.dialog.label: VNC server: -+ - *serverDialog.dialog.value: -+ - *serverDialog.dialog.value.translations: #override\n\ -- <Key>Return: ServerDialogDone() -+ <Key>Return: ServerDialogDone() -+ -+*ycropDialog.dialog.label: Y Crop (max-height in pixels): -+ -+*ycropDialog.dialog.value: -+ -+*ycropDialog.dialog.value.translations: #override\n\ -+ <Key>Return: YCropDialogDone() -+ -+*scbarDialog.dialog.label: Scroll Bars width: -+ -+*scbarDialog.dialog.value: -+ -+*scbarDialog.dialog.value.translations: #override\n\ -+ <Key>Return: ScbarDialogDone() -+ -+*scaleDialog.dialog.label: Integer n for 1/n server scaling: -+ -+*scaleDialog.dialog.value: -+ -+*scaleDialog.dialog.value.translations: #override\n\ -+ <Key>Return: ScaleDialogDone() - - *passwordDialog.dialog.label: Password: -+ - *passwordDialog.dialog.value: -+ - *passwordDialog.dialog.value.AsciiSink.echo: False -+ - *passwordDialog.dialog.value.translations: #override\n\ -- <Key>Return: PasswordDialogDone() -+ <Key>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 <Message>WM_PROTOCOLS: HidePopup() -+ - *popup.buttonForm.translations: #override\n\ -- <KeyPress>: SendRFBEvent() HidePopup() -+ <KeyPress>: SendRFBEvent() HidePopup() - - - ! - ! Popup buttons - ! - --*popupButtonCount: 8 -+*popupButtonCount: 38 -+ -+*popupButtonBreak: 19 - - *popup*button1.label: Dismiss popup -+ - *popup*button1.translations: #override\n\ -- <Btn1Down>,<Btn1Up>: HidePopup() -+ <Btn1Down>,<Btn1Up>: HidePopup() - - *popup*button2.label: Quit viewer -+ - *popup*button2.translations: #override\n\ -- <Btn1Down>,<Btn1Up>: Quit() -+ <Btn1Down>,<Btn1Up>: Quit() -+ -+*popup*button3.label: Full screen (also F9) - --*popup*button3.label: Full screen - *popup*button3.type: toggle -+ - *popup*button3.translations: #override\n\ -- <Visible>: SetFullScreenState()\n\ -- <Btn1Down>,<Btn1Up>: toggle() HidePopup() ToggleFullScreen() -+ <Visible>: SetFullScreenState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleFullScreen() HidePopup() - - *popup*button4.label: Clipboard: local -> remote -+ - *popup*button4.translations: #override\n\ -- <Btn1Down>,<Btn1Up>: SelectionToVNC(always) HidePopup() -+ <Btn1Down>,<Btn1Up>: SelectionToVNC(always) HidePopup() - - *popup*button5.label: Clipboard: local <- remote -+ - *popup*button5.translations: #override\n\ -- <Btn1Down>,<Btn1Up>: SelectionFromVNC(always) HidePopup() -+ <Btn1Down>,<Btn1Up>: SelectionFromVNC(always) HidePopup() - - *popup*button6.label: Request refresh -+ - *popup*button6.translations: #override\n\ -- <Btn1Down>,<Btn1Up>: SendRFBEvent(fbupdate) HidePopup() -+ <Btn1Down>,<Btn1Up>: SendRFBEvent(fbupdate) HidePopup() - - *popup*button7.label: Send ctrl-alt-del -+ - *popup*button7.translations: #override\n\ -- <Btn1Down>,<Btn1Up>: SendRFBEvent(keydown,Control_L)\ -- SendRFBEvent(keydown,Alt_L)\ -- SendRFBEvent(key,Delete)\ -- SendRFBEvent(keyup,Alt_L)\ -- SendRFBEvent(keyup,Control_L)\ -- HidePopup() -+ <Btn1Down>,<Btn1Up>: SendRFBEvent(keydown,Control_L) SendRFBEvent(keydown,Alt_L) SendRFBEvent(key,Delete) SendRFBEvent(keyup,Alt_L) SendRFBEvent(keyup,Control_L) HidePopup() - - *popup*button8.label: Send F8 -+ - *popup*button8.translations: #override\n\ -- <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup() -+ <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup() -+ -+*popup*button9.label: Send F9 -+ -+*popup*button9.translations: #override\n\ -+ <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F9) HidePopup() -+ -+*popup*button10.label: ViewOnly -+ -+*popup*button10.type: toggle -+ -+*popup*button10.translations: #override\n\ -+ <Visible>: SetViewOnlyState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleViewOnly() HidePopup() -+ -+*popup*button11.label: Disable Bell -+ -+*popup*button11.type: toggle -+ -+*popup*button11.translations: #override\n\ -+ <Visible>: SetBellState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleBell() HidePopup() -+ -+*popup*button12.label: Cursor Shape -+ -+*popup*button12.type: toggle -+ -+*popup*button12.translations: #override\n\ -+ <Visible>: SetCursorShapeState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleCursorShape() HidePopup() -+ -+*popup*button13.label: X11 Cursor -+ -+*popup*button13.type: toggle -+ -+*popup*button13.translations: #override\n\ -+ <Visible>: SetX11CursorState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleX11Cursor() HidePopup() -+ -+*popup*button14.label: Cursor Alphablend -+ -+*popup*button14.type: toggle -+ -+*popup*button14.translations: #override\n\ -+ <Visible>: SetCursorAlphaState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleCursorAlpha() HidePopup() -+ -+*popup*button15.label: Toggle Tight/ZRLE -+ -+*popup*button15.type: toggle -+ -+*popup*button15.translations: #override\n\ -+ <Visible>: SetZRLEState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleTightZRLE() HidePopup() -+ -+*popup*button16.label: Toggle ZRLE/ZYWRLE -+ -+*popup*button16.type: toggle -+ -+*popup*button16.translations: #override\n\ -+ <Visible>: SetZYWRLEState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleZRLEZYWRLE() HidePopup() -+ -+*popup*button17.label: Quality Level -+ -+*popup*button17.translations: #override\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() ShowQuality() -+ -+*popup*button18.label: Compress Level -+ -+*popup*button18.translations: #override\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() ShowCompress() -+ -+*popup*button19.label: Disable JPEG -+ -+*popup*button19.type: toggle -+ -+*popup*button19.translations: #override\n\ -+ <Visible>: SetNOJPEGState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleJPEG() HidePopup() -+ -+*popup*button20.label: Full Color -+ -+*popup*button20.type: toggle -+ -+*popup*button20.translations: #override\n\ -+ <Visible>: SetFullColorState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleFullColor() HidePopup() -+ -+*popup*button21.label: Grey Scale (16 & 8-bpp) -+ -+*popup*button21.type: toggle -+ -+*popup*button21.translations: #override\n\ -+ <Visible>: SetGreyScaleState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleGreyScale() HidePopup() -+ -+*popup*button22.label: 16 bit color (BGR565) -+ -+*popup*button22.type: toggle -+ -+*popup*button22.translations: #override\n\ -+ <Visible>: Set16bppState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle16bpp() HidePopup() -+ -+*popup*button23.label: 8 bit color (BGR233) -+ -+*popup*button23.type: toggle -+ -+*popup*button23.translations: #override\n\ -+ <Visible>: Set8bppState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle8bpp() HidePopup() -+ -+*popup*button24.label: - 256 colors -+ -+*popup*button24.type: toggle -+ -+*popup*button24.translations: #override\n\ -+ <Visible>: Set256ColorsState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle256Colors() HidePopup() -+ -+*popup*button25.label: - 64 colors -+ -+*popup*button25.type: toggle -+ -+*popup*button25.translations: #override\n\ -+ <Visible>: Set64ColorsState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle64Colors() HidePopup() -+ -+*popup*button26.label: - 8 colors -+ -+*popup*button26.type: toggle -+ -+*popup*button26.translations: #override\n\ -+ <Visible>: Set8ColorsState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle8Colors() HidePopup() -+ -+*popup*button27.label: Set Y Crop (y-max) -+ -+*popup*button27.translations: #override\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() SetYCrop() -+ -+*popup*button28.label: Set Scrollbar Width -+ -+*popup*button28.translations: #override\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() SetScbar() -+ -+*popup*button29.label: UltraVNC Extensions: -+ -+*popup*button29.translations: #override\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() -+ -+*popup*button30.label: - Set 1/n Server Scale -+ -+*popup*button30.translations: #override\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() ShowScaleN() -+ -+*popup*button31.label: - Text Chat -+ -+*popup*button31.type: toggle -+ -+*popup*button31.translations: #override\n\ -+ <Visible>: SetTextChatState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleTextChat() HidePopup() -+ -+*popup*button32.label: - File Transfer -+ -+*popup*button32.type: toggle -+ -+*popup*button32.translations: #override\n\ -+ <Visible>: SetFileXferState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleFileXfer() HidePopup() -+ -+*popup*button33.label: - Single Window -+ -+*popup*button33.type: toggle -+ -+*popup*button33.translations: #override\n\ -+ <Visible>: SetSingleWindowState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleSingleWindow() HidePopup() -+ -+*popup*button34.label: - Disable Remote Input -+ -+*popup*button34.type: toggle -+ -+*popup*button34.translations: #override\n\ -+ <Visible>: SetServerInputState()\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleServerInput() HidePopup() -+ -+*popup*button35.label: -+ -+*popup*button36.label: -+ -+*popup*button37.label: -+ -+*popup*button38.label: -+ -+*scaleN*button0.label: Dismiss -+ -+*scaleN*button0.translations: #override\n\ -+ <Btn1Down>,<Btn1Up>: HideScaleN() -+ -+*scaleN*button1.label: 1/1 -+ -+*scaleN*button1.translations: #override\n\ -+ <Visible>: SetScaleNState(1)\n\ -+ <Btn1Down>,<Btn1Up>: SetScaleN(1) HideScaleN() -+ -+*scaleN*button2.label: 1/2 -+ -+*scaleN*button2.translations: #override\n\ -+ <Visible>: SetScaleNState(2)\n\ -+ <Btn1Down>,<Btn1Up>: SetScaleN(2) HideScaleN() -+ -+*scaleN*button3.label: 1/3 -+ -+*scaleN*button3.translations: #override\n\ -+ <Visible>: SetScaleNState(3)\n\ -+ <Btn1Down>,<Btn1Up>: SetScaleN(3) HideScaleN() -+ -+*scaleN*button4.label: 1/4 -+ -+*scaleN*button4.translations: #override\n\ -+ <Visible>: SetScaleNState(4)\n\ -+ <Btn1Down>,<Btn1Up>: SetScaleN(4) HideScaleN() -+ -+*scaleN*button5.label: 1/5 -+ -+*scaleN*button5.translations: #override\n\ -+ <Visible>: SetScaleNState(5)\n\ -+ <Btn1Down>,<Btn1Up>: SetScaleN(5) HideScaleN() -+ -+*scaleN*button6.label: Other -+ -+*scaleN*button6.translations: #override\n\ -+ <Visible>: SetScaleNState(6)\n\ -+ <Btn1Down>,<Btn1Up>: HideScaleN() DoServerScale() -+ -+*quality*buttonD.label: Dismiss -+ -+*quality*buttonD.translations: #override\n\ -+ <Btn1Down>,<Btn1Up>: HideQuality() -+ -+*quality*button0.label: 0 -+ -+*quality*button0.type: toggle -+ -+*quality*button0.translations: #override\n\ -+ <Visible>: SetQualityState(0)\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(0) HideQuality() -+ -+*quality*button1.label: 1 -+ -+*quality*button1.type: toggle -+ -+*quality*button1.translations: #override\n\ -+ <Visible>: SetQualityState(1)\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(1) HideQuality() -+ -+*quality*button2.label: 2 -+ -+*quality*button2.type: toggle -+ -+*quality*button2.translations: #override\n\ -+ <Visible>: SetQualityState(2)\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(2) HideQuality() -+ -+*quality*button3.label: 3 -+ -+*quality*button3.type: toggle -+ -+*quality*button3.translations: #override\n\ -+ <Visible>: SetQualityState(3)\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(3) HideQuality() -+ -+*quality*button4.label: 4 -+ -+*quality*button4.type: toggle -+ -+*quality*button4.translations: #override\n\ -+ <Visible>: SetQualityState(4)\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(4) HideQuality() -+ -+*quality*button5.label: 5 -+ -+*quality*button5.type: toggle -+ -+*quality*button5.translations: #override\n\ -+ <Visible>: SetQualityState(5)\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(5) HideQuality() -+ -+*quality*button6.label: 6 -+ -+*quality*button6.type: toggle -+ -+*quality*button6.translations: #override\n\ -+ <Visible>: SetQualityState(6)\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(6) HideQuality() -+ -+*quality*button7.label: 7 -+ -+*quality*button7.type: toggle -+ -+*quality*button7.translations: #override\n\ -+ <Visible>: SetQualityState(7)\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(7) HideQuality() -+ -+*quality*button8.label: 8 -+ -+*quality*button8.type: toggle -+ -+*quality*button8.translations: #override\n\ -+ <Visible>: SetQualityState(8)\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(8) HideQuality() -+ -+*quality*button9.label: 9 -+ -+*quality*button9.type: toggle -+ -+*quality*button9.translations: #override\n\ -+ <Visible>: SetQualityState(9)\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(9) HideQuality() -+ -+*compress*buttonD.label: Dismiss -+ -+*compress*buttonD.translations: #override\n\ -+ <Btn1Down>,<Btn1Up>: HideCompress() -+ -+*compress*button0.label: 0 -+ -+*compress*button0.translations: #override\n\ -+ <Visible>: SetCompressState(0)\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(0) HideCompress() -+ -+*compress*button1.label: 1 -+ -+*compress*button1.translations: #override\n\ -+ <Visible>: SetCompressState(1)\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(1) HideCompress() -+ -+*compress*button2.label: 2 -+ -+*compress*button2.translations: #override\n\ -+ <Visible>: SetCompressState(2)\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(2) HideCompress() -+ -+*compress*button3.label: 3 -+ -+*compress*button3.translations: #override\n\ -+ <Visible>: SetCompressState(3)\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(3) HideCompress() -+ -+*compress*button4.label: 4 -+ -+*compress*button4.translations: #override\n\ -+ <Visible>: SetCompressState(4)\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(4) HideCompress() -+ -+*compress*button5.label: 5 -+ -+*compress*button5.translations: #override\n\ -+ <Visible>: SetCompressState(5)\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(5) HideCompress() -+ -+*compress*button6.label: 6 -+ -+*compress*button6.translations: #override\n\ -+ <Visible>: SetCompressState(6)\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(6) HideCompress() -+ -+*compress*button7.label: 7 -+ -+*compress*button7.translations: #override\n\ -+ <Visible>: SetCompressState(7)\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(7) HideCompress() -+ -+*compress*button8.label: 8 -+ -+*compress*button8.translations: #override\n\ -+ <Visible>: SetCompressState(8)\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(8) HideCompress() -+ -+*compress*button9.label: 9 -+ -+*compress*button9.translations: #override\n\ -+ <Visible>: SetCompressState(9)\n\ -+ <Btn1Down>,<Btn1Up>: 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 2010-04-18 12:39:55.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:\ - <Enter>: SelectionToVNC()\\n\ - <Leave>: SelectionFromVNC()", - -@@ -45,8 +45,60 @@ - "*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\ -+ <KeyPress>Right: StartScroll(Forward)\\n\ -+ <KeyRelease>Right: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>Left: StartScroll(Backward)\\n\ -+ <KeyRelease>Left: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>Next: StartScroll(Forward)\\n\ -+ <KeyRelease>Next: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>Prior: StartScroll(Backward)\\n\ -+ <KeyRelease>Prior: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>z: StartScroll(Forward)\\n\ -+ <KeyRelease>z: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>a: StartScroll(Backward)\\n\ -+ <KeyRelease>a: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>f: StartScroll(Forward)\\n\ -+ <KeyRelease>f: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>b: StartScroll(Backward)\\n\ -+ <KeyRelease>b: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>Down: StartScroll(Forward)\\n\ -+ <KeyRelease>Down: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>Up: StartScroll(Backward)\\n\ -+ <KeyRelease>Up: NotifyScroll(FullLength) EndScroll()", -+ -+ "*viewport.vertical.translations: #override\\n\ -+ <KeyPress>Down: StartScroll(Forward)\\n\ -+ <KeyRelease>Down: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>Up: StartScroll(Backward)\\n\ -+ <KeyRelease>Up: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>Next: StartScroll(Forward)\\n\ -+ <KeyRelease>Next: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>Prior: StartScroll(Backward)\\n\ -+ <KeyRelease>Prior: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>z: StartScroll(Forward)\\n\ -+ <KeyRelease>z: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>a: StartScroll(Backward)\\n\ -+ <KeyRelease>a: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>f: StartScroll(Forward)\\n\ -+ <KeyRelease>f: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>b: StartScroll(Backward)\\n\ -+ <KeyRelease>b: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>Right: StartScroll(Forward)\\n\ -+ <KeyRelease>Right: NotifyScroll(FullLength) EndScroll()\\n\ -+ <KeyPress>Left: StartScroll(Backward)\\n\ -+ <KeyRelease>Left: NotifyScroll(FullLength) EndScroll()", -+ - "*desktop.baseTranslations:\ -- <Key>F8: ShowPopup()\\n\ -+ <KeyPress>F8: ShowPopup()\\n\ -+ <KeyRelease>F8: Noop()\\n\ -+ <KeyPress>F9: ToggleFullScreen()\\n\ -+ <KeyRelease>F9: Noop()\\n\ - <ButtonPress>: SendRFBEvent()\\n\ - <ButtonRelease>: SendRFBEvent()\\n\ - <Motion>: SendRFBEvent()\\n\ -@@ -55,26 +107,137 @@ - - "*serverDialog.dialog.label: VNC server:", - "*serverDialog.dialog.value:", -+ "*serverDialog.dialog.value.width: 150", - "*serverDialog.dialog.value.translations: #override\\n\ - <Key>Return: ServerDialogDone()", - -- "*passwordDialog.dialog.label: Password:", -+ "*userDialog.dialog.label: SSVNC: Enter Username", -+ "*userDialog.dialog.value:", -+ "*userDialog.dialog.value.width: 150", -+ "*userDialog.dialog.value.translations: #override\\n\ -+ <Key>Return: UserDialogDone()", -+ -+ "*scaleDialog.dialog.label: Scale: Enter 'none' (same as '1' or '1.0'),\\na geometry WxH (e.g. 1280x1024), or\\na fraction (e.g. 0.75 or 3/4).\\nUse 'fit' for full screen size.\\nUse 'auto' to match window size.\\nCurrent value:", -+ "*scaleDialog.dialog.value:", -+ "*scaleDialog.dialog.value.translations: #override\\n\ -+ <KeyRelease>Return: ScaleDialogDone()", -+ -+ "*escapeDialog.dialog.label: Escape Keys: Enter a comma separated list of modifier keys to be the\\n" -+ "'escape sequence'. When these keys are held down, the next keystroke is\\n" -+ "interpreted locally to invoke a special action instead of being sent to\\n" -+ "the remote VNC server. In other words, a set of 'Hot Keys'.\\n" -+ "\\n" -+ "To enable or disable this, click on 'Escape Keys: Toggle' in the Popup.\\n" -+ "\\n" -+ "Here is the list of hot-key mappings to special actions:\\n" -+ "\\n" -+ " r: refresh desktop b: toggle bell c: toggle full-color\\n" -+ " f: file transfer x: x11cursor z: toggle Tight/ZRLE\\n" -+ " l: full screen g: graball e: escape keys dialog\\n" -+ " s: scale dialog +: scale up (=) -: scale down (_)\\n" -+ " t: text chat a: alphablend cursor\\n" -+ " V: toggle viewonly Q: quit viewer 1 2 3 4 5 6: UltraVNC scale 1/n\\n" -+ "\\n" -+ " Arrow keys: pan the viewport about 10% for each keypress.\\n" -+ " PageUp / PageDown: pan the viewport by a screenful vertically.\\n" -+ " Home / End: pan the viewport by a screenful horizontally.\\n" -+ " KeyPad Arrow keys: pan the viewport by 1 pixel for each keypress.\\n" -+ " Dragging the Mouse with Button1 pressed also pans the viewport.\\n" -+ " Clicking Mouse Button3 brings up the Popup Menu.\\n" -+ "\\n" -+ "The above mappings are *always* active in ViewOnly mode, unless you set the\\n" -+ "Escape Keys value to 'never'.\\n" -+ "\\n" -+ "x11vnc -appshare hot-keys: x11vnc has a simple application sharing mode\\n" -+ "that enables the viewer-side to move, resize, or raise the remote toplevel\\n" -+ "windows. To enable it, hold down Shift + the Escape Keys and press these:\\n" -+ "\\n" -+ " Arrow keys: move the remote window around in its desktop.\\n" -+ " PageUp/PageDn/Home/End: resize the remote window.\\n" -+ " +/- raise or lower the remote window.\\n" -+ " M or Button1 move win to local position; D or Button3: delete remote win.\\n" -+ "\\n" -+ "If the Escape Keys value below is set to 'default' then a fixed list of\\n" -+ "modifier keys is used. For Unix it is: Alt_L,Super_L and for MacOSX it is\\n" -+ "Control_L,Meta_L. Note: the Super_L key usually has a Windows(TM) Flag.\\n" -+ "Also note the _L and _R mean the key is on the LEFT or RIGHT side of keyboard.\\n" -+ "\\n" -+ "On Unix the default is Alt and Windows keys on Left side of keyboard.\\n" -+ "On MacOSX the default is Control and Command keys on Left side of keyboard.\\n" -+ "\\n" -+ "Example: Press and hold the Alt and Windows keys on the LEFT side of the\\n" -+ "keyboard and then press 'c' to toggle the full-color state. Or press 't'\\n" -+ "to toggle the ultravnc Text Chat window, etc.\\n" -+ "\\n" -+ "To use something besides the default, supply a comma separated list (or a\\n" -+ "single one) from: Shift_L Shift_R Control_L Control_R Alt_L Alt_R Meta_L\\n" -+ "Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch.\\n" -+ "\\n" -+ "Current Escape Keys Value:", -+ "*escapeDialog.dialog.value:", -+ "*escapeDialog.dialog.value.width: 280", -+ "*escapeDialog.dialog.value.translations: #override\\n\ -+ <KeyRelease>Return: EscapeDialogDone()", -+ -+ "*ycropDialog.dialog.label: Y Crop (max-height in pixels):", -+ "*ycropDialog.dialog.value:", -+ "*ycropDialog.dialog.value.translations: #override\\n\ -+ <KeyRelease>Return: YCropDialogDone()", -+ -+ "*scbarDialog.dialog.label: Scroll Bars width:", -+ "*scbarDialog.dialog.value:", -+ "*scbarDialog.dialog.value.translations: #override\\n\ -+ <KeyRelease>Return: ScbarDialogDone()", -+ -+ "*scaleNDialog.dialog.label: Integer n for 1/n server scaling:", -+ "*scaleNDialog.dialog.value:", -+ "*scaleNDialog.dialog.value.translations: #override\\n\ -+ <KeyRelease>Return: ScaleNDialogDone()", -+ -+ "*passwordDialog.dialog.label: SSVNC: Enter Password", - "*passwordDialog.dialog.value:", -+ "*passwordDialog.dialog.value.width: 150", - "*passwordDialog.dialog.value.AsciiSink.echo: False", - "*passwordDialog.dialog.value.translations: #override\\n\ - <Key>Return: PasswordDialogDone()", - -- "*popup.title: TightVNC popup", -+ "*popup.title: SSVNC popup", - "*popup*background: grey", -- "*popup*font: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-*", -- "*popup.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", -+ -+ "*turboVNC.title: TurboVNC", -+ "*turboVNC*background: grey", -+ "*turboVNC*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", -+ "*turboVNC.buttonForm.Command.borderWidth: 0", -+ "*turboVNC.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 <Message>WM_PROTOCOLS: HidePopup()", - "*popup.buttonForm.translations: #override\\n\ - <KeyPress>: SendRFBEvent() HidePopup()", - -- "*popupButtonCount: 8", -+ "*popupButtonCount: 44", -+ "*popupButtonBreak: 22", - - "*popup*button1.label: Dismiss popup", - "*popup*button1.translations: #override\\n\ -@@ -84,7 +247,7 @@ - "*popup*button2.translations: #override\\n\ - <Btn1Down>,<Btn1Up>: Quit()", - -- "*popup*button3.label: Full screen", -+ "*popup*button3.label: Full screen (also F9)", - "*popup*button3.type: toggle", - "*popup*button3.translations: #override\\n\ - <Visible>: SetFullScreenState()\\n\ -@@ -105,16 +268,426 @@ - "*popup*button7.label: Send ctrl-alt-del", - "*popup*button7.translations: #override\\n\ - <Btn1Down>,<Btn1Up>: SendRFBEvent(keydown,Control_L)\ -- SendRFBEvent(keydown,Alt_L)\ -- SendRFBEvent(key,Delete)\ -- SendRFBEvent(keyup,Alt_L)\ -- SendRFBEvent(keyup,Control_L)\ -- HidePopup()", -+ SendRFBEvent(keydown,Alt_L)\ -+ SendRFBEvent(key,Delete)\ -+ SendRFBEvent(keyup,Alt_L)\ -+ SendRFBEvent(keyup,Control_L)\ -+ HidePopup()", - - "*popup*button8.label: Send F8", - "*popup*button8.translations: #override\\n\ - <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup()", - -+ "*popup*button9.label: Send F9", -+ "*popup*button9.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F9) HidePopup()", -+ -+ "*popup*button10.label: ViewOnly", -+ "*popup*button10.type: toggle", -+ "*popup*button10.translations: #override\\n\ -+ <Visible>: SetViewOnlyState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleViewOnly() HidePopup()", -+ -+ "*popup*button11.label: Disable Bell", -+ "*popup*button11.type: toggle", -+ "*popup*button11.translations: #override\\n\ -+ <Visible>: SetBellState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleBell() HidePopup()", -+ -+ "*popup*button12.label: Cursor Shape", -+ "*popup*button12.type: toggle", -+ "*popup*button12.translations: #override\\n\ -+ <Visible>: SetCursorShapeState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleCursorShape() HidePopup()", -+ -+ "*popup*button13.label: X11 Cursor", -+ "*popup*button13.type: toggle", -+ "*popup*button13.translations: #override\\n\ -+ <Visible>: SetX11CursorState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleX11Cursor() HidePopup()", -+ -+ "*popup*button14.label: Cursor Alphablend", -+ "*popup*button14.type: toggle", -+ "*popup*button14.translations: #override\\n\ -+ <Visible>: SetCursorAlphaState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleCursorAlpha() HidePopup()", -+ -+ "*popup*button15.label: Toggle Tight/Hextile", -+ "*popup*button15.type: toggle", -+ "*popup*button15.translations: #override\\n\ -+ <Visible>: SetHextileState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleTightHextile() HidePopup()", -+ -+ "*popup*button16.label: Toggle Tight/ZRLE", -+ "*popup*button16.type: toggle", -+ "*popup*button16.translations: #override\\n\ -+ <Visible>: SetZRLEState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleTightZRLE() HidePopup()", -+ -+ "*popup*button17.label: Toggle ZRLE/ZYWRLE", -+ "*popup*button17.type: toggle", -+ "*popup*button17.translations: #override\\n\ -+ <Visible>: SetZYWRLEState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleZRLEZYWRLE() HidePopup()", -+ -+ "*popup*button18.label: Quality Level", -+ "*popup*button18.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() ShowQuality()", -+ -+ "*popup*button19.label: Compress Level", -+ "*popup*button19.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() ShowCompress()", -+ -+ "*popup*button20.label: Disable JPEG", -+ "*popup*button20.type: toggle", -+ "*popup*button20.translations: #override\\n\ -+ <Visible>: SetNOJPEGState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleJPEG() HidePopup()", -+ -+ "*popup*button21.label: TurboVNC Settings", -+ "*popup*button21.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() ShowTurboVNC()", -+ -+ "*popup*button22.label: Pipeline Updates", -+ "*popup*button22.type: toggle", -+ "*popup*button22.translations: #override\\n\ -+ <Visible>: SetPipelineUpdates()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() TogglePipelineUpdates() HidePopup()", -+ -+ "*popup*button23.label: Full Color", -+ "*popup*button23.type: toggle", -+ "*popup*button23.translations: #override\\n\ -+ <Visible>: SetFullColorState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleFullColor() HidePopup()", -+ -+ "*popup*button24.label: Grey Scale (16 & 8-bpp)", -+ "*popup*button24.type: toggle", -+ "*popup*button24.translations: #override\\n\ -+ <Visible>: SetGreyScaleState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleGreyScale() HidePopup()", -+ -+ "*popup*button25.label: 16 bit color (BGR565)", -+ "*popup*button25.type: toggle", -+ "*popup*button25.translations: #override\\n\ -+ <Visible>: Set16bppState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle16bpp() HidePopup()", -+ -+ "*popup*button26.label: 8 bit color (BGR233)", -+ "*popup*button26.type: toggle", -+ "*popup*button26.translations: #override\\n\ -+ <Visible>: Set8bppState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle8bpp() HidePopup()", -+ -+ "*popup*button27.label: - 256 colors", -+ "*popup*button27.type: toggle", -+ "*popup*button27.translations: #override\\n\ -+ <Visible>: Set256ColorsState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle256Colors() HidePopup()", -+ -+ "*popup*button28.label: - 64 colors", -+ "*popup*button28.type: toggle", -+ "*popup*button28.translations: #override\\n\ -+ <Visible>: Set64ColorsState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle64Colors() HidePopup()", -+ -+ "*popup*button29.label: - 8 colors", -+ "*popup*button29.type: toggle", -+ "*popup*button29.translations: #override\\n\ -+ <Visible>: Set8ColorsState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle8Colors() HidePopup()", -+ -+ "*popup*button30.label: Scale Viewer", -+ "*popup*button30.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() SetScale()", -+ -+ "*popup*button31.label: Escape Keys: Toggle", -+ "*popup*button31.type: toggle", -+ "*popup*button31.translations: #override\\n\ -+ <Visible>: SetEscapeKeysState()\\n\ -+ <Btn1Down>, <Btn1Up>: toggle() ToggleEscapeActive() HidePopup()", -+ -+ "*popup*button32.label: Escape Keys: Help+Set", -+ "*popup*button32.translations: #override\\n\ -+ <Btn1Down>, <Btn1Up>: HidePopup() SetEscapeKeys()", -+ -+ "*popup*button33.label: Set Y Crop (y-max)", -+ "*popup*button33.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() SetYCrop()", -+ -+ "*popup*button34.label: Set Scrollbar Width", -+ "*popup*button34.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() SetScbar()", -+ -+ "*popup*button35.label: XGrabServer", -+ "*popup*button35.type: toggle", -+ "*popup*button35.translations: #override\\n\ -+ <Visible>: SetXGrabState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleXGrab() HidePopup()", -+ -+ "*popup*button36.label: UltraVNC Extensions:", -+ "*popup*button36.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup()", -+ -+ "*popup*button37.label: - Set 1/n Server Scale", -+ "*popup*button37.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() ShowScaleN()", -+ -+ "*popup*button38.label: - Text Chat", -+ "*popup*button38.type: toggle", -+ "*popup*button38.translations: #override\\n\ -+ <Visible>: SetTextChatState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleTextChat() HidePopup()", -+ -+ "*popup*button39.label: - File Transfer", -+ "*popup*button39.type: toggle", -+ "*popup*button39.translations: #override\\n\ -+ <Visible>: SetFileXferState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleFileXfer() HidePopup()", -+ -+ "*popup*button40.label: - Single Window", -+ "*popup*button40.type: toggle", -+ "*popup*button40.translations: #override\\n\ -+ <Visible>: SetSingleWindowState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleSingleWindow() HidePopup()", -+ -+ "*popup*button41.label: - Disable Remote Input", -+ "*popup*button41.type: toggle", -+ "*popup*button41.translations: #override\\n\ -+ <Visible>: SetServerInputState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleServerInput() HidePopup()", -+ -+ "*popup*button42.label: Send Clipboard not Primary", -+ "*popup*button42.type: toggle", -+ "*popup*button42.translations: #override\\n\ -+ <Visible>: SetSendClipboard()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleSendClipboard() HidePopup()", -+ -+ "*popup*button43.label: Send Selection Every time", -+ "*popup*button43.type: toggle", -+ "*popup*button43.translations: #override\\n\ -+ <Visible>: SetSendAlways()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleSendAlways() HidePopup()", -+ -+ "*popup*button44.label: ", -+ -+ "*turboVNC*button0.label: Dismiss", -+ "*turboVNC*button0.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HideTurboVNC()", -+ -+ "*turboVNC*button1.label: High Quality (LAN)", -+ "*turboVNC*button1.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: SetTurboVNC(1)", -+ -+ "*turboVNC*button2.label: Medium Quality", -+ "*turboVNC*button2.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: SetTurboVNC(2)", -+ -+ "*turboVNC*button3.label: Low Quality (WAN)", -+ "*turboVNC*button3.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: SetTurboVNC(3)", -+ -+ "*turboVNC*button4.label: Lossless (Gigabit)", -+ "*turboVNC*button4.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: SetTurboVNC(4)", -+ -+ "*turboVNC*button5.label: Lossless Zlib (WAN)", -+ "*turboVNC*button5.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: SetTurboVNC(5)", -+ -+ "*turboVNC*button6.label: Subsampling:", -+ -+ "*turboVNC*button7.label: - None", -+ "*turboVNC*button7.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: SetTurboVNC(6)", -+ -+ "*turboVNC*button8.label: - 2X", -+ "*turboVNC*button8.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: SetTurboVNC(7)", -+ -+ "*turboVNC*button9.label: - 4X", -+ "*turboVNC*button9.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: SetTurboVNC(8)", -+ -+ "*turboVNC*button10.label: - Gray", -+ "*turboVNC*button10.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: SetTurboVNC(9)", -+ -+ "*turboVNC*button11.label: Lossless Refresh", -+ "*turboVNC*button11.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: SetTurboVNC(10)", -+ -+ "*turboVNC*button12.label: Lossy Refresh", -+ "*turboVNC*button12.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: SendRFBEvent(fbupdate)", -+ -+ "*turboVNC*buttonNone.label: Not Compiled with\\nTurboVNC Support.", -+ "*turboVNC*buttonNone.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HideTurboVNC()", -+ -+ "*qualLabel.label: JPEG Image Quality:", -+ "*qualBar.length: 100", -+ "*qualBar.width: 130", -+ "*qualBar.orientation: horizontal", -+ "*qualBar.translations: #override\\n\ -+ <Btn1Down>: StartScroll(Continuous) MoveThumb() NotifyThumb()\\n\ -+ <Btn1Motion>: MoveThumb() NotifyThumb()\\n\ -+ <Btn3Down>: StartScroll(Continuous) MoveThumb() NotifyThumb()\\n\ -+ <Btn3Motion>: MoveThumb() NotifyThumb()", -+ -+ "*qualText.label: 000", -+ -+ "*scaleN*button0.label: Dismiss", -+ "*scaleN*button0.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HideScaleN()", -+ -+ "*scaleN*button1.label: 1/1", -+ "*scaleN*button1.translations: #override\\n\ -+ <Visible>: SetScaleNState(1)\\n\ -+ <Btn1Down>,<Btn1Up>: SetScaleN(1) HideScaleN()", -+ -+ "*scaleN*button2.label: 1/2", -+ "*scaleN*button2.translations: #override\\n\ -+ <Visible>: SetScaleNState(2)\\n\ -+ <Btn1Down>,<Btn1Up>: SetScaleN(2) HideScaleN()", -+ -+ "*scaleN*button3.label: 1/3", -+ "*scaleN*button3.translations: #override\\n\ -+ <Visible>: SetScaleNState(3)\\n\ -+ <Btn1Down>,<Btn1Up>: SetScaleN(3) HideScaleN()", -+ -+ "*scaleN*button4.label: 1/4", -+ "*scaleN*button4.translations: #override\\n\ -+ <Visible>: SetScaleNState(4)\\n\ -+ <Btn1Down>,<Btn1Up>: SetScaleN(4) HideScaleN()", -+ -+ "*scaleN*button5.label: 1/5", -+ "*scaleN*button5.translations: #override\\n\ -+ <Visible>: SetScaleNState(5)\\n\ -+ <Btn1Down>,<Btn1Up>: SetScaleN(5) HideScaleN()", -+ -+ "*scaleN*button6.label: Other", -+ "*scaleN*button6.translations: #override\\n\ -+ <Visible>: SetScaleNState(6)\\n\ -+ <Btn1Down>,<Btn1Up>: HideScaleN() DoServerScale()", -+ -+ "*quality*buttonD.label: Dismiss", -+ "*quality*buttonD.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HideQuality()", -+ -+ "*quality*button0.label: 0", -+ "*quality*button0.type: toggle", -+ "*quality*button0.translations: #override\\n\ -+ <Visible>: SetQualityState(0)\\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(0) HideQuality()", -+ -+ "*quality*button1.label: 1", -+ "*quality*button1.type: toggle", -+ "*quality*button1.translations: #override\\n\ -+ <Visible>: SetQualityState(1)\\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(1) HideQuality()", -+ -+ "*quality*button2.label: 2", -+ "*quality*button2.type: toggle", -+ "*quality*button2.translations: #override\\n\ -+ <Visible>: SetQualityState(2)\\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(2) HideQuality()", -+ -+ "*quality*button3.label: 3", -+ "*quality*button3.type: toggle", -+ "*quality*button3.translations: #override\\n\ -+ <Visible>: SetQualityState(3)\\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(3) HideQuality()", -+ -+ "*quality*button4.label: 4", -+ "*quality*button4.type: toggle", -+ "*quality*button4.translations: #override\\n\ -+ <Visible>: SetQualityState(4)\\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(4) HideQuality()", -+ -+ "*quality*button5.label: 5", -+ "*quality*button5.type: toggle", -+ "*quality*button5.translations: #override\\n\ -+ <Visible>: SetQualityState(5)\\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(5) HideQuality()", -+ -+ "*quality*button6.label: 6", -+ "*quality*button6.type: toggle", -+ "*quality*button6.translations: #override\\n\ -+ <Visible>: SetQualityState(6)\\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(6) HideQuality()", -+ -+ "*quality*button7.label: 7", -+ "*quality*button7.type: toggle", -+ "*quality*button7.translations: #override\\n\ -+ <Visible>: SetQualityState(7)\\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(7) HideQuality()", -+ -+ "*quality*button8.label: 8", -+ "*quality*button8.type: toggle", -+ "*quality*button8.translations: #override\\n\ -+ <Visible>: SetQualityState(8)\\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(8) HideQuality()", -+ -+ "*quality*button9.label: 9", -+ "*quality*button9.type: toggle", -+ "*quality*button9.translations: #override\\n\ -+ <Visible>: SetQualityState(9)\\n\ -+ <Btn1Down>,<Btn1Up>: SetQuality(9) HideQuality()", -+ -+ "*compress*buttonD.label: Dismiss", -+ "*compress*buttonD.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HideCompress()", -+ -+ "*compress*button0.label: 0", -+ "*compress*button0.translations: #override\\n\ -+ <Visible>: SetCompressState(0)\\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(0) HideCompress()", -+ -+ "*compress*button1.label: 1", -+ "*compress*button1.translations: #override\\n\ -+ <Visible>: SetCompressState(1)\\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(1) HideCompress()", -+ -+ "*compress*button2.label: 2", -+ "*compress*button2.translations: #override\\n\ -+ <Visible>: SetCompressState(2)\\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(2) HideCompress()", -+ -+ "*compress*button3.label: 3", -+ "*compress*button3.translations: #override\\n\ -+ <Visible>: SetCompressState(3)\\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(3) HideCompress()", -+ -+ "*compress*button4.label: 4", -+ "*compress*button4.translations: #override\\n\ -+ <Visible>: SetCompressState(4)\\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(4) HideCompress()", -+ -+ "*compress*button5.label: 5", -+ "*compress*button5.translations: #override\\n\ -+ <Visible>: SetCompressState(5)\\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(5) HideCompress()", -+ -+ "*compress*button6.label: 6", -+ "*compress*button6.translations: #override\\n\ -+ <Visible>: SetCompressState(6)\\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(6) HideCompress()", -+ -+ "*compress*button7.label: 7", -+ "*compress*button7.translations: #override\\n\ -+ <Visible>: SetCompressState(7)\\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(7) HideCompress()", -+ -+ "*compress*button8.label: 8", -+ "*compress*button8.translations: #override\\n\ -+ <Visible>: SetCompressState(8)\\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(8) HideCompress()", -+ -+ "*compress*button9.label: 9", -+ "*compress*button9.translations: #override\\n\ -+ <Visible>: SetCompressState(9)\\n\ -+ <Btn1Down>,<Btn1Up>: SetCompress(9) HideCompress()", -+ - NULL - }; - -@@ -124,7 +697,7 @@ - * from a dialog box. - */ - --char vncServerHost[256]; -+char vncServerHost[1024]; - int vncServerPort = 0; - - -@@ -135,6 +708,7 @@ - */ - - AppData appData; -+AppData appDataNew; - - static XtResource appDataResourceList[] = { - {"shareDesktop", "ShareDesktop", XtRBool, sizeof(Bool), -@@ -155,14 +729,44 @@ - {"userLogin", "UserLogin", XtRString, sizeof(String), - XtOffsetOf(AppData, userLogin), XtRImmediate, (XtPointer) 0}, - -+ {"unixPW", "UnixPW", XtRString, sizeof(String), -+ XtOffsetOf(AppData, unixPW), XtRImmediate, (XtPointer) 0}, -+ -+ {"msLogon", "MSLogon", XtRString, sizeof(String), -+ XtOffsetOf(AppData, msLogon), 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}, -+ -+ {"acceptPopup", "AcceptPopup", XtRBool, sizeof(Bool), -+ XtOffsetOf(AppData, acceptPopup), 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 +783,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 +798,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,11 +816,13 @@ - {"bumpScrollPixels", "BumpScrollPixels", XtRInt, sizeof(int), - XtOffsetOf(AppData, bumpScrollPixels), XtRImmediate, (XtPointer) 20}, - -+ /* hardwired compress -1 vs . 7 */ - {"compressLevel", "CompressionLevel", XtRInt, sizeof(int), - XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) -1}, - -+ /* hardwired quality was 6 */ - {"qualityLevel", "QualityLevel", XtRInt, sizeof(int), -- XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) 6}, -+ XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) -1}, - - {"enableJPEG", "EnableJPEG", XtRBool, sizeof(Bool), - XtOffsetOf(AppData, enableJPEG), XtRImmediate, (XtPointer) True}, -@@ -218,14 +830,97 @@ - {"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}, -+ -+ {"notty", "NoTty", XtRBool, sizeof(Bool), -+ XtOffsetOf(AppData, notty), 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}, -+ -+ {"useXserverBackingStore", "UseXserverBackingStore", XtRBool, sizeof(Bool), -+ XtOffsetOf(AppData, useXserverBackingStore), XtRImmediate, (XtPointer) False}, -+ -+ {"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}, -+ -+ {"chatOnly", "ChatOnly", XtRBool, sizeof(Bool), -+ XtOffsetOf(AppData, chatOnly), 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}, -+ -+ {"scale", "Scale", XtRString, sizeof(String), -+ XtOffsetOf(AppData, scale), XtRImmediate, (XtPointer) 0}, -+ -+ {"pipelineUpdates", "PipelineUpdates", XtRBool, sizeof(Bool), -+ XtOffsetOf(AppData, pipelineUpdates), XtRImmediate, (XtPointer) -+#ifdef TURBOVNC -+ True}, -+#else -+#if 0 -+ False}, -+#else -+ True}, -+#endif -+#endif -+ -+ {"noipv4", "noipv4", XtRBool, sizeof(Bool), -+ XtOffsetOf(AppData, noipv4), XtRImmediate, (XtPointer) False}, -+ -+ {"noipv6", "noipv6", XtRBool, sizeof(Bool), -+ XtOffsetOf(AppData, noipv6), XtRImmediate, (XtPointer) False}, -+ -+ {"sendClipboard", "SendClipboard", XtRBool, sizeof(Bool), -+ XtOffsetOf(AppData, sendClipboard), XtRImmediate, (XtPointer) False}, -+ -+ {"sendAlways", "SendAlways", XtRBool, sizeof(Bool), -+ XtOffsetOf(AppData, sendAlways), XtRImmediate, (XtPointer) False}, -+ -+ {"recvText", "RecvText", XtRString, sizeof(String), -+ XtOffsetOf(AppData, recvText), XtRImmediate, (XtPointer) 0}, -+ -+ {"appShare", "AppShare", XtRBool, sizeof(Bool), -+ XtOffsetOf(AppData, appShare), XtRImmediate, (XtPointer) False}, -+ -+ {"escapeKeys", "EscapeKeys", XtRString, sizeof(String), -+ XtOffsetOf(AppData, escapeKeys), XtRImmediate, (XtPointer) 0}, -+ -+ {"escapeActive", "EscapeActive", XtRBool, sizeof(Bool), -+ XtOffsetOf(AppData, escapeActive), XtRImmediate, (XtPointer) False} -+ -+ /* check commas */ - }; - - -@@ -242,8 +937,29 @@ - {"-noraiseonbeep", "*raiseOnBeep", XrmoptionNoArg, "False"}, - {"-passwd", "*passwordFile", XrmoptionSepArg, 0}, - {"-user", "*userLogin", XrmoptionSepArg, 0}, -+ {"-unixpw", "*unixPW", XrmoptionSepArg, 0}, -+ {"-mslogon", "*msLogon", XrmoptionSepArg, 0}, -+ {"-repeater", "*repeaterUltra", XrmoptionSepArg, 0}, -+ {"-ultradsm", "*ultraDSM", XrmoptionNoArg, "True"}, -+ {"-acceptpopup", "*acceptPopup", XrmoptionNoArg, "True"}, -+ {"-acceptpopupsc", "*acceptPopup", 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}, -+ {"-rawlocal", "*useRawLocal", XrmoptionNoArg, "True"}, -+ {"-notty", "*notty", XrmoptionNoArg, "True"}, -+ {"-alpha", "*useCursorAlpha", XrmoptionNoArg, "True"}, - {"-owncmap", "*forceOwnCmap", XrmoptionNoArg, "True"}, - {"-truecolor", "*forceTrueColour", XrmoptionNoArg, "True"}, - {"-truecolour", "*forceTrueColour", XrmoptionNoArg, "True"}, -@@ -253,8 +969,30 @@ - {"-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", "*useXserverBackingStore", XrmoptionNoArg, "True"}, -+ {"-nobs", "*useXserverBackingStore", XrmoptionNoArg, "False"}, -+ {"-popupfix", "*popupFix", XrmoptionNoArg, "True"}, -+ {"-noshm", "*useShm", XrmoptionNoArg, "False"}, -+ {"-termchat", "*termChat", XrmoptionNoArg, "True"}, -+ {"-chatonly", "*chatOnly", XrmoptionNoArg, "True"}, -+ {"-scale", "*scale", XrmoptionSepArg, 0}, -+ {"-appshare", "*appShare", XrmoptionNoArg, "True"}, -+ {"-escape", "*escapeKeys", XrmoptionSepArg, 0}, -+ {"-sendclipboard", "*sendClipboard", XrmoptionNoArg, "True"}, -+ {"-sendalways", "*sendAlways", XrmoptionNoArg, "True"}, -+ {"-recvtext", "*recvText", XrmoptionSepArg, 0}, -+ {"-pipeline", "*pipelineUpdates", XrmoptionNoArg, "True"}, -+ {"-nopipeline", "*pipelineUpdates", XrmoptionNoArg, "False"}, -+ {"-noipv4", "*noipv4", XrmoptionNoArg, "True"}, -+ {"-noipv6", "*noipv6", XrmoptionNoArg, "True"} - }; - - int numCmdLineOptions = XtNumber(cmdLineOptions); -@@ -267,16 +1005,100 @@ - static XtActionsRec actions[] = { - {"SendRFBEvent", SendRFBEvent}, - {"ShowPopup", ShowPopup}, -+ {"Noop", Noop}, - {"HidePopup", HidePopup}, -+ {"HideScaleN", HideScaleN}, -+ {"HideTurboVNC", HideTurboVNC}, -+ {"HideQuality", HideQuality}, -+ {"HideCompress", HideCompress}, - {"ToggleFullScreen", ToggleFullScreen}, -+ {"JumpLeft", JumpLeft}, -+ {"JumpRight", JumpRight}, -+ {"JumpUp", JumpUp}, -+ {"JumpDown", JumpDown}, - {"SetFullScreenState", SetFullScreenState}, - {"SelectionFromVNC", SelectionFromVNC}, - {"SelectionToVNC", SelectionToVNC}, - {"ServerDialogDone", ServerDialogDone}, -+ {"UserDialogDone", UserDialogDone}, -+ {"YCropDialogDone", YCropDialogDone}, -+ {"ScbarDialogDone", ScbarDialogDone}, -+ {"ScaleNDialogDone", ScaleNDialogDone}, -+ {"ScaleDialogDone", ScaleDialogDone}, - {"PasswordDialogDone", PasswordDialogDone}, - {"Pause", Pause}, - {"RunCommand", RunCommand}, - {"Quit", Quit}, -+ {"HideChat", HideChat}, -+ {"Toggle8bpp", Toggle8bpp}, -+ {"Toggle16bpp", Toggle16bpp}, -+ {"ToggleFullColor", ToggleFullColor}, -+ {"Toggle256Colors", Toggle256Colors}, -+ {"Toggle64Colors", Toggle64Colors}, -+ {"Toggle8Colors", Toggle8Colors}, -+ {"ToggleGreyScale", ToggleGreyScale}, -+ {"ToggleTightZRLE", ToggleTightZRLE}, -+ {"ToggleTightHextile", ToggleTightHextile}, -+ {"ToggleZRLEZYWRLE", ToggleZRLEZYWRLE}, -+ {"ToggleViewOnly", ToggleViewOnly}, -+ {"ToggleJPEG", ToggleJPEG}, -+ {"ToggleCursorShape", ToggleCursorShape}, -+ {"ToggleCursorAlpha", ToggleCursorAlpha}, -+ {"ToggleX11Cursor", ToggleX11Cursor}, -+ {"ToggleBell", ToggleBell}, -+ {"ToggleRawLocal", ToggleRawLocal}, -+ {"ToggleServerInput", ToggleServerInput}, -+ {"TogglePipelineUpdates", TogglePipelineUpdates}, -+ {"ToggleSendClipboard", ToggleSendClipboard}, -+ {"ToggleSendAlways", ToggleSendAlways}, -+ {"ToggleSingleWindow", ToggleSingleWindow}, -+ {"ToggleTextChat", ToggleTextChat}, -+ {"ToggleFileXfer", ToggleFileXfer}, -+ {"ToggleXGrab", ToggleXGrab}, -+ {"DoServerScale", DoServerScale}, -+ {"SetScale", SetScale}, -+ {"SetYCrop", SetYCrop}, -+ {"SetScbar", SetScbar}, -+ {"ShowScaleN", ShowScaleN}, -+ {"ShowTurboVNC", ShowTurboVNC}, -+ {"ShowQuality", ShowQuality}, -+ {"ShowCompress", ShowCompress}, -+ {"SetScaleN", SetScaleN}, -+ {"SetTurboVNC", SetTurboVNC}, -+ {"SetQuality", SetQuality}, -+ {"SetCompress", SetCompress}, -+ {"Set8bppState", Set8bppState}, -+ {"Set16bppState", Set16bppState}, -+ {"SetFullColorState", SetFullColorState}, -+ {"Set256ColorsState", Set256ColorsState}, -+ {"Set64ColorsState", Set64ColorsState}, -+ {"Set8ColorsState", Set8ColorsState}, -+ {"SetGreyScaleState", SetGreyScaleState}, -+ {"SetZRLEState", SetZRLEState}, -+ {"SetHextileState", SetHextileState}, -+ {"SetZYWRLEState", SetZYWRLEState}, -+ {"SetNOJPEGState", SetNOJPEGState}, -+ {"SetScaleNState", SetScaleNState}, -+ {"SetQualityState", SetQualityState}, -+ {"SetCompressState", SetCompressState}, -+ {"SetViewOnlyState", SetViewOnlyState}, -+ {"SetCursorShapeState", SetCursorShapeState}, -+ {"SetCursorAlphaState", SetCursorAlphaState}, -+ {"SetX11CursorState", SetX11CursorState}, -+ {"SetBellState", SetBellState}, -+ {"SetRawLocalState", SetRawLocalState}, -+ {"SetServerInputState", SetServerInputState}, -+ {"SetPipelineUpdates", SetPipelineUpdates}, -+ {"SetSendClipboard", SetSendClipboard}, -+ {"SetSendAlways", SetSendAlways}, -+ {"SetSingleWindowState", SetSingleWindowState}, -+ {"SetTextChatState", SetTextChatState}, -+ {"SetFileXferState", SetFileXferState}, -+ {"SetXGrabState", SetXGrabState}, -+ {"SetEscapeKeysState", SetEscapeKeysState}, -+ {"ToggleEscapeActive", ToggleEscapeActive}, -+ {"EscapeDialogDone", EscapeDialogDone}, -+ {"SetEscapeKeys", SetEscapeKeys} - }; - - -@@ -302,11 +1124,14 @@ - 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 [<OPTIONS>] [<HOST>][:<DISPLAY#>]\n" - " %s [<OPTIONS>] [<HOST>][::<PORT#>]\n" -+ " %s [<OPTIONS>] exec=[CMD ARGS...]\n" -+ " %s [<OPTIONS>] fd=n\n" -+ " %s [<OPTIONS>] /path/to/unix/socket\n" - " %s [<OPTIONS>] -listen [<DISPLAY#>]\n" - " %s -help\n" - "\n" -@@ -319,7 +1144,7 @@ - " -noraiseonbeep\n" - " -passwd <PASSWD-FILENAME> (standard VNC authentication)\n" - " -user <USERNAME> (Unix login authentication)\n" -- " -encodings <ENCODING-LIST> (e.g. \"tight copyrect\")\n" -+ " -encodings <ENCODING-LIST> (e.g. \"tight,copyrect\")\n" - " -bgr233\n" - " -owncmap\n" - " -truecolour\n" -@@ -332,10 +1157,390 @@ - " -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" -+ " If the host:port is specified as \"fd=n\" then it is assumed\n" -+ " n is an already opened file descriptor to the socket. (i.e\n" -+ " the parent did fork+exec)\n" -+ "\n" -+ " 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" -+ " -acceptpopup In -listen (reverse connection listening) mode when\n" -+ " a reverse VNC connection comes in show a popup asking\n" -+ " whether to Accept or Reject the connection. The IP\n" -+ " address of the connecting host is shown. Same as\n" -+ " setting the env. var. SSVNC_ACCEPT_POPUP=1.\n" -+ "\n" -+ " -acceptpopupsc As in -acceptpopup except assume UltraVNC Single\n" -+ " Click (SC) server. Retrieve User and ComputerName\n" -+ " info from UltraVNC Server and display in the Popup.\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" -+ " -scale str Scale the desktop locally. The string \"str\" can\n" -+ " a floating point ratio, e.g. \"0.9\", or a fraction,\n" -+ " e.g. \"3/4\", or WxH, e.g. 1280x1024. Use \"fit\"\n" -+ " to fit in the current screen size. Use \"auto\" to\n" -+ " fit in the window size. \"str\" can also be set by\n" -+ " the env. var. SSVNC_SCALE.\n" -+ "\n" -+ " If you observe mouse trail painting errors, enable\n" -+ " X11 Cursor mode (either via Popup or -x11cursor.)\n" -+ "\n" -+ " Note that scaling is done in software and so can be\n" -+ " slow and requires more memory. Some speedup Tips:\n" -+ "\n" -+ " ZRLE is faster than Tight in this mode. When\n" -+ " scaling is first detected, the encoding will\n" -+ " be automatically switched to ZRLE. Use the\n" -+ " Popup menu if you want to go back to Tight.\n" -+ " Set SSVNC_PRESERVE_ENCODING=1 to disable this.\n" -+ "\n" -+ " Use a solid background on the remote side.\n" -+ " (e.g. manually or via x11vnc -solid ...)\n" -+ "\n" -+ " If the remote server is x11vnc, try client\n" -+ " side caching: x11vnc -ncache 10 ...\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" -+ " -notty Try to avoid using the terminal for interactive\n" -+ " responses: use windows for messages and prompting\n" -+ " instead. Messages will also be printed to terminal.\n" -+ "\n" -+ " -sendclipboard Send the X CLIPBOARD selection (i.e. Ctrl+C,\n" -+ " Ctrl+V) instead of the X PRIMARY selection (mouse\n" -+ " select and middle button paste.)\n" -+ "\n" -+ " -sendalways Whenever the mouse enters the VNC viewer main\n" -+ " window, send the selection to the VNC server even if\n" -+ " it has not changed. This is like the Xt resource\n" -+ " translation SelectionToVNC(always)\n" -+ "\n" -+ " -recvtext str When cut text is received from the VNC server,\n" -+ " ssvncviewer will set both the X PRIMARY and the\n" -+ " X CLIPBOARD local selections. To control which\n" -+ " is set, specify 'str' as 'primary', 'clipboard',\n" -+ " or 'both' (the default.)\n" -+ "\n" -+ " -graball Grab the entire X server when in fullscreen mode,\n" -+ " needed by some old window managers like fvwm2.\n" -+ "\n" -+ " -popupfix Warp the popup back to the pointer position,\n" -+ " needed by some old window managers like fvwm2.\n" -+ " -sendclipboard Send the X CLIPBOARD selection (i.e. Ctrl+C,\n" -+ " Ctrl+V) instead of the X PRIMARY selection (mouse\n" -+ " select and middle button paste.)\n" -+ "\n" -+ " -sendalways Whenever the mouse enters the VNC viewer main\n" -+ " window, send the selection to the VNC server even if\n" -+ " it has not changed. This is like the Xt resource\n" -+ " translation SelectionToVNC(always)\n" -+ "\n" -+ " -recvtext str When cut text is received from the VNC server,\n" -+ " ssvncviewer will set both the X PRIMARY and the\n" -+ " X CLIPBOARD local selections. To control which\n" -+ " is set, specify 'str' as 'primary', 'clipboard',\n" -+ " or 'both' (the default.)\n" -+ "\n" -+ " -graball Grab the entire X server when in fullscreen mode,\n" -+ " needed by some old window managers like fvwm2.\n" -+ "\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" -+ " -mslogon user Use Windows MS Logon to an UltraVNC server. Supply the\n" -+ " username or \"1\" to be prompted. The default is to\n" -+ " autodetect the UltraVNC MS Logon server and prompt for\n" -+ " the username and password.\n" -+ "\n" -+ " IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman\n" -+ " exchange is very weak and can be brute forced to recover\n" -+ " your username and password in a few seconds of CPU time.\n" -+ " To be safe, be sure to use an additional encrypted tunnel\n" -+ " (e.g. SSL or SSH) for the entire VNC session.\n" -+ "\n" -+ " -chatonly Try to be a client that only does UltraVNC text chat. This\n" -+ " mode is used by x11vnc to present a chat window on the\n" -+ " physical X11 console (i.e. chat with the person at the\n" -+ " display).\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" -+ " -noipv6 Disable all IPv6 sockets. Same as VNCVIEWER_NO_IPV6=1.\n" -+ "\n" -+ " -noipv4 Disable all IPv4 sockets. Same as VNCVIEWER_NO_IPV4=1.\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" -+ " -pipeline Like TurboVNC, request the next framebuffer update as soon\n" -+ " as possible instead of waiting until the end of the current\n" -+ " framebuffer update coming in. Helps 'pipeline' the updates.\n" -+ " This is currently the default, use -nopipeline to disable.\n" -+ "\n" -+ " -appshare Enable features for use with x11vnc's -appshare mode where\n" -+ " instead of sharing the full desktop only the application's\n" -+ " windows are shared. Viewer multilisten mode is used to\n" -+ " create the multiple windows: -multilisten is implied.\n" -+ " See 'x11vnc -appshare -help' more information on the mode.\n" -+ "\n" -+ " Features enabled in the viewer under -appshare are:\n" -+ " Minimum extra text in the title, auto -ycrop is disabled,\n" -+ " x11vnc -remote_prefix X11VNC_APPSHARE_CMD: message channel,\n" -+ " x11vnc initial window position hints. See also Escape Keys\n" -+ " below for additional key and mouse bindings.\n" -+ "\n" -+ " -escape str This sets the 'Escape Keys' modifier sequence and enables\n" -+ " escape keys mode. When the modifier keys escape sequence\n" -+ " is held down, the next keystroke is interpreted locally\n" -+ " to perform a special action instead of being sent to the\n" -+ " remote VNC server.\n" -+ "\n" -+ " Use '-escape default' for the default modifier sequence.\n" -+ " (Unix: Alt_L,Super_L and MacOSX: Control_L,Meta_L)\n" -+ "\n" -+ " Here are the 'Escape Keys: Help+Set' instructions from the Popup Menu:\n" -+ "\n" -+ " Escape Keys: Enter a comma separated list of modifier keys to be the\n" -+ " 'escape sequence'. When these keys are held down, the next keystroke is\n" -+ " interpreted locally to invoke a special action instead of being sent to\n" -+ " the remote VNC server. In other words, a set of 'Hot Keys'.\n" -+ " \n" -+ " To enable or disable this, click on 'Escape Keys: Toggle' in the Popup.\n" -+ " \n" -+ " Here is the list of hot-key mappings to special actions:\n" -+ " \n" -+ " r: refresh desktop b: toggle bell c: toggle full-color\n" -+ " f: file transfer x: x11cursor z: toggle Tight/ZRLE\n" -+ " l: full screen g: graball e: escape keys dialog\n" -+ " s: scale dialog +: scale up (=) -: scale down (_)\n" -+ " t: text chat a: alphablend cursor\n" -+ " V: toggle viewonly Q: quit viewer 1 2 3 4 5 6: UltraVNC scale 1/n\n" -+ " \n" -+ " Arrow keys: pan the viewport about 10%% for each keypress.\n" -+ " PageUp / PageDown: pan the viewport by a screenful vertically.\n" -+ " Home / End: pan the viewport by a screenful horizontally.\n" -+ " KeyPad Arrow keys: pan the viewport by 1 pixel for each keypress.\n" -+ " Dragging the Mouse with Button1 pressed also pans the viewport.\n" -+ " Clicking Mouse Button3 brings up the Popup Menu.\n" -+ " \n" -+ " The above mappings are *always* active in ViewOnly mode, unless you set the\n" -+ " Escape Keys value to 'never'.\n" -+ " \n" -+ " If the Escape Keys value below is set to 'default' then a default list of\n" -+ " of modifier keys is used. For Unix it is: Alt_L,Super_L and for MacOSX it\n" -+ " is Control_L,Meta_L. Note: the Super_L key usually has a Windows(TM) Flag\n" -+ " on it. Also note the _L and _R mean the key is on the LEFT or RIGHT side\n" -+ " of the keyboard.\n" -+ " \n" -+ " On Unix the default is Alt and Windows keys on Left side of keyboard.\n" -+ " On MacOSX the default is Control and Command keys on Left side of keyboard.\n" -+ " \n" -+ " Example: Press and hold the Alt and Windows keys on the LEFT side of the\n" -+ " keyboard and then press 'c' to toggle the full-color state. Or press 't'\n" -+ " to toggle the ultravnc Text Chat window, etc.\n" -+ " \n" -+ " To use something besides the default, supply a comma separated list (or a\n" -+ " single one) from: Shift_L Shift_R Control_L Control_R Alt_L Alt_R Meta_L\n" -+ " Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch.\n" -+ "\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/Hextile: ~ -encodings hextile...\n" -+ " Toggle Tight/ZRLE: ~ -encodings zrle...\n" -+ " Toggle ZRLE/ZYWRLE: ~ -encodings zywrle...\n" -+ " Quality Level ~ -quality (both Tight and ZYWRLE)\n" -+ " Compress Level ~ -compresslevel\n" -+ " Disable JPEG: ~ -nojpeg (Tight)\n" -+ " Pipeline Updates ~ -pipeline\n" -+ "\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" -+ " Scale Viewer ~ -scale\n" -+ " Escape Keys: Toggle ~ -escape\n" -+ " Escape Keys: Help+Set ~ -escape\n" -+ " Set Y Crop (y-max) ~ -ycrop\n" -+ " Set Scrollbar Width ~ -sbwidth\n" -+ " XGrabServer ~ -graball\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" -+ " Send Clipboard not Primary ~ -sendclipboard\n" -+ " Send Selection Every time ~ -sendalways\n" -+ "\n" -+ "\n", programName, programName, programName, programName, programName, programName, programName); - exit(1); - } -+#if 0 -+ " -nooverride Do not apply OverrideRedirect in fullscreen mode.\n" -+#endif - - - /* -@@ -343,77 +1548,247 @@ - * not already processed by XtVaAppInitialize(). It sets vncServerHost and - * vncServerPort and all the fields in appData. - */ -+extern int saw_appshare; - - void - GetArgsAndResources(int argc, char **argv) - { -- int i; -- char *vncServerName, *colonPos; -- int len, portOffset; -+ char *vncServerName = NULL, *colonPos, *bracketPos; -+ int len, portOffset; -+ int disp; - - /* Turn app resource specs into our appData structure for the rest of the - program to use */ - -- XtGetApplicationResources(toplevel, &appData, appDataResourceList, -- XtNumber(appDataResourceList), 0, 0); -+ XtGetApplicationResources(toplevel, &appData, appDataResourceList, -+ XtNumber(appDataResourceList), 0, 0); -+ -+ /* -+ * we allow setting of some by env, to avoid clash with other -+ * viewer's cmdlines (e.g. change viewer in SSVNC). -+ */ -+ if (getenv("VNCVIEWER_ALPHABLEND")) { -+ appData.useCursorAlpha = True; -+ } -+ if (getenv("VNCVIEWER_POPUP_FIX")) { -+ if (getenv("NOPOPUPFIX")) { -+ ; -+ } else if (!strcmp(getenv("VNCVIEWER_POPUP_FIX"), "0")) { -+ ; -+ } else { -+ 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_RFBVERSION") && strcmp(getenv("VNCVIEWER_RFBVERSION"), "")) { -+ appData.rfbVersion = strdup(getenv("VNCVIEWER_RFBVERSION")); -+ } -+ if (getenv("VNCVIEWER_ENCODINGS") && strcmp(getenv("VNCVIEWER_ENCODINGS"), "")) { -+ appData.encodingsString = strdup(getenv("VNCVIEWER_ENCODINGS")); -+ } -+ if (getenv("VNCVIEWER_NOBELL")) { -+ appData.useBell = False; -+ } -+ if (getenv("VNCVIEWER_X11CURSOR")) { -+ appData.useX11Cursor = True; -+ } -+ if (getenv("VNCVIEWER_RAWLOCAL")) { -+ appData.useRawLocal = True; -+ } -+ if (getenv("VNCVIEWER_NOTTY") || getenv("SSVNC_VNCVIEWER_NOTTY")) { -+ appData.notty = True; -+ } -+ if (getenv("VNCVIEWER_SBWIDTH")) { -+ int n = atoi(getenv("VNCVIEWER_SBWIDTH")); -+ if (n != 0) { -+ appData.sbWidth = n; -+ } -+ } -+ if (getenv("VNCVIEWER_ULTRADSM")) { -+ appData.ultraDSM = True; -+ } -+ if (getenv("SSVNC_ULTRA_DSM") && strcmp(getenv("SSVNC_ULTRA_DSM"), "")) { -+ appData.ultraDSM = True; -+ } -+ if (getenv("SSVNC_NO_ULTRA_DSM")) { -+ appData.ultraDSM = False; -+ } -+ if (getenv("SSVNC_SCALE") && strcmp(getenv("SSVNC_SCALE"), "")) { -+ if (appData.scale == NULL) { -+ appData.scale = strdup(getenv("SSVNC_SCALE")); -+ } -+ } -+ if (getenv("VNCVIEWER_ESCAPE") && strcmp(getenv("VNCVIEWER_ESCAPE"), "")) { -+ if (appData.escapeKeys == NULL) { -+ appData.escapeKeys = strdup(getenv("VNCVIEWER_ESCAPE")); -+ } -+ } -+ if (saw_appshare) { -+ appData.appShare = True; -+ } -+ if (appData.appShare && appData.escapeKeys == NULL) { -+ appData.escapeKeys = strdup("default"); -+ } -+ if (appData.escapeKeys != NULL) { -+ appData.escapeActive = True; -+ } -+ if (getenv("VNCVIEWER_SEND_CLIPBOARD")) { -+ appData.sendClipboard = True; -+ } -+ if (getenv("VNCVIEWER_SEND_ALWAYS")) { -+ appData.sendAlways = True; -+ } -+ if (getenv("VNCVIEWER_RECV_TEXT")) { -+ char *s = getenv("VNCVIEWER_RECV_TEXT"); -+ if (!strcasecmp(s, "clipboard")) { -+ appData.recvText = strdup("clipboard"); -+ } else if (!strcasecmp(s, "primary")) { -+ appData.recvText = strdup("primary"); -+ } else if (!strcasecmp(s, "both")) { -+ appData.recvText = strdup("both"); -+ } -+ } -+ if (getenv("VNCVIEWER_PIPELINE_UPDATES")) { -+ appData.pipelineUpdates = True; -+ } else if (getenv("VNCVIEWER_NO_PIPELINE_UPDATES")) { -+ appData.pipelineUpdates = False; -+ } -+ -+ if (getenv("VNCVIEWER_NO_IPV4")) { -+ appData.noipv4 = True; -+ } -+ if (getenv("VNCVIEWER_NO_IPV6")) { -+ appData.noipv6 = True; -+ } -+ -+ if (appData.useBGR233 && appData.useBGR565) { -+ appData.useBGR233 = 0; -+ } -+ -+ if (getenv("SSVNC_ULTRA_FTP_JAR") == NULL && programName != NULL) { -+ int len = strlen(programName) + 200; -+ char *q, *jar = (char *) malloc(len); -+ -+ sprintf(jar, "%s", programName); -+ q = strrchr(jar, '/'); -+ if (q) { -+ struct stat sb; -+ *(q+1) = '\0'; -+ strcat(jar, "../lib/ssvnc/util/ultraftp.jar"); -+ if (stat(jar, &sb) == 0) { -+ char *put = (char *) malloc(len); -+ sprintf(put, "SSVNC_ULTRA_FTP_JAR=%s", jar); -+ fprintf(stderr, "Setting: %s\n\n", put); -+ putenv(put); -+ } else { -+ sprintf(jar, "%s", programName); -+ q = strrchr(jar, '/'); -+ *(q+1) = '\0'; -+ strcat(jar, "util/ultraftp.jar"); -+ if (stat(jar, &sb) == 0) { -+ char *put = (char *) malloc(len); -+ sprintf(put, "SSVNC_ULTRA_FTP_JAR=%s", jar); -+ fprintf(stderr, "Setting: %s\n\n", put); -+ putenv(put); -+ } -+ } -+ } -+ free(jar); -+ } -+ - - /* Add our actions to the actions table so they can be used in widget - resource specs */ - -- XtAppAddActions(appContext, actions, XtNumber(actions)); -+ XtAppAddActions(appContext, actions, XtNumber(actions)); - - /* Check any remaining command-line arguments. If -listen was specified - there should be none. Otherwise the only argument should be the VNC - server name. If not given then pop up a dialog box and wait for the - server name to be entered. */ - -- if (listenSpecified) { -- if (argc != 1) { -- fprintf(stderr,"\n%s -listen: invalid command line argument: %s\n", -- programName, argv[1]); -- usage(); -- } -- return; -- } -- -- if (argc == 1) { -- vncServerName = DoServerDialog(); -- appData.passwordDialog = True; -- } else if (argc != 2) { -- usage(); -- } else { -- vncServerName = argv[1]; -- -- if (!isatty(0)) -- appData.passwordDialog = True; -- if (vncServerName[0] == '-') -- usage(); -- } -- -- if (strlen(vncServerName) > 255) { -- fprintf(stderr,"VNC server name too long\n"); -- exit(1); -- } -- -- colonPos = strchr(vncServerName, ':'); -- if (colonPos == NULL) { -- /* No colon -- use default port number */ -- strcpy(vncServerHost, vncServerName); -- vncServerPort = SERVER_PORT_OFFSET; -- } else { -- memcpy(vncServerHost, vncServerName, colonPos - vncServerName); -- vncServerHost[colonPos - vncServerName] = '\0'; -- len = strlen(colonPos + 1); -- portOffset = SERVER_PORT_OFFSET; -- if (colonPos[1] == ':') { -- /* Two colons -- interpret as a port number */ -- colonPos++; -- len--; -- portOffset = 0; -- } -- if (!len || strspn(colonPos + 1, "0123456789") != len) { -- usage(); -- } -- vncServerPort = atoi(colonPos + 1) + portOffset; -- } -+ if (listenSpecified) { -+ if (argc != 1) { -+ fprintf(stderr,"\n%s -listen: invalid command line argument: %s\n", -+ programName, argv[1]); -+ usage(); -+ } -+ return; -+ } -+ -+ if (argc == 1) { -+ vncServerName = DoServerDialog(); -+ if (!use_tty()) { -+ appData.passwordDialog = True; -+ } -+ } else if (argc != 2) { -+ usage(); -+ } else { -+ vncServerName = argv[1]; -+ -+ if (!use_tty()) { -+ appData.passwordDialog = True; -+ } -+ if (vncServerName[0] == '-') { -+ usage(); -+ } -+ } -+ -+ if (strlen(vncServerName) > 255) { -+ fprintf(stderr,"VNC server name too long\n"); -+ exit(1); -+ } -+ -+ colonPos = strrchr(vncServerName, ':'); -+ bracketPos = strrchr(vncServerName, ']'); -+ if (strstr(vncServerName, "exec=") == vncServerName) { -+ /* special exec-external-command case */ -+ strcpy(vncServerHost, vncServerName); -+ vncServerPort = SERVER_PORT_OFFSET; -+ } else if (strstr(vncServerName, "fd=") == vncServerName) { -+ /* special exec-external-command case */ -+ strcpy(vncServerHost, vncServerName); -+ vncServerPort = SERVER_PORT_OFFSET; -+ } else if (colonPos == NULL) { -+ /* No colon -- use default port number */ -+ strcpy(vncServerHost, vncServerName); -+ vncServerPort = SERVER_PORT_OFFSET; -+ } else if (bracketPos != NULL && colonPos < bracketPos) { -+ strcpy(vncServerHost, vncServerName); -+ vncServerPort = SERVER_PORT_OFFSET; -+ } else { -+ if (colonPos > vncServerName && *(colonPos - 1) == ':') { -+ colonPos--; -+ } -+ memcpy(vncServerHost, vncServerName, colonPos - vncServerName); -+ vncServerHost[colonPos - vncServerName] = '\0'; -+ len = strlen(colonPos + 1); -+ portOffset = SERVER_PORT_OFFSET; -+ if (colonPos[1] == ':') { -+ /* Two colons -- interpret as a port number */ -+ colonPos++; -+ len--; -+ portOffset = 0; -+ } -+ if (!len || strspn(colonPos + 1, "0123456789") != (size_t) 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 2010-02-25 22:02:19.000000000 -0500 -@@ -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(unsigned long red_mask, unsigned long green_mask, unsigned long blue_mask); -+ - - /* - * 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(vis->red_mask, vis->green_mask, vis->blue_mask); -+ 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; -@@ -374,7 +442,7 @@ - if (!exactBGR233[i] && - XAllocColor(dpy, cmap, &cmapEntry[i])) { - -- if (cmapEntry[i].pixel == i) { -+ if ((long) cmapEntry[i].pixel == i) { - - shared[i] = True; /* probably shared */ - -@@ -394,16 +462,43 @@ - for (r = 0; r < 8; r++) { - for (g = 0; g < 8; g++) { - for (b = 0; b < 4; b++) { -- if (BGR233ToPixel[(b<<6) | (g<<3) | r] == INVALID_PIXEL) { -+ int bs = 6, gs = 3, rs = 0; -+ int bm = 3, gm = 7, rm = 7; -+ if (appData.useBGR233 == 64) { -+ bs = 4; gs = 2; rs = 0; -+ bm = 3; gm = 3; rm = 3; -+ } -+ if (appData.useBGR233 == 8) { -+ bs = 2; gs = 1; rs = 0; -+ bm = 1; gm = 1; rm = 1; -+ } -+ if ((b > bm || g > gm || r > rm)) { -+ continue; -+ } -+ if (BGR233ToPixel[(b<<bs) | (g<<gs) | (r<<rs)] == INVALID_PIXEL) { - - unsigned long minDistance = ULONG_MAX; - - for (i = 0; i < cmapSize; i++) { - if (exactBGR233[i] || shared[i]) { -- unsigned long distance -- = (abs(cmapEntry[i].red - r * 65535 / 7) -- + abs(cmapEntry[i].green - g * 65535 / 7) -- + abs(cmapEntry[i].blue - b * 65535 / 3)); -+ unsigned long distance; -+ int r1, g1, b1; -+ if (appData.useGreyScale) { -+ int ave; -+ ave = (r + g + 2*b)/3; -+ r1 = ave; -+ g1 = ave; -+ b1 = ave/2; -+ } else { -+ r1 = r; -+ g1 = g; -+ b1 = b; -+ } -+ distance -+ = ( abs(cmapEntry[i].red - r1 * 65535 / rm) -+ + abs(cmapEntry[i].green - g1 * 65535 / gm) -+ + abs(cmapEntry[i].blue - b1 * 65535 / bm)); -+ - - if (distance < minDistance) { - minDistance = distance; -@@ -412,7 +507,7 @@ - } - } - -- BGR233ToPixel[(b<<6) | (g<<3) | r] = nearestPixel; -+ BGR233ToPixel[(b<<bs) | (g<<gs) | (r<<rs)] = nearestPixel; - if (shared[nearestPixel] && !usedAsNearest[nearestPixel]) - nSharedUsed++; - usedAsNearest[nearestPixel] = True; -@@ -433,6 +528,59 @@ - } - } - -+static void -+SetupBGR565Map(unsigned long red_mask, unsigned long green_mask, unsigned long blue_mask) -+{ -+ int r, g, b; -+ int r2, g2, b2; -+ long idx; -+ int cnt = 0; -+ unsigned long pixel = 0; -+ -+ for (r = 0; r < 32; r++) { -+ for (g = 0; g < 64; g++) { -+ for (b = 0; b < 32; b++) { -+ int bs = 0, gs = 5, rs = 11; -+ int bm = 31, gm = 63, rm = 31; -+ if ((b > bm || g > gm || r > rm)) { -+ continue; -+ } -+ r2 = (255 * r) / rm; -+ g2 = (255 * g) / gm; -+ b2 = (255 * b) / bm; -+ -+ pixel = (r2 << 16) | (g2 << 8) | (b2 << 0); -+ if (appData.useGreyScale) { -+ int ave; -+ int r1, g1, b1; -+ ave = (2*r + g + 2*b)/3; -+ r1 = ave/2; -+ g1 = ave; -+ b1 = ave/2; -+ -+ r2 = (255 * r1) / rm; -+ g2 = (255 * g1) / gm; -+ b2 = (255 * b1) / bm; -+ -+ pixel = (r2 << 16) | (g2 << 8) | (b2 << 0); -+ } -+ -+ if (red_mask == 0xff) { -+ idx = (r<<bs) | (g<<gs) | (b<<rs); -+ } else { -+ idx = (b<<bs) | (g<<gs) | (r<<rs); -+ } -+ if (0) fprintf(stderr, "cnt: %5d idx: %lu pixel: 0x%08x\n", cnt, idx, (unsigned int) pixel); -+ BGR565ToPixel[idx] = pixel; -+ cnt++; -+ } -+ } -+ } -+ green_mask = 0; -+ blue_mask = 0; -+} -+ -+ - - /* - * AllocateExactBGR233Colours() attempts to allocate each of the colours in the -@@ -484,8 +632,13 @@ - ri = rn; - for (gi = 0; gi < gn; gi++) { - for (bi = 0; bi < bn; bi++) { -- if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) -- return; -+ if (appData.useBGR233 == 64 && (bv[bi] > 3 || gv[gi] > 3 || rv[ri] > 3)) { -+ nBGR233ColoursAllocated++; -+ } else if (appData.useBGR233 == 8 && (bv[bi] > 1 || gv[gi] > 1 || rv[ri] > 1)) { -+ nBGR233ColoursAllocated++; -+ } else if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) { -+ return; -+ } - } - } - rn++; -@@ -496,8 +649,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 +665,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 +692,36 @@ - AllocateBGR233Colour(int r, int g, int b) - { - XColor c; -+ int bs = 6, gs = 3, rs = 0; -+ int bm = 3, gm = 7, rm = 7; - - if (nBGR233ColoursAllocated >= appData.nColours) - return False; - -- c.red = r * 65535 / 7; -- c.green = g * 65535 / 7; -- c.blue = b * 65535 / 3; -+ if (appData.useBGR233 == 64) { -+ bs = 4; gs = 2, rs = 0; -+ bm = 3; gm = 3; rm = 3; -+ } -+ if (appData.useBGR233 == 8) { -+ bs = 2; gs = 1, rs = 0; -+ bm = 1; gm = 1; rm = 1; -+ } -+ -+ c.red = r * 65535 / rm; -+ c.green = g * 65535 / gm; -+ c.blue = b * 65535 / bm; -+ if (appData.useGreyScale) { -+ int ave; -+ ave = (c.red + c.green + c.blue)/3; -+ c.red = ave; -+ c.green = ave; -+ c.blue = ave; -+ } - - if (!XAllocColor(dpy, cmap, &c)) - return False; - -- BGR233ToPixel[(b<<6) | (g<<3) | r] = c.pixel; -+ BGR233ToPixel[(b<<bs) | (g<<gs) | r] = c.pixel; - - nBGR233ColoursAllocated++; - -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/corre.c vnc_unixsrc/vncviewer/corre.c ---- vnc_unixsrc.orig/vncviewer/corre.c 2000-06-11 08:00:53.000000000 -0400 -+++ vnc_unixsrc/vncviewer/corre.c 2008-10-05 15:16:01.000000000 -0400 -@@ -29,6 +29,18 @@ - #define HandleCoRREBPP CONCAT2E(HandleCoRRE,BPP) - #define CARDBPP CONCAT2E(CARD,BPP) - -+#define FillRectangle(x, y, w, h, color) \ -+ { \ -+ XGCValues _gcv; \ -+ _gcv.foreground = color; \ -+ if (!appData.useXserverBackingStore) { \ -+ FillScreen(x, y, w, h, _gcv.foreground); \ -+ } else { \ -+ XChangeGC(dpy, gc, GCForeground, &_gcv); \ -+ XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \ -+ } \ -+ } -+ - static Bool - HandleCoRREBPP (int rx, int ry, int rw, int rh) - { -@@ -50,11 +62,19 @@ - #if (BPP == 8) - gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix); - #else -+#if (BPP == 16) -+ gcv.foreground = (appData.useBGR565 ? BGR565ToPixel[pix] : pix); -+#else - gcv.foreground = pix; - #endif -+#endif - -+#if 0 - XChangeGC(dpy, gc, GCForeground, &gcv); - XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); -+#else -+ FillRectangle(rx, ry, rw, rh, gcv.foreground); -+#endif - - if (!ReadFromRFBServer(buffer, hdr.nSubrects * (4 + (BPP / 8)))) - return False; -@@ -72,12 +92,22 @@ - #if (BPP == 8) - gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix); - #else -+#if (BPP == 16) -+ gcv.foreground = (appData.useBGR565 ? BGR565ToPixel[pix] : pix); -+#else - gcv.foreground = pix; - #endif -+#endif - -+#if 0 - XChangeGC(dpy, gc, GCForeground, &gcv); - XFillRectangle(dpy, desktopWin, gc, rx + x, ry + y, w, h); -+#else -+ FillRectangle(rx + x, ry + y, w, h, gcv.foreground); -+#endif - } - - return True; - } -+ -+#undef FillRectangle -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cp_it vnc_unixsrc/vncviewer/cp_it ---- vnc_unixsrc.orig/vncviewer/cp_it 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/cp_it 2009-03-06 20:02:05.000000000 -0500 -@@ -0,0 +1,18 @@ -+#!/bin/sh -+ -+dest=/dist/bin/vncviewerz-1.3dev5-resize -+suc "cp -p $dest $dest.back; mv $dest $dest.unlink; mv $dest.back $dest; rm $dest.unlink" -+strip ./vncviewer -+cat ./vncviewer > $dest -+touch -r ./vncviewer $dest -+yy=/dist/src/apps/VNC/etc/libvncserver_cvs/expts/etv/ssvnc/bin/Linux.i686/vncviewer -+mv $yy $yy.unlink -+cp -p ./vncviewer $yy -+mv $yy.turbovnc $yy.unlink.turbovnc -+cp -p ./vncviewer $HOME/etv_col/Linux.i686 -+cp -p ./vncviewer.turbovnc $yy.turbovnc -+cp -p ./vncviewer.turbovnc $HOME/etv_col/Linux.i686/vncviewer.turbovnc -+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 2010-02-25 22:04:28.000000000 -0500 -@@ -38,8 +38,11 @@ - - - static Bool prevSoftCursorSet = False; --static Pixmap rcSavedArea; --static CARD8 *rcSource, *rcMask; -+static Pixmap rcSavedArea, rcSavedArea_0; -+static int rcSavedArea_w = -1, rcSavedArea_h = -1; -+static char *rcSavedScale = NULL; -+static int rcSavedScale_len = 0; -+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 +51,13 @@ - 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(); -+ -+extern XImage *image; -+extern XImage *image_scale; -+extern int scale_x, scale_y; -+int scale_round(int n, double factor); - - /* Copied from Xvnc/lib/font/util/utilbitmap.c */ - static unsigned char _reverse_byte[0x100] = { -@@ -91,6 +99,8 @@ - static Bool prevXCursorSet = False; - static Cursor prevXCursor; - -+extern double scale_factor_x; -+extern double scale_factor_y; - - Bool HandleXCursor(int xhot, int yhot, int width, int height) - { -@@ -124,7 +134,7 @@ - XQueryBestCursor(dpy, dr, width, height, &wret, &hret); - } - -- if (width * height == 0 || wret < width || hret < height) { -+ if (width * height == 0 || (int) wret < width || (int) hret < height) { - /* Free resources */ - if (buf != NULL) - free(buf); -@@ -139,7 +149,7 @@ - fg.green = (unsigned short)colors.foreGreen << 8 | colors.foreGreen; - fg.blue = (unsigned short)colors.foreBlue << 8 | colors.foreBlue; - -- for (i = 0; i < bytesData * 2; i++) -+ for (i = 0; (size_t) i < bytesData * 2; i++) - buf[i] = (char)_reverse_byte[(int)buf[i] & 0xFF]; - - source = XCreateBitmapFromData(dpy, dr, buf, width, height); -@@ -167,148 +177,179 @@ - - Bool HandleCursorShape(int xhot, int yhot, int width, int height, CARD32 enc) - { -- int bytesPerPixel; -- size_t bytesPerRow, bytesMaskData; -- Drawable dr; -- rfbXCursorColors rgb; -- CARD32 colors[2]; -- char *buf; -- CARD8 *ptr; -- int x, y, b; -- -- bytesPerPixel = myFormat.bitsPerPixel / 8; -- bytesPerRow = (width + 7) / 8; -- bytesMaskData = bytesPerRow * height; -- dr = DefaultRootWindow(dpy); -- -- FreeSoftCursor(); -+ int bytesPerPixel; -+ size_t bytesPerRow, bytesMaskData; -+ Drawable dr; -+ rfbXCursorColors rgb; -+ CARD32 colors[2]; -+ char *buf; -+ CARD8 *ptr; -+ int x, y, b; -+ -+ bytesPerPixel = myFormat.bitsPerPixel / 8; -+ bytesPerRow = (width + 7) / 8; -+ bytesMaskData = bytesPerRow * height; -+ dr = DefaultRootWindow(dpy); - -- if (width * height == 0) -- return True; -- -- /* Allocate memory for pixel data and temporary mask data. */ -+ FreeSoftCursor(); - -- rcSource = malloc(width * height * bytesPerPixel); -- if (rcSource == NULL) -- return False; -- -- buf = malloc(bytesMaskData); -- if (buf == NULL) { -- free(rcSource); -- return False; -- } -+ if (width * height == 0) { -+ return True; -+ } - -- /* Read and decode cursor pixel data, depending on the encoding type. */ -+ /* Allocate memory for pixel data and temporary mask data. */ - -- if (enc == rfbEncodingXCursor) { -- if (appData.useX11Cursor) { -- HandleXCursor(xhot, yhot, width, height); -- return True; -- } -+ rcSource = malloc(width * height * bytesPerPixel); -+ if (rcSource == NULL) { -+ return False; -+ } - -- /* Read and convert background and foreground colors. */ -- if (!ReadFromRFBServer((char *)&rgb, sz_rfbXCursorColors)) { -- free(rcSource); -- free(buf); -- return False; -- } -- colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue); -- colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue); -+ buf = malloc(bytesMaskData); -+ if (buf == NULL) { -+ free(rcSource); -+ rcSource = NULL; -+ return False; -+ } - -- /* Read 1bpp pixel data into a temporary buffer. */ -- if (!ReadFromRFBServer(buf, bytesMaskData)) { -- free(rcSource); -- free(buf); -- return False; -- } -+ /* Read and decode cursor pixel data, depending on the encoding type. */ - -- /* Convert 1bpp data to byte-wide color indices. */ -- ptr = rcSource; -- for (y = 0; y < height; y++) { -- for (x = 0; x < width / 8; x++) { -- for (b = 7; b >= 0; b--) { -- *ptr = buf[y * bytesPerRow + x] >> b & 1; -- ptr += bytesPerPixel; -- } -- } -- for (b = 7; b > 7 - width % 8; b--) { -- *ptr = buf[y * bytesPerRow + x] >> b & 1; -- ptr += bytesPerPixel; -- } -- } -+ if (enc == rfbEncodingXCursor) { -+ if (appData.useX11Cursor) { -+ HandleXCursor(xhot, yhot, width, height); -+ return True; -+ } -+ -+ /* Read and convert background and foreground colors. */ -+ if (!ReadFromRFBServer((char *)&rgb, sz_rfbXCursorColors)) { -+ free(rcSource); -+ rcSource = NULL; -+ free(buf); -+ return False; -+ } -+ colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue); -+ colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue); -+ -+ /* Read 1bpp pixel data into a temporary buffer. */ -+ if (!ReadFromRFBServer(buf, bytesMaskData)) { -+ free(rcSource); -+ rcSource = NULL; -+ free(buf); -+ return False; -+ } -+ -+ /* Convert 1bpp data to byte-wide color indices. */ -+ ptr = rcSource; -+ for (y = 0; y < height; y++) { -+ for (x = 0; x < width / 8; x++) { -+ for (b = 7; b >= 0; b--) { -+ *ptr = buf[y * bytesPerRow + x] >> b & 1; -+ ptr += bytesPerPixel; -+ } -+ } -+ for (b = 7; b > 7 - width % 8; b--) { -+ *ptr = buf[y * bytesPerRow + x] >> b & 1; -+ ptr += bytesPerPixel; -+ } -+ } -+ -+ /* Convert indices into the actual pixel values. */ -+ switch (bytesPerPixel) { -+ case 1: -+ for (x = 0; x < width * height; x++) { -+ rcSource[x] = (CARD8)colors[rcSource[x]]; -+ } -+ break; -+ case 2: -+ for (x = 0; x < width * height; x++) { -+ ((CARD16 *)rcSource)[x] = (CARD16)colors[rcSource[x * 2]]; -+ } -+ break; -+ case 4: -+ for (x = 0; x < width * height; x++) { -+ ((CARD32 *)rcSource)[x] = colors[rcSource[x * 4]]; -+ } -+ break; -+ } -+ -+ } else { /* enc == rfbEncodingRichCursor */ -+ if (!ReadFromRFBServer((char *)rcSource, width * height * bytesPerPixel)) { -+ free(rcSource); -+ rcSource = NULL; -+ free(buf); -+ return False; -+ } -+ } - -- /* Convert indices into the actual pixel values. */ -- switch (bytesPerPixel) { -- case 1: -- for (x = 0; x < width * height; x++) -- rcSource[x] = (CARD8)colors[rcSource[x]]; -- break; -- case 2: -- for (x = 0; x < width * height; x++) -- ((CARD16 *)rcSource)[x] = (CARD16)colors[rcSource[x * 2]]; -- break; -- case 4: -- for (x = 0; x < width * height; x++) -- ((CARD32 *)rcSource)[x] = colors[rcSource[x * 4]]; -- break; -- } -+ /* Read and decode mask data. */ - -- } else { /* enc == rfbEncodingRichCursor */ -+ if (!ReadFromRFBServer(buf, bytesMaskData)) { -+ free(rcSource); -+ rcSource = NULL; -+ free(buf); -+ return False; -+ } - -- if (!ReadFromRFBServer((char *)rcSource, width * height * bytesPerPixel)) { -- free(rcSource); -- free(buf); -- return False; -- } -+ rcMask = malloc(width * height); -+ if (rcMask == NULL) { -+ free(rcSource); -+ rcSource = NULL; -+ free(buf); -+ return False; -+ } - -- } -+ ptr = rcMask; -+ for (y = 0; y < height; y++) { -+ for (x = 0; x < width / 8; x++) { -+ for (b = 7; b >= 0; b--) { -+ *ptr++ = buf[y * bytesPerRow + x] >> b & 1; -+ } -+ } -+ for (b = 7; b > 7 - width % 8; b--) { -+ *ptr++ = buf[y * bytesPerRow + x] >> b & 1; -+ } -+ } - -- /* Read and decode mask data. */ -+ free(buf); - -- if (!ReadFromRFBServer(buf, bytesMaskData)) { -- free(rcSource); -- free(buf); -- return False; -- } -+ /* Set remaining data associated with cursor. */ - -- rcMask = malloc(width * height); -- if (rcMask == NULL) { -- free(rcSource); -- free(buf); -- return False; -- } -+ dr = DefaultRootWindow(dpy); - -- ptr = rcMask; -- for (y = 0; y < height; y++) { -- for (x = 0; x < width / 8; x++) { -- for (b = 7; b >= 0; b--) { -- *ptr++ = buf[y * bytesPerRow + x] >> b & 1; -- } -- } -- for (b = 7; b > 7 - width % 8; b--) { -- *ptr++ = buf[y * bytesPerRow + x] >> b & 1; -- } -- } -+ if (scale_x > 0) { -+ int w = scale_round(width, scale_factor_x) + 2; -+ int h = scale_round(height, scale_factor_y) + 2; -+ rcSavedArea = XCreatePixmap(dpy, dr, w, h, visdepth); -+ rcSavedArea_w = w; -+ rcSavedArea_h = h; -+ } else { -+ rcSavedArea = XCreatePixmap(dpy, dr, width, height, visdepth); -+ rcSavedArea_w = width; -+ rcSavedArea_h = height; -+ } -+ rcSavedArea_0 = XCreatePixmap(dpy, dr, width, height, visdepth); - -- free(buf); -+if (0) fprintf(stderr, "rcSavedArea_wh: %d %d scale_x: %d\n", rcSavedArea_w, rcSavedArea_h, scale_x); - -- /* Set remaining data associated with cursor. */ -+ if (rcSavedScale_len < 4 * width * height + 4096) { -+ if (rcSavedScale) { -+ free(rcSavedScale); -+ } -+ rcSavedScale = (char *) malloc(2 * 4 * width * height + 4096); -+ } - -- dr = DefaultRootWindow(dpy); -- rcSavedArea = XCreatePixmap(dpy, dr, width, height, visdepth); -- rcHotX = xhot; -- rcHotY = yhot; -- rcWidth = width; -- rcHeight = height; -+ rcHotX = xhot; -+ rcHotY = yhot; -+ rcWidth = width; -+ rcHeight = height; - -- SoftCursorCopyArea(OPER_SAVE); -- SoftCursorDraw(); -+ SoftCursorCopyArea(OPER_SAVE); -+ SoftCursorDraw(); - -- rcCursorHidden = False; -- rcLockSet = False; -+ rcCursorHidden = False; -+ rcLockSet = False; - -- prevSoftCursorSet = True; -- return True; -+ prevSoftCursorSet = True; -+ return True; - } - - /********************************************************************* -@@ -319,20 +360,27 @@ - - Bool HandleCursorPos(int x, int y) - { -- if (appData.useX11Cursor) { -- if (appData.fullScreen) -- XWarpPointer(dpy, None, desktopWin, 0, 0, 0, 0, x, y); -- -- return True; -- } -+ if (x < 0) x = 0; -+ if (y < 0) y = 0; - -- if (x >= si.framebufferWidth) -- x = si.framebufferWidth - 1; -- if (y >= si.framebufferHeight) -- y = si.framebufferHeight - 1; -+ /* fprintf(stderr, "xy: %d %d\n", x, y); */ - -- SoftCursorMove(x, y); -- return True; -+ if (x >= si.framebufferWidth) { -+ x = si.framebufferWidth - 1; -+ } -+ if (y >= si.framebufferHeight) { -+ y = si.framebufferHeight - 1; -+ } -+ -+ if (appData.useX11Cursor) { -+ if (appData.fullScreen) { -+ XWarpPointer(dpy, None, desktopWin, 0, 0, 0, 0, x, y); -+ } -+ return True; -+ } -+ -+ SoftCursorMove(x, y); -+ return True; - } - - /********************************************************************* -@@ -348,30 +396,31 @@ - { - int newX, newY; - -- if (!prevSoftCursorSet) -- return; -+ if (!prevSoftCursorSet) { -+ return; -+ } - -- if (!rcLockSet) { -- rcLockX = x; -- rcLockY = y; -- rcLockWidth = w; -- rcLockHeight = h; -- rcLockSet = True; -- } else { -- newX = (x < rcLockX) ? x : rcLockX; -- newY = (y < rcLockY) ? y : rcLockY; -- rcLockWidth = (x + w > rcLockX + rcLockWidth) ? -- (x + w - newX) : (rcLockX + rcLockWidth - newX); -- rcLockHeight = (y + h > rcLockY + rcLockHeight) ? -- (y + h - newY) : (rcLockY + rcLockHeight - newY); -- rcLockX = newX; -- rcLockY = newY; -- } -+ if (!rcLockSet) { -+ rcLockX = x; -+ rcLockY = y; -+ rcLockWidth = w; -+ rcLockHeight = h; -+ rcLockSet = True; -+ } else { -+ newX = (x < rcLockX) ? x : rcLockX; -+ newY = (y < rcLockY) ? y : rcLockY; -+ rcLockWidth = (x + w > rcLockX + rcLockWidth) ? -+ (x + w - newX) : (rcLockX + rcLockWidth - newX); -+ rcLockHeight = (y + h > rcLockY + rcLockHeight) ? -+ (y + h - newY) : (rcLockY + rcLockHeight - newY); -+ rcLockX = newX; -+ rcLockY = newY; -+ } - -- if (!rcCursorHidden && SoftCursorInLockedArea()) { -- SoftCursorCopyArea(OPER_RESTORE); -- rcCursorHidden = True; -- } -+ if (!rcCursorHidden && SoftCursorInLockedArea()) { -+ SoftCursorCopyArea(OPER_RESTORE); -+ rcCursorHidden = True; -+ } - } - - /********************************************************************* -@@ -381,15 +430,16 @@ - - void SoftCursorUnlockScreen(void) - { -- if (!prevSoftCursorSet) -- return; -+ if (!prevSoftCursorSet) { -+ return; -+ } - -- if (rcCursorHidden) { -- SoftCursorCopyArea(OPER_SAVE); -- SoftCursorDraw(); -- rcCursorHidden = False; -- } -- rcLockSet = False; -+ if (rcCursorHidden) { -+ SoftCursorCopyArea(OPER_SAVE); -+ SoftCursorDraw(); -+ rcCursorHidden = False; -+ } -+ rcLockSet = False; - } - - /********************************************************************* -@@ -401,19 +451,19 @@ - - void SoftCursorMove(int x, int y) - { -- if (prevSoftCursorSet && !rcCursorHidden) { -- SoftCursorCopyArea(OPER_RESTORE); -- rcCursorHidden = True; -- } -+ if (prevSoftCursorSet && !rcCursorHidden) { -+ SoftCursorCopyArea(OPER_RESTORE); -+ rcCursorHidden = True; -+ } - -- rcCursorX = x; -- rcCursorY = y; -+ rcCursorX = x; -+ rcCursorY = y; - -- if (prevSoftCursorSet && !(rcLockSet && SoftCursorInLockedArea())) { -- SoftCursorCopyArea(OPER_SAVE); -- SoftCursorDraw(); -- rcCursorHidden = False; -- } -+ if (prevSoftCursorSet && !(rcLockSet && SoftCursorInLockedArea())) { -+ SoftCursorCopyArea(OPER_SAVE); -+ SoftCursorDraw(); -+ rcCursorHidden = False; -+ } - } - - -@@ -429,41 +479,169 @@ - rcLockY + rcLockHeight > rcCursorY - rcHotY); - } - --static void SoftCursorCopyArea(int oper) --{ -- int x, y, w, h; -+void new_pixmap(int w, int h) { - -- 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; -- } -+ XFreePixmap(dpy, rcSavedArea); - -- if (oper == OPER_SAVE) { -- /* Save screen area in memory. */ --#ifdef MITSHM -- if (appData.useShm) -- XSync(dpy, False); --#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); -- } -+ if (w > 0 && h > 0) { -+ rcSavedArea = XCreatePixmap(dpy, DefaultRootWindow(dpy), w, h, visdepth); -+ rcSavedArea_w = w; -+ rcSavedArea_h = h; -+ -+ } else if (image_scale != NULL && scale_x > 0) { -+ int w2 = scale_round(rcWidth, scale_factor_x) + 2; -+ int h2 = scale_round(rcHeight, scale_factor_y) + 2; -+ rcSavedArea = XCreatePixmap(dpy, DefaultRootWindow(dpy), w2, h2, visdepth); -+ rcSavedArea_w = w2; -+ rcSavedArea_h = h2; -+ } else { -+ rcSavedArea = XCreatePixmap(dpy, DefaultRootWindow(dpy), rcWidth, rcHeight, visdepth); -+ rcSavedArea_w = rcWidth; -+ rcSavedArea_h = rcHeight; -+ } -+} -+ -+extern int XError_ign; -+ -+static void SoftCursorCopyArea(int oper) { -+ int x, y, w, h; -+ int xs = 0, ys = 0, ws = 0, hs = 0; -+ static int scale_saved = 0, ss_w, ss_h; -+ int db = 0; -+ -+ 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; -+ } -+ -+ if (image_scale != NULL && scale_x > 0) { -+ xs = (int) (x * scale_factor_x); -+ ys = (int) (y * scale_factor_y); -+ ws = scale_round(w, scale_factor_x); -+ hs = scale_round(h, scale_factor_y); -+ -+ if (xs > 0) xs -= 1; -+ if (ys > 0) ys -= 1; -+ ws += 2; -+ hs += 2; -+ } -+ -+ XError_ign = 1; -+ -+ if (oper == OPER_SAVE) { -+ /* Save screen area in memory. */ -+ scale_saved = 0; -+ if (appData.useXserverBackingStore) { -+ XSync(dpy, False); -+ XCopyArea(dpy, desktopWin, rcSavedArea, gc, x, y, w, h, 0, 0); -+ } else { -+ if (image_scale != NULL && scale_x > 0) { -+ int Bpp = image_scale->bits_per_pixel / 8; -+ int Bpl = image_scale->bytes_per_line; -+ int i; -+ char *src = image_scale->data + y * Bpl + x * Bpp; -+ char *dst = rcSavedScale; -+ -+ if (ws > rcSavedArea_w || hs > rcSavedArea_h) { -+ new_pixmap(0, 0); -+ } -+ -+if (db) fprintf(stderr, "save: %dx%d+%d+%d\n", ws, hs, xs, ys); -+ -+ XPutImage(dpy, rcSavedArea, gc, image, xs, ys, 0, 0, ws, hs); -+ -+ XPutImage(dpy, rcSavedArea_0, gc, image_scale, x, y, 0, 0, w, h); -+ -+ scale_saved = 1; -+ ss_w = ws; -+ ss_h = hs; -+ -+ for (i=0; i < h; i++) { -+ memcpy(dst, src, Bpp * w); -+ src += Bpl; -+ dst += Bpp * w; -+ } -+ } else { -+if (db) fprintf(stderr, "SAVE: %dx%d+%d+%d\n", w, h, x, y); -+ if (w > rcSavedArea_w || h > rcSavedArea_h) { -+ new_pixmap(0, 0); -+ } -+ -+ XPutImage(dpy, rcSavedArea, gc, image, x, y, 0, 0, w, h); -+ } -+ } -+ } else { -+ -+#define XE(s) if (XError_ign > 1) {fprintf(stderr, "X-%d\n", (s)); db = 1;} -+ -+ /* Restore screen area. */ -+ if (appData.useXserverBackingStore) { -+ XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y); -+XE(1) -+ XGetSubImage(dpy, rcSavedArea, 0, 0, w, h, AllPlanes, ZPixmap, image, x, y); -+XE(2) -+ -+ } else { -+ if (image_scale != NULL && scale_x > 0) { -+ int Bpp = image_scale->bits_per_pixel / 8; -+ int Bpl = image_scale->bytes_per_line; -+ int i; -+ char *dst = image_scale->data + y * Bpl + x * Bpp; -+ char *src = rcSavedScale; -+ -+ XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, ws, hs, xs, ys); -+XE(3) -+ XGetSubImage(dpy, rcSavedArea, 0, 0, ws, hs, AllPlanes, ZPixmap, image, xs, ys); -+XE(4) -+if (db) fprintf(stderr, "rstr: %dx%d+%d+%d\n", ws, hs, xs, ys); -+ -+ for (i=0; i < h; i++) { -+ memcpy(dst, src, Bpp * w); -+ src += Bpp * w; -+ dst += Bpl; -+ } -+ } else { -+ -+ if (scale_saved) { -+ XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, ss_w, ss_h, x, y); -+XE(5) -+ XGetSubImage(dpy, rcSavedArea, 0, 0, ss_w, ss_h, AllPlanes, ZPixmap, image, x, y); -+XE(6) -+ new_pixmap(w, h); -+ } else { -+ XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y); -+XE(7) -+ XGetSubImage(dpy, rcSavedArea, 0, 0, w, h, AllPlanes, ZPixmap, image, x, y); -+XE(8) -+ } -+ -+if (db) fprintf(stderr, "RSTR: %dx%d+%d+%d\n", w, h, x, y); -+ -+ } -+ } -+ } -+ -+ if (XError_ign > 1) { -+ fprintf(stderr, "XError_ign: %d, oper: %s\n", XError_ign, oper ? "restore" : "save"); -+ } -+ -+ XError_ign = 0; - } - - static void SoftCursorDraw(void) -@@ -472,43 +650,182 @@ - int offset, bytesPerPixel; - char *pos; - -+#define alphahack -+#ifdef alphahack -+ /* hack to have cursor transparency at 32bpp <runge@karlrunge.com> */ -+ int alphablend = 0; -+ -+ if (!rcSource) { -+ return; -+ } -+ -+ if (appData.useCursorAlpha) { -+ alphablend = 1; -+ } -+ - bytesPerPixel = myFormat.bitsPerPixel / 8; - -- /* FIXME: Speed optimization is possible. */ -- for (y = 0; y < rcHeight; y++) { -- y0 = rcCursorY - rcHotY + y; -- if (y0 >= 0 && y0 < si.framebufferHeight) { -- for (x = 0; x < rcWidth; x++) { -- x0 = rcCursorX - rcHotX + x; -- if (x0 >= 0 && x0 < si.framebufferWidth) { -- offset = y * rcWidth + x; -- if (rcMask[offset]) { -- pos = (char *)&rcSource[offset * bytesPerPixel]; -- CopyDataToScreen(pos, x0, y0, 1, 1); -- } -+ 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 = 192; -+ -+ 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 alpha_image (faster way?) */ -+ if (image_scale != NULL && scale_x > 0) { -+ XGetSubImage(dpy, rcSavedArea_0, 0, 0, rcWidth, rcHeight, AllPlanes, ZPixmap, alpha_image, 0, 0); -+ } else { -+ 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. */ -+ for (y = 0; y < rcHeight; y++) { -+ y0 = rcCursorY - rcHotY + y; -+ if (y0 >= 0 && y0 < si.framebufferHeight) { -+ for (x = 0; x < rcWidth; x++) { -+ x0 = rcCursorX - rcHotX + x; -+ if (x0 >= 0 && x0 < si.framebufferWidth) { -+ offset = y * rcWidth + x; -+ if (rcMask[offset]) { -+ pos = (char *)&rcSource[offset * bytesPerPixel]; -+ CopyDataToScreen(pos, x0, y0, 1, 1); -+ } -+ } -+ } -+ } -+ } -+ 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); -+ XFreePixmap(dpy, rcSavedArea_0); -+ 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 2010-02-25 22:32:49.000000000 -0500 -@@ -28,28 +28,497 @@ - #include <X11/extensions/XShm.h> - #endif - -+#include <X11/cursorfont.h> -+ - GC gc; - GC srcGC, dstGC; /* used for debugging copyrect */ - Window desktopWin; --Cursor dotCursor; -+Cursor dotCursor3 = None; -+Cursor dotCursor4 = None; -+Cursor bogoCursor = None; -+Cursor waitCursor = None; - Widget form, viewport, desktop; - -+int appshare_0_hint = -10000; -+int appshare_x_hint = -10000; -+int appshare_y_hint = -10000; -+ - static Bool modifierPressed[256]; - --static XImage *image = NULL; -+XImage *image = NULL; -+XImage *image_ycrop = NULL; -+XImage *image_scale = NULL; -+ -+int image_is_shm = 0; - - static Cursor CreateDotCursor(); - 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, -- XtRImmediate, (XtPointer) Always, -+ XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof(int), 0, -+ XtRImmediate, (XtPointer) Always, - }, - }; - -+double scale_factor_x = 0.0; -+double scale_factor_y = 0.0; -+int scale_x = 0, scale_y = 0; -+int scale_round(int len, double fac); -+ -+double last_rescale = 0.0; -+double last_fullscreen = 0.0; -+double start_time = 0.0; -+ -+int prev_fb_width = -1; -+int prev_fb_height = -1; -+ -+void get_scale_values(double *fx, double *fy) { -+ char *s = appData.scale; -+ double f, frac_x = -1.0, frac_y = -1.0; -+ int n, m; -+ int xmax = si.framebufferWidth; -+ int ymax = si.framebufferHeight; -+ -+ if (appData.yCrop > 0) { -+ ymax = appData.yCrop; -+ } -+ -+ if (sscanf(s, "%d/%d", &n, &m) == 2) { -+ if (m == 0) { -+ frac_x = 1.0; -+ } else { -+ frac_x = ((double) n) / ((double) m); -+ } -+ } -+ if (sscanf(s, "%dx%d", &n, &m) == 2) { -+ frac_x = ((double) n) / ((double) xmax); -+ frac_y = ((double) m) / ((double) ymax); -+ } -+ if (!strcasecmp(s, "fit")) { -+ frac_x = ((double) dpyWidth) / ((double) xmax); -+ frac_y = ((double) dpyHeight) / ((double) ymax); -+ } -+ if (!strcasecmp(s, "auto")) { -+ Dimension w, h; -+ XtVaGetValues(toplevel, XtNheight, &h, XtNwidth, &w, NULL); -+ fprintf(stderr, "auto: %dx%d\n", w, h); -+ if (w > 32 && h > 32) { -+ frac_x = ((double) w) / ((double) xmax); -+ frac_y = ((double) h) / ((double) ymax); -+ } -+ } -+ if (frac_x < 0.0 && sscanf(s, "%lf", &f) == 1) { -+ if (f > 0.0) { -+ frac_x = f; -+ } -+ } -+ -+ if (frac_y < 0.0) { -+ frac_y = frac_x; -+ } -+ -+ if (frac_y > 0.0 && frac_x > 0.0) { -+ if (fx != NULL) { -+ *fx = frac_x; -+ } -+ if (fy != NULL) { -+ *fy = frac_y; -+ } -+ } else { -+ if (appData.scale) { -+ fprintf(stderr, "Invalid scale string: '%s'\n", appData.scale); -+ } else { -+ fprintf(stderr, "Invalid scale string.\n"); -+ } -+ appData.scale = NULL; -+ } -+} -+ -+void try_create_image(void); -+void put_image(int src_x, int src_y, int dst_x, int dst_y, int width, int height, int solid); -+void create_image(); -+ -+/* toplevel -> form -> viewport -> desktop */ -+ -+void adjust_Xt_win(int w, int h) { -+ int x, y, dw, dh, h0 = h; -+ int mw = w, mh = h; -+ int autoscale = 0; -+ -+ if (!appData.fullScreen && appData.scale != NULL && !strcmp(appData.scale, "auto")) { -+ autoscale = 1; -+ mw = dpyWidth; -+ mh = dpyHeight; -+ } -+ -+ if (appData.yCrop > 0) { -+ int ycrop = appData.yCrop; -+ if (image_scale && scale_factor_y > 0.0) { -+ ycrop = scale_round(ycrop, scale_factor_y); -+ if (!autoscale) { -+ mh = ycrop; -+ } -+ } -+ XtVaSetValues(toplevel, XtNmaxWidth, mw, XtNmaxHeight, mh, XtNwidth, w, XtNheight, ycrop, NULL); -+ XtVaSetValues(form, XtNmaxWidth, mw, XtNmaxHeight, mh, XtNwidth, w, XtNheight, ycrop, NULL); -+ h0 = ycrop; -+ } else { -+ XtVaSetValues(toplevel, XtNmaxWidth, mw, XtNmaxHeight, mh, XtNwidth, w, XtNheight, h, NULL); -+ } -+ -+ fprintf(stderr, "adjust_Xt_win: %dx%d & %dx%d\n", w, h, w, h0); -+ -+ XtVaSetValues(desktop, XtNwidth, w, XtNheight, h, NULL); -+ -+ XtResizeWidget(desktop, w, h, 0); -+ -+ if (!autoscale) { -+ dw = appData.wmDecorationWidth; -+ dh = appData.wmDecorationHeight; -+ -+ x = (dpyWidth - w - dw)/2; -+ y = (dpyHeight - h0 - dh)/2; -+ -+ XtConfigureWidget(toplevel, x + dw, y + dh, w, h0, 0); -+ } -+} -+ -+void rescale_image(void) { -+ double frac_x, frac_y; -+ int w, h; -+ -+ if (image == NULL) { -+ create_image(); -+ return; -+ } -+ -+ if (appData.useXserverBackingStore) { -+ create_image(); -+ return; -+ } -+ -+ if (image == NULL && image_scale == NULL) { -+ create_image(); -+ return; -+ } -+ -+ if (appData.scale == NULL) { -+ /* switching to not scaled */ -+ frac_x = frac_y = 1.0; -+ } else { -+ get_scale_values(&frac_x, &frac_y); -+ if (frac_x < 0.0 || frac_y < 0.0) { -+ create_image(); -+ return; -+ } -+ } -+ -+ last_rescale = dnow(); -+ -+ SoftCursorLockArea(0, 0, si.framebufferWidth, si.framebufferHeight); -+ -+ if (image_scale == NULL) { -+ /* switching from not scaled */ -+ int i; -+ int Bpl = image->bytes_per_line; -+ char *dst, *src = image->data; -+ -+ image_scale = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL, -+ si.framebufferWidth, si.framebufferHeight, BitmapPad(dpy), 0); -+ -+ image_scale->data = (char *) malloc(image_scale->bytes_per_line * image_scale->height); -+ -+ fprintf(stderr, "rescale_image: switching from not scaled. created image_scale %dx%d\n", image_scale->width, image_scale->height); -+ fprintf(stderr, "rescale_image: copying image -> image_scale %dx%d -> %dx%d\n", image->width, image->height, image_scale->width, image_scale->height); -+ -+ dst = image_scale->data; -+ -+ /* copy from image->data */ -+ for (i=0; i < image->height; i++) { -+ memcpy(dst, src, Bpl); -+ dst += Bpl; -+ src += Bpl; -+ } -+ } -+ -+ /* now destroy image */ -+ if (image && image->data) { -+ if (UsingShm()) { -+ ShmDetach(); -+ } -+ XDestroyImage(image); -+ fprintf(stderr, "rescale_image: destroyed 'image'\n"); -+ if (UsingShm()) { -+ ShmCleanup(); -+ } -+ image = NULL; -+ } -+ if (image_ycrop && image_ycrop->data) { -+ XDestroyImage(image_ycrop); -+ fprintf(stderr, "rescale_image: destroyed 'image_ycrop'\n"); -+ image_ycrop = NULL; -+ } -+ -+ if (frac_x == 1.0 && frac_y == 1.0) { -+ /* switching to not scaled */ -+ fprintf(stderr, "rescale_image: switching to not scaled.\n"); -+ w = si.framebufferWidth; -+ h = si.framebufferHeight; -+ -+ scale_factor_x = 0.0; -+ scale_factor_y = 0.0; -+ scale_x = 0; -+ scale_y = 0; -+ } else { -+ w = scale_round(si.framebufferWidth, frac_x); -+ h = scale_round(si.framebufferHeight, frac_y); -+ -+ scale_factor_x = frac_x; -+ scale_factor_y = frac_y; -+ scale_x = w; -+ scale_y = h; -+ } -+ -+ adjust_Xt_win(w, h); -+ -+ fprintf(stderr, "rescale: %dx%d %.4f %.4f\n", w, h, scale_factor_x, scale_factor_y); -+ -+ try_create_image(); -+ -+ if (image && image->data && image_scale && frac_x == 1.0 && frac_y == 1.0) { -+ /* switched to not scaled */ -+ int i; -+ int Bpl = image->bytes_per_line; -+ char *dst = image->data; -+ char *src = image_scale->data; -+ -+ fprintf(stderr, "rescale_image: switching to not scaled.\n"); -+ -+ for (i=0; i < image->height; i++) { -+ memcpy(dst, src, Bpl); -+ dst += Bpl; -+ src += Bpl; -+ } -+ XDestroyImage(image_scale); -+ fprintf(stderr, "rescale_image: destroyed 'image_scale'\n"); -+ image_scale = NULL; -+ } -+ -+ if (appData.yCrop > 0) { -+ int ycrop = appData.yCrop; -+ /* do the top part first so they can see it earlier */ -+ put_image(0, 0, 0, 0, si.framebufferWidth, ycrop, 0); -+ if (si.framebufferHeight > ycrop) { -+ /* this is a big fb and so will take a long time */ -+ if (waitCursor != None) { -+ XDefineCursor(dpy, desktopWin, waitCursor); -+ XSync(dpy, False); -+ } -+ put_image(0, 0, 0, 0, si.framebufferWidth, si.framebufferHeight - ycrop, 0); -+ if (waitCursor != None) { -+ Xcursors(1); -+ if (appData.useX11Cursor) { -+ XSetWindowAttributes attr; -+ unsigned long valuemask = 0; -+ if (appData.viewOnly) { -+ attr.cursor = dotCursor4; -+ } else { -+ attr.cursor = dotCursor3; -+ } -+ valuemask |= CWCursor; -+ XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); -+ } -+ } -+ } -+ } else { -+ put_image(0, 0, 0, 0, si.framebufferWidth, si.framebufferHeight, 0); -+ } -+ -+ SoftCursorUnlockScreen(); -+ -+ fprintf(stderr, "rescale: image_scale=%p image=%p image_ycrop=%p\n", (void *) image_scale, (void *) image, (void *) image_ycrop); -+ last_rescale = dnow(); -+ -+} -+ -+void try_create_image(void) { -+ -+ image_is_shm = 0; -+ if (appData.useShm) { -+#ifdef MITSHM -+ image = CreateShmImage(0); -+ if (!image) { -+ if (appData.yCrop > 0) { -+ if (appData.scale != NULL && scale_x > 0) { -+ ; -+ } else { -+ image_ycrop = CreateShmImage(1); -+ if (!image_ycrop) { -+ appData.useShm = False; -+ } else { -+ fprintf(stderr, "created smaller image_ycrop shm image: %dx%d\n", -+ image_ycrop->width, image_ycrop->height); -+ } -+ } -+ } else { -+ appData.useShm = False; -+ } -+ } else { -+ image_is_shm = 1; -+ fprintf(stderr, "created shm image: %dx%d\n", image->width, image->height); -+ } -+#endif -+ } -+ -+ if (!image) { -+ fprintf(stderr, "try_create_image: shm image create fail: image == NULL\n"); -+ if (scale_x > 0) { -+ image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL, -+ scale_x, scale_y, BitmapPad(dpy), 0); -+ } else { -+ 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, "try_create_image: malloc failed\n"); -+ exit(1); -+ } else { -+ fprintf(stderr, "try_create_image: created *non-shm* image: %dx%d\n", image->width, image->height); -+ } -+ } -+ fprintf(stderr, "try_create_image: image->bytes_per_line: %d\n", image->bytes_per_line); -+} -+ -+void create_image() { -+ image = NULL; -+ image_ycrop = NULL; -+ image_scale = NULL; -+ -+ fprintf(stderr, "create_image()\n"); -+ -+ if (CreateShmImage(-1) == NULL) { -+ appData.useShm = False; -+ } -+ if (appData.scale != NULL) { -+ if (appData.useXserverBackingStore) { -+ fprintf(stderr, "Cannot scale when using X11 backingstore.\n"); -+ } else { -+ double frac_x = -1.0, frac_y = -1.0; -+ -+ get_scale_values(&frac_x, &frac_y); -+ -+ if (frac_x < 0.0 || frac_y < 0.0) { -+ fprintf(stderr, "Cannot figure out scale factor!\n"); -+ goto bork; -+ } -+ -+ scale_factor_x = 0.0; -+ scale_factor_y = 0.0; -+ scale_x = 0; -+ scale_y = 0; -+ -+ -+ if (1) { -+ int w, h, hyc; -+ -+ w = scale_round(si.framebufferWidth, frac_x); -+ h = scale_round(si.framebufferHeight, frac_y); -+ hyc = h; -+ if (appData.yCrop > 0) { -+ hyc = scale_round(appData.yCrop, frac_y); -+ } -+ -+ /* image scale is full framebuffer */ -+ image_scale = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL, -+ si.framebufferWidth, si.framebufferHeight, BitmapPad(dpy), 0); -+ -+ image_scale->data = (char *) malloc(image_scale->bytes_per_line * image_scale->height); -+ -+ fprintf(stderr, "create_image: created image_scale %dx%d\n", image_scale->width, image_scale->height); -+ -+ if (!image_scale->data) { -+ fprintf(stderr, "create_image: malloc failed\n"); -+ XDestroyImage(image_scale); -+ fprintf(stderr, "create_image: destroyed 'image_scale'\n"); -+ image_scale = NULL; -+ } else { -+ int h2; -+ scale_factor_x = frac_x; -+ scale_factor_y = frac_y; -+ scale_x = w; -+ scale_y = h; -+ -+ XtVaSetValues(toplevel, XtNmaxWidth, w, XtNmaxHeight, hyc, NULL); -+ -+ h2 = scale_round(si.framebufferHeight, frac_y); -+ XtVaSetValues(desktop, XtNwidth, w, XtNheight, h2, NULL); -+ -+ } -+ fprintf(stderr, "create_image: scale: %dx%d %.4f %.4f\n", w, h, -+ scale_factor_x, scale_factor_y); -+ } -+ } -+ } -+ bork: -+ try_create_image(); -+} -+ -+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 == 1440) { -+ return 900; -+ } else if (w == 1600) { -+ return 1200; -+ } else if (w == 1680) { -+ return 1050; -+ } else if (w == 1920) { -+ return 1200; -+ } else { -+ int h = (3 * w) / 4; -+ return h; -+ } -+} -+ -+void check_tall(void) { -+ if (appData.appShare) { -+ return; -+ } -+ 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"); -+ appData.yCrop = -1; -+ } -+ } -+} - - /* - * DesktopInitBeforeRealization creates the "desktop" widget and the viewport -@@ -59,91 +528,1023 @@ - void - DesktopInitBeforeRealization() - { -- int i; -+ int i; -+ int h = si.framebufferHeight; -+ int w = si.framebufferWidth; -+ double frac_x = 1.0, frac_y = 1.0; -+ -+ start_time = dnow(); -+ -+ prev_fb_width = si.framebufferWidth; -+ prev_fb_height = si.framebufferHeight; -+ -+ if (appData.scale != NULL) { -+ get_scale_values(&frac_x, &frac_y); -+ if (frac_x > 0.0 && frac_y > 0.0) { -+ w = scale_round(w, frac_x); -+ h = scale_round(h, frac_y); -+ } else { -+ appData.scale = NULL; -+ } -+ } - -- 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); -+ XtVaSetValues(desktop, XtNwidth, w, XtNheight, h, NULL); - -- XtAddEventHandler(desktop, LeaveWindowMask|ExposureMask, -- True, HandleBasicDesktopEvent, NULL); -+ XtAddEventHandler(desktop, LeaveWindowMask|EnterWindowMask|ExposureMask, -+ True, HandleBasicDesktopEvent, NULL); - -- for (i = 0; i < 256; i++) -- modifierPressed[i] = False; -+ if (appData.yCrop) { -+ int hm; -+ if (appData.yCrop < 0) { -+ appData.yCrop = guessCrop(); -+ fprintf(stderr, "Set -ycrop to: %d\n", appData.yCrop); -+ } -+ hm = appData.yCrop; - -- image = NULL; -+ fprintf(stderr, "ycrop h: %d -> %d\n", hm, (int) (hm*frac_y)); - --#ifdef MITSHM -- if (appData.useShm) { -- image = CreateShmImage(); -- if (!image) -- appData.useShm = False; -- } -+ hm *= frac_y; -+ -+ XtVaSetValues(toplevel, XtNmaxHeight, hm, XtNheight, hm, NULL); -+ XtVaSetValues(form, XtNmaxHeight, hm, XtNheight, hm, NULL); -+ XtVaSetValues(viewport, XtNforceBars, False, NULL); -+ XSync(dpy, False); -+ } -+ -+ old_width = si.framebufferWidth; -+ old_height = si.framebufferHeight; -+ -+ for (i = 0; i < 256; i++) { -+ modifierPressed[i] = False; -+ } -+ -+ create_image(); -+} -+ -+#if 0 -+static Widget scrollbar_y = NULL; -+static int xsst = 2; - #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); -- } -- } -+#include <X11/Xaw/Scrollbar.h> -+ -+#if 0 -+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); -+ } -+ if (closure) {} - } - -+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); -+ } -+ } -+ if (closure) {} -+} -+#endif -+ -+extern double dnow(void); -+ -+void check_things() { -+ 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; -+ double fac = image_scale ? scale_factor_y : 1.0; -+ -+ if (first) { -+ first = 0; -+ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False); -+ } -+ if (appData.yCrop > 0 && appData.yCrop * fac < 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 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 (%d/%d)\n\n", sb, w0, h1); -+ -+ 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); -+ -+ appData.sbWidth = sb; -+ } -+ } -+ last_scrollbar = dnow(); -+ } -+ -+ if (now <= last + 0.25) { -+ return; -+ } -+ -+ if (image_scale) { -+ scale_check_zrle(); -+ } -+ -+ /* e.g. xrandr resize */ -+ dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy)); -+ dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy)); -+ -+ if (appData.scale != NULL) { -+ static Dimension last_w = 0, last_h = 0; -+ static double last_resize = 0.0; -+ Dimension w, h; -+ if (last_w == 0) { -+ XtVaGetValues(toplevel, XtNwidth, &last_w, XtNheight, &last_h, NULL); -+ last_resize = now; -+ } -+ if (now < last_resize + 0.5) { -+ ; -+ } else if (appData.fullScreen) { -+ ; -+ } else if (!strcmp(appData.scale, "auto")) { -+ XtVaGetValues(toplevel, XtNwidth, &w, XtNheight, &h, NULL); -+ if (w < 32 || h < 32) { -+ ; -+ } else if (last_w != w || last_h != h) { -+ Window rr, cr, r = DefaultRootWindow(dpy); -+ int rx, ry, wx, wy; -+ unsigned int mask; -+ /* make sure mouse buttons not pressed */ -+ if (XQueryPointer(dpy, r, &rr, &cr, &rx, &ry, &wx, &wy, &mask)) { -+ if (mask == 0) { -+ rescale_image(); -+ last_w = w; -+ last_h = h; -+ last_resize = dnow(); -+ } -+ } -+ } -+ } -+ } -+ -+ 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.useXserverBackingStore) { -+ Screen *s = DefaultScreenOfDisplay(dpy); -+ if (DoesBackingStore(s) != Always) { -+ fprintf(stderr, "X server does not do backingstore, disabling it.\n"); -+ appData.useXserverBackingStore = False; -+ } -+ } -+ -+ if (appData.useXserverBackingStore) { -+ 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); -+ waitCursor = XCreateFontCursor(dpy, XC_watch); -+ -+ 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); - -- XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); -+void -+DesktopCursorOff() -+{ -+ if (dotCursor3 == None) { -+ dotCursor3 = CreateDotCursor(3); -+ dotCursor4 = CreateDotCursor(4); -+ } -+ if (appData.viewOnly) { -+ XDefineCursor(dpy, desktopWin, dotCursor4); -+ } else { -+ XDefineCursor(dpy, desktopWin, dotCursor3); -+ } -+ FreeX11Cursor(); -+ FreeSoftCursor(); -+} -+ -+ -+#define CEIL(x) ( (double) ((int) (x)) == (x) ? \ -+ (double) ((int) (x)) : (double) ((int) (x) + 1) ) -+#define FLOOR(x) ( (double) ((int) (x)) ) -+ -+#if 0 -+static int nfix(int i, int n) { -+ if (i < 0) { -+ i = 0; -+ } else if (i >= n) { -+ i = n - 1; -+ } -+ return i; - } -+#else -+#define nfix(i, n) ( i < 0 ? 0 : ( (i >= n) ? (n - 1) : i ) ) -+#endif -+ -+int scale_round(int len, double fac) { -+ double eps = 0.000001; -+ -+ len = (int) (len * fac + eps); -+ if (len < 1) { -+ len = 1; -+ } -+ return len; -+} -+ -+static void scale_rect(double factor_x, double factor_y, int blend, int interpolate, -+ int *px, int *py, int *pw, int *ph, int solid) { -+ -+ int i, j, i1, i2, j1, j2; /* indices for scaled fb (dest) */ -+ int I, J, I1, I2, J1, J2; /* indices for main fb (source) */ -+ -+ double w, wx, wy, wtot; /* pixel weights */ -+ -+ double x1 = 0, y1, x2 = 0, y2; /* x-y coords for destination pixels edges */ -+ double dx, dy; /* size of destination pixel */ -+ double ddx=0, ddy=0; /* for interpolation expansion */ -+ -+ char *src, *dest; /* pointers to the two framebuffers */ -+ -+ unsigned short us = 0; -+ unsigned char uc = 0; -+ unsigned int ui = 0; -+ -+ int use_noblend_shortcut = 1; -+ int shrink; /* whether shrinking or expanding */ -+ static int constant_weights = -1, mag_int = -1; -+ static int last_Nx = -1, last_Ny = -1, cnt = 0; -+ static double last_factor = -1.0; -+ int b, k; -+ double pixave[4]; /* for averaging pixel values */ -+ -+ /* internal */ -+ -+ int X1, X2, Y1, Y2; - -+ int Nx = si.framebufferWidth; -+ int Ny = si.framebufferHeight; -+ -+ int nx = scale_round(Nx, factor_x); -+ int ny = scale_round(Ny, factor_y); -+ -+ int Bpp = image->bits_per_pixel / 8; -+ int dst_bytes_per_line = image->bytes_per_line; -+ int src_bytes_per_line = image_scale->bytes_per_line; -+ -+ unsigned long main_red_mask = image->red_mask; -+ unsigned long main_green_mask = image->green_mask; -+ unsigned long main_blue_mask = image->blue_mask; -+ int mark = 1; -+ -+ char *src_fb = image_scale->data; -+ char *dst_fb = image->data; -+ -+ static int nosolid = -1; -+ int sbdy = 3; -+ double fmax = factor_x > factor_y ? factor_x : factor_y; -+#if 0 -+ double fmin = factor_x < factor_y ? factor_x : factor_y; -+#endif -+ -+ X1 = *px; -+ X2 = *px + *pw; -+ Y1 = *py; -+ Y2 = *py + *ph; -+ -+ if (fmax > 1.0) { -+ /* try to avoid problems with bleeding... */ -+ sbdy = (int) (2.0 * fmax * sbdy); -+ } -+ -+ /* fprintf(stderr, "scale_rect: %dx%d+%d+%d\n", *pw, *ph, *px, *py); */ -+ -+ *px = (int) (*px * factor_x); -+ *py = (int) (*py * factor_y); -+ *pw = scale_round(*pw, factor_x); -+ *ph = scale_round(*ph, factor_y); -+ -+ if (nosolid < 0) { -+ if (getenv("SSVNC_NOSOLID")) { -+ nosolid = 1; -+ } else { -+ nosolid = 0; -+ } -+ } -+ if (nosolid) solid = 0; -+ -+#define rfbLog printf -+/* Begin taken from x11vnc scale: */ -+ -+ if (factor_x <= 1.0 || factor_y <= 1.0) { -+ shrink = 1; -+ } else { -+ shrink = 0; -+ interpolate = 1; -+ } -+ -+ /* -+ * N.B. width and height (real numbers) of a scaled pixel. -+ * both are > 1 (e.g. 1.333 for -scale 3/4) -+ * they should also be equal but we don't assume it. -+ * -+ * This new way is probably the best we can do, take the inverse -+ * of the scaling factor to double precision. -+ */ -+ dx = 1.0/factor_x; -+ dy = 1.0/factor_y; -+ -+ /* -+ * There is some speedup if the pixel weights are constant, so -+ * let's special case these. -+ * -+ * If scale = 1/n and n divides Nx and Ny, the pixel weights -+ * are constant (e.g. 1/2 => equal on 2x2 square). -+ */ -+ if (factor_x != last_factor || Nx != last_Nx || Ny != last_Ny) { -+ constant_weights = -1; -+ mag_int = -1; -+ last_Nx = Nx; -+ last_Ny = Ny; -+ last_factor = factor_x; -+ } -+ -+ if (constant_weights < 0 && factor_x != factor_y) { -+ constant_weights = 0; -+ mag_int = 0; -+ } else if (constant_weights < 0) { -+ int n = 0; -+ double factor = factor_x; -+ -+ constant_weights = 0; -+ mag_int = 0; -+ -+ for (i = 2; i<=128; i++) { -+ double test = ((double) 1)/ i; -+ double diff, eps = 1.0e-7; -+ diff = factor - test; -+ if (-eps < diff && diff < eps) { -+ n = i; -+ break; -+ } -+ } -+ if (! blend || ! shrink || interpolate) { -+ ; -+ } else if (n != 0) { -+ if (Nx % n == 0 && Ny % n == 0) { -+ static int didmsg = 0; -+ if (mark && ! didmsg) { -+ didmsg = 1; -+ rfbLog("scale_and_mark_rect: using " -+ "constant pixel weight speedup " -+ "for 1/%d\n", n); -+ } -+ constant_weights = 1; -+ } -+ } -+ -+ n = 0; -+ for (i = 2; i<=32; i++) { -+ double test = (double) i; -+ double diff, eps = 1.0e-7; -+ diff = factor - test; -+ if (-eps < diff && diff < eps) { -+ n = i; -+ break; -+ } -+ } -+ if (! blend && factor > 1.0 && n) { -+ mag_int = n; -+ } -+ } -+if (0) fprintf(stderr, "X1: %d Y1: %d X2: %d Y2: %d\n", X1, Y1, X2, Y2); -+ -+ if (mark && !shrink && blend) { -+ /* -+ * kludge: correct for interpolating blurring leaking -+ * up or left 1 destination pixel. -+ */ -+ if (X1 > 0) X1--; -+ if (Y1 > 0) Y1--; -+ } -+ -+ /* -+ * find the extent of the change the input rectangle induces in -+ * the scaled framebuffer. -+ */ -+ -+ /* Left edges: find largest i such that i * dx <= X1 */ -+ i1 = FLOOR(X1/dx); -+ -+ /* Right edges: find smallest i such that (i+1) * dx >= X2+1 */ -+ i2 = CEIL( (X2+1)/dx ) - 1; -+ -+ /* To be safe, correct any overflows: */ -+ i1 = nfix(i1, nx); -+ i2 = nfix(i2, nx) + 1; /* add 1 to make a rectangle upper boundary */ -+ -+ /* Repeat above for y direction: */ -+ j1 = FLOOR(Y1/dy); -+ j2 = CEIL( (Y2+1)/dy ) - 1; -+ -+ j1 = nfix(j1, ny); -+ j2 = nfix(j2, ny) + 1; -+ -+ /* -+ * special case integer magnification with no blending. -+ * vision impaired magnification usage is interested in this case. -+ */ -+ if (mark && ! blend && mag_int && Bpp != 3) { -+ int jmin, jmax, imin, imax; -+ -+ /* outer loop over *source* pixels */ -+ for (J=Y1; J < Y2; J++) { -+ jmin = J * mag_int; -+ jmax = jmin + mag_int; -+ for (I=X1; I < X2; I++) { -+ /* extract value */ -+ src = src_fb + J*src_bytes_per_line + I*Bpp; -+ if (Bpp == 4) { -+ ui = *((unsigned int *)src); -+ } else if (Bpp == 2) { -+ us = *((unsigned short *)src); -+ } else if (Bpp == 1) { -+ uc = *((unsigned char *)src); -+ } -+ imin = I * mag_int; -+ imax = imin + mag_int; -+ /* inner loop over *dest* pixels */ -+ for (j=jmin; j<jmax; j++) { -+ dest = dst_fb + j*dst_bytes_per_line + imin*Bpp; -+ for (i=imin; i<imax; i++) { -+ if (Bpp == 4) { -+ *((unsigned int *)dest) = ui; -+ } else if (Bpp == 2) { -+ *((unsigned short *)dest) = us; -+ } else if (Bpp == 1) { -+ *((unsigned char *)dest) = uc; -+ } -+ dest += Bpp; -+ } -+ } -+ } -+ } -+ goto markit; -+ } -+ -+ /* set these all to 1.0 to begin with */ -+ wx = 1.0; -+ wy = 1.0; -+ w = 1.0; -+ -+ /* -+ * Loop over destination pixels in scaled fb: -+ */ -+ for (j=j1; j<j2; j++) { -+ int jbdy = 1, I1_solid = 0; -+ -+ y1 = j * dy; /* top edge */ -+ if (y1 > Ny - 1) { -+ /* can go over with dy = 1/scale_fac */ -+ y1 = Ny - 1; -+ } -+ y2 = y1 + dy; /* bottom edge */ -+ -+ /* Find main fb indices covered by this dest pixel: */ -+ J1 = (int) FLOOR(y1); -+ J1 = nfix(J1, Ny); -+ -+ if (shrink && ! interpolate) { -+ J2 = (int) CEIL(y2) - 1; -+ J2 = nfix(J2, Ny); -+ } else { -+ J2 = J1 + 1; /* simple interpolation */ -+ ddy = y1 - J1; -+ } -+ -+ /* destination char* pointer: */ -+ dest = dst_fb + j*dst_bytes_per_line + i1*Bpp; -+ -+ if (solid) { -+ if (j1+sbdy <= j && j < j2-sbdy) { -+ jbdy = 0; -+ x1 = (i1+sbdy) * dx; -+ if (x1 > Nx - 1) { -+ x1 = Nx - 1; -+ } -+ I1_solid = (int) FLOOR(x1); -+ if (I1_solid >= Nx) I1_solid = Nx - 1; -+ } -+ } -+ -+ for (i=i1; i<i2; i++) { -+ int solid_skip = 0; -+ -+ if (solid) { -+ /* if the region is solid, we can use the noblend speedup */ -+ if (!jbdy && i1+sbdy <= i && i < i2-sbdy) { -+ solid_skip = 1; -+ /* pixels all the same so use X1: */ -+ I1 = I1_solid; -+ goto jsolid; -+ } -+ } -+ -+ x1 = i * dx; /* left edge */ -+ if (x1 > Nx - 1) { -+ /* can go over with dx = 1/scale_fac */ -+ x1 = Nx - 1; -+ } -+ x2 = x1 + dx; /* right edge */ -+ -+ /* Find main fb indices covered by this dest pixel: */ -+ I1 = (int) FLOOR(x1); -+ if (I1 >= Nx) I1 = Nx - 1; -+ -+ jsolid: -+ cnt++; -+ -+ if ((!blend && use_noblend_shortcut) || solid_skip) { -+ /* -+ * The noblend case involves no weights, -+ * and 1 pixel, so just copy the value -+ * directly. -+ */ -+ src = src_fb + J1*src_bytes_per_line + I1*Bpp; -+ if (Bpp == 4) { -+ *((unsigned int *)dest) -+ = *((unsigned int *)src); -+ } else if (Bpp == 2) { -+ *((unsigned short *)dest) -+ = *((unsigned short *)src); -+ } else if (Bpp == 1) { -+ *(dest) = *(src); -+ } else if (Bpp == 3) { -+ /* rare case */ -+ for (k=0; k<=2; k++) { -+ *(dest+k) = *(src+k); -+ } -+ } -+ dest += Bpp; -+ continue; -+ } -+ -+ if (shrink && ! interpolate) { -+ I2 = (int) CEIL(x2) - 1; -+ if (I2 >= Nx) I2 = Nx - 1; -+ } else { -+ I2 = I1 + 1; /* simple interpolation */ -+ ddx = x1 - I1; -+ } -+#if 0 -+if (first) fprintf(stderr, " I1=%d I2=%d J1=%d J2=%d\n", I1, I2, J1, J2); -+#endif -+ -+ /* Zero out accumulators for next pixel average: */ -+ for (b=0; b<4; b++) { -+ pixave[b] = 0.0; /* for RGB weighted sums */ -+ } -+ -+ /* -+ * wtot is for accumulating the total weight. -+ * It should always sum to 1/(scale_fac * scale_fac). -+ */ -+ wtot = 0.0; -+ -+ /* -+ * Loop over source pixels covered by this dest pixel. -+ * -+ * These "extra" loops over "J" and "I" make -+ * the cache/cacheline performance unclear. -+ * For example, will the data brought in from -+ * src for j, i, and J=0 still be in the cache -+ * after the J > 0 data have been accessed and -+ * we are at j, i+1, J=0? The stride in J is -+ * main_bytes_per_line, and so ~4 KB. -+ * -+ * Typical case when shrinking are 2x2 loop, so -+ * just two lines to worry about. -+ */ -+ for (J=J1; J<=J2; J++) { -+ /* see comments for I, x1, x2, etc. below */ -+ if (constant_weights) { -+ ; -+ } else if (! blend) { -+ if (J != J1) { -+ continue; -+ } -+ wy = 1.0; -+ -+ /* interpolation scheme: */ -+ } else if (! shrink || interpolate) { -+ if (J >= Ny) { -+ continue; -+ } else if (J == J1) { -+ wy = 1.0 - ddy; -+ } else if (J != J1) { -+ wy = ddy; -+ } -+ -+ /* integration scheme: */ -+ } else if (J < y1) { -+ wy = J+1 - y1; -+ } else if (J+1 > y2) { -+ wy = y2 - J; -+ } else { -+ wy = 1.0; -+ } -+ -+ src = src_fb + J*src_bytes_per_line + I1*Bpp; -+ -+ for (I=I1; I<=I2; I++) { -+ -+ /* Work out the weight: */ -+ -+ if (constant_weights) { -+ ; -+ } else if (! blend) { -+ /* -+ * Ugh, PseudoColor colormap is -+ * bad news, to avoid random -+ * colors just take the first -+ * pixel. Or user may have -+ * specified :nb to fraction. -+ * The :fb will force blending -+ * for this case. -+ */ -+ if (I != I1) { -+ continue; -+ } -+ wx = 1.0; -+ -+ /* interpolation scheme: */ -+ } else if (! shrink || interpolate) { -+ if (I >= Nx) { -+ continue; /* off edge */ -+ } else if (I == I1) { -+ wx = 1.0 - ddx; -+ } else if (I != I1) { -+ wx = ddx; -+ } -+ -+ /* integration scheme: */ -+ } else if (I < x1) { -+ /* -+ * source left edge (I) to the -+ * left of dest left edge (x1): -+ * fractional weight -+ */ -+ wx = I+1 - x1; -+ } else if (I+1 > x2) { -+ /* -+ * source right edge (I+1) to the -+ * right of dest right edge (x2): -+ * fractional weight -+ */ -+ wx = x2 - I; -+ } else { -+ /* -+ * source edges (I and I+1) completely -+ * inside dest edges (x1 and x2): -+ * full weight -+ */ -+ wx = 1.0; -+ } -+ -+ w = wx * wy; -+ wtot += w; -+ -+ /* -+ * We average the unsigned char value -+ * instead of char value: otherwise -+ * the minimum (char 0) is right next -+ * to the maximum (char -1)! This way -+ * they are spread between 0 and 255. -+ */ -+ if (Bpp == 4) { -+ /* unroll the loops, can give 20% */ -+ pixave[0] += w * ((unsigned char) *(src )); -+ pixave[1] += w * ((unsigned char) *(src+1)); -+ pixave[2] += w * ((unsigned char) *(src+2)); -+ pixave[3] += w * ((unsigned char) *(src+3)); -+ } else if (Bpp == 2) { -+ /* -+ * 16bpp: trickier with green -+ * split over two bytes, so we -+ * use the masks: -+ */ -+ us = *((unsigned short *) src); -+ pixave[0] += w*(us & main_red_mask); -+ pixave[1] += w*(us & main_green_mask); -+ pixave[2] += w*(us & main_blue_mask); -+ } else if (Bpp == 1) { -+ pixave[0] += w * -+ ((unsigned char) *(src)); -+ } else { -+ for (b=0; b<Bpp; b++) { -+ pixave[b] += w * -+ ((unsigned char) *(src+b)); -+ } -+ } -+ src += Bpp; -+ } -+ } -+ -+ if (wtot <= 0.0) { -+ wtot = 1.0; -+ } -+ wtot = 1.0/wtot; /* normalization factor */ -+ -+ /* place weighted average pixel in the scaled fb: */ -+ if (Bpp == 4) { -+ *(dest ) = (char) (wtot * pixave[0]); -+ *(dest+1) = (char) (wtot * pixave[1]); -+ *(dest+2) = (char) (wtot * pixave[2]); -+ *(dest+3) = (char) (wtot * pixave[3]); -+ } else if (Bpp == 2) { -+ /* 16bpp / 565 case: */ -+ pixave[0] *= wtot; -+ pixave[1] *= wtot; -+ pixave[2] *= wtot; -+ us = (main_red_mask & (int) pixave[0]) -+ | (main_green_mask & (int) pixave[1]) -+ | (main_blue_mask & (int) pixave[2]); -+ *( (unsigned short *) dest ) = us; -+ } else if (Bpp == 1) { -+ *(dest) = (char) (wtot * pixave[0]); -+ } else { -+ for (b=0; b<Bpp; b++) { -+ *(dest+b) = (char) (wtot * pixave[b]); -+ } -+ } -+ dest += Bpp; -+ } -+ } -+ markit: -+/* End taken from x11vnc scale: */ -+ if (0) {} -+} -+ -+void do_scale_stats(int width, int height) { -+ static double calls = 0.0, sum = 0.0, var = 0.0, last = 0.0; -+ double A = width * height; -+ -+ if (last == 0.0) { -+ last = dnow(); -+ } -+ -+ calls += 1.0; -+ sum += A; -+ var += A*A; -+ -+ if (dnow() > last + 4.0) { -+ double cnt = calls; -+ if (cnt <= 0.0) cnt = 1.0; -+ var /= cnt; -+ sum /= cnt; -+ var = var - sum * sum; -+ if (sum > 0.0) { -+ var = var / (sum*sum); -+ } -+ fprintf(stderr, "scale_rect stats: %10d %10.1f ave: %10.3f var-rat: %10.3f\n", (int) calls, sum * cnt, sum, var); -+ -+ calls = 0.0; -+ sum = 0.0; -+ var = 0.0; -+ last = dnow(); -+ } -+} -+ -+void put_image(int src_x, int src_y, int dst_x, int dst_y, int width, -+ int height, int solid) { -+ int db = 0; -+ int xmax = si.framebufferWidth; -+ int ymax = si.framebufferHeight; -+ -+if (db || 0) fprintf(stderr, "put_image(%d %d %d %d %d %d)\n", src_x, src_y, dst_x, dst_y, width, height); -+ -+ if (image_scale) { -+ int i; -+ static int scale_stats = -1; -+ -+ for (i=0; i < 2; i++) { -+ if (src_x > 0) src_x--; -+ if (src_y > 0) src_y--; -+ } -+ for (i=0; i < 4; i++) { -+ if (src_x + width < xmax) width++; -+ if (src_y + height < ymax) height++; -+ } -+ -+ if (db) fprintf(stderr, "put_image(%d %d %d %d %d %d)\n", src_x, src_y, dst_x, dst_y, width, height); -+ if (db) fprintf(stderr, "scale_rect(%d %d %d %d)\n", src_x, src_y, width, height); -+ -+ if (scale_stats < 0) { -+ if (getenv("SSVNC_SCALE_STATS")) { -+ scale_stats = 1; -+ } else { -+ scale_stats = 0; -+ } -+ } -+ if (scale_stats) { -+ do_scale_stats(width, height); -+ } -+ -+ scale_rect(scale_factor_x, scale_factor_y, 1, 0, &src_x, &src_y, &width, &height, solid); -+ dst_x = src_x; -+ dst_y = src_y; -+ } -+ -+#ifdef MITSHM -+ if (appData.useShm) { -+ double fac = image_scale ? scale_factor_y : 1.0; -+ if (image_ycrop == NULL) { -+ if (image_is_shm) { -+ XShmPutImage(dpy, desktopWin, gc, image, src_x, src_y, -+ dst_x, dst_y, width, height, False); -+ } else { -+ XPutImage(dpy, desktopWin, gc, image, src_x, src_y, -+ dst_x, dst_y, width, height); -+ } -+ } else if ((width < 32 && height < 32) || height > appData.yCrop * fac) { -+ 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; -+ } -+ XShmPutImage(dpy, desktopWin, gc, image_ycrop, 0, 0, -+ dst_x, dst_y, width, height, False); -+ } -+ } else -+#endif -+ { -+ XPutImage(dpy, desktopWin, gc, image, src_x, src_y, -+ dst_x, dst_y, width, height); -+ } -+} -+ -+#if 0 -+fprintf(stderr, "non-shmB image %d %d %d %d %d %d\n", src_x, src_y, dst_x, dst_y, width, height); -+fprintf(stderr, "shm image_ycrop %d %d %d %d %d %d\n", 0, 0, dst_x, dst_y, width, height); -+fprintf(stderr, "non-shmA image %d %d %d %d %d %d\n", src_x, src_y, dst_x, dst_y, width, height); -+#endif -+ -+void releaseAllPressedModifiers(void) { -+ int i; -+ static int debug_release = -1; -+ if (debug_release < 0) { -+ if (getenv("SSVNC_DEBUG_RELEASE")) { -+ debug_release = 1; -+ } else { -+ debug_release = 0; -+ } -+ } -+ if (debug_release) fprintf(stderr, "into releaseAllPressedModifiers()\n"); -+ for (i = 0; i < 256; i++) { -+ if (modifierPressed[i]) { -+ SendKeyEvent(XKeycodeToKeysym(dpy, i, 0), False); -+ modifierPressed[i] = False; -+ if (debug_release) fprintf(stderr, "releasing[%d] %s\n", i, XKeysymToString(XKeycodeToKeysym(dpy, i, 0))); -+ } -+ } -+} -+ -+#define PR_EXPOSE fprintf(stderr, "Expose: %04dx%04d+%04d+%04d %04d/%04d/%04d now: %8.4f rescale: %8.4f fullscreen: %8.4f\n", width, height, x, y, si.framebufferWidth, appData.yCrop, si.framebufferHeight, now - start_time, now - last_rescale, now - last_fullscreen); - - /* - * HandleBasicDesktopEvent - deal with expose and leave events. -@@ -152,42 +1553,529 @@ - static void - HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont) - { -- int i; -+ int x, y, width, height; -+ double now = dnow(); - -- switch (ev->type) { -+ if (w || ptr || cont) {} -+ -+ if (0) { -+ PR_EXPOSE; -+ } - -+ -+ 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; -+ -+ if (image_scale) { -+ int i; -+ x /= scale_factor_x; -+ y /= scale_factor_y; -+ width /= scale_factor_x; -+ height /= scale_factor_y; -+ /* make them a little wider to avoid painting errors */ -+ for (i=0; i < 3; i++) { -+ if (x > 0) x--; -+ if (y > 0) y--; -+ } -+ for (i=0; i < 6; i++) { -+ if (x + width < si.framebufferWidth) width++; -+ if (y + height < si.framebufferHeight) height++; -+ } -+ } - -- 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; -- } -- -- SendFramebufferUpdateRequest(ev->xexpose.x, ev->xexpose.y, -- ev->xexpose.width, ev->xexpose.height, False); -- break; -+ if (x + width > si.framebufferWidth) { -+ width = si.framebufferWidth - x; -+ if (width <= 0) { -+ break; -+ } -+ } -+ -+ if (y + height > si.framebufferHeight) { -+ height = si.framebufferHeight - y; -+ if (height <= 0) { -+ break; -+ } -+ } -+ -+ if (appData.useXserverBackingStore) { -+ SendFramebufferUpdateRequest(x, y, width, height, False); -+ } else { -+ int ok = 1; -+ double delay = 2.5; -+ if (appData.fullScreen && now < last_fullscreen + delay) { -+ int xmax = si.framebufferWidth; -+ int ymax = si.framebufferHeight; -+ if (appData.yCrop > 0) { -+ ymax = appData.yCrop; -+ } -+ xmax = scale_round(xmax, scale_factor_x); -+ ymax = scale_round(ymax, scale_factor_y); -+ if (dpyWidth < xmax) { -+ xmax = dpyWidth; -+ } -+ if (dpyHeight < ymax) { -+ ymax = dpyHeight; -+ } -+ if (x != 0 && y != 0) { -+ ok = 0; -+ } -+ if (width < 0.9 * xmax) { -+ ok = 0; -+ } -+ if (height < 0.9 * ymax) { -+ ok = 0; -+ } -+ } -+ if (appData.yCrop > 0) { -+ if (now < last_fullscreen + delay || now < last_rescale + delay) { -+ if (y + height > appData.yCrop) { -+ height = appData.yCrop - y; -+ } -+ } -+ } -+ if (ok) { -+ put_image(x, y, x, y, width, height, 0); -+ XSync(dpy, False); -+ } else { -+ fprintf(stderr, "Skip "); -+ PR_EXPOSE; -+ } -+ } -+ break; - - case LeaveNotify: -- for (i = 0; i < 256; i++) { -- if (modifierPressed[i]) { -- SendKeyEvent(XKeycodeToKeysym(dpy, i, 0), False); -- modifierPressed[i] = False; -- } -- } -- break; -+ releaseAllPressedModifiers(); -+ if (appData.fullScreen) { -+ fs_ungrab(1); -+ } -+ break; -+ case EnterNotify: -+ if (appData.fullScreen) { -+ fs_grab(1); -+ } -+ break; -+ case ClientMessage: -+ if (ev->xclient.window == XtWindow(desktop) && ev->xclient.message_type == XA_INTEGER && -+ ev->xclient.format == 8 && !strcmp(ev->xclient.data.b, "SendRFBUpdate")) { -+ SendIncrementalFramebufferUpdateRequest(); -+ } -+ break; - } -+ check_things(); -+} -+ -+extern Position desktopX, desktopY; -+ -+void x11vnc_appshare(char *cmd) { -+ char send[200], str[100]; -+ char *id = "cmd=id_cmd"; -+ int m_big = 80, m_fine = 15; -+ int resize = 100, db = 0; -+ -+ if (getenv("X11VNC_APPSHARE_DEBUG")) { -+ db = atoi(getenv("X11VNC_APPSHARE_DEBUG")); -+ } -+ -+ if (db) fprintf(stderr, "x11vnc_appshare: cmd=%s\n", cmd); -+ -+ str[0] = '\0'; -+ -+ if (!strcmp(cmd, "left")) { -+ sprintf(str, "%s:move:-%d+0", id, m_big); -+ } else if (!strcmp(cmd, "right")) { -+ sprintf(str, "%s:move:+%d+0", id, m_big); -+ } else if (!strcmp(cmd, "up")) { -+ sprintf(str, "%s:move:+0-%d", id, m_big); -+ } else if (!strcmp(cmd, "down")) { -+ sprintf(str, "%s:move:+0+%d", id, m_big); -+ } else if (!strcmp(cmd, "left-fine")) { -+ sprintf(str, "%s:move:-%d+0", id, m_fine); -+ } else if (!strcmp(cmd, "right-fine")) { -+ sprintf(str, "%s:move:+%d+0", id, m_fine); -+ } else if (!strcmp(cmd, "up-fine")) { -+ sprintf(str, "%s:move:+0-%d", id, m_fine); -+ } else if (!strcmp(cmd, "down-fine")) { -+ sprintf(str, "%s:move:+0+%d", id, m_fine); -+ } else if (!strcmp(cmd, "taller")) { -+ sprintf(str, "%s:resize:+0+%d", id, resize); -+ } else if (!strcmp(cmd, "shorter")) { -+ sprintf(str, "%s:resize:+0-%d", id, resize); -+ } else if (!strcmp(cmd, "wider")) { -+ sprintf(str, "%s:resize:+%d+0", id, resize); -+ } else if (!strcmp(cmd, "narrower")) { -+ sprintf(str, "%s:resize:-%d+0", id, resize); -+ } else if (!strcmp(cmd, "lower")) { -+ sprintf(str, "%s:lower", id); -+ } else if (!strcmp(cmd, "raise")) { -+ sprintf(str, "%s:raise", id); -+ } else if (!strcmp(cmd, "delete")) { -+ sprintf(str, "%s:wm_delete", id); -+ } else if (!strcmp(cmd, "position")) { -+ Position x, y; -+ int xi, yi; -+ -+ XtVaGetValues(toplevel, XtNx, &x, XtNy, &y, NULL); -+ xi = (int) x; -+ yi = (int) y; -+ if (appData.scale) { -+ double fx = 1.0, fy = 1.0; -+ get_scale_values(&fx, &fy); -+ if (fx > 0.0 && fy > 0.0) { -+ xi /= fx; -+ yi /= fx; -+ } -+ } -+ sprintf(str, "%s:geom:0x0+%d+%d", id, xi, yi); -+ fprintf(stderr, "str=%s\n", str); -+ } -+ if (strcmp(str, "")) { -+ Bool vo = appData.viewOnly; -+ strcpy(send, "X11VNC_APPSHARE_CMD:"); -+ strcat(send, str); -+ if (db) fprintf(stderr, "x11vnc_appshare: send=%s\n", send); -+ if (vo) appData.viewOnly = False; -+ SendClientCutText(send, strlen(send)); -+ if (vo) appData.viewOnly = True; -+ } -+} -+ -+void scroll_desktop(int horiz, int vert, double amount) { -+ Dimension h, w; -+ Position x, y; -+ Position x2, y2; -+ static int db = -1; -+ -+ if (db < 0) { -+ if (getenv("SSVNC_DEBUG_ESCAPE_KEYS")) { -+ db = 1; -+ } else { -+ db = 0; -+ } -+ } -+ -+ XtVaGetValues(form, XtNheight, &h, XtNwidth, &w, NULL); -+ XtVaGetValues(desktop, XtNx, &x, XtNy, &y, NULL); -+ -+ x2 = -x; -+ y2 = -y; -+ -+ if (amount == -1.0) { -+ int dx = horiz; -+ int dy = vert; -+ if (dx == 0 && dy == 0) { -+ return; -+ } -+ x2 -= dx; -+ y2 -= dy; -+ } else { -+ if (horiz) { -+ int dx = (int) (amount * w); -+ if (dx < 0) dx = -dx; -+ if (amount == 0.0) dx = 1; -+ if (horiz > 0) { -+ x2 += dx; -+ } else { -+ x2 -= dx; -+ } -+ if (x2 < 0) x2 = 0; -+ } -+ if (vert) { -+ int dy = (int) (amount * h); -+ if (amount == 0.0) dy = 1; -+ if (dy < 0) dy = -dy; -+ if (vert < 0) { -+ y2 += dy; -+ } else { -+ y2 -= dy; -+ } -+ if (y2 < 0) y2 = 0; -+ } -+ } -+ -+ if (db) fprintf(stderr, "%d %d %f viewport(%dx%d): %d %d -> %d %d\n", horiz, vert, amount, w, h, -x, -y, x2, y2); -+ XawViewportSetCoordinates(viewport, x2, y2); -+ -+ if (appData.fullScreen) { -+ XSync(dpy, False); -+ XtVaGetValues(desktop, XtNx, &x, XtNy, &y, NULL); -+ desktopX = -x; -+ desktopY = -y; -+ } else if (amount == -1.0) { -+ XSync(dpy, False); -+ } - } - -+void scale_desktop(int bigger, double frac) { -+ double current, new; -+ char tmp[100]; -+ char *s; -+ int fs; -+ -+ if (appData.scale == NULL) { -+ s = "1.0"; -+ } else { -+ s = appData.scale; -+ } -+ if (!strcmp(s, "auto")) { -+ fprintf(stderr, "scale_desktop: skipping scale mode '%s'\n", s); -+ return; -+ } else if (!strcmp(s, "fit")) { -+ fprintf(stderr, "scale_desktop: skipping scale mode '%s'\n", s); -+ return; -+ } else if (strstr(s, "x")) { -+ fprintf(stderr, "scale_desktop: skipping scale mode '%s'\n", s); -+ return; -+ } else if (!strcmp(s, "none")) { -+ s = "1.0"; -+ } -+ -+ if (sscanf(s, "%lf", ¤t) != 1) { -+ fprintf(stderr, "scale_desktop: skipping scale mode '%s'\n", s); -+ return; -+ } -+ if (bigger) { -+ new = current * (1.0 + frac); -+ } else { -+ new = current / (1.0 + frac); -+ } -+ if (0.99 < new && new < 1.01) { -+ new = 1.0; -+ } - -+ if (new > 5.0) { -+ fprintf(stderr, "scale_desktop: not scaling > 5.0: %f\n", new); -+ return; -+ } else if (new < 0.05) { -+ fprintf(stderr, "scale_desktop: not scaling < 0.05: %f\n", new); -+ return; -+ } -+ sprintf(tmp, "%.16f", new); -+ appData.scale = strdup(tmp); -+ -+ fs = 0; -+ if (appData.fullScreen) { -+ fs = 1; -+ FullScreenOff(); -+ } -+ if (1) { -+ double fx, fy; -+ get_scale_values(&fx, &fy); -+ if (fx > 0.0 && fy > 0.0) { -+ rescale_image(); -+ } -+ } -+ if (fs) { -+ FullScreenOn(); -+ } -+} -+ -+static int escape_mods[8]; -+static int escape_drag_in_progress = 0, last_x = 0, last_y = 0; -+static double last_drag = 0.0; -+static double last_key = 0.0; -+ -+static int escape_sequence_pressed(void) { -+ static char *prev = NULL; -+ char *str = "default"; -+ int sum, i, init = 0, pressed; -+ static int db = -1; -+ -+ if (db < 0) { -+ if (getenv("SSVNC_DEBUG_ESCAPE_KEYS")) { -+ db = 1; -+ } else { -+ db = 0; -+ } -+ } -+ -+ if (appData.escapeKeys != NULL) { -+ str = appData.escapeKeys; -+ } -+ if (prev == NULL) { -+ init = 1; -+ prev = strdup(str); -+ } else { -+ if (strcmp(prev, str)) { -+ init = 1; -+ free(prev); -+ prev = strdup(str); -+ } -+ } -+ if (db) fprintf(stderr, "str: %s\n", str); -+ -+ if (init) { -+ char *p, *s; -+ KeySym ks; -+ int k = 0, failed = 0; -+ -+ for (i = 0; i < 8; i++) { -+ escape_mods[i] = -1; -+ } -+ -+ if (!strcasecmp(str, "default")) { -+#if (defined(__MACH__) && defined(__APPLE__)) -+ s = strdup("Control_L,Meta_L"); -+#else -+ s = strdup("Alt_L,Super_L"); -+#endif -+ } else { -+ s = strdup(str); -+ } -+ -+ p = strtok(s, ",+ "); -+ while (p) { -+ ks = XStringToKeysym(p); -+ if (ks == XK_Shift_L || ks == XK_Shift_R) { -+ putenv("NO_X11VNC_APPSHARE=1"); -+ } -+ if (k >= 8) { -+ fprintf(stderr, "EscapeKeys: more than 8 modifier keys.\n"); -+ failed = 1; -+ break; -+ } -+ if (ks == NoSymbol) { -+ fprintf(stderr, "EscapeKeys: failed lookup for '%s'\n", p); -+ failed = 1; -+ break; -+ } else if (!IsModifierKey(ks)) { -+ fprintf(stderr, "EscapeKeys: not a modifier key '%s'\n", p); -+ failed = 1; -+ break; -+ } else { -+ KeyCode kc = XKeysymToKeycode(dpy, ks); -+ if (kc == NoSymbol) { -+ fprintf(stderr, "EscapeKeys: no keycode for modifier key '%s'\n", p); -+ failed = 1; -+ break; -+ } -+ if (db) fprintf(stderr, "set: %d %d\n", k, kc); -+ escape_mods[k++] = kc; -+ } -+ -+ p = strtok(NULL, ",+ "); -+ } -+ free(s); -+ -+ if (failed) { -+ for (i = 0; i < 8; i++) { -+ escape_mods[i] = -1; -+ } -+ } -+ } -+ -+ pressed = 1; -+ sum = 0; -+ for (i = 0; i < 8; i++) { -+ int kc = escape_mods[i]; -+ if (kc != -1 && kc < 256) { -+ if (db) fprintf(stderr, "try1: %d %d = %d\n", i, kc, modifierPressed[kc]); -+ if (!modifierPressed[kc]) { -+ pressed = 0; -+ break; -+ } else { -+ sum++; -+ } -+ } -+ } -+ if (sum == 0) pressed = 0; -+ -+ if (!pressed) { -+ /* user may have dragged mouse outside of toplevel window */ -+ int i, k; -+ int keystate[256]; -+ char keys[32]; -+ -+ /* so query server instead of modifierPressed[] */ -+ XQueryKeymap(dpy, keys); -+ for (i=0; i<32; i++) { -+ char c = keys[i]; -+ -+ for (k=0; k < 8; k++) { -+ if (c & 0x1) { -+ keystate[8*i + k] = 1; -+ } else { -+ keystate[8*i + k] = 0; -+ } -+ c = c >> 1; -+ } -+ } -+ -+ /* check again using keystate[] */ -+ pressed = 2; -+ sum = 0; -+ for (i = 0; i < 8; i++) { -+ int kc = escape_mods[i]; -+ if (kc != -1 && kc < 256) { -+ if (db) fprintf(stderr, "try2: %d %d = %d\n", i, kc, keystate[kc]); -+ if (!keystate[kc]) { -+ pressed = 0; -+ break; -+ } else { -+ sum++; -+ } -+ } -+ } -+ if (sum == 0) pressed = 0; -+ } -+ -+ return pressed; -+} -+ -+static int shift_is_down(void) { -+ int shift_down = 0; -+ KeyCode kc; -+ -+ if (appData.viewOnly) { -+ int i, k; -+ char keys[32]; -+ int keystate[256]; -+ -+ XQueryKeymap(dpy, keys); -+ for (i=0; i<32; i++) { -+ char c = keys[i]; -+ -+ for (k=0; k < 8; k++) { -+ if (c & 0x1) { -+ keystate[8*i + k] = 1; -+ } else { -+ keystate[8*i + k] = 0; -+ } -+ c = c >> 1; -+ } -+ } -+ -+ kc = XKeysymToKeycode(dpy, XK_Shift_L); -+ if (kc != NoSymbol && keystate[kc]) { -+ shift_down = 1; -+ } else { -+ kc = XKeysymToKeycode(dpy, XK_Shift_R); -+ if (kc != NoSymbol && keystate[kc]) { -+ shift_down = 1; -+ } -+ } -+ return shift_down; -+ } else { -+ kc = XKeysymToKeycode(dpy, XK_Shift_L); -+ if (kc != NoSymbol && modifierPressed[kc]) { -+ shift_down = 1; -+ } else { -+ kc = XKeysymToKeycode(dpy, XK_Shift_R); -+ if (kc != NoSymbol && modifierPressed[kc]) { -+ shift_down = 1; -+ } -+ } -+ return shift_down; -+ } -+} -+ - /* - * SendRFBEvent is an action which sends an RFB event. It can be used in two - * ways. Without any parameters it simply sends an RFB event corresponding to -@@ -201,127 +2089,406 @@ - * 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) - { -- KeySym ks; -- char keyname[256]; -- int buttonMask, x, y; -- -- if (appData.fullScreen && ev->type == MotionNotify) { -- if (BumpScroll(ev)) -- return; -- } -+ KeySym ks; -+ char keyname[256]; -+ int buttonMask, x, y; -+ int do_escape; -+ static int db = -1; -+ char *ek = appData.escapeKeys; -+ -+ if (db < 0) { -+ if (getenv("SSVNC_DEBUG_ESCAPE_KEYS")) { -+ db = 1; -+ } else { -+ db = 0; -+ } -+ } -+ -+ if (ev->type == MotionNotify || ev->type == KeyRelease) { -+ static double last = 0.0; -+ double now = dnow(); -+ if (now > last + 0.25) { -+ check_things(); -+ last = now; -+ } -+ } -+ -+ 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.fullScreen && ev->type == MotionNotify && !escape_drag_in_progress) { -+ if (BumpScroll(ev)) { -+ return; -+ } -+ } -+ -+ do_escape = 0; -+ if (ek != NULL && (ek[0] == 'n' || ek[0] == 'N') && !strcasecmp(ek, "never")) { -+ ; -+ } else if (appData.viewOnly) { -+ do_escape = 1; -+ } else if (appData.escapeActive) { -+ int skip = 0, is_key = 0; -+ -+ if (ev->type == KeyPress || ev->type == KeyRelease) { -+ is_key = 1; -+ XLookupString(&ev->xkey, keyname, 256, &ks, NULL); -+ if (IsModifierKey(ks)) { -+ skip = 1; -+ } -+ } -+ if (!skip) { -+ int es = escape_sequence_pressed(); -+ if (es == 1) { -+ do_escape = 1; -+ } else if (es == 2) { -+ if (is_key) { -+ if (dnow() < last_key + 5.0) { -+ do_escape = 1; -+ } -+ } else { -+ if (dnow() < last_drag + 5.0) { -+ do_escape = 1; -+ } -+ } -+ } -+ } -+ } -+ if (!do_escape) { -+ escape_drag_in_progress = 0; -+ } -+ if (db) fprintf(stderr, "do_escape: %d\n", do_escape); -+ -+ if (do_escape) { -+ int W = si.framebufferWidth; -+ int H = si.framebufferHeight; -+ int shift_down = 0; -+ -+ if (!getenv("NO_X11VNC_APPSHARE")) { -+ shift_down = shift_is_down(); -+ } -+ if (db) fprintf(stderr, "shift_down: %d\n", shift_down); -+ -+ 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 (db) fprintf(stderr, "ButtonRelease: %d %d %d\n", b->x_root, b->y_root, b->state); -+ if (b->button == 3) { -+ if (shift_down) { -+ x11vnc_appshare("delete"); -+ } else { -+ ShowPopup(w, ev, params, num_params); -+ } -+ } else if (escape_drag_in_progress && b->button == 1) { -+ escape_drag_in_progress = 0; -+ } -+ } else if (ev->type == ButtonPress) { -+ XButtonEvent *b = (XButtonEvent *) ev; -+ if (db) fprintf(stderr, "ButtonPress: %d %d %d\n", b->x_root, b->y_root, b->state); -+ if (b->button == 1) { -+ if (shift_down) { -+ x11vnc_appshare("position"); -+ } else { -+ escape_drag_in_progress = 1; -+ last_x = b->x_root; -+ last_y = b->y_root; -+ } -+ } else { -+ escape_drag_in_progress = 0; -+ } -+ } else if (ev->type == MotionNotify) { -+ XMotionEvent *m = (XMotionEvent *) ev; -+ if (escape_drag_in_progress) { -+ if (db) fprintf(stderr, "MotionNotify: %d %d %d\n", m->x_root, m->y_root, m->state); -+ scroll_desktop(m->x_root - last_x, m->y_root - last_y, -1.0); -+ last_x = m->x_root; -+ last_y = m->y_root; -+ } -+ } else if (ev->type == KeyRelease) { -+ int did = 1; -+ -+ XLookupString(&ev->xkey, keyname, 256, &ks, NULL); -+ if (ks == XK_1 || ks == XK_KP_1) { -+ set_server_scale(1); -+ } else if (ks == XK_2 || ks == XK_KP_2) { -+ set_server_scale(2); -+ } else if (ks == XK_3 || ks == XK_KP_3) { -+ 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_c || ks == XK_C) { -+ Toggle8bpp(w, ev, params, num_params); -+ } else if (ks == XK_x || ks == XK_X) { -+ ToggleX11Cursor(w, ev, params, num_params); -+ } else if (ks == XK_z || ks == XK_Z) { -+ ToggleTightZRLE(w, ev, params, num_params); -+ } else if (ks == XK_h || ks == XK_H) { -+ ToggleTightHextile(w, ev, params, num_params); -+ } else if (ks == XK_f || ks == XK_F) { -+ ToggleFileXfer(w, ev, params, num_params); -+ } else if (ks == XK_V) { -+ ToggleViewOnly(w, ev, params, num_params); -+ } else if (ks == XK_Q) { -+ Quit(w, ev, params, num_params); -+ } else if (ks == XK_l || ks == XK_L) { -+ ToggleFullScreen(w, ev, params, num_params); -+ } else if (ks == XK_a || ks == XK_A) { -+ ToggleCursorAlpha(w, ev, params, num_params); -+ } else if (ks == XK_s || ks == XK_S) { -+ SetScale(w, ev, params, num_params); -+ } else if (ks == XK_t || ks == XK_T) { -+ ToggleTextChat(w, ev, params, num_params); -+ } else if (ks == XK_e || ks == XK_E) { -+ SetEscapeKeys(w, ev, params, num_params); -+ } else if (ks == XK_g || ks == XK_G) { -+ ToggleXGrab(w, ev, params, num_params); -+ } else if (ks == XK_D) { -+ if (shift_down || appData.appShare) { -+ x11vnc_appshare("delete"); -+ } -+ } else if (ks == XK_M) { -+ if (shift_down || appData.appShare) { -+ x11vnc_appshare("position"); -+ } -+ } else if (ks == XK_Left) { -+ if (shift_down) { -+ x11vnc_appshare("left"); -+ } else { -+ scroll_desktop(-1, 0, 0.1); -+ } -+ } else if (ks == XK_Right) { -+ if (shift_down) { -+ x11vnc_appshare("right"); -+ } else { -+ scroll_desktop(+1, 0, 0.1); -+ } -+ } else if (ks == XK_Up) { -+ if (shift_down) { -+ x11vnc_appshare("up"); -+ } else { -+ scroll_desktop(0, +1, 0.1); -+ } -+ } else if (ks == XK_Down) { -+ if (shift_down) { -+ x11vnc_appshare("down"); -+ } else { -+ scroll_desktop(0, -1, 0.1); -+ } -+ } else if (ks == XK_KP_Left) { -+ if (shift_down) { -+ x11vnc_appshare("left-fine"); -+ } else { -+ scroll_desktop(-1, 0, 0.0); -+ } -+ } else if (ks == XK_KP_Right) { -+ if (shift_down) { -+ x11vnc_appshare("right-fine"); -+ } else { -+ scroll_desktop(+1, 0, 0.0); -+ } -+ } else if (ks == XK_KP_Up) { -+ if (shift_down) { -+ x11vnc_appshare("up-fine"); -+ } else { -+ scroll_desktop(0, +1, 0.0); -+ } -+ } else if (ks == XK_KP_Down) { -+ if (shift_down) { -+ x11vnc_appshare("down-fine"); -+ } else { -+ scroll_desktop(0, -1, 0.0); -+ } -+ } else if (ks == XK_Next || ks == XK_KP_Next) { -+ if (shift_down && ks == XK_Next) { -+ x11vnc_appshare("shorter"); -+ } else { -+ scroll_desktop(0, -1, 1.0); -+ } -+ } else if (ks == XK_Prior || ks == XK_KP_Prior) { -+ if (shift_down && ks == XK_Prior) { -+ x11vnc_appshare("taller"); -+ } else { -+ scroll_desktop(0, +1, 1.0); -+ } -+ } else if (ks == XK_End || ks == XK_KP_End) { -+ if (shift_down && ks == XK_End) { -+ x11vnc_appshare("narrower"); -+ } else { -+ scroll_desktop(+1, 0, 1.0); -+ } -+ } else if (ks == XK_Home || ks == XK_KP_Home) { -+ if (shift_down && ks == XK_Home) { -+ x11vnc_appshare("wider"); -+ } else { -+ scroll_desktop(-1, 0, 1.0); -+ } -+ } else if (ks == XK_equal || ks == XK_plus) { -+ if (shift_down) { -+ x11vnc_appshare("raise"); -+ } else { -+ scale_desktop(1, 0.1); -+ } -+ } else if (ks == XK_underscore || ks == XK_minus) { -+ if (shift_down) { -+ x11vnc_appshare("lower"); -+ } else { -+ scale_desktop(0, 0.1); -+ } -+ } else { -+ did = 0; -+ } -+ if (did) { -+ last_key = dnow(); -+ } -+ } -+ if (escape_drag_in_progress) { -+ last_drag = dnow(); -+ } -+ return; -+ } -+ if (appData.viewOnly) { -+ return; -+ } -+ -+ if (*num_params != 0) { -+ if (strncasecmp(params[0],"key",3) == 0) { -+ if (*num_params != 2) { -+ fprintf(stderr, "Invalid params: " -+ "SendRFBEvent(key|keydown|keyup,<keysym>)\n"); -+ return; -+ } -+ ks = XStringToKeysym(params[1]); -+ if (ks == NoSymbol) { -+ fprintf(stderr,"Invalid keysym '%s' passed to " -+ "SendRFBEvent\n", params[1]); -+ return; -+ } -+ if (strcasecmp(params[0],"keydown") == 0) { -+ SendKeyEvent(ks, 1); -+ } else if (strcasecmp(params[0],"keyup") == 0) { -+ SendKeyEvent(ks, 0); -+ } else if (strcasecmp(params[0],"key") == 0) { -+ SendKeyEvent(ks, 1); -+ SendKeyEvent(ks, 0); -+ } else { -+ fprintf(stderr,"Invalid event '%s' passed to " -+ "SendRFBEvent\n", params[0]); -+ return; -+ } -+ } else if (strcasecmp(params[0],"fbupdate") == 0) { -+ if (*num_params != 1) { -+ fprintf(stderr, "Invalid params: " -+ "SendRFBEvent(fbupdate)\n"); -+ return; -+ } -+ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, -+ si.framebufferHeight, False); -+ -+ } else if (strcasecmp(params[0],"ptr") == 0) { -+ if (*num_params == 4) { -+ x = atoi(params[1]); -+ y = atoi(params[2]); -+ buttonMask = atoi(params[3]); -+ SendPointerEvent(x, y, buttonMask); -+ } else if (*num_params == 2) { -+ switch (ev->type) { -+ case ButtonPress: -+ case ButtonRelease: -+ x = ev->xbutton.x; -+ y = ev->xbutton.y; -+ break; -+ case KeyPress: -+ case KeyRelease: -+ x = ev->xkey.x; -+ y = ev->xkey.y; -+ break; -+ default: -+ fprintf(stderr, "Invalid event caused " -+ "SendRFBEvent(ptr,<buttonMask>)\n"); -+ return; -+ } -+ buttonMask = atoi(params[1]); -+ SendPointerEvent(x, y, buttonMask); -+ } else { -+ fprintf(stderr, "Invalid params: " -+ "SendRFBEvent(ptr,<x>,<y>,<buttonMask>)\n" -+ " or SendRFBEvent(ptr,<buttonMask>)\n"); -+ return; -+ } -+ } else { -+ fprintf(stderr,"Invalid event '%s' passed to " -+ "SendRFBEvent\n", params[0]); -+ } -+ return; -+ } - -- if (*num_params != 0) { -- if (strncasecmp(params[0],"key",3) == 0) { -- if (*num_params != 2) { -- fprintf(stderr, -- "Invalid params: SendRFBEvent(key|keydown|keyup,<keysym>)\n"); -- return; -- } -- ks = XStringToKeysym(params[1]); -- if (ks == NoSymbol) { -- fprintf(stderr,"Invalid keysym '%s' passed to SendRFBEvent\n", -- params[1]); -- return; -- } -- if (strcasecmp(params[0],"keydown") == 0) { -- SendKeyEvent(ks, 1); -- } else if (strcasecmp(params[0],"keyup") == 0) { -- SendKeyEvent(ks, 0); -- } else if (strcasecmp(params[0],"key") == 0) { -- SendKeyEvent(ks, 1); -- SendKeyEvent(ks, 0); -- } else { -- fprintf(stderr,"Invalid event '%s' passed to SendRFBEvent\n", -- params[0]); -- return; -- } -- } else if (strcasecmp(params[0],"fbupdate") == 0) { -- if (*num_params != 1) { -- fprintf(stderr, "Invalid params: SendRFBEvent(fbupdate)\n"); -- return; -- } -- SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, -- si.framebufferHeight, False); -- } else if (strcasecmp(params[0],"ptr") == 0) { -- if (*num_params == 4) { -- x = atoi(params[1]); -- y = atoi(params[2]); -- buttonMask = atoi(params[3]); -- SendPointerEvent(x, y, buttonMask); -- } else if (*num_params == 2) { - switch (ev->type) { -+ case MotionNotify: -+ while (XCheckTypedWindowEvent(dpy, desktopWin, MotionNotify, ev)) { -+ ; /* discard all queued motion notify events */ -+ } -+ -+ SendPointerEvent(ev->xmotion.x, ev->xmotion.y, -+ (ev->xmotion.state & 0x1f00) >> 8); -+ return; -+ - case ButtonPress: -+ SendPointerEvent(ev->xbutton.x, ev->xbutton.y, -+ (((ev->xbutton.state & 0x1f00) >> 8) | -+ (1 << (ev->xbutton.button - 1)))); -+ return; -+ - case ButtonRelease: -- x = ev->xbutton.x; -- y = ev->xbutton.y; -- break; -+ SendPointerEvent(ev->xbutton.x, ev->xbutton.y, -+ (((ev->xbutton.state & 0x1f00) >> 8) & -+ ~(1 << (ev->xbutton.button - 1)))); -+ return; -+ - case KeyPress: - case KeyRelease: -- x = ev->xkey.x; -- y = ev->xkey.y; -- break; -- default: -- fprintf(stderr, -- "Invalid event caused SendRFBEvent(ptr,<buttonMask>)\n"); -- return; -- } -- buttonMask = atoi(params[1]); -- SendPointerEvent(x, y, buttonMask); -- } else { -- fprintf(stderr, -- "Invalid params: SendRFBEvent(ptr,<x>,<y>,<buttonMask>)\n" -- " or SendRFBEvent(ptr,<buttonMask>)\n"); -- return; -- } -- -- } else { -- fprintf(stderr,"Invalid event '%s' passed to SendRFBEvent\n", params[0]); -- } -- return; -- } -- -- switch (ev->type) { -+ XLookupString(&ev->xkey, keyname, 256, &ks, NULL); - -- case MotionNotify: -- while (XCheckTypedWindowEvent(dpy, desktopWin, MotionNotify, ev)) -- ; /* discard all queued motion notify events */ -- -- SendPointerEvent(ev->xmotion.x, ev->xmotion.y, -- (ev->xmotion.state & 0x1f00) >> 8); -- return; -- -- case ButtonPress: -- SendPointerEvent(ev->xbutton.x, ev->xbutton.y, -- (((ev->xbutton.state & 0x1f00) >> 8) | -- (1 << (ev->xbutton.button - 1)))); -- return; -- -- case ButtonRelease: -- SendPointerEvent(ev->xbutton.x, ev->xbutton.y, -- (((ev->xbutton.state & 0x1f00) >> 8) & -- ~(1 << (ev->xbutton.button - 1)))); -- return; -- -- case KeyPress: -- case KeyRelease: -- XLookupString(&ev->xkey, keyname, 256, &ks, NULL); -- -- if (IsModifierKey(ks)) { -- ks = XKeycodeToKeysym(dpy, ev->xkey.keycode, 0); -- modifierPressed[ev->xkey.keycode] = (ev->type == KeyPress); -- } -+ if (IsModifierKey(ks)) { -+ ks = XKeycodeToKeysym(dpy, ev->xkey.keycode, 0); -+ modifierPressed[ev->xkey.keycode] = (ev->type == KeyPress); -+ } - -- SendKeyEvent(ks, (ev->type == KeyPress)); -- return; -+ SendKeyEvent(ks, (ev->type == KeyPress)); -+ return; - -- default: -- fprintf(stderr,"Invalid event passed to SendRFBEvent\n"); -- } -+ default: -+ fprintf(stderr,"Invalid event passed to SendRFBEvent\n"); -+ } - } - - -@@ -329,68 +2496,255 @@ - * CreateDotCursor. - */ - -+#ifndef very_small_dot_cursor - static Cursor --CreateDotCursor() -+CreateDotCursor(int which) - { -- 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 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; -+ return cursor; - } -+#else -+static Cursor -+CreateDotCursor() -+{ -+ 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, always_skip = -1; -+ int singles_max = 64; -+ -+ if (always_skip < 0) { -+ if (getenv("SSVNC_NO_MAYBE_SYNC")) { -+ always_skip = 1; -+ } else { -+ always_skip = 0; -+ } -+ } -+ if (skip_maybe_sync || always_skip) { -+ return; -+ } -+#if 0 -+ if (width > 1 || height > 1) { -+ XSync(dpy, False); -+ singles = 0; -+ } else { -+ if (++singles >= singles_max) { -+ singles = 0; -+ XSync(dpy, False); -+ } -+ } -+#else -+ if (width * height >= singles_max) { -+ XSync(dpy, False); -+ singles = 0; -+ } else { -+ singles += width * height; -+ if (singles >= singles_max) { -+ XSync(dpy, False); -+ singles = 0; -+ } -+ } -+#endif -+} - /* -- * CopyDataToScreen. -+ * FillImage. - */ - - void --CopyDataToScreen(char *buf, int x, int y, int width, int height) -+FillScreen(int x, int y, int width, int height, unsigned long fill) - { -- if (appData.rawDelay != 0) { -- XFillRectangle(dpy, desktopWin, gc, x, y, width, height); -+ XImage *im = image_scale ? image_scale : image; -+ int bpp = im->bits_per_pixel; -+ int Bpp = im->bits_per_pixel / 8; -+ int Bpl = im->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; - -- XSync(dpy,False); -+#if 0 -+fprintf(stderr, "FillImage bpp=%d %04dx%04d+%04d+%04d -- 0x%x\n", bpp, width, height, x, y, fill); -+#endif -+ if (appData.chatOnly) { -+ return; -+ } - -- usleep(appData.rawDelay * 1000); -- } -+ 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; -+ } - -- 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); -- } -+ 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; -+ } -+ } - --#ifdef MITSHM -- if (appData.useShm) { -- XShmPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height, False); -- return; -- } -+ scr = im->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, 1); -+ 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; -+ XImage *im = image_scale ? image_scale : image; -+ int Bpp = im->bits_per_pixel / 8; -+ int Bpl = im->bytes_per_line; -+ int did2 = 0; -+ -+#if 0 -+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); - #endif -- XPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height); -+ copyrect2: -+ -+ if (y < src_y) { -+ src = im->data + src_y * Bpl + src_x * Bpp; -+ dst = im->data + y * Bpl + x * Bpp; -+ for (i = 0; i < height; i++) { -+ memmove(dst, src, Bpp * width); -+ src += Bpl; -+ dst += Bpl; -+ } -+ } else { -+ src = im->data + (src_y + height - 1) * Bpl + src_x * Bpp; -+ dst = im->data + (y + height - 1) * Bpl + x * Bpp; -+ for (i = 0; i < height; i++) { -+ memmove(dst, src, Bpp * width); -+ src -= Bpl; -+ dst -= Bpl; -+ } -+ } -+ -+ if (image_scale && !did2) { -+ im = image; -+ Bpp = im->bits_per_pixel / 8; -+ Bpl = im->bytes_per_line; -+ -+ x *= scale_factor_x; -+ y *= scale_factor_y; -+ src_x *= scale_factor_x; -+ src_y *= scale_factor_y; -+ width = scale_round(width, scale_factor_x); -+ height = scale_round(height, scale_factor_y); -+ -+ did2 = 1; -+ goto copyrect2; -+ } -+} -+ -+ -+/* -+ * CopyDataToScreen. -+ */ -+ -+void -+CopyDataToScreen(char *buf, int x, int y, int width, int height) -+{ -+ if (appData.chatOnly) { -+ return; -+ } -+ if (appData.rawDelay != 0) { -+ XFillRectangle(dpy, desktopWin, gc, x, y, width, height); -+ XSync(dpy,False); -+ usleep(appData.rawDelay * 1000); -+ } -+ -+ 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; -+ XImage *im = image_scale ? image_scale : image; -+ -+ if (scrWidthInBytes != im->bytes_per_line) scrWidthInBytes = im->bytes_per_line; -+ -+ scr = (im->data + y * scrWidthInBytes -+ + x * myFormat.bitsPerPixel / 8); -+ -+ for (h = 0; h < height; h++) { -+ memcpy(scr, buf, widthInBytes); -+ buf += widthInBytes; -+ scr += scrWidthInBytes; -+ } -+ } -+ -+ put_image(x, y, x, y, width, height, 0); -+ maybe_sync(width, height); - } - - -@@ -401,62 +2755,338 @@ - 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; -+ XImage *im = image_scale ? image_scale : image; -+ int p, q; -+ int xoff = 7 - (x & 7); -+ int xcur; -+ int fbwb = si.framebufferWidth / 8; -+ int src_width8 = im->bytes_per_line/1; -+ int src_width16 = im->bytes_per_line/2; -+ int src_width32 = im->bytes_per_line/4; -+ CARD8 *src1 = ((CARD8 *)im->data) + y * fbwb + x / 8; -+ CARD8 *srct; -+ CARD8 *src8 = ( (CARD8 *)im->data) + y * src_width8 + x; -+ CARD16 *src16 = ((CARD16 *)im->data) + y * src_width16 + x; -+ CARD32 *src32 = ((CARD32 *)im->data) + y * src_width32 + 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++; -- } -- } -- 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 32: -- for (q = 0; q < height; q++) { -- for (p = 0; p < width; p++) { -- *(scr32++) = BGR233ToPixel[*(buf++)]; -- } -- scr32 += si.framebufferWidth - width; -- } -- break; -- } -+ case 1: -+ for (q = 0; q < height; q++) { -+ xcur = xoff; -+ srct = src1; -+ for (p = 0; p < width; p++) { -+ *srct = ((*srct & ~(1 << xcur)) -+ | (BGR233ToPixel[*(buf++)] << xcur)); -+ -+ if (xcur-- == 0) { -+ xcur = 7; -+ srct++; -+ } -+ } -+ src1 += fbwb; -+ } -+ break; -+ -+ case 8: -+ for (q = 0; q < height; q++) { -+ for (p = 0; p < width; p++) { -+ *(src8++) = BGR233ToPixel[*(buf++)]; -+ } -+ src8 += src_width8 - width; -+ } -+ break; -+ -+ case 16: -+ for (q = 0; q < height; q++) { -+ for (p = 0; p < width; p++) { -+ *(src16++) = BGR233ToPixel[*(buf++)]; -+ } -+ src16 += src_width16 - width; -+ } -+ break; -+ -+ case 24: -+ if (isLSB) { -+ b0 = 0; b1 = 1; b2 = 2; -+ } else { -+ b0 = 2; b1 = 1; b2 = 0; -+ } -+ src8 = ((CARD8 *)im->data) + (y * si.framebufferWidth + x) * 3; -+ for (q = 0; q < height; q++) { -+ for (p = 0; p < width; p++) { -+ CARD32 v = BGR233ToPixel[*(buf++)]; -+ *(src8 + b0) = (unsigned char) ((v & 0x0000ff) >> 0); -+ *(src8 + b1) = (unsigned char) ((v & 0x00ff00) >> 8); -+ *(src8 + b2) = (unsigned char) ((v & 0xff0000) >> 16); -+ src8 += 3; -+ } -+ src8 += (si.framebufferWidth - width) * 3; -+ } -+ break; -+ -+ case 32: -+ for (q = 0; q < height; q++) { -+ for (p = 0; p < width; p++) { -+ *(src32++) = BGR233ToPixel[*(buf++)]; -+ } -+ src32 += src_width32 - width; -+ } -+ break; -+ } -+} -+ -+static void -+BGR565_24bpp(CARD16 *buf, int x, int y, int width, int height) -+{ -+ int p, q; -+ int b0, b1, b2; -+ XImage *im = image_scale ? image_scale : image; -+ unsigned char *src= (unsigned char *)im->data + (y * si.framebufferWidth + x) * 3; -+ -+ if (isLSB) { -+ b0 = 0; b1 = 1; b2 = 2; -+ } else { -+ b0 = 2; b1 = 1; b2 = 0; -+ } -+ -+ /* case 24: */ -+ for (q = 0; q < height; q++) { -+ for (p = 0; p < width; p++) { -+ CARD32 v = BGR565ToPixel[*(buf++)]; -+ *(src + b0) = (unsigned char) ((v & 0x0000ff) >> 0); -+ *(src + b1) = (unsigned char) ((v & 0x00ff00) >> 8); -+ *(src + b2) = (unsigned char) ((v & 0xff0000) >> 16); -+ src += 3; -+ } -+ src += (si.framebufferWidth - width) * 3; -+ } -+} -+ -+static void -+CopyBGR565ToScreen(CARD16 *buf, int x, int y, int width, int height) -+{ -+ int p, q; -+ XImage *im = image_scale ? image_scale : image; -+ int src_width32 = im->bytes_per_line/4; -+ CARD32 *src32 = ((CARD32 *)im->data) + y * src_width32 + 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++) { -+ *(src32++) = BGR565ToPixel[*(buf++)]; -+ } -+ src32 += src_width32 - width; -+ } -+} -+ -+static void reset_image(void) { -+ if (UsingShm()) { -+ ShmDetach(); -+ } -+ if (image && image->data) { -+ XDestroyImage(image); -+ fprintf(stderr, "reset_image: destroyed 'image'\n"); -+ } -+ image = NULL; -+ if (image_ycrop && image_ycrop->data) { -+ XDestroyImage(image_ycrop); -+ fprintf(stderr, "reset_image: destroyed 'image_ycrop'\n"); -+ } -+ image_ycrop = NULL; -+ if (image_scale && image_scale->data) { -+ XDestroyImage(image_scale); -+ fprintf(stderr, "reset_image: destroyed 'image_scale'\n"); -+ } -+ image_scale = NULL; -+ -+ if (UsingShm()) { -+ ShmCleanup(); -+ } -+ create_image(); -+ XFlush(dpy); -+} -+ -+void ReDoDesktop(void) { -+ int w, w0, h, h0, x, y, dw, dh; -+ int fs = 0; -+ int autoscale = 0; -+ Position x_orig, y_orig; -+ Dimension w_orig, h_orig; -+ -+ if (!appData.fullScreen && appData.scale != NULL && !strcmp(appData.scale, "auto")) { -+ autoscale = 1; -+ } -+ -+ fprintf(stderr, "ReDoDesktop: ycrop: %d\n", appData.yCrop); -+ -+ XtVaGetValues(toplevel, XtNx, &x_orig, XtNy, &y_orig, NULL); -+ XtVaGetValues(toplevel, XtNheight, &h_orig, XtNwidth, &w_orig, NULL); -+ -+ 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; -+ 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 (prev_fb_width != si.framebufferWidth || prev_fb_height != si.framebufferHeight) { -+ int xmax = si.framebufferWidth; -+ int ymax = si.framebufferHeight; -+ if (appData.yCrop > 0) { -+ ymax = appData.yCrop; -+ } -+ if (scale_x > 0) { -+ xmax = scale_round(xmax, scale_factor_x); -+ ymax = scale_round(ymax, scale_factor_y); -+ } -+ if (xmax < dpyWidth || ymax < dpyHeight) { -+ FullScreenOff(); -+ fs = 1; -+ } -+ } -+ } -+ -+ prev_fb_width = si.framebufferWidth; -+ prev_fb_height = si.framebufferHeight; -+ -+ if (appData.fullScreen) { -+ -+ int xmax = si.framebufferWidth; -+ int ymax = si.framebufferHeight; -+ if (scale_x > 0) { -+ xmax = scale_round(xmax, scale_factor_x); -+ ymax = scale_round(ymax, scale_factor_y); -+ } -+ -+ 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); -+ } -+ -+ /* XXX scaling?? */ -+ XtResizeWidget(desktop, xmax, ymax, 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; -+ w0 = w; -+ h0 = h; -+ if (appData.yCrop > 0) { -+ h = appData.yCrop; -+ } -+ if (image_scale) { -+ w = scale_round(w, scale_factor_x); -+ h = scale_round(h, scale_factor_y); -+ w0 = scale_round(w0, scale_factor_x); -+ h0 = scale_round(h0, scale_factor_y); -+ } -+ -+ if (w + dw >= dpyWidth) { -+ w = dpyWidth - dw; -+ } -+ if (h + dh >= dpyHeight) { -+ h = dpyHeight - dh; -+ } -+ -+ if (!autoscale) { -+ XtVaSetValues(toplevel, XtNmaxWidth, w, XtNmaxHeight, h, NULL); -+ } else { -+ XtVaSetValues(toplevel, XtNmaxWidth, dpyWidth, XtNmaxHeight, dpyHeight, NULL); -+ } -+ -+ XtVaSetValues(desktop, XtNwidth, w0, XtNheight, h0, NULL); -+ -+ XtResizeWidget(desktop, w0, h0, 0); -+ -+ if (appData.yCrop > 0) { -+ int ycrop = appData.yCrop; -+ if (image_scale) { -+ ycrop *= scale_factor_y; -+ } -+ XtVaSetValues(toplevel, XtNmaxHeight, ycrop, NULL); -+ XtVaSetValues(form, XtNmaxHeight, ycrop, NULL); -+ } -+ -+ x = (dpyWidth - w - dw)/2; -+ y = (dpyHeight - h - dh)/2; -+ -+ if (!autoscale) { -+ -+ if (!getenv("VNCVIEWER_ALWAYS_RECENTER")) { -+ int x_cm_old, y_cm_old; -+ int x_cm_new, y_cm_new; -+ int x_try, y_try; -+ -+ x_cm_old = (int) x_orig + ((int) w_orig)/2; -+ y_cm_old = (int) y_orig + ((int) h_orig)/2; -+ -+ x_cm_new = dpyWidth/2; -+ y_cm_new = dpyHeight/2; -+ -+ x_try = x + (x_cm_old - x_cm_new); -+ y_try = y + (y_cm_old - y_cm_new); -+ if (x_try < 0) { -+ x_try = 0; -+ } -+ if (y_try < 0) { -+ y_try = 0; -+ } -+ if (x_try + w + dw > dpyWidth) { -+ x_try = dpyWidth - w - dw; -+ } -+ if (y_try + h + dh > dpyHeight) { -+ y_try = dpyHeight - h - dh; -+ } -+ x = x_try; -+ y = y_try; -+ } -+ -+ XtConfigureWidget(toplevel, x + dw, y + dh, w, h, 0); -+ } -+ -+ reset_image(); -+ -+ if (fs) { -+ FullScreenOn(); -+ } - } -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 2010-02-25 22:33:06.000000000 -0500 -@@ -25,75 +25,564 @@ - #include <X11/Xaw/Dialog.h> - - static Bool serverDialogDone = False; -+static Bool userDialogDone = False; - static Bool passwordDialogDone = False; -+static Bool ycropDialogDone = False; -+static Bool scaleDialogDone = False; -+static Bool escapeDialogDone = False; -+static Bool scbarDialogDone = False; -+static Bool scaleNDialogDone = False; -+static Bool qualityDialogDone = False; -+static Bool compressDialogDone = False; -+ -+extern void popupFixer(Widget wid); -+ -+int use_tty(void) { -+ if (appData.notty) { -+ return 0; -+ } else if (!isatty(0)) { -+ return 0; -+ } -+ return 1; -+} -+ -+void -+ScaleDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ scaleDialogDone = True; -+ if (w || event || params || num_params) {} -+} -+ -+void -+EscapeDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ escapeDialogDone = True; -+ if (w || event || params || num_params) {} -+} -+ -+void dialog_over(Widget wid) { -+ if (appData.fullScreen) { -+ if (!net_wm_supported()) { -+ XtVaSetValues(wid, XtNoverrideRedirect, True, NULL); -+ XSync(dpy, True); -+ } -+ } -+} -+ -+extern int XError_ign; -+ -+void dialog_input(Widget wid) { -+ XError_ign = 1; -+ XSetInputFocus(dpy, XtWindow(wid), RevertToParent, CurrentTime); -+ XSync(dpy, False); -+ usleep(30 * 1000); -+ XSync(dpy, False); -+ usleep(20 * 1000); -+ XSync(dpy, False); -+ XError_ign = 0; -+} -+ -+static void rmNL(char *s) { -+ int len; -+ if (s == NULL) { -+ return; -+ } -+ len = strlen(s); -+ if (len > 0 && s[len-1] == '\n') { -+ s[len-1] = '\0'; -+ } -+} -+ -+static void wm_delete(Widget w, char *func) { -+ char str[1024]; -+ Atom wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False); -+ XSetWMProtocols(dpy, XtWindow(w), &wmDeleteWindow, 1); -+ if (func) { -+ sprintf(str, "<Message>WM_PROTOCOLS: %s", func); -+ XtOverrideTranslations(w, XtParseTranslationTable (str)); -+ } -+} -+ -+static void xtmove(Widget w) { -+ XtMoveWidget(w, WidthOfScreen(XtScreen(w))*2/5, HeightOfScreen(XtScreen(w))*2/5); -+} -+ -+char * -+DoScaleDialog() -+{ -+ Widget pshell, dialog; -+ char *scaleValue; -+ char *valueString; -+ -+ pshell = XtVaCreatePopupShell("scaleDialog", transientShellWidgetClass, -+ toplevel, NULL); -+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); -+ -+ dialog_over(pshell); -+ -+ if (0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); -+ XtPopup(pshell, XtGrabNonexclusive); -+ XtRealizeWidget(pshell); -+ -+ if (appData.scale != NULL) { -+ String label; -+ char tmp[410]; -+ XtVaGetValues(dialog, XtNlabel, &label, NULL); -+ if (strlen(label) + strlen(appData.scale) < 400) { -+ sprintf(tmp, "%s %s", label, appData.scale); -+ XtVaSetValues(dialog, XtNlabel, tmp, NULL); -+ } -+ } -+ -+ -+ if (1 && appData.popupFix) { -+ popupFixer(pshell); -+ } else { -+ xtmove(pshell); -+ } -+ dialog_input(pshell); -+ wm_delete(pshell, "ScaleDialogDone()"); -+ -+ scaleDialogDone = False; -+ -+ while (!scaleDialogDone) { -+ XtAppProcessEvent(appContext, XtIMAll); -+ } -+ -+ valueString = XawDialogGetValueString(dialog); -+ rmNL(valueString); -+ scaleValue = XtNewString(valueString); -+ -+ XtPopdown(pshell); -+ return scaleValue; -+} -+ -+char * -+DoEscapeKeysDialog() -+{ -+ Widget pshell, dialog; -+ char *escapeValue; -+ char *valueString; -+ char *curr = appData.escapeKeys ? appData.escapeKeys : "default"; -+ -+ pshell = XtVaCreatePopupShell("escapeDialog", transientShellWidgetClass, -+ toplevel, NULL); -+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); -+ -+ dialog_over(pshell); -+ -+ if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); -+ XtPopup(pshell, XtGrabNonexclusive); -+ XtRealizeWidget(pshell); -+ -+ if (curr != NULL) { -+ String label; -+ char tmp[3010]; -+ XtVaGetValues(dialog, XtNlabel, &label, NULL); -+ if (strlen(label) + strlen(curr) < 3000) { -+ sprintf(tmp, "%s %s", label, curr); -+ XtVaSetValues(dialog, XtNlabel, tmp, NULL); -+ } -+ } -+ -+ if (appData.popupFix) { -+ popupFixer(pshell); -+ } else { -+ /* too big */ -+ if (0) xtmove(pshell); -+ } -+ dialog_input(pshell); -+ wm_delete(pshell, "EscapeDialogDone()"); -+ -+ escapeDialogDone = False; -+ -+ while (!escapeDialogDone) { -+ XtAppProcessEvent(appContext, XtIMAll); -+ } -+ -+ valueString = XawDialogGetValueString(dialog); -+ rmNL(valueString); -+ escapeValue = XtNewString(valueString); -+ -+ XtPopdown(pshell); -+ return escapeValue; -+} -+ -+void -+YCropDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ ycropDialogDone = True; -+ if (w || event || params || num_params) {} -+} -+ -+char * -+DoYCropDialog() -+{ -+ Widget pshell, dialog; -+ char *ycropValue; -+ char *valueString; -+ -+ pshell = XtVaCreatePopupShell("ycropDialog", transientShellWidgetClass, -+ toplevel, NULL); -+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); -+ -+ dialog_over(pshell); -+ -+ if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); -+ XtPopup(pshell, XtGrabNonexclusive); -+ XtRealizeWidget(pshell); -+ -+ if (1 && appData.popupFix) { -+ popupFixer(pshell); -+ } else { -+ xtmove(pshell); -+ } -+ dialog_input(pshell); -+ wm_delete(pshell, "YCropDialogDone()"); -+ -+ ycropDialogDone = False; -+ -+ while (!ycropDialogDone) { -+ XtAppProcessEvent(appContext, XtIMAll); -+ } -+ -+ valueString = XawDialogGetValueString(dialog); -+ rmNL(valueString); -+ ycropValue = XtNewString(valueString); -+ -+ XtPopdown(pshell); -+ return ycropValue; -+} -+ -+void -+ScbarDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ scbarDialogDone = True; -+ if (w || event || params || num_params) {} -+} -+ -+char * -+DoScbarDialog() -+{ -+ Widget pshell, dialog; -+ char *scbarValue; -+ char *valueString; -+ -+ pshell = XtVaCreatePopupShell("scbarDialog", transientShellWidgetClass, -+ toplevel, NULL); -+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); -+ -+ dialog_over(pshell); -+ -+ if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); -+ XtPopup(pshell, XtGrabNonexclusive); -+ XtRealizeWidget(pshell); -+ -+ if (1 && appData.popupFix) { -+ popupFixer(pshell); -+ } else { -+ xtmove(pshell); -+ } -+ dialog_input(pshell); -+ wm_delete(pshell, "ScbarDialogDone()"); -+ -+ scbarDialogDone = False; -+ -+ while (!scbarDialogDone) { -+ XtAppProcessEvent(appContext, XtIMAll); -+ } -+ -+ valueString = XawDialogGetValueString(dialog); -+ rmNL(valueString); -+ scbarValue = XtNewString(valueString); -+ -+ XtPopdown(pshell); -+ return scbarValue; -+} -+ -+void -+ScaleNDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ scaleNDialogDone = True; -+ if (w || event || params || num_params) {} -+} -+ -+char * -+DoScaleNDialog() -+{ -+ Widget pshell, dialog; -+ char *scaleNValue; -+ char *valueString; -+ -+ pshell = XtVaCreatePopupShell("scaleNDialog", transientShellWidgetClass, -+ toplevel, NULL); -+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); -+ -+ dialog_over(pshell); -+ wm_delete(pshell, "ScaleNDialogDone()"); -+ -+ if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); -+ XtPopup(pshell, XtGrabNonexclusive); -+ XtRealizeWidget(pshell); -+ -+ if (appData.popupFix) { -+ popupFixer(pshell); -+ } else { -+ xtmove(pshell); -+ } -+ dialog_input(pshell); -+ wm_delete(pshell, "ScaleNDialogDone()"); -+ -+ scaleNDialogDone = False; -+ -+ while (!scaleNDialogDone) { -+ XtAppProcessEvent(appContext, XtIMAll); -+ } -+ -+ valueString = XawDialogGetValueString(dialog); -+ rmNL(valueString); -+ scaleNValue = XtNewString(valueString); -+ -+ XtPopdown(pshell); -+ return scaleNValue; -+} -+ -+void -+QualityDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ qualityDialogDone = True; -+ if (w || event || params || num_params) {} -+} -+ -+char * -+DoQualityDialog() -+{ -+ Widget pshell, dialog; -+ char *qualityValue; -+ char *valueString; -+ -+ pshell = XtVaCreatePopupShell("qualityDialog", transientShellWidgetClass, -+ toplevel, NULL); -+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); -+ -+ dialog_over(pshell); -+ -+ if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); -+ XtPopup(pshell, XtGrabNonexclusive); -+ XtRealizeWidget(pshell); -+ -+ if (1 && appData.popupFix) { -+ popupFixer(pshell); -+ } else { -+ xtmove(pshell); -+ } -+ dialog_input(pshell); -+ wm_delete(pshell, "QualityDialogDone() HideQuality()"); -+ -+ qualityDialogDone = False; -+ -+ while (!qualityDialogDone) { -+ XtAppProcessEvent(appContext, XtIMAll); -+ } -+ -+ valueString = XawDialogGetValueString(dialog); -+ rmNL(valueString); -+ qualityValue = XtNewString(valueString); -+ -+ XtPopdown(pshell); -+ return qualityValue; -+} -+ -+void -+CompressDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ compressDialogDone = True; -+ if (w || event || params || num_params) {} -+} -+ -+char * -+DoCompressDialog() -+{ -+ Widget pshell, dialog; -+ char *compressValue; -+ char *valueString; -+ -+ fprintf(stderr, "compress start:\n"); -+ -+ pshell = XtVaCreatePopupShell("compressDialog", transientShellWidgetClass, -+ toplevel, NULL); -+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); -+ -+ dialog_over(pshell); -+ -+ if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); -+ XtPopup(pshell, XtGrabNonexclusive); -+ XtRealizeWidget(pshell); -+ -+ if (1 && appData.popupFix) { -+ popupFixer(pshell); -+ } else { -+ xtmove(pshell); -+ } -+ dialog_input(pshell); -+ wm_delete(pshell, "CompressDialogDone() HideCompress()"); -+ -+ compressDialogDone = False; -+ -+ while (!compressDialogDone) { -+ XtAppProcessEvent(appContext, XtIMAll); -+ } -+ -+ valueString = XawDialogGetValueString(dialog); -+ rmNL(valueString); -+ compressValue = XtNewString(valueString); -+ -+ fprintf(stderr, "compress done: %s\n", compressValue); -+ -+ XtPopdown(pshell); -+ return compressValue; -+} - - void - ServerDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) - { -- serverDialogDone = True; -+ serverDialogDone = True; -+ if (w || event || params || num_params) {} - } - - char * - DoServerDialog() - { -- Widget pshell, dialog; -- char *vncServerName; -- char *valueString; -+ Widget pshell, dialog; -+ char *vncServerName; -+ char *valueString; - -- pshell = XtVaCreatePopupShell("serverDialog", transientShellWidgetClass, -+ pshell = XtVaCreatePopupShell("serverDialog", transientShellWidgetClass, - toplevel, NULL); -- dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); -+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); - -- XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, -- HeightOfScreen(XtScreen(pshell))*2/5); -- XtPopup(pshell, XtGrabNonexclusive); -- XtRealizeWidget(pshell); -+ dialog_over(pshell); - -- serverDialogDone = False; -+ if (0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); -+ XtPopup(pshell, XtGrabNonexclusive); -+ XtRealizeWidget(pshell); -+ -+ if (0 && appData.popupFix) { -+ popupFixer(pshell); -+ } else { -+ xtmove(pshell); -+ } -+#if 0 -+ dialog_input(pshell); -+#endif -+ wm_delete(pshell, "ServerDialogDone()"); -+ -+ serverDialogDone = False; -+ -+ while (!serverDialogDone) { -+ XtAppProcessEvent(appContext, XtIMAll); -+ } -+ -+ valueString = XawDialogGetValueString(dialog); -+ rmNL(valueString); -+ vncServerName = XtNewString(valueString); - -- while (!serverDialogDone) { -- XtAppProcessEvent(appContext, XtIMAll); -- } -+ XtPopdown(pshell); -+ return vncServerName; -+} - -- valueString = XawDialogGetValueString(dialog); -- vncServerName = XtNewString(valueString); -+void -+UserDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ userDialogDone = True; -+ if (w || event || params || num_params) {} -+} - -- XtPopdown(pshell); -- return vncServerName; -+char * -+DoUserDialog() -+{ -+ Widget pshell, dialog; -+ char *userName; -+ char *valueString; -+ -+ pshell = XtVaCreatePopupShell("userDialog", transientShellWidgetClass, -+ toplevel, NULL); -+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); -+ -+ dialog_over(pshell); -+ -+ if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); -+ XtPopup(pshell, XtGrabNonexclusive); -+ XtRealizeWidget(pshell); -+ -+ if (0 && appData.popupFix) { -+ popupFixer(pshell); -+ } else { -+ xtmove(pshell); -+ } -+#if 0 -+ dialog_input(pshell); -+#endif -+ wm_delete(pshell, "UserDialogDone()"); -+ -+ userDialogDone = False; -+ -+ while (!userDialogDone) { -+ XtAppProcessEvent(appContext, XtIMAll); -+ } -+ -+ valueString = XawDialogGetValueString(dialog); -+ rmNL(valueString); -+ userName = XtNewString(valueString); -+ -+ XtPopdown(pshell); -+ return userName; - } - - void --PasswordDialogDone(Widget w, XEvent *event, String *params, -- Cardinal *num_params) -+PasswordDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) - { -- passwordDialogDone = True; -+ passwordDialogDone = True; -+ if (w || event || params || num_params) {} - } - - char * - DoPasswordDialog() - { -- Widget pshell, dialog; -- char *password; -- char *valueString; -+ Widget pshell, dialog; -+ char *password; -+ char *valueString; - -- pshell = XtVaCreatePopupShell("passwordDialog", transientShellWidgetClass, -+ pshell = XtVaCreatePopupShell("passwordDialog", 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); -- -- passwordDialogDone = False; -+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); - -- while (!passwordDialogDone) { -- XtAppProcessEvent(appContext, XtIMAll); -- } -+ dialog_over(pshell); - -- valueString = XawDialogGetValueString(dialog); -- password = XtNewString(valueString); -+ if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); -+ XtPopup(pshell, XtGrabNonexclusive); -+ XtRealizeWidget(pshell); -+ -+ if (0 && appData.popupFix) { -+ popupFixer(pshell); -+ } else { -+ xtmove(pshell); -+ } -+#if 0 -+ dialog_input(pshell); -+#endif -+ wm_delete(pshell, "PasswordDialogDone()"); -+ -+ passwordDialogDone = False; -+ -+ while (!passwordDialogDone) { -+ XtAppProcessEvent(appContext, XtIMAll); -+ } -+ -+ valueString = XawDialogGetValueString(dialog); -+ rmNL(valueString); -+ password = XtNewString(valueString); - -- XtPopdown(pshell); -- return password; -+ XtPopdown(pshell); -+ return password; - } -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 2010-02-25 22:37:49.000000000 -0500 -@@ -22,20 +22,24 @@ - */ - - #include <vncviewer.h> -+#include <time.h> - #include <X11/Xaw/Form.h> - #include <X11/Xaw/Viewport.h> - #include <X11/Xaw/Toggle.h> - - 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; --static Position desktopX, desktopY; -+Position desktopX, desktopY; - static Dimension viewportWidth, viewportHeight; - static Dimension scrollbarWidth, scrollbarHeight; - - -+int scale_round(int len, double fac); - - /* - * FullScreenOn goes into full-screen mode. It makes the toplevel window -@@ -78,112 +82,456 @@ - * variables so that FullScreenOff can use them. - */ - --void --FullScreenOn() --{ -- Dimension toplevelWidth, toplevelHeight; -- Dimension oldViewportWidth, oldViewportHeight, clipWidth, clipHeight; -- Position viewportX, viewportY; -- -- appData.fullScreen = True; -- -- if (si.framebufferWidth > dpyWidth || si.framebufferHeight > dpyHeight) { -- -- XtVaSetValues(viewport, XtNforceBars, True, NULL); -- XtVaGetValues(viewport, XtNwidth, &oldViewportWidth, -- XtNheight, &oldViewportHeight, NULL); -- XtVaGetValues(XtNameToWidget(viewport, "clip"), -- XtNwidth, &clipWidth, XtNheight, &clipHeight, NULL); -- -- scrollbarWidth = oldViewportWidth - clipWidth; -- scrollbarHeight = oldViewportHeight - clipHeight; -- -- if (si.framebufferWidth > dpyWidth) { -- viewportWidth = toplevelWidth = dpyWidth + scrollbarWidth; -- } else { -- viewportWidth = si.framebufferWidth + scrollbarWidth; -- toplevelWidth = dpyWidth; -- } -- -- if (si.framebufferHeight > dpyHeight) { -- viewportHeight = toplevelHeight = dpyHeight + scrollbarHeight; -- } else { -- viewportHeight = si.framebufferHeight + scrollbarHeight; -- toplevelHeight = dpyHeight; -- } -- -- } else { -- viewportWidth = si.framebufferWidth; -- viewportHeight = si.framebufferHeight; -- toplevelWidth = dpyWidth; -- toplevelHeight = dpyHeight; -- } -+int net_wm_supported(void) { -+ unsigned char *data; -+ unsigned long items_read, items_left, i; -+ int ret, format; -+ Window wm; -+ Atom type; -+ Atom _NET_SUPPORTING_WM_CHECK; -+ Atom _NET_SUPPORTED; -+ Atom _NET_WM_STATE; -+ Atom _NET_WM_STATE_FULLSCREEN; -+ -+ static time_t last_check = 0; -+ static int fs_supported = -1; -+ -+ if (fs_supported >= 0 && time(NULL) < last_check + 600) { -+ static int first = 1; -+ if (first) { -+ fprintf(stderr, "fs_supported: %d\n", fs_supported); -+ } -+ first = 0; -+ return fs_supported; -+ } -+ last_check = time(NULL); -+ -+ fs_supported = 0; -+ -+ _NET_SUPPORTING_WM_CHECK = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); -+ _NET_SUPPORTED = XInternAtom(dpy, "_NET_SUPPORTED", False); -+ _NET_WM_STATE = XInternAtom(dpy, "_NET_WM_STATE", False); -+ _NET_WM_STATE_FULLSCREEN = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); -+ -+ ret = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _NET_SUPPORTING_WM_CHECK, -+ 0L, 1L, False, XA_WINDOW, &type, &format, &items_read, &items_left, &data); -+ -+ if (ret != Success || !items_read) { -+ if (ret == Success) { -+ XFree(data); -+ } -+ return fs_supported; -+ } -+ -+ wm = ((Window*) data)[0]; -+ XFree(data); -+ -+ ret = XGetWindowProperty(dpy, wm, _NET_SUPPORTING_WM_CHECK, -+ 0L, 1L, False, XA_WINDOW, &type, &format, &items_read, &items_left, &data); -+ -+ if (ret != Success || !items_read) { -+ if (ret == Success) { -+ XFree(data); -+ } -+ return fs_supported; -+ } -+ -+ if (wm != ((Window*) data)[0]) { -+ XFree(data); -+ return fs_supported; -+ } -+ -+ ret = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _NET_SUPPORTED, -+ 0L, 8192L, False, XA_ATOM, &type, &format, &items_read, &items_left, &data); -+ -+ if (ret != Success || !items_read) { -+ if (ret == Success) { -+ XFree(data); -+ } -+ return fs_supported; -+ } -+ -+ for (i=0; i < items_read; i++) { -+ if ( ((Atom*) data)[i] == _NET_WM_STATE_FULLSCREEN) { -+ fs_supported = 1; -+ } -+ } -+ XFree(data); - -- viewportX = (toplevelWidth - viewportWidth) / 2; -- viewportY = (toplevelHeight - viewportHeight) / 2; -+ return fs_supported; -+} - -+static void net_wm_fullscreen(int to_fs) { -+ -+ int _NET_WM_STATE_REMOVE = 0; -+ int _NET_WM_STATE_ADD = 1; -+#if 0 -+ int _NET_WM_STATE_TOGGLE = 2; -+#endif -+ Atom _NET_WM_STATE = XInternAtom(dpy, "_NET_WM_STATE", False); -+ Atom _NET_WM_STATE_FULLSCREEN = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); -+ XEvent xev; -+ -+ if (to_fs == 2) { -+ XChangeProperty(dpy, XtWindow(toplevel), _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char*)&_NET_WM_STATE_FULLSCREEN, 1); -+ } else { -+ xev.xclient.type = ClientMessage; -+ xev.xclient.window = XtWindow(toplevel); -+ xev.xclient.message_type = _NET_WM_STATE; -+ xev.xclient.serial = 0; -+ xev.xclient.display = dpy; -+ xev.xclient.send_event = True; -+ xev.xclient.format = 32; -+ xev.xclient.data.l[0] = to_fs ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; -+ xev.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN; -+ xev.xclient.data.l[2] = 0; -+ xev.xclient.data.l[3] = 0; -+ xev.xclient.data.l[4] = 0; -+ XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); -+ } - -- /* We want to stop the window manager from managing our toplevel window. -- This is not really a nice thing to do, so may not work properly with every -- window manager. We do this simply by setting overrideRedirect and -- reparenting our window to the root. The window manager will get a -- ReparentNotify and hopefully clean up its frame window. */ -+ XSync(dpy, False); -+} - -- XtVaSetValues(toplevel, XtNoverrideRedirect, True, NULL); -+time_t main_grab = 0; - -- XReparentWindow(dpy, XtWindow(toplevel), DefaultRootWindow(dpy), 0, 0); -+void fs_ungrab(int check) { -+ if (check) { -+ if (time(NULL) <= main_grab + 2) { -+ return; -+ } -+ if (net_wm_supported()) { -+ return; -+ } -+ } -+ fprintf(stderr, "calling fs_ungrab()\n"); -+ if (appData.grabAll) { /* runge top of FullScreenOff */ -+ fprintf(stderr, "calling XUngrabServer(dpy)\n"); -+ XUngrabServer(dpy); -+ } -+ if (appData.grabKeyboard) { -+ fprintf(stderr, "calling XUngrabKeyboard(dpy)\n"); -+ XtUngrabKeyboard(desktop, CurrentTime); -+ } -+} - -- /* Some WMs does not obey x,y values of XReparentWindow; the window -- is not placed in the upper, left corner. The code below fixes -- this: It manually moves the window, after the Xserver is done -- with XReparentWindow. The last XSync seems to prevent losing -- focus, but I don't know why. */ -- XSync(dpy, False); -- XMoveWindow(dpy, XtWindow(toplevel), 0, 0); -- XSync(dpy, False); -- -- /* Now we want to fix the size of "viewport". We shouldn't just change it -- directly. Instead we set "toplevel" to the required size (which should -- propagate through "form" to "viewport"). Then we remove "viewport" from -- being managed by "form", change its resources to position it and make sure -- that "form" won't attempt to resize it, then ask "form" to manage it -- again. */ -- -- XtResizeWidget(toplevel, viewportWidth, viewportHeight, 0); -- -- XtUnmanageChild(viewport); -- -- XtVaSetValues(viewport, -- XtNhorizDistance, viewportX, -- XtNvertDistance, viewportY, -- XtNleft, XtChainLeft, -- XtNright, XtChainLeft, -- XtNtop, XtChainTop, -- XtNbottom, XtChainTop, -- NULL); -+void fs_grab(int check) { -+ if (check) { -+ if (time(NULL) <= main_grab + 2) { -+ return; -+ } -+ if (net_wm_supported()) { -+ return; -+ } -+ } -+ -+ main_grab = time(NULL); -+ -+ fprintf(stderr, "calling fs_grab()\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(100 * 1000); -+ FORCE_UP -+ -+ if (XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) { -+ fprintf(stderr, "XtGrabKeyboard() failed again.\n"); -+ usleep(200 * 1000); -+ XSync(dpy, False); -+ 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)); -+ } -+ -+ if (appData.grabAll) { -+ fprintf(stderr, "calling XGrabServer(dpy)\n"); -+ if (! XGrabServer(dpy)) { -+ XSync(dpy, False); -+ usleep(100 * 1000); -+ fprintf(stderr, "calling XGrabServer(dpy) 2nd time\n"); -+ if (!XGrabServer(dpy)) { -+ XSync(dpy, False); -+ usleep(200 * 1000); -+ fprintf(stderr, "calling XGrabServer(dpy) 3rd time\n"); -+ if (XGrabServer(dpy)) { -+ fprintf(stderr, "XGrabServer(dpy) OK 3rd time\n"); -+ } -+ } else { -+ fprintf(stderr, "XGrabServer(dpy) OK 2nd time\n"); -+ } -+ XSync(dpy, False); -+ } -+ if (getenv("VNCVIEWER_FORCE_UP")) { -+ fprintf(stderr, "FORCE_UP\n"); -+ FORCE_UP -+ } -+ } -+} -+ -+extern int fullscreen_startup; -+extern double last_fullscreen; -+ -+#define set_size_hints() \ -+{ \ -+ long supplied; \ -+ XSizeHints *sizehints = XAllocSizeHints(); \ -+ XGetWMSizeHints(dpy, topwin, sizehints, &supplied, XA_WM_NORMAL_HINTS); \ -+ if (sizehints->base_width < toplevelWidth) { \ -+ sizehints->base_width = toplevelWidth; \ -+ } \ -+ if (sizehints->base_height < toplevelHeight) { \ -+ sizehints->base_height = toplevelHeight; \ -+ } \ -+ if (sizehints->max_width < toplevelWidth) { \ -+ sizehints->max_width = toplevelWidth; \ -+ } \ -+ if (sizehints->max_height < toplevelHeight) { \ -+ sizehints->max_height = toplevelHeight; \ -+ } \ -+ XSetWMSizeHints(dpy, topwin, sizehints, XA_WM_NORMAL_HINTS); \ -+ XFree(sizehints); \ -+} - -- XtManageChild(viewport); -+extern int scale_x, scale_y; -+extern double scale_factor_y; -+ -+void -+FullScreenOn() -+{ -+ Dimension toplevelWidth, toplevelHeight; -+ Dimension oldViewportWidth, oldViewportHeight, clipWidth, clipHeight; -+ Position viewportX, viewportY; -+ int do_net_wm = net_wm_supported(); -+ int fbW = si.framebufferWidth; -+ int fbH = si.framebufferHeight; -+ int eff_height; -+ -+ Bool fsAlready = appData.fullScreen, toobig = False; -+ Window topwin = XtWindow(toplevel); -+ -+ appData.fullScreen = True; -+ -+ last_fullscreen = dnow(); -+ -+ if (scale_x > 0) { -+ fbW = scale_x; -+ fbH = scale_y; -+ } -+ -+ eff_height = fbH; -+ if (appData.yCrop > 0) { -+ eff_height = appData.yCrop; -+ if (scale_y > 0) { -+ eff_height = scale_round(eff_height, scale_factor_y); -+ } -+ } -+ -+ if (fbW > dpyWidth || eff_height > dpyHeight) { -+ -+ toobig = True; -+ -+ /* -+ * This is a crazy thing to have the scrollbars hang -+ * just a bit offscreen to the right and below. the user -+ * will not see them and bumpscroll will work. -+ */ -+ -+ XtVaSetValues(viewport, XtNforceBars, True, NULL); -+ XtVaGetValues(viewport, XtNwidth, &oldViewportWidth, XtNheight, &oldViewportHeight, NULL); -+ XtVaGetValues(XtNameToWidget(viewport, "clip"), XtNwidth, &clipWidth, XtNheight, &clipHeight, NULL); -+ -+ scrollbarWidth = oldViewportWidth - clipWidth; -+ scrollbarHeight = oldViewportHeight - clipHeight; -+ -+ if (fbW > dpyWidth) { -+ viewportWidth = toplevelWidth = dpyWidth + scrollbarWidth; -+ } else { -+ viewportWidth = fbW + scrollbarWidth; -+ toplevelWidth = dpyWidth; -+ } -+ -+ if (eff_height > dpyHeight) { -+ viewportHeight = toplevelHeight = dpyHeight + scrollbarHeight; -+ } else { -+ viewportHeight = eff_height + scrollbarHeight; -+ toplevelHeight = dpyHeight; -+ } -+ if (do_net_wm) { -+ /* but for _NET_WM we make toplevel be correct dpy size */ -+ toplevelWidth = dpyWidth; -+ toplevelHeight = dpyHeight; -+ } -+ -+ } else { -+ viewportWidth = fbW; -+ viewportHeight = eff_height; -+ toplevelWidth = dpyWidth; -+ toplevelHeight = dpyHeight; -+ } - -- /* Now we can set "toplevel" to its proper size. */ -+ viewportX = (toplevelWidth - viewportWidth) / 2; -+ viewportY = (toplevelHeight - viewportHeight) / 2; - -- XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0); -+ if (viewportX < 0) viewportX = 0; -+ if (viewportY < 0) viewportY = 0; - -- /* Set the popup to overrideRedirect too */ - -- XtVaSetValues(popup, XtNoverrideRedirect, True, NULL); -+ /* We want to stop the window manager from managing our toplevel window. -+ This is not really a nice thing to do, so may not work properly with every -+ window manager. We do this simply by setting overrideRedirect and -+ reparenting our window to the root. The window manager will get a -+ ReparentNotify and hopefully clean up its frame window. */ - -- /* Try to get the input focus. */ -+ if (! fsAlready) { -+ if (!do_net_wm) { -+ /* added to try to raise it on top for some cirumstances */ -+ XUnmapWindow(dpy, topwin); -+ -+ XtVaSetValues(toplevel, XtNoverrideRedirect, True, NULL); -+#if 0 -+ XtVaSetValues(viewport, XtNoverrideRedirect, True, NULL); -+ XtVaSetValues(desktop, XtNoverrideRedirect, True, NULL); -+#endif -+ XtVaSetValues(popup, XtNoverrideRedirect, True, NULL); -+ -+ XReparentWindow(dpy, topwin, DefaultRootWindow(dpy), 0, 0); -+ -+ /* Some WMs does not obey x,y values of XReparentWindow; the window -+ is not placed in the upper, left corner. The code below fixes -+ this: It manually moves the window, after the Xserver is done -+ with XReparentWindow. The last XSync seems to prevent losing -+ focus, but I don't know why. */ -+ -+ XSync(dpy, False); -+ -+ /* added to try to raise it on top for some cirumstances */ -+ XMapRaised(dpy, topwin); -+ -+ XMoveWindow(dpy, topwin, 0, 0); -+ XSync(dpy, False); -+ } -+ -+ /* Now we want to fix the size of "viewport". We shouldn't just change it -+ directly. Instead we set "toplevel" to the required size (which should -+ propagate through "form" to "viewport"). Then we remove "viewport" from -+ being managed by "form", change its resources to position it and make sure -+ that "form" won't attempt to resize it, then ask "form" to manage it -+ again. */ -+ -+ XtResizeWidget(toplevel, viewportWidth, viewportHeight, 0); -+ -+ XtUnmanageChild(viewport); -+ -+ XtVaSetValues(viewport, -+ XtNhorizDistance, viewportX, -+ XtNvertDistance, viewportY, -+ XtNleft, XtChainLeft, -+ XtNright, XtChainLeft, -+ XtNtop, XtChainTop, -+ XtNbottom, XtChainTop, -+ NULL); -+ -+ XtManageChild(viewport); -+ XSync(dpy, False); -+ } else { -+ XSync(dpy, False); -+ } -+ -+ /* Now we can set "toplevel" to its proper size. */ -+ -+#if 0 -+ XtVaSetValues(toplevel, XtNwidth, toplevelWidth, XtNheight, toplevelHeight, NULL); -+ XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0); -+#endif -+ XResizeWindow(dpy, topwin, toplevelWidth, toplevelHeight); -+ -+ if (do_net_wm) { -+ XWindowAttributes attr; -+ int ok = 0, i, delay = 20; -+ -+ usleep(delay * 1000); -+ -+#define GSIZE() \ -+ XGetWindowAttributes(dpy, topwin, &attr); -+ -+#define PSIZE(s) \ -+ XSync(dpy, False); \ -+ XGetWindowAttributes(dpy, topwin, &attr); \ -+ fprintf(stderr, "%s %dx%d+%d+%d\n", s, attr.width, attr.height, attr.x, attr.y); -+ -+ PSIZE("size-A:"); -+ -+ set_size_hints(); -+ -+ net_wm_fullscreen(1); -+ -+ PSIZE("size-B:"); -+ -+ for (i=0; i < 30; i++) { -+ usleep(delay * 1000); -+ GSIZE(); -+ fprintf(stderr, "size[%d] %dx%d+%d+%d\n", i, attr.width, attr.height, attr.x, attr.y); -+ if (attr.width == toplevelWidth && attr.height == toplevelHeight) { -+ ok = 1; -+ fprintf(stderr, "size ok.\n"); -+ XSync(dpy, False); -+ break; -+ } -+ set_size_hints(); -+ XResizeWindow(dpy, topwin, toplevelWidth, toplevelHeight); -+ XMoveWindow(dpy, topwin, 0, 0); -+ XSync(dpy, False); -+ } -+ -+ PSIZE("size-C:"); -+ } -+ -+ fprintf(stderr, "\ntoplevel: %dx%d viewport: %dx%d\n", toplevelWidth, toplevelHeight, viewportWidth, viewportHeight); -+ -+#if defined (__SVR4) && defined (__sun) -+ if (!do_net_wm) { -+ /* CDE */ -+ XSync(dpy, False); -+ usleep(200 * 1000); -+ XMoveWindow(dpy, topwin, 0, 0); -+ XMapRaised(dpy, topwin); -+ XSync(dpy, False); -+ } -+#endif -+ -+ if (fsAlready) { -+ XtResizeWidget(viewport, viewportWidth, viewportHeight, 0); -+ if (! toobig) { -+ XtVaSetValues(viewport, XtNforceBars, False, NULL); -+ } -+ XMoveWindow(dpy, topwin, viewportX, viewportY); -+ XSync(dpy, False); -+ } -+ -+ /* Try to get the input focus. */ - -- XSetInputFocus(dpy, DefaultRootWindow(dpy), RevertToPointerRoot, -- CurrentTime); -+ /* original vnc: DefaultRootWindow(dpy) instead of PointerRoot */ -+ XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); - -- /* Optionally, grab the keyboard. */ -+ /* Optionally, grab the keyboard. */ -+ fs_grab(0); - -- if (appData.grabKeyboard && -- XtGrabKeyboard(desktop, True, GrabModeAsync, -- GrabModeAsync, CurrentTime) != GrabSuccess) { -- fprintf(stderr, "XtGrabKeyboard() failed.\n"); -- } -+ /* finally done. */ - } - - -@@ -205,28 +553,52 @@ - void - FullScreenOff() - { -- int toplevelWidth = si.framebufferWidth; -- int toplevelHeight = si.framebufferHeight; -- -- appData.fullScreen = False; -+ int toplevelWidth, toplevelHeight; -+ int do_net_wm = net_wm_supported(); -+ int fbW = si.framebufferWidth; -+ int fbH = si.framebufferHeight; -+ int eff_height; -+ -+ appData.fullScreen = False; -+ -+ last_fullscreen = dnow(); -+ -+ if (scale_x > 0) { -+ fbW = scale_x; -+ fbH = scale_y; -+ } -+ -+ eff_height = fbH; -+ if (appData.yCrop > 0) { -+ eff_height = appData.yCrop; -+ if (scale_y > 0) { -+ eff_height = scale_round(eff_height, scale_factor_y); -+ } -+ } -+ -+ toplevelWidth = fbW; -+ toplevelHeight = eff_height; -+ -+ fs_ungrab(0); -+ -+ if (do_net_wm) { -+ net_wm_fullscreen(0); -+ } else { -+ XtUnmapWidget(toplevel); -+ } - -- if (appData.grabKeyboard) -- XtUngrabKeyboard(desktop, CurrentTime); -- -- XtUnmapWidget(toplevel); -- -- XtResizeWidget(toplevel, -+ XtResizeWidget(toplevel, - viewportWidth - scrollbarWidth, - viewportHeight - scrollbarHeight, 0); -- XtResizeWidget(viewport, -+ XtResizeWidget(viewport, - viewportWidth - scrollbarWidth, - viewportHeight - scrollbarHeight, 0); - -- XtVaSetValues(viewport, XtNforceBars, False, NULL); -+ XtVaSetValues(viewport, XtNforceBars, False, NULL); - -- XtUnmanageChild(viewport); -+ XtUnmanageChild(viewport); - -- XtVaSetValues(viewport, -+ XtVaSetValues(viewport, - XtNhorizDistance, 0, - XtNvertDistance, 0, - XtNleft, XtChainLeft, -@@ -235,24 +607,42 @@ - XtNbottom, XtChainBottom, - NULL); - -- XtManageChild(viewport); -- -- XtVaSetValues(toplevel, XtNoverrideRedirect, False, NULL); -- -- if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth) -- toplevelWidth = dpyWidth - appData.wmDecorationWidth; -- -- if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight) -- toplevelHeight = dpyHeight - appData.wmDecorationHeight; -- -- XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0); -- -- XtMapWidget(toplevel); -- XSync(dpy, False); -+ XtManageChild(viewport); - -- /* Set the popup back to non-overrideRedirect */ -- -- XtVaSetValues(popup, XtNoverrideRedirect, False, NULL); -+ if (!do_net_wm) { -+ XtVaSetValues(toplevel, XtNoverrideRedirect, False, NULL); -+#if 0 -+ XtVaSetValues(viewport, XtNoverrideRedirect, False, NULL); -+ XtVaSetValues(desktop, XtNoverrideRedirect, False, NULL); -+#endif -+ XtVaSetValues(popup, XtNoverrideRedirect, False, NULL); -+ } -+ -+ if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth) -+ toplevelWidth = dpyWidth - appData.wmDecorationWidth; -+ -+ if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight) -+ toplevelHeight = dpyHeight - appData.wmDecorationHeight; -+ -+ XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0); -+ -+ if (!do_net_wm) { -+ XtMapWidget(toplevel); -+ } -+ XSync(dpy, False); -+ -+ /* Set the popup back to non-overrideRedirect */ -+ -+ XtVaSetValues(popup, XtNoverrideRedirect, False, NULL); -+ -+ if (!do_net_wm) { -+ int x = (dpyWidth - toplevelWidth) / 2; -+ int y = (dpyHeight - toplevelHeight) / 2; -+ if (x > 0 && y > 0) { -+ XSync(dpy, False); -+ XMoveWindow(dpy, XtWindow(toplevel), x, y); -+ } -+ } - } - - -@@ -264,10 +654,12 @@ - void - SetFullScreenState(Widget w, XEvent *ev, String *params, Cardinal *num_params) - { -- if (appData.fullScreen) -- XtVaSetValues(w, XtNstate, True, NULL); -- else -- XtVaSetValues(w, XtNstate, False, NULL); -+ if (appData.fullScreen) { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } -+ if (w || ev || params || num_params) {} - } - - -@@ -278,11 +670,12 @@ - void - ToggleFullScreen(Widget w, XEvent *ev, String *params, Cardinal *num_params) - { -- if (appData.fullScreen) { -- FullScreenOff(); -- } else { -- FullScreenOn(); -- } -+ if (appData.fullScreen) { -+ FullScreenOff(); -+ } else { -+ FullScreenOn(); -+ } -+ if (w || ev || params || num_params) {} - } - - -@@ -294,84 +687,226 @@ - Bool - BumpScroll(XEvent *ev) - { -- scrollLeft = scrollRight = scrollUp = scrollDown = False; -+ scrollLeft = scrollRight = scrollUp = scrollDown = False; - -- if (ev->xmotion.x_root >= dpyWidth - 3) -- scrollRight = True; -- else if (ev->xmotion.x_root <= 2) -- scrollLeft = True; -- -- if (ev->xmotion.y_root >= dpyHeight - 3) -- scrollDown = True; -- else if (ev->xmotion.y_root <= 2) -- scrollUp = True; -- -- if (scrollLeft || scrollRight || scrollUp || scrollDown) { -- if (timerSet) -- return True; -- -- XtVaGetValues(desktop, XtNx, &desktopX, XtNy, &desktopY, NULL); -- desktopX = -desktopX; -- desktopY = -desktopY; -- -- return DoBumpScroll(); -- } -- -- if (timerSet) { -- XtRemoveTimeOut(timer); -- timerSet = False; -- } -+ if (ev->xmotion.x_root >= dpyWidth - 3) -+ scrollRight = True; -+ else if (ev->xmotion.x_root <= 2) -+ scrollLeft = True; -+ -+ if (ev->xmotion.y_root >= dpyHeight - 3) -+ scrollDown = True; -+ else if (ev->xmotion.y_root <= 2) -+ scrollUp = True; -+ -+ if (scrollLeft || scrollRight || scrollUp || scrollDown) { -+ if (timerSet) -+ return True; -+ -+ XtVaGetValues(desktop, XtNx, &desktopX, XtNy, &desktopY, NULL); -+ desktopX = -desktopX; -+ desktopY = -desktopY; -+ -+ return DoBumpScroll(); -+ } -+ -+ if (timerSet) { -+ XtRemoveTimeOut(timer); -+ timerSet = False; -+ } - -- return False; -+ return False; - } - - static Bool - DoBumpScroll() - { -- int oldx = desktopX, oldy = desktopY; -- -- if (scrollRight) { -- if (desktopX < si.framebufferWidth - dpyWidth) { -- desktopX += appData.bumpScrollPixels; -- if (desktopX > si.framebufferWidth - dpyWidth) -- desktopX = si.framebufferWidth - dpyWidth; -- } -- } else if (scrollLeft) { -- if (desktopX > 0) { -- desktopX -= appData.bumpScrollPixels; -- if (desktopX < 0) -- desktopX = 0; -- } -- } -- -- if (scrollDown) { -- if (desktopY < si.framebufferHeight - dpyHeight) { -- desktopY += appData.bumpScrollPixels; -- if (desktopY > si.framebufferHeight - dpyHeight) -- desktopY = si.framebufferHeight - dpyHeight; -- } -- } else if (scrollUp) { -- if (desktopY > 0) { -- desktopY -= appData.bumpScrollPixels; -- if (desktopY < 0) -- desktopY = 0; -- } -- } -- -- if (oldx != desktopX || oldy != desktopY) { -- XawViewportSetCoordinates(viewport, desktopX, desktopY); -- timer = XtAppAddTimeOut(appContext, appData.bumpScrollTime, -- BumpScrollTimerCallback, NULL); -- timerSet = True; -- return True; -- } -+ int oldx = desktopX, oldy = desktopY; -+ int fbW = si.framebufferWidth; -+ int fbH = si.framebufferHeight; -+ -+ if (scale_x > 0) { -+ fbW = scale_x; -+ fbH = scale_y; -+ } -+ -+ if (scrollRight) { -+ if (desktopX < fbW - dpyWidth) { -+ desktopX += appData.bumpScrollPixels; -+ if (desktopX > fbW - dpyWidth) { -+ desktopX = fbW - dpyWidth; -+ } -+ } -+ } else if (scrollLeft) { -+ if (desktopX > 0) { -+ desktopX -= appData.bumpScrollPixels; -+ if (desktopX < 0) { -+ desktopX = 0; -+ } -+ } -+ } -+ -+ if (scrollDown) { -+ int ycrop = appData.yCrop; -+ if (scale_y > 0) { -+ ycrop = scale_round(ycrop, scale_factor_y); -+ } -+ if (ycrop > 0 && desktopY + dpyHeight >= ycrop) { -+ ; -+ } else if (desktopY < fbH - dpyHeight) { -+ desktopY += appData.bumpScrollPixels; -+ if (desktopY > fbH - dpyHeight) { -+ desktopY = fbH - dpyHeight; -+ } -+ } -+ } else if (scrollUp) { -+ if (desktopY > 0) { -+ desktopY -= appData.bumpScrollPixels; -+ if (desktopY < 0) { -+ desktopY = 0; -+ } -+ } -+ } -+ -+ if (oldx != desktopX || oldy != desktopY) { -+ XawViewportSetCoordinates(viewport, desktopX, desktopY); -+ timer = XtAppAddTimeOut(appContext, appData.bumpScrollTime, BumpScrollTimerCallback, NULL); -+ timerSet = True; -+ return True; -+ } - -- timerSet = False; -- return False; -+ timerSet = False; -+ return False; - } - - static void - BumpScrollTimerCallback(XtPointer clientData, XtIntervalId *id) - { -- DoBumpScroll(); -+ DoBumpScroll(); -+ if (clientData || id) {} -+} -+ -+/* 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, jumpV; -+ int fbW = si.framebufferWidth; -+ int fbH = si.framebufferHeight; -+ -+ if (scale_x > 0) { -+ fbW = scale_x; -+ fbH = scale_y; -+ } -+ jumpH = fbW / 4; -+ jumpV = fbH / 4; -+ -+ if (scrollRight) { -+ if (desktopX < fbW - dpyWidth) { -+ desktopX += jumpH; -+ if (desktopX > fbW - dpyWidth) -+ desktopX = fbW - 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 < fbH - dpyHeight) { -+ desktopY += jumpV; -+ if (desktopY > fbH - dpyHeight) -+ desktopY = fbH - 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(); -+ if (clientData || id) {} -+} -+void JumpRight(Widget w, XEvent *ev, String *params, Cardinal *num_params) { -+ JumpScroll(1, 0); -+ if (w || ev || params || num_params) {} -+} -+void JumpLeft(Widget w, XEvent *ev, String *params, Cardinal *num_params) { -+ JumpScroll(0, 0); -+ if (w || ev || params || num_params) {} -+} -+void JumpUp(Widget w, XEvent *ev, String *params, Cardinal *num_params) { -+ JumpScroll(1, 1); -+ if (w || ev || params || num_params) {} - } -+void JumpDown(Widget w, XEvent *ev, String *params, Cardinal *num_params) { -+ JumpScroll(0, 1); -+ if (w || ev || params || num_params) {} -+} -+ -+ -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 (<HELP>) { -+ $_ =~ s/&/&/g; -+ $_ =~ 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 2009-10-16 22:54:40.000000000 -0400 -@@ -30,6 +30,21 @@ - #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.useXserverBackingStore) { \ -+ FillScreen(x, y, w, h, _gcv.foreground); \ -+ } else { \ -+ XChangeGC(dpy, gc, GCForeground, &_gcv); \ -+ XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \ -+ } \ -+ } -+ -+extern int skip_maybe_sync; -+extern void maybe_sync(int w, int h); -+ - static Bool - HandleHextileBPP (int rx, int ry, int rw, int rh) - { -@@ -41,21 +56,43 @@ - int sx, sy, sw, sh; - CARD8 subencoding; - CARD8 nSubrects; -+ int irect = 0, nrects = (rw * rh) / (16 * 16); -+ static int nosync_ycrop = -1; -+ -+ if (nosync_ycrop < 0) { -+ nosync_ycrop = 0; -+ if (getenv("HEXTILE_YCROP_TOO")) { -+ nosync_ycrop = 1; -+ } -+ } - - for (y = ry; y < ry+rh; y += 16) { - for (x = rx; x < rx+rw; x += 16) { - w = h = 16; -- if (rx+rw - x < 16) -+ if (rx+rw - x < 16) { - w = rx+rw - x; -- if (ry+rh - y < 16) -+ } -+ if (ry+rh - y < 16) { - h = ry+rh - y; -+ } -+ -+ if (nrects > 400 && (appData.yCrop == 0 || nosync_ycrop)) { -+ skip_maybe_sync = 0; -+ if (irect++ % 2000 != 0) { -+ if (x < rx+rw-16 || y < ry+rh-16) { -+ skip_maybe_sync = 1; -+ } -+ } -+ } - -- if (!ReadFromRFBServer((char *)&subencoding, 1)) -+ if (!ReadFromRFBServer((char *)&subencoding, 1)) { - return False; -+ } - - if (subencoding & rfbHextileRaw) { -- if (!ReadFromRFBServer(buffer, w * h * (BPP / 8))) -+ if (!ReadFromRFBServer(buffer, w * h * (BPP / 8))) { - return False; -+ } - - CopyDataToScreen(buffer, x, y, w, h); - continue; -@@ -66,14 +103,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 +149,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 +175,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 +199,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 +211,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 2010-04-11 23:14:21.000000000 -0400 -@@ -32,14 +32,88 @@ - #define FLASHDELAY 1 /* seconds */ - - Bool listenSpecified = False; -+pid_t listenParent = 0; - int listenPort = 0, flashPort = 0; - -+#if 0 - static Font flashFont; -- - static void getFlashFont(Display *d); - static void flashDisplay(Display *d, char *user); -+#endif -+ - static Bool AllXEventsPredicate(Display *d, XEvent *ev, char *arg); - -+void raiseme(int force); -+ -+static int accept_popup_check(int *argc, char **argv, char *sip, char *sih) { -+ char line[16]; -+ char msg[1000]; -+ int dopopup = 1; -+ -+ if (!getenv("SSVNC_ACCEPT_POPUP")) { -+ return 1; -+ } -+ -+ if (!dopopup && use_tty()) { -+ raiseme(1); -+ fprintf(stderr, "Accept VNC connection? y/[n] "); -+ fgets(line, sizeof(line), stdin); -+ if (!strchr(line, 'y') && !strchr(line, 'Y')) { -+ fprintf(stderr, "Refusing connection.\n"); -+ return 0; -+ } else { -+ fprintf(stderr, "Accepting connection.\n"); -+ return 1; -+ } -+ } else { -+ int pid, pid2, accept_it = 0; -+ -+ pid = fork(); -+ if (pid == -1) { -+ perror("fork"); -+ exit(1); -+ } -+ if (pid == 0) { -+ char *geometry = "2x2+0+0"; -+ String fb[] = { "*message.Scroll: whenNeeded", NULL}; -+ close(rfbsock); -+ -+ toplevel = XtAppInitialize(&appContext, "Ssvnc", cmdLineOptions, numCmdLineOptions, -+ argc, argv, fb, NULL, 0); -+ XtVaSetValues(toplevel, XtNmaxWidth, 2, XtNmaxHeight, 2, NULL); -+ XtVaSetValues(toplevel, XtNgeometry, geometry, NULL); -+ XtRealizeWidget(toplevel); -+ dpy = XtDisplay(toplevel); -+ sprintf(msg, "\n(LISTEN) Reverse VNC connection from IP: %s\n Hostname: %s\n\n", sip, sih); -+ strcat(msg, "Accept or Reject VNC connection?"); -+ if (CreateMsg(msg, 2)) { -+ XCloseDisplay(dpy); -+ exit(0); -+ } else { -+ XCloseDisplay(dpy); -+ exit(1); -+ } -+ } else { -+ int status; -+ pid2 = waitpid(pid, &status, 0); -+ fprintf(stderr, "waitpid: %d/%d status: %d\n", pid, pid2, status); -+ if (pid2 == pid) { -+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { -+ accept_it = 1; -+ } -+ } -+ } -+ if (accept_it) { -+ fprintf(stderr, "Accepting connection.\n"); -+ return 1; -+ } else { -+ fprintf(stderr, "Refusing connection.\n"); -+ return 0; -+ } -+ } -+ return 0; -+} -+ - /* - * listenForIncomingConnections() - listen for incoming connections from - * servers, and fork a new process to deal with each connection. We must do -@@ -47,145 +121,291 @@ - * cope with forking very well. - */ - -+extern char *accept6_hostname; -+extern char *accept6_ipaddr; -+ - void - listenForIncomingConnections(int *argc, char **argv, int listenArgIndex) - { -- Display *d; -- XEvent ev; -- int listenSocket, flashSocket, sock; -- fd_set fds; -- char flashUser[256]; -- int n; -- int i; -- char *displayname = NULL; -- -- listenSpecified = True; -- -- for (i = 1; i < *argc; i++) { -- if (strcmp(argv[i], "-display") == 0 && i+1 < *argc) { -- displayname = argv[i+1]; -- } -- } -+ Display *d; -+ XEvent ev; -+ int listenSocket, listenSocket6, flashSocket, sock; -+ fd_set fds; -+ char flashUser[256]; -+ int n; -+ int i; -+ char *displayname = NULL; -+ int children = 0; -+ int totalconn = 0, maxconn = 0; -+ -+ listenSpecified = True; -+ listenParent = getpid(); -+ -+ for (i = 1; i < *argc; i++) { -+ if (strcmp(argv[i], "-display") == 0 && i+1 < *argc) { -+ displayname = argv[i+1]; -+ } -+ } -+ if (sock || flashUser || n) {} - -- if (listenArgIndex+1 < *argc && argv[listenArgIndex+1][0] >= '0' && -+ if (listenArgIndex+1 < *argc && argv[listenArgIndex+1][0] >= '0' && - argv[listenArgIndex+1][0] <= '9') { - -- listenPort = LISTEN_PORT_OFFSET + atoi(argv[listenArgIndex+1]); -- flashPort = FLASH_PORT_OFFSET + atoi(argv[listenArgIndex+1]); -- removeArgs(argc, argv, listenArgIndex, 2); -+ listenPort = LISTEN_PORT_OFFSET + atoi(argv[listenArgIndex+1]); -+ flashPort = FLASH_PORT_OFFSET + atoi(argv[listenArgIndex+1]); -+ removeArgs(argc, argv, listenArgIndex, 2); - -- } else { -+ } else { - -- char *display; -- char *colonPos; -- struct utsname hostinfo; -+ char *display; -+ char *colonPos; -+ struct utsname hostinfo; - -- removeArgs(argc, argv, listenArgIndex, 1); -+ removeArgs(argc, argv, listenArgIndex, 1); - -- display = XDisplayName(displayname); -- colonPos = strchr(display, ':'); -+ display = XDisplayName(displayname); -+ colonPos = strchr(display, ':'); - -- uname(&hostinfo); -+ uname(&hostinfo); - -- if (colonPos && ((colonPos == display) || -- (strncmp(hostinfo.nodename, display, -- strlen(hostinfo.nodename)) == 0))) { -+ if (colonPos && ((colonPos == display) || -+ (strncmp(hostinfo.nodename, display, -+ strlen(hostinfo.nodename)) == 0))) { - -- listenPort = LISTEN_PORT_OFFSET + atoi(colonPos+1); -- flashPort = FLASH_PORT_OFFSET + atoi(colonPos+1); -+ listenPort = LISTEN_PORT_OFFSET + atoi(colonPos+1); -+ flashPort = FLASH_PORT_OFFSET + atoi(colonPos+1); - -- } else { -- fprintf(stderr,"%s: cannot work out which display number to " -- "listen on.\n", programName); -- fprintf(stderr,"Please specify explicitly with -listen <num>\n"); -- exit(1); -- } -- } -+ } else { -+ fprintf(stderr,"%s: cannot work out which display number to " -+ "listen on.\n", programName); -+ fprintf(stderr,"Please specify explicitly with -listen <num>\n"); -+ exit(1); -+ } - -- if (!(d = XOpenDisplay(displayname))) { -- fprintf(stderr,"%s: unable to open display %s\n", -- programName, XDisplayName(displayname)); -- exit(1); -- } -+ } - -- getFlashFont(d); -+ if (!(d = XOpenDisplay(displayname))) { -+ fprintf(stderr,"%s: unable to open display %s\n", -+ programName, XDisplayName(displayname)); -+ exit(1); -+ } - -- listenSocket = ListenAtTcpPort(listenPort); -- flashSocket = ListenAtTcpPort(flashPort); -+#if 0 -+ getFlashFont(d); -+#endif - -- if ((listenSocket < 0) || (flashSocket < 0)) exit(1); -+ listenSocket = ListenAtTcpPort(listenPort); -+ listenSocket6 = ListenAtTcpPort6(listenPort); -+ -+#if 0 -+ flashSocket = ListenAtTcpPort(flashPort); -+#endif -+ flashSocket = 1234; -+ -+ if (listenSocket < 0 && listenSocket6 < 0) { -+ fprintf(stderr,"%s -listen: could not obtain a listening socket on port %d\n", -+ programName, listenPort); -+ 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 ipv4_fd: %d ipv6_fd: %d\n", -+ programName, listenPort, listenSocket, listenSocket6); -+ fprintf(stderr,"%s -listen: Cmdline errors are not reported until " - "a connection comes in.\n", programName); - -- while (True) { -+ /* this will only work if X events drives this loop -- they don't */ -+ if (getenv("SSVNC_MAX_LISTEN")) { -+ maxconn = atoi(getenv("SSVNC_MAX_LISTEN")); -+ } - -- /* reap any zombies */ -- int status, pid; -- while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0); -- -- /* discard any X events */ -- while (XCheckIfEvent(d, &ev, AllXEventsPredicate, NULL)) -- ; -- -- FD_ZERO(&fds); -- -- FD_SET(flashSocket, &fds); -- FD_SET(listenSocket, &fds); -- FD_SET(ConnectionNumber(d), &fds); -- -- select(FD_SETSIZE, &fds, NULL, NULL, NULL); -- -- if (FD_ISSET(flashSocket, &fds)) { -- -- sock = AcceptTcpConnection(flashSocket); -- if (sock < 0) exit(1); -- n = read(sock, flashUser, 255); -- if (n > 0) { -- flashUser[n] = 0; -- flashDisplay(d, flashUser); -- } else { -- flashDisplay(d, NULL); -- } -- close(sock); -- } -+ while (True) { -+ int lsock = -1; - -- if (FD_ISSET(listenSocket, &fds)) { -- rfbsock = AcceptTcpConnection(listenSocket); -- if (rfbsock < 0) exit(1); -- if (!SetNonBlocking(rfbsock)) exit(1); -+ /* reap any zombies */ -+ int status, pid; -+ 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); -+ } -+ } -+ } - -- XCloseDisplay(d); -+ /* discard any X events */ -+ while (XCheckIfEvent(d, &ev, AllXEventsPredicate, NULL)) { -+ ; -+ } - -- /* Now fork off a new process to deal with it... */ -+ FD_ZERO(&fds); - -- switch (fork()) { -+#if 0 -+ FD_SET(flashSocket, &fds); -+#endif -+ if (listenSocket >= 0) { -+ FD_SET(listenSocket, &fds); -+ } -+ if (listenSocket6 >= 0) { -+ FD_SET(listenSocket6, &fds); -+ } -+ FD_SET(ConnectionNumber(d), &fds); - -- case -1: -- perror("fork"); -- exit(1); -+ select(FD_SETSIZE, &fds, NULL, NULL, NULL); - -- case 0: -- /* child - return to caller */ -- close(listenSocket); -- close(flashSocket); -- return; -+ 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); -+ } -+ } -+ } - -- default: -- /* parent - go round and listen again */ -- close(rfbsock); -- if (!(d = XOpenDisplay(displayname))) { -- fprintf(stderr,"%s: unable to open display %s\n", -- programName, XDisplayName(displayname)); -- exit(1); -+#if 0 -+ if (FD_ISSET(flashSocket, &fds)) { -+ sock = AcceptTcpConnection(flashSocket); -+ if (sock < 0) exit(1); -+ n = read(sock, flashUser, 255); -+ if (n > 0) { -+ flashUser[n] = 0; -+ flashDisplay(d, flashUser); -+ } else { -+ flashDisplay(d, NULL); -+ } -+ close(sock); -+ } -+#endif -+ -+ lsock = -1; -+ if (listenSocket >= 0 && FD_ISSET(listenSocket, &fds)) { -+ lsock = listenSocket; -+ } else if (listenSocket6 >= 0 && FD_ISSET(listenSocket6, &fds)) { -+ lsock = listenSocket6; -+ } -+ -+ if (lsock >= 0) { -+ int multi_ok = 0; -+ char *sml = getenv("SSVNC_MULTIPLE_LISTEN"); -+ char *sip = NULL; -+ char *sih = NULL; -+ -+ if (lsock == listenSocket) { -+ rfbsock = AcceptTcpConnection(lsock); -+ } else { -+ rfbsock = AcceptTcpConnection6(lsock); -+ } -+ -+ 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; -+ } -+ -+ if (lsock == listenSocket) { -+ sip = get_peer_ip(rfbsock); -+ if (strlen(sip) > 100) sip = "0.0.0.0"; -+ sih = ip2host(sip); -+ if (strlen(sih) > 300) sih = "unknown"; -+ } else { -+ if (accept6_hostname != NULL) { -+ sip = accept6_ipaddr; -+ accept6_ipaddr = NULL; -+ sih = accept6_hostname; -+ accept6_hostname = NULL; -+ } else { -+ sip = "unknown"; -+ sih = "unknown"; -+ } -+ } -+ -+ fprintf(stderr, "\n"); -+ fprintf(stderr, "(LISTEN) Reverse VNC connection from IP: %s\n", sip); -+ fprintf(stderr, " Hostname: %s\n\n", sih); -+ -+ if (sml == NULL && !accept_popup_check(argc, argv, sip, sih)) { -+ close(rfbsock); -+ rfbsock = -1; -+ continue; -+ } -+ -+ totalconn++; -+ -+ XCloseDisplay(d); -+ -+ /* Now fork off a new process to deal with it... */ -+ -+ switch (fork()) { -+ -+ case -1: -+ perror("fork"); -+ exit(1); -+ -+ case 0: -+ /* child - return to caller */ -+ close(listenSocket); -+#if 0 -+ close(flashSocket); -+#endif -+ if (sml != NULL && !accept_popup_check(argc, argv, sip, sih)) { -+ close(rfbsock); -+ rfbsock = -1; -+ exit(0); -+ } -+ return; -+ -+ default: -+ /* parent - go round and listen again */ -+ children++; -+ close(rfbsock); -+ if (!(d = XOpenDisplay(displayname))) { -+ fprintf(stderr,"%s: unable to open display %s\n", -+ programName, XDisplayName(displayname)); -+ exit(1); -+ } -+#if 0 -+ getFlashFont(d); -+#endif -+ 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; -+ } - } -- getFlashFont(d); -- break; -- } - } -- } - } - - -@@ -193,9 +413,16 @@ - * getFlashFont - */ - -+#if 0 - static void - getFlashFont(Display *d) - { -+ -+#if 1 -+ /* no longer used */ -+ if (d) {} -+ return; -+#else - char fontName[256]; - char **fontNames; - int nFontNames; -@@ -209,6 +436,9 @@ - sprintf(fontName,"fixed"); - } - flashFont = XLoadFont(d, fontName); -+ -+#endif -+ - } - - -@@ -219,6 +449,11 @@ - static void - flashDisplay(Display *d, char *user) - { -+#if 1 -+ /* no longer used */ -+ if (d || user) {} -+ return; -+#else - Window w1, w2, w3, w4; - XSetWindowAttributes attr; - -@@ -284,7 +519,11 @@ - XDestroyWindow(d, w3); - XDestroyWindow(d, w4); - XFlush(d); -+ -+#endif -+ - } -+#endif - - /* - * AllXEventsPredicate is needed to make XCheckIfEvent return all events. -@@ -293,5 +532,6 @@ - static Bool - AllXEventsPredicate(Display *d, XEvent *ev, char *arg) - { -- return True; -+ if (d || ev || arg) {} -+ return True; - } -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 2010-02-25 22:44:09.000000000 -0500 -@@ -23,6 +23,7 @@ - - #include <vncviewer.h> - #include <signal.h> -+#include <sys/wait.h> - #include <fcntl.h> - - static void CleanupSignalHandler(int sig); -@@ -33,12 +34,20 @@ - - Dimension dpyWidth, dpyHeight; - Atom wmDeleteWindow, wmState; -+int fullscreen_startup = 0; - - static Bool xloginIconified = False; - static XErrorHandler defaultXErrorHandler; - static XIOErrorHandler defaultXIOErrorHandler; - static XtErrorHandler defaultXtErrorHandler; - -+int XError_ign = 0; -+ -+void check_tall(void); -+int guessCrop(void); -+void get_scale_values(double *fx, double *fy); -+int scale_round(int n, double factor); -+Bool SendTextChatFinished(void); - - /* - * ToplevelInitBeforeRealization sets the title, geometry and other resources -@@ -48,87 +57,122 @@ - void - ToplevelInitBeforeRealization() - { -- char *titleFormat; -- char *title; -- char *geometry; -- -- XtVaGetValues(toplevel, XtNtitle, &titleFormat, NULL); -- title = XtMalloc(strlen(titleFormat) + strlen(desktopName) + 1); -- sprintf(title, titleFormat, desktopName); -- XtVaSetValues(toplevel, XtNtitle, title, XtNiconName, title, NULL); -- -- XtVaSetValues(toplevel, XtNmaxWidth, si.framebufferWidth, -- XtNmaxHeight, si.framebufferHeight, NULL); -- -- dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy)); -- dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy)); -- -- if (appData.fullScreen) { -- -- /* full screen - set position to 0,0, but defer size calculation until -- widgets are realized */ -- -- XtVaSetValues(toplevel, XtNoverrideRedirect, True, -- XtNgeometry, "+0+0", NULL); -- -- } else { -- -- /* not full screen - work out geometry for middle of screen unless -- specified by user */ -- -- XtVaGetValues(toplevel, XtNgeometry, &geometry, NULL); -- -- if (geometry == NULL) { -- Dimension toplevelX, toplevelY; -- Dimension toplevelWidth = si.framebufferWidth; -- Dimension toplevelHeight = si.framebufferHeight; -- -- if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth) -- toplevelWidth = dpyWidth - appData.wmDecorationWidth; -- -- if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight) -- toplevelHeight = dpyHeight - appData.wmDecorationHeight; -- -- toplevelX = (dpyWidth - toplevelWidth - appData.wmDecorationWidth) / 2; -- -- toplevelY = (dpyHeight - toplevelHeight - appData.wmDecorationHeight) /2; -- -- /* set position via "geometry" so that window manager thinks it's a -- user-specified position and therefore honours it */ -- -- geometry = XtMalloc(256); -- -- sprintf(geometry, "%dx%d+%d+%d", -- toplevelWidth, toplevelHeight, toplevelX, toplevelY); -- XtVaSetValues(toplevel, XtNgeometry, geometry, NULL); -- } -- } -+ char *titleFormat; -+ char *title; -+ char *geometry; -+ int h = si.framebufferHeight; -+ int w = si.framebufferWidth; -+ -+ check_tall(); -+ if (appData.yCrop < 0) { -+ appData.yCrop = guessCrop(); -+ fprintf(stderr, "Set -ycrop to: %d\n", appData.yCrop); -+ if (appData.yCrop > 0) { -+ h = appData.yCrop; -+ } -+ } -+ -+ XtVaGetValues(toplevel, XtNtitle, &titleFormat, NULL); -+ title = XtMalloc(strlen(titleFormat) + strlen(desktopName) + 1); -+ sprintf(title, titleFormat, desktopName); -+ XtVaSetValues(toplevel, XtNtitle, title, XtNiconName, title, NULL); -+ -+ if (appData.scale != NULL) { -+ /* switched to not scaled */ -+ double frac_x, frac_y; -+ get_scale_values(&frac_x, &frac_y); -+ if (frac_x > 0.0 && frac_y > 0.0) { -+ w = scale_round(w, frac_x); -+ h = scale_round(h, frac_y); -+ } -+ } -+ XtVaSetValues(toplevel, XtNmaxWidth, w, XtNmaxHeight, h, NULL); -+ -+ dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy)); -+ dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy)); -+ -+ if (appData.fullScreen) { -+ /* full screen - set position to 0,0, but defer size calculation until widgets are realized */ -+ -+ if (!net_wm_supported()) { -+ XtVaSetValues(toplevel, XtNoverrideRedirect, True, XtNgeometry, "+0+0", NULL); -+ } else { -+ fullscreen_startup = 1; -+ } -+ -+ } else { -+ -+ /* not full screen - work out geometry for middle of screen unless specified by user */ -+ -+ XtVaGetValues(toplevel, XtNgeometry, &geometry, NULL); -+ -+ if (geometry == NULL) { -+ Dimension toplevelX, toplevelY; -+ Dimension toplevelWidth = w; -+ Dimension toplevelHeight = h; -+ -+ if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth) { -+ toplevelWidth = dpyWidth - appData.wmDecorationWidth; -+ } -+ -+ if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight) { -+ toplevelHeight = dpyHeight - appData.wmDecorationHeight; -+ } -+ -+ toplevelX = (dpyWidth - toplevelWidth - appData.wmDecorationWidth) / 2; -+ toplevelY = (dpyHeight - toplevelHeight - appData.wmDecorationHeight) /2; -+ -+ if (appData.appShare) { -+ int X = appshare_x_hint; -+ int Y = appshare_y_hint; -+ if (appData.scale) { -+ double fx = 1.0, fy = 1.0; -+ get_scale_values(&fx, &fy); -+ if (fx > 0.0 && fy > 0.0) { -+ X *= fx; -+ Y *= fy; -+ } -+ } -+ if (appshare_x_hint != appshare_0_hint) { -+ toplevelX = X; -+ } -+ if (appshare_y_hint != appshare_0_hint) { -+ toplevelY = Y; -+ } -+ } -+ -+ /* set position via "geometry" so that window manager thinks it's a -+ user-specified position and therefore honours it */ -+ -+ geometry = XtMalloc(256); -+ -+ sprintf(geometry, "%dx%d+%d+%d", toplevelWidth, toplevelHeight, toplevelX, toplevelY); -+ fprintf(stderr, "geometry: %s ycrop: %d\n", geometry, appData.yCrop); -+ XtVaSetValues(toplevel, XtNgeometry, geometry, NULL); -+ } -+ } - - /* Test if the keyboard is grabbed. If so, it's probably because the - XDM login window is up, so try iconifying it to release the grab */ - -- if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), False, GrabModeSync, -- GrabModeSync, CurrentTime) == GrabSuccess) { -- XUngrabKeyboard(dpy, CurrentTime); -- } else { -- wmState = XInternAtom(dpy, "WM_STATE", False); -- -- if (IconifyNamedWindow(DefaultRootWindow(dpy), "xlogin", False)) { -- xloginIconified = True; -- XSync(dpy, False); -- sleep(1); -- } -- } -- -- /* Set handlers for signals and X errors to perform cleanup */ -- -- signal(SIGHUP, CleanupSignalHandler); -- signal(SIGINT, CleanupSignalHandler); -- signal(SIGTERM, CleanupSignalHandler); -- defaultXErrorHandler = XSetErrorHandler(CleanupXErrorHandler); -- defaultXIOErrorHandler = XSetIOErrorHandler(CleanupXIOErrorHandler); -- defaultXtErrorHandler = XtAppSetErrorHandler(appContext, -- CleanupXtErrorHandler); -+ if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), False, GrabModeSync, GrabModeSync, CurrentTime) == GrabSuccess) { -+ XUngrabKeyboard(dpy, CurrentTime); -+ } else { -+ wmState = XInternAtom(dpy, "WM_STATE", False); -+ if (IconifyNamedWindow(DefaultRootWindow(dpy), "xlogin", False)) { -+ xloginIconified = True; -+ XSync(dpy, False); -+ sleep(1); -+ } -+ } -+ -+ /* Set handlers for signals and X errors to perform cleanup */ -+ signal(SIGHUP, CleanupSignalHandler); -+ signal(SIGINT, CleanupSignalHandler); -+ signal(SIGTERM, CleanupSignalHandler); -+ defaultXErrorHandler = XSetErrorHandler(CleanupXErrorHandler); -+ defaultXIOErrorHandler = XSetIOErrorHandler(CleanupXIOErrorHandler); -+ defaultXtErrorHandler = XtAppSetErrorHandler(appContext, CleanupXtErrorHandler); - } - - -@@ -141,14 +185,22 @@ - void - ToplevelInitAfterRealization() - { -- if (appData.fullScreen) { -- FullScreenOn(); -- } -- -- wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False); -- XSetWMProtocols(dpy, XtWindow(toplevel), &wmDeleteWindow, 1); -- XtOverrideTranslations -- (toplevel, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()")); -+ if (appData.fullScreen) { -+ FullScreenOn(); -+ if (net_wm_supported()) { -+ /* problem with scroll bars sticking: */ -+ XSync(dpy, False); -+ usleep(50 * 1000); -+ FullScreenOff(); -+ XSync(dpy, False); -+ usleep(50 * 1000); -+ FullScreenOn(); -+ } -+ } -+ -+ wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False); -+ XSetWMProtocols(dpy, XtWindow(toplevel), &wmDeleteWindow, 1); -+ XtOverrideTranslations(toplevel, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()")); - } - - -@@ -157,9 +209,7 @@ - * CurrentTime if the event has no time field. - */ - --Time --TimeFromEvent(XEvent *ev) --{ -+Time TimeFromEvent(XEvent *ev) { - switch (ev->type) { - case KeyPress: - case KeyRelease: -@@ -192,18 +242,16 @@ - * generated by SendRFBEvent. - */ - --void --Pause(Widget w, XEvent *event, String *params, Cardinal *num_params) --{ -- int msec; -+void Pause(Widget w, XEvent *event, String *params, Cardinal *num_params) { -+ int msec; - -- if (*num_params == 0) { -- msec = 100; -- } else { -- msec = atoi(params[0]); -- } -- -- usleep(msec * 1000); -+ if (*num_params == 0) { -+ msec = 100; -+ } else { -+ msec = atoi(params[0]); -+ } -+ usleep(msec * 1000); -+ if (w || event || params || num_params) {} - } - - -@@ -256,6 +304,7 @@ - /* Wait for Child 1 to die */ - wait(&childstatus); - -+ if (w || event || params || num_params) {} - return; - } - -@@ -264,11 +313,10 @@ - * Quit action - called when we get a "delete window" message. - */ - --void --Quit(Widget w, XEvent *event, String *params, Cardinal *num_params) --{ -- Cleanup(); -- exit(0); -+void Quit(Widget w, XEvent *event, String *params, Cardinal *num_params) { -+ Cleanup(); -+ if (w || event || params || num_params) {} -+ exit(0); - } - - -@@ -276,49 +324,94 @@ - * Cleanup - perform any cleanup operations prior to exiting. - */ - --void --Cleanup() --{ -- if (xloginIconified) { -- IconifyNamedWindow(DefaultRootWindow(dpy), "xlogin", True); -- XFlush(dpy); -- } -+void Cleanup() { -+ -+ if (appData.chatActive) { -+ appData.chatActive = False; -+ fprintf(stderr,"Sending SendTextChatClose()\n"); -+ SendTextChatClose(); -+ SendTextChatFinished(); -+ } -+ -+ if (xloginIconified) { -+ IconifyNamedWindow(DefaultRootWindow(dpy), "xlogin", True); -+ XFlush(dpy); -+ } - #ifdef MITSHM -- if (appData.useShm) -- ShmCleanup(); -+ if (appData.useShm) { -+ if (UsingShm()) { -+ ShmDetach(); -+ } -+ ShmCleanup(); -+ } - #endif -+ -+ releaseAllPressedModifiers(); -+ -+ fprintf(stderr,"\nVNC Viewer exiting.\n\n"); -+ if (listenSpecified) { -+ if (listenParent != 0 && getenv("SSVNC_LISTEN_ONCE") && listenParent != getpid()) { -+ fprintf(stderr, "SSVNC_LISTEN_ONCE: Trying to kill Listening Parent: %d\n", (int) listenParent); -+ fprintf(stderr, "SSVNC_LISTEN_ONCE: Press Ctrl-C if it continues to Listen.\n\n"); -+ kill(listenParent, SIGTERM); -+ } else { -+ fprintf(stderr,"(NOTE: You may need to Press Ctrl-C to make the Viewer Stop Listening.)\n\n"); -+ } -+ } -+} -+ -+static void check_dbg(void) { -+ if (getenv("SSVNC_EXIT_DEBUG")) { -+ fprintf(stderr, "Press any key to continue: "); -+ getc(stdin); -+ } - } - - static int - CleanupXErrorHandler(Display *dpy, XErrorEvent *error) - { -- fprintf(stderr,"CleanupXErrorHandler called\n"); -- Cleanup(); -- return (*defaultXErrorHandler)(dpy, error); -+ if (XError_ign) { -+ char str[4096]; -+ XError_ign++; -+ fprintf(stderr,"XError_ign called.\n"); -+ str[0] = '\0'; -+ if (XGetErrorText(dpy, error->error_code, str, 4096)) { -+ fprintf(stderr, "%s", str); -+ } -+ return 0; -+ } -+ fprintf(stderr,"CleanupXErrorHandler called\n"); -+ check_dbg(); -+ Cleanup(); -+ return (*defaultXErrorHandler)(dpy, error); - } - - static int - CleanupXIOErrorHandler(Display *dpy) - { -- fprintf(stderr,"CleanupXIOErrorHandler called\n"); -- Cleanup(); -- return (*defaultXIOErrorHandler)(dpy); -+ fprintf(stderr,"CleanupXIOErrorHandler called\n"); -+ check_dbg(); -+ Cleanup(); -+ return (*defaultXIOErrorHandler)(dpy); - } - - static void - CleanupXtErrorHandler(String message) - { -- fprintf(stderr,"CleanupXtErrorHandler called\n"); -- Cleanup(); -- (*defaultXtErrorHandler)(message); -+ fprintf(stderr,"CleanupXtErrorHandler called\n"); -+ check_dbg(); -+ Cleanup(); -+ (*defaultXtErrorHandler)(message); - } - - static void - CleanupSignalHandler(int sig) - { -- fprintf(stderr,"CleanupSignalHandler called\n"); -- Cleanup(); -- exit(1); -+ fprintf(stderr,"CleanupSignalHandler called\n"); -+ check_dbg(); -+ Cleanup(); -+ if (sig) {} -+ exit(1); - } - - -@@ -362,7 +455,7 @@ - if (!XQueryTree(dpy, w, &dummy, &dummy, &children, &nchildren)) - return False; - -- for (i = 0; i < nchildren; i++) { -+ for (i = 0; i < (int) nchildren; i++) { - if (IconifyNamedWindow(children[i], name, undo)) { - XFree ((char *)children); - return True; -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 2010-04-11 22:03:32.000000000 -0400 -@@ -22,25 +22,69 @@ - */ - - #include "vncviewer.h" -+#include <time.h> -+#include <sys/wait.h> - - #include <X11/Xaw/Form.h> - #include <X11/Xaw/Command.h> -+#include <X11/Xaw/AsciiText.h> - #include <X11/Xaw/Toggle.h> - -+#include <X11/Xaw/Box.h> -+#include <X11/Xaw/Scrollbar.h> -+ - Widget popup, fullScreenToggle; - -+Bool SendTextChatFinished(void); -+ -+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 Noop(Widget w, XEvent *event, String *params, Cardinal *num_params) { -+ if (0) fprintf(stderr, "No-op\n"); -+ if (w || event || params || num_params) {} -+} -+ - void - ShowPopup(Widget w, XEvent *event, String *params, Cardinal *num_params) - { -- XtMoveWidget(popup, event->xbutton.x_root, event->xbutton.y_root); -- XtPopup(popup, XtGrabNone); -- XSetWMProtocols(dpy, XtWindow(popup), &wmDeleteWindow, 1); -+ if (appData.popupFix) { -+ popupFixer(popup); -+ } else { -+ XtMoveWidget(popup, event->xbutton.x_root, event->xbutton.y_root); -+ XtPopup(popup, XtGrabNone); -+ } -+ if (appData.grabAll) { -+ XSync(dpy, False); -+ XRaiseWindow(dpy, XtWindow(popup)); -+ } -+ XSetWMProtocols(dpy, XtWindow(popup), &wmDeleteWindow, 1); -+ XtOverrideTranslations(popup, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HidePopup()")); -+ if (w || event || params || num_params) {} - } - - void --HidePopup(Widget w, XEvent *event, String *params, Cardinal *num_params) --{ -- XtPopdown(popup); -+HidePopup(Widget w, XEvent *event, String *params, Cardinal *num_params) { -+ XtPopdown(popup); -+ if (w || event || params || num_params) {} - } - - -@@ -52,42 +96,808 @@ - }; - - void --CreatePopup() -+CreatePopup() { -+ Widget buttonForm1, buttonForm2, twoForm, button = 0, 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); -+ XtOverrideTranslations(scaleN, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HideScaleN()")); -+ if (w || event || params || num_params) {} -+} -+ -+void -+HideScaleN(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ XtPopdown(scaleN); -+ if (w || event || params || num_params) {} -+} -+ -+ -+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 turbovncW; -+ -+static Widget turboButtons[32]; -+ -+Widget qualtext, qualslider; -+ -+void UpdateQualSlider(void) { -+#ifdef TURBOVNC -+ char text[16]; -+ XawScrollbarSetThumb(qualslider, (float)appData.qualityLevel/100., 0.); -+ sprintf(text, "%3d", appData.qualityLevel); -+ XtVaSetValues(qualtext, XtNlabel, text, NULL); -+#endif -+} -+ -+void qualScrollProc(Widget w, XtPointer client, XtPointer p) { -+#ifdef TURBOVNC -+ float size, val; int qual, pos=(int)p; -+ XtVaGetValues(w, XtNshown, &size, XtNtopOfThumb, &val, 0); -+ if(pos<0) val-=.1; else val+=.1; -+ qual=(int)(val*100.); if(qual<1) qual=1; if(qual>100) qual=100; -+ XawScrollbarSetThumb(w, val, 0.); -+ appData.qualityLevel=qual; -+ UpdateQual(); -+#endif -+ if (w || client || p) {} -+} -+ -+void qualJumpProc(Widget w, XtPointer client, XtPointer p) { -+#ifdef TURBOVNC -+ float val=*(float *)p; int qual; -+ qual=(int)(val*100.); if(qual<1) qual=1; if(qual>100) qual=100; -+ appData.qualityLevel=qual; -+ UpdateQual(); -+#endif -+ if (w || client || p) {} -+} -+ -+void UpdateSubsampButtons(void) { -+#ifdef TURBOVNC -+ int i; -+ for (i=7; i <= 10; i++) { -+ XtVaSetValues(turboButtons[i], XtNstate, 0, NULL); -+ } -+ if (appData.subsampLevel==TVNC_1X) { -+ i = 7; -+ } else if (appData.subsampLevel==TVNC_2X) { -+ i = 8; -+ } else if (appData.subsampLevel==TVNC_4X) { -+ i = 9; -+ } else if (appData.subsampLevel==TVNC_GRAY) { -+ i = 10; -+ } else { -+ return; -+ } -+ XtVaSetValues(turboButtons[i], XtNstate, 1, NULL); -+#endif -+} -+ -+void -+ShowTurboVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ UpdateSubsampButtons(); -+ UpdateQualSlider(); -+ if (appData.popupFix) { -+ popupFixer(turbovncW); -+ } else { -+ XtMoveWidget(turbovncW, event->xbutton.x_root, event->xbutton.y_root); -+ XtPopup(turbovncW, XtGrabNone); -+ } -+ if (appData.grabAll) { -+ XRaiseWindow(dpy, XtWindow(turbovncW)); -+ } -+ XSetWMProtocols(dpy, XtWindow(turbovncW), &wmDeleteWindow, 1); -+ XtOverrideTranslations(turbovncW, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HideTurboVNC()")); -+ if (w || event || params || num_params) {} -+} -+ -+void -+HideTurboVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ XtPopdown(turbovncW); -+ if (w || event || params || num_params) {} -+} -+ -+void -+CreateTurboVNC() { -+ Widget buttonForm, button, prevButton = NULL; -+ Widget label; -+ int i; -+ char buttonName[32]; -+ String buttonType; -+ -+ turbovncW = XtVaCreatePopupShell("turboVNC", transientShellWidgetClass, toplevel, NULL); -+ -+ buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, turbovncW, NULL); -+ -+ for (i = 0; i <= 12; i++) { -+ sprintf(buttonName, "button%d", i); -+#ifndef TURBOVNC -+ if (i == 0) { -+ sprintf(buttonName, "buttonNone"); -+ } else if (i > 0) { -+ return; -+ } -+#endif -+ XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName, -+ "Button", resources, 1, NULL); -+ -+ button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, -+ buttonForm, NULL); -+ turboButtons[i] = button; -+ XtVaSetValues(button, XtNfromVert, prevButton, -+ XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); -+ prevButton = button; -+ } -+ -+ label = XtCreateManagedWidget("qualLabel", toggleWidgetClass, buttonForm, NULL, 0); -+ XtVaSetValues(label, XtNfromVert, prevButton, XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); -+ -+ qualslider = XtCreateManagedWidget("qualBar", scrollbarWidgetClass, buttonForm, NULL, 0); -+ XtVaSetValues(qualslider, XtNfromVert, label, XtNleft, XawChainLeft, NULL); -+ XtAddCallback(qualslider, XtNscrollProc, qualScrollProc, NULL) ; -+ XtAddCallback(qualslider, XtNjumpProc, qualJumpProc, NULL) ; -+ -+ qualtext = XtCreateManagedWidget("qualText", labelWidgetClass, buttonForm, NULL, 0); -+ XtVaSetValues(qualtext, XtNfromVert, label, XtNfromHoriz, qualslider, XtNright, XawChainRight, NULL); -+} -+ -+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); -+ XtOverrideTranslations(qualityW, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HideQuality()")); -+ if (w || event || params || num_params) {} -+} -+ -+void -+HideQuality(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ XtPopdown(qualityW); -+ if (w || event || params || num_params) {} -+} -+ -+ -+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); -+ XtOverrideTranslations(compressW, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HideCompress()")); -+ if (w || event || params || num_params) {} -+} -+ -+void -+HideCompress(Widget w, XEvent *event, String *params, Cardinal *num_params) -+{ -+ XtPopdown(compressW); -+ if (w || event || params || num_params) {} -+} -+ -+ -+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; -+ } -+ if (w || event || params || num_params) {} -+} -+ -+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) { -+ sock = ListenAtTcpPort6(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; -+ if (w || event || params || num_params) {} -+} -+ -+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; -+ wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False); -+ XSetWMProtocols(dpy, XtWindow(chat), &wmDeleteWindow, 1); -+ if (appData.chatOnly) { -+ XtOverrideTranslations(chat, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()")); -+ } else { -+ XtOverrideTranslations(chat, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HideChat()")); -+ } -+ XSync(dpy, False); -+ usleep(200 * 1000); -+ } -+ if (w || event || params || num_params) {} -+} -+ -+void hidechat(void) { -+ appData.chatActive = False; -+ if (appData.termChat) { -+ return; -+ } -+ if (chat_visible) { -+ XtPopdown(chat); -+ chat_visible = 0; -+ XSync(dpy, False); -+ usleep(200 * 1000); -+ } -+ if (appData.chatOnly) { -+ Quit(0, NULL, NULL, NULL); -+ } -+} -+ -+void HideChat(Widget w, XEvent *event, String *params, Cardinal *num_params) { -+ SendTextChatClose(); -+ SendTextChatFinished(); -+ hidechat(); -+ if (w || event || params || num_params) {} -+} -+ -+void dismiss_proc(Widget w, XtPointer client_data, XtPointer call_data) { -+ SendTextChatClose(); -+ SendTextChatFinished(); -+ hidechat(); -+ if (w || client_data || call_data) {} -+} -+ -+extern void printChat(char *, Bool); -+ -+static void ChatTextCallback(XtPointer clientData, XtIntervalId *id); -+static XtIntervalId timer; -+static Bool timerSet = False; -+ -+void CheckTextInput(void); -+extern double start_time; -+ -+static void ChatTextCallback(XtPointer clientData, XtIntervalId *id) { -+ static int db = -1; -+ if (db < 0) { -+ if (getenv("SSVNC_DEBUG_CHAT")) { -+ db = 1; -+ } else { -+ db = 0; -+ } -+ } -+ if (db) fprintf(stderr, "ChatTextCallback: %.4f\n", dnow() - start_time); -+ CheckTextInput(); -+ if (clientData || id) {} -+} -+ -+void CheckTextInput(void) { -+ Arg args[2]; -+ String str; -+ int len; -+ static int db = -1; -+ -+ if (timerSet) { -+ XtRemoveTimeOut(timer); -+ timerSet = False; -+ } -+ if (appData.chatActive) { -+ timer = XtAppAddTimeOut(appContext, 333, ChatTextCallback, NULL); -+ timerSet = True; -+ } -+ if (appData.chatOnly && !appData.chatActive) { -+ Quit(0, NULL, NULL, NULL); -+ } -+ -+ if (appData.termChat) { -+ return; -+ } -+#if 0 -+ if (!appData.chatActive) { -+ return; -+ } -+#endif -+ -+ if (db < 0) { -+ if (getenv("SSVNC_DEBUG_CHAT")) { -+ db = 1; -+ } else { -+ db = 0; -+ } -+ } -+ -+ XtSetArg(args[0], XtNstring, &str); -+ XtGetValues(entry, args, 1); -+ -+ if (db) fprintf(stderr, "CheckTextInput\n"); -+ -+ if (str == NULL || str[0] == '\0') { -+ return; -+ } else { -+ char *q; -+ len = strlen(str); -+ if (db) fprintf(stderr, "CheckTextInput: len: %d '%s'\n", len, str); -+ if (len <= 0) { -+ return; -+ } -+ q = strrchr(str, '\n'); -+ if (q) { -+ char *send, save[2]; -+ save[0] = *(q+1); -+ *(q+1) = '\0'; -+ send = strdup(str); -+ *(q+1) = save[0]; -+ if (send) { -+ SendTextChat(send); -+ printChat("Send: ", True); -+ printChat(send, True); -+ free(send); -+ if (save[0] == '\0') { -+ XtVaSetValues(entry, XtNtype, XawAsciiString, XtNstring, "", NULL); -+ } else { -+ char *leak = strdup(q+1); -+ XtVaSetValues(entry, XtNtype, XawAsciiString, XtNstring, leak, NULL); -+ if (strlen(leak) > 0) { -+ XSync(dpy, False); -+ XtVaSetValues(entry, XtNinsertPosition, strlen(leak), NULL); -+ } -+ } -+ } -+ } -+ } -+} -+ -+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) { -+ XawTextPosition beg, end; -+ static XawTextPosition pos = 0; -+ XawTextBlock txt; -+ -+ if (appData.termChat) { -+ return; -+ } -+ -+ XawTextSetInsertionPoint(text, pos); -+ beg = XawTextGetInsertionPoint(text); -+ end = beg; -+#if 0 -+ fprintf(stderr, "AppendChatInput: pos=%d in= '%s'\n", beg, in); -+#endif -+ -+ 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); -+#if 0 -+ fprintf(stderr, "AppendChatInput done pos=%d\n", pos); -+#endif -+} -+ -+#if 0 -+static char errorbuf[1] = {0}; -+#endif -+ -+void CreateChat(void) { -+ -+ Widget myform, dismiss; -+ Dimension w = 400, h = 300; -+ -+ 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, XawtextWrapNever, -+ 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); -+ -+ XtSetKeyboardFocus(chat, entry); -+} -+ -+Widget msgwin, msgtext; -+ -+void AppendMsg(char *in) { -+ XawTextPosition beg, end; -+ static XawTextPosition pos = 0; -+ XawTextBlock txt; -+ -+ XawTextSetInsertionPoint(msgtext, pos); -+ beg = XawTextGetInsertionPoint(msgtext); -+ end = beg; -+ -+ txt.firstPos = 0; -+ txt.length = strlen(in); -+ txt.ptr = in; -+ txt.format = FMT8BIT; -+ -+ XawTextReplace(msgtext, beg, end, &txt); -+ XawTextSetInsertionPoint(msgtext, beg + txt.length); -+ -+ pos = XawTextGetInsertionPoint(msgtext); -+} -+ -+static int msg_visible = 0; -+static int msg_NO_clicked = 0; -+ -+void msg_dismiss_proc(Widget w, XtPointer client_data, XtPointer call_data) { -+ XtPopdown(msgwin); -+ msg_visible = 0; -+ XSync(dpy, False); -+ usleep(200 * 1000); -+ if (w || client_data || call_data) {} -+} -+ -+void msg_NO_proc(Widget w, XtPointer client_data, XtPointer call_data) { -+ XtPopdown(msgwin); -+ msg_visible = 0; -+ msg_NO_clicked = 1; -+ XSync(dpy, False); -+ usleep(200 * 1000); -+ if (w || client_data || call_data) {} -+} -+ -+int CreateMsg(char *msg, int wait) { -+ -+ Widget myform, dismiss, reject; -+ char *p; -+ int n, run, wmax = 0; -+ int ret = 1; -+ Dimension w, h; -+ -+ -+ n = 0; -+ run = 0; -+ p = msg; -+ while (*p != '\0') { -+ if (*p == '\n') { -+ run = 0; -+ n++; -+ } -+ run++; -+ if (run > wmax) wmax = run; -+ p++; -+ } -+ if (wmax > 80) { -+ if (wmax > 120) n++; -+ if (wmax > 80) n++; -+ wmax = 80; -+ } -+ h = (Dimension) (n+2) * 14; -+ w = (Dimension) (wmax+10) * 8; -+ -+ msgwin = XtVaCreatePopupShell("Message", topLevelShellWidgetClass, toplevel, XtNmappedWhenManaged, False, NULL); -+ -+ myform = XtVaCreateManagedWidget("myform", formWidgetClass, msgwin, NULL); -+ -+ msgtext = XtVaCreateManagedWidget("msgtext", 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); -+ -+ if (wait == 2) { -+ msg_NO_clicked = 0; -+ -+ dismiss = XtVaCreateManagedWidget("dismiss", commandWidgetClass, myform, XtNlabel, "Accept", XtNfromVert, msgtext, NULL); -+ XtAddCallback(dismiss, XtNcallback, msg_dismiss_proc, NULL); -+ -+ reject = XtVaCreateManagedWidget("reject", commandWidgetClass, myform, XtNlabel, "Reject", XtNfromVert, dismiss, NULL); -+ XtAddCallback(reject, XtNcallback, msg_NO_proc, NULL); -+ } else { -+ dismiss = XtVaCreateManagedWidget("dismiss", commandWidgetClass, myform, XtNlabel, "OK", XtNfromVert, msgtext, NULL); -+ XtAddCallback(dismiss, XtNcallback, msg_dismiss_proc, NULL); -+ -+ } -+ -+ AppendMsg(""); -+ AppendMsg(msg); -+ -+ XtRealizeWidget(msgwin); -+ -+ XtPopup(msgwin, XtGrabNone); -+ -+ XSync(dpy, False); -+ msg_visible = 1; -+ while (wait && msg_visible) { -+ if (0) fprintf(stderr, "mv: %d\n", msg_visible); -+ XtAppProcessEvent(appContext, XtIMAll); -+ } -+ if (wait == 2) { -+ if (msg_NO_clicked) { -+ ret = 0; -+ } else { -+ ret = 1; -+ } -+ } -+ return ret; -+} -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, "<argsresources.c") || die; -+ -+while (<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 2010-04-17 22:34:38.000000000 -0400 -@@ -23,7 +23,10 @@ - * rfbproto.c - functions to deal with client side of RFB protocol. - */ - -+#include <sys/stat.h> - #include <unistd.h> -+#include <time.h> -+#include <ctype.h> - #include <errno.h> - #include <pwd.h> - #include <vncviewer.h> -@@ -31,6 +34,9 @@ - #include <zlib.h> - #include <jpeglib.h> - -+int server_major = 0, server_minor = 0; -+int viewer_major = 0, viewer_minor = 0; -+ - static void InitCapabilities(void); - static Bool SetupTunneling(void); - static int ReadSecurityType(void); -@@ -57,6 +63,47 @@ - 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); -+ -+extern Bool HandleCursorPos(int x, int y); -+extern void printChat(char *, Bool); -+ -+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 +114,25 @@ - static void JpegSetSrcManager(j_decompress_ptr cinfo, CARD8 *compressedData, - int compressedLen); - -+extern void deskey(unsigned char *, int); -+extern void des(unsigned char *, unsigned char *); -+ -+extern int currentMsg; -+extern double scale_factor_x; -+extern double scale_factor_y; -+ -+extern int skip_maybe_sync; -+ -+int sent_FBU = 0; -+int skip_XtUpdate = 0; -+int skip_XtUpdateAll = 0; -+ -+static double dt_out = 0.0; -+static double dt_out_sc = 0.0; -+double latency = 0.0; -+double connect_time = 0.0; -+ -+void raiseme(int force); - - int rfbsock; - char *desktopName; -@@ -75,6 +141,14 @@ - char *serverCutText = NULL; - Bool newServerCutText = False; - -+/* ultravnc mslogon */ -+#define rfbUltraVncMsLogon 0xfffffffa -+static Bool AuthUltraVncMsLogon(void); -+extern void UvncEncryptPasswd_MSLOGON(unsigned char *encryptedPasswd, char *passwd); -+extern void UvncEncryptBytes2(unsigned char *where, int length, unsigned char *key); -+extern void UvncDecryptBytes2(unsigned char *where, int length, unsigned char *key); -+extern unsigned int urandom(void); -+ - int endianTest = 1; - - static Bool tightVncProtocol = False; -@@ -177,8 +251,26 @@ - 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"); -+ -+#ifdef TURBOVNC -+ CapsAdd(encodingCaps, rfbJpegQualityLevel1, rfbTurboVncVendor, -+ sig_rfbEncodingNewFBSize, "TurboJPEG quality level"); -+ CapsAdd(encodingCaps, rfbJpegSubsamp1X, rfbTurboVncVendor, -+ sig_rfbEncodingNewFBSize, "TurboJPEG subsampling level"); -+#endif - } - -+static char msgbuf[10000]; -+ -+static void wmsg(char *msg, int wait) { -+ fprintf(stderr, "%s", msg); -+ if (!use_tty() && !getenv("SSVNC_NO_MESSAGE_POPUP")) { -+ CreateMsg(msg, wait); -+ } -+} - - /* - * ConnectToRFBServer. -@@ -187,24 +279,179 @@ - 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; -- } -+ 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; -+ } -+ } -+ } - -- rfbsock = ConnectToTcpAddr(host, port); -+ if (cmd != NULL) { -+ int sfd[2]; -+ char *q, *cmd2 = strdup(cmd); -+ pid_t pid; -+ -+ q = strstr(cmd2, "pw="); -+ if (q && !getenv("SSVNC_SHOW_ULTRAVNC_DSM_PASSWORD")) { -+ q += strlen("pw="); -+ while (*q != '\0' && !isspace(*q)) { -+ *q = '*'; -+ q++; -+ } -+ } -+ -+ fprintf(stderr, "exec-cmd: %s\n\n", cmd2); -+ free(cmd2); -+ -+ 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) { -+ sprintf(msgbuf,"Unable to connect to exec'd command: %s\n", cmd); -+ wmsg(msgbuf, 1); -+ return False; -+ } -+ } else if (strstr(hostname, "fd=") == hostname) { -+ rfbsock = atoi(hostname + strlen("fd=")); -+ } else if (strchr(hostname, '/') && stat(hostname, &sb) == 0) { -+ /* assume unix domain socket */ -+ char *thost = strdup(hostname); -+ -+ rfbsock = ConnectToUnixSocket(thost); -+ free(thost); -+ -+ if (rfbsock < 0) { -+ sprintf(msgbuf,"Unable to connect to VNC server (unix-domain socket: %s)\n", hostname); -+ wmsg(msgbuf, 1); -+ return False; -+ } -+ -+ } else { -+ rfbsock = ConnectToTcpAddr(hostname, port); -+ -+ if (rfbsock < 0 && !appData.noipv4) { -+ char *q, *hosttmp; -+ if (hostname[0] == '[') { -+ hosttmp = strdup(hostname+1); -+ } else { -+ hosttmp = strdup(hostname); -+ } -+ q = strrchr(hosttmp, ']'); -+ if (q) *q = '\0'; -+ if (strstr(hosttmp, "::ffff:") == hosttmp || strstr(hosttmp, "::FFFF:") == hosttmp) { -+ char *host = hosttmp + strlen("::ffff:"); -+ if (dotted_ip(host, 0)) { -+ fprintf(stderr, "ConnectToTcpAddr[ipv4]: re-trying connection using '%s'\n", host); -+ rfbsock = ConnectToTcpAddr(host, port); -+ } -+ } -+ free(hosttmp); -+ } -+ -+ if (rfbsock < 0) { -+ sprintf(msgbuf,"Unable to connect to VNC server (%s:%d)\n", hostname, port); -+ wmsg(msgbuf, 1); -+ return False; -+ } -+ } - -- if (rfbsock < 0) { -- fprintf(stderr,"Unable to connect to VNC server\n"); -- return False; -- } -+ setnb = SetNonBlocking(rfbsock); -+ return setnb; -+} - -- return SetNonBlocking(rfbsock); -+static void printFailureReason(void) { -+ CARD32 reasonLen; -+ ReadFromRFBServer((char *)&reasonLen, 4); -+ reasonLen = Swap32IfLE(reasonLen); -+ if (reasonLen < 4096) { -+ char *reason = (char *) malloc(reasonLen+1); -+ memset(reason, 0, reasonLen+1); -+ ReadFromRFBServer(reason, reasonLen); -+ sprintf(msgbuf, "Reason: %s\n", reason); -+ wmsg(msgbuf, 1); -+ free(reason); -+ } - } - -+static char *pr_sec_type(int type) { -+ char *str = "unknown"; -+ if (type == rfbSecTypeInvalid) str = "rfbSecTypeInvalid"; -+ if (type == rfbSecTypeNone) str = "rfbSecTypeNone"; -+ if (type == rfbSecTypeVncAuth) str = "rfbSecTypeVncAuth"; -+ if (type == rfbSecTypeRA2) str = "rfbSecTypeRA2"; -+ if (type == rfbSecTypeRA2ne) str = "rfbSecTypeRA2ne"; -+ if (type == rfbSecTypeTight) str = "rfbSecTypeTight"; -+ if (type == rfbSecTypeUltra) str = "rfbSecTypeUltra"; -+ -+ if (type == rfbSecTypeAnonTls) str = "rfbSecTypeAnonTls"; -+ if (type == rfbSecTypeVencrypt) str = "rfbSecTypeVencrypt"; -+ -+ if (type == (int) rfbUltraVncMsLogon) str = "rfbUltraVncMsLogon"; -+ return str; -+} -+ -+static char *pr_sec_subtype(int type) { -+ char *str = "unknown"; -+ if (type == rfbVencryptPlain) str = "rfbVencryptPlain"; -+ if (type == rfbVencryptTlsNone) str = "rfbVencryptTlsNone"; -+ if (type == rfbVencryptTlsVnc) str = "rfbVencryptTlsVnc"; -+ if (type == rfbVencryptTlsPlain) str = "rfbVencryptTlsPlain"; -+ if (type == rfbVencryptX509None) str = "rfbVencryptX509None"; -+ if (type == rfbVencryptX509Vnc) str = "rfbVencryptX509Vnc"; -+ if (type == rfbVencryptX509Plain) str = "rfbVencryptX509Plain"; -+ return str; -+} - -+extern void ProcessXtEvents(void); - /* - * InitialiseRFBConnection. - */ -@@ -212,211 +459,654 @@ - Bool - InitialiseRFBConnection(void) - { -- rfbProtocolVersionMsg pv; -- int server_major, server_minor; -- int viewer_major, viewer_minor; -- rfbClientInitMsg ci; -- int secType; -+ rfbProtocolVersionMsg pv; -+ rfbClientInitMsg ci; -+ int i, secType, anon_dh = 0, accept_uvnc = 0; -+ FILE *pd; -+ char *hsfile = NULL; -+ char *hsparam[128]; -+ char *envsetsec = getenv("SSVNC_SET_SECURITY_TYPE"); -+ char line[128]; -+ double dt = 0.0; - -- /* 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; -+ for (i=0; i < 128; i++) { -+ hsparam[i] = NULL; -+ } - -- errorMessageOnReadFailure = True; -+ skip_XtUpdateAll = 1; -+ ProcessXtEvents(); -+ skip_XtUpdateAll = 0; -+ -+ if (getenv("SSVNC_PREDIGESTED_HANDSHAKE")) { -+ double start = dnow(); -+ hsfile = getenv("SSVNC_PREDIGESTED_HANDSHAKE"); -+ while (dnow() < start + 10.0) { -+ int done = 0; -+ usleep(100 * 1000); -+ if ((pd = fopen(hsfile, "r")) != NULL) { -+ while (fgets(line, 128, pd) != NULL) { -+ if (strstr(line, "done") == line) { -+ done = 1; -+ usleep(100 * 1000); -+ break; -+ } -+ } -+ fclose(pd); -+ } -+ if (done) { -+ break; -+ } -+ } -+ if ((pd = fopen(hsfile, "r")) != NULL) { -+ i = 0; -+ while (fgets(line, 128, pd) != NULL) { -+ hsparam[i] = strdup(line); -+ fprintf(stderr, "%s", line); -+ if (i++ > 100) break; -+ } -+ fclose(pd); -+ } -+ unlink(hsfile); -+ } - -- pv[sz_rfbProtocolVersionMsg] = 0; -+ if (getenv("SSVNC_SKIP_RFB_PROTOCOL_VERSION")) { -+ viewer_major = 3; -+ viewer_minor = 8; -+ goto end_of_proto_msg; -+ } else if (hsfile) { -+ int k = 0; -+ while (hsparam[k] != NULL) { -+ char *str = hsparam[k++]; -+ if (strstr(str, "server=") == str) { -+ sprintf(pv, "%s", str + strlen("server=")); -+ goto readed_pv; -+ } -+ } -+ } - -- if (sscanf(pv, rfbProtocolVersionFormat, -- &server_major, &server_minor) != 2) { -- fprintf(stderr,"Not a valid VNC server\n"); -- return False; -- } -+ dt = dnow(); -+ if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) { -+ return False; -+ } -+ if (getenv("PRINT_DELAY1")) fprintf(stderr, "delay1: %.3f ms\n", (dnow() - dt) * 1000); -+ dt = 0.0; - -- 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; -- } -+ readed_pv: - -- fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n", -- viewer_major, viewer_minor); -+ errorMessageOnReadFailure = True; - -- sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor); -+ pv[sz_rfbProtocolVersionMsg] = 0; - -- if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) -- 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) { -+ msgbuf[0] = '\0'; -+ strcat(msgbuf, "\n"); -+ strcat(msgbuf, "***************************************************************\n"); -+ strcat(msgbuf, "To work around UltraVNC SC III SSL dropping after a few minutes\n"); -+ strcat(msgbuf, "you may need to set STUNNEL_EXTRA_OPTS_USER='options = ALL'.\n"); -+ strcat(msgbuf, "***************************************************************\n"); -+ strcat(msgbuf, "\n"); -+ wmsg(msgbuf, 0); -+ } -+ if (strstr(pv, "ID:") == pv) { -+ goto check_ID_string; -+ } -+ if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) == 2) { -+ goto ultra_vnc_nonsense; -+ } -+ } -+ sprintf(msgbuf, "Not a valid VNC server: '%s'\n", pv); -+ wmsg(msgbuf, 1); -+ return False; -+ } - -- /* Read or select the security type. */ -- if (viewer_minor == rfbProtocolMinorVersion) { -- secType = SelectSecurityType(); -- } else { -- secType = ReadSecurityType(); -- } -- if (secType == rfbSecTypeInvalid) -- return False; -+ 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) { -+ sprintf(msgbuf,"Not a valid VNC server: '%s'\n", pv); -+ wmsg(msgbuf, 1); -+ return False; -+ } -+ } - -- switch (secType) { -- case rfbSecTypeNone: -- fprintf(stderr, "No authentication needed\n"); -- break; -- case rfbSecTypeVncAuth: -- if (!AuthenticateVNC()) -- return False; -- break; -- case rfbSecTypeTight: -- tightVncProtocol = True; -- InitCapabilities(); -- if (!SetupTunneling()) -- return False; -- if (!PerformAuthenticationTight()) -- return False; -- break; -- default: /* should never happen */ -- fprintf(stderr, "Internal error: Invalid security type\n"); -- return False; -- } -+ ultra_vnc_nonsense: -+ fprintf(stderr,"\nProto: %s\n", pv); - -- ci.shared = (appData.shareDesktop ? 1 : 0); -+ viewer_major = 3; - -- if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) -- 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\n", viewer_major, viewer_minor); - -- if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg)) -- return False; -+ } else if (getenv("SSVNC_RFB_VERSION") != NULL && sscanf(getenv("SSVNC_RFB_VERSION"), "%d.%d", &viewer_major, &viewer_minor) == 2) { -+ fprintf(stderr,"Setting RFB version to %d.%d from SSVNC_RFB_VERSION.\n\n", viewer_major, viewer_minor); -+ -+ } else if (server_major > 3) { -+ viewer_minor = 8; -+ } 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\n"); -+ viewer_minor = 3; -+ -+ } else if (server_major == 3 && server_minor >= 8) { -+ /* the server supports at least the standard protocol 3.8 */ -+ viewer_minor = 8; -+ -+ } else if (server_major == 3 && server_minor == 7) { -+ /* the server supports at least the standard protocol 3.7 */ -+ viewer_minor = 7; -+ -+ } else { -+ /* any other server version, request the standard 3.3 */ -+ viewer_minor = 3; -+ } -+ /* n.b. Apple Remote Desktop uses 003.889, but we should be OK with 3.8 */ - -- si.framebufferWidth = Swap16IfLE(si.framebufferWidth); -- si.framebufferHeight = Swap16IfLE(si.framebufferHeight); -- si.format.redMax = Swap16IfLE(si.format.redMax); -- si.format.greenMax = Swap16IfLE(si.format.greenMax); -- si.format.blueMax = Swap16IfLE(si.format.blueMax); -- si.nameLength = Swap32IfLE(si.nameLength); -- -- /* FIXME: Check arguments to malloc() calls. */ -- desktopName = malloc(si.nameLength + 1); -- if (!desktopName) { -- fprintf(stderr, "Error allocating memory for desktop name, %lu bytes\n", -- (unsigned long)si.nameLength); -- return False; -- } -+ if (appData.msLogon) { -+ if (server_minor == 4) { -+ fprintf(stderr,"Setting RFB version to 3.4 for UltraVNC MS Logon.\n\n"); -+ viewer_minor = 4; -+ } -+ } -+ if (getenv("SSVNC_ACCEPT_POPUP_SC")) { -+ if (server_minor == -4 || server_minor == -6 || server_minor == 14 || server_minor == 16) { -+ /* 4 and 6 work too? */ -+ viewer_minor = server_minor; -+ accept_uvnc = 1; -+ fprintf(stderr,"Reset RFB version to 3.%d for UltraVNC SSVNC_ACCEPT_POPUP_SC.\n\n", viewer_minor); -+ } -+ } - -- if (!ReadFromRFBServer(desktopName, si.nameLength)) return False; -+ fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n", viewer_major, viewer_minor); - -- desktopName[si.nameLength] = 0; -+ if (hsfile) { -+ int k = 0; -+ while (hsparam[k] != NULL) { -+ char *str = hsparam[k++]; -+ if (strstr(str, "latency=") == str) { -+ latency = 1000. * atof(str + strlen("latency=")); -+ } -+ } -+ k = 0; -+ while (hsparam[k] != NULL) { -+ char *str = hsparam[k++]; -+ int v1, v2; -+ if (sscanf(str, "viewer=RFB %d.%d\n", &v1, &v2) == 2) { -+ viewer_major = v1; -+ viewer_minor = v2; -+ fprintf(stderr, "\nPre-Handshake set protocol version to: %d.%d Latency: %.2f ms\n", viewer_major, viewer_minor, latency); -+ goto end_of_proto_msg; -+ } -+ } -+ } -+ sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor); - -- fprintf(stderr,"Desktop name \"%s\"\n",desktopName); -+ if (!appData.appShare) { -+ usleep(100*1000); -+ } -+ dt = dnow(); -+ if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) { -+ return False; -+ } - -- fprintf(stderr,"VNC server default format:\n"); -- PrintPixelFormat(&si.format); -+ end_of_proto_msg: - -- if (tightVncProtocol) { -- /* Read interaction capabilities (protocol 3.7t) */ -- if (!ReadInteractionCaps()) -- return False; -- } -+ if (envsetsec) { -+ secType = atoi(getenv("SSVNC_SET_SECURITY_TYPE")); -+ goto sec_type; -+ } -+ if (hsfile) { -+ int k = 0; -+ while (hsparam[k] != NULL) { -+ char *str = hsparam[k++]; -+ int st; -+ if (sscanf(str, "sectype=%d\n", &st) == 1) { -+ secType = st; -+ fprintf(stderr, "Pre-Handshake set Security-Type to: %d (%s)\n", st, pr_sec_type(st)); -+ if (secType == rfbSecTypeVencrypt) { -+ goto sec_type; -+ } else if (secType == rfbSecTypeAnonTls) { -+ break; -+ } -+ } -+ } -+ } - -- return True; -+ if (accept_uvnc) { -+ unsigned int msg_sz = 0; -+ unsigned int nimmer = 0; -+ char msg[3000]; -+ char *msg_buf, *sip = NULL, *sih = NULL; -+ -+ if (!ReadFromRFBServer((char *) &msg_sz, 4)) { -+ return False; -+ } -+ dt_out_sc = dnow(); -+ msg_sz = Swap32IfBE(msg_sz); -+ if (msg_sz > 1024) { -+ fprintf(stderr, "UVNC msg size too big: %d\n", msg_sz); -+ exit(1); -+ } -+ msg_buf = (char *)calloc(msg_sz + 100, 1); -+ if (!ReadFromRFBServer(msg_buf, msg_sz)) { -+ return False; -+ } -+ -+ if (0) { -+ fprintf(stderr, "msg_buf: "); -+ write(2, msg_buf, msg_sz); -+ fprintf(stderr, "\n"); -+ } -+ -+ sip = get_peer_ip(rfbsock); -+ if (strlen(sip) > 100) sip = "0.0.0.0"; -+ sih = ip2host(sip); -+ if (strlen(sih) > 300) sih = "unknown"; -+ -+ sprintf(msg, "\n(LISTEN) Reverse VNC connection from IP: %s\n Hostname: %s\n\n", sip, sih); -+ strcat(msg, "UltraVNC Server Message:\n"); -+ strcat(msg, msg_buf); -+ free(msg_buf); -+ strcat(msg, "\n\n"); -+ strcat(msg, "Accept or Reject VNC connection?"); -+ if (CreateMsg(msg, 2)) { -+ nimmer = 1; -+ fprintf(stderr, "Accepting connection.\n\n"); -+ } else { -+ nimmer = 0; -+ fprintf(stderr, "Refusing connection.\n\n"); -+ } -+ if (!WriteExact(rfbsock, (char *) &nimmer, 4)) { -+ return False; -+ } -+ } -+ -+ /* Read or select the security type. */ -+ dt_out = 0.0; -+ -+ skip_XtUpdateAll = 1; -+ if (viewer_minor >= 7 && !accept_uvnc) { -+ secType = SelectSecurityType(); -+ } else { -+ secType = ReadSecurityType(); -+ } -+ skip_XtUpdateAll = 0; -+ -+ if (accept_uvnc) { -+ dt_out = dt_out_sc; -+ } -+ -+ if (dt > 0.0 && dt_out > dt) { -+ latency = (dt_out - dt) * 1000; -+ } -+ -+ fprintf(stderr, "Security-Type: %d (%s) Latency: %.2f ms\n", (int) secType, pr_sec_type(secType), latency); -+ if (secType == rfbSecTypeInvalid) { -+ return False; -+ } -+ -+ sec_type: -+ -+ if (hsfile) { -+ int subsectype = 0; -+ int k = 0; -+ while (hsparam[k] != NULL) { -+ char *str = hsparam[k++]; -+ int st; -+ if (sscanf(str, "subtype=%d\n", &st) == 1) { -+ subsectype = st; -+ fprintf(stderr, "Pre-Handshake set Sub-Security-Type to: %d (%s)\n\n", st, pr_sec_subtype(st)); -+ break; -+ } -+ } -+ -+ if (!subsectype) { -+ ; -+ } else if (secType == rfbSecTypeVencrypt) { -+ if (subsectype == rfbVencryptTlsNone) { -+ anon_dh = 1; -+ secType = rfbSecTypeNone; -+ } else if (subsectype == rfbVencryptTlsVnc) { -+ anon_dh = 1; -+ secType = rfbSecTypeVncAuth; -+ } else if (subsectype == rfbVencryptTlsPlain) { -+ anon_dh = 1; -+ secType = rfbSecTypeNone; -+ } else if (subsectype == rfbVencryptX509None) { -+ secType = rfbSecTypeNone; -+ } else if (subsectype == rfbVencryptX509Vnc) { -+ secType = rfbSecTypeVncAuth; -+ } else if (subsectype == rfbVencryptX509Plain) { -+ secType = rfbSecTypeNone; -+ } -+ if (subsectype == rfbVencryptTlsPlain || subsectype == rfbVencryptX509Plain) { -+ usleep(300*1000); -+ } -+ if (subsectype == rfbVencryptTlsNone || subsectype == rfbVencryptTlsVnc || subsectype == rfbVencryptTlsPlain) { -+ char tmp[1000], line[100]; -+ tmp[0] = '\0'; -+ strcat(tmp, "\n"); -+ sprintf(line, "WARNING: Anonymous Diffie-Hellman TLS used (%s),\n", pr_sec_subtype(subsectype)); -+ strcat(tmp, line); -+ strcat(tmp, "WARNING: there will be *NO* Authentication of the VNC Server.\n"); -+ strcat(tmp, "WARNING: I.e. a Man-In-The-Middle attack is possible.\n"); -+ strcat(tmp, "WARNING: Configure the server to use X509 certs and verify them.\n\n"); -+ wmsg(tmp, 1); -+ } -+ if (subsectype == rfbVencryptTlsPlain || subsectype == rfbVencryptX509Plain) { -+ fprintf(stderr, "\nVeNCrypt Plain (username + passwd) selected.\n\n"); -+ if (appData.unixPW != NULL) { -+ unixpw(appData.unixPW, 1); -+ } else if (getenv("SSVNC_UNIXPW")) { -+ unixpw(getenv("SSVNC_UNIXPW"), 1); -+ } else { -+ unixpw(".", 1); -+ } -+ } -+ } -+ } -+ -+ switch (secType) { -+ case rfbSecTypeNone: -+ fprintf(stderr, "No VNC authentication needed\n"); -+ if (viewer_minor >= 8) { -+ CARD32 authResult; -+ -+ if (!ReadFromRFBServer((char *)&authResult, 4)) { -+ return False; -+ } -+ -+ authResult = Swap32IfLE(authResult); -+ -+ if (authResult == rfbVncAuthOK) { -+ fprintf(stderr, "VNC authentication succeeded (%d) for rfbSecTypeNone (RFB 3.8)\n", (int) authResult); -+ } else { -+ sprintf(msgbuf, "VNC authentication failed (%d) for rfbSecTypeNone (RFB 3.8)\n\n", (int) authResult); -+ wmsg(msgbuf, 1); -+ return False; -+ } -+ } -+ fprintf(stderr, "\n"); -+ break; -+ case rfbSecTypeVncAuth: -+ if (!AuthenticateVNC()) { -+ return False; -+ } -+ break; -+ case rfbSecTypeTight: -+ tightVncProtocol = True; -+ InitCapabilities(); -+ if (!SetupTunneling()) { -+ return False; -+ } -+ if (!PerformAuthenticationTight()) { -+ return False; -+ } -+ break; -+ case rfbUltraVncMsLogon: -+ if (!AuthUltraVncMsLogon()) { -+ return False; -+ } -+ break; -+ default: /* should never happen */ -+ sprintf(msgbuf, "Internal error: Invalid security type: %d\n", secType); -+ wmsg(msgbuf, 1); -+ return False; -+ } -+ -+ connect_time = dnow(); -+ -+ ci.shared = (appData.shareDesktop ? 1 : 0); -+ -+ if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) { -+ return False; -+ } -+ -+ if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg)) { -+ return False; -+ } -+ -+ si.framebufferWidth = Swap16IfLE(si.framebufferWidth); -+ si.framebufferHeight = Swap16IfLE(si.framebufferHeight); -+ si.format.redMax = Swap16IfLE(si.format.redMax); -+ si.format.greenMax = Swap16IfLE(si.format.greenMax); -+ si.format.blueMax = Swap16IfLE(si.format.blueMax); -+ si.nameLength = Swap32IfLE(si.nameLength); -+ -+ if (appData.chatOnly) { -+ si.framebufferWidth = 32; -+ si.framebufferHeight = 32; -+ } -+ -+ /* FIXME: Check arguments to malloc() calls. */ -+ desktopName = malloc(si.nameLength + 1); -+ memset(desktopName, 0, si.nameLength + 1); -+ if (!desktopName) { -+ fprintf(stderr, "Error allocating memory for desktop name, %lu bytes\n", -+ (unsigned long)si.nameLength); -+ return False; -+ } -+ -+ if (!ReadFromRFBServer(desktopName, si.nameLength)) { -+ return False; -+ } -+ -+ desktopName[si.nameLength] = 0; -+ -+ if (appData.appShare) { -+ int x_hint, y_hint; -+ char *p, *q = NULL; -+ p = desktopName; -+ while (*p != '\0') { -+ char *t = strstr(p, " XY="); -+ if (t) q = t; -+ p++; -+ } -+ if (q) { -+ int ok = 1; -+ p = q + strlen(" XY="); -+ while (*p != '\0') { -+ if (!strpbrk(p, "0123456789,+-")) { -+ ok = 0; -+ } -+ p++; -+ } -+ if (ok && sscanf(q+1, "XY=%d,%d", &x_hint, &y_hint) == 2) { -+ fprintf(stderr,"Using x11vnc appshare position: %s\n\n", q); -+ *q = '\0'; -+ appshare_x_hint = x_hint; -+ appshare_y_hint = y_hint; -+ } -+ } -+ } -+ -+ 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; -+ } -+ dt_out = dnow(); - -- 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) { -+ ; /* OK */ -+ } else if (secType == rfbSecTypeVncAuth) { -+ ; /* OK */ -+ } else if (secType == rfbUltraVncMsLogon) { -+ ; /* OK */ -+ } else { -+ sprintf(msgbuf, "Unknown security type from RFB server: %d\n", (int)secType); -+ wmsg(msgbuf, 1); -+ 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; -+ -+ if (secTypeNames) {} -+ -+ /* Read the list of security types. */ -+ if (!ReadFromRFBServer((char *)&nSecTypes, sizeof(nSecTypes))) { -+ return rfbSecTypeInvalid; -+ } -+ dt_out = dnow(); - -- 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; -+ } -+ -+ if (getenv("SSVNC_DEBUG_SEC_TYPES")) { -+ for (j = 0; j < (int)nSecTypes; j++) { -+ fprintf(stderr, "sec-type[%d] %d\n", j, (int) secTypes[j]); -+ } -+ } -+ -+ /* Find out if the server supports TightVNC protocol extensions */ -+ for (j = 0; j < (int)nSecTypes; j++) { -+ if (getenv("VNCVIEWER_NO_SEC_TYPE_TIGHT")) { -+ break; -+ } -+ if (getenv("SSVNC_NO_SEC_TYPE_TIGHT")) { -+ break; -+ } -+#ifdef TURBOVNC -+ break; -+#endif -+ if (secTypes[j] == rfbSecTypeTight) { -+ free(secTypes); -+ secType = rfbSecTypeTight; -+ if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) { -+ return rfbSecTypeInvalid; -+ } -+ fprintf(stderr, "Enabling TightVNC protocol extensions\n"); -+ return rfbSecTypeTight; -+ } -+ } -+ -+ /* Find first supported security type */ -+ for (j = 0; j < (int)nSecTypes; j++) { -+ for (i = 0; i < nKnownSecTypes; i++) { -+ if (secTypes[j] == knownSecTypes[i]) { -+ secType = secTypes[j]; -+ if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) { -+ free(secTypes); -+ return rfbSecTypeInvalid; -+ } -+ break; -+ } -+ } -+ if (secType != rfbSecTypeInvalid) { -+ break; -+ } -+ } - -- free(secTypes); -+ if (secType == rfbSecTypeInvalid) { -+ fprintf(stderr, "Server did not offer supported security type:\n"); -+ for (j = 0; j < (int)nSecTypes; j++) { -+ fprintf(stderr, " sectype[%d] %d\n", j, (int) secTypes[j]); -+ } -+ } - -- if (secType == rfbSecTypeInvalid) -- fprintf(stderr, "Server did not offer supported security type\n"); -+ free(secTypes); - -- return (int)secType; -+ return (int)secType; - } - - -@@ -451,6 +1141,9 @@ - return True; - } - -+static char *restart_session_pw = NULL; -+static int restart_session_len = 0; -+ - - /* - * Negotiate authentication scheme (protocol version 3.7t) -@@ -459,58 +1152,406 @@ - 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 VNC authentication needed\n\n"); -+ if (viewer_minor >= 8) { -+ CARD32 authResult; -+ -+ if (!ReadFromRFBServer((char *)&authResult, 4)) { -+ return False; -+ } -+ -+ authResult = Swap32IfLE(authResult); -+ -+ if (authResult == rfbVncAuthOK) { -+ fprintf(stderr, "VNC authentication succeeded (%d) for PerformAuthenticationTight rfbSecTypeNone (RFB 3.8)\n", (int) authResult); -+ } else { -+ sprintf(msgbuf, "VNC authentication failed (%d) for PerformAuthenticationTight rfbSecTypeNone (RFB 3.8)\n\n", (int) authResult); -+ wmsg(msgbuf, 1); -+ return False; -+ } -+ } -+ 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; -+ sprintf(msgbuf, "No suitable authentication schemes offered by server\n"); -+ wmsg(msgbuf, 1); -+ return False; -+} -+ -+#if 0 -+unsigned char encPasswd[8]; -+unsigned char encPasswd_MSLOGON[32]; -+char clearPasswd_MSLOGIN[256]; -+static Bool old_ultravnc_mslogon_code(void) { -+ char *passwd = NULL; -+ CARD8 challenge_mslogon[CHALLENGESIZE_MSLOGON]; -+ -+ /* code from the old uvnc way (1.0.2?) that would go into AuthenticateVNC() template */ -+ -+ if (appData.msLogon != NULL) { -+ raiseme(1); -+ if (!strcmp(appData.msLogon, "1")) { -+ char tmp[256]; -+ fprintf(stderr, "\nUltraVNC MS Logon Username[@Domain]: "); -+ if (fgets(tmp, 256, stdin) == NULL) { -+ exit(1); -+ } -+ appData.msLogon = strdup(tmp); -+ } -+ passwd = getpass("UltraVNC MS Logon Password: "); -+ if (! passwd) { -+ exit(1); -+ } -+ fprintf(stderr, "\n"); -+ -+ UvncEncryptPasswd_MSLOGON(encPasswd_MSLOGON, passwd); -+ } -+ if (appData.msLogon) { -+ if (!ReadFromRFBServer((char *)challenge_mslogon, CHALLENGESIZE_MSLOGON)) { -+ return False; -+ } -+ } -+ if (appData.msLogon) { -+ int i; -+ char tmp[256]; -+ char *q, *domain = "."; -+ for (i=0; i < 32; i++) { -+ challenge_mslogon[i] = encPasswd_MSLOGON[i] ^ challenge_mslogon[i]; -+ } -+ q = strchr(appData.msLogon, '@'); -+ if (q) { -+ *q = '\0'; -+ domain = strdup(q+1); -+ } -+ memset(tmp, 0, sizeof(tmp)); -+ strcat(tmp, appData.msLogon); -+ if (!WriteExact(rfbsock, tmp, 256)) { -+ return False; -+ } -+ memset(tmp, 0, sizeof(tmp)); -+ strcat(tmp, domain); -+ if (!WriteExact(rfbsock, tmp, 256)) { -+ return False; -+ } -+ memset(tmp, 0, sizeof(tmp)); -+ strcat(tmp, passwd); -+ if (!WriteExact(rfbsock, tmp, CHALLENGESIZE_MSLOGON)) { -+ return False; -+ } -+ } - } -+#endif - -+static void hexprint(char *label, char *data, int len) { -+ int i; -+ fprintf(stderr, "%s: ", label); -+ for (i=0; i < len; i++) { -+ unsigned char c = (unsigned char) data[i]; -+ fprintf(stderr, "%02x ", (int) c); -+ if ((i+1) % 20 == 0) { -+ fprintf(stderr, "\n%s: ", label); -+ } -+ } -+ fprintf(stderr, "\n"); -+} -+ -+#define DH_MAX_BITS 31 -+static unsigned long long max_dh = ((unsigned long long) 1) << DH_MAX_BITS; -+ -+static unsigned long long bytes_to_uint64(char *bytes) { -+ unsigned long long result = 0; -+ int i; -+ -+ for (i=0; i < 8; i++) { -+ result <<= 8; -+ result += (unsigned char) bytes[i]; -+ } -+ return result; -+} -+ -+static void uint64_to_bytes(unsigned long long n, char *bytes) { -+ int i; -+ -+ for (i=0; i < 8; i++) { -+ bytes[i] = (unsigned char) (n >> (8 * (7 - i))); -+ } -+} -+ -+static void try_invert(char *wireuser, char *wirepass, unsigned long long actual_key) { -+ if (wireuser || wirepass || actual_key) {} -+ return; -+} -+ -+ -+static unsigned long long XpowYmodN(unsigned long long x, unsigned long long y, unsigned long long N) { -+ unsigned long long result = 1; -+ unsigned long long oneShift63 = ((unsigned long long) 1) << 63; -+ int i; -+ -+ for (i = 0; i < 64; y <<= 1, i++) { -+ result = result * result % N; -+ if (y & oneShift63) { -+ result = result * x % N; -+ } -+ } -+ return result; -+} -+ -+/* -+ * UltraVNC MS-Logon authentication (for v1.0.5 and later.) -+ */ -+ -+/* -+ * NOTE: The UltraVNC MS-Logon username and password exchange is -+ * VERY insecure. It can be brute forced in ~2e+9 operations. -+ * It's not clear we should support it... It is only worth using -+ * in an environment where no one is sniffing the network, in which -+ * case all of this DH exchange secrecy is unnecessary... -+ */ -+ -+static Bool AuthUltraVncMsLogon(void) { -+ CARD32 authResult; -+ char gen[8], mod[8], pub[8], rsp[8]; -+ char user[256], passwd[64], *gpw; -+ unsigned char key[8]; -+ unsigned long long ugen, umod, ursp, upub, uprv, ukey; -+ double now = dnow(); -+ int db = 0; -+ -+ if (getenv("SSVNC_DEBUG_MSLOGON")) { -+ db = atoi(getenv("SSVNC_DEBUG_MSLOGON")); -+ } -+ -+ fprintf(stderr, "\nAuthUltraVncMsLogon()\n"); -+ -+ if (!ReadFromRFBServer(gen, sizeof(gen))) { -+ return False; -+ } -+ if (db) hexprint("gen", gen, sizeof(gen)); -+ -+ if (!ReadFromRFBServer(mod, sizeof(mod))) { -+ return False; -+ } -+ if (db) hexprint("mod", mod, sizeof(mod)); -+ -+ if (!ReadFromRFBServer(rsp, sizeof(rsp))) { -+ return False; -+ } -+ if (db) hexprint("rsp", rsp, sizeof(rsp)); -+ -+ ugen = bytes_to_uint64(gen); -+ umod = bytes_to_uint64(mod); -+ ursp = bytes_to_uint64(rsp); -+ -+ if (db) { -+ fprintf(stderr, "ugen: 0x%016llx %12llu\n", ugen, ugen); -+ fprintf(stderr, "umod: 0x%016llx %12llu\n", umod, umod); -+ fprintf(stderr, "ursp: 0x%016llx %12llu\n", ursp, ursp); -+ } -+ -+ if (ugen > max_dh) { -+ fprintf(stderr, "ugen: too big: 0x%016llx\n", ugen); -+ return False; -+ } -+ -+ if (umod > max_dh) { -+ fprintf(stderr, "umod: too big: 0x%016llx\n", umod); -+ return False; -+ } -+ -+ /* make a random long long: */ -+ uprv = 0xffffffff * (now - (unsigned int) now); -+ uprv = uprv << 32; -+ uprv |= (unsigned long long) urandom(); -+ uprv = uprv % max_dh; -+ -+ if (db) fprintf(stderr, "uprv: 0x%016llx %12llu\n", uprv, uprv); -+ -+ upub = XpowYmodN(ugen, uprv, umod); -+ -+ if (db) fprintf(stderr, "upub: 0x%016llx %12llu\n", upub, upub); -+ -+ uint64_to_bytes(upub, pub); -+ -+ if (db) hexprint("pub", pub, sizeof(pub)); -+ -+ if (!WriteExact(rfbsock, (char *)pub, sizeof(pub))) { -+ return False; -+ } -+ if (db) fprintf(stderr, "wrote pub.\n"); -+ -+ if (ursp > max_dh) { -+ fprintf(stderr, "ursp: too big: 0x%016llx\n", ursp); -+ return False; -+ } -+ -+ ukey = XpowYmodN(ursp, uprv, umod); -+ -+ if (db) fprintf(stderr, "ukey: 0x%016llx %12llu\n", ukey, ukey); -+ -+ if (1) { -+ char tmp[10000]; -+ tmp[0] = '\0'; -+ strcat(tmp, "\n"); -+ strcat(tmp, "WARNING: The UltraVNC Diffie-Hellman Key is weak (key < 2e+9, i.e. 31 bits)\n"); -+ strcat(tmp, "WARNING: and so an eavesdropper could recover your MS-Logon username and\n"); -+ strcat(tmp, "WARNING: password via brute force in a few seconds of CPU time. \n"); -+ strcat(tmp, "WARNING: If this connection is NOT being tunnelled through a separate SSL or\n"); -+ strcat(tmp, "WARNING: SSH encrypted tunnel, consider things carefully before proceeding...\n"); -+ strcat(tmp, "WARNING: Do not enter an important username+password when prompted below if\n"); -+ strcat(tmp, "WARNING: there is a risk of an eavesdropper sniffing this connection.\n"); -+ strcat(tmp, "WARNING: UltraVNC MSLogon encryption is VERY weak. You've been warned!\n"); -+ wmsg(tmp, 1); -+ } -+ -+ uint64_to_bytes(ukey, (char *) key); -+ -+ if (appData.msLogon == NULL || !strcmp(appData.msLogon, "1")) { -+ char tmp[256], *q, *s; -+ if (!use_tty()) { -+ fprintf(stderr, "\nEnter UltraVNC MS-Logon Username[@Domain] in the popup.\n"); -+ s = DoUserDialog(); -+ } else { -+ raiseme(1); -+ fprintf(stderr, "\nUltraVNC MS-Logon Username[@Domain]: "); -+ if (fgets(tmp, 256, stdin) == NULL) { -+ exit(1); -+ } -+ s = strdup(tmp); -+ } -+ q = strchr(s, '\n'); -+ if (q) *q = '\0'; -+ appData.msLogon = strdup(s); -+ } -+ -+ if (!use_tty()) { -+ gpw = DoPasswordDialog(); -+ } else { -+ raiseme(1); -+ gpw = getpass("UltraVNC MS-Logon Password: "); -+ } -+ if (! gpw) { -+ return False; -+ } -+ fprintf(stderr, "\n"); -+ -+ memset(user, 0, sizeof(user)); -+ strncpy(user, appData.msLogon, 255); -+ -+ memset(passwd, 0, sizeof(passwd)); -+ strncpy(passwd, gpw, 63); -+ -+ if (db > 1) { -+ fprintf(stderr, "user='%s'\n", user); -+ fprintf(stderr, "pass='%s'\n", passwd); -+ } -+ -+ UvncEncryptBytes2((unsigned char *) user, sizeof(user), key); -+ UvncEncryptBytes2((unsigned char *) passwd, sizeof(passwd), key); -+ -+ if (getenv("TRY_INVERT")) { -+ try_invert(user, passwd, ukey); -+ exit(0); -+ } -+ -+ if (db) { -+ hexprint("user", user, sizeof(user)); -+ hexprint("pass", passwd, sizeof(passwd)); -+ } -+ -+ if (!WriteExact(rfbsock, user, sizeof(user))) { -+ return False; -+ } -+ if (db) fprintf(stderr, "wrote user.\n"); -+ -+ if (!WriteExact(rfbsock, passwd, sizeof(passwd))) { -+ return False; -+ } -+ if (db) fprintf(stderr, "wrote passwd.\n"); -+ -+ if (!ReadFromRFBServer((char *) &authResult, 4)) { -+ return False; -+ } -+ authResult = Swap32IfLE(authResult); -+ -+ if (db) fprintf(stderr, "authResult: %d\n", (int) authResult); -+ -+ switch (authResult) { -+ case rfbVncAuthOK: -+ fprintf(stderr, "UVNC MS-Logon authentication succeeded.\n\n"); -+ break; -+ case rfbVncAuthFailed: -+ fprintf(stderr, "UVNC MS-Logon authentication failed.\n"); -+ if (viewer_minor >= 8) { -+ printFailureReason(); -+ } else { -+ sprintf(msgbuf, "UVNC MS-Logon authentication failed.\n"); -+ wmsg(msgbuf, 1); -+ } -+ fprintf(stderr, "\n"); -+ return False; -+ case rfbVncAuthTooMany: -+ sprintf(msgbuf, "UVNC MS-Logon authentication failed - too many tries.\n\n"); -+ wmsg(msgbuf, 1); -+ return False; -+ default: -+ sprintf(msgbuf, "Unknown UVNC MS-Logon authentication result: %d\n\n", -+ (int)authResult); -+ wmsg(msgbuf, 1); -+ return False; -+ } -+ -+ return True; -+} - - /* - * Standard VNC authentication. -@@ -519,80 +1560,119 @@ - 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"); -+ if (authScheme) {} - -- if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) -- return False; -+ fprintf(stderr, "\nPerforming standard VNC authentication\n"); - -- 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 (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) { -+ return False; -+ } -+ -+ 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) { -+ sprintf(msgbuf, "Cannot read valid password from file \"%s\"\n", appData.passwordFile); -+ wmsg(msgbuf, 1); -+ return False; -+ } -+ } else if (appData.autoPass) { -+ passwd = buffer; -+ raiseme(1); -+ 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 (getenv("VNCVIEWER_PASSWORD")) { -+ passwd = strdup(getenv("VNCVIEWER_PASSWORD")); -+ } else if (appData.passwordDialog || !use_tty()) { -+ passwd = DoPasswordDialog(); -+ } else { -+ raiseme(1); -+ 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 (getenv("VNCVIEWER_PASSWORD")) { -+ putenv("VNCVIEWER_PASSWORD=none"); -+ } - -- vncEncryptBytes(challenge, passwd); -+ 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) { -+ sprintf(msgbuf, "Reading password failed\n\n"); -+ wmsg(msgbuf, 1); -+ return False; -+ } -+ if (strlen(passwd) > 8) { -+ passwd[8] = '\0'; -+ } -+ } - -- /* Lose the password from memory */ -- memset(passwd, '\0', strlen(passwd)); -+ vncEncryptBytes(challenge, passwd); -+ - -- if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) -- return False; - -- if (!ReadFromRFBServer((char *)&authResult, 4)) -- return False; -+#if 0 -+ /* Lose the password from memory */ -+ memset(passwd, '\0', strlen(passwd)); -+#endif - -- authResult = Swap32IfLE(authResult); -+ if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) { -+ return False; -+ } - -- switch (authResult) { -- case rfbVncAuthOK: -- fprintf(stderr, "VNC authentication succeeded\n"); -- break; -- case rfbVncAuthFailed: -- fprintf(stderr, "VNC authentication failed\n"); -- return False; -- case rfbVncAuthTooMany: -- fprintf(stderr, "VNC authentication failed - too many tries\n"); -- return False; -- default: -- fprintf(stderr, "Unknown VNC authentication result: %d\n", -- (int)authResult); -- return False; -- } -+ if (!ReadFromRFBServer((char *)&authResult, 4)) { -+ return False; -+ } - -- return True; -+ authResult = Swap32IfLE(authResult); -+ -+ switch (authResult) { -+ case rfbVncAuthOK: -+ fprintf(stderr, "VNC authentication succeeded\n\n"); -+ break; -+ case rfbVncAuthFailed: -+ fprintf(stderr, "VNC authentication failed.\n"); -+ if (viewer_minor >= 8) { -+ printFailureReason(); -+ } else { -+ sprintf(msgbuf, "VNC authentication failed.\n"); -+ wmsg(msgbuf, 1); -+ } -+ fprintf(stderr, "\n"); -+ return False; -+ case rfbVncAuthTooMany: -+ sprintf(msgbuf, "VNC authentication failed - too many tries\n\n"); -+ wmsg(msgbuf, 1); -+ return False; -+ default: -+ sprintf(msgbuf, "Unknown VNC authentication result: %d\n\n", (int)authResult); -+ wmsg(msgbuf, 1); -+ return False; -+ } -+ -+ return True; - } - - /* -@@ -602,68 +1682,77 @@ - 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 || !use_tty()) { -+ passwd = DoPasswordDialog(); -+ } else { -+ raiseme(1); -+ 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)); -+#if 0 -+ /* Lose the password from memory */ -+ memset(passwd, '\0', strlen(passwd)); -+#endif - -- 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: -+ sprintf(msgbuf, "Authentication failed\n\n"); -+ wmsg(msgbuf, 1); -+ return False; -+ case rfbVncAuthTooMany: -+ sprintf(msgbuf, "Authentication failed - too many tries\n\n"); -+ wmsg(msgbuf, 1); -+ return False; -+ default: -+ sprintf(msgbuf, "Unknown authentication result: %d\n\n", -+ (int)authResult); -+ wmsg(msgbuf, 1); -+ return False; -+ } - -- return True; -+ return True; - } - - -@@ -675,19 +1764,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)); - } - - -@@ -697,22 +1787,70 @@ - * many records to read from the socket. - */ - --static Bool --ReadCapabilityList(CapsContainer *caps, int count) --{ -- rfbCapabilityInfo msginfo; -- int i; -+static Bool -+ReadCapabilityList(CapsContainer *caps, int count) -+{ -+ 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); -+ } -+ -+ return True; -+} -+ - -- for (i = 0; i < count; i++) { -- if (!ReadFromRFBServer((char *)&msginfo, sz_rfbCapabilityInfo)) -- return False; -- msginfo.code = Swap32IfLE(msginfo.code); -- CapsEnable(caps, &msginfo); -- } -+/* used to have !tunnelSpecified */ - -- return True; -+static int guess_compresslevel(void) { -+ int n; -+ if (latency > 200.0) { -+ n = 8; -+ } else if (latency > 100.0) { -+ n = 7; -+ } else if (latency > 60.0) { -+ n = 6; -+ } else if (latency > 15.0) { -+ n = 4; -+ } else if (latency > 8.0) { -+ n = 2; -+ } else if (latency > 0.0) { -+ n = 1; -+ } else { -+ /* no latency measurement */ -+ n = 3; -+ } -+ return n; - } - -+static int guess_qualitylevel(void) { -+ int n; -+ if (latency > 200.0) { -+ n = 4; -+ } else if (latency > 100.0) { -+ n = 5; -+ } else if (latency > 60.0) { -+ n = 6; -+ } else if (latency > 15.0) { -+ n = 7; -+ } else if (latency > 8.0) { -+ n = 8; -+ } else if (latency > 0.0) { -+ n = 9; -+ } else { -+ /* no latency measurement */ -+ n = 6; -+ } -+#ifdef TURBOVNC -+ n *= 10; -+#endif -+ return n; -+} - - /* - * SetFormatAndEncodings. -@@ -729,6 +1867,21 @@ - Bool requestCompressLevel = False; - Bool requestQualityLevel = False; - Bool requestLastRectEncoding = False; -+ Bool requestNewFBSizeEncoding = True; -+ Bool requestTextChatEncoding = True; -+ Bool requestSubsampLevel = False; -+ int dsm = 0; -+ int tQL, tQLmax = 9; -+ static int qlmsg = 0, clmsg = 0; -+#ifdef TURBOVNC -+ tQLmax = 100; -+#endif -+ -+ if (requestTextChatEncoding || requestSubsampLevel || tQL) {} -+ -+#if 0 -+ fprintf(stderr, "SetFormatAndEncodings: sent_FBU state: %2d\n", sent_FBU); -+#endif - - spf.type = rfbSetPixelFormat; - spf.format = myFormat; -@@ -736,15 +1889,32 @@ - 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; -+ if (strchr(encStr, ',')) { -+ char *p; -+ encStr = strdup(encStr); -+ p = encStr; -+ while (*p != '\0') { -+ if (*p == ',') { -+ *p = ' '; -+ } -+ p++; -+ } -+ } - do { - char *nextEncStr = strchr(encStr, ' '); - if (nextEncStr) { -@@ -754,50 +1924,102 @@ - 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) -- requestCompressLevel = True; -- if (appData.enableJPEG) -- requestQualityLevel = True; -+ if (appData.compressLevel >= 0 && appData.compressLevel <= 9) { -+ requestCompressLevel = True; -+ } -+ if (appData.enableJPEG) { -+ requestQualityLevel = True; -+ } -+#ifdef TURBOVNC -+ requestSubsampLevel = True; -+#endif - } 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) { -+ if (appData.compressLevel >= 0 && appData.compressLevel <= 9) { -+ requestCompressLevel = True; -+ } -+ } 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) { -+ int qlevel = appData.qualityLevel; -+ if (qlevel < 0 || qlevel > tQLmax) qlevel = guess_qualitylevel(); -+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE); -+ requestQualityLevel = True; -+ if (qlevel < 3) { -+ zywrle_level = 3; -+ } else if (qlevel < 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; - } while (encStr && se->nEncodings < MAX_ENCODINGS); - - if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) { -- encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + -- rfbEncodingCompressLevel0); -+ ; -+ } else if (se->nEncodings < MAX_ENCODINGS) { -+ appData.compressLevel = guess_compresslevel(); -+ if (clmsg++ == 0) fprintf(stderr, "guessed: -compresslevel %d\n", appData.compressLevel); - } -+ encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); - - if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) { -- if (appData.qualityLevel < 0 || appData.qualityLevel > 9) -- appData.qualityLevel = 5; -- encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + -- rfbEncodingQualityLevel0); -+ if (appData.qualityLevel < 0 || appData.qualityLevel > tQLmax) { -+ appData.qualityLevel = guess_qualitylevel(); -+ if (qlmsg++ == 0) fprintf(stderr, "guessed: -qualitylevel %d\n", appData.qualityLevel); -+ } -+ } else if (se->nEncodings < MAX_ENCODINGS) { -+ appData.qualityLevel = guess_qualitylevel(); -+ if (qlmsg++ == 0) fprintf(stderr, "guessed: -qualitylevel %d\n", appData.qualityLevel); -+ } -+#ifdef TURBOVNC -+ tQL = appData.qualityLevel / 10; -+ if (tQL < 0) tQL = 1; -+ if (tQL > 9) tQL = 9; -+ encs[se->nEncodings++] = Swap32IfLE(tQL + rfbEncodingQualityLevel0); -+ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbJpegQualityLevel1 - 1); -+ if (se->nEncodings < MAX_ENCODINGS && requestSubsampLevel) { -+ if (appData.subsampLevel < 0 || appData.subsampLevel > TVNC_SAMPOPT - 1) { -+ appData.subsampLevel = TVNC_1X; -+ } -+ encs[se->nEncodings++] = Swap32IfLE(appData.subsampLevel + rfbJpegSubsamp1X); - } -+#else -+ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbEncodingQualityLevel0); -+#endif - - 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 +2028,16 @@ - if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) { - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect); - } -- } -- else { -+ -+ if (se->nEncodings < MAX_ENCODINGS && requestNewFBSizeEncoding) { -+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize); -+ } -+ -+ } else { -+ /* DIFFERENT CASE */ -+ - if (SameMachine(rfbsock)) { -- if (!tunnelSpecified) { -+ if (!tunnelSpecified && appData.useRawLocal) { - fprintf(stderr,"Same machine: preferring raw encoding\n"); - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw); - } else { -@@ -818,44 +2046,84 @@ - } - - 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) { -- encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + -- rfbEncodingCompressLevel0); -- } else if (!tunnelSpecified) { -- /* If -tunnel option was provided, we assume that server machine is -- not in the local network so we use default compression level for -- tight encoding instead of fast compression. Thus we are -- requesting level 1 compression only if tunneling is not used. */ -- encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCompressLevel1); -- } -- -- if (appData.enableJPEG) { -- if (appData.qualityLevel < 0 || appData.qualityLevel > 9) -- appData.qualityLevel = 5; -- encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + -- rfbEncodingQualityLevel0); -+ if (!dsm && appData.compressLevel >= 0 && appData.compressLevel <= 9) { -+ encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); -+ } else { -+ /* -+ * OUT OF DATE: If -tunnel option was provided, we assume that server machine is -+ * not in the local network so we use default compression level for -+ * tight encoding instead of fast compression. Thus we are -+ * requesting level 1 compression only if tunneling is not used. -+ */ -+ appData.compressLevel = guess_compresslevel(); -+ if (clmsg++ == 0) fprintf(stderr, "guessed: -compresslevel %d\n", appData.compressLevel); -+ encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); -+ } -+ -+ if (!dsm && appData.enableJPEG) { -+ if (appData.qualityLevel < 0 || appData.qualityLevel > tQLmax) { -+ appData.qualityLevel = guess_qualitylevel(); -+ if (qlmsg++ == 0) fprintf(stderr, "guessed: -qualitylevel %d\n", appData.qualityLevel); -+ } -+ -+#ifdef TURBOVNC -+ requestSubsampLevel = True; -+ tQL = appData.qualityLevel / 10; -+ if (tQL < 0) tQL = 1; -+ if (tQL > 9) tQL = 9; -+ encs[se->nEncodings++] = Swap32IfLE(tQL + rfbEncodingQualityLevel0); -+ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbJpegQualityLevel1 - 1); -+ if (se->nEncodings < MAX_ENCODINGS && requestSubsampLevel) { -+ if (appData.subsampLevel < 0 || appData.subsampLevel > TVNC_SAMPOPT - 1) { -+ appData.subsampLevel = TVNC_1X; -+ } -+ encs[se->nEncodings++] = Swap32IfLE(appData.subsampLevel + rfbJpegSubsamp1X); -+ } -+#else -+ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbEncodingQualityLevel0); -+#endif -+ - } - - 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 +2136,86 @@ - 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); -+ -+ -+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 +2226,38 @@ - Bool - SendPointerEvent(int x, int y, int buttonMask) - { -- rfbPointerEventMsg pe; -+ rfbPointerEventMsg pe; -+ -+ if (appData.fileActive) { -+ if (!dyn || time(NULL) < last_filexfer + delay_filexfer) { -+#if 0 -+ fprintf(stderr, "skip SendPointerEvent: %d - %d\n", last_filexfer, time(NULL)); -+#endif -+ 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 (scale_factor_x > 0.0 && scale_factor_x != 1.0) { -+ x /= scale_factor_x; -+ } -+ if (scale_factor_y > 0.0 && scale_factor_y != 1.0) { -+ y /= scale_factor_y; -+ } -+ -+ 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 +2268,22 @@ - Bool - SendKeyEvent(CARD32 key, Bool down) - { -- rfbKeyEventMsg ke; -+ rfbKeyEventMsg ke; -+ -+ if (appData.fileActive) { -+ if (!dyn || time(NULL) < last_filexfer + delay_filexfer) { -+#if 0 -+ fprintf(stderr, "skip SendPointerEvent: %d - %d\n", last_filexfer, time(NULL)); -+#endif -+ 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 +2294,1025 @@ - Bool - SendClientCutText(char *str, int len) - { -- rfbClientCutTextMsg cct; -+ rfbClientCutTextMsg cct; -+ -+ 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; -+ } - -- if (serverCutText) -- free(serverCutText); -- serverCutText = NULL; -- -- cct.type = rfbClientCutText; -- cct.length = Swap32IfLE(len); -- return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) && -- WriteExact(rfbsock, str, len)); -+ cct.type = rfbClientCutText; -+ cct.length = Swap32IfLE((unsigned int) 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) -+{ -+ static int db = -1; -+ rfbTextChatMsg chat; - -- for (i = 0; i < msg.scme.nColours; i++) { -- if (!ReadFromRFBServer((char *)rgb, 6)) -- return False; -- xc.pixel = msg.scme.firstColour + i; -- xc.red = Swap16IfLE(rgb[0]); -- xc.green = Swap16IfLE(rgb[1]); -- xc.blue = Swap16IfLE(rgb[2]); -- xc.flags = DoRed|DoGreen|DoBlue; -- XStoreColor(dpy, cmap, &xc); -- } -+ if (db < 0) { -+ if (getenv("SSVNC_DEBUG_CHAT")) { -+ db = 1; -+ } else { -+ db = 0; -+ } -+ } -+ if (!appData.chatActive) { -+ SendTextChatOpen(); -+ appData.chatActive = True; -+ } - -- break; -- } -+ chat.type = rfbTextChat; -+ chat.pad1 = 0; -+ chat.pad2 = 0; -+ chat.length = (unsigned int) strlen(str); -+ if (db) fprintf(stderr, "SendTextChat: %d '%s'\n", (int) 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)); -+} - -- case rfbFramebufferUpdate: -- { -- rfbFramebufferUpdateRectHeader rect; -- int linesToRead; -- int bytesPerLine; -- int i; -- int usecs; -+extern void raiseme(int force); - -- if (!ReadFromRFBServer(((char *)&msg.fu) + 1, -- sz_rfbFramebufferUpdateMsg - 1)) -- return False; -+Bool -+SendTextChatOpen(void) -+{ -+ rfbTextChatMsg chat; - -- msg.fu.nRects = Swap16IfLE(msg.fu.nRects); -+ raiseme(0); -+ chat.type = rfbTextChat; -+ chat.pad1 = 0; -+ chat.pad2 = 0; -+ chat.length = Swap32IfLE(rfbTextChatOpen); -+ return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg); -+} - -- for (i = 0; i < msg.fu.nRects; i++) { -- if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) -- return False; -+Bool -+SendTextChatClose(void) -+{ -+ rfbTextChatMsg chat; -+ chat.type = rfbTextChat; -+ chat.pad1 = 0; -+ chat.pad2 = 0; -+ chat.length = Swap32IfLE(rfbTextChatClose); -+ appData.chatActive = False; -+ return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg); -+} - -- rect.encoding = Swap32IfLE(rect.encoding); -- if (rect.encoding == rfbEncodingLastRect) -- break; -+Bool -+SendTextChatFinished(void) -+{ -+ rfbTextChatMsg chat; -+ chat.type = rfbTextChat; -+ chat.pad1 = 0; -+ chat.pad2 = 0; -+ chat.length = Swap32IfLE(rfbTextChatFinished); -+ appData.chatActive = False; -+ 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. */ -+#define rfbRErrorCmd 0xFFFFFFFF -+ -+ static int db = -1; -+ static int guess_x11vnc = 0; -+ -+#if 0 -+ if (filexfer_sock < 0) { -+ return True; -+ } -+ /* instead, we read and discard the ft msg data. */ -+#endif -+ -+/*fprintf(stderr, "In HandleFileXfer\n"); */ - -- 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; -+ if (db < 0) { -+ if (getenv("DEBUG_HandleFileXfer")) { -+ db = 1; -+ } else { -+ db = 0; -+ } - } -- continue; -- } - -- if (rect.encoding == rfbEncodingPointerPos) { -- if (!HandleCursorPos(rect.r.x, rect.r.y)) { -- return False; -+ last_filexfer = time(NULL); -+ /*fprintf(stderr, "last_filexfer-1: %d\n", last_filexfer); */ -+ -+ /* load first byte to send to Java be the FT msg number: */ -+ hdr[0] = rfbFileTransfer; -+ -+ /* 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.r.x + rect.r.w > si.framebufferWidth) || -- (rect.r.y + rect.r.h > si.framebufferHeight)) -- { -- fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n", -- rect.r.w, rect.r.h, rect.r.x, rect.r.y); -- return False; -+ if (hdr[1] == rfbEndOfFile) { -+ goto read_no_more; -+ } else if (hdr[1] == rfbAbortFileTransfer) { -+ goto read_no_more; - } - -- if (rect.r.h * rect.r.w == 0) { -- fprintf(stderr,"Zero size rect - ignoring\n"); -- continue; -- } -+ if (hdr[1] == rfbDirPacket && hdr[3] == rfbADirectory) { -+ -+ } -+ -+ 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 (len >= 12 && hdr[1] == rfbDirPacket) { -+ /* try to guess if x11vnc or not... */ -+ if (db) { -+ int i; -+ fprintf(stderr, "HFX DIR PKT (attr, timeL, timeH):"); -+ for (i=0; i < 12; i++) { -+ fprintf(stderr, " %d", (unsigned char) fxfer[i]); -+ } -+ fprintf(stderr, "\n"); -+ } -+ if (hdr[2] == 1) { -+ int dattr = (unsigned char) fxfer[0]; -+ int timeL1 = (unsigned char) fxfer[4]; -+ int timeL2 = (unsigned char) fxfer[5]; -+ int timeL3 = (unsigned char) fxfer[6]; -+ int timeL4 = (unsigned char) fxfer[7]; -+ int timeH1 = (unsigned char) fxfer[8]; -+ int timeH2 = (unsigned char) fxfer[9]; -+ int timeH3 = (unsigned char) fxfer[10]; -+ int timeH4 = (unsigned char) fxfer[11]; -+ if (dattr != 0) { -+ if (timeH1 == 0 && timeH2 == 0 && timeH3 == 0 && timeH4 == 0) { -+ if ((timeL1 != 0 || timeL2 != 0) && timeL3 != 0 && timeL4 != 0) { -+ if (!guess_x11vnc) fprintf(stderr, "guessed x11vnc server\n"); -+ guess_x11vnc = 1; -+ } -+ } -+ } -+ } -+ } -+ 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); -+ } -+ } -+ -+ len = (hdr[4] << 24) | (hdr[5] << 16) | (hdr[6] << 8) | hdr[7]; -+ if (db) fprintf(stderr, "Got rfbFileTransfer: len2 %u\n", len); -+ -+#if 0 -+ if (hdr[1] == rfbFileHeader && len != rfbRErrorCmd) -+#else -+ /* the extra 4 bytes get send on rfbRErrorCmd as well. */ -+ if (hdr[1] == rfbFileHeader) { -+#endif -+ int is_err = 0; -+ if (len == rfbRErrorCmd) { -+ is_err = 1; -+ } -+ if (db) fprintf(stderr, "Got rfbFileTransfer: rfbFileHeader\n"); -+ if (is_err && guess_x11vnc) { -+ fprintf(stderr, "rfbRErrorCmd x11vnc skip read 4 bytes.\n"); -+ goto read_no_more; -+ } -+ 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 (is_err) { -+ fprintf(stderr, "rfbRErrorCmd skip write 4 bytes.\n"); -+ goto read_no_more; -+ } -+ 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; -+ msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); -+ msg.scme.nColours = Swap16IfLE(msg.scme.nColours); -+ -+ for (i = 0; i < msg.scme.nColours; i++) { -+ if (!ReadFromRFBServer((char *)rgb, 6)) { -+ return False; -+ } -+ xc.pixel = msg.scme.firstColour + i; -+ xc.red = Swap16IfLE(rgb[0]); -+ xc.green = Swap16IfLE(rgb[1]); -+ xc.blue = Swap16IfLE(rgb[2]); -+ if (appData.useGreyScale) { -+ int ave = (xc.red + xc.green + xc.blue)/3; -+ xc.red = ave; -+ xc.green = ave; -+ xc.blue = ave; -+ } -+ xc.flags = DoRed|DoGreen|DoBlue; -+ XStoreColor(dpy, cmap, &xc); - } -+ - break; -- } -+ } -+ -+ case rfbFramebufferUpdate: -+ { -+ rfbFramebufferUpdateRectHeader rect; -+ int linesToRead; -+ int bytesPerLine; -+ int i; -+ -+ int area_copyrect = 0; -+ int area_tight = 0; -+ int area_zrle = 0; -+ int area_raw = 0; -+ static int rdb = -1; -+ static int delay_sync = -1; -+ static int delay_sync_env = -1; -+ int try_delay_sync = 0; -+ int cnt_pseudo = 0; -+ int cnt_image = 0; -+ -+ int skip_incFBU = 0; -+ -+ 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; -+ } -+ } -+ if (delay_sync < 0) { -+ if (getenv("SSVNC_DELAY_SYNC")) { -+ delay_sync = atoi(getenv("SSVNC_DELAY_SYNC")); -+ delay_sync_env = delay_sync; -+ } else { -+ delay_sync = 0; -+ } -+ } -+ -+ sent_FBU = -1; - -- case rfbEncodingHextile: -- { -- switch (myFormat.bitsPerPixel) { -- case 8: -- if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) -- return False; -- break; -- case 16: -- if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) -- return False; -- break; -- case 32: -- if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) -- return False; -- break; -+ if (appData.pipelineUpdates) { -+ /* turbovnc speed idea */ -+ XEvent ev; -+ memset(&ev, 0, sizeof(ev)); -+ ev.xclient.type = ClientMessage; -+ ev.xclient.window = XtWindow(desktop); -+ ev.xclient.message_type = XA_INTEGER; -+ ev.xclient.format = 8; -+ strcpy(ev.xclient.data.b, "SendRFBUpdate"); -+ XSendEvent(dpy, XtWindow(desktop), False, 0, &ev); - } -- break; -- } - -- case rfbEncodingZlib: -- { -- switch (myFormat.bitsPerPixel) { -- case 8: -- if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) -- return False; -- break; -- case 16: -- if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) -- return False; -- break; -- case 32: -- if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) -- return False; -- break; -+ if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) { -+ return False; - } -- 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; -+ msg.fu.nRects = Swap16IfLE(msg.fu.nRects); -+ -+ if (rdb) fprintf(stderr, "Begin rect loop %d\n", msg.fu.nRects); -+ -+ if (delay_sync) { -+ try_delay_sync = 1; -+ } else { -+ if (delay_sync_env != -1 && delay_sync_env == 0) { -+ ; -+ } else if (appData.yCrop > 0) { -+ ; -+ } else if (scale_factor_x > 0.0 && scale_factor_x != 1.0) { -+ ; -+ } else if (scale_factor_y > 0.0 && scale_factor_y != 1.0) { -+ ; -+ } else { -+ static int msg = 0; -+ /* fullScreen? */ -+ /* useXserverBackingStore? */ -+ /* useX11Cursor & etc? */ -+ /* scrollbars? */ -+ if (!msg) { -+ fprintf(stderr, "enabling 'delay_sync' mode for faster local drawing,\ndisable via env SSVNC_DELAY_SYNC=0 if there are painting errors.\n"); -+ msg = 1; -+ } -+ try_delay_sync = 1; -+ } -+ } -+ if (try_delay_sync) { -+ skip_maybe_sync = 1; -+ } -+#define STOP_DELAY_SYNC \ -+ if (try_delay_sync) { \ -+ if (cnt_image && skip_maybe_sync) { \ -+ XSync(dpy, False); \ -+ } \ -+ try_delay_sync = 0; \ -+ skip_maybe_sync = 0; \ - } -- break; -- } - -- default: -- fprintf(stderr,"Unknown rect encoding %d\n", -- (int)rect.encoding); -- return False; -- } -+ 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 (rdb > 1) fprintf(stderr, "nRects: %d i=%d enc: %d %dx%d+%d+%d\n", msg.fu.nRects, i, (int) rect.encoding, rect.r.w, rect.r.h, rect.r.x, rect.r.y); -+ -+ if (rect.encoding == rfbEncodingXCursor || rect.encoding == rfbEncodingRichCursor) { -+ cnt_pseudo++; -+ STOP_DELAY_SYNC -+ -+ 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) { -+ cnt_pseudo++; -+ STOP_DELAY_SYNC -+ 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) { -+ cnt_pseudo++; -+ STOP_DELAY_SYNC -+ if (appData.chatOnly) { -+ continue; -+ } -+ 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); -+ cnt_image++; -+ -+ 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)) { -+ if (!appData.chatOnly) { -+ 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, (int) 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, (int) 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; -+ -+ STOP_DELAY_SYNC -+ XSync(dpy, False); -+ -+ if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) { -+ return False; -+ } -+ if (appData.chatOnly) { -+ break; -+ } -+ -+ 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.useXserverBackingStore) { -+ 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, 0); -+ 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<<myFormat.redShift)| -+ (myFormat.greenMax<<myFormat.greenShift)| -+ (myFormat.blueMax<<myFormat.blueShift); -+ static int ZRLE32 = -1; -+ -+ if (ZRLE32 < 0) { -+ /* for debugging or workaround e.g. BE display to LE */ -+ if (getenv("ZRLE32")) { -+ if (strstr(getenv("ZRLE32"), "24Up")) { -+ ZRLE32 = 3; -+ } else if (strstr(getenv("ZRLE32"), "24Down")) { -+ ZRLE32 = 2; -+ } else { -+ ZRLE32 = 1; -+ } -+ } else { -+ ZRLE32 = 0; -+ } -+ } -+ -+if (db) fprintf(stderr, "maxColor: 0x%x mfbigEnding: %d\n", maxColor, myFormat.bigEndian); -+ -+ if (ZRLE32 == 1) { -+if (db) fprintf(stderr, "HandleZRLE32\n"); -+ if (!HandleZRLE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { -+ return False; -+ } -+ } else if (ZRLE32 == 2) { -+if (db) fprintf(stderr, "HandleZRLE24Down\n"); -+ if (!HandleZRLE24Down(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { -+ return False; -+ } -+ } else if (ZRLE32 == 3) { -+if (db) fprintf(stderr, "HandleZRLE24Up\n"); -+ if (!HandleZRLE24Up(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { -+ return False; -+ } -+ } else if ((myFormat.bigEndian && (maxColor&0xff)==0) || (!myFormat.bigEndian && (maxColor&0xff000000)==0)) { -+if (db) fprintf(stderr, "HandleZRLE24\n"); -+ if (!HandleZRLE24(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { -+ return False; -+ } -+ } else if (!myFormat.bigEndian && (maxColor&0xff)==0) { -+if (db) fprintf(stderr, "HandleZRLE24Up\n"); -+ if (!HandleZRLE24Up(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { -+ return False; -+ } -+ } else if (myFormat.bigEndian && (maxColor&0xff000000)==0) { -+if (db) fprintf(stderr, "HandleZRLE24Down\n"); -+ if (!HandleZRLE24Down(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { -+ return False; -+ } -+ } else if (!HandleZRLE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { -+ return False; -+ } -+ break; -+ } -+ } -+ break; -+ } -+ -+ default: -+ fprintf(stderr,"Unknown rect encoding %d\n", (int)rect.encoding); -+ return False; -+ } - -- /* Now we may discard "soft cursor locks". */ -- SoftCursorUnlockScreen(); -- } -+ /* Now we may discard "soft cursor locks". */ -+ if (db) fprintf(stderr, "FBU-SUL1 %.6f\n", dnow()); -+ -+ SoftCursorUnlockScreen(); -+ -+ if (db) fprintf(stderr, "FBU-SUL2 %.6f\n", dnow()); -+ } -+ -+ if (try_delay_sync) { -+ skip_maybe_sync = 0; -+ } -+ -+ if (1 || area_copyrect) { -+ /* we always do this now for some reason... */ -+ if (db) fprintf(stderr, "FBU-XSN1 %.6f\n", dnow()); -+ XSync(dpy, False); -+ if (db) fprintf(stderr, "FBU-XSN2 %.6f\n", dnow()); -+ } -+ sent_FBU = 0; -+ /* -+ * we need to be careful since Xt events are processed -+ * usually in the middle of FBU. So we do any scheduled ones now -+ * which is pretty safe but not absolutely safe. -+ */ -+ if (do_format_change) { -+ cutover_format_change(); -+ do_format_change = 0; -+ SetVisualAndCmap(); -+ SetFormatAndEncodings(); -+ if (do_cursor_change) { -+ if (do_cursor_change == 1) { -+ DesktopCursorOff(); -+ } -+ do_cursor_change = 0; -+ } else { -+ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, -+ si.framebufferHeight, False); -+ skip_incFBU = 1; -+ } -+ } -+ if (do_fb_update != 0.0) { -+ if (dnow() > 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 +3320,168 @@ - 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 -+ { -+ /* we do it always now. */ -+ XSync(dpy, False); -+ } -+ -+ if (skip_XtUpdate || skip_incFBU) { -+ ; -+ } else if (appData.pipelineUpdates) { -+ ; -+ } 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 +3501,93 @@ - #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; -+ -+#ifdef TURBOVNC -+#include "turbovnc/turbojpeg.h" -+tjhandle tjhnd=NULL; -+static char *compressedData = NULL; -+static char *uncompressedData = NULL; -+#define CopyDataToImage CopyDataToScreen -+static void turbovnc_FillRectangle(XGCValues *gcv, int rx, int ry, int rw, int rh) { -+ if (!appData.useXserverBackingStore) { -+ FillScreen(rx, ry, rw, rh, gcv->foreground); -+ } else { -+ XChangeGC(dpy, gc, GCForeground, gcv); -+ XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); -+ } -+} -+static void CopyImageToScreen(int x, int y, int w, int h) { -+ put_image(x, y, x, y, w, h, 0); -+} -+#endif -+ - #define BPP 8 - #include "rre.c" - #include "corre.c" - #include "hextile.c" - #include "zlib.c" -+ -+#ifdef TURBOVNC -+#undef FillRectangle -+#define FillRectangle turbovnc_FillRectangle -+#include "turbovnc/tight.c" -+#undef FillRectangle -+#else - #include "tight.c" -+#endif -+ -+#include "zrle.c" - #undef BPP -+ - #define BPP 16 - #include "rre.c" - #include "corre.c" - #include "hextile.c" - #include "zlib.c" -+ -+#ifdef TURBOVNC -+#undef FillRectangle -+#define FillRectangle turbovnc_FillRectangle -+#include "turbovnc/tight.c" -+#undef FillRectangle -+#else - #include "tight.c" -+#endif -+ -+#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" -+ -+#ifdef TURBOVNC -+#undef FillRectangle -+#define FillRectangle turbovnc_FillRectangle -+#include "turbovnc/tight.c" -+#undef FillRectangle -+#else - #include "tight.c" -+#endif -+ -+#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 - - /* -@@ -1325,23 +3597,27 @@ - static void - ReadConnFailedReason(void) - { -- CARD32 reasonLen; -- char *reason = NULL; -+ CARD32 reasonLen; -+ char *reason = NULL; - -- if (ReadFromRFBServer((char *)&reasonLen, sizeof(reasonLen))) { -- reasonLen = Swap32IfLE(reasonLen); -- if ((reason = malloc(reasonLen)) != NULL && -- ReadFromRFBServer(reason, reasonLen)) { -- fprintf(stderr,"VNC connection failed: %.*s\n", (int)reasonLen, reason); -- free(reason); -- return; -- } -- } -+ if (ReadFromRFBServer((char *)&reasonLen, sizeof(reasonLen))) { -+ reasonLen = Swap32IfLE(reasonLen); -+ if ((reason = malloc(reasonLen)) != NULL && -+ ReadFromRFBServer(reason, reasonLen)) { -+ int len = (int) reasonLen < sizeof(msgbuf) - 10 ? (int) reasonLen : sizeof(msgbuf) - 10; -+ sprintf(msgbuf,"VNC connection failed: %.*s\n", len, reason); -+ wmsg(msgbuf, 1); -+ free(reason); -+ return; -+ } -+ } - -- fprintf(stderr, "VNC connection failed\n"); -+ sprintf(msgbuf, "VNC connection failed\n"); -+ wmsg(msgbuf, 1); - -- if (reason != NULL) -- free(reason); -+ if (reason != NULL) { -+ free(reason); -+ } - } - - /* -@@ -1358,9 +3634,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 +3738,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 2008-10-05 15:16:30.000000000 -0400 -@@ -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.useXserverBackingStore) { \ -+ 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/selection.c vnc_unixsrc/vncviewer/selection.c ---- vnc_unixsrc.orig/vncviewer/selection.c 2004-03-03 04:11:52.000000000 -0500 -+++ vnc_unixsrc/vncviewer/selection.c 2010-02-25 23:28:48.000000000 -0500 -@@ -43,13 +43,16 @@ - unsigned long* length, int* format); - static void LoseSelection(Widget w, Atom *selection); - --static Bool iAmSelectionOwner = False; -+static Bool PrimarySelectionOwner = False; -+static Bool ClipboardSelectionOwner = False; - static Time prevSelectionTime = 0L; - static Time cutBufferTime = 0L; - - #define TIME_LATER(a, b) ((a) != 0 && ((b) == 0 || (INT32)((a) - (b)) > 0)) - - -+static Atom clipboard_atom = None; -+ - /* - * InitialiseSelection() must be called after realizing widgets (because - * otherwise XtGetSelectionValue() fails). We register events on the root -@@ -62,22 +65,28 @@ - * available. - */ - --void --InitialiseSelection() --{ -+static int dbg_sel = -1; -+ -+void InitialiseSelection() { - #if XtSpecificationRelease >= 6 -- XtRegisterDrawable(dpy, DefaultRootWindow(dpy), toplevel); -+ XtRegisterDrawable(dpy, DefaultRootWindow(dpy), toplevel); - #else -- _XtRegisterWindow(DefaultRootWindow(dpy), toplevel); -+ _XtRegisterWindow(DefaultRootWindow(dpy), toplevel); - #endif -- XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask); -+ XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask); - -- XtAddRawEventHandler(toplevel, PropertyChangeMask, False, CutBufferChange, -- NULL); -+ XtAddRawEventHandler(toplevel, PropertyChangeMask, False, CutBufferChange, NULL); - -- XtGetSelectionValue(toplevel, XA_PRIMARY, -+ clipboard_atom = XInternAtom(dpy, "CLIPBOARD", False); -+ -+ XtGetSelectionValue(toplevel, XA_PRIMARY, - XInternAtom(dpy, "TIMESTAMP", False), - GetInitialSelectionTimeCallback, NULL, CurrentTime); -+ -+ if (dbg_sel < 0) { -+ dbg_sel = 0; -+ if (getenv("SSVNC_DEBUG_SELECTION")) dbg_sel = 1; -+ } - } - - -@@ -93,13 +102,16 @@ - Atom* selection, Atom* type, XtPointer value, - unsigned long* length, int* format) - { -- if (value && *format == 32 && *length == 1) -- prevSelectionTime = *(CARD32 *)value; -- else -- prevSelectionTime = 0L; -- -- if (value) -- XtFree(value); -+ if (value && *format == 32 && *length == 1) { -+ prevSelectionTime = *(CARD32 *)value; -+ } else { -+ prevSelectionTime = 0L; -+ } -+ -+ if (value) { -+ XtFree(value); -+ } -+ if (w || clientData || selection || type || value || length || format) {} - } - - -@@ -121,26 +133,30 @@ - void - SelectionToVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) - { -- Bool always = False; -+ Bool always = appData.sendAlways; -+ Atom sendsel = XA_PRIMARY; - -- if (*num_params != 0) { -- if (strcmp(params[0],"always") == 0) { -- always = True; -- } else if (strcmp(params[0],"new") == 0) { -- always = False; -- } else { -- fprintf(stderr,"Invalid params: SelectionToVNC(always|new)\n"); -- return; -- } -- } -- -- if (always) { -- XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, -- TimeFromEvent(event)); -- } else { -- XtGetSelectionValue(w, XA_PRIMARY, XInternAtom(dpy, "TIMESTAMP", False), -- GetSelectionTimeCallback, NULL, TimeFromEvent(event)); -- } -+ if (*num_params != 0) { -+ if (strcmp(params[0],"always") == 0) { -+ always = True; -+ } else if (strcmp(params[0],"new") == 0) { -+ always = False; -+ } else { -+ fprintf(stderr,"Invalid params: SelectionToVNC(always|new)\n"); -+ return; -+ } -+ } -+ if (appData.sendClipboard && clipboard_atom != None) { -+ sendsel = clipboard_atom; -+ } -+ if (dbg_sel) fprintf(stderr, "SelectionToVNC %s\n", sendsel == XA_PRIMARY ? "PRIMARY" : "CLIPBOARD"); -+ -+ if (always) { -+ XtGetSelectionValue(w, sendsel, XA_STRING, GetSelectionCallback, NULL, TimeFromEvent(event)); -+ } else { -+ XtGetSelectionValue(w, sendsel, XInternAtom(dpy, "TIMESTAMP", False), GetSelectionTimeCallback, NULL, TimeFromEvent(event)); -+ } -+ if (w || event || params || num_params) {} - } - - -@@ -158,10 +174,13 @@ - int len = *length; - char *str = (char *)value; - -- if (str) -- SendClientCutText(str, len); -- else -- SendCutBuffer(); -+ if (str) { -+ if (dbg_sel) fprintf(stderr, "SendClientCutText len: %d\n", len); -+ SendClientCutText(str, len); -+ } else if (!getenv("VNCVIEWER_NO_CUTBUFFER")) { -+ SendCutBuffer(); -+ } -+ if (w || clientData || selection || type || value || length || format) {} - } - - -@@ -180,26 +199,24 @@ - Atom* type, XtPointer value, unsigned long* length, - int* format) - { -- if (value && *format == 32 && *length == 1) { -+ if (value && *format == 32 && *length == 1) { -+ Time t = *(CARD32 *)value; - -- Time t = *(CARD32 *)value; -- -- if (TIME_LATER(t, prevSelectionTime)) { -- prevSelectionTime = t; -- XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, -- CurrentTime); -- } -- -- } else { -- -- if (TIME_LATER(cutBufferTime, prevSelectionTime)) { -- prevSelectionTime = cutBufferTime; -- SendCutBuffer(); -- } -- } -- -- if (value) -- XtFree(value); -+ if (TIME_LATER(t, prevSelectionTime)) { -+ prevSelectionTime = t; -+ XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, CurrentTime); -+ } -+ } else if (!getenv("VNCVIEWER_NO_CUTBUFFER")) { -+ if (TIME_LATER(cutBufferTime, prevSelectionTime)) { -+ prevSelectionTime = cutBufferTime; -+ SendCutBuffer(); -+ } -+ } -+ -+ if (value) { -+ XtFree(value); -+ } -+ if (w || clientData || selection || type || value || length || format) {} - } - - -@@ -209,16 +226,17 @@ - */ - - static void --SendCutBuffer() --{ -- char *str; -- int len; -+SendCutBuffer() { -+ char *str; -+ int len; - -- str = XFetchBytes(dpy, &len); -- if (!str) return; -+ if (dbg_sel) fprintf(stderr, "SendCutBuffer len: %d\n", len); - -- SendClientCutText(str, len); -- XFree(str); -+ str = XFetchBytes(dpy, &len); -+ if (!str) return; -+ -+ SendClientCutText(str, len); -+ XFree(str); - } - - -@@ -230,10 +248,12 @@ - static void - CutBufferChange(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont) - { -- if (ev->type != PropertyNotify || ev->xproperty.atom != XA_CUT_BUFFER0) -- return; -+ if (ev->type != PropertyNotify || ev->xproperty.atom != XA_CUT_BUFFER0) { -+ return; -+ } - -- cutBufferTime = ev->xproperty.time; -+ cutBufferTime = ev->xproperty.time; -+ if (w || ptr || cont) {} - } - - -@@ -249,36 +269,69 @@ - void - SelectionFromVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) - { -- Bool always = False; -- Time t = TimeFromEvent(event); -- -- if (*num_params != 0) { -- if (strcmp(params[0],"always") == 0) { -- always = True; -- } else if (strcmp(params[0],"new") == 0) { -- always = False; -- } else { -- fprintf(stderr,"Invalid params: SelectionFromVNC(always|new)\n"); -- return; -- } -- } -- -- if (t == CurrentTime) { -- fprintf(stderr,"Error in translations: SelectionFromVNC() must act on " -- "event with time field\n"); -- return; -- } -- -- if (!serverCutText || (!always && !newServerCutText)) -- return; -- -- newServerCutText = False; -- -- XStoreBytes(dpy, serverCutText, strlen(serverCutText)); -- if (XtOwnSelection(desktop, XA_PRIMARY, t, ConvertSelection, LoseSelection, -- NULL)) { -- iAmSelectionOwner = True; -- } -+ Bool always = False; -+ Time t = TimeFromEvent(event); -+ int hold_primary = 0; -+ int hold_clipboard = 0; -+ -+ if (dbg_sel) fprintf(stderr, "SelectionFromVNC\n"); -+ -+ if (*num_params != 0) { -+ if (strcmp(params[0],"always") == 0) { -+ always = True; -+ } else if (strcmp(params[0],"new") == 0) { -+ always = False; -+ } else { -+ fprintf(stderr,"Invalid params: SelectionFromVNC(always|new)\n"); -+ return; -+ } -+ } -+ -+ if (t == CurrentTime) { -+ fprintf(stderr,"Error in translations: SelectionFromVNC() must act on " -+ "event with time field\n"); -+ return; -+ } -+ -+ if (!serverCutText || (!always && !newServerCutText)) { -+ return; -+ } -+ -+ newServerCutText = False; -+ -+ if (appData.appShare) { -+ if (strstr(serverCutText, "X11VNC_APPSHARE_CMD:") == serverCutText) { -+ /* do something with it? */ -+ return; -+ } -+ } -+ -+ XStoreBytes(dpy, serverCutText, strlen(serverCutText)); -+ -+ if (appData.recvText == NULL) { -+ appData.recvText = strdup("both"); -+ } -+ if (!strcasecmp(appData.recvText, "primary")) { -+ hold_primary = 1; -+ } else if (!strcasecmp(appData.recvText, "clipboard")) { -+ hold_clipboard = 1; -+ } else { -+ hold_primary = hold_clipboard = 1; -+ } -+ -+ if (!hold_primary) { -+ ; -+ } else if (XtOwnSelection(desktop, XA_PRIMARY, t, ConvertSelection, LoseSelection, NULL)) { -+ PrimarySelectionOwner = True; -+ if (dbg_sel) fprintf(stderr, "Own PRIMARY\n"); -+ } -+ if (!hold_clipboard || clipboard_atom == None) { -+ ; -+ } else if (XtOwnSelection(desktop, clipboard_atom, t, ConvertSelection, LoseSelection, NULL)) { -+ ClipboardSelectionOwner = True; -+ if (dbg_sel) fprintf(stderr, "Own CLIPBOARD\n"); -+ } -+ if (w || event || params || num_params) {} - } - - -@@ -293,37 +346,36 @@ - XtPointer* value, unsigned long* length, int* format) - { - -- if (*target == XA_STRING && serverCutText != NULL) { -- *type = XA_STRING; -- *length = strlen(serverCutText); -- *value = (XtPointer)XtMalloc(*length); -- memcpy((char*)*value, serverCutText, *length); -- *format = 8; -- return True; -- } -+ if (*target == XA_STRING && serverCutText != NULL) { -+ *type = XA_STRING; -+ *length = strlen(serverCutText); -+ *value = (XtPointer)XtMalloc(*length); -+ memcpy((char*)*value, serverCutText, *length); -+ *format = 8; -+ return True; -+ } - -- if (XmuConvertStandardSelection(w, CurrentTime, selection, target, type, -+ if (XmuConvertStandardSelection(w, CurrentTime, selection, target, type, - (XPointer*)value, length, format)) { -- if (*target == XInternAtom(dpy, "TARGETS", False)) { -- /* add STRING to list of standard targets */ -- Atom* targetP; -- Atom* std_targets = (Atom*)*value; -- unsigned long std_length = *length; -- -- *length = std_length + 1; -- *value = (XtPointer)XtMalloc(sizeof(Atom)*(*length)); -- targetP = *(Atom**)value; -- *targetP++ = XA_STRING; -- memmove((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); -- XtFree((char*)std_targets); -- *type = XA_ATOM; -- *format = 32; -- return True; -- } -- -- return True; -- } -- return False; -+ if (*target == XInternAtom(dpy, "TARGETS", False)) { -+ /* add STRING to list of standard targets */ -+ Atom* targetP; -+ Atom* std_targets = (Atom*)*value; -+ unsigned long std_length = *length; -+ -+ *length = std_length + 1; -+ *value = (XtPointer)XtMalloc(sizeof(Atom)*(*length)); -+ targetP = *(Atom**)value; -+ *targetP++ = XA_STRING; -+ memmove((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); -+ XtFree((char*)std_targets); -+ *type = XA_ATOM; -+ *format = 32; -+ return True; -+ } -+ return True; -+ } -+ return False; - } - - -@@ -332,7 +384,13 @@ - */ - - static void --LoseSelection(Widget w, Atom *selection) --{ -- iAmSelectionOwner = False; -+LoseSelection(Widget w, Atom *selection) { -+ if (*selection == XA_PRIMARY) { -+ if (dbg_sel) fprintf(stderr, "lost PRIMARY\n"); -+ PrimarySelectionOwner = False; -+ } else if (clipboard_atom != None && *selection == clipboard_atom) { -+ if (dbg_sel) fprintf(stderr, "lost CLIPBOARD\n"); -+ ClipboardSelectionOwner = False; -+ } -+ if (w) {} - } -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 2010-02-25 23:40:58.000000000 -0500 -@@ -30,71 +30,113 @@ - static Bool caughtShmError = False; - static Bool needShmCleanup = False; - --void --ShmCleanup() --{ -- fprintf(stderr,"ShmCleanup called\n"); -- if (needShmCleanup) { -- shmdt(shminfo.shmaddr); -- shmctl(shminfo.shmid, IPC_RMID, 0); -- needShmCleanup = False; -- } -+static int ShmCreationXErrorHandler(Display *dpy, XErrorEvent *error) { -+ caughtShmError = True; -+ if (dpy || error) {} -+ return 0; - } - --static int --ShmCreationXErrorHandler(Display *dpy, XErrorEvent *error) --{ -- caughtShmError = True; -- return 0; -+void ShmDetach() { -+ if (needShmCleanup) { -+ XErrorHandler oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler); -+ fprintf(stderr,"ShmDetach called.\n"); -+ XShmDetach(dpy, &shminfo); -+ XSync(dpy, False); -+ XSetErrorHandler(oldXErrorHandler); -+ } - } - --XImage * --CreateShmImage() --{ -- 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); -+void ShmCleanup() { -+ if (needShmCleanup) { -+ fprintf(stderr,"ShmCleanup called.\n"); -+ XSync(dpy, False); -+ shmdt(shminfo.shmaddr); -+ shmctl(shminfo.shmid, IPC_RMID, 0); - -- 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; -- } -+ needShmCleanup = False; -+ } -+} - -- shminfo.readOnly = True; -+Bool UsingShm() { -+ return needShmCleanup; -+} - -- oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler); -- XShmAttach(dpy, &shminfo); -- XSync(dpy, False); -- XSetErrorHandler(oldXErrorHandler); -+int scale_round(int len, double fac); -+extern int scale_x, scale_y; -+extern double scale_factor_x, scale_factor_y; - -- if (caughtShmError) { -- XDestroyImage(image); -- shmdt(shminfo.shmaddr); -- shmctl(shminfo.shmid, IPC_RMID, 0); -- return NULL; -- } -+XImage * -+CreateShmImage(int do_ycrop) -+{ -+ XImage *image; -+ XErrorHandler oldXErrorHandler; -+ int ymax = si.framebufferHeight; -+ int xmax = si.framebufferWidth; -+ -+ if (!XShmQueryExtension(dpy)) { -+ return NULL; -+ } -+ if (!appData.useShm) { -+ return NULL; -+ } -+ if (do_ycrop == -1) { -+ /* kludge to test for shm prescence */ -+ return (XImage *) 0x1; -+ } -+ -+ if (do_ycrop) { -+ ymax = appData.yCrop; -+ } -+ -+ if (scale_x > 0) { -+ xmax = scale_round(xmax, scale_factor_x); -+ ymax = scale_round(ymax, scale_factor_y); -+ } -+ -+ image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo, xmax, 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); -+ if (0) fprintf(stderr, "CreateShmImage: destroyed 'image' (1)\n"); -+ return NULL; -+ } -+ -+ shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0); -+ -+ if (shminfo.shmaddr == (char *)-1) { -+ XDestroyImage(image); -+#if 0 -+ fprintf(stderr, "CreateShmImage: destroyed 'image' (2)\n"); -+#endif -+ 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); -+#if 0 -+ fprintf(stderr, "CreateShmImage: destroyed 'image' (3)\n"); -+#endif -+ 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, Size %dx%d)\n", do_ycrop, xmax, ymax); - -- 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 2010-04-18 11:41:07.000000000 -0400 -@@ -22,17 +22,31 @@ - */ - - #include <unistd.h> -+#include <time.h> - #include <sys/socket.h> - #include <errno.h> - #include <netinet/in.h> - #include <netinet/tcp.h> - #include <arpa/inet.h> -+#include <sys/un.h> - #include <netdb.h> - #include <fcntl.h> - #include <assert.h> - #include <vncviewer.h> - -+#ifndef SOL_IPV6 -+#ifdef IPPROTO_IPV6 -+#define SOL_IPV6 IPPROTO_IPV6 -+#endif -+#endif -+ -+/* Solaris (sysv?) needs INADDR_NONE */ -+#ifndef INADDR_NONE -+#define INADDR_NONE ((in_addr_t) 0xffffffff) -+#endif -+ - void PrintInHex(char *buf, int len); -+extern void printChat(char *, Bool); - - Bool errorMessageOnReadFailure = True; - -@@ -56,31 +70,396 @@ - */ - - 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; -+#if 0 -+ XtRemoveInput(*id); -+#endif -+ XtRemoveInput(rfbsockId); -+ if (do_xfrsockId) { -+ XtRemoveInput(xfrsockId); -+ } -+ if (clientData || fd || id) {} - } - - static void --ProcessXtEvents() -+xfrsockReadyCallback(XtPointer clientData, int *fd, XtInputId *id) - { -- rfbsockReady = False; -- XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask, -- rfbsockReadyCallback, NULL); -- while (!rfbsockReady) { -- XtAppProcessEvent(appContext, XtIMAll); -- } -+ xfrsockReady = True; -+ XtRemoveInput(xfrsockId); -+ if (do_rfbsockId) { -+ XtRemoveInput(rfbsockId); -+ } -+ if (clientData || fd || id) {} -+} -+ -+ -+extern int skip_XtUpdate; -+extern int skip_XtUpdateAll; -+extern int filexfer_sock, filexfer_listen; -+extern time_t start_listen; -+extern void CheckTextInput(void); -+extern time_t last_filexfer; -+ -+static char fxfer[65536]; -+int fxfer_size = 65536; -+ -+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; -+ } -+if (0) 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 (hdr || len || i) {} -+#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); -+#if 0 -+ fprintf(stderr, "last_filexfer-2a: %d\n", last_filexfer); -+#endif -+ 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); -+#if 0 -+ fprintf(stderr, "last_filexfer-2b: %d\n", last_filexfer); -+#endif -+ -+ 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; -+#if 0 -+ fprintf(stderr, "grace: %d\n", grace); -+ /* forgot that this is about... */ -+#endif -+ usleep(10 * 1000); -+ continue; -+ } -+ } -+ break; -+ } -+ } -+ if (igot) { -+ last_filexfer = time(NULL); -+#if 0 -+ fprintf(stderr, "last_filexfer-2c: %d\n", last_filexfer); -+#endif -+ } -+#if 0 -+fprintf(stderr, "Out CheckFileXfer\n"); -+#endif -+ return; -+} -+ -+static void check_term_chat(void) { -+ fd_set fds; -+ struct timeval tv; -+ int i, igot = -1, n = fileno(stdin); -+ char strs[100][512]; -+ char buf[rfbTextMaxSize]; -+ -+ for (i=0; i < 100; i++) { -+ FD_ZERO(&fds); -+ FD_SET(n,&fds); -+ tv.tv_sec = 0; -+ tv.tv_usec = 0; -+ if (select(n+1, &fds, NULL, NULL, &tv) > 0) { -+ if (FD_ISSET(n, &fds)) { -+ fgets(strs[i], 512, stdin); -+ igot = i; -+ } else { -+ break; -+ } -+ } else { -+ break; -+ } -+ } -+ buf[0] = '\0'; -+ for (i=0; i <= igot; i++) { -+ if (strlen(buf) + strlen(strs[i]) < rfbTextMaxSize) { -+ strcat(buf, strs[i]); -+ } else { -+ SendTextChat(buf); -+ buf[0] = '0'; -+ } -+ } -+ if (buf[0] != '\0') { -+ SendTextChat(buf); -+ } -+ if (igot >= 0) printChat("Send: ", False); -+} -+ -+static time_t time_mark; -+extern int delay_filexfer; -+#include <sys/stat.h> -+ -+extern double start_time; -+ -+void ProcessXtEvents() -+{ -+ int db = 0; -+ static int dyn = -1; -+ static int chat_was_active = 0; -+ int check_chat = 0; -+ -+ 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 0 -+ if (0) fprintf(stderr, "ProcessXtEvents: %d %.4f\n", skip_XtUpdateAll, dnow() - start_time); -+#endif -+ -+ if (skip_XtUpdateAll) { -+ return; -+ } -+ -+ /* text chat */ -+ if (appData.chatActive ) { -+ check_chat = 1; -+ } else if (chat_was_active) { -+ static double last_check = 0.0; -+ double now = dnow(); -+ if (now > last_check + 0.75) { -+ check_chat = 1; -+ last_check = now; -+ } -+ } -+ if (check_chat) { -+ if (appData.chatActive) { -+ chat_was_active = 1; -+ } -+ if (!appData.termChat) { -+ CheckTextInput(); -+ } else { -+ check_term_chat(); -+ } -+ } -+ -+ 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 - ReadFromRFBServer(char *out, unsigned int n) - { -+#if 0 -+ double start = dnow(), dn = n; -+#endif - if (n <= buffered) { - memcpy(out, bufoutptr, n); - bufoutptr += n; - buffered -= n; -+#if 0 -+fprintf(stderr, "R0: %06d\n", (int) dn); -+#endif - return True; - } - -@@ -119,6 +498,9 @@ - memcpy(out, bufoutptr, n); - bufoutptr += n; - buffered -= n; -+#if 0 -+fprintf(stderr, "R1: %06d %06d %10.2f KB/sec\n", (int) dn, buffered+n, 1e-3 * (buffered+n)/(dnow() - start)); -+#endif - return True; - - } else { -@@ -146,11 +528,16 @@ - n -= i; - } - -+#if 0 -+fprintf(stderr, "R2: %06d %06d %10.2f KB/sec\n", (int) dn, (int) dn, 1e-3 * (dn)/(dnow() - start)); -+#endif - return True; - } - } - - -+int currentMsg = -1; -+ - /* - * Write an exact number of bytes, and don't return until you've sent them. - */ -@@ -158,81 +545,321 @@ - 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; -+} -+ -+char *ipv6_getipaddr(struct sockaddr *paddr, int addrlen) { -+#if defined(AF_INET6) && defined(NI_NUMERICHOST) -+ char name[200]; -+ if (appData.noipv6) { -+ return strdup("unknown"); -+ } -+ if (getnameinfo(paddr, addrlen, name, sizeof(name), NULL, 0, NI_NUMERICHOST) == 0) { -+ return strdup(name); -+ } -+#endif -+ if (paddr || addrlen) {} -+ return strdup("unknown"); -+} -+ -+char *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen) { -+#if defined(AF_INET6) -+ char name[200]; -+ if (appData.noipv6) { -+ return strdup("unknown"); -+ } -+ if (getnameinfo(paddr, addrlen, name, sizeof(name), NULL, 0, 0) == 0) { -+ return strdup(name); -+ } -+#endif -+ if (paddr || addrlen) {} -+ return strdup("unknown"); -+} -+ -+int dotted_ip(char *host, int partial) { -+ int len, dots = 0; -+ char *p = host; -+ -+ if (!host) { -+ return 0; -+ } -+ -+ if (!isdigit((unsigned char) host[0])) { -+ return 0; -+ } -+ -+ len = strlen(host); -+ if (!partial && !isdigit((unsigned char) host[len-1])) { -+ return 0; -+ } -+ -+ while (*p != '\0') { -+ if (*p == '.') dots++; -+ if (*p == '.' || isdigit((unsigned char) (*p))) { -+ p++; -+ continue; -+ } -+ return 0; -+ } -+ if (!partial && dots != 3) { -+ return 0; -+ } -+ return 1; -+} - - /* - * ConnectToTcpAddr connects to the given TCP port. - */ - --int --ConnectToTcpAddr(unsigned int host, int port) --{ -- int sock; -- struct sockaddr_in addr; -- int one = 1; -- -- addr.sin_family = AF_INET; -- addr.sin_port = htons(port); -- addr.sin_addr.s_addr = host; -+int ConnectToTcpAddr(const char *hostname, int port) { -+ int sock = -1, one = 1; -+ unsigned int host; -+ struct sockaddr_in addr; -+ -+ if (appData.noipv4) { -+ fprintf(stderr, "ipv4 is disabled via VNCVIEWER_NO_IPV4/-noipv4.\n"); -+ goto try6; -+ } - -- sock = socket(AF_INET, SOCK_STREAM, 0); -- if (sock < 0) { -- fprintf(stderr,programName); -- perror(": ConnectToTcpAddr: socket"); -- return -1; -- } -+ if (!StringToIPAddr(hostname, &host)) { -+ fprintf(stderr, "Could not convert '%s' to ipv4 host address.\n", hostname); -+ goto try6; -+ } - -- if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { -- fprintf(stderr,programName); -- perror(": ConnectToTcpAddr: connect"); -- close(sock); -- return -1; -- } -+ memset(&addr, 0, sizeof(struct sockaddr_in)); - -- if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, -- (char *)&one, sizeof(one)) < 0) { -- fprintf(stderr,programName); -- perror(": ConnectToTcpAddr: setsockopt"); -- close(sock); -- return -1; -- } -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ addr.sin_addr.s_addr = host; -+ -+ sock = socket(AF_INET, SOCK_STREAM, 0); -+ if (sock < 0) { -+ perror("ConnectToTcpAddr[ipv4]: socket"); -+ sock = -1; -+ goto try6; -+ } -+ -+ if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { -+ perror("ConnectToTcpAddr[ipv4]: connect"); -+ close(sock); -+ sock = -1; -+ goto try6; -+ } -+ -+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { -+ perror("ConnectToTcpAddr[ipv4]: setsockopt"); -+ close(sock); -+ sock = -1; -+ goto try6; -+ } - -- return sock; -+ if (sock >= 0) { -+ return sock; -+ } -+ -+ try6: -+ -+#ifdef AF_INET6 -+ if (!appData.noipv6) { -+ int err; -+ struct addrinfo *ai; -+ struct addrinfo hints; -+ char service[32], *host2, *q; -+ -+ fprintf(stderr, "Trying ipv6 connection to '%s'\n", hostname); -+ -+ memset(&hints, 0, sizeof(hints)); -+ sprintf(service, "%d", port); -+ -+ hints.ai_family = AF_UNSPEC; -+ hints.ai_socktype = SOCK_STREAM; -+#ifdef AI_ADDRCONFIG -+ hints.ai_flags |= AI_ADDRCONFIG; -+#endif -+#ifdef AI_NUMERICSERV -+ hints.ai_flags |= AI_NUMERICSERV; -+#endif -+ if (!strcmp(hostname, "localhost")) { -+ host2 = strdup("::1"); -+ } else if (!strcmp(hostname, "127.0.0.1")) { -+ host2 = strdup("::1"); -+ } else if (hostname[0] == '[') { -+ host2 = strdup(hostname+1); -+ } else { -+ host2 = strdup(hostname); -+ } -+ q = strrchr(host2, ']'); -+ if (q) { -+ *q = '\0'; -+ } -+ -+ err = getaddrinfo(host2, service, &hints, &ai); -+ if (err != 0) { -+ fprintf(stderr, "ConnectToTcpAddr[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err)); -+ usleep(100 * 1000); -+ err = getaddrinfo(host2, service, &hints, &ai); -+ } -+ free(host2); -+ -+ if (err != 0) { -+ fprintf(stderr, "ConnectToTcpAddr[ipv6]: getaddrinfo[%d]: %s (2nd try)\n", err, gai_strerror(err)); -+ } else { -+ struct addrinfo *ap = ai; -+ while (ap != NULL) { -+ int fd = -1; -+ char *s = ipv6_getipaddr(ap->ai_addr, ap->ai_addrlen); -+ if (s) { -+ fprintf(stderr, "ConnectToTcpAddr[ipv6]: trying ip-addr: '%s'\n", s); -+ free(s); -+ } -+ if (appData.noipv4) { -+ struct sockaddr_in6 *s6ptr; -+ if (ap->ai_family != AF_INET6) { -+ fprintf(stderr, "ConnectToTcpAddr[ipv6]: skipping AF_INET address under VNCVIEWER_NO_IPV4/-noipv4\n"); -+ ap = ap->ai_next; -+ continue; -+ } -+#ifdef IN6_IS_ADDR_V4MAPPED -+ s6ptr = (struct sockaddr_in6 *) ap->ai_addr; -+ if (IN6_IS_ADDR_V4MAPPED(&(s6ptr->sin6_addr))) { -+ fprintf(stderr, "ConnectToTcpAddr[ipv6]: skipping V4MAPPED address under VNCVIEWER_NO_IPV4/-noipv4\n"); -+ ap = ap->ai_next; -+ continue; -+ } -+#endif -+ } -+ -+ fd = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol); -+ if (fd == -1) { -+ perror("ConnectToTcpAddr[ipv6]: socket"); -+ } else { -+ int dmsg = 0; -+ int res = connect(fd, ap->ai_addr, ap->ai_addrlen); -+#if defined(SOL_IPV6) && defined(IPV6_V6ONLY) -+ if (res != 0) { -+ int zero = 0; -+ perror("ConnectToTcpAddr[ipv6]: connect"); -+ dmsg = 1; -+ if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (char *)&zero, sizeof(zero)) == 0) { -+ fprintf(stderr, "ConnectToTcpAddr[ipv6]: trying again with IPV6_V6ONLY=0\n"); -+ res = connect(fd, ap->ai_addr, ap->ai_addrlen); -+ dmsg = 0; -+ } -+ } -+#endif -+ if (res == 0) { -+ fprintf(stderr, "ConnectToTcpAddr[ipv6]: connect OK\n"); -+ sock = fd; -+ break; -+ } else { -+ if (!dmsg) perror("ConnectToTcpAddr[ipv6]: connect"); -+ close(fd); -+ } -+ } -+ ap = ap->ai_next; -+ } -+ freeaddrinfo(ai); -+ } -+ if (sock >= 0 && setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { -+ perror("ConnectToTcpAddr: setsockopt"); -+ close(sock); -+ sock = -1; -+ } -+ } -+#endif -+ return sock; - } - -+Bool SocketPair(int fd[2]) { -+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, 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 -@@ -242,29 +869,31 @@ - int - FindFreeTcpPort(void) - { -- int sock, port; -- struct sockaddr_in addr; -+ int sock, port; -+ struct sockaddr_in addr; - -- addr.sin_family = AF_INET; -- addr.sin_addr.s_addr = INADDR_ANY; -+ memset(&addr, 0, sizeof(struct sockaddr_in)); - -- sock = socket(AF_INET, SOCK_STREAM, 0); -- if (sock < 0) { -- fprintf(stderr,programName); -- perror(": FindFreeTcpPort: socket"); -- return 0; -- } -+ addr.sin_family = AF_INET; -+ addr.sin_addr.s_addr = INADDR_ANY; - -- for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) { -- addr.sin_port = htons((unsigned short)port); -- if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { -- close(sock); -- return port; -- } -- } -+ sock = socket(AF_INET, SOCK_STREAM, 0); -+ if (sock < 0) { -+ fprintf(stderr,programName); -+ perror(": FindFreeTcpPort: socket"); -+ return 0; -+ } -+ -+ for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) { -+ addr.sin_port = htons((unsigned short)port); -+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { -+ close(sock); -+ return port; -+ } -+ } - -- close(sock); -- return 0; -+ close(sock); -+ return 0; - } - - -@@ -272,47 +901,110 @@ - * ListenAtTcpPort starts listening at the given TCP port. - */ - --int --ListenAtTcpPort(int port) --{ -- int sock; -- struct sockaddr_in addr; -- int one = 1; -- -- addr.sin_family = AF_INET; -- addr.sin_port = htons(port); -- addr.sin_addr.s_addr = INADDR_ANY; -+int use_loopback = 0; - -- sock = socket(AF_INET, SOCK_STREAM, 0); -- if (sock < 0) { -- fprintf(stderr,programName); -- perror(": ListenAtTcpPort: socket"); -- return -1; -- } -+int ListenAtTcpPort(int port) { -+ int sock; -+ struct sockaddr_in addr; -+ int one = 1; -+ -+ if (appData.noipv4) { -+ fprintf(stderr, "ipv4 is disabled via VNCVIEWER_NO_IPV4/-noipv4.\n"); -+ return -1; -+ } - -- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, -- (const char *)&one, sizeof(one)) < 0) { -- fprintf(stderr,programName); -- perror(": ListenAtTcpPort: setsockopt"); -- close(sock); -- return -1; -- } -+ memset(&addr, 0, sizeof(struct sockaddr_in)); - -- if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { -- fprintf(stderr,programName); -- perror(": ListenAtTcpPort: bind"); -- close(sock); -- return -1; -- } -+ addr.sin_family = AF_INET; -+ addr.sin_port = htons(port); -+ addr.sin_addr.s_addr = INADDR_ANY; - -- if (listen(sock, 5) < 0) { -- fprintf(stderr,programName); -- perror(": ListenAtTcpPort: listen"); -- close(sock); -- return -1; -- } -+ 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) { -+ perror("ListenAtTcpPort: socket"); -+ return -1; -+ } - -- return sock; -+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, sizeof(one)) < 0) { -+ perror("ListenAtTcpPort: setsockopt"); -+ close(sock); -+ return -1; -+ } -+ -+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { -+ perror("ListenAtTcpPort: bind"); -+ close(sock); -+ return -1; -+ } -+ -+ if (listen(sock, 32) < 0) { -+ perror("ListenAtTcpPort: listen"); -+ close(sock); -+ return -1; -+ } -+ -+ return sock; -+} -+ -+int ListenAtTcpPort6(int port) { -+ int sock = -1; -+#ifdef AF_INET6 -+ struct sockaddr_in6 sin; -+ int one = 1; -+ -+ if (appData.noipv6) { -+ fprintf(stderr, "ipv6 is disabled via VNCVIEWER_NO_IPV6/-noipv6.\n"); -+ return -1; -+ } -+ -+ sock = socket(AF_INET6, SOCK_STREAM, 0); -+ if (sock < 0) { -+ perror("ListenAtTcpPort[ipv6]: socket"); -+ return -1; -+ } -+ -+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) { -+ perror("ListenAtTcpPort[ipv6]: setsockopt1"); -+ close(sock); -+ return -1; -+ } -+ -+#if defined(SOL_IPV6) && defined(IPV6_V6ONLY) -+ if (setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) { -+ perror("ListenAtTcpPort[ipv6]: setsockopt2"); -+ close(sock); -+ return -1; -+ } -+#endif -+ -+ memset((char *)&sin, 0, sizeof(sin)); -+ sin.sin6_family = AF_INET6; -+ sin.sin6_port = htons(port); -+ sin.sin6_addr = in6addr_any; -+ -+ if (getenv("VNCVIEWER_LISTEN_LOCALHOST") || use_loopback) { -+ sin.sin6_addr = in6addr_loopback; -+ } -+ -+ if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { -+ perror("ListenAtTcpPort[ipv6]: bind"); -+ close(sock); -+ return -1; -+ } -+ -+ if (listen(sock, 32) < 0) { -+ perror("ListenAtTcpPort[ipv6]: listen"); -+ close(sock); -+ return -1; -+ } -+ -+#endif -+ if (port) {} -+ return sock; - } - - -@@ -320,33 +1012,69 @@ - * AcceptTcpConnection accepts a TCP connection. - */ - --int --AcceptTcpConnection(int listenSock) --{ -- int sock; -- struct sockaddr_in addr; -- int addrlen = sizeof(addr); -- int one = 1; -+int AcceptTcpConnection(int listenSock) { -+ int sock; -+ struct sockaddr_in addr; -+ int addrlen = sizeof(addr); -+ int one = 1; -+ -+ sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen); -+ if (sock < 0) { -+ perror("AcceptTcpConnection: accept"); -+ return -1; -+ } - -- sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen); -- if (sock < 0) { -- fprintf(stderr,programName); -- perror(": AcceptTcpConnection: accept"); -- return -1; -- } -+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { -+ perror("AcceptTcpConnection: setsockopt"); -+ close(sock); -+ return -1; -+ } - -- if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, -- (char *)&one, sizeof(one)) < 0) { -- fprintf(stderr,programName); -- perror(": AcceptTcpConnection: setsockopt"); -- close(sock); -- return -1; -- } -+ return sock; -+} -+ -+char *accept6_ipaddr = NULL; -+char *accept6_hostname = NULL; -+ -+int AcceptTcpConnection6(int listenSock) { -+ int sock = -1; -+#ifdef AF_INET6 -+ struct sockaddr_in6 addr; -+ socklen_t addrlen = sizeof(addr); -+ int one = 1; -+ char *name; -+ -+ if (appData.noipv6) { -+ return -1; -+ } -+ -+ sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen); -+ if (sock < 0) { -+ perror("AcceptTcpConnection[ipv6]: accept"); -+ return -1; -+ } -+ -+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { -+ perror("AcceptTcpConnection[ipv6]: setsockopt"); -+ close(sock); -+ return -1; -+ } - -- return sock; -+ name = ipv6_getipaddr((struct sockaddr *) &addr, addrlen); -+ if (!name) name = strdup("unknown"); -+ accept6_ipaddr = name; -+ fprintf(stderr, "AcceptTcpConnection6: ipv6 connection from: '%s'\n", name); -+ -+ name = ipv6_getnameinfo((struct sockaddr *) &addr, addrlen); -+ if (!name) name = strdup("unknown"); -+ accept6_hostname = name; -+#endif -+ if (listenSock) {} -+ return sock; - } - - -+ - /* - * SetNonBlocking sets a socket into non-blocking mode. - */ -@@ -379,7 +1107,7 @@ - - *addr = inet_addr(str); - -- if (*addr != -1) -+ if (*addr != (unsigned int) -1) - return True; - - hp = gethostbyname(str); -@@ -392,6 +1120,42 @@ - return False; - } - -+char *get_peer_ip(int sock) { -+ struct sockaddr_in saddr; -+ unsigned int saddr_len; -+ int saddr_port; -+ char *saddr_ip_str = NULL; -+ -+ saddr_len = sizeof(saddr); -+ memset(&saddr, 0, sizeof(saddr)); -+ saddr_port = -1; -+ if (!getpeername(sock, (struct sockaddr *)&saddr, &saddr_len)) { -+ saddr_ip_str = inet_ntoa(saddr.sin_addr); -+ } -+ if (! saddr_ip_str) { -+ saddr_ip_str = "unknown"; -+ } -+ return strdup(saddr_ip_str); -+} -+ -+char *ip2host(char *ip) { -+ char *str; -+ struct hostent *hp; -+ in_addr_t iaddr; -+ -+ iaddr = inet_addr(ip); -+ if (iaddr == htonl(INADDR_NONE)) { -+ return strdup("unknown"); -+ } -+ -+ hp = gethostbyaddr((char *)&iaddr, sizeof(in_addr_t), AF_INET); -+ if (!hp) { -+ return strdup("unknown"); -+ } -+ str = strdup(hp->h_name); -+ return str; -+} -+ - - /* - * Test if the other end of a socket is on the same machine. -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 2008-10-05 15:16:35.000000000 -0400 -@@ -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.useXserverBackingStore) { -+ 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/tmake vnc_unixsrc/vncviewer/tmake ---- vnc_unixsrc.orig/vncviewer/tmake 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/tmake 2009-10-25 10:31:22.000000000 -0400 -@@ -0,0 +1,17 @@ -+#!/bin/sh -+TURBOVNC_DIR=/home/runge/turbojpeg -+make clean -+(cd ../libvncauth || exit 1; make) -+if [ "X$1" = "X-a" ]; then -+ exit -+fi -+make CCOPTIONS=-DTURBOVNC EXTRA_LIBRARIES="-L$TURBOVNC_DIR -Xlinker --rpath=$TURBOVNC_DIR -Xlinker --rpath=/usr/local/lib -lturbojpeg" -+cp -p vncviewer vncviewer.turbovnc -+strip vncviewer.turbovnc -+ls -l vncviewer.turbovnc -+ldd vncviewer.turbovnc -+ -+echo -+make clean all -+ls -l vncviewer -+ldd vncviewer -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 2010-02-25 23:39:24.000000000 -0500 -@@ -100,7 +100,6 @@ - int *pargc, char **argv, int tunnelArgIndex) - { - char *pdisplay; -- int port; - - if (tunnelArgIndex >= *pargc - 1) - usage(); -@@ -132,6 +131,7 @@ - { - char *colonPos; - int len, portOffset; -+ int disp; - - if (tunnelArgIndex >= *pargc - 2) - usage(); -@@ -150,10 +150,17 @@ - len--; - portOffset = 0; - } -- if (!len || strspn(colonPos, "-0123456789") != len) { -+ if (!len || (int) 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/turbovnc/tight.c vnc_unixsrc/vncviewer/turbovnc/tight.c ---- vnc_unixsrc.orig/vncviewer/turbovnc/tight.c 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/turbovnc/tight.c 2008-08-20 13:35:58.000000000 -0400 -@@ -0,0 +1,613 @@ -+/* -+ * Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved. -+ * Copyright (C) 2004 Landmark Graphics Corporation. All Rights Reserved. -+ * Copyright (C) 2000, 2001 Const Kaplinsky. 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. -+ */ -+ -+/* -+ * tight.c - handle ``tight'' 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 a tight-encoded rectangle with BPP bits per pixel. -+ * -+ */ -+ -+#define TIGHT_MIN_TO_COMPRESS 12 -+ -+#define CARDBPP CONCAT2E(CARD,BPP) -+#define filterPtrBPP CONCAT2E(filterPtr,BPP) -+ -+#define HandleTightBPP CONCAT2E(HandleTight,BPP) -+#define InitFilterCopyBPP CONCAT2E(InitFilterCopy,BPP) -+#define InitFilterPaletteBPP CONCAT2E(InitFilterPalette,BPP) -+#define InitFilterGradientBPP CONCAT2E(InitFilterGradient,BPP) -+#define FilterCopyBPP CONCAT2E(FilterCopy,BPP) -+#define FilterPaletteBPP CONCAT2E(FilterPalette,BPP) -+#define FilterGradientBPP CONCAT2E(FilterGradient,BPP) -+ -+#if BPP != 8 -+#define DecompressJpegRectBPP CONCAT2E(DecompressJpegRect,BPP) -+#endif -+ -+#ifndef RGB_TO_PIXEL -+ -+#define RGB_TO_PIXEL(bpp,r,g,b) \ -+ (((CARD##bpp)(r) & myFormat.redMax) << myFormat.redShift | \ -+ ((CARD##bpp)(g) & myFormat.greenMax) << myFormat.greenShift | \ -+ ((CARD##bpp)(b) & myFormat.blueMax) << myFormat.blueShift) -+ -+#define RGB24_TO_PIXEL(bpp,r,g,b) \ -+ ((((CARD##bpp)(r) & 0xFF) * myFormat.redMax + 127) / 255 \ -+ << myFormat.redShift | \ -+ (((CARD##bpp)(g) & 0xFF) * myFormat.greenMax + 127) / 255 \ -+ << myFormat.greenShift | \ -+ (((CARD##bpp)(b) & 0xFF) * myFormat.blueMax + 127) / 255 \ -+ << myFormat.blueShift) -+ -+#define RGB24_TO_PIXEL32(r,g,b) \ -+ (((CARD32)(r) & 0xFF) << myFormat.redShift | \ -+ ((CARD32)(g) & 0xFF) << myFormat.greenShift | \ -+ ((CARD32)(b) & 0xFF) << myFormat.blueShift) -+ -+#endif -+ -+extern XImage *image; -+ -+/* Type declarations */ -+ -+typedef void (*filterPtrBPP)(int, int, int); -+ -+/* Prototypes */ -+ -+static int InitFilterCopyBPP (int rw, int rh); -+static int InitFilterPaletteBPP (int rw, int rh); -+static int InitFilterGradientBPP (int rw, int rh); -+static void FilterCopyBPP (int srcx, int srcy, int numRows); -+static void FilterPaletteBPP (int srcx, int srcy, int numRows); -+static void FilterGradientBPP (int srcx, int srcy, int numRows); -+ -+static Bool DecompressJpegRectBPP(int x, int y, int w, int h); -+ -+/* Definitions */ -+ -+static Bool -+HandleTightBPP (int rx, int ry, int rw, int rh) -+{ -+ CARDBPP fill_colour; -+ XGCValues gcv; -+ CARD8 comp_ctl; -+ CARD8 filter_id; -+ filterPtrBPP filterFn; -+ z_streamp zs; -+ int err, stream_id, compressedLen, bitsPixel; -+ int bufferSize, rowSize, numRows; -+ Bool readUncompressed = False; -+ CARDBPP *rawData; -+ -+ if (!ReadFromRFBServer((char *)&comp_ctl, 1)) -+ return False; -+ -+ /* Flush zlib streams if we are told by the server to do so. */ -+ for (stream_id = 0; stream_id < 4; stream_id++) { -+ if ((comp_ctl & 1) && zlibStreamActive[stream_id]) { -+ if (inflateEnd (&zlibStream[stream_id]) != Z_OK && -+ zlibStream[stream_id].msg != NULL) -+ fprintf(stderr, "inflateEnd: %s\n", zlibStream[stream_id].msg); -+ zlibStreamActive[stream_id] = False; -+ } -+ comp_ctl >>= 1; -+ } -+ -+ if ((comp_ctl & rfbTightNoZlib) == rfbTightNoZlib) { -+ comp_ctl &= ~(rfbTightNoZlib); -+ readUncompressed = True; -+ } -+ -+ /* Handle solid rectangles. */ -+ if (comp_ctl == rfbTightFill) { -+#if BPP == 32 -+ if (myFormat.depth == 24 && myFormat.redMax == 0xFF && -+ myFormat.greenMax == 0xFF && myFormat.blueMax == 0xFF) { -+ if (!ReadFromRFBServer(buffer, 3)) -+ return False; -+ fill_colour = RGB24_TO_PIXEL32(buffer[0], buffer[1], buffer[2]); -+ } else { -+ if (!ReadFromRFBServer((char*)&fill_colour, sizeof(fill_colour))) -+ return False; -+ } -+#else -+ if (!ReadFromRFBServer((char*)&fill_colour, sizeof(fill_colour))) -+ return False; -+#endif -+ -+#if (BPP == 8) -+ gcv.foreground = (appData.useBGR233) ? -+ BGR233ToPixel[fill_colour] : fill_colour; -+#else -+ gcv.foreground = fill_colour; -+#endif -+ -+ FillRectangle(&gcv, rx, ry, rw, rh); -+ return True; -+ } -+ -+#if BPP == 8 -+ if (comp_ctl == rfbTightJpeg) { -+ fprintf(stderr, "Tight encoding: JPEG is not supported in 8 bpp mode.\n"); -+ return False; -+ } -+#else -+ if (comp_ctl == rfbTightJpeg) { -+ return DecompressJpegRectBPP(rx, ry, rw, rh); -+ } -+#endif -+ -+ /* Quit on unsupported subencoding value. */ -+ if (comp_ctl > rfbTightMaxSubencoding) { -+ fprintf(stderr, "Tight encoding: bad subencoding value received.\n"); -+ return False; -+ } -+ -+ /* -+ * Here primary compression mode handling begins. -+ * Data was processed with optional filter + zlib compression. -+ */ -+ -+ /* First, we should identify a filter to use. */ -+ if ((comp_ctl & rfbTightExplicitFilter) != 0) { -+ if (!ReadFromRFBServer((char*)&filter_id, 1)) -+ return False; -+ -+ switch (filter_id) { -+ case rfbTightFilterCopy: -+ filterFn = FilterCopyBPP; -+ bitsPixel = InitFilterCopyBPP(rw, rh); -+ break; -+ case rfbTightFilterPalette: -+ filterFn = FilterPaletteBPP; -+ bitsPixel = InitFilterPaletteBPP(rw, rh); -+ break; -+ case rfbTightFilterGradient: -+ filterFn = FilterGradientBPP; -+ bitsPixel = InitFilterGradientBPP(rw, rh); -+ break; -+ default: -+ fprintf(stderr, "Tight encoding: unknown filter code received.\n"); -+ return False; -+ } -+ } else { -+ filterFn = FilterCopyBPP; -+ bitsPixel = InitFilterCopyBPP(rw, rh); -+ } -+ if (bitsPixel == 0) { -+ fprintf(stderr, "Tight encoding: error receiving palette.\n"); -+ return False; -+ } -+ -+ /* Determine if the data should be decompressed or just copied. */ -+ rowSize = (rw * bitsPixel + 7) / 8; -+ bufferSize = -1; -+ if (rh * rowSize < TIGHT_MIN_TO_COMPRESS) -+ bufferSize = rh * rowSize; -+ else if (readUncompressed) { -+ bufferSize = (int)ReadCompactLen(); -+ } -+ if (bufferSize != -1) { -+ uncompressedData = (char *)realloc(uncompressedData, bufferSize); -+ if (!uncompressedData) { -+ fprintf(stderr, "Memory allocation error\n"); -+ return False; -+ } -+ if (!ReadFromRFBServer(uncompressedData, bufferSize)) -+ return False; -+ filterFn(rx, ry, rh); -+ if (appData.useBGR233) CopyDataToImage(buffer, rx, ry, rw, rh); -+ if (!appData.doubleBuffer) CopyImageToScreen(rx, ry, rw, rh); -+ -+ return True; -+ } -+ -+ /* Read the length (1..3 bytes) of compressed data following. */ -+ compressedLen = (int)ReadCompactLen(); -+ if (compressedLen <= 0) { -+ fprintf(stderr, "Incorrect data received from the server.\n"); -+ return False; -+ } -+ -+ /* Now let's initialize compression stream if needed. */ -+ stream_id = comp_ctl & 0x03; -+ zs = &zlibStream[stream_id]; -+ if (!zlibStreamActive[stream_id]) { -+ zs->zalloc = Z_NULL; -+ zs->zfree = Z_NULL; -+ zs->opaque = Z_NULL; -+ err = inflateInit(zs); -+ if (err != Z_OK) { -+ if (zs->msg != NULL) -+ fprintf(stderr, "InflateInit error: %s.\n", zs->msg); -+ return False; -+ } -+ zlibStreamActive[stream_id] = True; -+ } -+ -+ /* Read, decode and draw actual pixel data in a loop. */ -+ -+ compressedData = (char *)realloc(compressedData, compressedLen); -+ if (!compressedData) { -+ fprintf(stderr, "Memory allocation error\n"); -+ return False; -+ } -+ uncompressedData = (char *)realloc(uncompressedData, rh * rowSize); -+ if (!uncompressedData) { -+ fprintf(stderr, "Memory allocation error\n"); -+ return False; -+ } -+ -+ if (!ReadFromRFBServer(compressedData, compressedLen)) -+ return False; -+ zs->next_in = (Bytef *)compressedData; -+ zs->avail_in = compressedLen; -+ zs->next_out = (Bytef *)uncompressedData; -+ zs->avail_out = rh * rowSize; -+ -+ err = inflate(zs, Z_SYNC_FLUSH); -+ if (err != Z_OK && err != Z_STREAM_END) { -+ if (zs->msg != NULL) { -+ fprintf(stderr, "Inflate error: %s.\n", zs->msg); -+ } else { -+ fprintf(stderr, "Inflate error: %d.\n", err); -+ } -+ return False; -+ } -+ -+ filterFn(rx, ry, rh); -+ if (appData.useBGR233) CopyDataToImage(buffer, rx, ry, rw, rh); -+ if (!appData.doubleBuffer) CopyImageToScreen(rx, ry, rw, rh); -+ -+ return True; -+} -+ -+/*---------------------------------------------------------------------------- -+ * -+ * Filter stuff. -+ * -+ */ -+ -+/* -+ The following variables are defined in rfbproto.c: -+ static Bool cutZeros; -+ static int rectWidth, rectColors; -+ static CARD8 tightPalette[256*4]; -+ static CARD8 tightPrevRow[2048*3*sizeof(CARD16)]; -+*/ -+ -+static int -+InitFilterCopyBPP (int rw, int rh) -+{ -+ rectWidth = rw; -+ -+#if BPP == 32 -+ if (myFormat.depth == 24 && myFormat.redMax == 0xFF && -+ myFormat.greenMax == 0xFF && myFormat.blueMax == 0xFF) { -+ cutZeros = True; -+ return 24; -+ } else { -+ cutZeros = False; -+ } -+#endif -+ -+ return BPP; -+} -+ -+static void -+FilterCopyBPP (int srcx, int srcy, int numRows) -+{ -+ CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line -+ + srcx * image->bits_per_pixel/8]; -+ int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); -+ int y; -+#if BPP == 32 -+ int x; -+#endif -+ -+ if (appData.useBGR233) { -+ dst = (CARDBPP *)buffer; -+ dstw = rectWidth; -+ } -+ -+#if BPP == 32 -+ if (cutZeros) { -+ for (y = 0; y < numRows; y++) { -+ for (x = 0; x < rectWidth; x++) { -+ dst[y*dstw+x] = -+ RGB24_TO_PIXEL32(uncompressedData[(y*rectWidth+x)*3], -+ uncompressedData[(y*rectWidth+x)*3+1], -+ uncompressedData[(y*rectWidth+x)*3+2]); -+ } -+ } -+ return; -+ } -+#endif -+ -+ for (y = 0; y < numRows; y++) -+ memcpy (&dst[y*dstw], &uncompressedData[y*rectWidth], rectWidth * (BPP / 8)); -+} -+ -+static int -+InitFilterGradientBPP (int rw, int rh) -+{ -+ int bits; -+ -+ bits = InitFilterCopyBPP(rw, rh); -+ if (cutZeros) -+ memset(tightPrevRow, 0, rw * 3); -+ else -+ memset(tightPrevRow, 0, rw * 3 * sizeof(CARD16)); -+ -+ return bits; -+} -+ -+#if BPP == 32 -+ -+static void -+FilterGradient24 (int srcx, int srcy, int numRows) -+{ -+ CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line -+ + srcx * image->bits_per_pixel/8]; -+ int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); -+ int x, y, c; -+ CARD8 thisRow[2048*3]; -+ CARD8 pix[3]; -+ int est[3]; -+ -+ if (appData.useBGR233) { -+ dst = (CARDBPP *)buffer; -+ dstw = rectWidth; -+ } -+ -+ for (y = 0; y < numRows; y++) { -+ -+ /* First pixel in a row */ -+ for (c = 0; c < 3; c++) { -+ pix[c] = tightPrevRow[c] + uncompressedData[y*rectWidth*3+c]; -+ thisRow[c] = pix[c]; -+ } -+ dst[y*dstw] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); -+ -+ /* Remaining pixels of a row */ -+ for (x = 1; x < rectWidth; x++) { -+ for (c = 0; c < 3; c++) { -+ est[c] = (int)tightPrevRow[x*3+c] + (int)pix[c] - -+ (int)tightPrevRow[(x-1)*3+c]; -+ if (est[c] > 0xFF) { -+ est[c] = 0xFF; -+ } else if (est[c] < 0x00) { -+ est[c] = 0x00; -+ } -+ pix[c] = (CARD8)est[c] + buffer[(y*rectWidth+x)*3+c]; -+ thisRow[x*3+c] = pix[c]; -+ } -+ dst[y*dstw+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); -+ } -+ -+ memcpy(tightPrevRow, thisRow, rectWidth * 3); -+ } -+} -+ -+#endif -+ -+static void -+FilterGradientBPP (int srcx, int srcy, int numRows) -+{ -+ int x, y, c; -+ CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line -+ + srcx * image->bits_per_pixel/8]; -+ int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); -+ CARDBPP *src = (CARDBPP *)uncompressedData; -+ CARD16 *thatRow = (CARD16 *)tightPrevRow; -+ CARD16 thisRow[2048*3]; -+ CARD16 pix[3]; -+ CARD16 max[3]; -+ int shift[3]; -+ int est[3]; -+ -+ if (appData.useBGR233) { -+ dst = (CARDBPP *)buffer; -+ dstw = rectWidth; -+ } -+ -+#if BPP == 32 -+ if (cutZeros) { -+ FilterGradient24(srcx, srcy, numRows); -+ return; -+ } -+#endif -+ -+ max[0] = myFormat.redMax; -+ max[1] = myFormat.greenMax; -+ max[2] = myFormat.blueMax; -+ -+ shift[0] = myFormat.redShift; -+ shift[1] = myFormat.greenShift; -+ shift[2] = myFormat.blueShift; -+ -+ for (y = 0; y < numRows; y++) { -+ -+ /* First pixel in a row */ -+ for (c = 0; c < 3; c++) { -+ pix[c] = (CARD16)((src[y*rectWidth] >> shift[c]) + thatRow[c] & max[c]); -+ thisRow[c] = pix[c]; -+ } -+ dst[y*dstw] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); -+ -+ /* Remaining pixels of a row */ -+ for (x = 1; x < rectWidth; x++) { -+ for (c = 0; c < 3; c++) { -+ est[c] = (int)thatRow[x*3+c] + (int)pix[c] - (int)thatRow[(x-1)*3+c]; -+ if (est[c] > (int)max[c]) { -+ est[c] = (int)max[c]; -+ } else if (est[c] < 0) { -+ est[c] = 0; -+ } -+ pix[c] = (CARD16)((src[y*rectWidth+x] >> shift[c]) + est[c] & max[c]); -+ thisRow[x*3+c] = pix[c]; -+ } -+ dst[y*dstw+x] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); -+ } -+ memcpy(thatRow, thisRow, rectWidth * 3 * sizeof(CARD16)); -+ } -+} -+ -+static int -+InitFilterPaletteBPP (int rw, int rh) -+{ -+ int i; -+ CARD8 numColors; -+ CARDBPP *palette = (CARDBPP *)tightPalette; -+ -+ rectWidth = rw; -+ -+ if (!ReadFromRFBServer((char*)&numColors, 1)) -+ return 0; -+ -+ rectColors = (int)numColors; -+ if (++rectColors < 2) -+ return 0; -+ -+#if BPP == 32 -+ if (myFormat.depth == 24 && myFormat.redMax == 0xFF && -+ myFormat.greenMax == 0xFF && myFormat.blueMax == 0xFF) { -+ if (!ReadFromRFBServer((char*)&tightPalette, rectColors * 3)) -+ return 0; -+ for (i = rectColors - 1; i >= 0; i--) { -+ palette[i] = RGB24_TO_PIXEL32(tightPalette[i*3], -+ tightPalette[i*3+1], -+ tightPalette[i*3+2]); -+ } -+ return (rectColors == 2) ? 1 : 8; -+ } -+#endif -+ -+ if (!ReadFromRFBServer((char*)&tightPalette, rectColors * (BPP / 8))) -+ return 0; -+ -+ return (rectColors == 2) ? 1 : 8; -+} -+ -+static void -+FilterPaletteBPP (int srcx, int srcy, int numRows) -+{ -+ int x, y, b, w; -+ CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line -+ + srcx * image->bits_per_pixel/8]; -+ int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); -+ CARD8 *src = (CARD8 *)uncompressedData; -+ CARDBPP *palette = (CARDBPP *)tightPalette; -+ -+ if (appData.useBGR233) { -+ dst = (CARDBPP *)buffer; -+ dstw = rectWidth; -+ } -+ -+ if (rectColors == 2) { -+ w = (rectWidth + 7) / 8; -+ for (y = 0; y < numRows; y++) { -+ for (x = 0; x < rectWidth / 8; x++) { -+ for (b = 7; b >= 0; b--) -+ dst[y*dstw+x*8+7-b] = palette[src[y*w+x] >> b & 1]; -+ } -+ for (b = 7; b >= 8 - rectWidth % 8; b--) { -+ dst[y*dstw+x*8+7-b] = palette[src[y*w+x] >> b & 1]; -+ } -+ } -+ } else { -+ for (y = 0; y < numRows; y++) -+ for (x = 0; x < rectWidth; x++) -+ dst[y*dstw+x] = palette[(int)src[y*rectWidth+x]]; -+ } -+} -+ -+#if BPP != 8 -+ -+/*---------------------------------------------------------------------------- -+ * -+ * JPEG decompression. -+ * -+ */ -+ -+/* -+ The following variables are defined in rfbproto.c: -+ static Bool jpegError; -+ static struct jpeg_source_mgr jpegSrcManager; -+ static JOCTET *jpegBufferPtr; -+ static size_t *jpegBufferLen; -+*/ -+ -+static Bool -+DecompressJpegRectBPP(int x, int y, int w, int h) -+{ -+ int compressedLen; -+ char *dstptr; -+ int ps, flags=0; -+ -+ compressedLen = (int)ReadCompactLen(); -+ if (compressedLen <= 0) { -+ fprintf(stderr, "Incorrect data received from the server.\n"); -+ return False; -+ } -+ -+ compressedData = (char *)realloc(compressedData, compressedLen); -+ if (compressedData == NULL) { -+ fprintf(stderr, "Memory allocation error.\n"); -+ return False; -+ } -+ -+ if (!ReadFromRFBServer(compressedData, compressedLen)) { -+ return False; -+ } -+ -+ if(!tjhnd) { -+ if((tjhnd=tjInitDecompress())==NULL) { -+ fprintf(stderr, "TurboJPEG error: %s\n", tjGetErrorStr()); -+ return False; -+ } -+ } -+ -+ ps=image->bits_per_pixel/8; -+ if(myFormat.bigEndian && ps==4) flags|=TJ_ALPHAFIRST; -+ if(myFormat.redShift==16 && myFormat.blueShift==0) -+ flags|=TJ_BGR; -+ if(myFormat.bigEndian) flags^=TJ_BGR; -+ -+ dstptr=&image->data[image->bytes_per_line*y+x*ps]; -+ if(tjDecompress(tjhnd, (unsigned char *)compressedData, (unsigned long)compressedLen, -+ (unsigned char *)dstptr, w, image->bytes_per_line, h, ps, flags)==-1) { -+ fprintf(stderr, "TurboJPEG error: %s\n", tjGetErrorStr()); -+ return False; -+ } -+ -+ if (!appData.doubleBuffer) -+ CopyImageToScreen(x, y, w, h); -+ -+ return True; -+} -+ -+#endif -+ -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/turbovnc/turbojpeg.h vnc_unixsrc/vncviewer/turbovnc/turbojpeg.h ---- vnc_unixsrc.orig/vncviewer/turbovnc/turbojpeg.h 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/turbovnc/turbojpeg.h 2008-04-03 04:28:56.000000000 -0400 -@@ -0,0 +1,229 @@ -+/* Copyright (C)2004 Landmark Graphics -+ * Copyright (C)2005, 2006 Sun Microsystems, Inc. -+ * -+ * This library is free software and may be redistributed and/or modified under -+ * the terms of the wxWindows Library License, Version 3.1 or (at your option) -+ * any later version. The full license is in the LICENSE.txt file included -+ * with this distribution. -+ * -+ * This library 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 -+ * wxWindows Library License for more details. -+ */ -+ -+#if (defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)) && defined(_WIN32) && defined(DLLDEFINE) -+#define DLLEXPORT __declspec(dllexport) -+#else -+#define DLLEXPORT -+#endif -+ -+#define DLLCALL -+ -+/* Subsampling */ -+#define NUMSUBOPT 4 -+ -+enum {TJ_444=0, TJ_422, TJ_411, TJ_GRAYSCALE}; -+ -+/* Flags */ -+#define TJ_BGR 1 -+#define TJ_BOTTOMUP 2 -+#define TJ_FORCEMMX 8 /* Force IPP to use MMX code even if SSE available */ -+#define TJ_FORCESSE 16 /* Force IPP to use SSE1 code even if SSE2 available */ -+#define TJ_FORCESSE2 32 /* Force IPP to use SSE2 code (useful if auto-detect is not working properly) */ -+#define TJ_ALPHAFIRST 64 /* BGR buffer is ABGR and RGB buffer is ARGB */ -+#define TJ_FORCESSE3 128 /* Force IPP to use SSE3 code (useful if auto-detect is not working properly) */ -+ -+typedef void* tjhandle; -+ -+#define TJPAD(p) (((p)+3)&(~3)) -+#ifndef max -+ #define max(a,b) ((a)>(b)?(a):(b)) -+#endif -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/* API follows */ -+ -+ -+/* -+ tjhandle tjInitCompress(void) -+ -+ Creates a new JPEG compressor instance, allocates memory for the structures, -+ and returns a handle to the instance. Most applications will only -+ need to call this once at the beginning of the program or once for each -+ concurrent thread. Don't try to create a new instance every time you -+ compress an image, because this will cause performance to suffer. -+ -+ RETURNS: NULL on error -+*/ -+DLLEXPORT tjhandle DLLCALL tjInitCompress(void); -+ -+ -+/* -+ int tjCompress(tjhandle j, -+ unsigned char *srcbuf, int width, int pitch, int height, int pixelsize, -+ unsigned char *dstbuf, unsigned long *size, -+ int jpegsubsamp, int jpegqual, int flags) -+ -+ [INPUT] j = instance handle previously returned from a call to -+ tjInitCompress() -+ [INPUT] srcbuf = pointer to user-allocated image buffer containing pixels in -+ RGB(A) or BGR(A) form -+ [INPUT] width = width (in pixels) of the source image -+ [INPUT] pitch = bytes per line of the source image (width*pixelsize if the -+ bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap -+ is padded to the nearest 32-bit boundary, such as is the case for Windows -+ bitmaps. You can also be clever and use this parameter to skip lines, etc., -+ as long as the pitch is greater than 0.) -+ [INPUT] height = height (in pixels) of the source image -+ [INPUT] pixelsize = size (in bytes) of each pixel in the source image -+ RGBA and BGRA: 4, RGB and BGR: 3 -+ [INPUT] dstbuf = pointer to user-allocated image buffer which will receive -+ the JPEG image. Use the macro TJBUFSIZE(width, height) to determine -+ the appropriate size for this buffer based on the image width and height. -+ [OUTPUT] size = pointer to unsigned long which receives the size (in bytes) -+ of the compressed image -+ [INPUT] jpegsubsamp = Specifies either 4:1:1, 4:2:2, or 4:4:4 subsampling. -+ When the image is converted from the RGB to YCbCr colorspace as part of the -+ JPEG compression process, every other Cb and Cr (chrominance) pixel can be -+ discarded to produce a smaller image with little perceptible loss of -+ image clarity (the human eye is more sensitive to small changes in -+ brightness than small changes in color.) -+ -+ TJ_411: 4:1:1 subsampling. Discards every other Cb, Cr pixel in both -+ horizontal and vertical directions. -+ TJ_422: 4:2:2 subsampling. Discards every other Cb, Cr pixel only in -+ the horizontal direction. -+ TJ_444: no subsampling. -+ TJ_GRAYSCALE: Generate grayscale JPEG image -+ -+ [INPUT] jpegqual = JPEG quality (an integer between 0 and 100 inclusive.) -+ [INPUT] flags = the bitwise OR of one or more of the following -+ -+ TJ_BGR: The components of each pixel in the source image are stored in -+ B,G,R order, not R,G,B -+ TJ_BOTTOMUP: The source image is stored in bottom-up (Windows) order, -+ not top-down -+ TJ_FORCEMMX: Valid only for the Intel Performance Primitives implementation -+ of this codec-- force IPP to use MMX code (bypass CPU auto-detection) -+ TJ_FORCESSE: Valid only for the Intel Performance Primitives implementation -+ of this codec-- force IPP to use SSE code (bypass CPU auto-detection) -+ TJ_FORCESSE2: Valid only for the Intel Performance Primitives implementation -+ of this codec-- force IPP to use SSE2 code (bypass CPU auto-detection) -+ TJ_FORCESSE3: Valid only for the Intel Performance Primitives implementation -+ of this codec-- force IPP to use SSE3 code (bypass CPU auto-detection) -+ -+ RETURNS: 0 on success, -1 on error -+*/ -+DLLEXPORT int DLLCALL tjCompress(tjhandle j, -+ unsigned char *srcbuf, int width, int pitch, int height, int pixelsize, -+ unsigned char *dstbuf, unsigned long *size, -+ int jpegsubsamp, int jpegqual, int flags); -+ -+DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height); -+ -+/* -+ tjhandle tjInitDecompress(void) -+ -+ Creates a new JPEG decompressor instance, allocates memory for the -+ structures, and returns a handle to the instance. Most applications will -+ only need to call this once at the beginning of the program or once for each -+ concurrent thread. Don't try to create a new instance every time you -+ decompress an image, because this will cause performance to suffer. -+ -+ RETURNS: NULL on error -+*/ -+DLLEXPORT tjhandle DLLCALL tjInitDecompress(void); -+ -+ -+/* -+ int tjDecompressHeader(tjhandle j, -+ unsigned char *srcbuf, unsigned long size, -+ int *width, int *height) -+ -+ [INPUT] j = instance handle previously returned from a call to -+ tjInitDecompress() -+ [INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image -+ to decompress -+ [INPUT] size = size of the JPEG image buffer (in bytes) -+ [OUTPUT] width = width (in pixels) of the JPEG image -+ [OUTPUT] height = height (in pixels) of the JPEG image -+ -+ RETURNS: 0 on success, -1 on error -+*/ -+DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle j, -+ unsigned char *srcbuf, unsigned long size, -+ int *width, int *height); -+ -+ -+/* -+ int tjDecompress(tjhandle j, -+ unsigned char *srcbuf, unsigned long size, -+ unsigned char *dstbuf, int width, int pitch, int height, int pixelsize, -+ int flags) -+ -+ [INPUT] j = instance handle previously returned from a call to -+ tjInitDecompress() -+ [INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image -+ to decompress -+ [INPUT] size = size of the JPEG image buffer (in bytes) -+ [INPUT] dstbuf = pointer to user-allocated image buffer which will receive -+ the bitmap image. This buffer should normally be pitch*height -+ bytes in size, although this pointer may also be used to decompress into -+ a specific region of a larger buffer. -+ [INPUT] width = width (in pixels) of the destination image -+ [INPUT] pitch = bytes per line of the destination image (width*pixelsize if the -+ bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap -+ is padded to the nearest 32-bit boundary, such as is the case for Windows -+ bitmaps. You can also be clever and use this parameter to skip lines, etc., -+ as long as the pitch is greater than 0.) -+ [INPUT] height = height (in pixels) of the destination image -+ [INPUT] pixelsize = size (in bytes) of each pixel in the destination image -+ RGBA/RGBx and BGRA/BGRx: 4, RGB and BGR: 3 -+ [INPUT] flags = the bitwise OR of one or more of the following -+ -+ TJ_BGR: The components of each pixel in the destination image should be -+ written in B,G,R order, not R,G,B -+ TJ_BOTTOMUP: The destination image should be stored in bottom-up -+ (Windows) order, not top-down -+ TJ_FORCEMMX: Valid only for the Intel Performance Primitives implementation -+ of this codec-- force IPP to use MMX code (bypass CPU auto-detection) -+ TJ_FORCESSE: Valid only for the Intel Performance Primitives implementation -+ of this codec-- force IPP to use SSE code (bypass CPU auto-detection) -+ TJ_FORCESSE2: Valid only for the Intel Performance Primitives implementation -+ of this codec-- force IPP to use SSE2 code (bypass CPU auto-detection) -+ -+ RETURNS: 0 on success, -1 on error -+*/ -+DLLEXPORT int DLLCALL tjDecompress(tjhandle j, -+ unsigned char *srcbuf, unsigned long size, -+ unsigned char *dstbuf, int width, int pitch, int height, int pixelsize, -+ int flags); -+ -+ -+/* -+ int tjDestroy(tjhandle h) -+ -+ Frees structures associated with a compression or decompression instance -+ -+ [INPUT] h = instance handle (returned from a previous call to -+ tjInitCompress() or tjInitDecompress() -+ -+ RETURNS: 0 on success, -1 on error -+*/ -+DLLEXPORT int DLLCALL tjDestroy(tjhandle h); -+ -+ -+/* -+ char *tjGetErrorStr(void) -+ -+ Returns a descriptive error message explaining why the last command failed -+*/ -+DLLEXPORT char* DLLCALL tjGetErrorStr(void); -+ -+#ifdef __cplusplus -+} -+#endif -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vncviewer/vncviewer._man ---- vnc_unixsrc.orig/vncviewer/vncviewer._man 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/vncviewer._man 2010-04-11 23:30:24.000000000 -0400 -@@ -0,0 +1,829 @@ -+'\" t -+.\" ** The above line should force tbl to be a preprocessor ** -+.\" Man page for X vncviewer -+.\" -+.\" Copyright (C) 1998 Marcus.Brinkmann@ruhr-uni-bochum.de -+.\" Copyright (C) 2000,2001 Red Hat, Inc. -+.\" Copyright (C) 2001-2003 Constantin Kaplinsky <const@ce.cctpu.edu.ru> -+.\" Copyright (C) 2006-2010 Karl J. Runge <runge@karlrunge.com> -+.\" -+.\" 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 ssvncviewer 1 "April 2010" "" "SSVNC" -+.SH NAME -+ssvncviewer \- an X viewer client for VNC -+.SH SYNOPSIS -+.B ssvncviewer -+.RI [\| options \|] -+.RI [\| host \|][\| :display \|] -+.br -+.B ssvncviewer -+.RI [\| options \|] -+.RI [\| host \|][\| ::port \|] -+.br -+.B ssvncviewer -+.RI [\| options \|] -+.RI exec=[\| cmd+args... \|] -+.br -+.B ssvncviewer -+.RI [\| options \|] -+.RI fd=n -+.br -+.B ssvncviewer -+.RI [\| options \|] -+.RI /path/to/unix/socket -+.br -+.B ssvncviewer -+.RI [\| options \|] -+.IR \-listen -+.RI [\| display \|] -+.br -+.B ssvncviewer -+.IR \-help -+.br -+.SH DESCRIPTION -+.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, 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 -+.TP -+\fB\-help\fR -+Prints a short usage notice to stderr. -+.TP -+\fB\-listen\fR -+Make the viewer listen on port 5500+\fIdisplay\fR for reverse -+connections from a server. WinVNC supports reverse connections using -+the "Add New Client" menu option, or the \-connect command line -+option. \fBXvnc\fR requires the use of the helper program -+\fBvncconnect\fR. -+.TP -+\fB\-via\fR \fIgateway\fR -+Automatically create encrypted TCP tunnel to the \fIgateway\fR machine -+before connection, connect to the \fIhost\fR through that tunnel -+(TightVNC\-specific). By default, this option invokes SSH local port -+forwarding, assuming that SSH client binary can be accessed as -+/usr/bin/ssh. Note that when using the \fB\-via\fR option, the host -+machine name should be specified as known to the gateway machine, e.g. -+"localhost" denotes the \fIgateway\fR, not the machine where vncviewer -+was launched. See the ENVIRONMENT section below for the information on -+configuring the \fB\-via\fR option. -+.TP -+\fB\-shared\fR -+When connecting, specify that a shared connection is requested. In -+TightVNC, this is the default mode, allowing you to share the desktop -+with other clients already using it. -+.TP -+\fB\-noshared\fR -+When connecting, specify that the session may not be shared. This -+would either disconnect other connected clients or refuse your -+connection, depending on the server configuration. -+.TP -+\fB\-viewonly\fR -+Disable transfer of mouse and keyboard events from the client to the -+server. -+.TP -+\fB\-fullscreen\fR -+Start in full\-screen mode. Please be aware that operating in -+full\-screen mode may confuse X window managers. Typically, such -+conflicts cause incorrect handling of input focus or make the viewer -+window disappear mysteriously. See the grabKeyboard setting in the -+RESOURCES section below for a method to solve input focus problem. -+.TP -+\fB\-noraiseonbeep\fR -+By default, the viewer shows and raises its window on remote beep -+(bell) event. This option disables such behaviour -+(TightVNC\-specific). -+.TP -+\fB\-user\fR \fIusername\fR -+User name for Unix login authentication. Default is to use current -+Unix user name. If this option was given, the viewer will prefer Unix -+login authentication over the standard VNC authentication. -+.TP -+\fB\-passwd\fR \fIpasswd\-file\fR -+File from which to get the password (as generated by the -+\fBvncpasswd\fR(1) program). This option affects only the standard VNC -+authentication. -+.TP -+\fB\-encodings\fR \fIencoding\-list\fR -+TightVNC supports several different compression methods to encode -+screen updates; this option specifies a set of them to use in order of -+preference. Encodings are specified separated with spaces, and must -+thus be enclosed in quotes if more than one is specified. Commas may be used to avoid spaces. -+Available encodings, in default order for a remote connection, are -+"copyrect tight hextile zlib corre rre raw". For a local connection -+(to the same machine), the default order to try is "raw copyrect tight -+hextile zlib corre rre". Raw encoding is always assumed as a last option -+if no other encoding can be used for some reason. For more information -+on encodings, see the section ENCODINGS below. -+.TP -+\fB\-bgr233\fR -+Always use the BGR233 format to encode pixel data. This reduces -+network traffic, but colors may be represented inaccurately. The -+bgr233 format is an 8\-bit "true color" format, with 2 bits blue, 3 -+bits green, and 3 bits red. -+.TP -+\fB\-owncmap\fR -+Try to use a PseudoColor visual and a private colormap. This allows -+the VNC server to control the colormap. -+.TP -+\fB\-truecolour\fR, \fB\-truecolor\fR -+Try to use a TrueColor visual. -+.TP -+\fB\-depth\fR \fIdepth\fR -+On an X server which supports multiple TrueColor visuals of different -+depths, attempt to use the specified one (in bits per pixel); if -+successful, this depth will be requested from the VNC server. -+.TP -+\fB\-compresslevel \fIlevel\fR -+Use specified compression \fIlevel\fR (0..9) for "tight" and "zlib" -+encodings (TightVNC\-specific). Level 1 uses minimum of CPU time and -+achieves weak compression ratios, while level 9 offers best -+compression but is slow in terms of CPU time consumption on the server -+side. Use high levels with very slow network connections, and low -+levels when working over high\-speed LANs. It's not recommended to use -+compression level 0, reasonable choices start from the level 1. -+.TP -+\fB\-quality \fIlevel\fR -+Use the specified JPEG quality \fIlevel\fR (0..9) for the "tight" -+encoding (TightVNC\-specific). Quality level 0 denotes bad image -+quality but very impressive compression ratios, while level 9 offers -+very good image quality at lower compression ratios. Note that the -+"tight" encoder uses JPEG to encode only those screen areas that look -+suitable for lossy compression, so quality level 0 does not always -+mean unacceptable image quality. -+.TP -+\fB\-nojpeg\fR -+Disable lossy JPEG compression in Tight encoding (TightVNC\-specific). -+Disabling JPEG compression is not a good idea in typical cases, as -+that makes the Tight encoder less efficient. You might want to use -+this option if it's absolutely necessary to achieve perfect image -+quality (see also the \fB\-quality\fR option). -+.TP -+\fB\-nocursorshape\fR -+Disable cursor shape updates, protocol extensions used to handle -+remote cursor movements locally on the client side -+(TightVNC\-specific). Using cursor shape updates decreases delays with -+remote cursor movements, and can improve bandwidth usage dramatically. -+.TP -+\fB\-x11cursor\fR -+Use a real X11 cursor with X-style cursor shape updates, instead of -+drawing the remote cursor on the framebuffer. This option also -+disables the dot cursor, and disables cursor position updates in -+non-fullscreen mode. -+.TP -+\fB\-autopass\fR -+Read a plain-text password from stdin. This option affects only the -+standard VNC authentication. -+ -+.SH Enhanced TightVNC Viewer (SSVNC) OPTIONS -+.TP -+Enhanced TightVNC Viewer (SSVNC) web page is located at: -+.TP -+http://www.karlrunge.com/x11vnc/ssvnc.html -+.TP -+Note: ZRLE 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. -+ -+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. -+ -+If the host:port is specified as "fd=n" then it is assumed -+n is an already opened file descriptor to the socket. (i.e -+the parent did fork+exec) -+ -+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\-acceptpopup\fR -+In \fB\-listen\fR (reverse connection listening) mode when -+a reverse VNC connection comes in show a popup asking -+whether to Accept or Reject the connection. The IP -+address of the connecting host is shown. Same as -+setting the env. var. SSVNC_ACCEPT_POPUP=1. -+.TP -+\fB\-acceptpopupsc\fR -+As in \fB\-acceptpopup\fR except assume UltraVNC Single -+Click (SC) server. Retrieve User and ComputerName -+info from UltraVNC Server and display in the Popup. -+.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\-scale\fR \fIstr\fR -+Scale the desktop locally. The string "str" can -+a floating point ratio, e.g. "0.9", or a fraction, -+e.g. "3/4", or WxH, e.g. 1280x1024. Use "fit" -+to fit in the current screen size. Use "auto" to -+fit in the window size. "str" can also be set by -+the env. var. SSVNC_SCALE. -+ -+If you observe mouse trail painting errors, enable -+X11 Cursor mode (either via Popup or \fB\-x11cursor\fR.) -+ -+Note that scaling is done in software and so can be -+slow and requires more memory. Some speedup Tips: -+ -+ZRLE is faster than Tight in this mode. When -+scaling is first detected, the encoding will -+be automatically switched to ZRLE. Use the -+Popup menu if you want to go back to Tight. -+Set SSVNC_PRESERVE_ENCODING=1 to disable this. -+ -+Use a solid background on the remote side. -+(e.g. manually or via x11vnc \fB\-solid\fR ...) -+ -+If the remote server is x11vnc, try client -+side caching: x11vnc \fB\-ncache\fR 10 ... -+.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\-notty\fR -+Try to avoid using the terminal for interactive -+responses: use windows for messages and prompting -+instead. Messages will also be printed to terminal. -+.TP -+\fB\-sendclipboard\fR -+Send the X CLIPBOARD selection (i.e. Ctrl+C, -+Ctrl+V) instead of the X PRIMARY selection (mouse -+select and middle button paste.) -+.TP -+\fB\-sendalways\fR -+Whenever the mouse enters the VNC viewer main -+window, send the selection to the VNC server even if -+it has not changed. This is like the Xt resource -+translation SelectionToVNC(always) -+.TP -+\fB\-recvtext\fR -+str When cut text is received from the VNC server, -+ssvncviewer will set both the X PRIMARY and the -+X CLIPBOARD local selections. To control which -+is set, specify 'str' as 'primary', 'clipboard', -+or 'both' (the default.) -+.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\-mslogon\fR \fIuser\fR -+Use Windows MS Logon to an UltraVNC server. Supply the -+username or "1" to be prompted. The default is to -+autodetect the UltraVNC MS Logon server and prompt for -+the username and password. -+ -+IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman -+exchange is very weak and can be brute forced to recover -+your username and password in a few seconds of CPU -+time. To be safe, be sure to use an additional encrypted -+tunnel (e.g. SSL or SSH) for the entire VNC session. -+.TP -+\fB\-chatonly\fR -+Try to be a client that only does UltraVNC text chat. This -+mode is used by x11vnc to present a chat window on the physical -+X11 console (i.e. to chat with the person at the display). -+.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\-noipv6\fR -+Disable all IPv6 sockets. Same as VNCVIEWER_NO_IPV6=1. -+.TP -+\fB\-noipv4\fR -+Disable all IPv4 sockets. Same as VNCVIEWER_NO_IPV4=1. -+.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\-pipeline\fR -+Like TurboVNC, request the next framebuffer update as soon -+as possible instead of waiting until the end of the current -+framebuffer update coming in. Helps 'pipeline' the updates. -+This is currently the default, use \fB-nopipeline\fR to disable. -+.TP -+\fB\-appshare\fR -+Enable features for use with x11vnc's \fB\-appshare\fR mode where -+instead of sharing the full desktop only the application's -+windows are shared. Viewer multilisten mode is used to -+create the multiple windows: \fB\-multilisten\fR is implied. -+See 'x11vnc \fB\-appshare\fR \fB\-help\fR' more information on the mode. -+Features enabled in the viewer under \fB\-appshare\fR are: -+Minimum extra text in the title, auto \fB\-ycrop\fR is disabled, -+x11vnc \fB\-remote_prefix\fR X11VNC_APPSHARE_CMD: message channel, -+x11vnc initial window position hints. See also Escape Keys -+below for additional key and mouse bindings. -+.TP -+\fB\-escape \fR\fIstr\fR -+This sets the 'Escape Keys' modifier sequence and enables -+escape keys mode. When the modifier keys escape sequence -+is held down, the next keystroke is interpreted locally -+to perform a special action instead of being sent to the -+remote VNC server. -+ -+Use '\fB\-escape\fR default' for the default modifier sequence. -+(Unix: Alt_L,Super_L and MacOSX: Control_L,Meta_L) -+ -+Here are the 'Escape Keys: Help+Set' instructions from the Popup: -+ -+Escape Keys: Enter a comma separated list of modifier keys to be the 'escape -+sequence'. When these keys are held down, the next keystroke is -+interpreted locally to invoke a special action instead of being sent to -+the remote VNC server. In other words, a set of 'Hot Keys'. -+ -+Here is the list of local key mappings to special actions: -+ -+r: refresh desktop b: toggle bell c: toggle full-color -+ -+f: file transfer x: x11cursor z: toggle Tight/ZRLE -+ -+l: full screen g: graball e: escape keys dialog -+ -+s: scale dialog +: scale up (=) -: scale down (_) -+ -+t: text chat a: alphablend cursor -+ -+V: toggle viewonly Q: quit viewer 123456: UltraVNC scale 1/n -+ -+Arrow keys: pan the viewport about 10% for each keypress. -+ -+PageUp/PageDown: pan the viewport by a screenful vertically. -+ -+Home/End: pan the viewport by a screenful horizontally. -+ -+KeyPad Arrows: pan the viewport by 1 pixel for each keypress. -+ -+Dragging the Mouse with Button1 pressed also pans the viewport. -+ -+Clicking Mouse Button3 brings up the Popup Menu. -+ -+The above mappings are \fBalways\fR active in ViewOnly mode, unless you set -+the Escape Keys value to 'never'. -+ -+x11vnc -appshare hot-keys: x11vnc has a simple application sharing mode -+that enables the viewer-side to move, resize, or raise the remote toplevel -+windows. To enable it, hold down Shift + the Escape Keys and press these: -+ -+Arrow keys: move the remote window around in its desktop. -+ -+PageUp/PageDn/Home/End: resize the remote window. -+ -++/-: raise or lower the remote window. -+ -+M or Button1 move win to local position; D or Button3: delete remote win. -+ -+If the Escape Keys value below is set to 'default' then a default list of -+of modifier keys is used. For Unix it is: Alt_L,Super_L and for MacOSX it -+is Control_L,Meta_L. Note: the Super_L key usually has a Windows(TM) Flag -+on it. Also note the _L and _R mean the key is on the LEFT or RIGHT side -+of the keyboard. -+ -+On Unix the default is Alt and Windows keys on Left side of keyboard. -+On MacOSX the default is Control and Command keys on Left side of keyboard. -+ -+Example: Press and hold the Alt and Windows keys on the LEFT side of the -+keyboard and then press 'c' to toggle the full-color state. Or press 't' -+to toggle the ultravnc Text Chat window, etc. -+ -+To use something besides the default, supply a comma separated list (or a -+single one) from: Shift_L Shift_R Control_L Control_R Alt_L Alt_R Meta_L -+Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch. -+.TP -+\fB New Popup actions:\fR -+ -+ ViewOnly: ~ -viewonly -+ Disable Bell: ~ -nobell -+ Cursor Shape: ~ -nocursorshape -+ X11 Cursor: ~ -x11cursor -+ Cursor Alphablend: ~ -alpha -+ Toggle Tight/Hextile: ~ -encodings hextile... -+ Toggle Tight/ZRLE: ~ -encodings zrle... -+ Toggle ZRLE/ZYWRLE: ~ -encodings zywrle... -+ Quality Level ~ -quality (both Tight and ZYWRLE) -+ Compress Level ~ -compresslevel -+ Disable JPEG: ~ -nojpeg (Tight) -+ Pipeline Updates ~ -pipeline -+ -+ Full Color as many colors as local screen allows. -+ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only. -+ 16 bit color (BGR565) ~ -16bpp / -bgr565 -+ 8 bit color (BGR233) ~ -bgr233 -+ 256 colors ~ -bgr233 default # of colors. -+ 64 colors ~ -bgr222 / -use64 -+ 8 colors ~ -bgr111 / -use8 -+ Scale Viewer ~ -scale -+ Escape Keys: Toggle ~ -escape -+ Escape Keys: Help+Set ~ -escape -+ Set Y Crop (y-max) ~ -ycrop -+ Set Scrollbar Width ~ -sbwidth -+ XGrabServer ~ -graball -+ -+ 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 and view a single window. -+ (select then 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. -+ -+ Send Clipboard not Primary ~ -sendclipboard -+ Send Selection Every time ~ -sendalways -+ -+.SH ENCODINGS -+The server supplies information in whatever format is desired by the -+client, in order to make the client as easy as possible to implement. -+If the client represents itself as able to use multiple formats, the -+server will choose one. -+ -+.I Pixel format -+refers to the representation of an individual pixel. The most common -+formats are 24 and 16 bit "true\-color" values, and 8\-bit "color map" -+representations, where an arbitrary map converts the color number to -+RGB values. -+ -+.I Encoding -+refers to how a rectangle of pixels are sent (all pixel information in -+VNC is sent as rectangles). All rectangles come with a header giving -+the location and size of the rectangle and an encoding type used by -+the data which follows. These types are listed below. -+.TP -+.B Raw -+The raw encoding simply sends width*height pixel values. All clients -+are required to support this encoding type. Raw is also the fastest -+when the server and viewer are on the same machine, as the connection -+speed is essentially infinite and raw encoding minimizes processing -+time. -+.TP -+.B CopyRect -+The Copy Rectangle encoding is efficient when something is being -+moved; the only data sent is the location of a rectangle from which -+data should be copied to the current location. Copyrect could also be -+used to efficiently transmit a repeated pattern. -+.TP -+.B RRE -+The Rise\-and\-Run\-length\-Encoding is basically a 2D version of -+run\-length encoding (RLE). In this encoding, a sequence of identical -+pixels are compressed to a single value and repeat count. In VNC, this -+is implemented with a background color, and then specifications of an -+arbitrary number of subrectangles and color for each. This is an -+efficient encoding for large blocks of constant color. -+.TP -+.B CoRRE -+This is a minor variation on RRE, using a maximum of 255x255 pixel -+rectangles. This allows for single\-byte values to be used, reducing -+packet size. This is in general more efficient, because the savings -+from sending 1\-byte values generally outweighs the losses from the -+(relatively rare) cases where very large regions are painted the same -+color. -+.TP -+.B Hextile -+Here, rectangles are split up in to 16x16 tiles, which are sent in a -+predetermined order. The data within the tiles is sent either raw or -+as a variant on RRE. Hextile encoding is usually the best choice for -+using in high\-speed network environments (e.g. Ethernet local\-area -+networks). -+.TP -+.B Zlib -+Zlib is a very simple encoding that uses zlib library to compress raw -+pixel data. This encoding achieves good compression, but consumes a -+lot of CPU time. Support for this encoding is provided for -+compatibility with VNC servers that might not understand Tight -+encoding which is more efficient than Zlib in nearly all real\-life -+situations. -+.TP -+.B Tight -+Like Zlib encoding, Tight encoding uses zlib library to compress the -+pixel data, but it pre\-processes data to maximize compression ratios, -+and to minimize CPU usage on compression. Also, JPEG compression may -+be used to encode color\-rich screen areas (see the description of -+\-quality and \-nojpeg options above). Tight encoding is usually the -+best choice for low\-bandwidth network environments (e.g. slow modem -+connections). -+.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: -+.TP -+.B shareDesktop -+Equivalent of \fB\-shared\fR/\fB\-noshared\fR options. Default true. -+.TP -+.B viewOnly -+Equivalent of \fB\-viewonly\fR option. Default false. -+.TP -+.B fullScreen -+Equivalent of \fB\-fullscreen\fR option. Default false. -+.TP -+.B grabKeyboard -+Grab keyboard in full-screen mode. This can help to solve problems -+with losing keyboard focus. Default false. -+.TP -+.B raiseOnBeep -+Equivalent of \fB\-noraiseonbeep\fR option, when set to false. Default -+true. -+.TP -+.B passwordFile -+Equivalent of \fB\-passwd\fR option. -+.TP -+.B userLogin -+Equivalent of \fB\-user\fR option. -+.TP -+.B passwordDialog -+Whether to use a dialog box to get the password (true) or get it from -+the tty (false). Irrelevant if \fBpasswordFile\fR is set. Default -+false. -+.TP -+.B encodings -+Equivalent of \fB\-encodings\fR option. -+.TP -+.B compressLevel -+Equivalent of \fB\-compresslevel\fR option (TightVNC\-specific). -+.TP -+.B qualityLevel -+Equivalent of \fB\-quality\fR option (TightVNC\-specific). -+.TP -+.B enableJPEG -+Equivalent of \fB\-nojpeg\fR option, when set to false. Default true. -+.TP -+.B useRemoteCursor -+Equivalent of \fB\-nocursorshape\fR option, when set to false -+(TightVNC\-specific). Default true. -+.TP -+.B useBGR233 -+Equivalent of \fB\-bgr233\fR option. Default false. -+.TP -+.B nColours -+When using BGR233, try to allocate this many "exact" colors from the -+BGR233 color cube. When using a shared colormap, setting this resource -+lower leaves more colors for other X clients. Irrelevant when using -+truecolor. Default is 256 (i.e. all of them). -+.TP -+.B useSharedColours -+If the number of "exact" BGR233 colors successfully allocated is less -+than 256 then the rest are filled in using the "nearest" colors -+available. This resource says whether to only use the "exact" BGR233 -+colors for this purpose, or whether to use other clients' "shared" -+colors as well. Default true (i.e. use other clients' colors). -+.TP -+.B forceOwnCmap -+Equivalent of \fB\-owncmap\fR option. Default false. -+.TP -+.B forceTrueColour -+Equivalent of \fB\-truecolour\fR option. Default false. -+.TP -+.B requestedDepth -+Equivalent of \fB\-depth\fR option. -+.TP -+.B useSharedMemory -+Use MIT shared memory extension if on the same machine as the X -+server. Default true. -+.TP -+.B wmDecorationWidth, wmDecorationHeight -+The total width and height taken up by window manager decorations. -+This is used to calculate the maximum size of the VNC viewer window. -+Default is width 4, height 24. -+.TP -+.B bumpScrollTime, bumpScrollPixels -+When in full screen mode and the VNC desktop is bigger than the X -+display, scrolling happens whenever the mouse hits the edge of the -+screen. The maximum speed of scrolling is bumpScrollPixels pixels -+every bumpScrollTime milliseconds. The actual speed of scrolling will -+be slower than this, of course, depending on how fast your machine is. -+Default 20 pixels every 25 milliseconds. -+.TP -+.B popupButtonCount -+The number of buttons in the popup window. See the README file for -+more information on how to customize the buttons. -+.TP -+.B debug -+For debugging. Default false. -+.TP -+.B rawDelay, copyRectDelay -+For debugging, see the README file for details. Default 0 (off). -+.SH ENVIRONMENT -+When started with the \fB\-via\fR option, vncviewer reads the -+\fBVNC_VIA_CMD\fR environment variable, expands patterns beginning -+with the "%" character, and executes result as a command assuming that -+it would create TCP tunnel that should be used for VNC connection. If -+not set, this environment variable defaults to "/usr/bin/ssh -f -L -+%L:%H:%R %G sleep 20". -+ -+The following patterns are recognized in the \fBVNC_VIA_CMD\fR (note -+that all the patterns %G, %H, %L and %R must be present in the command -+template): -+.TP -+.B %% -+A literal "%"; -+.TP -+.B %G -+gateway host name; -+.TP -+.B %H -+remote VNC host name, as known to the gateway; -+.TP -+.B %L -+local TCP port number; -+.TP -+.B %R -+remote TCP port number. -+.SH SEE ALSO -+\fBvncserver\fR(1), \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 -+participated in development, testing and support. Karl J. Runge -+added all of the SSVNC related features and improvements. -+ -+\fBMan page authors:\fR -+.br -+Marcus Brinkmann <Marcus.Brinkmann@ruhr-uni-bochum.de>, -+.br -+Terran Melconian <terran@consistent.org>, -+.br -+Tim Waugh <twaugh@redhat.com>, -+.br -+Constantin Kaplinsky <const@ce.cctpu.edu.ru> -+.br -+Karl J. Runge <runge@karlrunge.com> -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 2010-04-18 12:43:47.000000000 -0400 -@@ -22,6 +22,8 @@ - */ - - #include "vncviewer.h" -+#include <ctype.h> -+#include <X11/Xaw/Toggle.h> - - char *programName; - XtAppContext appContext; -@@ -29,11 +31,274 @@ - - Widget toplevel; - -+extern void raiseme(int force); -+extern void CreateChat(void); -+ -+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++; -+ } -+} -+ -+void min_title(void) { -+ char *q; -+ int k; -+ -+ k = 0; -+ while (fallback_resources[k] != NULL) { -+ q = strstr(fallback_resources[k], "Ssvnc.title: "); -+ if (q) { -+ fallback_resources[k] = strdup("Ssvnc.title: %s"); -+ } -+ k++; -+ } -+} -+ -+#include <sys/types.h> -+#include <sys/stat.h> -+#include <unistd.h> -+ -+void unixpw(char *instr, int vencrypt_plain) { -+ char *str, *q, *infile = NULL; -+ FILE *in; -+ int i, rmfile = 0; -+ struct stat sb; -+ int N = 99; -+ char username[100], passwd[100]; -+ static int did = 0; -+ -+ if (did) { -+ return; -+ } -+ did = 1; -+ -+ 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; -+ if (!use_tty()) { -+ char *u; -+ fprintf(stderr, "\nEnter Unix Username and Password in the popups.\n"); -+ u = DoUserDialog(); -+ if (strlen(u) >= 100) { -+ exit(1); -+ } -+ sprintf(username, u); -+ p = DoPasswordDialog(); -+ } else { -+ raiseme(1); -+ 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; -+ if (!use_tty()) { -+ fprintf(stderr, "\nEnter unixuser@unixpasswd in the popup.\n"); -+ p = DoPasswordDialog(); -+ } else { -+ raiseme(1); -+ 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 (vencrypt_plain) { -+ CARD32 ulen, plen; -+ char *q; -+ -+ q = strrchr(username, '\n'); -+ if (q) *q = '\0'; -+ q = strrchr(passwd, '\n'); -+ if (q) *q = '\0'; -+ -+ ulen = Swap32IfLE((CARD32)strlen(username)); -+ plen = Swap32IfLE((CARD32)strlen(passwd)); -+ -+ if (!WriteExact(rfbsock, (char *)&ulen, 4) || -+ !WriteExact(rfbsock, (char *)&plen, 4)) { -+ return; -+ } -+ -+ if (!WriteExact(rfbsock, username, strlen(username)) || -+ !WriteExact(rfbsock, passwd, strlen(passwd))) { -+ return; -+ } -+ return; -+ } -+ -+ -+ 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); -+} -+ -+static void chat_window_only(void) { -+ if (appData.chatOnly) { -+ static double last_time = 0.0; -+ if (dnow() > last_time + 1.5) { -+ XSync(dpy, False); -+ XUnmapWindow(dpy, XtWindow(toplevel)); -+ } -+ } -+} -+ -+int saw_appshare = 0; -+ - int - main(int argc, char **argv) - { -- int i; -- programName = argv[0]; -+ int i, save_sbw, saw_listen = 0; -+ char *pw_loc = NULL; -+ programName = argv[0]; -+ -+ if (strrchr(programName, '/') != NULL) { -+ programName = strrchr(programName, '/') + 1; -+ } -+ -+ for (i = 1; i < argc; i++) { -+ if (!strcmp(argv[i], "-env")) { -+ if (i+1 < argc) { -+ char *estr = argv[i+1]; -+ if (strchr(estr, '=')) { -+ putenv(estr); -+ } -+ } -+ } -+ if (!strcmp(argv[i], "-noipv4")) { -+ putenv("VNCVIEWER_NO_IPV4=1"); -+ } -+ if (!strcmp(argv[i], "-noipv6")) { -+ putenv("VNCVIEWER_NO_IPV6=1"); -+ } -+ } -+ if (getenv("VNCVIEWER_NO_IPV4")) { -+ appData.noipv4 = True; -+ } -+ if (getenv("VNCVIEWER_NO_IPV6")) { -+ appData.noipv6 = True; -+ } - - /* 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 +310,1744 @@ - 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], "-appshare")) { -+ putenv("SSVNC_MULTIPLE_LISTEN=1"); -+ fprintf(stderr, "Enabling -multilisten mode for 'x11vnc -appshare' usage.\n\n"); -+ saw_appshare = 1; -+ } -+ if (!strcmp(argv[i], "-multilisten")) { -+ putenv("SSVNC_MULTIPLE_LISTEN=1"); -+ saw_listen = 2; -+ } -+ if (!strcmp(argv[i], "-listen")) { -+ saw_listen = 1; -+ } -+ if (!strcmp(argv[i], "-acceptpopup")) { -+ putenv("SSVNC_ACCEPT_POPUP=1"); -+ } -+ if (!strcmp(argv[i], "-acceptpopupsc")) { -+ putenv("SSVNC_ACCEPT_POPUP_SC=1"); -+ } -+ if (strstr(argv[i], " pw=") != NULL) { -+ pw_loc = strstr(argv[i], " pw=") + 1; -+ } -+ } -+ -+ for (i = 1; i < argc; i++) { -+ if (!strcmp(argv[i], "-appshare") && !saw_listen) { -+ listenForIncomingConnections(&argc, argv, i); -+ break; -+ } -+ if (!strcmp(argv[i], "-multilisten")) { -+ listenForIncomingConnections(&argc, argv, i); -+ break; -+ } -+ if (!strcmp(argv[i], "-listen")) { -+ listenForIncomingConnections(&argc, argv, i); -+ break; -+ } -+ if (!strcmp(argv[i], "-tunnel") || !strcmp(argv[i], "-via")) { -+ if (!createTunnel(&argc, argv, i)) { -+ exit(1); -+ } -+ break; -+ } -+ if (!strcmp(argv[i], "-printres") || !strcmp(argv[i], "-res")) { -+ 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); -+ if (saw_appshare || getenv("VNCVIEWER_MIN_TITLE")) { -+ min_title(); -+ } -+ 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 (saw_appshare) { -+ appData.appShare = True; -+ } -+ -+ if (save_sbw) { -+ appData.sbWidth = save_sbw; -+ } -+ -+ if (appData.chatOnly) { -+ appData.encodingsString = "raw hextile"; -+ } -+ -+ if (pw_loc != NULL) { -+ char *q = pw_loc; -+ while (*q != '\0' && !isspace(*q)) { -+ *q = ' '; -+ q++; -+ } -+ } - - /* 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 >= (int) 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()) { -+ Cleanup(); -+ exit(1); -+ } -+ if (appData.unixPW != NULL) { -+ unixpw(appData.unixPW, 0); -+ } else if (getenv("SSVNC_UNIXPW")) { -+ unixpw(getenv("SSVNC_UNIXPW"), 0); -+ } - - /* 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(); -+ CreateTurboVNC(); -+ 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(); -+ -+ if (appData.chatOnly) { -+ chat_window_only(); -+ ToggleTextChat(0, NULL, NULL, NULL); -+ } - - /* 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; -+ } -+ if (appData.chatOnly) { -+ chat_window_only(); -+ } -+ } -+ -+ 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; -+double 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(); -+ if (w || ev || params || num_params) {} -+} -+ -+ -+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(); -+ if (w || ev || params || num_params) {} -+} -+ -+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(); -+ if (w || ev || params || num_params) {} -+} -+ -+void -+ToggleXGrab(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.grabAll) { -+ appData.grabAll = False; -+ } else { -+ appData.grabAll = True; -+ } -+ fprintf(stderr, "ToggleXGrab, current=%d\n", appData.grabAll); -+ /* always ungrab to be sure, fullscreen will handle the rest */ -+ XUngrabServer(dpy); -+ if (w || ev || params || num_params) {} -+} -+ -+void -+ToggleEscapeActive(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.escapeActive) { -+ appData.escapeActive = False; -+ } else { -+ appData.escapeActive = True; -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+/* -+ * 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(); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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(); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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(); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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(); -+ if (w || ev || params || num_params) {} -+} -+ -+/* -+ * 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(); -+ if (w || ev || params || num_params) {} -+} -+ -+/* -+ * ToggleTightZRLE -+ */ -+ -+static Bool usingZRLE = False; -+static Bool usingZYWRLE = False; -+static Bool usingHextile = 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(); -+ usingHextile = False; -+ 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(); -+ if (w || ev || params || num_params) {} -+} -+ -+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; -+ usingHextile = False; -+ 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(); -+ if (w || ev || params || num_params) {} -+} -+ -+void -+ToggleTightHextile(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ char prefTight[] = "copyrect tight zrle zywrle zlib hextile corre rre raw"; -+ char prefHextile[] = "copyrect hextile tight zrle zywrle zlib corre rre raw"; -+ init_format_change(); -+ usingZRLE = False; -+ usingZYWRLE = False; -+ if (! appData.encodingsString) { -+ appDataNew.encodingsString = strdup(prefHextile); -+ usingHextile = True; -+ fprintf(stderr, "prefer: Hextile\n"); -+ } else { -+ char *t, *z; -+ static int first = 1; -+ t = strstr(appData.encodingsString, "tight"); -+ z = strstr(appData.encodingsString, "hextile"); -+ if (first && usingHextile) { -+ appDataNew.encodingsString = strdup(prefTight); -+ usingHextile = False; -+ } else if (! t) { -+ appDataNew.encodingsString = strdup(prefHextile); -+ usingHextile = True; -+ fprintf(stderr, "prefer: Hextile\n"); -+ } else if (! z) { -+ appDataNew.encodingsString = strdup(prefTight); -+ usingHextile = False; -+ skip_maybe_sync = 0; -+ fprintf(stderr, "prefer: Tight\n"); -+ } else { -+ if (t < z) { -+ appDataNew.encodingsString = strdup(prefHextile); -+ usingHextile = True; -+ fprintf(stderr, "prefer: Hextile\n"); -+ } else { -+ appDataNew.encodingsString = strdup(prefTight); -+ usingHextile = False; -+ skip_maybe_sync = 0; -+ fprintf(stderr, "prefer: Tight\n"); -+ } -+ } -+ first = 0; -+ } -+ schedule_format_change(); -+ if (w || ev || params || num_params) {} -+} -+ -+void scale_check_zrle(void) { -+ static int didit = 0; -+ if (didit) { -+ return; -+ } -+ didit = 1; -+ if (getenv("SSVNC_PRESERVE_ENCODING")) { -+ return; -+ } -+ if (!usingZRLE && !usingHextile) { -+ Widget w = 0; -+ fprintf(stderr, "\nSwitching to faster ZRLE encoding in client-side scaling mode.\n"); -+ fprintf(stderr, "Switch back to Tight via the Popup menu if you prefer it.\n\n"); -+ ToggleTightZRLE(w, NULL, NULL, NULL); -+ } -+} -+ -+/* -+ * 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); -+ if (w || ev || params || num_params) {} -+} -+ -+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; -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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"); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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; -+ if (w || ev || params || num_params) {} -+} -+ -+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"); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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(); -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+TogglePipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.pipelineUpdates) { -+ appData.pipelineUpdates= False; -+ fprintf(stderr, "pipeline-update: off\n"); -+ } else { -+ appData.pipelineUpdates = True; -+ fprintf(stderr, "pipeline-update: on\n"); -+ } -+ /* XXX request one to be sure? */ -+ if (w || ev || params || num_params) {} -+} -+ -+void -+ToggleSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.sendClipboard) { -+ appData.sendClipboard= False; -+ fprintf(stderr, "Send CLIPBOARD Selection: off (send PRIMARY instead)\n"); -+ } else { -+ appData.sendClipboard = True; -+ fprintf(stderr, "Send CLIPBOARD Selection: on (do not send PRIMARY)\n"); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+ToggleSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.sendAlways) { -+ appData.sendAlways= False; -+ fprintf(stderr, "Send Selection Always: off\n"); -+ } else { -+ appData.sendAlways = True; -+ fprintf(stderr, "Send Selection Always: on\n"); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+ -+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); -+ } -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void raiseme(int force); -+void AppendChatInput(char *); -+ -+extern void ShowChat(Widget w, XEvent *event, String *params, Cardinal *num_params); -+extern void ShowFile(Widget w, XEvent *event, String *params, Cardinal *num_params); -+extern Bool SendTextChatFinished(void); -+ -+ -+void printChat(char *str, Bool raise) { -+ if (appData.termChat) { -+ if (raise) { -+ raiseme(0); -+ } -+ fprintf(stderr, str); -+ } else { -+ if (raise) { -+ ShowChat(0, 0, 0, 0); -+ } -+ AppendChatInput(str); -+ } -+} -+ -+void -+ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.chatActive) { -+ printChat("\n*SentClose*\n\n", False); -+ SendTextChatClose(); -+ SendTextChatFinished(); -+ HideChat(0, NULL, NULL, NULL); -+ appData.chatActive= False; -+ } else { -+ ShowChat(0, 0, 0, 0); -+ SendTextChatOpen(); -+ if (appData.termChat) { -+ printChat("\n*SentOpen*\n\nSend: ", True); -+ } else { -+ printChat("\n*SentOpen*\n", True); -+ } -+ appData.chatActive = True; -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+extern int filexfer_sock; -+extern pid_t java_helper; -+#define KILLJAVA -+#ifdef KILLJAVA -+#include <signal.h> -+#endif -+ -+void -+ToggleFileXfer(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ static double last_start = 0.0; -+ if (appData.fileActive) { -+#if 0 -+ HideFile(w, ev, params, num_params); -+ appData.fileActive = False; -+#endif -+#ifndef KILLJAVA -+ if (filexfer_sock >= 0) { -+ close(filexfer_sock); -+ } -+#else -+ if (java_helper != 0) { -+ int i; -+ if (dnow() < last_start + 6.0) { -+ fprintf(stderr, "skipping early kill of java helper (less than 5 secs)\n"); -+ } else { -+ 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; -+ last_start = dnow(); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+static int fooHandler(Display *dpy, XErrorEvent *error) { -+ if (dpy || 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 = DoScaleNDialog(); -+ } 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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+extern void rescale_image(void); -+extern void get_scale_values(double *fx, double *fy); -+ -+void -+SetScale(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ char *s; -+ s = DoScaleDialog(); -+ if (s[0] != '\0') { -+#if 0 -+ int w = si.framebufferWidth; -+ int h = si.framebufferHeight; -+#endif -+ double fx, fy; -+ int fs = 0; -+ if (appData.scale != NULL && !strcmp(s, appData.scale)) { -+ return; -+ } -+ -+ if (!strcasecmp(s, "none")) { -+ appData.scale = NULL; -+ } else if (!strcmp(s, "1.0")) { -+ appData.scale = NULL; -+ } else if (!strcmp(s, "1")) { -+ appData.scale = NULL; -+ } else { -+ appData.scale = strdup(s); -+ } -+ if (appData.scale != NULL) { -+ get_scale_values(&fx, &fy); -+ if (fx <= 0.0 || fy <= 0.0) { -+ appData.scale = NULL; -+ return; -+ } -+ } -+ -+ if (appData.fullScreen) { -+ fs = 1; -+ FullScreenOff(); -+ } -+ rescale_image(); -+ if (fs) { -+ FullScreenOn(); -+ } -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+SetEscapeKeys(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ char *s; -+ s = DoEscapeKeysDialog(); -+ fprintf(stderr, "set escape keys: '%s'\n", s); -+ if (s[0] != '\0') { -+ appData.escapeKeys = strdup(s); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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(); -+ } -+} - -- Cleanup(); -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+SetScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (*num_params != 0) { -+ int n = atoi(params[0]); -+ set_server_scale(n); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void UpdateQual(void) { -+ SetFormatAndEncodings(); -+ UpdateSubsampButtons(); -+ UpdateQualSlider(); -+} -+ -+extern double latency; -+ -+static void LosslessRefresh(void) { -+ String encodings = appData.encodingsString; -+ int compressLevel = appData.compressLevel; -+ int qual = appData.qualityLevel; -+ Bool enableJPEG = appData.enableJPEG; -+ appData.qualityLevel = -1; -+ appData.enableJPEG = False; -+ appData.encodingsString = "tight copyrect"; -+ appData.compressLevel = 1; -+ SetFormatAndEncodings(); -+ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False); -+ if (latency > 0.0) { -+ if (0) usleep((int) latency * 1000); -+ } -+ appData.qualityLevel = qual; -+ appData.enableJPEG = enableJPEG; -+ appData.encodingsString = encodings; -+ appData.compressLevel = compressLevel; -+ SetFormatAndEncodings(); -+} -+ -+static void QualHigh(void) { -+ appData.encodingsString = "tight copyrect"; -+ if(appData.useBGR233 || appDataNew.useBGR565) { -+ fprintf(stderr, "WARNING: Cannot enable JPEG because BGR233/BGR565 is enabled.\n"); -+ } else { -+ appData.enableJPEG = True; -+ } -+ appData.subsampLevel = TVNC_1X; -+ appData.qualityLevel = 95; -+ UpdateQual(); -+} -+ -+static void QualMed(void) { -+ appData.encodingsString = "tight copyrect"; -+ if(appData.useBGR233 || appDataNew.useBGR565) { -+ fprintf(stderr, "WARNING: Cannot enable JPEG because BGR233/BGR565 is enabled.\n"); -+ } else { -+ appData.enableJPEG = True; -+ } -+ appData.subsampLevel = TVNC_2X; -+ appData.qualityLevel = 80; -+ UpdateQual(); -+} -+ -+static void QualLow(void) { -+ appData.encodingsString = "tight copyrect"; -+ if(appData.useBGR233 || appDataNew.useBGR565) { -+ fprintf(stderr, "WARNING: Cannot enable JPEG because BGR233/BGR565 is enabled.\n"); -+ } else { -+ appData.enableJPEG = True; -+ } -+ appData.subsampLevel = TVNC_4X; -+ appData.qualityLevel = 30; -+ UpdateQual(); -+} -+ -+static void QualLossless(void) { -+ appData.encodingsString = "tight copyrect"; -+ appData.enableJPEG = False; -+ appData.compressLevel = 0; -+ UpdateQual(); -+} - -- return 0; -+static void QualLosslessWAN(void) { -+ appData.encodingsString = "tight copyrect"; -+ appData.enableJPEG = False; -+ appData.compressLevel = 1; -+ UpdateQual(); -+} -+ -+void -+SetTurboVNC(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (*num_params != 0) { -+ int n = atoi(params[0]); -+ if (0) fprintf(stderr, "SetTurboVNC: %d\n", n); -+ if (n == 1) { -+ QualHigh(); -+ } else if (n == 2) { -+ QualMed(); -+ } else if (n == 3) { -+ QualLow(); -+ } else if (n == 4) { -+ QualLossless(); -+ } else if (n == 5) { -+ QualLosslessWAN(); -+ } else if (n == 6) { -+ appData.subsampLevel = TVNC_1X; -+ UpdateQual(); -+ } else if (n == 7) { -+ appData.subsampLevel = TVNC_2X; -+ UpdateQual(); -+ } else if (n == 8) { -+ appData.subsampLevel = TVNC_4X; -+ UpdateQual(); -+ } else if (n == 9) { -+ appData.subsampLevel = TVNC_GRAY; -+ UpdateQual(); -+ } else if (n == 10) { -+ LosslessRefresh(); -+ } -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+SetQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (*num_params != 0) { -+ int n = atoi(params[0]); -+ set_server_quality(n); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+SetCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (*num_params != 0) { -+ int n = atoi(params[0]); -+ set_server_compress(n); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+GotChatText(char *str, int len) -+{ -+ static char *b = NULL; -+ static int blen = -1; -+ int i, k; -+ 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); -+ } -+ -+ k = 0; -+ for (i=0; i < len; i++) { -+ if (str[i] != '\r') { -+ b[k++] = str[i]; -+ } -+ } -+ b[k] = '\0'; -+ 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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+SetXGrabState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.grabAll) { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+SetEscapeKeysState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (appData.escapeActive) { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+static void init_state(void) { -+ static int first = 1; -+ if (first && appData.encodingsString) { -+ char *t, *z, *y, *h; -+ char *str = appData.encodingsString; -+ int len = strlen(str); -+ -+ t = strstr(str, "tight"); -+ z = strstr(str, "zrle"); -+ y = strstr(str, "zywrle"); -+ h = strstr(str, "hextile"); -+ -+ if (!t) t = str + len; -+ if (!z) z = str + len; -+ if (!y) y = str + len; -+ if (!h) h = str + len; -+ -+ usingZRLE = False; -+ usingZYWRLE = False; -+ usingHextile = False; -+ -+ if (t < z && t < y && t < h) { -+ ; -+ } else if (z < t && z < y && z < h) { -+ usingZRLE = True; -+ } else if (y < t && y < z && y < h) { -+ usingZYWRLE = True; -+ usingZRLE = True; -+ } else if (h < t && h < z && h < y) { -+ usingHextile = True; -+ } -+ } -+ first = 0; -+ -+} -+ -+void -+SetZRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ init_state(); -+ if (usingZRLE) { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+SetHextileState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ init_state(); -+ if (usingHextile) { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+SetZYWRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ init_state(); -+ if (usingZYWRLE) { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+SetPipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (!appData.pipelineUpdates) { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+SetSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (!appData.sendClipboard) { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+void -+SetSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params) -+{ -+ if (!appData.sendAlways) { -+ XtVaSetValues(w, XtNstate, False, NULL); -+ } else { -+ XtVaSetValues(w, XtNstate, True, NULL); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} -+} -+ -+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); -+ } -+ if (w || ev || params || num_params) {} - } -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 2010-04-17 22:29:42.000000000 -0400 -@@ -28,6 +28,7 @@ - #include <string.h> - #include <sys/time.h> - #include <sys/types.h> -+#include <sys/stat.h> - #include <unistd.h> - #include <pwd.h> - #include <X11/IntrinsicP.h> -@@ -51,7 +52,13 @@ - (((l) & 0x0000ff00) << 8) | \ - (((l) & 0x000000ff) << 24)) : (l)) - --#define MAX_ENCODINGS 20 -+#define Swap32IfBE(l) \ -+ (*(char *)&endianTest ? (l) : ((((l) & 0xff000000) >> 24) | \ -+ (((l) & 0x00ff0000) >> 8) | \ -+ (((l) & 0x0000ff00) << 8) | \ -+ (((l) & 0x000000ff) << 24)) ) -+ -+#define MAX_ENCODINGS 24 - - #define FLASH_PORT_OFFSET 5400 - #define LISTEN_PORT_OFFSET 5500 -@@ -64,60 +71,133 @@ - #define DEFAULT_VIA_CMD \ - (DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20") - -+#define TVNC_SAMPOPT 4 -+enum {TVNC_1X=0, TVNC_4X, TVNC_2X, TVNC_GRAY}; - --/* 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; -+#if 0 -+static const char *subsampLevel2str[TVNC_SAMPOPT] = { -+ "1X", "4X", "2X", "Gray" -+}; -+#endif -+#ifdef TURBOVNC -+#define rfbTightNoZlib 0x0A -+#define rfbTurboVncVendor "TRBO" -+#define rfbJpegQualityLevel1 0xFFFFFE01 -+#define rfbJpegQualityLevel100 0xFFFFFE64 -+#define rfbJpegSubsamp1X 0xFFFFFD00 -+#define rfbJpegSubsamp4X 0xFFFFFD01 -+#define rfbJpegSubsamp2X 0xFFFFFD02 -+#define rfbJpegSubsampGray 0xFFFFFD03 -+#endif -+ -+/* for debugging width, height, etc */ -+#if 0 -+#define XtVaSetValues printf("%s:%d\n", __FILE__, __LINE__); XtVaSetValues -+#endif - -- Bool debug; - -- int popupButtonCount; -+/* argsresources.c */ - -- int bumpScrollTime; -- int bumpScrollPixels; -+typedef struct { -+ 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 useXserverBackingStore; -+ Bool overrideRedir; -+ Bool popupFix; -+ -+ Bool useShm; -+ Bool termChat; -+ -+ int wmDecorationWidth; -+ int wmDecorationHeight; -+ -+ char *userLogin; -+ char *unixPW; -+ char *msLogon; -+ char *repeaterUltra; -+ Bool ultraDSM; -+ Bool acceptPopup; -+ char *rfbVersion; -+ -+ char *passwordFile; -+ Bool passwordDialog; -+ Bool notty; -+ -+ 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 chatOnly; -+ Bool fileActive; -+ -+ char *scale; -+ char *escapeKeys; -+ Bool appShare; -+ Bool escapeActive; -+ Bool pipelineUpdates; -+ -+ Bool sendClipboard; -+ Bool sendAlways; -+ char *recvText; -+ -+ /* only for turbovnc mode */ -+ String subsampString; -+ int subsampLevel; -+ Bool doubleBuffer; - -- int compressLevel; -- int qualityLevel; -- Bool enableJPEG; -- Bool useRemoteCursor; -- Bool useX11Cursor; -- Bool autoPass; -+ Bool noipv4; -+ Bool noipv6; - - } AppData; - - extern AppData appData; -+extern AppData appDataNew; - - extern char *fallback_resources[]; - extern char vncServerHost[]; - extern int vncServerPort; - extern Bool listenSpecified; -+extern pid_t listenParent; - extern int listenPort, flashPort; - - extern XrmOptionDescRec cmdLineOptions[]; -@@ -130,10 +210,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(); - -@@ -155,15 +236,60 @@ - extern GC srcGC, dstGC; - extern Dimension dpyWidth, dpyHeight; - -+extern int appshare_0_hint; -+extern int appshare_x_hint; -+extern int appshare_y_hint; -+ - 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, int solid); -+extern void copy_rect(int x, int y, int width, int height, int src_x, int src_y); -+ -+extern void releaseAllPressedModifiers(void); -+extern void fs_grab(int check); -+extern void fs_ungrab(int check); -+ - /* dialogs.c */ - -+extern int use_tty(void); -+ -+extern void ScaleDialogDone(Widget w, XEvent *event, String *params, -+ Cardinal *num_params); -+extern char *DoScaleDialog(); -+ -+extern void EscapeDialogDone(Widget w, XEvent *event, String *params, -+ Cardinal *num_params); -+extern char *DoEscapeKeysDialog(); -+ -+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 ScaleNDialogDone(Widget w, XEvent *event, String *params, -+ Cardinal *num_params); -+extern char *DoScaleNDialog(); -+ -+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(); -@@ -171,6 +297,10 @@ - Cardinal *num_params); - extern char *DoPasswordDialog(); - -+extern void UserDialogDone(Widget w, XEvent *event, String *params, -+ Cardinal *num_params); -+extern char *DoUserDialog(); -+ - /* fullscreen.c */ - - extern void ToggleFullScreen(Widget w, XEvent *event, String *params, -@@ -181,6 +311,13 @@ - extern void FullScreenOn(); - extern void FullScreenOff(); - -+extern int net_wm_supported(void); -+ -+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(); -@@ -196,6 +333,8 @@ - Cardinal *num_params); - extern void Quit(Widget w, XEvent *event, String *params, - Cardinal *num_params); -+extern void HideChat(Widget w, XEvent *event, String *params, -+ Cardinal *num_params); - extern void Cleanup(); - - /* popup.c */ -@@ -207,6 +346,29 @@ - Cardinal *num_params); - extern void CreatePopup(); - -+extern void HideScaleN(Widget w, XEvent *event, String *params, -+ Cardinal *num_params); -+extern void CreateScaleN(); -+ -+extern void HideTurboVNC(Widget w, XEvent *event, String *params, -+ Cardinal *num_params); -+extern void CreateTurboVNC(); -+extern void UpdateSubsampButtons(); -+extern void UpdateQualSlider(); -+extern void UpdateQual(); -+ -+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(); -+ -+extern void Noop(Widget w, XEvent *event, String *params, -+ Cardinal *num_params); -+ -+extern int CreateMsg(char *msg, int wait); - /* rfbproto.c */ - - extern int rfbsock; -@@ -229,8 +391,19 @@ - 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); - -+extern double dnow(void); -+ - /* selection.c */ - - extern void InitialiseSelection(); -@@ -241,8 +414,10 @@ - - /* shm.c */ - --extern XImage *CreateShmImage(); -+extern XImage *CreateShmImage(int do_ycrop); - extern void ShmCleanup(); -+extern void ShmDetach(); -+extern Bool UsingShm(); - - /* sockets.c */ - -@@ -252,11 +427,19 @@ - extern Bool WriteExact(int sock, char *buf, int n); - extern int FindFreeTcpPort(void); - extern int ListenAtTcpPort(int port); --extern int ConnectToTcpAddr(unsigned int host, int port); -+extern int ListenAtTcpPort6(int port); -+extern int dotted_ip(char *host, int partial); -+extern int ConnectToTcpAddr(const char *hostname, int port); -+extern int ConnectToUnixSocket(char *file); - extern int AcceptTcpConnection(int listenSock); -+extern int AcceptTcpConnection6(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 char *get_peer_ip(int sock); -+extern char *ip2host(char *ip); - extern Bool SameMachine(int sock); - - /* tunnel.c */ -@@ -271,3 +454,82 @@ - extern XtAppContext appContext; - extern Display* dpy; - extern Widget toplevel; -+ -+extern void GotChatText(char *str, int len); -+extern void unixpw(char *instr, int vencrypt_plain); -+ -+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 ToggleTightHextile(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 TogglePipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void ToggleSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void ToggleSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void ToggleSingleWindow(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void ToggleXGrab(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void ToggleEscapeActive(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void SetEscapeKeys(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 SetScale(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 ShowTurboVNC(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 SetTurboVNC(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 scale_check_zrle(void); -+ -+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 SetHextileState(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 SetPipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void SetSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void SetSendAlways(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); -+extern void SetXGrabState(Widget w, XEvent *ev, String *params, Cardinal *num_params); -+extern void SetEscapeKeysState(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 2010-04-11 23:30:24.000000000 -0400 -@@ -5,38 +5,55 @@ - .\" Copyright (C) 1998 Marcus.Brinkmann@ruhr-uni-bochum.de - .\" Copyright (C) 2000,2001 Red Hat, Inc. - .\" Copyright (C) 2001-2003 Constantin Kaplinsky <const@ce.cctpu.edu.ru> -+.\" Copyright (C) 2006-2010 Karl J. Runge <runge@karlrunge.com> - .\" - .\" 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 "April 2010" "" "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 fd=n -+.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 -@@ -102,13 +119,13 @@ - TightVNC supports several different compression methods to encode - screen updates; this option specifies a set of them to use in order of - preference. Encodings are specified separated with spaces, and must --thus be enclosed in quotes if more than one is specified. Available --encodings, in default order for a remote connection, are "copyrect --tight hextile zlib corre rre raw". For a local connection (to the same --machine), the default order to try is "raw copyrect tight hextile zlib --corre rre". Raw encoding is always assumed as a last option if no --other encoding can be used for some reason. For more information on --encodings, see the section ENCODINGS below. -+thus be enclosed in quotes if more than one is specified. Commas may be used to avoid spaces. -+Available encodings, in default order for a remote connection, are -+"copyrect tight hextile zlib corre rre raw". For a local connection -+(to the same machine), the default order to try is "raw copyrect tight -+hextile zlib corre rre". Raw encoding is always assumed as a last option -+if no other encoding can be used for some reason. For more information -+on encodings, see the section ENCODINGS below. - .TP - \fB\-bgr233\fR - Always use the BGR233 format to encode pixel data. This reduces -@@ -168,6 +185,424 @@ - \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. -+ -+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. -+ -+If the host:port is specified as "fd=n" then it is assumed -+n is an already opened file descriptor to the socket. (i.e -+the parent did fork+exec) -+ -+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\-acceptpopup\fR -+In \fB\-listen\fR (reverse connection listening) mode when -+a reverse VNC connection comes in show a popup asking -+whether to Accept or Reject the connection. The IP -+address of the connecting host is shown. Same as -+setting the env. var. SSVNC_ACCEPT_POPUP=1. -+.TP -+\fB\-acceptpopupsc\fR -+As in \fB\-acceptpopup\fR except assume UltraVNC Single -+Click (SC) server. Retrieve User and ComputerName -+info from UltraVNC Server and display in the Popup. -+.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\-scale\fR \fIstr\fR -+Scale the desktop locally. The string "str" can -+a floating point ratio, e.g. "0.9", or a fraction, -+e.g. "3/4", or WxH, e.g. 1280x1024. Use "fit" -+to fit in the current screen size. Use "auto" to -+fit in the window size. "str" can also be set by -+the env. var. SSVNC_SCALE. -+ -+If you observe mouse trail painting errors, enable -+X11 Cursor mode (either via Popup or \fB\-x11cursor\fR.) -+ -+Note that scaling is done in software and so can be -+slow and requires more memory. Some speedup Tips: -+ -+ZRLE is faster than Tight in this mode. When -+scaling is first detected, the encoding will -+be automatically switched to ZRLE. Use the -+Popup menu if you want to go back to Tight. -+Set SSVNC_PRESERVE_ENCODING=1 to disable this. -+ -+Use a solid background on the remote side. -+(e.g. manually or via x11vnc \fB\-solid\fR ...) -+ -+If the remote server is x11vnc, try client -+side caching: x11vnc \fB\-ncache\fR 10 ... -+.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\-notty\fR -+Try to avoid using the terminal for interactive -+responses: use windows for messages and prompting -+instead. Messages will also be printed to terminal. -+.TP -+\fB\-sendclipboard\fR -+Send the X CLIPBOARD selection (i.e. Ctrl+C, -+Ctrl+V) instead of the X PRIMARY selection (mouse -+select and middle button paste.) -+.TP -+\fB\-sendalways\fR -+Whenever the mouse enters the VNC viewer main -+window, send the selection to the VNC server even if -+it has not changed. This is like the Xt resource -+translation SelectionToVNC(always) -+.TP -+\fB\-recvtext\fR -+str When cut text is received from the VNC server, -+ssvncviewer will set both the X PRIMARY and the -+X CLIPBOARD local selections. To control which -+is set, specify 'str' as 'primary', 'clipboard', -+or 'both' (the default.) -+.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\-mslogon\fR \fIuser\fR -+Use Windows MS Logon to an UltraVNC server. Supply the -+username or "1" to be prompted. The default is to -+autodetect the UltraVNC MS Logon server and prompt for -+the username and password. -+ -+IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman -+exchange is very weak and can be brute forced to recover -+your username and password in a few seconds of CPU -+time. To be safe, be sure to use an additional encrypted -+tunnel (e.g. SSL or SSH) for the entire VNC session. -+.TP -+\fB\-chatonly\fR -+Try to be a client that only does UltraVNC text chat. This -+mode is used by x11vnc to present a chat window on the physical -+X11 console (i.e. to chat with the person at the display). -+.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\-noipv6\fR -+Disable all IPv6 sockets. Same as VNCVIEWER_NO_IPV6=1. -+.TP -+\fB\-noipv4\fR -+Disable all IPv4 sockets. Same as VNCVIEWER_NO_IPV4=1. -+.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\-pipeline\fR -+Like TurboVNC, request the next framebuffer update as soon -+as possible instead of waiting until the end of the current -+framebuffer update coming in. Helps 'pipeline' the updates. -+This is currently the default, use \fB-nopipeline\fR to disable. -+.TP -+\fB\-appshare\fR -+Enable features for use with x11vnc's \fB\-appshare\fR mode where -+instead of sharing the full desktop only the application's -+windows are shared. Viewer multilisten mode is used to -+create the multiple windows: \fB\-multilisten\fR is implied. -+See 'x11vnc \fB\-appshare\fR \fB\-help\fR' more information on the mode. -+Features enabled in the viewer under \fB\-appshare\fR are: -+Minimum extra text in the title, auto \fB\-ycrop\fR is disabled, -+x11vnc \fB\-remote_prefix\fR X11VNC_APPSHARE_CMD: message channel, -+x11vnc initial window position hints. See also Escape Keys -+below for additional key and mouse bindings. -+.TP -+\fB\-escape \fR\fIstr\fR -+This sets the 'Escape Keys' modifier sequence and enables -+escape keys mode. When the modifier keys escape sequence -+is held down, the next keystroke is interpreted locally -+to perform a special action instead of being sent to the -+remote VNC server. -+ -+Use '\fB\-escape\fR default' for the default modifier sequence. -+(Unix: Alt_L,Super_L and MacOSX: Control_L,Meta_L) -+ -+Here are the 'Escape Keys: Help+Set' instructions from the Popup: -+ -+Escape Keys: Enter a comma separated list of modifier keys to be the 'escape -+sequence'. When these keys are held down, the next keystroke is -+interpreted locally to invoke a special action instead of being sent to -+the remote VNC server. In other words, a set of 'Hot Keys'. -+ -+Here is the list of local key mappings to special actions: -+ -+r: refresh desktop b: toggle bell c: toggle full-color -+ -+f: file transfer x: x11cursor z: toggle Tight/ZRLE -+ -+l: full screen g: graball e: escape keys dialog -+ -+s: scale dialog +: scale up (=) -: scale down (_) -+ -+t: text chat a: alphablend cursor -+ -+V: toggle viewonly Q: quit viewer 123456: UltraVNC scale 1/n -+ -+Arrow keys: pan the viewport about 10% for each keypress. -+ -+PageUp/PageDown: pan the viewport by a screenful vertically. -+ -+Home/End: pan the viewport by a screenful horizontally. -+ -+KeyPad Arrows: pan the viewport by 1 pixel for each keypress. -+ -+Dragging the Mouse with Button1 pressed also pans the viewport. -+ -+Clicking Mouse Button3 brings up the Popup Menu. -+ -+The above mappings are \fBalways\fR active in ViewOnly mode, unless you set -+the Escape Keys value to 'never'. -+ -+x11vnc -appshare hot-keys: x11vnc has a simple application sharing mode -+that enables the viewer-side to move, resize, or raise the remote toplevel -+windows. To enable it, hold down Shift + the Escape Keys and press these: -+ -+Arrow keys: move the remote window around in its desktop. -+ -+PageUp/PageDn/Home/End: resize the remote window. -+ -++/-: raise or lower the remote window. -+ -+M or Button1 move win to local position; D or Button3: delete remote win. -+ -+If the Escape Keys value below is set to 'default' then a default list of -+of modifier keys is used. For Unix it is: Alt_L,Super_L and for MacOSX it -+is Control_L,Meta_L. Note: the Super_L key usually has a Windows(TM) Flag -+on it. Also note the _L and _R mean the key is on the LEFT or RIGHT side -+of the keyboard. -+ -+On Unix the default is Alt and Windows keys on Left side of keyboard. -+On MacOSX the default is Control and Command keys on Left side of keyboard. -+ -+Example: Press and hold the Alt and Windows keys on the LEFT side of the -+keyboard and then press 'c' to toggle the full-color state. Or press 't' -+to toggle the ultravnc Text Chat window, etc. -+ -+To use something besides the default, supply a comma separated list (or a -+single one) from: Shift_L Shift_R Control_L Control_R Alt_L Alt_R Meta_L -+Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch. -+.TP -+\fB New Popup actions:\fR -+ -+ ViewOnly: ~ -viewonly -+ Disable Bell: ~ -nobell -+ Cursor Shape: ~ -nocursorshape -+ X11 Cursor: ~ -x11cursor -+ Cursor Alphablend: ~ -alpha -+ Toggle Tight/Hextile: ~ -encodings hextile... -+ Toggle Tight/ZRLE: ~ -encodings zrle... -+ Toggle ZRLE/ZYWRLE: ~ -encodings zywrle... -+ Quality Level ~ -quality (both Tight and ZYWRLE) -+ Compress Level ~ -compresslevel -+ Disable JPEG: ~ -nojpeg (Tight) -+ Pipeline Updates ~ -pipeline -+ -+ Full Color as many colors as local screen allows. -+ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only. -+ 16 bit color (BGR565) ~ -16bpp / -bgr565 -+ 8 bit color (BGR233) ~ -bgr233 -+ 256 colors ~ -bgr233 default # of colors. -+ 64 colors ~ -bgr222 / -use64 -+ 8 colors ~ -bgr111 / -use8 -+ Scale Viewer ~ -scale -+ Escape Keys: Toggle ~ -escape -+ Escape Keys: Help+Set ~ -escape -+ Set Y Crop (y-max) ~ -ycrop -+ Set Scrollbar Width ~ -sbwidth -+ XGrabServer ~ -graball -+ -+ 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 and view a single window. -+ (select then 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. -+ -+ Send Clipboard not Primary ~ -sendclipboard -+ Send Selection Every time ~ -sendalways -+ - .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 +673,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,12 +808,13 @@ - .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 --participated in development, testing and support. -+participated in development, testing and support. Karl J. Runge -+added all of the SSVNC related features and improvements. - - \fBMan page authors:\fR - .br -@@ -380,3 +825,5 @@ - Tim Waugh <twaugh@redhat.com>, - .br - Constantin Kaplinsky <const@ce.cctpu.edu.ru> -+.br -+Karl J. Runge <runge@karlrunge.com> -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 2010-02-25 23:24:28.000000000 -0500 -@@ -0,0 +1,620 @@ -+/* -+ * 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.useXserverBackingStore) { \ -+ 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; j<rh; j+=rfbZRLETileHeight) -+ for(i=0; i<rw; i+=rfbZRLETileWidth) { -+ int subWidth=(i+rfbZRLETileWidth>rw)?rw-i:rfbZRLETileWidth; -+ int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight; -+ int result=HandleZRLETile(buf,remaining,rx+i,ry+j,subWidth,subHeight); -+ -+ if(result<0) { -+ fprintf(stderr, "ZRLE decoding failed (%d)\n",result); -+return True; -+ return False; -+ } -+ -+ buf+=result; -+ remaining-=result; -+ } -+ } -+ else { -+ -+ fprintf(stderr, -+ "zlib inflate returned error: %d, msg: %s\n", -+ inflateResult, -+ decompStream.msg); -+ return False; -+ -+ } -+ -+ return True; -+} -+ -+#if REALBPP!=BPP && defined(UNCOMP) && UNCOMP!=0 -+# if 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 XImage *image_scale; -+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; i<x+w; i++,buffer+=REALBPP/8) { -+# if 0 -+ ((CARDBPP*)frameBuffer)[j+i] = UncompressCPixel(buffer); -+ /* alt */ -+ CARDBPP color = UncompressCPixel(buffer); -+ CopyDataToScreen((char *)&color, i, j/si.framebufferWidth, 1, 1); -+# else -+ ((CARDBPP*)frameBuffer)[m0++] = UncompressCPixel(buffer); -+# endif -+ } -+ } -+ CopyDataToScreen((char *)frameBuffer, x, y, w, h); -+if (0) fprintf(stderr, "cha1: %dx%d+%d+%d\n", w, h, x, y); -+ -+#else -+# if 0 -+ CopyRectangle(buffer, x, y, w, h); -+# else -+ CopyDataToScreen((char *)buffer, x, y, w, h); -+# endif -+ buffer+=w*h*REALBPP/8; -+#endif -+ } -+ break; -+ } -+ case 1: /* solid */ -+ { -+ CARDBPP color = UncompressCPixel(buffer); -+ -+ if(1+REALBPP/8>buffer_length) -+ return -4; -+ -+ if ((BPP == 8 && appData.useBGR233) || (BPP == 16 && appData.useBGR565)) { -+ int m0; -+ for (m0=0; m0 < w*h; m0++) { -+ ((CARDBPP*)frameBuffer)[m0] = color; -+ } -+ CopyDataToScreen((char *)frameBuffer, x, y, w, h); -+ } else { -+ FillRectangle(x, y, w, h, color); -+ } -+if (0) fprintf(stderr, "cha2: %dx%d+%d+%d\n", w, h, x, y); -+ -+ buffer+=REALBPP/8; -+ -+ break; -+ } -+ case 2 ... 127: /* packed Palette */ -+ { -+ CARDBPP palette[16]; -+ int m0, i,j,shift, -+ bpp=(type>4?(type>16?8:4):(type>2?2:1)), -+ mask=(1<<bpp)-1, -+ divider=(8/bpp); -+ -+ if(1+type*REALBPP/8+((w+divider-1)/divider)*h>buffer_length) -+ return -5; -+ -+ /* read palette */ -+ for(i=0; i<type; i++,buffer+=REALBPP/8) -+ palette[i] = UncompressCPixel(buffer); -+ -+ m0 = 0; -+ /* read palettized pixels */ -+ for(j=y*si.framebufferWidth; j<(y+h)*si.framebufferWidth; j+=si.framebufferWidth) { -+ for(i=x,shift=8-bpp; i<x+w; i++) { -+# if 0 -+ ((CARDBPP*)frameBuffer)[j+i] = palette[((*buffer)>>shift)&mask]; -+ /* alt */ -+ CARDBPP color = palette[((*buffer)>>shift)&mask]; -+ CopyDataToScreen((char *)&color, i, j/si.framebufferWidth, 1, 1); -+# else -+ ((CARDBPP*)frameBuffer)[m0++] = palette[((*buffer)>>shift)&mask]; -+# endif -+ shift-=bpp; -+ if(shift<0) { -+ shift=8-bpp; -+ buffer++; -+ } -+ } -+ if(shift<8-bpp) -+ buffer++; -+ } -+ CopyDataToScreen((char *)frameBuffer, x, y, w, h); -+if (0) fprintf(stderr, "cha3: %dx%d+%d+%d\n", w, h, x, y); -+ -+ break; -+ } -+ /* case 17 ... 127: not used, but valid */ -+ case 128: /* plain RLE */ -+ { -+ int m0=0, i=0,j=0; -+ while(j<h) { -+ int color,length; -+ /* read color */ -+ if(buffer+REALBPP/8+1>buffer_end) -+ return -7; -+ color = UncompressCPixel(buffer); -+ buffer+=REALBPP/8; -+ /* read run length */ -+ length=1; -+ while(*buffer==0xff) { -+ if(buffer+1>=buffer_end) -+ return -8; -+ length+=*buffer; -+ buffer++; -+ } -+ length+=*buffer; -+ buffer++; -+ while(j<h && length>0) { -+# if 0 -+ ((CARDBPP*)frameBuffer)[(y+j)*si.framebufferWidth+x+i] = color; -+ /* alt */ -+ CopyDataToScreen((char *)&color, x+i, y+j, 1, 1); -+# else -+ ((CARDBPP*)frameBuffer)[m0++] = color; -+# endif -+ length--; -+ i++; -+ if(i>=w) { -+ i=0; -+ j++; -+ } -+ } -+ if(length>0) -+ fprintf(stderr, "Warning: possible ZRLE corruption\n"); -+ } -+ CopyDataToScreen((char *)frameBuffer, x, y, w, h); -+if (0) fprintf(stderr, "cha4: %dx%d+%d+%d\n", w, h, x, y); -+ -+ break; -+ } -+ case 129: /* unused */ -+ { -+ return -8; -+ } -+ case 130 ... 255: /* palette RLE */ -+ { -+ CARDBPP palette[128]; -+ int m0 = 0, i,j; -+ -+ if(2+(type-128)*REALBPP/8>buffer_length) -+ return -9; -+ -+ /* read palette */ -+ for(i=0; i<type-128; i++,buffer+=REALBPP/8) -+ palette[i] = UncompressCPixel(buffer); -+ /* read palettized pixels */ -+ i=j=0; -+ while(j<h) { -+ int color,length; -+ /* read color */ -+ if(buffer>=buffer_end) -+ return -10; -+ color = palette[(*buffer)&0x7f]; -+ length=1; -+ if(*buffer&0x80) { -+ if(buffer+1>=buffer_end) -+ return -11; -+ buffer++; -+ /* read run length */ -+ while(*buffer==0xff) { -+ if(buffer+1>=buffer_end) -+ return -8; -+ length+=*buffer; -+ buffer++; -+ } -+ length+=*buffer; -+ } -+ buffer++; -+ while(j<h && length>0) { -+# if 0 -+ ((CARDBPP*)frameBuffer)[(y+j)*si.framebufferWidth+x+i] = color; -+ /* alt */ -+ CopyDataToScreen((char *)&color, x+i, y+j, 1, 1); -+# else -+ ((CARDBPP*)frameBuffer)[m0++] = color; -+# endif -+ length--; -+ i++; -+ if(i>=w) { -+ i=0; -+ j++; -+ } -+ } -+ if(length>0) -+ fprintf(stderr, "Warning: possible ZRLE corruption\n"); -+ } -+ CopyDataToScreen((char *)frameBuffer, x, y, w, h); -+if (0) fprintf(stderr, "cha5: %dx%d+%d+%d\n", w, h, x, y); -+ -+ break; -+ } -+ } -+ -+#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; -+ XImage *im = image_scale ? image_scale : image; -+ -+ 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; -+ if (scrWidthInBytes != im->bytes_per_line) scrWidthInBytes = im->bytes_per_line; -+ scr = im->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; -+ if (scrWidthInBytes != im->bytes_per_line) scrWidthInBytes = im->bytes_per_line; -+ scr = im->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 <assert.h> -+ -+/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same -+ but also expands its arguments if they are macros */ -+ -+#ifndef __RFB_CONCAT2E -+#define __RFB_CONCAT2(a,b) a##b -+#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b) -+#endif -+ -+#ifndef __RFB_CONCAT3E -+#define __RFB_CONCAT3(a,b,c) a##b##c -+#define __RFB_CONCAT3E(a,b,c) __RFB_CONCAT3(a,b,c) -+#endif -+ -+#undef END_FIX -+#if ZYWRLE_ENDIAN == ENDIAN_LITTLE -+# define END_FIX LE -+#elif ZYWRLE_ENDIAN == ENDIAN_BIG -+# define END_FIX BE -+#else -+# define END_FIX NE -+#endif -+ -+#ifdef CPIXEL -+#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP) -+#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL) -+#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,CPIXEL,END_FIX) -+#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,CPIXEL,END_FIX) -+#define BPPOUT 24 -+#elif BPP==15 -+#define PIXEL_T __RFB_CONCAT2E(zrle_U,16) -+#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,16) -+#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX) -+#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX) -+#define BPPOUT 16 -+#else -+#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP) -+#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP) -+#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX) -+#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX) -+#define BPPOUT BPP -+#endif -+ -+#ifndef ZRLE_ONCE -+#define ZRLE_ONCE -+ -+static const int bitsPerPackedPixel[] = { -+ 0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 -+}; -+ -+int zywrle_level; -+int zywrleBuf[rfbZRLETileWidth*rfbZRLETileHeight]; -+ -+static zrlePaletteHelper paletteHelper; -+ -+#endif /* ZRLE_ONCE */ -+ -+void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os); -+ -+#if BPP!=8 -+#define ZYWRLE_ENCODE -+#include "zywrletemplate.c" -+#endif -+ -+static void ZRLE_ENCODE (int x, int y, int w, int h, -+ zrleOutStream* os, void* buf -+ EXTRA_ARGS -+ ) -+{ -+ int ty; -+ for (ty = y; ty < y+h; ty += rfbZRLETileHeight) { -+ int tx, th = rfbZRLETileHeight; -+ if (th > y+h-ty) th = y+h-ty; -+ for (tx = x; tx < x+w; tx += rfbZRLETileWidth) { -+ int tw = rfbZRLETileWidth; -+ if (tw > x+w-tx) tw = x+w-tx; -+ -+ GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf); -+ -+ ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, os); -+ } -+ } -+ zrleOutStreamFlush(os); -+} -+ -+ -+void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os) -+{ -+ /* First find the palette and the number of runs */ -+ -+ zrlePaletteHelper *ph; -+ -+ int runs = 0; -+ int singlePixels = 0; -+ -+ rfbBool useRle; -+ rfbBool usePalette; -+ -+ int estimatedBytes; -+ int plainRleBytes; -+ int i; -+ -+ PIXEL_T* ptr = data; -+ PIXEL_T* end = ptr + h * w; -+ *end = ~*(end-1); /* one past the end is different so the while loop ends */ -+ -+ ph = &paletteHelper; -+ zrlePaletteHelperInit(ph); -+ -+ while (ptr < end) { -+ PIXEL_T pix = *ptr; -+ if (*++ptr != pix) { -+ singlePixels++; -+ } else { -+ while (*++ptr == pix) ; -+ runs++; -+ } -+ zrlePaletteHelperInsert(ph, pix); -+ } -+ -+ /* Solid tile is a special case */ -+ -+ if (ph->size == 1) { -+ zrleOutStreamWriteU8(os, 1); -+ zrleOutStreamWRITE_PIXEL(os, ph->palette[0]); -+ return; -+ } -+ -+ /* Try to work out whether to use RLE and/or a palette. We do this by -+ estimating the number of bytes which will be generated and picking the -+ method which results in the fewest bytes. Of course this may not result -+ in the fewest bytes after compression... */ -+ -+ useRle = FALSE; -+ usePalette = FALSE; -+ -+ estimatedBytes = w * h * (BPPOUT/8); /* start assuming raw */ -+ -+#if BPP!=8 -+ if( (zywrle_level>0)&& !(zywrle_level & 0x80) ){ -+ estimatedBytes >>= zywrle_level; -+ } -+#endif -+ -+ plainRleBytes = ((BPPOUT/8)+1) * (runs + singlePixels); -+ -+ if (plainRleBytes < estimatedBytes) { -+ useRle = TRUE; -+ estimatedBytes = plainRleBytes; -+ } -+ -+ if (ph->size < 128) { -+ int paletteRleBytes = (BPPOUT/8) * ph->size + 2 * runs + singlePixels; -+ -+ if (paletteRleBytes < estimatedBytes) { -+ useRle = TRUE; -+ usePalette = TRUE; -+ estimatedBytes = paletteRleBytes; -+ } -+ -+ if (ph->size < 17) { -+ int packedBytes = ((BPPOUT/8) * ph->size + -+ w * h * bitsPerPackedPixel[ph->size-1] / 8); -+ -+ if (packedBytes < estimatedBytes) { -+ useRle = FALSE; -+ usePalette = TRUE; -+ estimatedBytes = packedBytes; -+ } -+ } -+ } -+ -+ if (!usePalette) ph->size = 0; -+ -+ zrleOutStreamWriteU8(os, (useRle ? 128 : 0) | ph->size); -+ -+ for (i = 0; i < ph->size; i++) { -+ zrleOutStreamWRITE_PIXEL(os, ph->palette[i]); -+ } -+ -+ if (useRle) { -+ -+ PIXEL_T* ptr = data; -+ PIXEL_T* end = ptr + w * h; -+ PIXEL_T* runStart; -+ PIXEL_T pix; -+ while (ptr < end) { -+ int len; -+ runStart = ptr; -+ pix = *ptr++; -+ while (*ptr == pix && ptr < end) -+ ptr++; -+ len = ptr - runStart; -+ if (len <= 2 && usePalette) { -+ int index = zrlePaletteHelperLookup(ph, pix); -+ if (len == 2) -+ zrleOutStreamWriteU8(os, index); -+ zrleOutStreamWriteU8(os, index); -+ continue; -+ } -+ if (usePalette) { -+ int index = zrlePaletteHelperLookup(ph, pix); -+ zrleOutStreamWriteU8(os, index | 128); -+ } else { -+ zrleOutStreamWRITE_PIXEL(os, pix); -+ } -+ len -= 1; -+ while (len >= 255) { -+ zrleOutStreamWriteU8(os, 255); -+ len -= 255; -+ } -+ zrleOutStreamWriteU8(os, len); -+ } -+ -+ } else { -+ -+ /* no RLE */ -+ -+ if (usePalette) { -+ int bppp; -+ PIXEL_T* ptr = data; -+ -+ /* packed pixels */ -+ -+ assert (ph->size < 17); -+ -+ bppp = bitsPerPackedPixel[ph->size-1]; -+ -+ for (i = 0; i < h; i++) { -+ zrle_U8 nbits = 0; -+ zrle_U8 byte = 0; -+ -+ PIXEL_T* eol = ptr + w; -+ -+ while (ptr < eol) { -+ PIXEL_T pix = *ptr++; -+ zrle_U8 index = zrlePaletteHelperLookup(ph, pix); -+ byte = (byte << bppp) | index; -+ nbits += bppp; -+ if (nbits >= 8) { -+ zrleOutStreamWriteU8(os, byte); -+ nbits = 0; -+ } -+ } -+ if (nbits > 0) { -+ byte <<= 8 - nbits; -+ zrleOutStreamWriteU8(os, byte); -+ } -+ } -+ } else { -+ -+ /* raw */ -+ -+#if BPP!=8 -+ if( (zywrle_level>0)&& !(zywrle_level & 0x80) ){ -+ ZYWRLE_ANALYZE( data, data, w, h, w, zywrle_level, zywrleBuf ); -+ zywrle_level |= 0x80; -+ ZRLE_ENCODE_TILE( data, w, h, os ); -+ zywrle_level &= 0x7F; -+ }else -+#endif -+ { -+#ifdef CPIXEL -+ PIXEL_T *ptr; -+ for (ptr = data; ptr < data+w*h; ptr++) { -+ zrleOutStreamWRITE_PIXEL(os, *ptr); -+ } -+#else -+ zrleOutStreamWriteBytes(os, (zrle_U8 *)data, w*h*(BPP/8)); -+#endif -+ } -+ } -+ } -+} -+ -+#undef PIXEL_T -+#undef zrleOutStreamWRITE_PIXEL -+#undef ZRLE_ENCODE -+#undef ZRLE_ENCODE_TILE -+#undef ZYWRLE_ENCODE_TILE -+#undef BPPOUT -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrleoutstream.c vnc_unixsrc/vncviewer/zrleoutstream.c ---- vnc_unixsrc.orig/vncviewer/zrleoutstream.c 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/zrleoutstream.c 2005-05-15 10:57:54.000000000 -0400 -@@ -0,0 +1,275 @@ -+/* -+ * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. -+ * Copyright (C) 2003 Sun Microsystems, Inc. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include "zrleoutstream.h" -+#include <stdlib.h> -+ -+#define ZRLE_IN_BUFFER_SIZE 16384 -+#define ZRLE_OUT_BUFFER_SIZE 1024 -+#undef ZRLE_DEBUG -+ -+static rfbBool zrleBufferAlloc(zrleBuffer *buffer, int size) -+{ -+ buffer->ptr = buffer->start = malloc(size); -+ if (buffer->start == NULL) { -+ buffer->end = NULL; -+ return FALSE; -+ } -+ -+ buffer->end = buffer->start + size; -+ -+ return TRUE; -+} -+ -+static void zrleBufferFree(zrleBuffer *buffer) -+{ -+ if (buffer->start) -+ free(buffer->start); -+ buffer->start = buffer->ptr = buffer->end = NULL; -+} -+ -+static rfbBool zrleBufferGrow(zrleBuffer *buffer, int size) -+{ -+ int offset; -+ -+ size += buffer->end - buffer->start; -+ offset = ZRLE_BUFFER_LENGTH (buffer); -+ -+ buffer->start = realloc(buffer->start, size); -+ if (!buffer->start) { -+ return FALSE; -+ } -+ -+ buffer->end = buffer->start + size; -+ buffer->ptr = buffer->start + offset; -+ -+ return TRUE; -+} -+ -+zrleOutStream *zrleOutStreamNew(void) -+{ -+ zrleOutStream *os; -+ -+ os = malloc(sizeof(zrleOutStream)); -+ if (os == NULL) -+ return NULL; -+ -+ if (!zrleBufferAlloc(&os->in, ZRLE_IN_BUFFER_SIZE)) { -+ free(os); -+ return NULL; -+ } -+ -+ if (!zrleBufferAlloc(&os->out, ZRLE_OUT_BUFFER_SIZE)) { -+ zrleBufferFree(&os->in); -+ free(os); -+ return NULL; -+ } -+ -+ os->zs.zalloc = Z_NULL; -+ os->zs.zfree = Z_NULL; -+ os->zs.opaque = Z_NULL; -+ if (deflateInit(&os->zs, Z_DEFAULT_COMPRESSION) != Z_OK) { -+ zrleBufferFree(&os->in); -+ free(os); -+ return NULL; -+ } -+ -+ return os; -+} -+ -+void zrleOutStreamFree (zrleOutStream *os) -+{ -+ deflateEnd(&os->zs); -+ zrleBufferFree(&os->in); -+ zrleBufferFree(&os->out); -+ free(os); -+} -+ -+rfbBool zrleOutStreamFlush(zrleOutStream *os) -+{ -+ os->zs.next_in = os->in.start; -+ os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in); -+ -+#ifdef ZRLE_DEBUG -+ rfbLog("zrleOutStreamFlush: avail_in %d\n", os->zs.avail_in); -+#endif -+ -+ while (os->zs.avail_in != 0) { -+ do { -+ int ret; -+ -+ if (os->out.ptr >= os->out.end && -+ !zrleBufferGrow(&os->out, os->out.end - os->out.start)) { -+ rfbLog("zrleOutStreamFlush: failed to grow output buffer\n"); -+ return FALSE; -+ } -+ -+ os->zs.next_out = os->out.ptr; -+ os->zs.avail_out = os->out.end - os->out.ptr; -+ -+#ifdef ZRLE_DEBUG -+ rfbLog("zrleOutStreamFlush: calling deflate, avail_in %d, avail_out %d\n", -+ os->zs.avail_in, os->zs.avail_out); -+#endif -+ -+ if ((ret = deflate(&os->zs, Z_SYNC_FLUSH)) != Z_OK) { -+ rfbLog("zrleOutStreamFlush: deflate failed with error code %d\n", ret); -+ return FALSE; -+ } -+ -+#ifdef ZRLE_DEBUG -+ rfbLog("zrleOutStreamFlush: after deflate: %d bytes\n", -+ os->zs.next_out - os->out.ptr); -+#endif -+ -+ os->out.ptr = os->zs.next_out; -+ } while (os->zs.avail_out == 0); -+ } -+ -+ os->in.ptr = os->in.start; -+ -+ return TRUE; -+} -+ -+static int zrleOutStreamOverrun(zrleOutStream *os, -+ int size) -+{ -+#ifdef ZRLE_DEBUG -+ rfbLog("zrleOutStreamOverrun\n"); -+#endif -+ -+ while (os->in.end - os->in.ptr < size && os->in.ptr > os->in.start) { -+ os->zs.next_in = os->in.start; -+ os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in); -+ -+ do { -+ int ret; -+ -+ if (os->out.ptr >= os->out.end && -+ !zrleBufferGrow(&os->out, os->out.end - os->out.start)) { -+ rfbLog("zrleOutStreamOverrun: failed to grow output buffer\n"); -+ return FALSE; -+ } -+ -+ os->zs.next_out = os->out.ptr; -+ os->zs.avail_out = os->out.end - os->out.ptr; -+ -+#ifdef ZRLE_DEBUG -+ rfbLog("zrleOutStreamOverrun: calling deflate, avail_in %d, avail_out %d\n", -+ os->zs.avail_in, os->zs.avail_out); -+#endif -+ -+ if ((ret = deflate(&os->zs, 0)) != Z_OK) { -+ rfbLog("zrleOutStreamOverrun: deflate failed with error code %d\n", ret); -+ return 0; -+ } -+ -+#ifdef ZRLE_DEBUG -+ rfbLog("zrleOutStreamOverrun: after deflate: %d bytes\n", -+ os->zs.next_out - os->out.ptr); -+#endif -+ -+ os->out.ptr = os->zs.next_out; -+ } while (os->zs.avail_out == 0); -+ -+ /* output buffer not full */ -+ -+ if (os->zs.avail_in == 0) { -+ os->in.ptr = os->in.start; -+ } else { -+ /* but didn't consume all the data? try shifting what's left to the -+ * start of the buffer. -+ */ -+ rfbLog("zrleOutStreamOverrun: out buf not full, but in data not consumed\n"); -+ memmove(os->in.start, os->zs.next_in, os->in.ptr - os->zs.next_in); -+ os->in.ptr -= os->zs.next_in - os->in.start; -+ } -+ } -+ -+ if (size > os->in.end - os->in.ptr) -+ size = os->in.end - os->in.ptr; -+ -+ return size; -+} -+ -+static int zrleOutStreamCheck(zrleOutStream *os, int size) -+{ -+ if (os->in.ptr + size > os->in.end) { -+ return zrleOutStreamOverrun(os, size); -+ } -+ return size; -+} -+ -+void zrleOutStreamWriteBytes(zrleOutStream *os, -+ const zrle_U8 *data, -+ int length) -+{ -+ const zrle_U8* dataEnd = data + length; -+ while (data < dataEnd) { -+ int n = zrleOutStreamCheck(os, dataEnd - data); -+ memcpy(os->in.ptr, data, n); -+ os->in.ptr += n; -+ data += n; -+ } -+} -+ -+void zrleOutStreamWriteU8(zrleOutStream *os, zrle_U8 u) -+{ -+ zrleOutStreamCheck(os, 1); -+ *os->in.ptr++ = u; -+} -+ -+void zrleOutStreamWriteOpaque8(zrleOutStream *os, zrle_U8 u) -+{ -+ zrleOutStreamCheck(os, 1); -+ *os->in.ptr++ = u; -+} -+ -+void zrleOutStreamWriteOpaque16 (zrleOutStream *os, zrle_U16 u) -+{ -+ zrleOutStreamCheck(os, 2); -+ *os->in.ptr++ = ((zrle_U8*)&u)[0]; -+ *os->in.ptr++ = ((zrle_U8*)&u)[1]; -+} -+ -+void zrleOutStreamWriteOpaque32 (zrleOutStream *os, zrle_U32 u) -+{ -+ zrleOutStreamCheck(os, 4); -+ *os->in.ptr++ = ((zrle_U8*)&u)[0]; -+ *os->in.ptr++ = ((zrle_U8*)&u)[1]; -+ *os->in.ptr++ = ((zrle_U8*)&u)[2]; -+ *os->in.ptr++ = ((zrle_U8*)&u)[3]; -+} -+ -+void zrleOutStreamWriteOpaque24A(zrleOutStream *os, zrle_U32 u) -+{ -+ zrleOutStreamCheck(os, 3); -+ *os->in.ptr++ = ((zrle_U8*)&u)[0]; -+ *os->in.ptr++ = ((zrle_U8*)&u)[1]; -+ *os->in.ptr++ = ((zrle_U8*)&u)[2]; -+} -+ -+void zrleOutStreamWriteOpaque24B(zrleOutStream *os, zrle_U32 u) -+{ -+ zrleOutStreamCheck(os, 3); -+ *os->in.ptr++ = ((zrle_U8*)&u)[1]; -+ *os->in.ptr++ = ((zrle_U8*)&u)[2]; -+ *os->in.ptr++ = ((zrle_U8*)&u)[3]; -+} -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrleoutstream.h vnc_unixsrc/vncviewer/zrleoutstream.h ---- vnc_unixsrc.orig/vncviewer/zrleoutstream.h 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/zrleoutstream.h 2004-05-25 06:05:15.000000000 -0400 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. -+ * Copyright (C) 2003 Sun Microsystems, Inc. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#ifndef __ZRLE_OUT_STREAM_H__ -+#define __ZRLE_OUT_STREAM_H__ -+ -+#include <zlib.h> -+#include "zrletypes.h" -+#include "rfb/rfb.h" -+ -+typedef struct { -+ zrle_U8 *start; -+ zrle_U8 *ptr; -+ zrle_U8 *end; -+} zrleBuffer; -+ -+typedef struct { -+ zrleBuffer in; -+ zrleBuffer out; -+ -+ z_stream zs; -+} zrleOutStream; -+ -+#define ZRLE_BUFFER_LENGTH(b) ((b)->ptr - (b)->start) -+ -+zrleOutStream *zrleOutStreamNew (void); -+void zrleOutStreamFree (zrleOutStream *os); -+rfbBool zrleOutStreamFlush (zrleOutStream *os); -+void zrleOutStreamWriteBytes (zrleOutStream *os, -+ const zrle_U8 *data, -+ int length); -+void zrleOutStreamWriteU8 (zrleOutStream *os, -+ zrle_U8 u); -+void zrleOutStreamWriteOpaque8 (zrleOutStream *os, -+ zrle_U8 u); -+void zrleOutStreamWriteOpaque16 (zrleOutStream *os, -+ zrle_U16 u); -+void zrleOutStreamWriteOpaque32 (zrleOutStream *os, -+ zrle_U32 u); -+void zrleOutStreamWriteOpaque24A(zrleOutStream *os, -+ zrle_U32 u); -+void zrleOutStreamWriteOpaque24B(zrleOutStream *os, -+ zrle_U32 u); -+ -+#endif /* __ZRLE_OUT_STREAM_H__ */ -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrlepalettehelper.c vnc_unixsrc/vncviewer/zrlepalettehelper.c ---- vnc_unixsrc.orig/vncviewer/zrlepalettehelper.c 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/zrlepalettehelper.c 2004-05-25 06:05:15.000000000 -0400 -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. -+ * Copyright (C) 2003 Sun Microsystems, Inc. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#include "zrlepalettehelper.h" -+#include <assert.h> -+#include <string.h> -+ -+#define ZRLE_HASH(pix) (((pix) ^ ((pix) >> 17)) & 4095) -+ -+void zrlePaletteHelperInit(zrlePaletteHelper *helper) -+{ -+ memset(helper->palette, 0, sizeof(helper->palette)); -+ memset(helper->index, 255, sizeof(helper->index)); -+ memset(helper->key, 0, sizeof(helper->key)); -+ helper->size = 0; -+} -+ -+void zrlePaletteHelperInsert(zrlePaletteHelper *helper, zrle_U32 pix) -+{ -+ if (helper->size < ZRLE_PALETTE_MAX_SIZE) { -+ int i = ZRLE_HASH(pix); -+ -+ while (helper->index[i] != 255 && helper->key[i] != pix) -+ i++; -+ if (helper->index[i] != 255) return; -+ -+ helper->index[i] = helper->size; -+ helper->key[i] = pix; -+ helper->palette[helper->size] = pix; -+ } -+ helper->size++; -+} -+ -+int zrlePaletteHelperLookup(zrlePaletteHelper *helper, zrle_U32 pix) -+{ -+ int i = ZRLE_HASH(pix); -+ -+ assert(helper->size <= ZRLE_PALETTE_MAX_SIZE); -+ -+ while (helper->index[i] != 255 && helper->key[i] != pix) -+ i++; -+ if (helper->index[i] != 255) return helper->index[i]; -+ -+ return -1; -+} -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrlepalettehelper.h vnc_unixsrc/vncviewer/zrlepalettehelper.h ---- vnc_unixsrc.orig/vncviewer/zrlepalettehelper.h 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/zrlepalettehelper.h 2004-05-25 06:05:15.000000000 -0400 -@@ -0,0 +1,46 @@ -+/* -+ * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. -+ * Copyright (C) 2003 Sun Microsystems, Inc. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+/* -+ * The PaletteHelper class helps us build up the palette from pixel data by -+ * storing a reverse index using a simple hash-table -+ */ -+ -+#ifndef __ZRLE_PALETTE_HELPER_H__ -+#define __ZRLE_PALETTE_HELPER_H__ -+ -+#include "zrletypes.h" -+ -+#define ZRLE_PALETTE_MAX_SIZE 127 -+ -+typedef struct { -+ zrle_U32 palette[ZRLE_PALETTE_MAX_SIZE]; -+ zrle_U8 index[ZRLE_PALETTE_MAX_SIZE + 4096]; -+ zrle_U32 key[ZRLE_PALETTE_MAX_SIZE + 4096]; -+ int size; -+} zrlePaletteHelper; -+ -+void zrlePaletteHelperInit (zrlePaletteHelper *helper); -+void zrlePaletteHelperInsert(zrlePaletteHelper *helper, -+ zrle_U32 pix); -+int zrlePaletteHelperLookup(zrlePaletteHelper *helper, -+ zrle_U32 pix); -+ -+#endif /* __ZRLE_PALETTE_HELPER_H__ */ -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrletypes.h vnc_unixsrc/vncviewer/zrletypes.h ---- vnc_unixsrc.orig/vncviewer/zrletypes.h 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/zrletypes.h 2004-05-25 06:05:15.000000000 -0400 -@@ -0,0 +1,30 @@ -+/* -+ * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. -+ * -+ * This is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This software is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this software; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, -+ * USA. -+ */ -+ -+#ifndef __ZRLE_TYPES_H__ -+#define __ZRLE_TYPES_H__ -+ -+typedef unsigned char zrle_U8; -+typedef unsigned short zrle_U16; -+typedef unsigned int zrle_U32; -+typedef signed char zrle_S8; -+typedef signed short zrle_S16; -+typedef signed int zrle_S32; -+ -+#endif /* __ZRLE_TYPES_H__ */ -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zywrletemplate.c vnc_unixsrc/vncviewer/zywrletemplate.c ---- vnc_unixsrc.orig/vncviewer/zywrletemplate.c 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/zywrletemplate.c 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)*SkipPixel; -+ end = pX0+(size>>(l+1))*s; -+ s -= 2; -+ ofs = (4<<l)*SkipPixel; -+ while (pX0 < end) { -+ Harr(pX0, pX0+ofs); -+ pX0++; -+ Harr(pX0, pX0+ofs); -+ pX0++; -+ Harr(pX0, pX0+ofs); -+ pX0 += s; -+ } -+} -+#define InvWaveletLevel(d,s,l,pix) WaveletLevel(d,s,l,pix) -+ -+#ifdef ZYWRLE_ENCODE -+# ifndef ZYWRLE_QUANTIZE -+/* Type A:lower bit omitting of EZW style. */ -+static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l) -+{ -+ int r, s; -+ int x, y; -+ int* pH; -+ const unsigned int* pM; -+ -+ pM = &(zywrleParam[level-1][l]); -+ s = 2<<l; -+ for (r = 1; r < 4; r++) { -+ pH = pBuf; -+ if (r & 0x01) -+ pH += s>>1; -+ if (r & 0x02) -+ pH += (s>>1)*width; -+ for (y = 0; y < height / s; y++) { -+ for (x = 0; x < width / s; x++) { -+ /* -+ these are same following code. -+ pH[x] = pH[x] / (~pM[x]+1) * (~pM[x]+1); -+ ( round pH[x] with pM[x] bit ) -+ '&' operator isn't 'round' but is 'floor'. -+ So, we must offset when pH[x] is negative. -+ */ -+ if (((signed char*)pH)[0] & 0x80) -+ ((signed char*)pH)[0] += ~((signed char*)pM)[0]; -+ if (((signed char*)pH)[1] & 0x80) -+ ((signed char*)pH)[1] += ~((signed char*)pM)[1]; -+ if (((signed char*)pH)[2] & 0x80) -+ ((signed char*)pH)[2] += ~((signed char*)pM)[2]; -+ *pH &= *pM; -+ pH += s; -+ } -+ pH += (s-1)*width; -+ } -+ } -+} -+# else -+/* -+ Type B:Non liner quantization filter. -+ -+ Coefficients have Gaussian curve and smaller value which is -+ large part of coefficients isn't more important than larger value. -+ So, I use filter of Non liner quantize/dequantize table. -+ In general, Non liner quantize formula is explained as following. -+ -+ y=f(x) = sign(x)*round( ((abs(x)/(2^7))^ r )* 2^(bo-1) )*2^(8-bo) -+ x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi) -+ ( r:power coefficient bi:effective MSB in input bo:effective MSB in output ) -+ -+ r < 1.0 : Smaller value is more important than larger value. -+ r > 1.0 : Larger value is more important than smaller value. -+ r = 1.0 : Liner quantization which is same with EZW style. -+ -+ r = 0.75 is famous non liner quantization used in MP3 audio codec. -+ In contrast to audio data, larger value is important in wavelet coefficients. -+ So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ). -+ -+ As compared with EZW style liner quantization, this filter tended to be -+ more sharp edge and be more compression rate but be more blocking noise and be less quality. -+ Especially, the surface of graphic objects has distinguishable noise in middle quality mode. -+ -+ We need only quantized-dequantized(filtered) value rather than quantized value itself -+ because all values are packed or palette-lized in later ZRLE section. -+ This lead us not to need to modify client decoder when we change -+ the filtering procedure in future. -+ Client only decodes coefficients given by encoder. -+*/ -+static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l) -+{ -+ int r, s; -+ int x, y; -+ int* pH; -+ const signed char** pM; -+ -+ pM = zywrleParam[level-1][l]; -+ s = 2<<l; -+ for (r = 1; r < 4; r++) { -+ pH = pBuf; -+ if (r & 0x01) -+ pH += s>>1; -+ if (r & 0x02) -+ pH += (s>>1)*width; -+ for (y = 0; y < height / s; y++) { -+ for (x = 0; x < width / s; x++) { -+ ((signed char*)pH)[0] = pM[0][((unsigned char*)pH)[0]]; -+ ((signed char*)pH)[1] = pM[1][((unsigned char*)pH)[1]]; -+ ((signed char*)pH)[2] = pM[2][((unsigned char*)pH)[2]]; -+ pH += s; -+ } -+ pH += (s-1)*width; -+ } -+ } -+} -+# endif -+ -+static InlineX void Wavelet(int* pBuf, int width, int height, int level) -+{ -+ int l, s; -+ int* pTop; -+ int* pEnd; -+ -+ for (l = 0; l < level; l++) { -+ pTop = pBuf; -+ pEnd = pBuf+height*width; -+ s = width<<l; -+ while (pTop < pEnd) { -+ WaveletLevel(pTop, width, l, 1); -+ pTop += s; -+ } -+ pTop = pBuf; -+ pEnd = pBuf+width; -+ s = 1<<l; -+ while (pTop < pEnd) { -+ WaveletLevel(pTop, height,l, width); -+ pTop += s; -+ } -+ FilterWaveletSquare(pBuf, width, height, level, l); -+ } -+} -+#endif -+#ifdef ZYWRLE_DECODE -+static InlineX void InvWavelet(int* pBuf, int width, int height, int level) -+{ -+ int l, s; -+ int* pTop; -+ int* pEnd; -+ -+ for (l = level - 1; l >= 0; l--) { -+ pTop = pBuf; -+ pEnd = pBuf+width; -+ s = 1<<l; -+ while (pTop < pEnd) { -+ InvWaveletLevel(pTop, height,l, width); -+ pTop += s; -+ } -+ pTop = pBuf; -+ pEnd = pBuf+height*width; -+ s = width<<l; -+ while (pTop < pEnd) { -+ InvWaveletLevel(pTop, width, l, 1); -+ pTop += s; -+ } -+ } -+} -+#endif -+ -+/* Load/Save coefficients stuffs. -+ Coefficients manages as 24 bits little-endian pixel. */ -+#define ZYWRLE_LOAD_COEFF(pSrc,R,G,B) { \ -+ R = ((signed char*)pSrc)[2]; \ -+ G = ((signed char*)pSrc)[1]; \ -+ B = ((signed char*)pSrc)[0]; \ -+} -+#define ZYWRLE_SAVE_COEFF(pDst,R,G,B) { \ -+ ((signed char*)pDst)[2] = (signed char)R; \ -+ ((signed char*)pDst)[1] = (signed char)G; \ -+ ((signed char*)pDst)[0] = (signed char)B; \ -+} -+ -+/* -+ RGB <=> YUV conversion stuffs. -+ YUV coversion is explained as following formula in strict meaning: -+ Y = 0.299R + 0.587G + 0.114B ( 0<=Y<=255) -+ U = -0.169R - 0.331G + 0.500B (-128<=U<=127) -+ V = 0.500R - 0.419G - 0.081B (-128<=V<=127) -+ -+ I use simple conversion RCT(reversible color transform) which is described -+ in JPEG-2000 specification. -+ Y = (R + 2G + B)/4 ( 0<=Y<=255) -+ U = B-G (-256<=U<=255) -+ V = R-G (-256<=V<=255) -+*/ -+#define ROUND(x) (((x)<0)?0:(((x)>255)?255:(x))) -+ /* RCT is N-bit RGB to N-bit Y and N+1-bit UV. -+ For make Same N-bit, UV is lossy. -+ More exact PLHarr, we reduce to odd range(-127<=x<=127). */ -+#define ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ymask,uvmask) { \ -+ Y = (R+(G<<1)+B)>>2; \ -+ U = B-G; \ -+ V = R-G; \ -+ Y -= 128; \ -+ U >>= 1; \ -+ V >>= 1; \ -+ Y &= ymask; \ -+ U &= uvmask; \ -+ V &= uvmask; \ -+ if (Y == -128) \ -+ Y += (0xFFFFFFFF-ymask+1); \ -+ if (U == -128) \ -+ U += (0xFFFFFFFF-uvmask+1); \ -+ if (V == -128) \ -+ V += (0xFFFFFFFF-uvmask+1); \ -+} -+#define ZYWRLE_YUVRGB1(R,G,B,Y,U,V) { \ -+ Y += 128; \ -+ U <<= 1; \ -+ V <<= 1; \ -+ G = Y-((U+V)>>2); \ -+ B = U+G; \ -+ R = V+G; \ -+ G = ROUND(G); \ -+ B = ROUND(B); \ -+ R = ROUND(R); \ -+} -+ -+/* -+ coefficient packing/unpacking stuffs. -+ Wavelet transform makes 4 sub coefficient image from 1 original image. -+ -+ model with pyramid decomposition: -+ +------+------+ -+ | | | -+ | L | Hx | -+ | | | -+ +------+------+ -+ | | | -+ | H | Hxy | -+ | | | -+ +------+------+ -+ -+ So, we must transfer each sub images individually in strict meaning. -+ But at least ZRLE meaning, following one decompositon image is same as -+ avobe individual sub image. I use this format. -+ (Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L) -+ for simplified procedure for any wavelet level.) -+ -+ +------+------+ -+ | L | -+ +------+------+ -+ | Hx | -+ +------+------+ -+ | Hy | -+ +------+------+ -+ | Hxy | -+ +------+------+ -+*/ -+#define 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<<level; \ -+ if (r & 0x01) \ -+ pH += s>>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<<level)-1); -+ *pH &= ~((1<<level)-1); -+} -+ -+#endif /* ZYWRLE_ONCE */ -+ -+#ifndef CPIXEL -+#ifdef ZYWRLE_ENCODE -+static InlineX void ZYWRLE_RGBYUV(int* pBuf, PIXEL_T* data, int width, int height, int scanline) -+{ -+ int R, G, B; -+ int Y, U, V; -+ int* pLine; -+ int* pEnd; -+ pEnd = pBuf+height*width; -+ while (pBuf < pEnd) { -+ pLine = pBuf+width; -+ while (pBuf < pLine) { -+ ZYWRLE_LOAD_PIXEL(data,R,G,B); -+ ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ZYWRLE_YMASK,ZYWRLE_UVMASK); -+ ZYWRLE_SAVE_COEFF(pBuf,V,Y,U); -+ pBuf++; -+ data++; -+ } -+ data += scanline-width; -+ } -+} -+#endif -+#ifdef ZYWRLE_DECODE -+static InlineX void ZYWRLE_YUVRGB(int* pBuf, PIXEL_T* data, int width, int height, int scanline) { -+ int R, G, B; -+ int Y, U, V; -+ int* pLine; -+ int* pEnd; -+ pEnd = pBuf+height*width; -+ while (pBuf < pEnd) { -+ pLine = pBuf+width; -+ while (pBuf < pLine) { -+ ZYWRLE_LOAD_COEFF(pBuf,V,Y,U); -+ ZYWRLE_YUVRGB1(R,G,B,Y,U,V); -+ ZYWRLE_SAVE_PIXEL(data,R,G,B); -+ pBuf++; -+ data++; -+ } -+ data += scanline-width; -+ } -+} -+#endif -+ -+#ifdef ZYWRLE_ENCODE -+PIXEL_T* ZYWRLE_ANALYZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf) { -+ int l; -+ int uw = w; -+ int uh = h; -+ int* pTop; -+ int* pEnd; -+ int* pLine; -+ PIXEL_T* pData; -+ int R, G, B; -+ int s; -+ int* pH; -+ -+ zywrleCalcSize(&w, &h, level); -+ if (w == 0 || h == 0) -+ return NULL; -+ uw -= w; -+ uh -= h; -+ -+ pData = dst; -+ ZYWRLE_LOAD_UNALIGN(src,*(PIXEL_T*)pTop=*pData;) -+ ZYWRLE_RGBYUV(pBuf, src, w, h, scanline); -+ Wavelet(pBuf, w, h, level); -+ for (l = 0; l < level; l++) { -+ ZYWRLE_PACK_COEFF(pBuf, dst, 3, w, h, scanline, l); -+ ZYWRLE_PACK_COEFF(pBuf, dst, 2, w, h, scanline, l); -+ ZYWRLE_PACK_COEFF(pBuf, dst, 1, w, h, scanline, l); -+ if (l == level - 1) { -+ ZYWRLE_PACK_COEFF(pBuf, dst, 0, w, h, scanline, l); -+ } -+ } -+ ZYWRLE_SAVE_UNALIGN(dst,*dst=*(PIXEL_T*)pTop;) -+ return dst; -+} -+#endif -+#ifdef ZYWRLE_DECODE -+PIXEL_T* ZYWRLE_SYNTHESIZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf) -+{ -+ int l; -+ int uw = w; -+ int uh = h; -+ int* pTop; -+ int* pEnd; -+ int* pLine; -+ PIXEL_T* pData; -+ int R, G, B; -+ int s; -+ int* pH; -+ -+ zywrleCalcSize(&w, &h, level); -+ if (w == 0 || h == 0) -+ return NULL; -+ uw -= w; -+ uh -= h; -+ -+ pData = src; -+ for (l = 0; l < level; l++) { -+ ZYWRLE_UNPACK_COEFF(pBuf, src, 3, w, h, scanline, l); -+ ZYWRLE_UNPACK_COEFF(pBuf, src, 2, w, h, scanline, l); -+ ZYWRLE_UNPACK_COEFF(pBuf, src, 1, w, h, scanline, l); -+ if (l == level - 1) { -+ ZYWRLE_UNPACK_COEFF(pBuf, src, 0, w, h, scanline, l); -+ } -+ } -+ ZYWRLE_SAVE_UNALIGN(src,*(PIXEL_T*)pTop=*src;) -+ InvWavelet(pBuf, w, h, level); -+ ZYWRLE_YUVRGB(pBuf, dst, w, h, scanline); -+ ZYWRLE_LOAD_UNALIGN(dst,*pData=*(PIXEL_T*)pTop;) -+ return src; -+} -+#endif -+#endif /* CPIXEL */ -+ -+#undef ZYWRLE_RGBYUV -+#undef ZYWRLE_YUVRGB -+#undef ZYWRLE_LOAD_PIXEL -+#undef ZYWRLE_SAVE_PIXEL -diff -Naur -X ./exclude vnc_unixsrc.orig/include/rfbproto.h vnc_unixsrc/include/rfbproto.h ---- vnc_unixsrc.orig/include/rfbproto.h 2004-05-27 03:02:02.000000000 -0400 -+++ vnc_unixsrc/include/rfbproto.h 2010-02-25 21:54:58.000000000 -0500 -@@ -205,7 +205,22 @@ - #define rfbSecTypeInvalid 0 - #define rfbSecTypeNone 1 - #define rfbSecTypeVncAuth 2 -+#define rfbSecTypeRA2 5 -+#define rfbSecTypeRA2ne 6 - #define rfbSecTypeTight 16 -+#define rfbSecTypeUltra 17 -+ -+/* try to support VeNCrypt and TLS */ -+#define rfbSecTypeAnonTls 18 -+#define rfbSecTypeVencrypt 19 -+ -+#define rfbVencryptPlain 256 -+#define rfbVencryptTlsNone 257 -+#define rfbVencryptTlsVnc 258 -+#define rfbVencryptTlsPlain 259 -+#define rfbVencryptX509None 260 -+#define rfbVencryptX509Vnc 261 -+#define rfbVencryptX509Plain 262 - - - /*----------------------------------------------------------------------------- -@@ -381,6 +396,11 @@ - #define rfbBell 2 - #define rfbServerCutText 3 - -+#define rfbResizeFrameBuffer 4 /* Modif sf@2002 */ -+ -+/* http://sourceforge.net/projects/vncsessmgr */ -+#define rfbRestartConnection 82 -+ - #define rfbFileListData 130 - #define rfbFileDownloadData 131 - #define rfbFileUploadCancel 132 -@@ -403,6 +423,18 @@ - #define rfbPointerEvent 5 - #define rfbClientCutText 6 - -+/* ultra */ -+ -+#define rfbFileTransfer 7 -+#define rfbSetScale 8 -+#define rfbSetServerInput 9 -+#define rfbSetSW 10 -+#define rfbTextChat 11 -+#define rfbKeyFrameRequest 12 -+#define rfbPalmVNCSetScaleFactor 0xF -+ -+ -+ - #define rfbFileListRequest 130 - #define rfbFileDownloadRequest 131 - #define rfbFileUploadRequest 132 -@@ -435,6 +467,13 @@ - #define rfbEncodingTight 7 - #define rfbEncodingZlibHex 8 - -+#define rfbEncodingZRLE 16 -+/* -+nyama/2006/08/02:new YUV-Wavlet lossy codec based on ZRLE (ZYWRLE) -+ */ -+#define rfbEncodingZYWRLE 17 -+ -+ - /* signatures for basic encoding types */ - #define sig_rfbEncodingRaw "RAW_____" - #define sig_rfbEncodingCopyRect "COPYRECT" -@@ -955,6 +994,51 @@ - #define sz_rfbFileDownloadFailedMsg 4 - - /*----------------------------------------------------------------------------- -+ * RestartConnection - the server has restarted the client connection. -+ */ -+ -+typedef struct _rfbRestartConnectionMsg { -+ CARD8 type; /* always rfbRestartConnection */ -+ CARD8 pad1; -+ CARD16 pad2; -+ CARD32 length; -+ /* followed by char text[length] */ -+} rfbRestartConnectionMsg; -+ -+#define sz_rfbRestartConnectionMsg 8 -+ -+ -+typedef struct _rfbTextChatMsg { -+ CARD8 type; /* always rfbTextChat */ -+ CARD8 pad1; /* Could be used later as an additionnal param */ -+ CARD16 pad2; /* Could be used later as text offset, for instance */ -+ CARD32 length; /* Specific values for Open, close, finished (-1, -2, -3) */ -+ /* followed by char text[length] */ -+} rfbTextChatMsg; -+ -+#define sz_rfbTextChatMsg 8 -+ -+#define rfbTextMaxSize 4096 -+#define rfbTextChatOpen 0xFFFFFFFF -+#define rfbTextChatClose 0xFFFFFFFE -+#define rfbTextChatFinished 0xFFFFFFFD -+ -+/*----------------------------------------------------------------------------- -+ * Modif sf@2002 -+ * ResizeFrameBuffer - The Client must change the size of its framebuffer -+ */ -+ -+typedef struct _rfbResizeFrameBufferMsg { -+ CARD8 type; /* always rfbResizeFrameBuffer */ -+ CARD8 pad1; -+ CARD16 framebufferWidth; /* FrameBuffer width */ -+ CARD16 framebufferHeight; /* FrameBuffer height */ -+} rfbResizeFrameBufferMsg; -+ -+#define sz_rfbResizeFrameBufferMsg 6 -+ -+ -+/*----------------------------------------------------------------------------- - * Union of all server->client messages. - */ - -@@ -968,6 +1052,8 @@ - rfbFileDownloadDataMsg fdd; - rfbFileUploadCancelMsg fuc; - rfbFileDownloadFailedMsg fdf; -+ rfbRestartConnectionMsg rc; -+ rfbTextChatMsg tc; - } rfbServerToClientMsg; - - -@@ -1221,6 +1307,41 @@ - - #define sz_rfbFileCreateDirRequestMsg 4 - -+/* ultra */ -+typedef struct _rfbSetScaleMsg { -+ CARD8 type; /* always rfbSetScale */ -+ CARD8 scale; /* Scale value 1<sv<n */ -+ CARD16 pad; -+} rfbSetScaleMsg; -+ -+#define sz_rfbSetScaleMsg 4 -+ -+typedef struct { -+ CARD8 type; /* always rfbSetScaleFactor */ -+ -+ CARD8 scale; /* Scale factor (positive non-zero integer) */ -+ CARD16 pad2; -+} rfbPalmVNCSetScaleFactorMsg; -+ -+#define sz_rfbPalmVNCSetScaleFactorMsg (4) -+ -+typedef struct _rfbSetServerInputMsg { -+ CARD8 type; /* always rfbSetServerInputMsg */ -+ CARD8 status; /* on or off */ -+ CARD16 pad; -+} rfbSetServerInputMsg; -+ -+#define sz_rfbSetServerInputMsg 4 -+ -+typedef struct _rfbSetSWMsg { -+ CARD8 type; /* always rfbSetSW */ -+ CARD8 status; -+ CARD16 x; -+ CARD16 y; -+} rfbSetSWMsg; -+ -+#define sz_rfbSetSWMsg 6 -+ - /*----------------------------------------------------------------------------- - * Union of all client->server messages. - */ -@@ -1241,4 +1362,9 @@ - rfbFileDownloadCancelMsg fdc; - rfbFileUploadFailedMsg fuf; - rfbFileCreateDirRequestMsg fcdr; -+ rfbSetScaleMsg ssc; -+ rfbPalmVNCSetScaleFactorMsg pssf; -+ rfbSetServerInputMsg sim; -+ rfbSetSWMsg sw; -+ rfbTextChatMsg tc; - } rfbClientToServerMsg; -diff -Naur -X ./exclude vnc_unixsrc.orig/include/vncauth.h vnc_unixsrc/include/vncauth.h ---- vnc_unixsrc.orig/include/vncauth.h 2000-06-11 08:00:53.000000000 -0400 -+++ vnc_unixsrc/include/vncauth.h 2009-03-21 00:37:23.000000000 -0400 -@@ -23,8 +23,11 @@ - - #define MAXPWLEN 8 - #define CHALLENGESIZE 16 -+#define CHALLENGESIZE_MSLOGON 64 - - extern int vncEncryptAndStorePasswd(char *passwd, char *fname); - extern char *vncDecryptPasswdFromFile(char *fname); - extern void vncRandomBytes(unsigned char *bytes); - extern void vncEncryptBytes(unsigned char *bytes, char *passwd); -+ -+extern void vncEncryptPasswd_MSLOGON(unsigned char *encryptedPasswd, char *passwd); -diff -Naur -X ./exclude vnc_unixsrc.orig/libvncauth/d3des.c vnc_unixsrc/libvncauth/d3des.c ---- vnc_unixsrc.orig/libvncauth/d3des.c 2000-06-11 08:00:53.000000000 -0400 -+++ vnc_unixsrc/libvncauth/d3des.c 2010-02-25 21:49:02.000000000 -0500 -@@ -34,12 +34,15 @@ - static void cookey(unsigned long *); - - static unsigned long KnL[32] = { 0L }; -+/* no londer used: */ -+#if 0 - static unsigned long KnR[32] = { 0L }; - static unsigned long Kn3[32] = { 0L }; - static unsigned char Df_Key[24] = { - 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, - 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, - 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; -+#endif - - static unsigned short bytebit[8] = { - 01, 02, 04, 010, 020, 040, 0100, 0200 }; -diff -Naur -X ./exclude vnc_unixsrc.orig/libvncauth/vncauth.c vnc_unixsrc/libvncauth/vncauth.c ---- vnc_unixsrc.orig/libvncauth/vncauth.c 2003-03-01 11:48:06.000000000 -0500 -+++ vnc_unixsrc/libvncauth/vncauth.c 2010-02-25 21:47:25.000000000 -0500 -@@ -27,9 +27,11 @@ - #include <sys/types.h> - #include <sys/stat.h> - #include <unistd.h> -+#include <time.h> - #include <vncauth.h> - #include <d3des.h> - -+#include <fcntl.h> - - /* - * Make sure we call srandom() only once. -@@ -45,6 +47,8 @@ - - static unsigned char s_fixedkey[8] = {23,82,107,6,35,78,88,7}; - -+int vncEncryptAndStorePasswd2(char *passwd, char *passwdViewOnly, char *fname); -+int vncDecryptPasswdFromFile2(char *fname, char *passwdFullControl, char *passwdViewOnly); - - /* - * Encrypt a password and store it in a file. Returns 0 if successful, -@@ -73,7 +77,7 @@ - vncEncryptAndStorePasswd2(char *passwd, char *passwdViewOnly, char *fname) - { - FILE *fp; -- int i, bytesToWrite, bytesWrote; -+ int bytesToWrite, bytesWrote; - unsigned char encryptedPasswd[16] = { - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0 -@@ -195,6 +199,44 @@ - return (i < 16) ? 1 : 2; - } - -+unsigned int urandom(void) { -+ unsigned int val = 0; -+ struct stat sb; -+ int fd = -1; -+ if (fd < 0 && stat("/dev/urandom", &sb) == 0) { -+ fd = open("/dev/urandom", O_RDONLY); -+ } -+ if (fd < 0 && stat("/dev/random", &sb) == 0) { -+ fd = open("/dev/random", O_RDONLY); -+ } -+ if (fd < 0 && stat("/proc/loadavg", &sb) == 0) { -+ fd = open("/proc/loadavg", O_RDONLY); -+ } -+ if (fd < 0 && stat("/bin/bash", &sb) == 0) { -+ fd = open("/bin/bash", O_RDONLY); -+ lseek(fd, (off_t) (unsigned int) getpid(), SEEK_SET); -+ } -+ if (fd >= 0) { -+ int i; -+ for (i=0; i < 3; i++) { -+ char buf[2]; -+ if (read(fd, buf, 1) > 0) { -+ unsigned char uc = (unsigned char) buf[0]; -+ if (i==0) { -+ val += uc; -+ } else if (i==1) { -+ val += uc * 256; -+ } else if (i==2) { -+ val += uc * 256 * 256; -+ } -+ } -+ } -+ close(fd); -+ } else { -+ val = (unsigned int) getpid(); -+ } -+ return val; -+} - - /* - * Generate CHALLENGESIZE random bytes for use in challenge-response -@@ -207,11 +249,13 @@ - int i; - unsigned int seed; - -- if (!s_srandom_called) { -- seed = (unsigned int)time(0) ^ (unsigned int)getpid(); -- srandom(seed); -- s_srandom_called = 1; -- } -+ if (!s_srandom_called) { -+ seed = (unsigned int)time(0) ^ (unsigned int)getpid(); -+ seed += urandom(); -+ -+ srandom(seed); -+ s_srandom_called = 1; -+ } - - for (i = 0; i < CHALLENGESIZE; i++) { - bytes[i] = (unsigned char)(random() & 255); -@@ -245,3 +289,48 @@ - des(bytes+i, bytes+i); - } - } -+ -+void UvncEncryptPasswd_MSLOGON(unsigned char *encryptedPasswd, char *passwd) { -+ unsigned int i; -+ for (i=0; i < 32; i++) { -+ if (i < strlen(passwd)) { -+ encryptedPasswd[i] = passwd[i]; -+ } else { -+ encryptedPasswd[i] = '\0'; -+ } -+ } -+ deskey(s_fixedkey, EN0); -+ des(encryptedPasswd, encryptedPasswd); -+} -+ -+void UvncEncryptBytes2(unsigned char *where, int length, unsigned char *key) { -+ int i, j; -+ deskey(key, EN0); -+ for (i=0; i < 8; i++) { -+ where[i] ^= key[i]; -+ } -+ des(where, where); -+ for (i=8; i < length; i += 8) { -+ for (j=0; j < 8; j++) { -+ where[i+j] ^= where[i+j-8]; -+ } -+ des(where+i, where+i); -+ } -+} -+ -+void UvncDecryptBytes2(unsigned char *where, int length, unsigned char *key) { -+ int i, j; -+ deskey(key, DE1); -+ for (i = length - 8; i > 0; i -= 8) { -+ des(where + i, where + i); -+ for (j=0; j < 8; j++) { -+ where[i+j] ^= where[i+j-8]; -+ } -+ } -+ /* i=0 */ -+ des(where, where); -+ for (i=0; i < 8; i++) { -+ where[i] ^= key[i]; -+ } -+} -+ |