You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libtdevnc/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch

16855 lines
461 KiB

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 2008-10-17 22:04:19.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\
@@ -58,23 +110,65 @@
"*serverDialog.dialog.value.translations: #override\\n\
<Key>Return: ServerDialogDone()",
+ "*scaleDialogPREV.dialog.label: Scale: Enter 'none' 'auto' 'aspect'\\nor fraction (e.g. 0.75 or 3/4).\\ncurrent value:",
+
+ "*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\
+ <Key>Return: ScaleDialogDone()",
+
+ "*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()",
+
+ "*scaleNDialog.dialog.label: Integer n for 1/n server scaling:",
+ "*scaleNDialog.dialog.value:",
+ "*scaleNDialog.dialog.value.translations: #override\\n\
+ <Key>Return: ScaleNDialogDone()",
+
"*passwordDialog.dialog.label: Password:",
"*passwordDialog.dialog.value:",
"*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",
+
+ "*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: 38",
+ "*popupButtonBreak: 19",
"*popup*button1.label: Dismiss popup",
"*popup*button1.translations: #override\\n\
@@ -84,7 +178,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 +199,323 @@
"*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/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: Scale Viewer",
+ "*popup*button27.translations: #override\\n\
+ <Btn1Down>,<Btn1Up>: HidePopup() SetScale()",
+
+ "*popup*button28.label: Set Y Crop (y-max)",
+ "*popup*button28.translations: #override\\n\
+ <Btn1Down>,<Btn1Up>: HidePopup() SetYCrop()",
+
+ "*popup*button29.label: Set Scrollbar Width",
+ "*popup*button29.translations: #override\\n\
+ <Btn1Down>,<Btn1Up>: HidePopup() SetScbar()",
+
+ "*popup*button30.label: XGrabServer",
+ "*popup*button30.type: toggle",
+ "*popup*button30.translations: #override\\n\
+ <Visible>: SetXGrabState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() ToggleXGrab() HidePopup()",
+
+ "*popup*button31.label: UltraVNC Extensions:",
+ "*popup*button31.translations: #override\\n\
+ <Btn1Down>,<Btn1Up>: HidePopup()",
+
+ "*popup*button32.label: - Set 1/n Server Scale",
+ "*popup*button32.translations: #override\\n\
+ <Btn1Down>,<Btn1Up>: HidePopup() ShowScaleN()",
+
+ "*popup*button33.label: - Text Chat",
+ "*popup*button33.type: toggle",
+ "*popup*button33.translations: #override\\n\
+ <Visible>: SetTextChatState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() ToggleTextChat() HidePopup()",
+
+ "*popup*button34.label: - File Transfer",
+ "*popup*button34.type: toggle",
+ "*popup*button34.translations: #override\\n\
+ <Visible>: SetFileXferState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() ToggleFileXfer() HidePopup()",
+
+ "*popup*button35.label: - Single Window",
+ "*popup*button35.type: toggle",
+ "*popup*button35.translations: #override\\n\
+ <Visible>: SetSingleWindowState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() ToggleSingleWindow() HidePopup()",
+
+ "*popup*button36.label: - Disable Remote Input",
+ "*popup*button36.type: toggle",
+ "*popup*button36.translations: #override\\n\
+ <Visible>: SetServerInputState()\\n\
+ <Btn1Down>,<Btn1Up>: toggle() ToggleServerInput() HidePopup()",
+
+ "*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()",
+
NULL
};
@@ -124,7 +525,7 @@
* from a dialog box.
*/
-char vncServerHost[256];
+char vncServerHost[1024];
int vncServerPort = 0;
@@ -135,6 +536,7 @@
*/
AppData appData;
+AppData appDataNew;
static XtResource appDataResourceList[] = {
{"shareDesktop", "ShareDesktop", XtRBool, sizeof(Bool),
@@ -155,14 +557,38 @@
{"userLogin", "UserLogin", XtRString, sizeof(String),
XtOffsetOf(AppData, userLogin), XtRImmediate, (XtPointer) 0},
+ {"unixPW", "UnixPW", XtRString, sizeof(String),
+ XtOffsetOf(AppData, unixPW), XtRImmediate, (XtPointer) 0},
+
+ {"repeaterUltra", "RepeaterUltra", XtRString, sizeof(String),
+ XtOffsetOf(AppData, repeaterUltra), XtRImmediate, (XtPointer) 0},
+
+ {"ultraDSM", "UltraDSM", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, ultraDSM), XtRImmediate, (XtPointer) False},
+
+ {"rfbVersion", "RfbVersion", XtRString, sizeof(String),
+ XtOffsetOf(AppData, rfbVersion), XtRImmediate, (XtPointer) 0},
+
{"passwordDialog", "PasswordDialog", XtRBool, sizeof(Bool),
XtOffsetOf(AppData, passwordDialog), XtRImmediate, (XtPointer) False},
{"encodings", "Encodings", XtRString, sizeof(String),
XtOffsetOf(AppData, encodingsString), XtRImmediate, (XtPointer) 0},
- {"useBGR233", "UseBGR233", XtRBool, sizeof(Bool),
- XtOffsetOf(AppData, useBGR233), XtRImmediate, (XtPointer) False},
+ {"useBGR233", "UseBGR233", XtRInt, sizeof(int),
+ XtOffsetOf(AppData, useBGR233), XtRImmediate, (XtPointer) 0},
+
+ {"useBGR565", "UseBGR565", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, useBGR565), XtRImmediate, (XtPointer) False},
+
+ {"useGreyScale", "UseGreyScale", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, useGreyScale), XtRImmediate, (XtPointer) False},
+
+ {"yCrop", "yCrop", XtRInt, sizeof(int),
+ XtOffsetOf(AppData, yCrop), XtRImmediate, (XtPointer) 0},
+
+ {"sbWidth", "sbWidth", XtRInt, sizeof(int),
+ XtOffsetOf(AppData, sbWidth), XtRImmediate, (XtPointer) 2},
{"nColours", "NColours", XtRInt, sizeof(int),
XtOffsetOf(AppData, nColours), XtRImmediate, (XtPointer) 256},
@@ -179,9 +605,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 +620,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},
@@ -207,7 +639,7 @@
XtOffsetOf(AppData, bumpScrollPixels), XtRImmediate, (XtPointer) 20},
{"compressLevel", "CompressionLevel", XtRInt, sizeof(int),
- XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) -1},
+ XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) 7},
{"qualityLevel", "QualityLevel", XtRInt, sizeof(int),
XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) 6},
@@ -218,14 +650,58 @@
{"useRemoteCursor", "UseRemoteCursor", XtRBool, sizeof(Bool),
XtOffsetOf(AppData, useRemoteCursor), XtRImmediate, (XtPointer) True},
+ {"useCursorAlpha", "UseCursorAlpha", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, useCursorAlpha), XtRImmediate, (XtPointer) False},
+
+ {"useRawLocal", "UseRawLocal", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, useRawLocal), XtRImmediate, (XtPointer) False},
+
{"useX11Cursor", "UseX11Cursor", XtRBool, sizeof(Bool),
XtOffsetOf(AppData, useX11Cursor), XtRImmediate, (XtPointer) False},
+ {"useBell", "UseBell", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, useBell), XtRImmediate, (XtPointer) True},
+
{"grabKeyboard", "GrabKeyboard", XtRBool, sizeof(Bool),
- XtOffsetOf(AppData, grabKeyboard), XtRImmediate, (XtPointer) False},
+ XtOffsetOf(AppData, grabKeyboard), XtRImmediate, (XtPointer) True},
{"autoPass", "AutoPass", XtRBool, sizeof(Bool),
- XtOffsetOf(AppData, autoPass), XtRImmediate, (XtPointer) False}
+ XtOffsetOf(AppData, autoPass), XtRImmediate, (XtPointer) False},
+
+ {"grabAll", "GrabAll", XtRBool, sizeof(Bool),
+ XtOffsetOf(AppData, grabAll), XtRImmediate, (XtPointer) False},
+
+ {"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}
+
+ /* check commas */
};
@@ -242,8 +718,25 @@
{"-noraiseonbeep", "*raiseOnBeep", XrmoptionNoArg, "False"},
{"-passwd", "*passwordFile", XrmoptionSepArg, 0},
{"-user", "*userLogin", XrmoptionSepArg, 0},
+ {"-unixpw", "*unixPW", XrmoptionSepArg, 0},
+ {"-repeater", "*repeaterUltra", XrmoptionSepArg, 0},
+ {"-ultradsm", "*ultraDSM", XrmoptionNoArg, "True"},
+ {"-rfbversion", "*rfbVersion", XrmoptionSepArg, 0},
{"-encodings", "*encodings", XrmoptionSepArg, 0},
- {"-bgr233", "*useBGR233", XrmoptionNoArg, "True"},
+ {"-bgr233", "*useBGR233", XrmoptionNoArg, "256"},
+ {"-use64", "*useBGR233", XrmoptionNoArg, "64"},
+ {"-bgr222", "*useBGR233", XrmoptionNoArg, "64"},
+ {"-use8", "*useBGR233", XrmoptionNoArg, "8"},
+ {"-bgr111", "*useBGR233", XrmoptionNoArg, "8"},
+ {"-16bpp", "*useBGR565", XrmoptionNoArg, "True"},
+ {"-bgr565", "*useBGR565", XrmoptionNoArg, "True"},
+ {"-grey", "*useGreyScale", XrmoptionNoArg, "True"},
+ {"-gray", "*useGreyScale", XrmoptionNoArg, "True"},
+ {"-sbwidth", "*sbwidth", XrmoptionSepArg, 0},
+ {"-env", "*envDummy", XrmoptionSepArg, 0},
+ {"-ycrop", "*yCrop", XrmoptionSepArg, 0},
+ {"-rawlocal", "*useRawLocal", XrmoptionNoArg, "True"},
+ {"-alpha", "*useCursorAlpha", XrmoptionNoArg, "True"},
{"-owncmap", "*forceOwnCmap", XrmoptionNoArg, "True"},
{"-truecolor", "*forceTrueColour", XrmoptionNoArg, "True"},
{"-truecolour", "*forceTrueColour", XrmoptionNoArg, "True"},
@@ -253,7 +746,21 @@
{"-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},
};
@@ -267,16 +774,84 @@
static XtActionsRec actions[] = {
{"SendRFBEvent", SendRFBEvent},
{"ShowPopup", ShowPopup},
+ {"Noop", Noop},
{"HidePopup", HidePopup},
+ {"HideScaleN", HideScaleN},
+ {"HideQuality", HideQuality},
+ {"HideCompress", HideCompress},
{"ToggleFullScreen", ToggleFullScreen},
+ {"JumpLeft", JumpLeft},
+ {"JumpRight", JumpRight},
+ {"JumpUp", JumpUp},
+ {"JumpDown", JumpDown},
{"SetFullScreenState", SetFullScreenState},
{"SelectionFromVNC", SelectionFromVNC},
{"SelectionToVNC", SelectionToVNC},
{"ServerDialogDone", ServerDialogDone},
+ {"YCropDialogDone", YCropDialogDone},
+ {"ScbarDialogDone", ScbarDialogDone},
+ {"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},
+ {"ToggleZRLEZYWRLE", ToggleZRLEZYWRLE},
+ {"ToggleViewOnly", ToggleViewOnly},
+ {"ToggleJPEG", ToggleJPEG},
+ {"ToggleCursorShape", ToggleCursorShape},
+ {"ToggleCursorAlpha", ToggleCursorAlpha},
+ {"ToggleX11Cursor", ToggleX11Cursor},
+ {"ToggleBell", ToggleBell},
+ {"ToggleRawLocal", ToggleRawLocal},
+ {"ToggleServerInput", ToggleServerInput},
+ {"ToggleSingleWindow", ToggleSingleWindow},
+ {"ToggleTextChat", ToggleTextChat},
+ {"ToggleFileXfer", ToggleFileXfer},
+ {"ToggleXGrab", ToggleXGrab},
+ {"DoServerScale", DoServerScale},
+ {"SetScale", SetScale},
+ {"SetYCrop", SetYCrop},
+ {"SetScbar", SetScbar},
+ {"ShowScaleN", ShowScaleN},
+ {"ShowQuality", ShowQuality},
+ {"ShowCompress", ShowCompress},
+ {"SetScaleN", SetScaleN},
+ {"SetQuality", SetQuality},
+ {"SetCompress", SetCompress},
+ {"Set8bppState", Set8bppState},
+ {"Set16bppState", Set16bppState},
+ {"SetFullColorState", SetFullColorState},
+ {"Set256ColorsState", Set256ColorsState},
+ {"Set64ColorsState", Set64ColorsState},
+ {"Set8ColorsState", Set8ColorsState},
+ {"SetGreyScaleState", SetGreyScaleState},
+ {"SetZRLEState", SetZRLEState},
+ {"SetZYWRLEState", SetZYWRLEState},
+ {"SetNOJPEGState", SetNOJPEGState},
+ {"SetScaleNState", SetScaleNState},
+ {"SetQualityState", SetQualityState},
+ {"SetCompressState", SetCompressState},
+ {"SetViewOnlyState", SetViewOnlyState},
+ {"SetCursorShapeState", SetCursorShapeState},
+ {"SetCursorAlphaState", SetCursorAlphaState},
+ {"SetX11CursorState", SetX11CursorState},
+ {"SetBellState", SetBellState},
+ {"SetRawLocalState", SetRawLocalState},
+ {"SetServerInputState", SetServerInputState},
+ {"SetSingleWindowState", SetSingleWindowState},
+ {"SetTextChatState", SetTextChatState},
+ {"SetFileXferState", SetFileXferState},
+ {"SetXGrabState", SetXGrabState}
};
@@ -302,11 +877,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"
@@ -332,10 +910,230 @@
" -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"
+ " -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.\n"
+ "\n"
+ " Note that scaling is done in software and can be slow\n"
+ " and requires more memory. \"str\" can also be set by\n"
+ " the env. var. SSVNC_SCALE.\n"
+ "\n"
+ " -ycrop n Only show the top n rows of the framebuffer. For\n"
+ " use with x11vnc -ncache client caching option\n"
+ " to help \"hide\" the pixel cache region.\n"
+ " Use a negative value (e.g. -1) for autodetection.\n"
+ " Autodetection will always take place if the remote\n"
+ " fb height is more than 2 times the width.\n"
+ "\n"
+ " -sbwidth n Scrollbar width for x11vnc -ncache mode (-ycrop),\n"
+ " default is very narrow: 2 pixels, it is narrow to\n"
+ " avoid distraction in -ycrop mode.\n"
+ "\n"
+ " -nobell Disable bell.\n"
+ "\n"
+ " -rawlocal Prefer raw encoding for localhost, default is\n"
+ " no, i.e. assumes you have a SSH tunnel instead.\n"
+ "\n"
+ " -graball Grab the entire X server when in fullscreen mode,\n"
+ " needed by some old window managers like fvwm2.\n"
+ " -popupfix Warp the popup back to the pointer position,\n"
+ " needed by some old window managers like fvwm2.\n"
+ "\n"
+ " -grabkbd Grab the X keyboard when in fullscreen mode,\n"
+ " needed by some window managers. Same as -grabkeyboard.\n"
+ " -grabkbd is the default, use -nograbkbd to disable.\n"
+ "\n"
+ " -bs, -nobs Whether or not to use X server Backingstore for the\n"
+ " main viewer window. The default is to not, mainly\n"
+ " because most Linux, etc, systems X servers disable\n"
+ " *all* Backingstore by default. To re-enable it put\n"
+ "\n"
+ " Option \"Backingstore\"\n"
+ "\n"
+ " in the Device section of /etc/X11/xorg.conf.\n"
+ " In -bs mode with no X server backingstore, whenever an\n"
+ " area of the screen is re-exposed it must go out to the\n"
+ " VNC server to retrieve the pixels. This is too slow.\n"
+ "\n"
+ " In -nobs mode, memory is allocated by the viewer to\n"
+ " provide its own backing of the main viewer window. This\n"
+ " actually makes some activities faster (changes in large\n"
+ " regions) but can appear to \"flash\" too much.\n"
+ "\n"
+ " -noshm Disable use of MIT shared memory extension (not recommended)\n"
+ "\n"
+ " -termchat Do the UltraVNC chat in the terminal vncviewer is in\n"
+ " instead of in an independent window.\n"
+ "\n"
+ " -unixpw str Useful for logging into x11vnc in -unixpw mode. \"str\" is a\n"
+ " string that allows many ways to enter the Unix Username\n"
+ " and Unix Password. These characters: username, newline,\n"
+ " password, newline are sent to the VNC server after any VNC\n"
+ " authentication has taken place. Under x11vnc they are\n"
+ " used for the -unixpw login. Other VNC servers could do\n"
+ " something similar.\n"
+ "\n"
+ " You can also indicate \"str\" via the environment\n"
+ " variable SSVNC_UNIXPW.\n"
+ "\n"
+ " Note that the Escape key is actually sent first to tell\n"
+ " x11vnc to not echo the Unix Username back to the VNC\n"
+ " viewer. Set SSVNC_UNIXPW_NOESC=1 to override this.\n"
+ "\n"
+ " If str is \".\", then you are prompted at the command line\n"
+ " for the username and password in the normal way. If str is\n"
+ " \"-\" the stdin is read via getpass(3) for username@password.\n"
+ " Otherwise if str is a file, it is opened and the first line\n"
+ " read is taken as the Unix username and the 2nd as the\n"
+ " password. If str prefixed by \"rm:\" the file is removed\n"
+ " after reading. Otherwise, if str has a \"@\" character,\n"
+ " it is taken as username@password. Otherwise, the program\n"
+ " exits with an error. Got all that?\n"
+ "\n"
+ " -repeater str This is for use with UltraVNC repeater proxy described\n"
+ " here: http://www.uvnc.com/addons/repeater.html. The \"str\"\n"
+ " is the ID string to be sent to the repeater. E.g. ID:1234\n"
+ " It can also be the hostname and port or display of the VNC\n"
+ " server, e.g. 12.34.56.78:0 or snoopy.com:1. Note that when\n"
+ " using -repeater, the host:dpy on the cmdline is the repeater\n"
+ " server, NOT the VNC server. The repeater will connect you.\n"
+ "\n"
+ " Example: vncviewer ... -repeater ID:3333 repeat.host:5900\n"
+ " Example: vncviewer ... -repeater vhost:0 repeat.host:5900\n"
+ "\n"
+ " Use, e.g., '-repeater SCIII=ID:3210' if the repeater is a\n"
+ " Single Click III (SSL) repeater (repeater_SSL.exe) and you\n"
+ " are passing the SSL part of the connection through stunnel,\n"
+ " socat, etc. This way the magic UltraVNC string 'testB'\n"
+ " needed to work with the repeater is sent to it.\n"
+ "\n"
+ " -rfbversion str Set the advertised RFB version. E.g.: -rfbversion 3.6\n"
+ " For some servers, e.g. UltraVNC this needs to be done.\n"
+ "\n"
+ " -ultradsm UltraVNC has symmetric private key encryption DSM plugins:\n"
+ " http://www.uvnc.com/features/encryption.html. It is assumed\n"
+ " you are using a unix program (e.g. our ultravnc_dsm_helper)\n"
+ " to encrypt and decrypt the UltraVNC DSM stream. IN ADDITION\n"
+ " TO THAT supply -ultradsm to tell THIS viewer to modify the\n"
+ " RFB data sent so as to work with the UltraVNC Server. For\n"
+ " some reason, each RFB msg type must be sent twice under DSM.\n"
+ "\n"
+ " -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"
+ " -printres Print out the Ssvnc X resources (appdefaults) and then exit\n"
+ " You can save them to a file and customize them (e.g. the\n"
+ " keybindings and Popup menu) Then point to the file via\n"
+ " XENVIRONMENT or XAPPLRESDIR.\n"
+ "\n"
+ " New Popup actions:\n"
+ "\n"
+ " ViewOnly: ~ -viewonly\n"
+ " Disable Bell: ~ -nobell\n"
+ " Cursor Shape: ~ -nocursorshape\n"
+ " X11 Cursor: ~ -x11cursor\n"
+ " Cursor Alphablend: ~ -alpha\n"
+ " Toggle Tight/ZRLE: ~ -encodings ...\n"
+ " Toggle ZRLE/ZYWRLE: ~ -encodings zywrle...\n"
+ " Quality Level ~ -quality (both Tight and ZYWRLE)\n"
+ " Compress Level ~ -compresslevel\n"
+ " Disable JPEG: ~ -nojpeg (Tight)\n"
+ " Full Color as many colors as local screen allows.\n"
+ " Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only.\n"
+ " 16 bit color (BGR565) ~ -16bpp / -bgr565\n"
+ " 8 bit color (BGR233) ~ -bgr233\n"
+ " 256 colors ~ -bgr233 default # of colors.\n"
+ " 64 colors ~ -bgr222 / -use64\n"
+ " 8 colors ~ -bgr111 / -use8\n"
+ " Scale Viewer ~ -scale\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"
+ "\n", programName, programName, programName, programName, programName, programName, programName);
exit(1);
}
+#if 0
+ " -nooverride Do not apply OverrideRedirect in fullscreen mode.\n"
+#endif
/*
@@ -347,73 +1145,153 @@
void
GetArgsAndResources(int argc, char **argv)
{
- int i;
- char *vncServerName, *colonPos;
- int len, portOffset;
+ int i;
+ char *vncServerName, *colonPos;
+ int len, portOffset;
+ int disp;
/* Turn app resource specs into our appData structure for the rest of the
program to use */
- 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")) {
+ 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_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"));
+ }
+ }
+
/* 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 (appData.useBGR233 && appData.useBGR565) {
+ appData.useBGR233 = 0;
+ }
+
+ 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 (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 {
+ 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();
+ }
+#if 0
+ vncServerPort = atoi(colonPos + 1) + portOffset;
+#else
+ disp = atoi(colonPos + 1);
+ if (portOffset != 0 && disp >= 100) {
+ portOffset = 0;
+ }
+ vncServerPort = disp + portOffset;
+#endif
+ }
}
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewer/colour.c
--- vnc_unixsrc.orig/vncviewer/colour.c 2002-04-30 09:07:31.000000000 -0400
+++ vnc_unixsrc/vncviewer/colour.c 2007-03-22 21:36:12.000000000 -0400
@@ -31,9 +31,12 @@
#define BGR233_SIZE 256
unsigned long BGR233ToPixel[BGR233_SIZE];
+#define BGR565_SIZE 65536
+unsigned long BGR565ToPixel[BGR565_SIZE];
+
Colormap cmap;
Visual *vis;
-unsigned int visdepth, visbpp;
+unsigned int visdepth, visbpp, isLSB;
Bool allocColorFailed = False;
static int nBGR233ColoursAllocated;
@@ -45,6 +48,8 @@
static void AllocateExactBGR233Colours();
static Bool AllocateBGR233Colour(int r, int g, int b);
+static void SetupBGR565Map();
+
/*
* SetVisualAndCmap() deals with the wonderful world of X "visuals" (which are
@@ -97,6 +102,44 @@
visbpp = GetBPPForDepth(visdepth);
cmap = DefaultColormap(dpy,DefaultScreen(dpy));
+ if (ImageByteOrder(dpy) == LSBFirst) {
+ isLSB = 1;
+ } else {
+ isLSB = 0;
+ }
+ if (visbpp == 24) {
+ if (!appData.useBGR233) {
+ fprintf(stderr, "Warning: for 24bpp enabling -bgr565 -- Don't use FullColor!\n");
+ appData.useBGR565 = True;
+ } else {
+ fprintf(stderr, "Warning: for 24bpp using -bgr233 -- Don't use FullColor!\n");
+ }
+ }
+
+ if (appData.useBGR565) {
+ if (visdepth < 24 || visbpp < 24 || vis->class != TrueColor) {
+ fprintf(stderr, "disabling -16bpp BGR565 on non-depth 24 machine\n");
+ appData.useBGR565 = False;
+ } else {
+ myFormat.bitsPerPixel = 16;
+ myFormat.depth = 16;
+ myFormat.trueColour = 1;
+ myFormat.bigEndian = 0;
+ myFormat.redMax = 31;
+ myFormat.greenMax = 63;
+ myFormat.blueMax = 31;
+ myFormat.redShift = 11;
+ myFormat.greenShift = 5;
+ myFormat.blueShift = 0;
+
+ fprintf(stderr, "Using default colormap and translating from BGR565 (65536 colors). Pixel format:\n");
+ PrintPixelFormat(&myFormat);
+
+ SetupBGR565Map();
+ return;
+ }
+ }
+
if (!appData.useBGR233 && (vis->class == TrueColor)) {
myFormat.bitsPerPixel = visbpp;
@@ -116,21 +159,42 @@
return;
}
- appData.useBGR233 = True;
+ if (appData.useBGR233 == 0) {
+ appData.useBGR233 = 256;
+ }
myFormat.bitsPerPixel = 8;
myFormat.depth = 8;
myFormat.trueColour = 1;
myFormat.bigEndian = 0;
- myFormat.redMax = 7;
+ myFormat.redMax = 7;
myFormat.greenMax = 7;
- myFormat.blueMax = 3;
- myFormat.redShift = 0;
+ myFormat.blueMax = 3;
+ myFormat.redShift = 0;
myFormat.greenShift = 3;
- myFormat.blueShift = 6;
+ myFormat.blueShift = 6;
+
+ if (appData.useBGR233 == 64) {
+ /* BGR222 */
+ myFormat.redMax = 3;
+ myFormat.greenMax = 3;
+ myFormat.blueMax = 3;
+ myFormat.redShift = 0;
+ myFormat.greenShift = 2;
+ myFormat.blueShift = 4;
+ }
+ if (appData.useBGR233 == 8) {
+ /* BGR111 */
+ myFormat.redMax = 2;
+ myFormat.greenMax = 2;
+ myFormat.blueMax = 2;
+ myFormat.redShift = 0;
+ myFormat.greenShift = 1;
+ myFormat.blueShift = 2;
+ }
fprintf(stderr,
- "Using default colormap and translating from BGR233. Pixel format:\n");
+ "Using default colormap and translating from BGR233 (%d colors). Pixel format:\n", appData.useBGR233);
PrintPixelFormat(&myFormat);
SetupBGR233Map();
@@ -282,8 +346,12 @@
XFree(format);
if (bpp != 1 && bpp != 8 && bpp != 16 && bpp != 32) {
- fprintf(stderr,"Can't cope with %d bits-per-pixel. Sorry.\n", bpp);
- exit(1);
+ if (bpp == 24) {
+ fprintf(stderr,"Warning: 24 bits-per-pixel may have problems...\n");
+ } else {
+ fprintf(stderr,"Can't cope with %d bits-per-pixel. Sorry.\n", bpp);
+ exit(1);
+ }
}
return bpp;
@@ -394,16 +462,43 @@
for (r = 0; r < 8; r++) {
for (g = 0; g < 8; g++) {
for (b = 0; b < 4; b++) {
- if (BGR233ToPixel[(b<<6) | (g<<3) | r] == INVALID_PIXEL) {
+ int bs = 6, gs = 3, rs = 0;
+ int bm = 3, gm = 7, rm = 7;
+ if (appData.useBGR233 == 64) {
+ bs = 4; gs = 2; rs = 0;
+ bm = 3; gm = 3; rm = 3;
+ }
+ if (appData.useBGR233 == 8) {
+ bs = 2; gs = 1; rs = 0;
+ bm = 1; gm = 1; rm = 1;
+ }
+ if ((b > bm || g > gm || r > rm)) {
+ continue;
+ }
+ if (BGR233ToPixel[(b<<bs) | (g<<gs) | (r<<rs)] == INVALID_PIXEL) {
unsigned long minDistance = ULONG_MAX;
for (i = 0; i < cmapSize; i++) {
if (exactBGR233[i] || shared[i]) {
- unsigned long distance
- = (abs(cmapEntry[i].red - r * 65535 / 7)
- + abs(cmapEntry[i].green - g * 65535 / 7)
- + abs(cmapEntry[i].blue - b * 65535 / 3));
+ unsigned long distance;
+ int r1, g1, b1;
+ if (appData.useGreyScale) {
+ int ave;
+ ave = (r + g + 2*b)/3;
+ r1 = ave;
+ g1 = ave;
+ b1 = ave/2;
+ } else {
+ r1 = r;
+ g1 = g;
+ b1 = b;
+ }
+ distance
+ = ( abs(cmapEntry[i].red - r1 * 65535 / rm)
+ + abs(cmapEntry[i].green - g1 * 65535 / gm)
+ + abs(cmapEntry[i].blue - b1 * 65535 / bm));
+
if (distance < minDistance) {
minDistance = distance;
@@ -412,7 +507,7 @@
}
}
- BGR233ToPixel[(b<<6) | (g<<3) | r] = nearestPixel;
+ BGR233ToPixel[(b<<bs) | (g<<gs) | (r<<rs)] = nearestPixel;
if (shared[nearestPixel] && !usedAsNearest[nearestPixel])
nSharedUsed++;
usedAsNearest[nearestPixel] = True;
@@ -433,6 +528,53 @@
}
}
+static void
+SetupBGR565Map()
+{
+ int r, g, b;
+ int r2, g2, b2;
+ long i, idx;
+ int cnt = 0;
+ unsigned long pixel = 0;
+
+ for (r = 0; r < 32; r++) {
+ for (g = 0; g < 64; g++) {
+ for (b = 0; b < 32; b++) {
+ int bs = 0, gs = 5, rs = 11;
+ int bm = 31, gm = 63, rm = 31;
+ if ((b > bm || g > gm || r > rm)) {
+ continue;
+ }
+ r2 = (255 * r) / rm;
+ g2 = (255 * g) / gm;
+ b2 = (255 * b) / bm;
+
+ pixel = (r2 << 16) | (g2 << 8) | (b2 << 0);
+ if (appData.useGreyScale) {
+ int ave;
+ int r1, g1, b1;
+ ave = (2*r + g + 2*b)/3;
+ r1 = ave/2;
+ g1 = ave;
+ b1 = ave/2;
+
+ r2 = (255 * r1) / rm;
+ g2 = (255 * g1) / gm;
+ b2 = (255 * b1) / bm;
+
+ pixel = (r2 << 16) | (g2 << 8) | (b2 << 0);
+ }
+
+ idx = (b<<bs) | (g<<gs) | (r<<rs);
+ if (0) fprintf(stderr, "cnt: %5d idx: %5d pixel: 0x%08x\n", cnt, idx, pixel);
+ BGR565ToPixel[idx] = pixel;
+ cnt++;
+ }
+ }
+ }
+}
+
+
/*
* AllocateExactBGR233Colours() attempts to allocate each of the colours in the
@@ -484,8 +626,13 @@
ri = rn;
for (gi = 0; gi < gn; gi++) {
for (bi = 0; bi < bn; bi++) {
- if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi]))
- return;
+ if (appData.useBGR233 == 64 && (bv[bi] > 3 || gv[gi] > 3 || rv[ri] > 3)) {
+ nBGR233ColoursAllocated++;
+ } else if (appData.useBGR233 == 8 && (bv[bi] > 1 || gv[gi] > 1 || rv[ri] > 1)) {
+ nBGR233ColoursAllocated++;
+ } else if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) {
+ return;
+ }
}
}
rn++;
@@ -496,8 +643,13 @@
gi = gn;
for (ri = 0; ri < rn; ri++) {
for (bi = 0; bi < bn; bi++) {
- if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi]))
- return;
+ if (appData.useBGR233 == 64 && (bv[bi] > 3 || gv[gi] > 3 || rv[ri] > 3)) {
+ nBGR233ColoursAllocated++;
+ } else if (appData.useBGR233 == 8 && (bv[bi] > 1 || gv[gi] > 1 || rv[ri] > 1)) {
+ nBGR233ColoursAllocated++;
+ } else if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) {
+ return;
+ }
}
}
gn++;
@@ -507,8 +659,13 @@
bi = bn;
for (ri = 0; ri < rn; ri++) {
for (gi = 0; gi < gn; gi++) {
- if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi]))
- return;
+ if (appData.useBGR233 == 64 && (bv[bi] > 3 || gv[gi] > 3 || rv[ri] > 3)) {
+ nBGR233ColoursAllocated++;
+ } else if (appData.useBGR233 == 8 && (bv[bi] > 1 || gv[gi] > 1 || rv[ri] > 1)) {
+ nBGR233ColoursAllocated++;
+ } else if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) {
+ return;
+ }
}
}
bn++;
@@ -529,18 +686,36 @@
AllocateBGR233Colour(int r, int g, int b)
{
XColor c;
+ int bs = 6, gs = 3, rs = 0;
+ int bm = 3, gm = 7, rm = 7;
if (nBGR233ColoursAllocated >= appData.nColours)
return False;
- c.red = r * 65535 / 7;
- c.green = g * 65535 / 7;
- c.blue = b * 65535 / 3;
+ if (appData.useBGR233 == 64) {
+ bs = 4; gs = 2, rs = 0;
+ bm = 3; gm = 3; rm = 3;
+ }
+ if (appData.useBGR233 == 8) {
+ bs = 2; gs = 1, rs = 0;
+ bm = 1; gm = 1; rm = 1;
+ }
+
+ c.red = r * 65535 / rm;
+ c.green = g * 65535 / gm;
+ c.blue = b * 65535 / bm;
+ if (appData.useGreyScale) {
+ int ave;
+ ave = (c.red + c.green + c.blue)/3;
+ c.red = ave;
+ c.green = ave;
+ c.blue = ave;
+ }
if (!XAllocColor(dpy, cmap, &c))
return False;
- BGR233ToPixel[(b<<6) | (g<<3) | r] = c.pixel;
+ BGR233ToPixel[(b<<bs) | (g<<gs) | r] = c.pixel;
nBGR233ColoursAllocated++;
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/corre.c vnc_unixsrc/vncviewer/corre.c
--- vnc_unixsrc.orig/vncviewer/corre.c 2000-06-11 08:00:53.000000000 -0400
+++ vnc_unixsrc/vncviewer/corre.c 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 2007-03-24 10:05:16.000000000 -0400
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+dest=/dist/bin/vncviewerz-1.3dev5-resize
+suc "cp -p $dest $dest.back; mv $dest $dest.unlink; mv $dest.back $dest; rm $dest.unlink"
+strip ./vncviewer
+cat ./vncviewer > $dest
+touch -r ./vncviewer $dest
+yy=/dist/src/apps/VNC/etc/libvncserver_cvs/expts/etv/ssvnc/bin/Linux.i686/vncviewer
+mv $yy $yy.unlink
+cp -p ./vncviewer $yy
+cp -p ./vncviewer $HOME/etv_col/Linux.i686
+chmod 755 $yy
+rm -f $yy.unlink
+ls -l ./vncviewer $dest $yy $HOME/etv_col/Linux.i686/vncviewer
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewer/cursor.c
--- vnc_unixsrc.orig/vncviewer/cursor.c 2003-01-15 04:46:52.000000000 -0500
+++ vnc_unixsrc/vncviewer/cursor.c 2008-10-18 09:35:02.000000000 -0400
@@ -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)
{
@@ -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,170 @@
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, ys, ws, hs;
+ 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) {
+ int i, t = 1;
+ 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 +651,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 2008-10-17 22:12:57.000000000 -0400
@@ -28,28 +28,473 @@
#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;
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 Cursor CreateBogoCursor();
static void CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width,int height);
static void HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev,
Boolean *cont);
+static void CopyBGR565ToScreen(CARD16 *buf, int x, int y, int width,int height);
+
static XtResource desktopBackingStoreResources[] = {
{
- XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof(int), 0,
- 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 (fx != NULL) {
+ *fx = frac_x;
+ }
+ if (fy != NULL) {
+ *fy = frac_y;
+ }
+}
+
+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) {
+ create_image();
+ return;
+ }
+ }
+
+ last_rescale = dnow();
+
+ SoftCursorLockArea(0, 0, si.framebufferWidth, si.framebufferHeight);
+
+ if (image_scale == NULL) {
+ /* switching from not scaled */
+ int i, start_over = 0;
+ 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()) {
+ ShmCleanup();
+ }
+ XDestroyImage(image);
+ fprintf(stderr, "rescale_image: destroyed 'image'\n");
+ 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=0x%x image=0x%x image_ycrop=0x%x\n", image_scale, image, 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);
+ }
+ }
+}
+
+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;
+
+ scale_factor_x = 0.0;
+ scale_factor_y = 0.0;
+ scale_x = 0;
+ scale_y = 0;
+
+ get_scale_values(&frac_x, &frac_y);
+
+ if (frac_x < 0.0) {
+ fprintf(stderr, "Cannot figure out scale factor!\n");
+ } else {
+ 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);
+ }
+ }
+ }
+ 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.yCrop) {
+ int w = si.framebufferWidth;
+ int h = si.framebufferHeight;
+ if (h > 2 * w) {
+ fprintf(stderr, "Tall display (%dx%d) suspect 'x11vnc -ncache' mode,\n", w, h);
+ fprintf(stderr, " setting auto -ycrop detection.\n", w, h);
+ appData.yCrop = -1;
+ }
+ }
+}
/*
* DesktopInitBeforeRealization creates the "desktop" widget and the viewport
@@ -59,91 +504,964 @@
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);
+ w = scale_round(w, frac_x);
+ h = scale_round(h, frac_y);
+ }
- 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 wm, 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;
- }
-#endif
+ hm *= frac_y;
- 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);
- }
- }
+ 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();
}
+static Widget scrollbar_y = NULL;
+
+static int xsst = 2;
+#include <X11/Xaw/Scrollbar.h>
+
+static XtCallbackProc Scrolled(Widget w, XtPointer closure, XtPointer call_data) {
+ Position x, y;
+ XtVaGetValues(desktop, XtNx, &x, XtNy, &y, NULL);
+ if (0) fprintf(stderr, "scrolled by %d pixels x=%d y=%d\n", (int) call_data, x, y);
+ if (xsst == 2) {
+ x = 0;
+ y = 0;
+ XtVaSetValues(desktop, XtNx, x, XtNy, y, NULL);
+ } else if (xsst) {
+ XawScrollbarSetThumb(w, 0.0, 0.0);
+ } else {
+ float t = 0.0;
+ XtVaSetValues(w, XtNtopOfThumb, &t, NULL);
+ }
+}
+
+static XtCallbackProc Jumped(Widget w, XtPointer closure, XtPointer call_data) {
+ float top = *((float *) call_data);
+ Position x, y;
+ XtVaGetValues(desktop, XtNx, &x, XtNy, &y, NULL);
+ if (0) fprintf(stderr, "thumb value: %.4f x=%d y=%d\n", top, x, y);
+ if (top > 0.01) {
+ if (xsst == 2) {
+ x = 0;
+ y = 0;
+ XtVaSetValues(desktop, XtNx, x, XtNy, y, NULL);
+ } else if (xsst) {
+ XawScrollbarSetThumb(w, 0.0, 0.0);
+ } else {
+ float t = 0.0, s = 1.0;
+ XtVaSetValues(w, XtNtopOfThumb, *(XtArgVal*)&t, XtNshown, *(XtArgVal*)&s, NULL);
+ }
+ }
+}
+
+extern double dnow(void);
+
+void check_things() {
+ static int installed_callback = 0;
+ static int first = 1;
+ static double last_scrollbar = 0.0;
+ int w = si.framebufferWidth;
+ int h = si.framebufferHeight;
+ double now = dnow();
+ static double last = 0;
+ 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 doit = 1;
+ int sb = appData.sbWidth;
+ XtVaGetValues(wv, XtNwidth, &w0, XtNheight, &h0, XtNborderWidth, &b0, XtNx, &x0, XtNy, &y0, NULL);
+ XtVaGetValues(wh, XtNwidth, &w1, XtNheight, &h1, XtNborderWidth, &b1, XtNx, &x1, XtNy, &y1, NULL);
+ XtVaGetValues(wc, XtNwidth, &w2, XtNheight, &h2, XtNborderWidth, &b2, NULL);
+ if (!sb) {
+ sb = 2;
+ }
+ if (w0 != sb || h1 != sb) {
+ fprintf(stderr, "Very tall (-ncache) fb, setting scrollbar thickness to: %d pixels (%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;
+ }
+
+ /* 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);
+
+void
+DesktopCursorOff()
+{
+ XSetWindowAttributes attr;
+ unsigned long valuemask;
+
+ if (dotCursor3 == None) {
+ dotCursor3 = CreateDotCursor(3);
+ dotCursor4 = CreateDotCursor(4);
+ }
+ if (appData.viewOnly) {
+ XDefineCursor(dpy, desktopWin, dotCursor4);
+ } else {
+ XDefineCursor(dpy, desktopWin, dotCursor3);
+ }
+ FreeX11Cursor();
+ FreeSoftCursor();
+}
+
+
+#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, y1, x2, 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, n;
+
+ 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;
+ double fmin = factor_x < factor_y ? factor_x : factor_y;
- XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr);
+ 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);//G
+
+ 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;
+
+ 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 (first) fprintf(stderr, " I1=%d I2=%d J1=%d J2=%d\n", I1, I2, J1, J2);//G
+
+ /* 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 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;
+ 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);
+
+ 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);
+ }
+}
+
+//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);
+
+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,39 +1470,116 @@
static void
HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont)
{
- int i;
+ int i, x, y, width, height;
+ static double last_expose = 0.0;
+ double now = dnow();
- switch (ev->type) {
+ 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 (x + width > si.framebufferWidth) {
+ width = si.framebufferWidth - x;
+ if (width <= 0) {
+ break;
+ }
+ }
- if (ev->xexpose.y + ev->xexpose.height > si.framebufferHeight) {
- ev->xexpose.height = si.framebufferHeight - ev->xexpose.y;
- if (ev->xexpose.height <= 0) break;
- }
+ if (y + height > si.framebufferHeight) {
+ height = si.framebufferHeight - y;
+ if (height <= 0) {
+ break;
+ }
+ }
- SendFramebufferUpdateRequest(ev->xexpose.x, ev->xexpose.y,
- ev->xexpose.width, ev->xexpose.height, False);
- break;
+ if (appData.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;
}
+ check_things();
}
@@ -201,6 +1596,13 @@
* button2 down, 3 for both, etc).
*/
+extern Bool selectingSingleWindow;
+
+extern Cursor dotCursor3;
+extern Cursor dotCursor4;
+
+extern void set_server_scale(int);
+
void
SendRFBEvent(Widget w, XEvent *ev, String *params, Cardinal *num_params)
{
@@ -208,12 +1610,71 @@
char keyname[256];
int buttonMask, x, y;
- if (appData.fullScreen && ev->type == MotionNotify) {
- if (BumpScroll(ev))
- return;
- }
+ 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 (appData.fullScreen && ev->type == MotionNotify) {
+ if (BumpScroll(ev)) {
+ return;
+ }
+ }
+
+ if (selectingSingleWindow && ev->type == ButtonPress) {
+ selectingSingleWindow = False;
+ SendSingleWindow(ev->xbutton.x, ev->xbutton.y);
+ if (appData.viewOnly) {
+ XDefineCursor(dpy, desktopWin, dotCursor4);
+ } else {
+ XDefineCursor(dpy, desktopWin, dotCursor3);
+ }
+ return;
+ }
- if (appData.viewOnly) return;
+ if (appData.viewOnly) {
+ int W = si.framebufferWidth;
+ int H = si.framebufferHeight;
+ if (*num_params != 0) {
+ if (strcasecmp(params[0],"fbupdate") == 0) {
+ SendFramebufferUpdateRequest(0, 0, W, H, False);
+ }
+ }
+ if (ev->type == ButtonRelease) {
+ XButtonEvent *b = (XButtonEvent *) ev;
+ if (b->state & Button3Mask) {
+ ShowPopup(w, ev, params, num_params);
+ }
+ } else if (ev->type == KeyRelease) {
+ XLookupString(&ev->xkey, keyname, 256, &ks, NULL);
+ if (ks == XK_1 || ks == XK_KP_1 || ks == XK_KP_End) {
+ set_server_scale(1);
+ } else if (ks == XK_2 || ks == XK_KP_2 || ks == XK_KP_Down) {
+ set_server_scale(2);
+ } else if (ks == XK_3 || ks == XK_KP_3 || ks == XK_KP_Next) {
+ set_server_scale(3);
+ } else if (ks == XK_4 || ks == XK_KP_4) {
+ set_server_scale(4);
+ } else if (ks == XK_5 || ks == XK_KP_5) {
+ set_server_scale(5);
+ } else if (ks == XK_6 || ks == XK_KP_6) {
+ set_server_scale(6);
+ } else if (ks == XK_r || ks == XK_R) {
+ SendFramebufferUpdateRequest(0, 0, W, H, False);
+ } else if (ks == XK_b || ks == XK_B) {
+ ToggleBell(w, ev, params, num_params);
+ } else if (ks == XK_f || ks == XK_F) {
+ Toggle8bpp(w, ev, params, num_params);
+ } else if (ks == XK_V) {
+ ToggleViewOnly(w, ev, params, num_params);
+ }
+ }
+ return;
+ }
if (*num_params != 0) {
if (strncasecmp(params[0],"key",3) == 0) {
@@ -245,8 +1706,8 @@
fprintf(stderr, "Invalid params: SendRFBEvent(fbupdate)\n");
return;
}
- SendFramebufferUpdateRequest(0, 0, si.framebufferWidth,
- si.framebufferHeight, False);
+ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False);
+
} else if (strcasecmp(params[0],"ptr") == 0) {
if (*num_params == 4) {
x = atoi(params[1]);
@@ -329,26 +1790,185 @@
* CreateDotCursor.
*/
+#ifndef very_small_dot_cursor
+static Cursor
+CreateDotCursor(int which)
+{
+ Cursor cursor;
+ Pixmap src, msk;
+ static char srcBits3[] = { 0x00, 0x02, 0x00 };
+ static char mskBits3[] = { 0x02, 0x07, 0x02 };
+ static char srcBits4[] = { 0x00, 0x06, 0x06, 0x00 };
+ static char mskBits4[] = { 0x06, 0x0f, 0x0f, 0x06 };
+ XColor fg, bg;
+
+ if (which == 3) {
+ src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits3, 3, 3);
+ msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits3, 3, 3);
+ } else {
+ src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits4, 4, 4);
+ msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits4, 4, 4);
+ }
+ XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "black",
+ &fg, &fg);
+ XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "white",
+ &bg, &bg);
+ cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 1, 1);
+ XFreePixmap(dpy, src);
+ XFreePixmap(dpy, msk);
+
+ return cursor;
+}
+#else
static Cursor
CreateDotCursor()
{
- Cursor cursor;
- Pixmap src, msk;
- static char srcBits[] = { 0, 14,14,14, 0 };
- static char mskBits[] = { 14,31,31,31,14 };
- XColor fg, bg;
-
- src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits, 5, 5);
- msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits, 5, 5);
- XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "black",
- &fg, &fg);
- XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "white",
- &bg, &bg);
- cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 2, 2);
- XFreePixmap(dpy, src);
- XFreePixmap(dpy, msk);
+ Cursor cursor;
+ Pixmap src, msk;
+ static char srcBits[] = { 0, 14, 0 };
+ static char mskBits[] = { 14,31,14 };
+ XColor fg, bg;
+
+ src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits, 3, 3);
+ msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits, 3, 3);
+ XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "black",
+ &fg, &fg);
+ XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "white",
+ &bg, &bg);
+ cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 1, 1);
+ XFreePixmap(dpy, src);
+ XFreePixmap(dpy, msk);
- return cursor;
+ return cursor;
+}
+#endif
+
+int skip_maybe_sync = 0;
+void maybe_sync(int width, int height) {
+ static int singles = 0;
+ if (skip_maybe_sync) {
+ return;
+ }
+ if (width > 1 || height > 1) {
+ XSync(dpy, False);
+ singles = 0;
+ } else {
+ if (++singles >= 32) {
+ singles = 0;
+ XSync(dpy, False);
+ }
+ }
+}
+/*
+ * FillImage.
+ */
+
+void
+FillScreen(int x, int y, int width, int height, unsigned long fill)
+{
+ 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;
+
+//fprintf(stderr, "FillImage bpp=%d %04dx%04d+%04d+%04d -- 0x%x\n", bpp, width, height, x, y, fill);
+ if (appData.chatOnly) {
+ return;
+ }
+
+ if (widthInBytes > buflen || !buf) {
+ if (buf) {
+ free(buf);
+ }
+ buflen = widthInBytes * 2;
+ buf = (char *)malloc(buflen);
+ }
+ ucp = (unsigned char*) buf;
+ usp = (unsigned short*) buf;
+ uip = (unsigned int*) buf;
+
+ if (isLSB) {
+ b0 = 0; b1 = 1; b2 = 2;
+ } else {
+ b0 = 2; b1 = 1; b2 = 0;
+ }
+
+ for (h = 0; h < width; h++) {
+ if (bpp == 8) {
+ *(ucp+h) = (unsigned char) fill;
+ } else if (bpp == 16) {
+ *(usp+h) = (unsigned short) fill;
+ } else if (bpp == 24) {
+ *(ucp + 3*h + b0) = (unsigned char) ((fill & 0x0000ff) >> 0);
+ *(ucp + 3*h + b1) = (unsigned char) ((fill & 0x00ff00) >> 8);
+ *(ucp + 3*h + b2) = (unsigned char) ((fill & 0xff0000) >> 16);
+ } else if (bpp == 32) {
+ *(uip+h) = (unsigned int) fill;
+ }
+ }
+
+ 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;
+
+//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);
+ 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;
+ }
}
@@ -359,38 +1979,37 @@
void
CopyDataToScreen(char *buf, int x, int y, int width, int height)
{
- if (appData.rawDelay != 0) {
- XFillRectangle(dpy, desktopWin, gc, x, y, width, height);
-
- XSync(dpy,False);
-
- usleep(appData.rawDelay * 1000);
- }
+ if (appData.chatOnly) {
+ return;
+ }
+ if (appData.rawDelay != 0) {
+ XFillRectangle(dpy, desktopWin, gc, x, y, width, height);
+ XSync(dpy,False);
+ usleep(appData.rawDelay * 1000);
+ }
- if (!appData.useBGR233) {
- int h;
- int widthInBytes = width * myFormat.bitsPerPixel / 8;
- int scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8;
-
- char *scr = (image->data + y * scrWidthInBytes
- + x * myFormat.bitsPerPixel / 8);
-
- for (h = 0; h < height; h++) {
- memcpy(scr, buf, widthInBytes);
- buf += widthInBytes;
- scr += scrWidthInBytes;
- }
- } else {
- CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height);
- }
+ if (appData.useBGR233) {
+ CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height);
+ } else if (appData.useBGR565) {
+ CopyBGR565ToScreen((CARD16 *)buf, x, y, width, height);
+ } else {
+ int h;
+ int widthInBytes = width * myFormat.bitsPerPixel / 8;
+ int scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8;
+ XImage *im = image_scale ? image_scale : image;
+
+ char *scr = (im->data + y * scrWidthInBytes
+ + x * myFormat.bitsPerPixel / 8);
+
+ for (h = 0; h < height; h++) {
+ memcpy(scr, buf, widthInBytes);
+ buf += widthInBytes;
+ scr += scrWidthInBytes;
+ }
+ }
-#ifdef MITSHM
- if (appData.useShm) {
- XShmPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height, False);
- return;
- }
-#endif
- XPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height);
+ put_image(x, y, x, y, width, height, 0);
+ maybe_sync(width, height);
}
@@ -401,62 +2020,295 @@
static void
CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width, int height)
{
- int p, q;
- int xoff = 7 - (x & 7);
- int xcur;
- int fbwb = si.framebufferWidth / 8;
- CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8;
- CARD8 *scrt;
- CARD8 *scr8 = ((CARD8 *)image->data) + y * si.framebufferWidth + x;
- CARD16 *scr16 = ((CARD16 *)image->data) + y * si.framebufferWidth + x;
- CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x;
+ int p, q;
+ int xoff = 7 - (x & 7);
+ int xcur;
+ int fbwb = si.framebufferWidth / 8;
+ XImage *im = image_scale ? image_scale : image;
+ CARD8 *scr1 = ((CARD8 *)im->data) + y * fbwb + x / 8;
+ CARD8 *scrt;
+ CARD8 *scr8 = ( (CARD8 *)im->data) + y * si.framebufferWidth + x;
+ CARD16 *scr16 = ((CARD16 *)im->data) + y * si.framebufferWidth + x;
+ CARD32 *scr32 = ((CARD32 *)im->data) + y * si.framebufferWidth + x;
+ int b0, b1, b2;
- switch (visbpp) {
+ switch (visbpp) {
/* thanks to Chris Hooper for single bpp support */
- case 1:
- for (q = 0; q < height; q++) {
- xcur = xoff;
- scrt = scr1;
- for (p = 0; p < width; p++) {
- *scrt = ((*scrt & ~(1 << xcur))
- | (BGR233ToPixel[*(buf++)] << xcur));
-
- if (xcur-- == 0) {
- xcur = 7;
- scrt++;
+ case 1:
+ for (q = 0; q < height; q++) {
+ xcur = xoff;
+ scrt = scr1;
+ for (p = 0; p < width; p++) {
+ *scrt = ((*scrt & ~(1 << xcur))
+ | (BGR233ToPixel[*(buf++)] << xcur));
+
+ if (xcur-- == 0) {
+ xcur = 7;
+ scrt++;
+ }
+ }
+ scr1 += fbwb;
+ }
+ break;
+
+ case 8:
+ for (q = 0; q < height; q++) {
+ for (p = 0; p < width; p++) {
+ *(scr8++) = BGR233ToPixel[*(buf++)];
+ }
+ scr8 += si.framebufferWidth - width;
+ }
+ break;
+
+ case 16:
+ for (q = 0; q < height; q++) {
+ for (p = 0; p < width; p++) {
+ *(scr16++) = BGR233ToPixel[*(buf++)];
+ }
+ scr16 += si.framebufferWidth - width;
+ }
+ break;
+
+ case 24:
+ if (isLSB) {
+ b0 = 0; b1 = 1; b2 = 2;
+ } else {
+ b0 = 2; b1 = 1; b2 = 0;
+ }
+ scr8 = ((CARD8 *)im->data) + (y * si.framebufferWidth + x) * 3;
+ for (q = 0; q < height; q++) {
+ for (p = 0; p < width; p++) {
+ CARD32 v = BGR233ToPixel[*(buf++)];
+ *(scr8 + b0) = (unsigned char) ((v & 0x0000ff) >> 0);
+ *(scr8 + b1) = (unsigned char) ((v & 0x00ff00) >> 8);
+ *(scr8 + b2) = (unsigned char) ((v & 0xff0000) >> 16);
+ scr8 += 3;
+ }
+ scr8 += (si.framebufferWidth - width) * 3;
+ }
+ break;
+
+ case 32:
+ for (q = 0; q < height; q++) {
+ for (p = 0; p < width; p++) {
+ *(scr32++) = BGR233ToPixel[*(buf++)];
+ }
+ scr32 += si.framebufferWidth - width;
+ }
+ break;
}
- }
- scr1 += fbwb;
- }
- break;
+}
- case 8:
- for (q = 0; q < height; q++) {
- for (p = 0; p < width; p++) {
- *(scr8++) = BGR233ToPixel[*(buf++)];
- }
- scr8 += si.framebufferWidth - width;
- }
- break;
+static void
+BGR565_24bpp(CARD16 *buf, int x, int y, int width, int height)
+{
+ int p, q;
+ int b0, b1, b2;
+ XImage *im = image_scale ? image_scale : image;
+ unsigned char *scr= (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 16:
- for (q = 0; q < height; q++) {
- for (p = 0; p < width; p++) {
- *(scr16++) = BGR233ToPixel[*(buf++)];
- }
- scr16 += si.framebufferWidth - width;
- }
- break;
+ /* case 24: */
+ for (q = 0; q < height; q++) {
+ for (p = 0; p < width; p++) {
+ CARD32 v = BGR565ToPixel[*(buf++)];
+ *(scr + b0) = (unsigned char) ((v & 0x0000ff) >> 0);
+ *(scr + b1) = (unsigned char) ((v & 0x00ff00) >> 8);
+ *(scr + b2) = (unsigned char) ((v & 0xff0000) >> 16);
+ scr += 3;
+ }
+ scr += (si.framebufferWidth - width) * 3;
+ }
+}
- case 32:
- for (q = 0; q < height; q++) {
- for (p = 0; p < width; p++) {
- *(scr32++) = BGR233ToPixel[*(buf++)];
- }
- scr32 += si.framebufferWidth - width;
- }
- break;
- }
+static void
+CopyBGR565ToScreen(CARD16 *buf, int x, int y, int width, int height)
+{
+ int p, q;
+ XImage *im = image_scale ? image_scale : image;
+ CARD32 *scr32 = ((CARD32 *)im->data) + y * si.framebufferWidth + x;
+
+ if (visbpp == 24) {
+ BGR565_24bpp(buf, x, y, width, height);
+ return;
+ }
+
+ /* case 32: */
+ for (q = 0; q < height; q++) {
+ for (p = 0; p < width; p++) {
+ *(scr32++) = BGR565ToPixel[*(buf++)];
+ }
+ scr32 += si.framebufferWidth - width;
+ }
+}
+
+static void reset_image(void) {
+ if (UsingShm()) {
+ ShmCleanup();
+ }
+ if (image && image->data) {
+ XDestroyImage(image);
+ 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;
+
+ create_image();
+ XFlush(dpy);
+}
+
+void ReDoDesktop(void) {
+ int w, h, h0, x, y, dw, dh;
+ int fs = 0;
+ int autoscale = 0;
+
+ if (!appData.fullScreen && appData.scale != NULL && !strcmp(appData.scale, "auto")) {
+ autoscale = 1;
+ }
+
+ fprintf(stderr, "ReDoDesktop: ycrop: %d\n", appData.yCrop);
+
+ check_tall();
+
+ if (appData.yCrop) {
+ if (appData.yCrop < 0 || old_width <= 0) {
+ appData.yCrop = guessCrop();
+ fprintf(stderr, "Set -ycrop to: %d\n", appData.yCrop);
+ } else {
+ int w1 = si.framebufferWidth;
+ int w0 = old_width;
+ appData.yCrop = (w1 * appData.yCrop) / old_width;
+ if (appData.yCrop <= 100) {
+ appData.yCrop = guessCrop();
+ fprintf(stderr, "Set small -ycrop to: %d\n", appData.yCrop);
+ }
+ }
+ fprintf(stderr, "Using -ycrop: %d\n", appData.yCrop);
+ }
+
+ old_width = si.framebufferWidth;
+ old_height = si.framebufferHeight;
+
+ if (appData.fullScreen) {
+ if (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;
+ 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);
+ 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, w, XtNheight, h0, NULL);
+
+ x = (dpyWidth - w - dw)/2;
+ y = (dpyHeight - h - dh)/2;
+
+ XtResizeWidget(desktop, w, 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);
+ }
+
+ if (!autoscale) {
+ 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 2008-10-10 15:46:43.000000000 -0400
@@ -26,6 +26,299 @@
static Bool serverDialogDone = False;
static Bool passwordDialogDone = False;
+static Bool ycropDialogDone = False;
+static Bool scaleDialogDone = False;
+static Bool scbarDialogDone = False;
+static Bool scaleNDialogDone = False;
+static Bool qualityDialogDone = False;
+static Bool compressDialogDone = False;
+
+extern void popupFixer(Widget wid);
+
+void
+ScaleDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ scaleDialogDone = True;
+}
+
+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;
+}
+
+char *
+DoScaleDialog()
+{
+ Widget pshell, dialog;
+ char *scaleValue;
+ char *valueString;
+
+ pshell = XtVaCreatePopupShell("scaleDialog", transientShellWidgetClass,
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
+ dialog_over(pshell);
+
+ 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 (appData.popupFix) {
+ popupFixer(pshell);
+ }
+ dialog_input(pshell);
+
+ scaleDialogDone = False;
+
+ while (!scaleDialogDone) {
+ XtAppProcessEvent(appContext, XtIMAll);
+ }
+
+ valueString = XawDialogGetValueString(dialog);
+ scaleValue = XtNewString(valueString);
+
+ XtPopdown(pshell);
+ return scaleValue;
+}
+
+void
+YCropDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ ycropDialogDone = True;
+}
+
+char *
+DoYCropDialog()
+{
+ Widget pshell, dialog;
+ char *ycropValue;
+ char *valueString;
+
+ pshell = XtVaCreatePopupShell("ycropDialog", transientShellWidgetClass,
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
+ dialog_over(pshell);
+
+ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
+ HeightOfScreen(XtScreen(pshell))*2/5);
+ XtPopup(pshell, XtGrabNonexclusive);
+ XtRealizeWidget(pshell);
+
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
+ dialog_input(pshell);
+
+ ycropDialogDone = False;
+
+ while (!ycropDialogDone) {
+ XtAppProcessEvent(appContext, XtIMAll);
+ }
+
+ valueString = XawDialogGetValueString(dialog);
+ ycropValue = XtNewString(valueString);
+
+ XtPopdown(pshell);
+ return ycropValue;
+}
+
+void
+ScbarDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ scbarDialogDone = True;
+}
+
+char *
+DoScbarDialog()
+{
+ Widget pshell, dialog;
+ char *scbarValue;
+ char *valueString;
+
+ pshell = XtVaCreatePopupShell("scbarDialog", transientShellWidgetClass,
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
+ dialog_over(pshell);
+
+ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
+ HeightOfScreen(XtScreen(pshell))*2/5);
+ XtPopup(pshell, XtGrabNonexclusive);
+ XtRealizeWidget(pshell);
+
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
+ dialog_input(pshell);
+
+ scbarDialogDone = False;
+
+ while (!scbarDialogDone) {
+ XtAppProcessEvent(appContext, XtIMAll);
+ }
+
+ valueString = XawDialogGetValueString(dialog);
+ scbarValue = XtNewString(valueString);
+
+ XtPopdown(pshell);
+ return scbarValue;
+}
+
+void
+ScaleNDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ scaleNDialogDone = True;
+}
+
+char *
+DoScaleNDialog()
+{
+ Widget pshell, dialog;
+ char *scaleNValue;
+ char *valueString;
+
+ pshell = XtVaCreatePopupShell("scaleNDialog", transientShellWidgetClass,
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
+ dialog_over(pshell);
+
+ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
+ HeightOfScreen(XtScreen(pshell))*2/5);
+ XtPopup(pshell, XtGrabNonexclusive);
+ XtRealizeWidget(pshell);
+
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
+ dialog_input(pshell);
+
+ scaleNDialogDone = False;
+
+ while (!scaleNDialogDone) {
+ XtAppProcessEvent(appContext, XtIMAll);
+ }
+
+ valueString = XawDialogGetValueString(dialog);
+ scaleNValue = XtNewString(valueString);
+
+ XtPopdown(pshell);
+ return scaleNValue;
+}
+
+void
+QualityDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ qualityDialogDone = True;
+}
+
+char *
+DoQualityDialog()
+{
+ Widget pshell, dialog;
+ char *qualityValue;
+ char *valueString;
+
+ pshell = XtVaCreatePopupShell("qualityDialog", transientShellWidgetClass,
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
+ dialog_over(pshell);
+
+ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
+ HeightOfScreen(XtScreen(pshell))*2/5);
+ XtPopup(pshell, XtGrabNonexclusive);
+ XtRealizeWidget(pshell);
+
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
+ dialog_input(pshell);
+
+ qualityDialogDone = False;
+
+ while (!qualityDialogDone) {
+ XtAppProcessEvent(appContext, XtIMAll);
+ }
+
+ valueString = XawDialogGetValueString(dialog);
+ qualityValue = XtNewString(valueString);
+
+ XtPopdown(pshell);
+ return qualityValue;
+}
+
+void
+CompressDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ compressDialogDone = True;
+}
+
+char *
+DoCompressDialog()
+{
+ Widget pshell, dialog;
+ char *compressValue;
+ char *valueString;
+
+ pshell = XtVaCreatePopupShell("compressDialog", transientShellWidgetClass,
+ toplevel, NULL);
+ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+
+ dialog_over(pshell);
+
+ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
+ HeightOfScreen(XtScreen(pshell))*2/5);
+ XtPopup(pshell, XtGrabNonexclusive);
+ XtRealizeWidget(pshell);
+
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
+ dialog_input(pshell);
+
+ compressDialogDone = False;
+
+ while (!compressDialogDone) {
+ XtAppProcessEvent(appContext, XtIMAll);
+ }
+
+ valueString = XawDialogGetValueString(dialog);
+ compressValue = XtNewString(valueString);
+
+ XtPopdown(pshell);
+ return compressValue;
+}
void
ServerDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params)
@@ -44,11 +337,18 @@
toplevel, NULL);
dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+ dialog_over(pshell);
+
XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
HeightOfScreen(XtScreen(pshell))*2/5);
XtPopup(pshell, XtGrabNonexclusive);
XtRealizeWidget(pshell);
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
+ dialog_input(pshell);
+
serverDialogDone = False;
while (!serverDialogDone) {
@@ -80,11 +380,18 @@
toplevel, NULL);
dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL);
+ dialog_over(pshell);
+
XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5,
HeightOfScreen(XtScreen(pshell))*2/5);
XtPopup(pshell, XtGrabNonexclusive);
XtRealizeWidget(pshell);
+ if (appData.popupFix) {
+ popupFixer(pshell);
+ }
+ dialog_input(pshell);
+
passwordDialogDone = False;
while (!passwordDialogDone) {
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/fullscreen.c vnc_unixsrc/vncviewer/fullscreen.c
--- vnc_unixsrc.orig/vncviewer/fullscreen.c 2003-10-09 05:23:49.000000000 -0400
+++ vnc_unixsrc/vncviewer/fullscreen.c 2008-10-12 15:12:52.000000000 -0400
@@ -27,7 +27,9 @@
#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;
@@ -36,6 +38,7 @@
static Dimension scrollbarWidth, scrollbarHeight;
+int scale_round(int len, double fac);
/*
* FullScreenOn goes into full-screen mode. It makes the toplevel window
@@ -78,112 +81,450 @@
* 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;
+ int _NET_WM_STATE_TOGGLE = 2;
+ 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);
+ //XtVaSetValues(viewport, XtNoverrideRedirect, True, NULL);
+ //XtVaSetValues(desktop, XtNoverrideRedirect, True, NULL);
+ 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. */
+
+// XtVaSetValues(toplevel, XtNwidth, toplevelWidth, XtNheight, toplevelHeight, NULL);
+// XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0);
+ 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 +546,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 +600,40 @@
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);
+ //XtVaSetValues(viewport, XtNoverrideRedirect, False, NULL);
+ //XtVaSetValues(desktop, XtNoverrideRedirect, False, NULL);
+ 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 +645,11 @@
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);
+ }
}
@@ -278,11 +660,11 @@
void
ToggleFullScreen(Widget w, XEvent *ev, String *params, Cardinal *num_params)
{
- if (appData.fullScreen) {
- FullScreenOff();
- } else {
- FullScreenOn();
- }
+ if (appData.fullScreen) {
+ FullScreenOff();
+ } else {
+ FullScreenOn();
+ }
}
@@ -294,84 +676,220 @@
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();
+}
+
+/* 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();
+}
+void JumpRight(Widget w, XEvent *ev, String *params, Cardinal *num_params) {
+ JumpScroll(1, 0);
+}
+void JumpLeft(Widget w, XEvent *ev, String *params, Cardinal *num_params) {
+ JumpScroll(0, 0);
+}
+void JumpUp(Widget w, XEvent *ev, String *params, Cardinal *num_params) {
+ JumpScroll(1, 1);
}
+void JumpDown(Widget w, XEvent *ev, String *params, Cardinal *num_params) {
+ JumpScroll(0, 1);
+}
+
+
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/h2html.pl vnc_unixsrc/vncviewer/h2html.pl
--- vnc_unixsrc.orig/vncviewer/h2html.pl 1969-12-31 19:00:00.000000000 -0500
+++ vnc_unixsrc/vncviewer/h2html.pl 2008-08-30 20:34:45.000000000 -0400
@@ -0,0 +1,10 @@
+#!/usr/bin/perl
+
+open(HELP, "./vncviewer -help|");
+
+while (<HELP>) {
+ $_ =~ s/&/&amp;/g;
+ $_ =~ s/</&lt;/g;
+ $_ =~ s/>/&gt;/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 2008-10-05 15:16:24.000000000 -0400
@@ -30,6 +30,18 @@
#define CARDBPP CONCAT2E(CARD,BPP)
#define GET_PIXEL CONCAT2E(GET_PIXEL,BPP)
+#define FillRectangle(x, y, w, h, color) \
+ { \
+ XGCValues _gcv; \
+ _gcv.foreground = color; \
+ if (!appData.useXserverBackingStore) { \
+ FillScreen(x, y, w, h, _gcv.foreground); \
+ } else { \
+ XChangeGC(dpy, gc, GCForeground, &_gcv); \
+ XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \
+ } \
+ }
+
static Bool
HandleHextileBPP (int rx, int ry, int rw, int rh)
{
@@ -66,14 +78,25 @@
return False;
#if (BPP == 8)
- if (appData.useBGR233)
+ if (appData.useBGR233) {
gcv.foreground = BGR233ToPixel[bg];
- else
+ } else
#endif
+#if (BPP == 16)
+ if (appData.useBGR565) {
+ gcv.foreground = BGR565ToPixel[bg];
+ } else
+#endif
+ {
gcv.foreground = bg;
+ }
- XChangeGC(dpy, gc, GCForeground, &gcv);
- XFillRectangle(dpy, desktopWin, gc, x, y, w, h);
+#if 0
+ XChangeGC(dpy, gc, GCForeground, &gcv);
+ XFillRectangle(dpy, desktopWin, gc, x, y, w, h);
+#else
+ FillRectangle(x, y, w, h, gcv.foreground);
+#endif
if (subencoding & rfbHextileForegroundSpecified)
if (!ReadFromRFBServer((char *)&fg, sizeof(fg)))
@@ -101,14 +124,25 @@
sh = rfbHextileExtractH(*ptr);
ptr++;
#if (BPP == 8)
- if (appData.useBGR233)
+ if (appData.useBGR233) {
gcv.foreground = BGR233ToPixel[fg];
- else
+ } else
+#endif
+#if (BPP == 16)
+ if (appData.useBGR565) {
+ gcv.foreground = BGR565ToPixel[fg];
+ } else
#endif
+ {
gcv.foreground = fg;
+ }
- XChangeGC(dpy, gc, GCForeground, &gcv);
- XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh);
+#if 0
+ XChangeGC(dpy, gc, GCForeground, &gcv);
+ XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh);
+#else
+ FillRectangle(x+sx, y+sy, sw, sh, gcv.foreground);
+#endif
}
} else {
@@ -116,13 +150,22 @@
return False;
#if (BPP == 8)
- if (appData.useBGR233)
+ if (appData.useBGR233) {
gcv.foreground = BGR233ToPixel[fg];
- else
+ } else
#endif
+#if (BPP == 16)
+ if (appData.useBGR565) {
+ gcv.foreground = BGR565ToPixel[fg];
+ } else
+#endif
+ {
gcv.foreground = fg;
+ }
+#if 0
XChangeGC(dpy, gc, GCForeground, &gcv);
+#endif
for (i = 0; i < nSubrects; i++) {
sx = rfbHextileExtractX(*ptr);
@@ -131,7 +174,11 @@
sw = rfbHextileExtractW(*ptr);
sh = rfbHextileExtractH(*ptr);
ptr++;
+#if 0
XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh);
+#else
+ FillRectangle(x+sx, y+sy, sw, sh, gcv.foreground);
+#endif
}
}
}
@@ -139,3 +186,5 @@
return True;
}
+
+#undef FillRectangle
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/listen.c vnc_unixsrc/vncviewer/listen.c
--- vnc_unixsrc.orig/vncviewer/listen.c 2001-01-16 03:07:57.000000000 -0500
+++ vnc_unixsrc/vncviewer/listen.c 2008-09-26 15:43:23.000000000 -0400
@@ -32,6 +32,7 @@
#define FLASHDELAY 1 /* seconds */
Bool listenSpecified = False;
+pid_t listenParent = 0;
int listenPort = 0, flashPort = 0;
static Font flashFont;
@@ -58,8 +59,11 @@
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) {
@@ -108,23 +112,40 @@
exit(1);
}
- getFlashFont(d);
+//getFlashFont(d);
listenSocket = ListenAtTcpPort(listenPort);
- flashSocket = ListenAtTcpPort(flashPort);
+
+//flashSocket = ListenAtTcpPort(flashPort);
+ flashSocket = 1234;
if ((listenSocket < 0) || (flashSocket < 0)) exit(1);
- fprintf(stderr,"%s -listen: Listening on port %d (flash port %d)\n",
- programName,listenPort,flashPort);
- fprintf(stderr,"%s -listen: Command line errors are not reported until "
+ fprintf(stderr,"%s -listen: Listening on port %d\n",
+ programName,listenPort);
+ fprintf(stderr,"%s -listen: Cmdline errors are not reported until "
"a connection comes in.\n", programName);
+ /* this will only work if X events drives this loop -- they don't */
+ if (getenv("SSVNC_MAX_LISTEN")) {
+ maxconn = atoi(getenv("SSVNC_MAX_LISTEN"));
+ }
+
while (True) {
/* reap any zombies */
int status, pid;
- while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0);
+ while ((pid = wait3(&status, WNOHANG, (struct rusage *)0))>0) {
+ if (pid > 0 && children > 0) {
+ children--;
+ /* this will only work if X events drives this loop -- they don't */
+ if (maxconn > 0 && totalconn >= maxconn) {
+ fprintf(stderr,"%s -listen: Finished final connection %d\n",
+ programName, maxconn);
+ exit(0);
+ }
+ }
+ }
/* discard any X events */
while (XCheckIfEvent(d, &ev, AllXEventsPredicate, NULL))
@@ -132,12 +153,24 @@
FD_ZERO(&fds);
- FD_SET(flashSocket, &fds);
+// FD_SET(flashSocket, &fds);
FD_SET(listenSocket, &fds);
FD_SET(ConnectionNumber(d), &fds);
select(FD_SETSIZE, &fds, NULL, NULL, NULL);
+ while ((pid = wait3(&status, WNOHANG, (struct rusage *)0))>0) {
+ if (pid > 0 && children > 0) {
+ children--;
+ if (maxconn > 0 && totalconn >= maxconn) {
+ fprintf(stderr,"%s -listen: Finished final connection %d\n",
+ programName, maxconn);
+ exit(0);
+ }
+ }
+ }
+
+#if 0
if (FD_ISSET(flashSocket, &fds)) {
sock = AcceptTcpConnection(flashSocket);
@@ -151,11 +184,48 @@
}
close(sock);
}
+#endif
if (FD_ISSET(listenSocket, &fds)) {
- rfbsock = AcceptTcpConnection(listenSocket);
- if (rfbsock < 0) exit(1);
- if (!SetNonBlocking(rfbsock)) exit(1);
+ int multi_ok = 0;
+ char *sml = getenv("SSVNC_MULTIPLE_LISTEN");
+
+ rfbsock = AcceptTcpConnection(listenSocket);
+
+ if (sml != NULL) {
+ if (strstr(sml, "MAX:") == sml || strstr(sml, "max:") == sml) {
+ char *q = strchr(sml, ':');
+ int maxc = atoi(q+1);
+ if (maxc == 0 && strcmp(q+1, "0")) {
+ maxc = -99;
+ }
+ if (maxc < 0) {
+ fprintf(stderr, "invalid SSVNC_MULTIPLE_LISTEN=MAX:n, %s, must be 0 or positive, using 1\n", sml);
+ } else if (maxc == 0) {
+ multi_ok = 1;
+ } else if (children < maxc) {
+ multi_ok = 1;
+ }
+ } else if (strcmp(sml, "") && strcmp(sml, "0")) {
+ multi_ok = 1;
+ }
+ }
+
+ if (rfbsock < 0) exit(1);
+ if (!SetNonBlocking(rfbsock)) exit(1);
+
+ if (children > 0 && !multi_ok) {
+ fprintf(stderr,"\n");
+ fprintf(stderr,"%s: denying extra incoming connection (%d already)\n",
+ programName, children);
+ fprintf(stderr,"%s: to override: use '-multilisten' or set SSVNC_MULTIPLE_LISTEN=1\n",
+ programName);
+ fprintf(stderr,"\n");
+ close(rfbsock);
+ rfbsock = -1;
+ continue;
+ }
+ totalconn++;
XCloseDisplay(d);
@@ -170,18 +240,23 @@
case 0:
/* child - return to caller */
close(listenSocket);
- close(flashSocket);
+// close(flashSocket);
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);
}
- getFlashFont(d);
+// getFlashFont(d);
+ fprintf(stderr,"\n\n%s -listen: Listening on port %d\n",
+ programName,listenPort);
+ fprintf(stderr,"%s -listen: Cmdline errors are not reported until "
+ "a connection comes in.\n\n", programName);
break;
}
}
@@ -200,6 +275,13 @@
char **fontNames;
int nFontNames;
+#if 1
+
+ /* no longer used */
+ return;
+
+#else
+
sprintf(fontName,"-*-courier-bold-r-*-*-%d-*-*-*-*-*-iso8859-1",
FLASHWIDTH);
fontNames = XListFonts(d, fontName, 1, &nFontNames);
@@ -209,6 +291,9 @@
sprintf(fontName,"fixed");
}
flashFont = XLoadFont(d, fontName);
+
+#endif
+
}
@@ -222,6 +307,11 @@
Window w1, w2, w3, w4;
XSetWindowAttributes attr;
+#if 1
+ /* no longer used */
+ return;
+#else
+
XBell(d, 0);
XForceScreenSaver(d, ScreenSaverReset);
@@ -284,6 +374,9 @@
XDestroyWindow(d, w3);
XDestroyWindow(d, w4);
XFlush(d);
+
+#endif
+
}
/*
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 2008-10-14 22:32:04.000000000 -0400
@@ -33,12 +33,14 @@
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;
/*
* ToplevelInitBeforeRealization sets the title, geometry and other resources
@@ -48,87 +50,103 @@
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) {
+ 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;
+
+ /* 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 +159,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 +183,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 +216,15 @@
* 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);
}
@@ -264,11 +285,9 @@
* 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();
+ exit(0);
}
@@ -276,49 +295,90 @@
* 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) {
+ 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;
+ }
+ 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();
+ exit(1);
}
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer/popup.c
--- vnc_unixsrc.orig/vncviewer/popup.c 2000-06-11 08:00:53.000000000 -0400
+++ vnc_unixsrc/vncviewer/popup.c 2008-10-15 08:26:28.000000000 -0400
@@ -25,22 +25,55 @@
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Command.h>
+#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Toggle.h>
Widget popup, fullScreenToggle;
+void popupFixer(Widget wid) {
+ Window rr, cr;
+ unsigned int m;
+ int x0 = 500, y0 = 500;
+ int xr, yr, wxr, wyr;
+ Dimension ph;
+ if (XQueryPointer(dpy, DefaultRootWindow(dpy), &rr, &cr, &xr, &yr, &wxr, &wyr, &m)) {
+ x0 = xr;
+ y0 = yr;
+ }
+ XtPopup(wid, XtGrabNone);
+ XtVaGetValues(wid, XtNheight, &ph, NULL);
+ if (y0 + (int) ph > dpyHeight) {
+ y0 = dpyHeight - (int) ph;
+ if (y0 < 0) {
+ y0 = 0;
+ }
+ }
+ XtMoveWidget(wid, x0, y0);
+}
+
+void Noop(Widget w, XEvent *event, String *params, Cardinal *num_params) {
+ //fprintf(stderr, "No-op\n");
+}
+
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);
}
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);
}
@@ -52,42 +85,541 @@
};
void
-CreatePopup()
+CreatePopup() {
+ Widget buttonForm1, buttonForm2, twoForm, button, prevButton = NULL;
+ int i;
+ char buttonName[12];
+ String buttonType;
+
+ popup = XtVaCreatePopupShell("popup", transientShellWidgetClass, toplevel, NULL);
+
+ twoForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, popup, NULL);
+ buttonForm1 = XtVaCreateManagedWidget("buttonForm", formWidgetClass, twoForm, NULL);
+ buttonForm2 = XtVaCreateManagedWidget("buttonForm", formWidgetClass, twoForm, XtNfromHoriz, (XtArgVal) buttonForm1, NULL);
+
+ if (appData.popupButtonCount > 100) {
+ fprintf(stderr,"Too many popup buttons\n");
+ exit(1);
+ }
+
+ for (i = 1; i <= appData.popupButtonCount; i++) {
+ Widget bform;
+ sprintf(buttonName, "button%d", i);
+
+ if (i <= appData.popupButtonBreak) {
+ bform = buttonForm1;
+ } else {
+ if (i == appData.popupButtonBreak+1) {
+ prevButton = NULL;
+ }
+ bform = buttonForm2;
+ }
+ XtVaGetSubresources(bform, (XtPointer)&buttonType, buttonName, "Button", resources, 1, NULL);
+
+ if (strcmp(buttonType, "command") == 0) {
+ button = XtVaCreateManagedWidget(buttonName, commandWidgetClass, bform, NULL);
+ XtVaSetValues(button, XtNfromVert, prevButton, XtNleft, XawChainLeft, XtNright, XawChainRight, NULL);
+ } else if (strcmp(buttonType, "toggle") == 0) {
+ button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, bform, NULL);
+ XtVaSetValues(button, XtNfromVert, prevButton, XtNleft, XawChainLeft, XtNright, XawChainRight, NULL);
+ } else {
+ fprintf(stderr,"unknown button type '%s'\n", buttonType);
+ }
+ prevButton = button;
+ }
+}
+
+
+Widget scaleN;
+
+void
+ShowScaleN(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ if (appData.popupFix) {
+ popupFixer(scaleN);
+
+ } else {
+ XtMoveWidget(scaleN, event->xbutton.x_root, event->xbutton.y_root);
+ XtPopup(scaleN, XtGrabNone);
+ }
+ if (appData.grabAll) {
+ XRaiseWindow(dpy, XtWindow(scaleN));
+ }
+ XSetWMProtocols(dpy, XtWindow(scaleN), &wmDeleteWindow, 1);
+}
+
+void
+HideScaleN(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ XtPopdown(scaleN);
+}
+
+
+void
+CreateScaleN()
{
Widget buttonForm, button, prevButton = NULL;
int i;
- char buttonName[12];
+ char buttonName[32];
String buttonType;
- popup = XtVaCreatePopupShell("popup", transientShellWidgetClass, toplevel,
+ scaleN = XtVaCreatePopupShell("scaleN", transientShellWidgetClass, toplevel,
NULL);
- buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, popup,
+ buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, scaleN,
NULL);
- if (appData.popupButtonCount > 100) {
- fprintf(stderr,"Too many popup buttons\n");
- exit(1);
- }
-
- for (i = 1; i <= appData.popupButtonCount; i++) {
+ for (i = 0; i <= 6; i++) {
sprintf(buttonName, "button%d", i);
XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName,
"Button", resources, 1, NULL);
- if (strcmp(buttonType, "command") == 0) {
- button = XtVaCreateManagedWidget(buttonName, commandWidgetClass,
+ button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass,
buttonForm, NULL);
- XtVaSetValues(button, XtNfromVert, prevButton,
+ XtVaSetValues(button, XtNfromVert, prevButton,
XtNleft, XawChainLeft, XtNright, XawChainRight, NULL);
- } else if (strcmp(buttonType, "toggle") == 0) {
- button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass,
+ prevButton = button;
+ }
+}
+
+Widget qualityW;
+
+void
+ShowQuality(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ if (appData.popupFix) {
+ popupFixer(qualityW);
+
+ } else {
+ XtMoveWidget(qualityW, event->xbutton.x_root, event->xbutton.y_root);
+ XtPopup(qualityW, XtGrabNone);
+ }
+ if (appData.grabAll) {
+ XRaiseWindow(dpy, XtWindow(qualityW));
+ }
+ XSetWMProtocols(dpy, XtWindow(qualityW), &wmDeleteWindow, 1);
+}
+
+void
+HideQuality(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ XtPopdown(qualityW);
+}
+
+
+void
+CreateQuality()
+{
+ Widget buttonForm, button, prevButton = NULL;
+ int i;
+ char buttonName[32];
+ String buttonType;
+
+ qualityW = XtVaCreatePopupShell("quality", transientShellWidgetClass, toplevel,
+ NULL);
+
+ buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, qualityW,
+ NULL);
+
+ for (i = -1; i <= 9; i++) {
+ if (i < 0) {
+ sprintf(buttonName, "buttonD");
+ } else {
+ sprintf(buttonName, "button%d", i);
+ }
+ XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName,
+ "Button", resources, 1, NULL);
+
+ button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass,
buttonForm, NULL);
- XtVaSetValues(button, XtNfromVert, prevButton,
+ XtVaSetValues(button, XtNfromVert, prevButton,
XtNleft, XawChainLeft, XtNright, XawChainRight, NULL);
+ prevButton = button;
+ }
+}
+
+Widget compressW;
+
+void
+ShowCompress(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ if (appData.popupFix) {
+ popupFixer(compressW);
+
+ } else {
+ XtMoveWidget(compressW, event->xbutton.x_root, event->xbutton.y_root);
+ XtPopup(compressW, XtGrabNone);
+ }
+ if (appData.grabAll) {
+ XRaiseWindow(dpy, XtWindow(compressW));
+ }
+ XSetWMProtocols(dpy, XtWindow(compressW), &wmDeleteWindow, 1);
+}
+
+void
+HideCompress(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ XtPopdown(compressW);
+}
+
+
+void
+CreateCompress()
+{
+ Widget buttonForm, button, prevButton = NULL;
+ int i;
+ char buttonName[32];
+ String buttonType;
+
+ compressW = XtVaCreatePopupShell("compress", transientShellWidgetClass, toplevel,
+ NULL);
+
+ buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, compressW,
+ NULL);
+
+ for (i = -1; i <= 9; i++) {
+ if (i < 0) {
+ sprintf(buttonName, "buttonD");
} else {
- fprintf(stderr,"unknown button type '%s'\n",buttonType);
+ sprintf(buttonName, "button%d", i);
}
+ XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName,
+ "Button", resources, 1, NULL);
+
+ button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass,
+ buttonForm, NULL);
+ XtVaSetValues(button, XtNfromVert, prevButton,
+ XtNleft, XawChainLeft, XtNright, XawChainRight, NULL);
prevButton = button;
}
}
+
+
+int filexfer_sock = -1;
+int filexfer_listen = -1;
+
+void HideFile(Widget w, XEvent *event, String *params, Cardinal *num_params) {
+ if (filexfer_sock >= 0) {
+ close(filexfer_sock);
+ filexfer_sock = -1;
+ }
+ if (filexfer_listen >= 0) {
+ close(filexfer_listen);
+ filexfer_listen = -1;
+ }
+}
+
+extern int use_loopback;
+time_t start_listen = 0;
+pid_t java_helper = 0;
+
+void ShowFile(Widget w, XEvent *event, String *params, Cardinal *num_params) {
+ int i, port0 = 7200, port, sock = -1;
+ char *cmd, *jar;
+ char fmt[] = "java -cp '%s' VncViewer HOST localhost PORT %d delayAuthPanel yes ignoreMSLogonCheck yes disableSSL yes ftpOnly yes graftFtp yes dsmActive no &";
+
+ if (getenv("SSVNC_ULTRA_FTP_JAR")) {
+ jar = getenv("SSVNC_ULTRA_FTP_JAR");
+ cmd = (char *) malloc(strlen(fmt) + strlen(jar) + 100);
+ } else {
+ fprintf(stderr, "Cannot find UltraVNC FTP jar file.\n");
+ return;
+ }
+
+ use_loopback = 1;
+ for (i = 0; i < 100; i++) {
+ port = port0 + i;
+ sock = ListenAtTcpPort(port);
+ if (sock >= 0) {
+ fprintf(stderr, "listening for filexfer on port: %d sock: %d\n", port, sock);
+ break;
+ }
+ }
+ use_loopback = 0;
+
+ if (sock >= 0) {
+ int st;
+ pid_t pid = fork();
+ if (pid < 0) {
+ free(cmd);
+ return;
+ } else if (pid == 0) {
+ int i;
+ sprintf(cmd, fmt, jar, port);
+ if (appData.ultraDSM) {
+ char *q = strstr(cmd, "dsmActive");
+ if (q) {
+ q = strstr(q, "no ");
+ if (q) {
+ q[0] = 'y';
+ q[1] = 'e';
+ q[2] = 's';
+ }
+ }
+ }
+ for (i = 3; i < 100; i++) {
+ close(i);
+ }
+ fprintf(stderr, "\n-- Experimental UltraVNC File Transfer --\n\nRunning cmd:\n\n %s\n\n", cmd);
+ system(cmd);
+ exit(0);
+ }
+ fprintf(stderr, "java helper pid is: %d\n", (int) pid);
+ waitpid(pid, &st, 0);
+ java_helper = pid;
+ start_listen = time(NULL);
+ }
+ free(cmd);
+ filexfer_listen = sock;
+}
+
+Widget chat, entry, text;
+
+static int chat_visible = 0;
+
+void
+ShowChat(Widget w, XEvent *event, String *params, Cardinal *num_params)
+{
+ if (appData.termChat) {
+ return;
+ }
+ if (! chat_visible) {
+ XtPopup(chat, XtGrabNone);
+ chat_visible = 1;
+ 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);
+ }
+}
+
+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();
+}
+
+void dismiss_proc(Widget w, XtPointer client_data, XtPointer call_data) {
+ SendTextChatClose();
+ SendTextChatFinished();
+ hidechat();
+}
+
+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();
+}
+
+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) {
+ int len;
+ XawTextPosition beg, end;
+ static XawTextPosition pos = 0;
+ XawTextBlock txt;
+
+ if (appData.termChat) {
+ return;
+ }
+
+ XawTextSetInsertionPoint(text, pos);
+ beg = XawTextGetInsertionPoint(text);
+ end = beg;
+ //fprintf(stderr, "AppendChatInput: pos=%d in= '%s'\n", beg, in);
+
+ txt.firstPos = 0;
+ txt.length = strlen(in);
+ txt.ptr = in;
+ txt.format = FMT8BIT;
+
+ XawTextReplace(text, beg, end, &txt);
+ XawTextSetInsertionPoint(text, beg + txt.length);
+
+ pos = XawTextGetInsertionPoint(text);
+ //fprintf(stderr, "AppendChatInput done pos=%d\n", pos);
+}
+
+static char errorbuf[1] = {0};
+
+void CreateChat(void) {
+
+ Widget myform, dismiss;
+ int i, n;
+ Dimension w = 400, h = 300;
+ Dimension x = 33, y = 33;
+ Arg args[10];
+
+ chat = XtVaCreatePopupShell("chat", topLevelShellWidgetClass, toplevel, XtNmappedWhenManaged, False, NULL);
+
+ myform = XtVaCreateManagedWidget("myform", formWidgetClass, chat, NULL);
+
+ text = XtVaCreateManagedWidget("text", asciiTextWidgetClass, myform,
+ XtNresize, XawtextResizeBoth, XtNresizable, True, XtNwrap, XawtextWrapWord,
+ XtNscrollHorizontal, XawtextScrollNever, XtNscrollVertical, XawtextScrollAlways,
+ XtNwidth, w, XtNheight, h, XtNdisplayCaret, False,
+ XtNeditType, XawtextAppend, XtNtype, XawAsciiString,
+ XtNuseStringInPlace, False, NULL);
+
+ entry = XtVaCreateManagedWidget("entry", asciiTextWidgetClass, myform,
+ XtNresize, XawtextResizeWidth, XtNresizable, True, XtNwrap, 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);
+}
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 2008-10-15 08:00:20.000000000 -0400
@@ -23,6 +23,7 @@
* rfbproto.c - functions to deal with client side of RFB protocol.
*/
+#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <pwd.h>
@@ -57,6 +58,44 @@
static Bool HandleTight16(int rx, int ry, int rw, int rh);
static Bool HandleTight32(int rx, int ry, int rw, int rh);
+/* runge add zrle */
+static Bool HandleZRLE8(int rx, int ry, int rw, int rh);
+static Bool HandleZRLE15(int rx, int ry, int rw, int rh);
+static Bool HandleZRLE16(int rx, int ry, int rw, int rh);
+static Bool HandleZRLE24(int rx, int ry, int rw, int rh);
+static Bool HandleZRLE24Up(int rx, int ry, int rw, int rh);
+static Bool HandleZRLE24Down(int rx, int ry, int rw, int rh);
+static Bool HandleZRLE32(int rx, int ry, int rw, int rh);
+
+typedef struct {
+ unsigned long length;
+} rfbZRLEHeader;
+
+#define sz_rfbZRLEHeader 4
+
+#define rfbZRLETileWidth 64
+#define rfbZRLETileHeight 64
+
+#define DO_ZYWRLE 1
+
+#if DO_ZYWRLE
+
+#ifndef ZRLE_ONCE
+#define ZRLE_ONCE
+
+static const int bitsPerPackedPixel[] = {
+ 0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
+};
+
+int zywrle_level;
+int zywrleBuf[rfbZRLETileWidth*rfbZRLETileHeight];
+
+#include "zrlepalettehelper.h"
+static zrlePaletteHelper paletteHelper;
+
+#endif /* ZRLE_ONCE */
+#endif /* DO_ZYWRLE */
+
static void ReadConnFailedReason(void);
static long ReadCompactLen (void);
@@ -67,6 +106,13 @@
static void JpegSetSrcManager(j_decompress_ptr cinfo, CARD8 *compressedData,
int compressedLen);
+extern int currentMsg;
+extern double scale_factor_x;
+extern double scale_factor_y;
+
+int sent_FBU = 0;
+int skip_XtUpdate = 0;
+int skip_XtUpdateAll = 0;
int rfbsock;
char *desktopName;
@@ -177,6 +223,9 @@
sig_rfbEncodingPointerPos, "Pointer position update");
CapsAdd(encodingCaps, rfbEncodingLastRect, rfbTightVncVendor,
sig_rfbEncodingLastRect, "LastRect protocol extension");
+
+ CapsAdd(encodingCaps, rfbEncodingNewFBSize, rfbTightVncVendor,
+ sig_rfbEncodingNewFBSize, "New FB size protocol extension");
}
@@ -187,21 +236,117 @@
Bool
ConnectToRFBServer(const char *hostname, int port)
{
- unsigned int host;
-
- if (!StringToIPAddr(hostname, &host)) {
- fprintf(stderr,"Couldn't convert '%s' to host address\n", hostname);
- return False;
- }
-
- rfbsock = ConnectToTcpAddr(host, port);
+ unsigned int host;
+ char *q, *cmd = NULL;
+ Bool setnb;
+ struct stat sb;
+
+ if (strstr(hostname, "exec=") == hostname) {
+ cmd = strdup(hostname);
+ q = strchr(cmd, '=');
+ *q = ' ';
+ if (getenv("SSVNC_BASEDIR")) {
+ char *base = getenv("SSVNC_BASEDIR");
+ char *newcmd = (char *)malloc(strlen(base) + strlen(cmd) + 1000);
+ sprintf(newcmd, "%s/unwrap.so", base);
+ if (stat(newcmd, &sb) == 0) {
+#if (defined(__MACH__) && defined(__APPLE__))
+ sprintf(newcmd, "DYLD_FORCE_FLAT_NAMESPACE=1; export DYLD_FORCE_FLAT_NAMESPACE; DYLD_INSERT_LIBRARIES='%s/unwrap.so'; export DYLD_INSERT_LIBRARIES; %s", base, cmd);
+#else
+ sprintf(newcmd, "LD_PRELOAD='%s/unwrap.so'; export LD_PRELOAD; %s", base, cmd);
+#endif
+ cmd = newcmd;
+ }
+ }
+ }
- if (rfbsock < 0) {
- fprintf(stderr,"Unable to connect to VNC server\n");
- return False;
- }
+ if (cmd != NULL) {
+ int sfd[2];
+ char *q, *cmd2 = strdup(cmd);
+ pid_t pid;
+
+ q = strstr(cmd2, "pw=");
+ if (q) {
+ q += strlen("pw=");
+ while (*q != '\0' && !isspace(*q)) {
+ *q = '*';
+ q++;
+ }
+ }
+
+ fprintf(stderr, "exec-cmd: %s\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) {
+ fprintf(stderr,"Unable to connect to exec'd command: %s\n", cmd);
+ 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) {
+ fprintf(stderr,"Unable to connect to VNC server (unix-domain socket: %s)\n", hostname);
+ return False;
+ }
+
+ } else {
+ if (!StringToIPAddr(hostname, &host)) {
+ fprintf(stderr,"Couldn't convert '%s' to host address\n", hostname);
+ return False;
+ }
+
+ rfbsock = ConnectToTcpAddr(host, port);
+
+ if (rfbsock < 0) {
+ fprintf(stderr,"Unable to connect to VNC server (%s:%d)\n", hostname, port);
+ return False;
+ }
+ }
- return SetNonBlocking(rfbsock);
+ setnb = SetNonBlocking(rfbsock);
+ return setnb;
}
@@ -212,211 +357,307 @@
Bool
InitialiseRFBConnection(void)
{
- rfbProtocolVersionMsg pv;
- int server_major, server_minor;
- int viewer_major, viewer_minor;
- rfbClientInitMsg ci;
- int secType;
+ rfbProtocolVersionMsg pv;
+ int server_major, server_minor;
+ int viewer_major, viewer_minor;
+ rfbClientInitMsg ci;
+ int secType;
- /* if the connection is immediately closed, don't report anything, so
- that pmw's monitor can make test connections */
+ /* if the connection is immediately closed, don't report anything, so
+ that pmw's monitor can make test connections */
- if (listenSpecified)
- errorMessageOnReadFailure = False;
+ if (listenSpecified) {
+ errorMessageOnReadFailure = False;
+ }
- if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg))
- return False;
+ if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) {
+ return False;
+ }
- errorMessageOnReadFailure = True;
+ errorMessageOnReadFailure = True;
- pv[sz_rfbProtocolVersionMsg] = 0;
+ pv[sz_rfbProtocolVersionMsg] = 0;
- if (sscanf(pv, rfbProtocolVersionFormat,
- &server_major, &server_minor) != 2) {
- fprintf(stderr,"Not a valid VNC server\n");
- return False;
- }
+ if (strstr(pv, "ID:") == pv) {
+ ;
+ } else if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) {
+ if (strstr(pv, "test") == pv) {
+ /* now some hacks for ultraVNC SC III (SSL) ... testA, etc */
+ int i;
+ char *se = NULL;
+
+ fprintf(stderr,"Trying UltraVNC Single Click III workaround: %s\n", pv);
+ for (i=0; i < 7 ; i++) {
+ pv[i] = pv[i+5];
+ }
+ if (!ReadFromRFBServer(pv+7, 5)) {
+ return False;
+ }
+
+ se = getenv("STUNNEL_EXTRA_OPTS");
+ if (se == NULL) {
+ se = getenv("STUNNEL_EXTRA_OPTS_USER");
+ }
+ if (se != NULL) {
+ if (strstr(se, "options")) {
+ if (strstr(se, "ALL") || strstr(se, "DONT_INSERT_EMPTY_FRAGMENTS")) {
+ ; /* good */
+ } else {
+ se = NULL;
+ }
+ } else {
+ se = NULL;
+ }
+ }
+ if (se == NULL) {
+ fprintf(stderr, "\n");
+ fprintf(stderr, "***************************************************************\n");
+ fprintf(stderr, "To work around UltraVNC SC III SSL dropping after a few minutes\n");
+ fprintf(stderr, "you may need to set STUNNEL_EXTRA_OPTS_USER='options = ALL'.\n");
+ fprintf(stderr, "***************************************************************\n");
+ fprintf(stderr, "\n");
+ }
+ if (strstr(pv, "ID:") == pv) {
+ goto check_ID_string;
+ }
+ if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) == 2) {
+ goto ultra_vnc_nonsense;
+ }
+ }
+ fprintf(stderr,"Not a valid VNC server: '%s'\n", pv);
+ return False;
+ }
- viewer_major = rfbProtocolMajorVersion;
- if (server_major == 3 && server_minor >= rfbProtocolMinorVersion) {
- /* the server supports at least the standard protocol 3.7 */
- viewer_minor = rfbProtocolMinorVersion;
- } else {
- /* any other server version, request the standard 3.3 */
- viewer_minor = rfbProtocolFallbackMinorVersion;
- }
+ check_ID_string:
+ if (strstr(pv, "ID:") == pv) {
+ char tmp[256];
+ fprintf(stderr, "UltraVNC Repeater string detected: %s\n", pv);
+ fprintf(stderr, "Pretending to be UltraVNC repeater: reading 250 bytes...\n\n");
+ if (!ReadFromRFBServer(tmp, 250 - 12)) {
+ return False;
+ }
+ if (!ReadFromRFBServer(pv, 12)) {
+ return False;
+ }
+ if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) {
+ fprintf(stderr,"Not a valid VNC server: '%s'\n", pv);
+ return False;
+ }
+ }
- fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n",
- viewer_major, viewer_minor);
+ ultra_vnc_nonsense:
+ fprintf(stderr,"Proto: %s\n", pv);
- sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor);
+ viewer_major = rfbProtocolMajorVersion;
- if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg))
- return False;
+ if (appData.rfbVersion != NULL && sscanf(appData.rfbVersion, "%d.%d", &viewer_major, &viewer_minor) == 2) {
+ fprintf(stderr,"Setting RFB version to %d.%d from -rfbversion.\n", viewer_major, viewer_minor);
+ } else if (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", viewer_major, viewer_minor);
+ } else if (server_major == 3 && (server_minor == 14 || server_minor == 16)) {
+ /* hack for UltraVNC Single Click. They misuse rfb proto version */
+ fprintf(stderr,"Setting RFB version to 3.3 for UltraVNC Single Click.\n");
+ viewer_minor = rfbProtocolFallbackMinorVersion;
+ } else if (server_major == 3 && server_minor >= rfbProtocolMinorVersion) {
+ /* the server supports at least the standard protocol 3.7 */
+ viewer_minor = rfbProtocolMinorVersion;
+ } else {
+ /* any other server version, request the standard 3.3 */
+ viewer_minor = rfbProtocolFallbackMinorVersion;
+ }
- /* Read or select the security type. */
- if (viewer_minor == rfbProtocolMinorVersion) {
- secType = SelectSecurityType();
- } else {
- secType = ReadSecurityType();
- }
- if (secType == rfbSecTypeInvalid)
- return False;
+ fprintf(stderr, "\nConnected to RFB server, using protocol version %d.%d\n", viewer_major, viewer_minor);
- switch (secType) {
- case rfbSecTypeNone:
- fprintf(stderr, "No authentication needed\n");
- break;
- case rfbSecTypeVncAuth:
- if (!AuthenticateVNC())
- return False;
- break;
- case rfbSecTypeTight:
- tightVncProtocol = True;
- InitCapabilities();
- if (!SetupTunneling())
- return False;
- if (!PerformAuthenticationTight())
- return False;
- break;
- default: /* should never happen */
- fprintf(stderr, "Internal error: Invalid security type\n");
- return False;
- }
+ sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor);
- ci.shared = (appData.shareDesktop ? 1 : 0);
+ if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) {
+ return False;
+ }
- if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg))
- return False;
+ /* Read or select the security type. */
+ if (viewer_minor == rfbProtocolMinorVersion) {
+ secType = SelectSecurityType();
+ } else {
+ secType = ReadSecurityType();
+ }
+ if (secType == rfbSecTypeInvalid) {
+ return False;
+ }
- if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg))
- return False;
+ switch (secType) {
+ case rfbSecTypeNone:
+ fprintf(stderr, "No authentication needed\n\n");
+ break;
+ case rfbSecTypeVncAuth:
+ if (!AuthenticateVNC()) {
+ return False;
+ }
+ break;
+ case rfbSecTypeTight:
+ tightVncProtocol = True;
+ InitCapabilities();
+ if (!SetupTunneling()) {
+ return False;
+ }
+ if (!PerformAuthenticationTight()) {
+ return False;
+ }
+ break;
+ default: /* should never happen */
+ fprintf(stderr, "Internal error: Invalid security type\n");
+ return False;
+ }
- si.framebufferWidth = Swap16IfLE(si.framebufferWidth);
- si.framebufferHeight = Swap16IfLE(si.framebufferHeight);
- si.format.redMax = Swap16IfLE(si.format.redMax);
- si.format.greenMax = Swap16IfLE(si.format.greenMax);
- si.format.blueMax = Swap16IfLE(si.format.blueMax);
- si.nameLength = Swap32IfLE(si.nameLength);
-
- /* FIXME: Check arguments to malloc() calls. */
- desktopName = malloc(si.nameLength + 1);
- if (!desktopName) {
- fprintf(stderr, "Error allocating memory for desktop name, %lu bytes\n",
- (unsigned long)si.nameLength);
- return False;
- }
+ ci.shared = (appData.shareDesktop ? 1 : 0);
- if (!ReadFromRFBServer(desktopName, si.nameLength)) return False;
+ if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) {
+ return False;
+ }
- desktopName[si.nameLength] = 0;
+ if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg)) {
+ return False;
+ }
- fprintf(stderr,"Desktop name \"%s\"\n",desktopName);
+ si.framebufferWidth = Swap16IfLE(si.framebufferWidth);
+ si.framebufferHeight = Swap16IfLE(si.framebufferHeight);
+ si.format.redMax = Swap16IfLE(si.format.redMax);
+ si.format.greenMax = Swap16IfLE(si.format.greenMax);
+ si.format.blueMax = Swap16IfLE(si.format.blueMax);
+ si.nameLength = Swap32IfLE(si.nameLength);
+
+ if (appData.chatOnly) {
+ si.framebufferWidth = 32;
+ si.framebufferHeight = 32;
+ }
- fprintf(stderr,"VNC server default format:\n");
- PrintPixelFormat(&si.format);
+ /* 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 (tightVncProtocol) {
- /* Read interaction capabilities (protocol 3.7t) */
- if (!ReadInteractionCaps())
- return False;
- }
+ if (!ReadFromRFBServer(desktopName, si.nameLength)) {
+ return False;
+ }
- return True;
+ desktopName[si.nameLength] = 0;
+
+ fprintf(stderr,"Desktop name \"%s\"\n\n", desktopName);
+
+ fprintf(stderr,"VNC server default format:\n");
+ PrintPixelFormat(&si.format);
+
+ if (tightVncProtocol) {
+ /* Read interaction capabilities (protocol 3.7t) */
+ if (!ReadInteractionCaps()) {
+ return False;
+ }
+ }
+
+ return True;
}
/*
- * Read security type from the server (protocol version 3.3)
+ * Read security type from the server (protocol 3.3)
*/
static int
ReadSecurityType(void)
{
- CARD32 secType;
+ CARD32 secType;
- /* Read the security type */
- if (!ReadFromRFBServer((char *)&secType, sizeof(secType)))
- return rfbSecTypeInvalid;
+ /* Read the security type */
+ if (!ReadFromRFBServer((char *)&secType, sizeof(secType))) {
+ return rfbSecTypeInvalid;
+ }
- secType = Swap32IfLE(secType);
+ secType = Swap32IfLE(secType);
- if (secType == rfbSecTypeInvalid) {
- ReadConnFailedReason();
- return rfbSecTypeInvalid;
- }
+ if (secType == rfbSecTypeInvalid) {
+ ReadConnFailedReason();
+ return rfbSecTypeInvalid;
+ }
- if (secType != rfbSecTypeNone && secType != rfbSecTypeVncAuth) {
- fprintf(stderr, "Unknown security type from RFB server: %d\n",
- (int)secType);
- return rfbSecTypeInvalid;
- }
+ if (secType != rfbSecTypeNone && secType != rfbSecTypeVncAuth) {
+ fprintf(stderr, "Unknown security type from RFB server: %d\n",
+ (int)secType);
+ return rfbSecTypeInvalid;
+ }
- return (int)secType;
+ return (int)secType;
}
/*
- * Select security type from the server's list (protocol version 3.7)
+ * Select security type from the server's list (protocol 3.7)
*/
static int
SelectSecurityType(void)
{
- CARD8 nSecTypes;
- char *secTypeNames[] = {"None", "VncAuth"};
- CARD8 knownSecTypes[] = {rfbSecTypeNone, rfbSecTypeVncAuth};
- int nKnownSecTypes = sizeof(knownSecTypes);
- CARD8 *secTypes;
- CARD8 secType = rfbSecTypeInvalid;
- int i, j;
-
- /* Read the list of secutiry types. */
- if (!ReadFromRFBServer((char *)&nSecTypes, sizeof(nSecTypes)))
- return rfbSecTypeInvalid;
-
- if (nSecTypes == 0) {
- ReadConnFailedReason();
- return rfbSecTypeInvalid;
- }
+ CARD8 nSecTypes;
+ char *secTypeNames[] = {"None", "VncAuth"};
+ CARD8 knownSecTypes[] = {rfbSecTypeNone, rfbSecTypeVncAuth};
+ int nKnownSecTypes = sizeof(knownSecTypes);
+ CARD8 *secTypes;
+ CARD8 secType = rfbSecTypeInvalid;
+ int i, j;
+
+ /* Read the list of secutiry types. */
+ if (!ReadFromRFBServer((char *)&nSecTypes, sizeof(nSecTypes))) {
+ return rfbSecTypeInvalid;
+ }
- secTypes = malloc(nSecTypes);
- if (!ReadFromRFBServer((char *)secTypes, nSecTypes))
- return rfbSecTypeInvalid;
-
- /* Find out if the server supports TightVNC protocol extensions */
- for (j = 0; j < (int)nSecTypes; j++) {
- if (secTypes[j] == rfbSecTypeTight) {
- free(secTypes);
- secType = rfbSecTypeTight;
- if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType)))
- return rfbSecTypeInvalid;
- fprintf(stderr, "Enabling TightVNC protocol extensions\n");
- return rfbSecTypeTight;
- }
- }
+ if (nSecTypes == 0) {
+ ReadConnFailedReason();
+ return rfbSecTypeInvalid;
+ }
- /* Find first supported security type */
- for (j = 0; j < (int)nSecTypes; j++) {
- for (i = 0; i < nKnownSecTypes; i++) {
- if (secTypes[j] == knownSecTypes[i]) {
- secType = secTypes[j];
- if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) {
- free(secTypes);
- return rfbSecTypeInvalid;
- }
- break;
- }
- }
- if (secType != rfbSecTypeInvalid) break;
- }
+ secTypes = malloc(nSecTypes);
+ if (!ReadFromRFBServer((char *)secTypes, nSecTypes)) {
+ return rfbSecTypeInvalid;
+ }
+
+ /* Find out if the server supports TightVNC protocol extensions */
+ for (j = 0; j < (int)nSecTypes; j++) {
+ if (secTypes[j] == rfbSecTypeTight) {
+ free(secTypes);
+ secType = rfbSecTypeTight;
+ if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) {
+ return rfbSecTypeInvalid;
+ }
+ fprintf(stderr, "Enabling TightVNC protocol extensions\n");
+ return rfbSecTypeTight;
+ }
+ }
+
+ /* Find first supported security type */
+ for (j = 0; j < (int)nSecTypes; j++) {
+ for (i = 0; i < nKnownSecTypes; i++) {
+ if (secTypes[j] == knownSecTypes[i]) {
+ secType = secTypes[j];
+ if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) {
+ free(secTypes);
+ return rfbSecTypeInvalid;
+ }
+ break;
+ }
+ }
+ if (secType != rfbSecTypeInvalid) {
+ break;
+ }
+ }
- free(secTypes);
+ free(secTypes);
- if (secType == rfbSecTypeInvalid)
- fprintf(stderr, "Server did not offer supported security type\n");
+ if (secType == rfbSecTypeInvalid) {
+ fprintf(stderr, "Server did not offer supported security type\n");
+ }
- return (int)secType;
+ return (int)secType;
}
@@ -451,6 +692,9 @@
return True;
}
+static char *restart_session_pw = NULL;
+static int restart_session_len = 0;
+
/*
* Negotiate authentication scheme (protocol version 3.7t)
@@ -459,56 +703,61 @@
static Bool
PerformAuthenticationTight(void)
{
- rfbAuthenticationCapsMsg caps;
- CARD32 authScheme;
- int i;
+ rfbAuthenticationCapsMsg caps;
+ CARD32 authScheme;
+ int i;
- /* In the protocol version 3.7t, the server informs us about supported
- authentication schemes. Here we read this information. */
+ /* In the protocol version 3.7t, the server informs us about supported
+ authentication schemes. Here we read this information. */
- if (!ReadFromRFBServer((char *)&caps, sz_rfbAuthenticationCapsMsg))
- return False;
+ if (!ReadFromRFBServer((char *)&caps, sz_rfbAuthenticationCapsMsg)) {
+ return False;
+ }
- caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes);
+ caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes);
- if (!caps.nAuthTypes) {
- fprintf(stderr, "No authentication needed\n");
- return True;
- }
+ if (!caps.nAuthTypes) {
+ fprintf(stderr, "No authentication needed\n\n");
+ return True;
+ }
- if (!ReadCapabilityList(authCaps, caps.nAuthTypes))
- return False;
+ if (!ReadCapabilityList(authCaps, caps.nAuthTypes)) {
+ return False;
+ }
- /* Prefer Unix login authentication if a user name was given. */
- if (appData.userLogin && CapsIsEnabled(authCaps, rfbAuthUnixLogin)) {
- authScheme = Swap32IfLE(rfbAuthUnixLogin);
- if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme)))
- return False;
- return AuthenticateUnixLogin();
- }
+ /* Prefer Unix login authentication if a user name was given. */
+ if (appData.userLogin && CapsIsEnabled(authCaps, rfbAuthUnixLogin)) {
+ authScheme = Swap32IfLE(rfbAuthUnixLogin);
+ if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) {
+ return False;
+ }
+ return AuthenticateUnixLogin();
+ }
- /* Otherwise, try server's preferred authentication scheme. */
- for (i = 0; i < CapsNumEnabled(authCaps); i++) {
- authScheme = CapsGetByOrder(authCaps, i);
- if (authScheme != rfbAuthUnixLogin && authScheme != rfbAuthVNC)
- continue; /* unknown scheme - cannot use it */
- authScheme = Swap32IfLE(authScheme);
- if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme)))
- return False;
- authScheme = Swap32IfLE(authScheme); /* convert it back */
- if (authScheme == rfbAuthUnixLogin) {
- return AuthenticateUnixLogin();
- } else if (authScheme == rfbAuthVNC) {
- return AuthenticateVNC();
- } else {
- /* Should never happen. */
- fprintf(stderr, "Assertion failed: unknown authentication scheme\n");
- return False;
- }
- }
+ /* Otherwise, try server's preferred authentication scheme. */
+ for (i = 0; i < CapsNumEnabled(authCaps); i++) {
+ authScheme = CapsGetByOrder(authCaps, i);
+ if (authScheme != rfbAuthUnixLogin && authScheme != rfbAuthVNC) {
+ continue; /* unknown scheme - cannot use it */
+ }
+ authScheme = Swap32IfLE(authScheme);
+ if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) {
+ return False;
+ }
+ authScheme = Swap32IfLE(authScheme); /* convert it back */
+ if (authScheme == rfbAuthUnixLogin) {
+ return AuthenticateUnixLogin();
+ } else if (authScheme == rfbAuthVNC) {
+ return AuthenticateVNC();
+ } else {
+ /* Should never happen. */
+ fprintf(stderr, "Assertion failed: unknown authentication scheme\n");
+ return False;
+ }
+ }
- fprintf(stderr, "No suitable authentication schemes offered by server\n");
- return False;
+ fprintf(stderr, "No suitable authentication schemes offered by server\n");
+ return False;
}
@@ -519,80 +768,100 @@
static Bool
AuthenticateVNC(void)
{
- CARD32 authScheme, authResult;
- CARD8 challenge[CHALLENGESIZE];
- char *passwd;
- char buffer[64];
- char* cstatus;
- int len;
+ CARD32 authScheme, authResult;
+ CARD8 challenge[CHALLENGESIZE];
+ char *passwd = NULL;
+ char buffer[64];
+ char* cstatus;
+ int len;
+ int restart = 0;
- fprintf(stderr, "Performing standard VNC authentication\n");
+ fprintf(stderr, "\nPerforming standard VNC authentication\n");
- if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE))
- return False;
+ if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) {
+ return False;
+ }
- if (appData.passwordFile) {
- passwd = vncDecryptPasswdFromFile(appData.passwordFile);
- if (!passwd) {
- fprintf(stderr, "Cannot read valid password from file \"%s\"\n",
- appData.passwordFile);
- return False;
- }
- } else if (appData.autoPass) {
- passwd = buffer;
- cstatus = fgets(buffer, sizeof buffer, stdin);
- if (cstatus == NULL)
- buffer[0] = '\0';
- else
- {
- len = strlen(buffer);
- if (len > 0 && buffer[len - 1] == '\n')
- buffer[len - 1] = '\0';
- }
- } else if (appData.passwordDialog) {
- passwd = DoPasswordDialog();
- } else {
- passwd = getpass("Password: ");
- }
+ if (restart_session_pw != NULL) {
+ passwd = restart_session_pw;
+ restart_session_pw = NULL;
+ restart = 1;
+ } else if (appData.passwordFile) {
+ passwd = vncDecryptPasswdFromFile(appData.passwordFile);
+ if (!passwd) {
+ fprintf(stderr, "Cannot read valid password from file \"%s\"\n",
+ appData.passwordFile);
+ return False;
+ }
+ } else if (appData.autoPass) {
+ passwd = buffer;
+ cstatus = fgets(buffer, sizeof buffer, stdin);
+ if (cstatus == NULL) {
+ buffer[0] = '\0';
+ } else {
+ len = strlen(buffer);
+ if (len > 0 && buffer[len - 1] == '\n') {
+ buffer[len - 1] = '\0';
+ }
+ }
+ } else if (getenv("VNCVIEWER_PASSWORD")) {
+ passwd = strdup(getenv("VNCVIEWER_PASSWORD"));
+ putenv("VNCVIEWER_PASSWORD=none");
+ } else if (appData.passwordDialog) {
+ passwd = DoPasswordDialog();
+ } else {
+ passwd = getpass("VNC Password: ");
+ }
- if (!passwd || strlen(passwd) == 0) {
- fprintf(stderr, "Reading password failed\n");
- return False;
- }
- if (strlen(passwd) > 8) {
- passwd[8] = '\0';
- }
+ if (restart) {
+#define EN0 0
+#define DE1 1
+ unsigned char s_fixedkey[8] = {23,82,107,6,35,78,88,7};
+ deskey(s_fixedkey, DE1);
+ des(passwd, passwd);
+ } else {
+ if (!passwd || strlen(passwd) == 0) {
+ fprintf(stderr, "Reading password failed\n\n");
+ return False;
+ }
+ if (strlen(passwd) > 8) {
+ passwd[8] = '\0';
+ }
+ }
+ vncEncryptBytes(challenge, passwd);
+
- vncEncryptBytes(challenge, passwd);
- /* Lose the password from memory */
- memset(passwd, '\0', strlen(passwd));
+// /* Lose the password from memory */
+// memset(passwd, '\0', strlen(passwd));
- if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE))
- return False;
+ if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) {
+ return False;
+ }
- if (!ReadFromRFBServer((char *)&authResult, 4))
- return False;
+ if (!ReadFromRFBServer((char *)&authResult, 4)) {
+ return False;
+ }
- authResult = Swap32IfLE(authResult);
+ authResult = Swap32IfLE(authResult);
- switch (authResult) {
- case rfbVncAuthOK:
- fprintf(stderr, "VNC authentication succeeded\n");
- break;
- case rfbVncAuthFailed:
- fprintf(stderr, "VNC authentication failed\n");
- return False;
- case rfbVncAuthTooMany:
- fprintf(stderr, "VNC authentication failed - too many tries\n");
- return False;
- default:
- fprintf(stderr, "Unknown VNC authentication result: %d\n",
- (int)authResult);
- return False;
- }
+ switch (authResult) {
+ case rfbVncAuthOK:
+ fprintf(stderr, "VNC authentication succeeded\n\n");
+ break;
+ case rfbVncAuthFailed:
+ fprintf(stderr, "VNC authentication failed\n\n");
+ return False;
+ case rfbVncAuthTooMany:
+ fprintf(stderr, "VNC authentication failed - too many tries\n\n");
+ return False;
+ default:
+ fprintf(stderr, "Unknown VNC authentication result: %d\n\n",
+ (int)authResult);
+ return False;
+ }
- return True;
+ return True;
}
/*
@@ -602,68 +871,71 @@
static Bool
AuthenticateUnixLogin(void)
{
- CARD32 loginLen, passwdLen, authResult;
- char *login;
- char *passwd;
- struct passwd *ps;
-
- fprintf(stderr, "Performing Unix login-style authentication\n");
-
- if (appData.userLogin) {
- login = appData.userLogin;
- } else {
- ps = getpwuid(getuid());
- login = ps->pw_name;
- }
+ CARD32 loginLen, passwdLen, authResult;
+ char *login;
+ char *passwd;
+ struct passwd *ps;
+
+ fprintf(stderr, "\nPerforming Unix login-style authentication\n");
+
+ if (appData.userLogin) {
+ login = appData.userLogin;
+ } else {
+ ps = getpwuid(getuid());
+ login = ps->pw_name;
+ }
- fprintf(stderr, "Using user name \"%s\"\n", login);
+ fprintf(stderr, "Using user name \"%s\"\n", login);
- if (appData.passwordDialog) {
- passwd = DoPasswordDialog();
- } else {
- passwd = getpass("Password: ");
- }
- if (!passwd || strlen(passwd) == 0) {
- fprintf(stderr, "Reading password failed\n");
- return False;
- }
+ if (appData.passwordDialog) {
+ passwd = DoPasswordDialog();
+ } else {
+ passwd = getpass("VNC Password: ");
+ }
+ if (!passwd || strlen(passwd) == 0) {
+ fprintf(stderr, "Reading password failed\n");
+ return False;
+ }
- loginLen = Swap32IfLE((CARD32)strlen(login));
- passwdLen = Swap32IfLE((CARD32)strlen(passwd));
+ loginLen = Swap32IfLE((CARD32)strlen(login));
+ passwdLen = Swap32IfLE((CARD32)strlen(passwd));
- if (!WriteExact(rfbsock, (char *)&loginLen, sizeof(loginLen)) ||
- !WriteExact(rfbsock, (char *)&passwdLen, sizeof(passwdLen)))
- return False;
+ if (!WriteExact(rfbsock, (char *)&loginLen, sizeof(loginLen)) ||
+ !WriteExact(rfbsock, (char *)&passwdLen, sizeof(passwdLen))) {
+ return False;
+ }
- if (!WriteExact(rfbsock, login, strlen(login)) ||
- !WriteExact(rfbsock, passwd, strlen(passwd)))
- return False;
+ if (!WriteExact(rfbsock, login, strlen(login)) ||
+ !WriteExact(rfbsock, passwd, strlen(passwd))) {
+ return False;
+ }
- /* Lose the password from memory */
- memset(passwd, '\0', strlen(passwd));
+// /* Lose the password from memory */
+// memset(passwd, '\0', strlen(passwd));
- if (!ReadFromRFBServer((char *)&authResult, sizeof(authResult)))
- return False;
+ if (!ReadFromRFBServer((char *)&authResult, sizeof(authResult))) {
+ return False;
+ }
- authResult = Swap32IfLE(authResult);
+ authResult = Swap32IfLE(authResult);
- switch (authResult) {
- case rfbVncAuthOK:
- fprintf(stderr, "Authentication succeeded\n");
- break;
- case rfbVncAuthFailed:
- fprintf(stderr, "Authentication failed\n");
- return False;
- case rfbVncAuthTooMany:
- fprintf(stderr, "Authentication failed - too many tries\n");
- return False;
- default:
- fprintf(stderr, "Unknown authentication result: %d\n",
- (int)authResult);
- return False;
- }
+ switch (authResult) {
+ case rfbVncAuthOK:
+ fprintf(stderr, "Authentication succeeded\n\n");
+ break;
+ case rfbVncAuthFailed:
+ fprintf(stderr, "Authentication failed\n\n");
+ return False;
+ case rfbVncAuthTooMany:
+ fprintf(stderr, "Authentication failed - too many tries\n\n");
+ return False;
+ default:
+ fprintf(stderr, "Unknown authentication result: %d\n\n",
+ (int)authResult);
+ return False;
+ }
- return True;
+ return True;
}
@@ -675,19 +947,20 @@
static Bool
ReadInteractionCaps(void)
{
- rfbInteractionCapsMsg intr_caps;
+ rfbInteractionCapsMsg intr_caps;
- /* Read the counts of list items following */
- if (!ReadFromRFBServer((char *)&intr_caps, sz_rfbInteractionCapsMsg))
- return False;
- intr_caps.nServerMessageTypes = Swap16IfLE(intr_caps.nServerMessageTypes);
- intr_caps.nClientMessageTypes = Swap16IfLE(intr_caps.nClientMessageTypes);
- intr_caps.nEncodingTypes = Swap16IfLE(intr_caps.nEncodingTypes);
-
- /* Read the lists of server- and client-initiated messages */
- return (ReadCapabilityList(serverMsgCaps, intr_caps.nServerMessageTypes) &&
- ReadCapabilityList(clientMsgCaps, intr_caps.nClientMessageTypes) &&
- ReadCapabilityList(encodingCaps, intr_caps.nEncodingTypes));
+ /* Read the counts of list items following */
+ if (!ReadFromRFBServer((char *)&intr_caps, sz_rfbInteractionCapsMsg)) {
+ return False;
+ }
+ intr_caps.nServerMessageTypes = Swap16IfLE(intr_caps.nServerMessageTypes);
+ intr_caps.nClientMessageTypes = Swap16IfLE(intr_caps.nClientMessageTypes);
+ intr_caps.nEncodingTypes = Swap16IfLE(intr_caps.nEncodingTypes);
+
+ /* Read the lists of server- and client-initiated messages */
+ return (ReadCapabilityList(serverMsgCaps, intr_caps.nServerMessageTypes) &&
+ ReadCapabilityList(clientMsgCaps, intr_caps.nClientMessageTypes) &&
+ ReadCapabilityList(encodingCaps, intr_caps.nEncodingTypes));
}
@@ -700,17 +973,18 @@
static Bool
ReadCapabilityList(CapsContainer *caps, int count)
{
- rfbCapabilityInfo msginfo;
- int i;
+ rfbCapabilityInfo msginfo;
+ int i;
- for (i = 0; i < count; i++) {
- if (!ReadFromRFBServer((char *)&msginfo, sz_rfbCapabilityInfo))
- return False;
- msginfo.code = Swap32IfLE(msginfo.code);
- CapsEnable(caps, &msginfo);
- }
+ for (i = 0; i < count; i++) {
+ if (!ReadFromRFBServer((char *)&msginfo, sz_rfbCapabilityInfo)) {
+ return False;
+ }
+ msginfo.code = Swap32IfLE(msginfo.code);
+ CapsEnable(caps, &msginfo);
+ }
- return True;
+ return True;
}
@@ -729,6 +1003,11 @@
Bool requestCompressLevel = False;
Bool requestQualityLevel = False;
Bool requestLastRectEncoding = False;
+ Bool requestNewFBSizeEncoding = True;
+ Bool requestTextChatEncoding = True;
+ int dsm = 0;
+
+// fprintf(stderr, "SetFormatAndEncodings: sent_FBU state: %2d\n", sent_FBU);
spf.type = rfbSetPixelFormat;
spf.format = myFormat;
@@ -736,12 +1015,18 @@
spf.format.greenMax = Swap16IfLE(spf.format.greenMax);
spf.format.blueMax = Swap16IfLE(spf.format.blueMax);
+
+ currentMsg = rfbSetPixelFormat;
if (!WriteExact(rfbsock, (char *)&spf, sz_rfbSetPixelFormatMsg))
return False;
se->type = rfbSetEncodings;
se->nEncodings = 0;
+ if (appData.ultraDSM) {
+ dsm = 1;
+ }
+
if (appData.encodingsString) {
char *encStr = appData.encodingsString;
int encStrLen;
@@ -754,11 +1039,17 @@
encStrLen = strlen(encStr);
}
+if (getenv("DEBUG_SETFORMAT")) {
+ fprintf(stderr, "encs: ");
+ write(2, encStr, encStrLen);
+ fprintf(stderr, "\n");
+}
+
if (strncasecmp(encStr,"raw",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw);
} else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect);
- } else if (strncasecmp(encStr,"tight",encStrLen) == 0) {
+ } else if (strncasecmp(encStr,"tight",encStrLen) == 0 && !dsm) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight);
requestLastRectEncoding = True;
if (appData.compressLevel >= 0 && appData.compressLevel <= 9)
@@ -767,16 +1058,33 @@
requestQualityLevel = True;
} else if (strncasecmp(encStr,"hextile",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile);
- } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) {
+ } else if (strncasecmp(encStr,"zlib",encStrLen) == 0 && !dsm) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib);
if (appData.compressLevel >= 0 && appData.compressLevel <= 9)
requestCompressLevel = True;
- } else if (strncasecmp(encStr,"corre",encStrLen) == 0) {
+ } else if (strncasecmp(encStr,"corre",encStrLen) == 0 && !dsm) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE);
} else if (strncasecmp(encStr,"rre",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE);
+ } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) {
+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZRLE);
+#if DO_ZYWRLE
+ } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) {
+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE);
+ requestQualityLevel = True;
+ if (appData.qualityLevel < 3) {
+ zywrle_level = 3;
+ } else if (appData.qualityLevel < 6) {
+ zywrle_level = 2;
+ } else {
+ zywrle_level = 1;
+ }
+#endif
} else {
fprintf(stderr,"Unknown encoding '%.*s'\n",encStrLen,encStr);
+ if (dsm && strstr(encStr, "tight") == encStr) fprintf(stderr, "tight encoding does not yet work with ultraDSM, skipping it.\n");
+ if (dsm && strstr(encStr, "corre") == encStr) fprintf(stderr, "corre encoding does not yet work with ultraDSM, skipping it.\n");
+ if (dsm && strstr(encStr, "zlib" ) == encStr) fprintf(stderr, "zlib encoding does not yet work with ultraDSM, skipping it.\n");
}
encStr = nextEncStr;
@@ -797,7 +1105,7 @@
if (appData.useRemoteCursor) {
if (se->nEncodings < MAX_ENCODINGS)
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
- if (se->nEncodings < MAX_ENCODINGS)
+ if (se->nEncodings < MAX_ENCODINGS && !appData.useX11Cursor)
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
if (se->nEncodings < MAX_ENCODINGS)
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos);
@@ -806,10 +1114,14 @@
if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect);
}
+
+ if (se->nEncodings < MAX_ENCODINGS && requestNewFBSizeEncoding) {
+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize);
+ }
}
else {
if (SameMachine(rfbsock)) {
- if (!tunnelSpecified) {
+ if (!tunnelSpecified && appData.useRawLocal) {
fprintf(stderr,"Same machine: preferring raw encoding\n");
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw);
} else {
@@ -818,13 +1130,15 @@
}
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect);
- encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight);
+ if (!dsm) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight);
+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZRLE);
+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile);
- encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib);
- encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE);
+ if (!dsm) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib);
+ if (!dsm) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE);
- if (appData.compressLevel >= 0 && appData.compressLevel <= 9) {
+ if (!dsm && appData.compressLevel >= 0 && appData.compressLevel <= 9) {
encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel +
rfbEncodingCompressLevel0);
} else if (!tunnelSpecified) {
@@ -835,7 +1149,7 @@
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCompressLevel1);
}
- if (appData.enableJPEG) {
+ if (!dsm && appData.enableJPEG) {
if (appData.qualityLevel < 0 || appData.qualityLevel > 9)
appData.qualityLevel = 5;
encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel +
@@ -844,18 +1158,35 @@
if (appData.useRemoteCursor) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
- encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
+ if (!appData.useX11Cursor) {
+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
+ }
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos);
}
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect);
+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize);
}
len = sz_rfbSetEncodingsMsg + se->nEncodings * 4;
- se->nEncodings = Swap16IfLE(se->nEncodings);
+ if (!appData.ultraDSM) {
+ se->nEncodings = Swap16IfLE(se->nEncodings);
- if (!WriteExact(rfbsock, buf, len)) return False;
+ if (!WriteExact(rfbsock, buf, len)) return False;
+ } else {
+ /* for UltraVNC encryption DSM we have to send each encoding separately (why?) */
+ int i, errs = 0, nenc = se->nEncodings;
+
+ se->nEncodings = Swap16IfLE(se->nEncodings);
+
+ currentMsg = rfbSetEncodings;
+ if (!WriteExact(rfbsock, buf, sz_rfbSetEncodingsMsg)) errs++;
+ for (i=0; i < nenc; i++) {
+ if (!WriteExact(rfbsock, (char *)&encs[i], sizeof(CARD32))) errs++;
+ }
+ if (errs) return False;
+ }
return True;
}
@@ -868,31 +1199,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 +1289,36 @@
Bool
SendPointerEvent(int x, int y, int buttonMask)
{
- rfbPointerEventMsg pe;
+ rfbPointerEventMsg pe;
+
+ if (appData.fileActive) {
+ if (!dyn || time(NULL) < last_filexfer + delay_filexfer) {
+ //fprintf(stderr, "skip SendPointerEvent: %d - %d\n", last_filexfer, time(NULL));
+ return True;
+ }
+ }
+
+ pe.type = rfbPointerEvent;
+ pe.buttonMask = buttonMask;
+
+ if (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.type = rfbPointerEvent;
- pe.buttonMask = buttonMask;
- if (x < 0) x = 0;
- if (y < 0) y = 0;
-
- if (!appData.useX11Cursor)
- SoftCursorMove(x, y);
-
- pe.x = Swap16IfLE(x);
- pe.y = Swap16IfLE(y);
- return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg);
+ pe.x = Swap16IfLE(x);
+ pe.y = Swap16IfLE(y);
+ currentMsg = rfbPointerEvent;
+ return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg);
}
@@ -926,12 +1329,20 @@
Bool
SendKeyEvent(CARD32 key, Bool down)
{
- rfbKeyEventMsg ke;
+ rfbKeyEventMsg ke;
+
+ if (appData.fileActive) {
+ if (!dyn || time(NULL) < last_filexfer + delay_filexfer) {
+ //fprintf(stderr, "skip SendPointerEvent: %d - %d\n", last_filexfer, time(NULL));
+ return True;
+ }
+ }
- ke.type = rfbKeyEvent;
- ke.down = down ? 1 : 0;
- ke.key = Swap32IfLE(key);
- return WriteExact(rfbsock, (char *)&ke, sz_rfbKeyEventMsg);
+ ke.type = rfbKeyEvent;
+ ke.down = down ? 1 : 0;
+ ke.key = Swap32IfLE(key);
+ currentMsg = rfbKeyEvent;
+ return WriteExact(rfbsock, (char *)&ke, sz_rfbKeyEventMsg);
}
@@ -942,281 +1353,943 @@
Bool
SendClientCutText(char *str, int len)
{
- rfbClientCutTextMsg cct;
+ rfbClientCutTextMsg cct;
- if (serverCutText)
- free(serverCutText);
- serverCutText = NULL;
-
- cct.type = rfbClientCutText;
- cct.length = Swap32IfLE(len);
- return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) &&
- WriteExact(rfbsock, str, len));
+ if (serverCutText) {
+ free(serverCutText);
+ }
+ serverCutText = NULL;
+
+ if (appData.fileActive) {
+ if (!dyn || time(NULL) < last_filexfer + delay_filexfer) {
+ // ultravnc java viewer lets this one through.
+ return True;
+ }
+ }
+
+ if (appData.viewOnly) {
+ return True;
+ }
+
+ cct.type = rfbClientCutText;
+ cct.length = Swap32IfLE(len);
+ currentMsg = rfbClientCutText;
+ return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) &&
+ WriteExact(rfbsock, str, len));
}
+static int ultra_scale = 0;
-/*
- * HandleRFBServerMessage.
- */
+Bool
+SendServerScale(int nfac)
+{
+ rfbSetScaleMsg ssc;
+ if (nfac < 0 || nfac > 100) {
+ return True;
+ }
+
+ ultra_scale = nfac;
+ ssc.type = rfbSetScale;
+ ssc.scale = nfac;
+ currentMsg = rfbSetScale;
+ return WriteExact(rfbsock, (char *)&ssc, sz_rfbSetScaleMsg);
+}
Bool
-HandleRFBServerMessage()
+SendServerInput(Bool enabled)
{
- rfbServerToClientMsg msg;
+ rfbSetServerInputMsg sim;
- if (!ReadFromRFBServer((char *)&msg, 1))
- return False;
+ sim.type = rfbSetServerInput;
+ sim.status = enabled;
+ currentMsg = rfbSetServerInput;
+ return WriteExact(rfbsock, (char *)&sim, sz_rfbSetServerInputMsg);
+}
- switch (msg.type) {
+Bool
+SendSingleWindow(int x, int y)
+{
+ static int w_old = -1, h_old = -1;
+ rfbSetSWMsg sw;
- case rfbSetColourMapEntries:
- {
- int i;
- CARD16 rgb[3];
- XColor xc;
+ fprintf(stderr, "SendSingleWindow: %d %d\n", x, y);
- if (!ReadFromRFBServer(((char *)&msg) + 1,
- sz_rfbSetColourMapEntriesMsg - 1))
- return False;
+ if (x == -1 && y == -1) {
+ sw.type = rfbSetSW;
+ sw.x = Swap16IfLE(1);
+ sw.y = Swap16IfLE(1);
+ if (w_old > 0) {
+ si.framebufferWidth = w_old;
+ si.framebufferHeight = h_old;
+ ReDoDesktop();
+ }
+ w_old = h_old = -1;
+ } else {
+ sw.type = rfbSetSW;
+ sw.x = Swap16IfLE(x);
+ sw.y = Swap16IfLE(y);
+ w_old = si.framebufferWidth;
+ h_old = si.framebufferHeight;
+
+ }
+ sw.status = True;
+ currentMsg = rfbSetSW;
+ return WriteExact(rfbsock, (char *)&sw, sz_rfbSetSWMsg);
+}
- msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour);
- msg.scme.nColours = Swap16IfLE(msg.scme.nColours);
+Bool
+SendTextChat(char *str)
+{
+ 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", 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)
+{
+ raiseme(0);
+ rfbTextChatMsg chat;
+ chat.type = rfbTextChat;
+ chat.pad1 = 0;
+ chat.pad2 = 0;
+ chat.length = Swap32IfLE(rfbTextChatOpen);
+ return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg);
+}
- msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
+Bool
+SendTextChatClose(void)
+{
+ rfbTextChatMsg chat;
+ chat.type = rfbTextChat;
+ chat.pad1 = 0;
+ chat.pad2 = 0;
+ chat.length = Swap32IfLE(rfbTextChatClose);
+ appData.chatActive = False;
+ return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg);
+}
- for (i = 0; i < msg.fu.nRects; i++) {
- if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader))
- return False;
+Bool
+SendTextChatFinished(void)
+{
+ rfbTextChatMsg chat;
+ chat.type = rfbTextChat;
+ chat.pad1 = 0;
+ chat.pad2 = 0;
+ chat.length = Swap32IfLE(rfbTextChatFinished);
+ 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
- rect.encoding = Swap32IfLE(rect.encoding);
- if (rect.encoding == rfbEncodingLastRect)
- break;
+//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) {
+
+ }
- /* 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);
+ 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);
+ }
+ }
- switch (rect.encoding) {
+ len = (hdr[4] << 24) | (hdr[5] << 16) | (hdr[6] << 8) | hdr[7];
+ if (db) fprintf(stderr, "Got rfbFileTransfer: len2 %u\n", len);
- case rfbEncodingRaw:
+#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);
+ }
+ }
- bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8;
- linesToRead = BUFFER_SIZE / bytesPerLine;
+ read_no_more:
- while (rect.r.h > 0) {
- if (linesToRead > rect.r.h)
- linesToRead = rect.r.h;
+ 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);
+ }
+ }
- if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead))
- return False;
+ if (db) fprintf(stderr, "Got rfbFileTransfer done.\n");
+ skip_XtUpdateAll = 0;
- CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w,
- linesToRead);
+ if (db) fprintf(stderr, "CFX: B\n");
+ CheckFileXfer();
+//fprintf(stderr, "Out HandleFileXfer\n");
+ return True;
+}
+
+/*
+ * HandleRFBServerMessage.
+ */
- rect.r.h -= linesToRead;
- rect.r.y += linesToRead;
- }
- break;
+Bool
+HandleRFBServerMessage()
+{
+ static int db = -1;
+ rfbServerToClientMsg msg;
- 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 (db < 0) {
+ if (getenv("DEBUG_RFB_SMSG")) {
+ db = 1;
+ } else {
+ db = 0;
+ }
}
- XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY,
- rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+ if (!ReadFromRFBServer((char *)&msg, 1)) {
+ return False;
+ }
+ if (appData.ultraDSM) {
+ if (!ReadFromRFBServer((char *)&msg, 1)) {
+ return False;
+ }
+ }
- break;
- }
+//fprintf(stderr, "msg.type: %d\n", msg.type);
- 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 (msg.type == rfbFileTransfer) {
+ return HandleFileXfer();
}
- 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;
+ switch (msg.type) {
+
+ case rfbSetColourMapEntries:
+ {
+ int i;
+ CARD16 rgb[3];
+ XColor xc;
+
+ if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbSetColourMapEntriesMsg - 1)) {
+ return False;
}
- 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;
+ 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 rfbEncodingZlib:
- {
- switch (myFormat.bitsPerPixel) {
- case 8:
- if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
- return False;
- break;
- case 16:
- if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
- return False;
- break;
- case 32:
- if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
- return False;
- break;
+ case rfbFramebufferUpdate:
+ {
+ rfbFramebufferUpdateRectHeader rect;
+ int linesToRead;
+ int bytesPerLine;
+ int i;
+ int usecs;
+
+ int area_copyrect = 0;
+ int area_tight = 0;
+ int area_zrle = 0;
+ int area_raw = 0;
+ static int rdb = -1;
+
+ if (db) fprintf(stderr, "FBU-0: %.6f\n", dnow());
+ if (rdb < 0) {
+ if (getenv("SSVNC_DEBUG_RECTS")) {
+ rdb = atoi(getenv("SSVNC_DEBUG_RECTS"));
+ } else {
+ rdb = 0;
+ }
}
- break;
- }
- case rfbEncodingTight:
- {
- switch (myFormat.bitsPerPixel) {
- case 8:
- if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
- return False;
- break;
- case 16:
- if (!HandleTight16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
- return False;
- break;
- case 32:
- if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
- return False;
- break;
+ int skip_incFBU = 0;
+ sent_FBU = -1;
+
+ if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) {
+ return False;
}
- break;
- }
- default:
- fprintf(stderr,"Unknown rect encoding %d\n",
- (int)rect.encoding);
- return False;
- }
+ msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
- /* Now we may discard "soft cursor locks". */
- SoftCursorUnlockScreen();
- }
+ for (i = 0; i < msg.fu.nRects; i++) {
+ if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) {
+ return False;
+ }
+
+ rect.encoding = Swap32IfLE(rect.encoding);
+ if (rect.encoding == rfbEncodingLastRect) {
+ break;
+ }
+
+ rect.r.x = Swap16IfLE(rect.r.x);
+ rect.r.y = Swap16IfLE(rect.r.y);
+ rect.r.w = Swap16IfLE(rect.r.w);
+ rect.r.h = Swap16IfLE(rect.r.h);
+
+
+ if (rect.encoding == rfbEncodingXCursor || rect.encoding == rfbEncodingRichCursor) {
+ if (db) fprintf(stderr, "FBU-Cur1 %.6f\n", dnow());
+ if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rect.encoding)) {
+ return False;
+ }
+ if (db) fprintf(stderr, "FBU-Cur2 %.6f\n", dnow());
+ continue;
+ }
+
+ if (rect.encoding == rfbEncodingPointerPos) {
+ if (db) fprintf(stderr, "FBU-Pos1 %.6f\n", dnow());
+ if (0) fprintf(stderr, "CursorPos: %d %d / %d %d\n", rect.r.x, rect.r.y, rect.r.w, rect.r.h);
+ if (ultra_scale > 0) {
+ int f = ultra_scale;
+ if (!HandleCursorPos(rect.r.x/f, rect.r.y/f)) {
+ return False;
+ }
+ } else {
+ if (!HandleCursorPos(rect.r.x, rect.r.y)) {
+ return False;
+ }
+ }
+ if (db) fprintf(stderr, "FBU-Pos2 %.6f\n", dnow());
+ continue;
+ }
+ if (rect.encoding == rfbEncodingNewFBSize) {
+ 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);
+
+ 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, rect.encoding);
+ return False;
+ }
+ }
+
+ if (rect.r.h * rect.r.w == 0) {
+ fprintf(stderr,"*** Warning *** Zero size rect: %dx%d+%d+%d encoding=%d\n",
+ rect.r.w, rect.r.h, rect.r.x, rect.r.y, rect.encoding);
+ if (0) continue;
+ }
+
+ /* If RichCursor encoding is used, we should prevent collisions
+ between framebuffer updates and cursor drawing operations. */
+ if (db) fprintf(stderr, "FBU-SCL1 %.6f\n", dnow());
+
+ SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h);
+
+ if (db) fprintf(stderr, "FBU-SCL2 %.6f\n", dnow());
+
+ switch (rect.encoding) {
+
+ case rfbEncodingRaw:
+
+ bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8;
+ linesToRead = BUFFER_SIZE / bytesPerLine;
+
+ if (db) fprintf(stderr, "Raw: %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y);
+ area_raw += rect.r.w * rect.r.h;
+
+ while (rect.r.h > 0) {
+ if (linesToRead > rect.r.h) {
+ linesToRead = rect.r.h;
+ }
+
+ if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) {
+ return False;
+ }
+
+ CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, linesToRead);
+
+ rect.r.h -= linesToRead;
+ rect.r.y += linesToRead;
+ }
+ break;
+
+ case rfbEncodingCopyRect:
+ {
+ rfbCopyRect cr;
+
+ if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) {
+ return False;
+ }
+ 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". */
+ if (db) fprintf(stderr, "FBU-SUL1 %.6f\n", dnow());
+
+ SoftCursorUnlockScreen();
+
+ if (db) fprintf(stderr, "FBU-SUL2 %.6f\n", dnow());
+ }
+
+ if (1 || area_copyrect) {
+ if (db) fprintf(stderr, "FBU-XSN1 %.6f\n", dnow());
+ XSync(dpy, False);
+ if (db) fprintf(stderr, "FBU-XSN2 %.6f\n", dnow());
+ }
+ 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 +2297,165 @@
mainly to avoid copyrect using invalid screen contents - not sure
if we'd need it otherwise. */
- if (appData.useShm)
- XSync(dpy, False);
+ if (appData.useShm) {
+ XSync(dpy, False);
+ } else
#endif
+ {
+ XSync(dpy, False);
+ }
+
+ if (skip_XtUpdate || skip_incFBU) {
+ ;
+ } else if (!SendIncrementalFramebufferUpdateRequest()) {
+ return False;
+ }
- if (!SendIncrementalFramebufferUpdateRequest())
- return False;
-
- break;
+ break;
}
case rfbBell:
{
- Window toplevelWin;
+ Window toplevelWin;
- XBell(dpy, 0);
+ if (appData.useBell) {
+ XBell(dpy, 0);
+ }
+
+ if (appData.raiseOnBeep) {
+ toplevelWin = XtWindow(toplevel);
+ XMapRaised(dpy, toplevelWin);
+ }
- if (appData.raiseOnBeep) {
- toplevelWin = XtWindow(toplevel);
- XMapRaised(dpy, toplevelWin);
+ break;
}
- break;
- }
+ case rfbServerCutText:
+ {
+ if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbServerCutTextMsg - 1)) {
+ return False;
+ }
- case rfbServerCutText:
- {
- if (!ReadFromRFBServer(((char *)&msg) + 1,
- sz_rfbServerCutTextMsg - 1))
- return False;
+ msg.sct.length = Swap32IfLE(msg.sct.length);
- msg.sct.length = Swap32IfLE(msg.sct.length);
+ if (serverCutText) {
+ free(serverCutText);
+ }
- if (serverCutText)
- free(serverCutText);
+ serverCutText = malloc(msg.sct.length+1);
- serverCutText = malloc(msg.sct.length+1);
+ if (!ReadFromRFBServer(serverCutText, msg.sct.length)) {
+ return False;
+ }
- if (!ReadFromRFBServer(serverCutText, msg.sct.length))
- return False;
+ serverCutText[msg.sct.length] = 0;
- serverCutText[msg.sct.length] = 0;
+ newServerCutText = True;
- newServerCutText = True;
+ break;
+ }
- break;
- }
+ case rfbTextChat:
+ {
+ char *buffer = NULL;
+ if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbTextChatMsg - 1)) {
+ return False;
+ }
+ msg.tc.length = Swap32IfLE(msg.tc.length);
+ switch(msg.tc.length) {
+ case rfbTextChatOpen:
+ if (appData.termChat) {
+ printChat("\n*ChatOpen*\n\nSend: ", True);
+ } else {
+ printChat("\n*ChatOpen*\n", True);
+ }
+ appData.chatActive = True;
+ break;
+ case rfbTextChatClose:
+ printChat("\n*ChatClose*\n", False);
+ appData.chatActive = False;
+ break;
+ case rfbTextChatFinished:
+ printChat("\n*ChatFinished*\n", False);
+ appData.chatActive = False;
+ break;
+ default:
+ buffer = (char *)malloc(msg.tc.length+1);
+ if (!ReadFromRFBServer(buffer, msg.tc.length)) {
+ free(buffer);
+ return False;
+ }
+ buffer[msg.tc.length] = '\0';
+ appData.chatActive = True;
+ GotChatText(buffer, msg.tc.length);
+ free(buffer);
+ }
+ break;
+ }
- default:
- fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type);
- return False;
- }
+ case rfbResizeFrameBuffer:
+ {
+ rfbResizeFrameBufferMsg rsmsg;
+ if (!ReadFromRFBServer(((char *)&rsmsg) + 1, sz_rfbResizeFrameBufferMsg - 1)) {
+ return False;
+ }
+ si.framebufferWidth = Swap16IfLE(rsmsg.framebufferWidth);
+ si.framebufferHeight = Swap16IfLE(rsmsg.framebufferHeight);
+ fprintf(stderr,"UltraVNC ReSize: %dx%d\n", si.framebufferWidth, si.framebufferHeight);
+ ReDoDesktop();
+ break;
+ }
- return True;
+ case rfbRestartConnection:
+ {
+ rfbRestartConnectionMsg rc;
+ int len;
+ char *rs_str;
+ char buf[5] = "\xff\xff\xff\xff";
+ fprintf(stderr, "rfbRestartConnection. type=%d\n", (int) rc.type);
+ if (!ReadFromRFBServer((char *)&rc + 1, sz_rfbRestartConnectionMsg - 1)) {
+ return False;
+ }
+ len = Swap32IfLE(rc.length);
+ fprintf(stderr, "rfbRestartConnection. pad1=%d\n", (int) rc.pad1);
+ fprintf(stderr, "rfbRestartConnection. pad2=%d\n", (int) rc.pad2);
+ fprintf(stderr, "rfbRestartConnection. len=%d\n", len);
+ if (len) {
+ rs_str = (char *)malloc(2*len);
+ if (!ReadFromRFBServer(rs_str, len)) {
+ return False;
+ }
+ restart_session_pw = rs_str;
+ restart_session_len = len;
+ }
+ if (!WriteExact(rfbsock, buf, 4)) {
+ return False;
+ }
+ InitialiseRFBConnection();
+ SetVisualAndCmap();
+ SetFormatAndEncodings();
+ DesktopCursorOff();
+ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False);
+
+ break;
+ }
+
+ default:
+ fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type);
+ return False;
+ }
+
+ if (appData.fileActive) {
+ if (filexfer_sock < 0 && filexfer_listen < 0) {
+ appData.fileActive = False;
+ SendFramebufferUpdateRequest(0, 0, 1, 1, False);
+ } else {
+//fprintf(stderr, "CFX: A\n");
+ CheckFileXfer();
+ }
+ }
+
+ return True;
}
@@ -1296,26 +2475,47 @@
#define CONCAT2(a,b) a##b
#define CONCAT2E(a,b) CONCAT2(a,b)
+#define CONCAT3(a,b,c) a##b##c
+#define CONCAT3E(a,b,c) CONCAT3(a,b,c)
+
+static unsigned char* frameBuffer = NULL;
+static int frameBufferLen = 0;
+
#define BPP 8
#include "rre.c"
#include "corre.c"
#include "hextile.c"
#include "zlib.c"
#include "tight.c"
+#include "zrle.c"
#undef BPP
+
#define BPP 16
#include "rre.c"
#include "corre.c"
#include "hextile.c"
#include "zlib.c"
#include "tight.c"
+#include "zrle.c"
+#define REALBPP 15
+#include "zrle.c"
#undef BPP
+
#define BPP 32
#include "rre.c"
#include "corre.c"
#include "hextile.c"
#include "zlib.c"
#include "tight.c"
+#include "zrle.c"
+#define REALBPP 24
+#include "zrle.c"
+#define REALBPP 24
+#define UNCOMP 8
+#include "zrle.c"
+#define REALBPP 24
+#define UNCOMP -8
+#include "zrle.c"
#undef BPP
/*
@@ -1358,9 +2558,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 +2662,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/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 2008-10-10 12:26:07.000000000 -0400
@@ -33,68 +33,97 @@
void
ShmCleanup()
{
- fprintf(stderr,"ShmCleanup called\n");
- if (needShmCleanup) {
- shmdt(shminfo.shmaddr);
- shmctl(shminfo.shmid, IPC_RMID, 0);
- needShmCleanup = False;
- }
+ fprintf(stderr,"ShmCleanup called\n");
+ if (needShmCleanup) {
+ shmdt(shminfo.shmaddr);
+ shmctl(shminfo.shmid, IPC_RMID, 0);
+ needShmCleanup = False;
+ }
+}
+
+Bool UsingShm() {
+ return needShmCleanup;
}
static int
ShmCreationXErrorHandler(Display *dpy, XErrorEvent *error)
{
- caughtShmError = True;
- return 0;
+ caughtShmError = True;
+ return 0;
}
+int scale_round(int len, double fac);
+extern int scale_x, scale_y;
+extern double scale_factor_x, scale_factor_y;
+
XImage *
-CreateShmImage()
+CreateShmImage(int do_ycrop)
{
- XImage *image;
- XErrorHandler oldXErrorHandler;
-
- if (!XShmQueryExtension(dpy))
- return NULL;
-
- image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo,
- si.framebufferWidth, si.framebufferHeight);
- if (!image) return NULL;
-
- shminfo.shmid = shmget(IPC_PRIVATE,
- image->bytes_per_line * image->height,
- IPC_CREAT|0777);
-
- if (shminfo.shmid == -1) {
- XDestroyImage(image);
- return NULL;
- }
-
- shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0);
-
- if (shminfo.shmaddr == (char *)-1) {
- XDestroyImage(image);
- shmctl(shminfo.shmid, IPC_RMID, 0);
- return NULL;
- }
-
- shminfo.readOnly = True;
-
- oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler);
- XShmAttach(dpy, &shminfo);
- XSync(dpy, False);
- XSetErrorHandler(oldXErrorHandler);
-
- if (caughtShmError) {
- XDestroyImage(image);
- shmdt(shminfo.shmaddr);
- shmctl(shminfo.shmid, IPC_RMID, 0);
- return NULL;
- }
+ XImage *image;
+ XErrorHandler oldXErrorHandler;
+ int ymax = si.framebufferHeight;
+ 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);
+ //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);
+ //fprintf(stderr, "CreateShmImage: destroyed 'image' (2)\n");
+ 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);
+ //fprintf(stderr, "CreateShmImage: destroyed 'image' (3)\n");
+ 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 2008-10-15 08:30:41.000000000 -0400
@@ -27,6 +27,7 @@
#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>
@@ -56,22 +57,366 @@
*/
static Bool rfbsockReady = False;
+static Bool xfrsockReady = False;
+static XtInputId rfbsockId = 0;
+static XtInputId xfrsockId = 0;
+static int do_rfbsockId = 0;
+static int do_xfrsockId = 0;
+
static void
rfbsockReadyCallback(XtPointer clientData, int *fd, XtInputId *id)
{
- rfbsockReady = True;
- XtRemoveInput(*id);
+ rfbsockReady = True;
+// XtRemoveInput(*id);
+ XtRemoveInput(rfbsockId);
+ if (do_xfrsockId) {
+ XtRemoveInput(xfrsockId);
+ }
+}
+
+static void
+xfrsockReadyCallback(XtPointer clientData, int *fd, XtInputId *id)
+{
+ xfrsockReady = True;
+ XtRemoveInput(xfrsockId);
+ if (do_rfbsockId) {
+ XtRemoveInput(rfbsockId);
+ }
+}
+
+
+extern int skip_XtUpdate;
+extern int skip_XtUpdateAll;
+extern int filexfer_sock, filexfer_listen;
+extern time_t start_listen;
+extern void CheckTextInput(void);
+extern time_t last_filexfer;
+
+static char fxfer[65536];
+int fxfer_size = 65536;
+
+int rfbsock_is_ready(void) {
+ fd_set fds;
+ struct timeval tv;
+
+ if (rfbsock < 0) {
+ return 0;
+ }
+ FD_ZERO(&fds);
+ FD_SET(rfbsock,&fds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ if (select(rfbsock+1, &fds, NULL, NULL, &tv) > 0) {
+ if (FD_ISSET(rfbsock, &fds)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+time_t filexfer_start = 0;
+
+void CheckFileXfer() {
+ fd_set fds;
+ struct timeval tv;
+ int i, icnt = 0, igot = 0, bytes0 = 0, bytes = 0, grace = 0, n, list = 0;
+ int db = 0;
+
+ if (!appData.fileActive || (filexfer_sock < 0 && filexfer_listen < 0)) {
+ return;
+ }
+
+ if (filexfer_listen >= 0 && time(NULL) > start_listen + 30) {
+ fprintf(stderr, "filexfer closing aging listen socket.\n");
+ close(filexfer_listen);
+ filexfer_listen = -1;
+ return;
+ }
+//fprintf(stderr, "In CheckFileXfer\n");
+
+ if (filexfer_listen >=0) {
+ n = filexfer_listen;
+ list = 1;
+ } else {
+ n = filexfer_sock;
+ }
+
+ while (1) {
+ icnt++;
+ FD_ZERO(&fds);
+ FD_SET(n,&fds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ if (select(n+1, &fds, NULL, NULL, &tv) > 0) {
+ if (FD_ISSET(n, &fds)) {
+ if (list) {
+ if (filexfer_sock >= 0) {
+ fprintf(stderr, "filexfer close stale(?) filexfer_sock.\n");
+ close(filexfer_sock);
+ filexfer_sock = -1;
+ }
+ filexfer_sock = AcceptTcpConnection(filexfer_listen);
+ if (filexfer_sock >= 0) {
+ fprintf(stderr, "filexfer accept OK.\n");
+ close(filexfer_listen);
+ filexfer_listen = -1;
+ filexfer_start = last_filexfer = time(NULL);
+ } else {
+ fprintf(stderr, "filexfer accept failed.\n");
+ }
+ break;
+ } else {
+ ssize_t rn;
+ unsigned char hdr[12];
+ unsigned int len;
+ if (db) fprintf(stderr, "try read filexfer...\n");
+#if 1
+ rn = read(n, fxfer, 1*8192);
+if (db) {
+ int i;
+ fprintf(stderr, "CFX HDR:");
+ for (i=0; i < 12; i++) {
+ fprintf(stderr, " %d", (int) fxfer[i]);
+ }
+ fprintf(stderr, " ?\n");
+}
+ if (0 || db) fprintf(stderr, "filexfer read[%d] %d.\n", icnt, rn);
+ if (rn < 0) {
+ fprintf(stderr, "filexfer bad read: %d\n", errno);
+ break;
+ } else if (rn == 0) {
+ fprintf(stderr, "filexfer gone.\n");
+ close(n);
+ filexfer_sock = -1;
+ last_filexfer = time(NULL);
+ //fprintf(stderr, "last_filexfer-2a: %d\n", last_filexfer);
+ appData.fileActive = False;
+ SendFramebufferUpdateRequest(0, 0, 1, 1, False);
+ return;
+ } else if (rn > 0) {
+ if (db > 1) write(2, fxfer, rn);
+ if (db) fprintf(stderr, "\n");
+ bytes += rn;
+ last_filexfer = time(NULL);
+ //fprintf(stderr, "last_filexfer-2b: %d\n", last_filexfer);
+
+ if (0) {
+ /* WE TRY TO FIX THIS IN THE JAVA NOW */
+ if (appData.ultraDSM) {
+ unsigned char msg = rfbFileTransfer;
+ unsigned char hdc = (unsigned char) fxfer[0];
+ if (msg == hdc) {
+ /* cross your fingers... */
+ WriteExact(rfbsock, (char *)&msg, 1);
+ }
+ }
+ }
+ if (!WriteExact(rfbsock, fxfer, rn)) {
+ return;
+ }
+ igot = 1;
+ }
+#else
+ // not working, not always 7 msg type.
+ rn = read(n, hdr, 12);
+ if (db) fprintf(stderr, "filexfer read %d.\n", rn);
+ if (rn == 0) {
+ fprintf(stderr, "filexfer gone.\n");
+ close(n);
+ filexfer_sock = -1;
+ last_filexfer = time(NULL);
+ return;
+ }
+ if (rn == 12) {
+ len = (hdr[8] << 24) | (hdr[9] << 16) | (hdr[10] << 8) | hdr[11];
+ if (db) fprintf(stderr, "n=%d len=%d\n", rn, len);
+ if (db > 1) write(2, hdr, rn);
+ if (db) fprintf(stderr, "\n");
+ WriteExact(rfbsock, hdr, rn);
+ if (len > 0) {
+ rn = read(len, fxfer, len);
+ if (!WriteExact(rfbsock, fxfer, len)) {
+ last_filexfer = time(NULL);
+ return;
+ }
+ if (db > 1) write(2, fxfer, len);
+ }
+ if (db) fprintf(stderr, "\n");
+ } else {
+ if (db) fprintf(stderr, "bad rn: %d\n", rn);
+ }
+ igot = 1;
+#endif
+ }
+ }
+ } else {
+ if (bytes >= 8192) {
+ int ok = 0;
+ if (bytes0 == 0) {
+ ok = 1;
+ } else if (bytes >= bytes0 + 12) {
+ ok = 1;
+ } else if (grace < 20) {
+ ok = 1;
+ }
+ if (ok) {
+ grace++;
+ bytes0 = bytes;
+ //fprintf(stderr, "grace: %d\n", grace);
+ // forgot that this is about...
+ usleep(10 * 1000);
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ if (igot) {
+ last_filexfer = time(NULL);
+ //fprintf(stderr, "last_filexfer-2c: %d\n", last_filexfer);
+ }
+//fprintf(stderr, "Out CheckFileXfer\n");
+ return;
}
+static 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: ");
+}
+
+static time_t time_mark;
+extern int delay_filexfer;
+#include <sys/stat.h>
+
+extern double start_time;
+
static void
ProcessXtEvents()
{
- rfbsockReady = False;
- XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask,
- rfbsockReadyCallback, NULL);
- while (!rfbsockReady) {
- XtAppProcessEvent(appContext, XtIMAll);
- }
+ int y, db = 0;
+ static int dyn = -1;
+ 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) fprintf(stderr, "ProcessXtEvents: %d %.4f\n", skip_XtUpdateAll, dnow() - start_time);
+
+ 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) {
+ //fprintf(stderr, "cwa\n");
+ 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
@@ -151,6 +496,8 @@
}
+int currentMsg = -1;
+
/*
* Write an exact number of bytes, and don't return until you've sent them.
*/
@@ -158,37 +505,81 @@
Bool
WriteExact(int sock, char *buf, int n)
{
- fd_set fds;
- int i = 0;
- int j;
-
- while (i < n) {
- j = write(sock, buf + i, (n - i));
- if (j <= 0) {
- if (j < 0) {
- if (errno == EWOULDBLOCK || errno == EAGAIN) {
- FD_ZERO(&fds);
- FD_SET(rfbsock,&fds);
+ fd_set fds;
+ int i = 0;
+ int j;
+
+ if (appData.ultraDSM && currentMsg >= 0) {
+ /* this is for goofy UltraVNC DSM send RFB msg char twice: */
+ unsigned char msg = (unsigned char) currentMsg;
+ currentMsg = -1;
+ if (!WriteExact(sock, (char *)&msg, sizeof(msg))) {
+ return False;
+ }
+ }
+ currentMsg = -1;
- if (select(rfbsock+1, NULL, &fds, NULL, NULL) <= 0) {
- fprintf(stderr,programName);
- perror(": select");
- return False;
- }
- j = 0;
- } else {
- fprintf(stderr,programName);
- perror(": write");
- return False;
+ while (i < n) {
+ j = write(sock, buf + i, (n - i));
+ if (j <= 0) {
+ if (j < 0) {
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ FD_ZERO(&fds);
+ FD_SET(rfbsock,&fds);
+
+ if (select(rfbsock+1, NULL, &fds, NULL, NULL) <= 0) {
+ fprintf(stderr,programName);
+ perror(": select");
+ return False;
+ }
+ j = 0;
+ } else {
+ fprintf(stderr,programName);
+ perror(": write");
+ return False;
+ }
+ } else {
+ fprintf(stderr,"%s: write failed\n",programName);
+ return False;
+ }
+ }
+ i += j;
}
- } else {
- fprintf(stderr,"%s: write failed\n",programName);
- return False;
- }
- }
- i += j;
- }
- return True;
+ return True;
+}
+
+int
+ConnectToUnixSocket(char *file) {
+ int sock;
+ struct sockaddr_un addr;
+ int i;
+
+ memset(&addr, 0, sizeof(struct sockaddr_un));
+
+ addr.sun_family = AF_UNIX;
+
+ for (i=0; i < 108; i++) {
+ addr.sun_path[i] = file[i];
+ if (file[i] == '\0') {
+ break;
+ }
+ }
+
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0) {
+ fprintf(stderr,programName);
+ perror(": ConnectToUnixSocket: socket");
+ return -1;
+ }
+
+ if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ fprintf(stderr, programName);
+ perror(": ConnectToUnixSocket: connect");
+ close(sock);
+ return -1;
+ }
+
+ return sock;
}
@@ -203,6 +594,8 @@
struct sockaddr_in addr;
int one = 1;
+ memset(&addr, 0, sizeof(struct sockaddr_in));
+
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = host;
@@ -232,7 +625,22 @@
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
@@ -245,6 +653,8 @@
int sock, port;
struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(struct sockaddr_in));
+
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
@@ -272,6 +682,8 @@
* ListenAtTcpPort starts listening at the given TCP port.
*/
+int use_loopback = 0;
+
int
ListenAtTcpPort(int port)
{
@@ -279,10 +691,16 @@
struct sockaddr_in addr;
int one = 1;
+ memset(&addr, 0, sizeof(struct sockaddr_in));
+
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
+ if (getenv("VNCVIEWER_LISTEN_LOCALHOST") || use_loopback) {
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ }
+
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
fprintf(stderr,programName);
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tight.c vnc_unixsrc/vncviewer/tight.c
--- vnc_unixsrc.orig/vncviewer/tight.c 2002-04-30 09:07:31.000000000 -0400
+++ vnc_unixsrc/vncviewer/tight.c 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/tunnel.c vnc_unixsrc/vncviewer/tunnel.c
--- vnc_unixsrc.orig/vncviewer/tunnel.c 2003-07-31 04:03:49.000000000 -0400
+++ vnc_unixsrc/vncviewer/tunnel.c 2007-05-08 21:28:01.000000000 -0400
@@ -132,6 +132,7 @@
{
char *colonPos;
int len, portOffset;
+ int disp;
if (tunnelArgIndex >= *pargc - 2)
usage();
@@ -153,7 +154,14 @@
if (!len || strspn(colonPos, "-0123456789") != len) {
usage();
}
+#if 0
*remotePort = atoi(colonPos) + portOffset;
+#else
+ disp = atoi(colonPos);
+ if (portOffset != 0 && disp >= 100)
+ portOffset = 0;
+ *remotePort = disp + portOffset;
+#endif
}
sprintf(lastArgv, "localhost::%d", localPort);
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncviewer/vncviewer.c
--- vnc_unixsrc.orig/vncviewer/vncviewer.c 2004-01-13 09:22:05.000000000 -0500
+++ vnc_unixsrc/vncviewer/vncviewer.c 2008-10-17 20:36:47.000000000 -0400
@@ -22,6 +22,7 @@
*/
#include "vncviewer.h"
+#include <X11/Xaw/Toggle.h>
char *programName;
XtAppContext appContext;
@@ -29,11 +30,190 @@
Widget toplevel;
+void set_sbwidth(int sbw) {
+ char *q, *p, t[5];
+ int i, k, N = 4;
+ int db = 0;
+
+ if (sbw < 1) {
+ sbw = 2;
+ } else if (sbw > 100) {
+ sbw = 100;
+ }
+ if (db) fprintf(stderr, "sbw: %d\n", sbw);
+
+ sprintf(t, "%4d", sbw);
+ k = 0;
+ while (fallback_resources[k] != NULL) {
+ q = strstr(fallback_resources[k], "horizontal.height: ");
+ if (!q) {
+ q = strstr(fallback_resources[k], "vertical.width: ");
+ }
+ if (q) {
+ p = strdup(fallback_resources[k]);
+ q = strstr(p, ": ");
+ if (q) {
+ q++;
+ q++;
+ for (i=0; i < N; i++) {
+ *(q+i) = t[i];
+ }
+ fallback_resources[k] = p;
+ if (db) fprintf(stderr, "res: %s\n\n", p);
+ }
+ }
+ k++;
+ }
+}
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+void unixpw(char *instr) {
+ char *str, *q, *infile = NULL;
+ FILE *in;
+ int i, rmfile = 0;
+ struct stat sb;
+ int N = 99;
+ char username[100], passwd[100];
+
+ for (i=0; i<100; i++) {
+ username[i] = '\0';
+ passwd[i] = '\0';
+ }
+
+ if (instr == NULL) {
+ return;
+ } else if (!strcmp(instr, "")) {
+ return;
+ }
+
+ str = strdup(instr);
+
+ if (strstr(str, "rm:") == str) {
+ rmfile = 1;
+ infile = str + strlen("rm:");
+ } else if (stat(str, &sb) == 0) {
+ infile = str;
+ }
+ if (!strcmp(str, ".")) {
+ char *p;
+ fprintf(stderr, "\nUnix Username: ");
+ if (fgets(username, N, stdin) == NULL) {
+ exit(1);
+ }
+ p = getpass("Unix Password: ");
+ if (! p) {
+ exit(1);
+ }
+ strncpy(passwd, p, N);
+ fprintf(stderr, "\n");
+
+ } else if (!strcmp(str, "-")) {
+ char *p, *q;
+ p = getpass("unixuser@unixpasswd: ");
+ if (! p) {
+ exit(1);
+ }
+ q = strchr(p, '@');
+ if (! q) {
+ exit(1);
+ }
+ *q = '\0';
+ strncpy(username, p, N);
+ strncpy(passwd, q+1, N);
+
+ } else if (infile) {
+ in = fopen(infile, "r");
+ if (in == NULL) {
+ fprintf(stderr, "failed to open -unixpw file.\n");
+ exit(1);
+ }
+ if (fgets(username, N, in) == NULL) {
+ exit(1);
+ }
+ if (fgets(passwd, N, in) == NULL) {
+ exit(1);
+ }
+ fclose(in);
+ fprintf(stderr, "read username@passwd from file: %s\n", infile);
+ if (rmfile) {
+ fprintf(stderr, "deleting username@passwd file: %s\n", infile);
+ unlink(infile);
+ }
+ } else if (strchr(str, '@')) {
+ char *q = strchr(str, '@');
+ *q = '\0';
+ strncpy(username, str, N);
+ strncpy(passwd, q+1, N);
+ } else {
+ exit(1);
+ }
+
+ free(str);
+
+ if (! getenv("SSVNC_UNIXPW_NOESC")) {
+ SendKeyEvent(XK_Escape, 1);
+ SendKeyEvent(XK_Escape, 0);
+ }
+
+ q = username;
+ while (*q != '\0' && *q != '\n') {
+ char c = *q;
+ if (c >= 0x20 && c <= 0x07e) {
+ KeySym ks = (KeySym) c;
+ SendKeyEvent(ks, 1);
+ SendKeyEvent(ks, 0);
+ }
+ q++;
+ }
+
+ SendKeyEvent(XK_Return, 1);
+ SendKeyEvent(XK_Return, 0);
+
+ q = passwd;
+ while (*q != '\0' && *q != '\n') {
+ char c = *q;
+ if (c >= 0x20 && c <= 0x07e) {
+ KeySym ks = (KeySym) c;
+ SendKeyEvent(ks, 1);
+ SendKeyEvent(ks, 0);
+ }
+ q++;
+ }
+
+ SendKeyEvent(XK_Return, 1);
+ SendKeyEvent(XK_Return, 0);
+}
+
+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
main(int argc, char **argv)
{
- int i;
- programName = argv[0];
+ int i, save_sbw;
+ char *pw_loc = NULL;
+ programName = argv[0];
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-env") == 0) {
+ if (i+1 < argc) {
+ char *estr = argv[i+1];
+ if (strchr(estr, '=')) {
+ putenv(estr);
+ }
+ }
+ }
+ }
/* The -listen option is used to make us a daemon process which listens for
incoming connections from servers, rather than actively connecting to a
@@ -45,89 +225,1363 @@
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 (strstr(argv[i], " pw=") != NULL) {
+ pw_loc = strstr(argv[i], " pw=") + 1;
+ }
+ }
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-listen") == 0) {
+ listenForIncomingConnections(&argc, argv, i);
+ break;
+ }
+ if (strcmp(argv[i], "-multilisten") == 0) {
+ putenv("SSVNC_MULTIPLE_LISTEN=1");
+ listenForIncomingConnections(&argc, argv, i);
+ break;
+ }
+ if (strcmp(argv[i], "-tunnel") == 0 || strcmp(argv[i], "-via") == 0) {
+ if (!createTunnel(&argc, argv, i)) {
+ exit(1);
+ }
+ break;
+ }
+ if (strcmp(argv[i], "-printres") == 0 || strcmp(argv[i], "-res") == 0) {
+ int j = 0;
+ fprintf(stdout, "\n! Ssvnc fallback X resources:\n\n");
+ while (1) {
+ char *p = fallback_resources[j++];
+ int k = 0;
+ if (p == NULL) break;
+ while (*p != '\0') {
+ fprintf(stdout, "%c", *p);
+ if (k > 0 && *p == 'n' && *(p-1) == '\\') {
+ fprintf(stdout, "\\\n");
+ }
+ p++; k++;
+ }
+ fprintf(stdout, "\n\n");
+ }
+ exit(0);
+ }
+ }
+
+ if (argc > 1 && strstr(argv[1], "-h") == argv[1]) {
+ usage();
+ return 0;
+ }
/* Call the main Xt initialisation function. It parses command-line options,
generating appropriate resource specs, and makes a connection to the X
display. */
- toplevel = XtVaAppInitialize(&appContext, "Vncviewer",
- cmdLineOptions, numCmdLineOptions,
- &argc, argv, fallback_resources,
- XtNborderWidth, 0, NULL);
+ appData.sbWidth = 0;
+ if (getenv("VNCVIEWER_SBWIDTH")) {
+ int sbw = atoi(getenv("VNCVIEWER_SBWIDTH"));
+ if (sbw > 0) {
+ appData.sbWidth = sbw;
+ }
+ }
+ if (appData.sbWidth == 0) {
+ int i, sbw = 0;
+ for (i = 1; i < argc - 1; i++) {
+ if (!strcmp(argv[i], "-sbwidth")) {
+ sbw = atoi(argv[i+1]);
+ }
+ }
+ if (sbw > 0) {
+ appData.sbWidth = sbw;
+ }
+ }
+ save_sbw = appData.sbWidth;
+ if (save_sbw > 0) {
+ set_sbwidth(save_sbw);
+ } else {
+ set_sbwidth(6);
+ }
+
+ toplevel = XtVaAppInitialize(&appContext, "Ssvnc", cmdLineOptions,
+ numCmdLineOptions, &argc, argv, fallback_resources,
+ XtNborderWidth, 0, NULL);
- dpy = XtDisplay(toplevel);
+ dpy = XtDisplay(toplevel);
/* Interpret resource specs and process any remaining command-line arguments
(i.e. the VNC server name). If the server name isn't specified on the
command line, getArgsAndResources() will pop up a dialog box and wait
for one to be entered. */
- GetArgsAndResources(argc, argv);
+ GetArgsAndResources(argc, argv);
+
+ if (save_sbw) {
+ appData.sbWidth = save_sbw;
+ }
+
+ 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 >= 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);
+ } else if (getenv("SSVNC_UNIXPW")) {
+ unixpw(getenv("SSVNC_UNIXPW"));
+ }
/* Create the "popup" widget - this won't actually appear on the screen until
some user-defined event causes the "ShowPopup" action to be invoked */
- CreatePopup();
+ CreatePopup();
+ CreateScaleN();
+ CreateQuality();
+ CreateCompress();
+ CreateChat();
/* Find the best pixel format and X visual/colormap to use */
- SetVisualAndCmap();
+ SetVisualAndCmap();
/* Create the "desktop" widget, and perform initialisation which needs doing
before the widgets are realized */
- ToplevelInitBeforeRealization();
+ ToplevelInitBeforeRealization();
- DesktopInitBeforeRealization();
+ DesktopInitBeforeRealization();
/* "Realize" all the widgets, i.e. actually create and map their X windows */
- XtRealizeWidget(toplevel);
+ XtRealizeWidget(toplevel);
/* Perform initialisation that needs doing after realization, now that the X
windows exist */
- InitialiseSelection();
+ InitialiseSelection();
- ToplevelInitAfterRealization();
+ ToplevelInitAfterRealization();
- DesktopInitAfterRealization();
+ DesktopInitAfterRealization();
/* Tell the VNC server which pixel format and encodings we want to use */
- SetFormatAndEncodings();
+ SetFormatAndEncodings();
+
+ 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;
+int do_fb_update = 0.0;
+static void schedule_format_change(void) {
+ do_format_change = 1;
+ do_cursor_change = 0;
+}
+extern double dnow(void);
+static void schedule_fb_update(void) {
+ do_fb_update = dnow();
+}
+static void init_format_change(void) {
+ appDataNew.useBGR233 = appData.useBGR233;
+ appDataNew.useBGR565 = appData.useBGR565;
+ appDataNew.useGreyScale = appData.useGreyScale;
+ appDataNew.enableJPEG = appData.enableJPEG;
+ appDataNew.encodingsString = appData.encodingsString;
+ appDataNew.useRemoteCursor = appData.useRemoteCursor;
+ appDataNew.useX11Cursor = appData.useX11Cursor;
+ appDataNew.useRawLocal = appData.useRawLocal;
+ appDataNew.qualityLevel = appData.qualityLevel;
+ appDataNew.compressLevel = appData.compressLevel;
+}
+void cutover_format_change(void) {
+ appData.useBGR233 = appDataNew.useBGR233;
+ appData.useBGR565 = appDataNew.useBGR565;
+ appData.useGreyScale = appDataNew.useGreyScale;
+ appData.enableJPEG = appDataNew.enableJPEG;
+ appData.encodingsString = appDataNew.encodingsString;
+ appData.useRemoteCursor = appDataNew.useRemoteCursor;
+ appData.useX11Cursor = appDataNew.useX11Cursor;
+ appData.useRawLocal = appDataNew.useRawLocal;
+ appData.qualityLevel = appDataNew.qualityLevel;
+ appData.compressLevel = appDataNew.compressLevel;
+}
+
+void
+Toggle8bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ fprintf(stderr, "Toggle8bpp: %d\n", appData.useBGR233);
+ b8 = w;
+ init_format_change();
+ if (appData.useBGR233) {
+ last_ncolors = appData.useBGR233;
+ appDataNew.useBGR233 = 0;
+ appDataNew.useBGR565 = save_useBGR565;
+ fprintf(stderr, "8bpp: off\n");
+ } else {
+ if (!last_ncolors) last_ncolors = 256;
+ appDataNew.useBGR233 = last_ncolors;
+ save_useBGR565 = appData.useBGR565;
+ appDataNew.useBGR565 = False;
+ fprintf(stderr, "8bpp: on (%d colors)\n", appDataNew.useBGR233);
+ }
+ schedule_format_change();
+}
+
+
+void
+Toggle16bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ fprintf(stderr, "Toggle16bpp: %d\n", appData.useBGR565);
+ b16 = w;
+ init_format_change();
+ if (appData.useBGR565) {
+ appDataNew.useBGR565 = False;
+ appDataNew.useBGR233 = save_useBGR233;
+ fprintf(stderr, "16bpp: off\n");
+ } else {
+ appDataNew.useBGR565 = True;
+ save_useBGR233 = appData.useBGR233;
+ appDataNew.useBGR233 = 0;
+ fprintf(stderr, "16bpp: on\n");
+ }
+ schedule_format_change();
+}
+
+void
+ToggleFullColor(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ fprintf(stderr, "ToggleFullColor\n");
+ bfull = w;
+ init_format_change();
+ if (appData.useBGR565 || appData.useBGR233) {
+ save_useBGR565 = appData.useBGR565;
+ appDataNew.useBGR565 = False;
+ save_useBGR233 = appData.useBGR233;
+ appDataNew.useBGR233 = 0;
+ fprintf(stderr, "FullColor: on\n");
+ } else {
+ if (save_useBGR565) {
+ appDataNew.useBGR565 = True;
+ appDataNew.useBGR233 = 0;
+ fprintf(stderr, "FullColor off -> 16bpp.\n");
+ } else {
+ appDataNew.useBGR565 = False;
+ if (!save_useBGR233) save_useBGR233 = 256;
+ appDataNew.useBGR233 = save_useBGR233;
+ fprintf(stderr, "FullColor off -> 8bpp.\n");
+ }
+ }
+ schedule_format_change();
+}
+
+void
+ToggleXGrab(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (getenv("SSVNC_DEBUG_GRAB")) {
+ fprintf(stderr, "ToggleXGrab, current=%d\n", appData.grabAll);
+ }
+ if (appData.grabAll) {
+ appData.grabAll = False;
+ } else {
+ appData.grabAll = True;
+ }
+ /* always ungrab to be sure, fullscreen will handle the rest */
+ XUngrabServer(dpy);
+}
+
+/*
+ * ToggleNColors
+ */
+
+static Widget w256 = NULL;
+static Widget w64 = NULL;
+static Widget w8 = NULL;
+
+void
+Toggle256Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ w256 = w;
+ if (appData.useBGR233 != 256) {
+ fprintf(stderr, "256 colors: on\n");
+ init_format_change();
+ last_ncolors = appDataNew.useBGR233 = 256;
+ save_useBGR565 = appData.useBGR565;
+ appDataNew.useBGR565 = False;
+ schedule_format_change();
+ }
+}
+
+void
+Toggle64Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ w64 = w;
+ if (appData.useBGR233 != 64) {
+ fprintf(stderr, "64 colors: on\n");
+ init_format_change();
+ last_ncolors = appDataNew.useBGR233 = 64;
+ save_useBGR565 = appData.useBGR565;
+ appDataNew.useBGR565 = False;
+ schedule_format_change();
+ }
+}
+
+void
+Toggle8Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ w8 = w;
+ if (appData.useBGR233 != 8) {
+ fprintf(stderr, "8 colors: on\n");
+ init_format_change();
+ last_ncolors = appDataNew.useBGR233 = 8;
+ save_useBGR565 = appData.useBGR565;
+ appDataNew.useBGR565 = False;
+ schedule_format_change();
+ }
+}
+
+void
+ToggleGreyScale(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ fprintf(stderr, "ToggleGreyScale\n");
+ init_format_change();
+ if (appData.useGreyScale) {
+ appDataNew.useGreyScale = False;
+ fprintf(stderr, "greyscale: off\n");
+ } else {
+ appDataNew.useGreyScale = True;
+ fprintf(stderr, "greyscale: on\n");
+ }
+ schedule_format_change();
+}
+
+/*
+ * ToggleJPEG
+ */
+
+void
+ToggleJPEG(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ init_format_change();
+ if (appData.enableJPEG) {
+ appDataNew.enableJPEG = False;
+ fprintf(stderr, "JPEG: off\n");
+ } else {
+ appDataNew.enableJPEG = True;
+ fprintf(stderr, "JPEG: on\n");
+ }
+ schedule_format_change();
+}
+
+/*
+ * ToggleTightZRLE
+ */
+
+static Bool usingZRLE = False;
+static Bool usingZYWRLE = False;
+extern int skip_maybe_sync;
+
+void
+ToggleTightZRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ char prefTight[] = "copyrect tight zrle zywrle zlib hextile corre rre raw";
+ char prefZRLE[] = "copyrect zrle zywrle tight zlib hextile corre rre raw";
+ init_format_change();
+ if (! appData.encodingsString) {
+ appDataNew.encodingsString = strdup(prefZRLE);
+ usingZRLE = True;
+ fprintf(stderr, "prefer: ZRLE\n");
+ } else {
+ char *t, *z;
+ static int first = 1;
+ t = strstr(appData.encodingsString, "tight");
+ z = strstr(appData.encodingsString, "zrle");
+ if (first && usingZRLE) {
+ appDataNew.encodingsString = strdup(prefTight);
+ usingZRLE = False;
+ usingZYWRLE = False;
+ } else if (! t) {
+ appDataNew.encodingsString = strdup(prefZRLE);
+ usingZRLE = True;
+ fprintf(stderr, "prefer: ZRLE\n");
+ } else if (! z) {
+ appDataNew.encodingsString = strdup(prefTight);
+ usingZRLE = False;
+ usingZYWRLE = False;
+ skip_maybe_sync = 0;
+ fprintf(stderr, "prefer: Tight\n");
+ } else {
+ if (t < z) {
+ appDataNew.encodingsString = strdup(prefZRLE);
+ usingZRLE = True;
+ fprintf(stderr, "prefer: ZRLE\n");
+ } else {
+ appDataNew.encodingsString = strdup(prefTight);
+ usingZRLE = False;
+ usingZYWRLE = False;
+ skip_maybe_sync = 0;
+ fprintf(stderr, "prefer: Tight\n");
+ }
+ }
+ first = 0;
+ }
+ schedule_format_change();
+}
+
+void
+ToggleZRLEZYWRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ char prefZYWRLE[] = "copyrect zywrle zrle tight zlib hextile corre rre raw";
+ char prefZRLE[] = "copyrect zrle zywrle tight zlib hextile corre rre raw";
+ init_format_change();
+ usingZRLE = True;
+ if (! appData.encodingsString) {
+ appDataNew.encodingsString = strdup(prefZYWRLE);
+ usingZYWRLE = True;
+ fprintf(stderr, "prefer: ZYWRLE\n");
+ } else {
+ char *z, *w;
+ w = strstr(appData.encodingsString, "zywrle");
+ z = strstr(appData.encodingsString, "zrle");
+ if (usingZYWRLE) {
+ appDataNew.encodingsString = strdup(prefZRLE);
+ fprintf(stderr, "prefer: ZRLE\n");
+ usingZYWRLE = False;
+ skip_maybe_sync = 0;
+ } else {
+ appDataNew.encodingsString = strdup(prefZYWRLE);
+ fprintf(stderr, "prefer: ZYWRLE\n");
+ usingZYWRLE = True;
+ }
+ }
+ schedule_format_change();
+}
+
+/*
+ * ToggleViewOnly
+ */
+
+void
+ToggleViewOnly(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.viewOnly) {
+ appData.viewOnly = False;
+ fprintf(stderr, "viewonly: off\n");
+ } else {
+ appData.viewOnly = True;
+ fprintf(stderr, "viewonly: on\n");
+ }
+ Xcursors(1);
+}
+
+void
+ToggleCursorShape(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ init_format_change();
+ if (appData.useRemoteCursor) {
+ appDataNew.useRemoteCursor = False;
+ fprintf(stderr, "useRemoteCursor: off\n");
+ } else {
+ appDataNew.useRemoteCursor = True;
+ fprintf(stderr, "useRemoteCursor: on\n");
+ }
+ schedule_format_change();
+ if (!appDataNew.useRemoteCursor) {
+ do_cursor_change = 1;
+ } else {
+ do_cursor_change = -1;
+ }
+}
+
+void
+ToggleCursorAlpha(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useCursorAlpha) {
+ appData.useCursorAlpha = False;
+ fprintf(stderr, "useCursorAlpha: off\n");
+ } else {
+ appData.useCursorAlpha = True;
+ fprintf(stderr, "useCursorAlpha: on\n");
+ }
+}
+
+void
+ToggleX11Cursor(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ init_format_change();
+ if (appData.useX11Cursor) {
+ appDataNew.useX11Cursor = False;
+ fprintf(stderr, "useX11Cursor: off\n");
+ } else {
+ appDataNew.useX11Cursor = True;
+ fprintf(stderr, "useX11Cursor: on\n");
+ }
+ schedule_format_change();
+ do_cursor_change = 1;
+}
+
+void
+ToggleBell(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useBell) {
+ appData.useBell = False;
+ fprintf(stderr, "useBell: off\n");
+ } else {
+ appData.useBell = True;
+ fprintf(stderr, "useBell: on\n");
+ }
+}
+
+void
+ToggleRawLocal(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ init_format_change();
+ if (appData.useRawLocal) {
+ appDataNew.useRawLocal = False;
+ fprintf(stderr, "useRawLocal: off\n");
+ } else {
+ appDataNew.useRawLocal = True;
+ fprintf(stderr, "useRawLocal: on\n");
+ }
+ schedule_format_change();
+}
+
+void
+ToggleServerInput(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.serverInput) {
+ appData.serverInput= False;
+ fprintf(stderr, "serverInput: off\n");
+ SendServerInput(True);
+ } else {
+ appData.serverInput = True;
+ fprintf(stderr, "serverInput: on\n");
+ SendServerInput(False);
+ }
+}
+
+Bool _sw1_ = False; /* XXX this is a weird bug... */
+Bool _sw2_ = False;
+Bool _sw3_ = False;
+Bool selectingSingleWindow = False;
+
+extern Cursor bogoCursor;
+
+void
+ToggleSingleWindow(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.singleWindow) {
+ appData.singleWindow= False;
+ fprintf(stderr, "singleWindow: off\n");
+ SendSingleWindow(-1, -1);
+ } else {
+ appData.singleWindow = True;
+ selectingSingleWindow = True;
+ fprintf(stderr, "singleWindow: on\n");
+ if (bogoCursor != None) {
+ XDefineCursor(dpy, desktopWin, bogoCursor);
+ }
+ }
+}
+
+void raiseme(int force);
+void AppendChatInput(char *);
+
+void printChat(char *str, Bool raise) {
+ if (appData.termChat) {
+ if (raise) {
+ raiseme(0);
+ }
+ fprintf(stderr, str);
+ } else {
+ if (raise) {
+ ShowChat();
+ }
+ AppendChatInput(str);
+ }
+}
+
+void
+ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.chatActive) {
+ printChat("\n*SentClose*\n\n", False);
+ SendTextChatClose();
+ SendTextChatFinished();
+ HideChat(0, NULL, NULL, NULL);
+ appData.chatActive= False;
+ } else {
+ ShowChat();
+ SendTextChatOpen();
+ if (appData.termChat) {
+ printChat("\n*SentOpen*\n\nSend: ", True);
+ } else {
+ printChat("\n*SentOpen*\n", True);
+ }
+ appData.chatActive = True;
+ }
+}
+
+extern int filexfer_sock;
+extern pid_t java_helper;
+#define KILLJAVA
+#ifdef KILLJAVA
+#include <signal.h>
+#endif
+
+void
+ToggleFileXfer(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.fileActive) {
+ //HideFile(w, ev, params, num_params);
+ //appData.fileActive = False;
+#ifndef KILLJAVA
+ if (filexfer_sock >= 0) {
+ close(filexfer_sock);
+ }
+#else
+ if (java_helper != 0) {
+ int i;
+ for (i=1; i<=5; i++) {
+ pid_t p = java_helper + i;
+ fprintf(stderr, "trying to kill java helper: %d\n", p);
+ if (kill(p, SIGTERM) == 0) {
+ java_helper = 0;
+ break;
+ }
+ }
+ }
+#endif
+ } else {
+ ShowFile(w, ev, params, num_params);
+ appData.fileActive = True;
+ }
+}
+
+static int fooHandler(Display *dpy, XErrorEvent *error) {
+ return 0;
+}
+
+void raiseme(int force) {
+ if ((force || appData.termChat) && getenv("WINDOWID")) {
+ unsigned long w;
+ if (sscanf(getenv("WINDOWID"), "%lu", &w) == 1) {
+ ;
+ } else if (sscanf(getenv("WINDOWID"), "0x%lx", &w) == 1) {
+ ;
+ } else {
+ w = 0;
+ }
+ if (w != 0) {
+ XErrorHandler old = XSetErrorHandler(fooHandler);
+ XMapRaised(dpy, (Window) w);
+ XSync(dpy, False);
+ XSetErrorHandler(old);
+ }
+ }
+}
+
+void set_server_scale(int n) {
+ if (n >= 1 && n < 100) {
+ int w = si.framebufferWidth;
+ int h = si.framebufferHeight;
+ appData.serverScale = n;
+ SendServerScale(n);
+ if (0) SendFramebufferUpdateRequest(0, 0, w, h, False);
+ schedule_fb_update();
+ }
+}
+
+void
+DoServerScale(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ char str[100], *s, *q;
+ int n;
+ if (1) {
+ s = 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);
+ }
+}
+
+void set_server_quality(int n) {
+ fprintf(stderr, "set_quality: %d\n", n);
+ if (n >= 0 && n <= 9) {
+ int w = si.framebufferWidth;
+ int h = si.framebufferHeight;
+ init_format_change();
+ appDataNew.qualityLevel = n;
+ SendFramebufferUpdateRequest(0, 0, w, h, False);
+ schedule_format_change();
+ }
+}
+
+void
+DoServerQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ char str[100], *s, *q;
+ int n;
+ if (1) {
+ s = DoQualityDialog();
+ } else {
+ raiseme(1);
+ fprintf(stderr, "\n\n\a\nEnter integer 1 <= n <= 9 for quality setting: ");
+ str[0] = '\0';
+ fgets(str, 100, stdin);
+ s = str;
+ q = strstr(str, "\n");
+ if (q) *q = '\0';
+ }
+ if (s[0] != '\0') {
+ n = atoi(s);
+ set_server_quality(n);
+ }
+}
+
+void set_server_compress(int n) {
+ fprintf(stderr, "set_compress: %d\n", n);
+ if (n >= 0 && n <= 9) {
+ int w = si.framebufferWidth;
+ int h = si.framebufferHeight;
+ init_format_change();
+ appDataNew.compressLevel = n;
+ SendFramebufferUpdateRequest(0, 0, w, h, False);
+ schedule_format_change();
+ }
+}
+
+void
+DoServerCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ char str[100], *s, *q;
+ int n;
+ if (1) {
+ s = DoCompressDialog();
+ } else {
+ raiseme(1);
+ fprintf(stderr, "\n\n\a\nEnter integer 1 <= n <= 9 for compress level setting: ");
+ str[0] = '\0';
+ fgets(str, 100, stdin);
+ s = str;
+ q = strstr(str, "\n");
+ if (q) *q = '\0';
+ }
+ if (s[0] != '\0') {
+ n = atoi(s);
+ set_server_compress(n);
+ }
+}
+
+extern void rescale_image(void);
+
+void
+SetScale(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ char *s;
+ s = DoScaleDialog();
+ if (s[0] != '\0') {
+ int w = si.framebufferWidth;
+ int h = si.framebufferHeight;
+ 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.fullScreen) {
+ fs = 1;
+ FullScreenOff();
+ }
+ rescale_image();
+ if (fs) {
+ FullScreenOn();
+ }
+ }
+}
+
+
+void set_ycrop(int n) {
+ if (n >= 1) {
+ int w = si.framebufferWidth;
+ int h = si.framebufferHeight;
+ appData.yCrop = n;
+ ReDoDesktop();
+ SendFramebufferUpdateRequest(0, 0, w, h, False);
+ schedule_fb_update();
+ }
+}
+
+void
+SetYCrop(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ char str[100], *q, *s;
+ int n;
+ if (1) {
+ s = DoYCropDialog();
+ } else {
+ raiseme(1);
+ fprintf(stderr, "\n\n\a\nEnter pixel size n -ycrop maximum y-height: ");
+ str[0] = '\0';
+ fgets(str, 100, stdin);
+ s = str;
+ q = strstr(str, "\n");
+ if (q) *q = '\0';
+ }
+ if (s[0] != '\0') {
+ n = atoi(s);
+ set_ycrop(n);
+ }
+}
+
+void set_scbar(int n) {
+ if (n >= 1) {
+ int w = si.framebufferWidth;
+ int h = si.framebufferHeight;
+fprintf(stderr, "set_scbat: %d\n", n);
+ appData.sbWidth = n;
+ ReDoDesktop();
+ SendFramebufferUpdateRequest(0, 0, w, h, False);
+ schedule_fb_update();
+ }
+}
+
+void
+SetScbar(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ char str[100], *q, *s;
+ int n;
+ if (1) {
+ s = DoScbarDialog();
+ } else {
+ raiseme(1);
+ fprintf(stderr, "\n\n\a\nEnter pixel size n scrollbar width: ");
+ str[0] = '\0';
+ fgets(str, 100, stdin);
+ s = str;
+ q = strstr(str, "\n");
+ if (q) *q = '\0';
+ }
+ if (s[0] != '\0') {
+ n = atoi(s);
+ set_scbar(n);
+ }
+}
+
+void
+SetScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (*num_params != 0) {
+ int n = atoi(params[0]);
+ set_server_scale(n);
+ }
+}
+
+void
+SetQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (*num_params != 0) {
+ int n = atoi(params[0]);
+ set_server_quality(n);
+ }
+}
+
+void
+SetCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (*num_params != 0) {
+ int n = atoi(params[0]);
+ set_server_compress(n);
+ }
+}
- Cleanup();
+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);
+ }
+ }
+}
- return 0;
+void
+SetViewOnlyState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.viewOnly) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetNOJPEGState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.enableJPEG) {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ }
+}
+
+void
+SetQualityState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (*num_params != 0) {
+ int n = atoi(params[0]);
+ if (appData.qualityLevel == n) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+ }
+}
+
+void
+SetCompressState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (*num_params != 0) {
+ int n = atoi(params[0]);
+ if (appData.compressLevel == n) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+ }
+}
+
+void
+SetScaleNState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (*num_params != 0) {
+ int n = atoi(params[0]);
+ if (appData.serverScale == n || (appData.serverScale >= 6 && n >= 6)) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+ }
+}
+
+void
+Set8bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useBGR233) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ if (b16 != NULL) {
+ XtVaSetValues(b16, XtNstate, False, NULL);
+ }
+ if (bfull != NULL) {
+ XtVaSetValues(bfull, XtNstate, False, NULL);
+ }
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+Set16bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useBGR565) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ if (b8 != NULL) {
+ XtVaSetValues(b8, XtNstate, False, NULL);
+ }
+ if (bfull != NULL) {
+ XtVaSetValues(bfull, XtNstate, False, NULL);
+ }
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetFullColorState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useBGR565 || appData.useBGR233) {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ if (b8 != NULL) {
+ XtVaSetValues(b8, XtNstate, False, NULL);
+ }
+ if (b16 != NULL) {
+ XtVaSetValues(b16, XtNstate, False, NULL);
+ }
+ }
+}
+
+void
+SetXGrabState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.grabAll) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+Set256ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useBGR233 == 256) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ if (w64 != NULL) {
+ XtVaSetValues(w64 , XtNstate, False, NULL);
+ }
+ if (w8 != NULL) {
+ XtVaSetValues(w8 , XtNstate, False, NULL);
+ }
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+Set64ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useBGR233 == 64) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ if (w256 != NULL) {
+ XtVaSetValues(w256, XtNstate, False, NULL);
+ }
+ if (w8 != NULL) {
+ XtVaSetValues(w8 , XtNstate, False, NULL);
+ }
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+Set8ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useBGR233 == 8) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ if (w256 != NULL) {
+ XtVaSetValues(w256, XtNstate, False, NULL);
+ }
+ if (w64 != NULL) {
+ XtVaSetValues(w64 , XtNstate, False, NULL);
+ }
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetGreyScaleState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useGreyScale) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetZRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ static int first = 1;
+ if (first && appData.encodingsString) {
+ char *t, *z, *w;
+ t = strstr(appData.encodingsString, "tight");
+ z = strstr(appData.encodingsString, "zrle");
+ w = strstr(appData.encodingsString, "zywrle");
+ if (t) {
+ if (z) {
+ if (w) {
+ if (t < z && t < w) {
+ usingZRLE = False;
+ } else {
+ usingZRLE = True;
+ }
+ if (z < w) {
+ usingZYWRLE = False;
+ } else {
+ usingZYWRLE = True;
+ }
+ } else {
+ if (t < z) {
+ usingZRLE = False;
+ } else {
+ usingZRLE = True;
+ }
+ usingZYWRLE = False;
+ }
+ } else {
+ if (w) {
+ if (t < w) {
+ usingZRLE = False;
+ } else {
+ usingZRLE = True;
+ }
+ usingZYWRLE = True;
+ } else {
+ usingZRLE = False;
+ usingZYWRLE = False;
+ }
+ }
+ } else {
+ if (z) {
+ if (w) {
+ usingZRLE = True;
+ if (z < w) {
+ usingZYWRLE = False;
+ } else {
+ usingZYWRLE = True;
+ }
+ } else {
+ usingZRLE = True;
+ usingZYWRLE = False;
+ }
+ } else {
+ if (w) {
+ usingZRLE = True;
+ usingZYWRLE = True;
+ } else {
+ usingZRLE = False;
+ usingZYWRLE = False;
+ }
+ }
+ }
+ }
+ first = 0;
+
+ if (usingZRLE) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetZYWRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (usingZYWRLE) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetCursorShapeState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useRemoteCursor) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetCursorAlphaState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useCursorAlpha) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetX11CursorState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useX11Cursor) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetBellState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useBell) {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ }
+}
+
+void
+SetRawLocalState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.useRawLocal) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetServerInputState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (!appData.serverInput) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.singleWindow) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.chatActive) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
+}
+
+void
+SetFileXferState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
+{
+ if (appData.fileActive) {
+ XtVaSetValues(w, XtNstate, True, NULL);
+ } else {
+ XtVaSetValues(w, XtNstate, False, NULL);
+ }
}
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncviewer/vncviewer.h
--- vnc_unixsrc.orig/vncviewer/vncviewer.h 2004-03-11 13:14:40.000000000 -0500
+++ vnc_unixsrc/vncviewer/vncviewer.h 2008-10-17 20:31:48.000000000 -0400
@@ -51,7 +51,7 @@
(((l) & 0x0000ff00) << 8) | \
(((l) & 0x000000ff) << 24)) : (l))
-#define MAX_ENCODINGS 20
+#define MAX_ENCODINGS 24
#define FLASH_PORT_OFFSET 5400
#define LISTEN_PORT_OFFSET 5500
@@ -65,59 +65,93 @@
(DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20")
-/* 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;
+/* for debugging width, height, etc */
+//#define XtVaSetValues printf("%s:%d\n", __FILE__, __LINE__); XtVaSetValues
- 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 *repeaterUltra;
+ Bool ultraDSM;
+ char *rfbVersion;
+
+ char *passwordFile;
+ Bool passwordDialog;
+
+ int rawDelay;
+ int copyRectDelay;
+
+ int yCrop;
+ int sbWidth;
+ Bool useCursorAlpha;
+ Bool useRawLocal;
+
+ Bool debug;
+
+ int popupButtonCount;
+ int popupButtonBreak;
+
+ int bumpScrollTime;
+ int bumpScrollPixels;
+
+ int compressLevel;
+ int qualityLevel;
+ Bool enableJPEG;
+ Bool useRemoteCursor;
+ Bool useX11Cursor;
+ Bool useBell;
+ Bool autoPass;
+
+ Bool serverInput;
+ Bool singleWindow;
+ int serverScale;
+ Bool chatActive;
+ Bool chatOnly;
+ Bool fileActive;
- int compressLevel;
- int qualityLevel;
- Bool enableJPEG;
- Bool useRemoteCursor;
- Bool useX11Cursor;
- Bool autoPass;
+ char *scale;
} 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 +164,11 @@
/* colour.c */
extern unsigned long BGR233ToPixel[];
+extern unsigned long BGR565ToPixel[];
extern Colormap cmap;
extern Visual *vis;
-extern unsigned int visdepth, visbpp;
+extern unsigned int visdepth, visbpp, isLSB;
extern void SetVisualAndCmap();
@@ -157,13 +192,48 @@
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 void ScaleDialogDone(Widget w, XEvent *event, String *params,
+ Cardinal *num_params);
+extern char *DoScaleDialog();
+
+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();
@@ -181,6 +251,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 +273,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 +286,20 @@
Cardinal *num_params);
extern void CreatePopup();
+extern void HideScaleN(Widget w, XEvent *event, String *params,
+ Cardinal *num_params);
+extern void CreateScaleN();
+
+extern void HideQuality(Widget w, XEvent *event, String *params,
+ Cardinal *num_params);
+extern void CreateQuality();
+
+extern void HideCompress(Widget w, XEvent *event, String *params,
+ Cardinal *num_params);
+extern void CreateCompress();
+
+extern void Noop(Widget w, XEvent *event, String *params,
+ Cardinal *num_params);
/* rfbproto.c */
extern int rfbsock;
@@ -229,8 +322,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 +345,9 @@
/* shm.c */
-extern XImage *CreateShmImage();
+extern XImage *CreateShmImage(int do_ycrop);
extern void ShmCleanup();
+extern Bool UsingShm();
/* sockets.c */
@@ -253,8 +358,11 @@
extern int FindFreeTcpPort(void);
extern int ListenAtTcpPort(int port);
extern int ConnectToTcpAddr(unsigned int host, int port);
+extern int ConnectToUnixSocket(char *file);
extern int AcceptTcpConnection(int listenSock);
extern Bool SetNonBlocking(int sock);
+extern Bool SetNoDelay(int sock);
+extern Bool SocketPair(int fd[2]);
extern int StringToIPAddr(const char *str, unsigned int *addr);
extern Bool SameMachine(int sock);
@@ -271,3 +379,66 @@
extern XtAppContext appContext;
extern Display* dpy;
extern Widget toplevel;
+
+extern void GotChatText(char *str, int len);
+
+extern void Toggle8bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Toggle16bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleFullColor(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Toggle256Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Toggle64Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Toggle8Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleGreyScale(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleTightZRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleZRLEZYWRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleViewOnly(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleJPEG(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleCursorShape(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleCursorAlpha(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleX11Cursor(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleBell(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleRawLocal(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleServerInput(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleSingleWindow(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleXGrab(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 ShowQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ShowCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleFileXfer(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void ToggleTermTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+
+extern void SetViewOnlyState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetNOJPEGState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetScaleNState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetQualityState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetCompressState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Set8bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Set16bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetFullColorState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Set256ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Set64ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void Set8ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetGreyScaleState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetZRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetZYWRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetCursorShapeState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetCursorAlphaState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetX11CursorState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetBellState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetRawLocalState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetServerInputState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetTermTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetFileXferState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
+extern void SetXGrabState(Widget w, XEvent *ev, String *params, Cardinal *num_params);
diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vncviewer/vncviewer.man
--- vnc_unixsrc.orig/vncviewer/vncviewer.man 2004-03-11 13:14:40.000000000 -0500
+++ vnc_unixsrc/vncviewer/vncviewer.man 2008-10-17 22:04:57.000000000 -0400
@@ -5,38 +5,51 @@
.\" Copyright (C) 1998 Marcus.Brinkmann@ruhr-uni-bochum.de
.\" Copyright (C) 2000,2001 Red Hat, Inc.
.\" Copyright (C) 2001-2003 Constantin Kaplinsky <const@ce.cctpu.edu.ru>
+.\" Copyright (C) 2006-2008 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 "October 2008" "" "SSVNC"
.SH NAME
-vncviewer \- an X viewer client for VNC
+ssvncviewer \- an X viewer client for VNC
.SH SYNOPSIS
-.B vncviewer
+.B ssvncviewer
.RI [\| options \|]
.RI [\| host \|][\| :display \|]
.br
-.B vncviewer
+.B ssvncviewer
.RI [\| options \|]
.RI [\| host \|][\| ::port \|]
.br
-.B vncviewer
+.B ssvncviewer
+.RI [\| options \|]
+.RI exec=[\| cmd+args... \|]
+.br
+.B ssvncviewer
+.RI [\| options \|]
+.RI /path/to/unix/socket
+.br
+.B ssvncviewer
.RI [\| options \|]
.IR \-listen
.RI [\| display \|]
.br
-.B vncviewer
+.B ssvncviewer
.IR \-help
.br
.SH DESCRIPTION
-.B vncviewer
+.B ssvncviewer
is an Xt\-based client application for the VNC (Virtual Network
Computing) system. It can connect to any VNC\-compatible server such
-as \fBXvnc\fR or WinVNC, allowing you to control desktop environment
+as \fBXvnc\fR, WinVNC, or \fBx11vnc\fR, allowing you to control desktop environment
of a different machine.
+ssvncviewer is an enhanced version of the tightvnc unix viewer that can
+take advantage of features in the \fBx11vnc\fR and UltraVNC VNC servers.
+See below for the description of these features.
+
You can use F8 to display a pop\-up utility menu. Press F8 twice to
pass single F8 to the remote side.
.SH OPTIONS
@@ -168,6 +181,244 @@
\fB\-autopass\fR
Read a plain-text password from stdin. This option affects only the
standard VNC authentication.
+
+.SH Enhanced TightVNC Viewer (SSVNC) OPTIONS
+.TP
+Enhanced TightVNC Viewer (SSVNC) web page is located at:
+.TP
+http://www.karlrunge.com/x11vnc/ssvnc.html
+.TP
+Note: ZRLE and ZYWRLE encodings are now supported.
+.TP
+Note: F9 is shortcut to Toggle FullScreen mode.
+.TP
+Note: In -listen mode set the env var. SSVNC_MULTIPLE_LISTEN=1
+to allow more than one incoming VNC server at a time.
+This is the same as -multilisten described below. Set
+SSVNC_MULTIPLE_LISTEN=MAX:n to allow no more than "n"
+simultaneous reverse connections.
+.TP
+Note: If the host:port is specified as "exec=command args..."
+then instead of making a TCP/IP socket connection to the
+remote VNC server, "command args..." is executed and the
+viewer is attached to its stdio. This enables tunnelling
+established via an external command, e.g. an stunnel(8)
+that does not involve a listening socket.
+This mode does not work for -listen reverse connections.
+.TP
+Note: If the host:port contains a '/' it is interpreted as a
+unix-domain socket (AF_LOCAL insead of AF_INET)
+.TP
+\fB\-multilisten\fR
+As in -listen (reverse connection listening) except
+allow more than one incoming VNC server to be connected
+at a time. The default for -listen of only one at a
+time tries to play it safe by not allowing anyone on
+the network to put (many) desktops on your screen over
+a long window of time. Use -multilisten for no limit.
+.TP
+\fB\-use64\fR
+In \fB\-bgr233\fR mode, use 64 colors instead of 256.
+.TP
+\fB\-bgr222\fR
+Same as \fB\-use64\fR.
+.TP
+\fB\-use8\fR
+In \fB\-bgr233\fR mode, use 8 colors instead of 256.
+.TP
+\fB\-bgr111\fR
+Same as \fB\-use8\fR.
+.TP
+\fB\-16bpp\fR
+If the vnc viewer X display is depth 24 at 32bpp
+request a 16bpp format from the VNC server to cut
+network traffic by up to 2X, then tranlate the
+pixels to 32bpp locally.
+.TP
+\fB\-bgr565\fR
+Same as \fB\-16bpp\fR.
+.TP
+\fB\-grey\fR
+Use a grey scale for the 16- and 8\fB\-bpp\fR modes.
+.TP
+\fB\-alpha\fR
+Use alphablending transparency for local cursors
+requires: x11vnc server, both client and server
+must be 32bpp and same endianness.
+.TP
+\fB\-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.
+Note that scaling is done in software and can be slow
+and requires more memory. "str" can also be set by
+the env. var. SSVNC_SCALE.
+.TP
+\fB\-ycrop\fR n
+Only show the top n rows of the framebuffer. For
+use with x11vnc \fB\-ncache\fR client caching option
+to help "hide" the pixel cache region.
+Use a negative value (e.g. \fB\-1\fR) for autodetection.
+Autodetection will always take place if the remote
+fb height is more than 2 times the width.
+.TP
+\fB\-sbwidth\fR n
+Scrollbar width for x11vnc \fB\-ncache\fR mode (\fB\-ycrop\fR),
+default is very narrow: 2 pixels, it is narrow to
+avoid distraction in \fB\-ycrop\fR mode.
+.TP
+\fB\-nobell\fR
+Disable bell.
+.TP
+\fB\-rawlocal\fR
+Prefer raw encoding for localhost, default is
+no, i.e. assumes you have a SSH tunnel instead.
+.TP
+\fB\-graball\fR
+Grab the entire X server when in fullscreen mode,
+needed by some old window managers like fvwm2.
+.TP
+\fB\-popupfix\fR
+Warp the popup back to the pointer position,
+needed by some old window managers like fvwm2.
+.TP
+\fB\-grabkbd\fR
+Grab the X keyboard when in fullscreen mode,
+needed by some window managers. Same as \fB\-grabkeyboard\fR.
+\fB\-grabkbd\fR is the default, use \fB\-nograbkbd\fR to disable.
+.TP
+\fB\-bs\fR, \fB\-nobs\fR
+Whether or not to use X server Backingstore for the
+main viewer window. The default is to not, mainly
+because most Linux, etc, systems X servers disable
+*all* Backingstore by default. To re\fB\-enable\fR it put
+Option "Backingstore"
+in the Device section of /etc/X11/xorg.conf.
+In \fB\-bs\fR mode with no X server backingstore, whenever an
+area of the screen is re\fB\-exposed\fR it must go out to the
+VNC server to retrieve the pixels. This is too slow.
+In \fB\-nobs\fR mode, memory is allocated by the viewer to
+provide its own backing of the main viewer window. This
+actually makes some activities faster (changes in large
+regions) but can appear to "flash" too much.
+.TP
+\fB\-noshm\fR
+Disable use of MIT shared memory extension (not recommended)
+.TP
+\fB\-termchat\fR
+Do the UltraVNC chat in the terminal vncviewer is in
+instead of in an independent window.
+.TP
+\fB\-unixpw\fR \fIstr\fR
+Useful for logging into x11vnc in \fB\-unixpw\fR mode. "str" is a
+string that allows many ways to enter the Unix Username
+and Unix Password. These characters: username, newline,
+password, newline are sent to the VNC server after any VNC
+authentication has taken place. Under x11vnc they are
+used for the \fB\-unixpw\fR login. Other VNC servers could do
+something similar.
+You can also indicate "str" via the environment
+variable SSVNC_UNIXPW.
+Note that the Escape key is actually sent first to tell
+x11vnc to not echo the Unix Username back to the VNC
+viewer. Set SSVNC_UNIXPW_NOESC=1 to override this.
+If str is ".", then you are prompted at the command line
+for the username and password in the normal way. If str is
+"-" the stdin is read via getpass(3) for username@password.
+Otherwise if str is a file, it is opened and the first line
+read is taken as the Unix username and the 2nd as the
+password. If str prefixed by "rm:" the file is removed
+after reading. Otherwise, if str has a "@" character,
+it is taken as username@password. Otherwise, the program
+exits with an error. Got all that?
+.TP
+\fB-repeater\fR \fIstr\fR
+This is for use with UltraVNC repeater proxy described
+here: http://www.uvnc.com/addons/repeater.html. The "str"
+is the ID string to be sent to the repeater. E.g. ID:1234
+It can also be the hostname and port or display of the VNC
+server, e.g. 12.34.56.78:0 or snoopy.com:1. Note that when
+using -repeater, the host:dpy on the cmdline is the repeater
+server, NOT the VNC server. The repeater will connect you.
+
+Example: vncviewer ... -repeater ID:3333 repeat.host:5900
+
+Example: vncviewer ... -repeater vhost:0 repeat.host:5900
+
+Use, e.g., '-repeater SCIII=ID:3210' if the repeater is a
+Single Click III (SSL) repeater (repeater_SSL.exe) and you
+are passing the SSL part of the connection through stunnel, socat, etc.
+This way the magic UltraVNC string 'testB' needed to work with the
+repeater is sent to it.
+.TP
+\fB-rfbversion\fR \fIstr\fR
+Set the advertised RFB version. E.g.: -rfbversion 3.6 For some
+servers, e.g. UltraVNC this needs to be done.
+.TP
+\fB-ultradsm\fR
+UltraVNC has symmetric private encryption DSM plugins. See
+http://www.uvnc.com/features/encryption.html. It is assumed
+you are using a unix program (e.g. our ultravnc_dsm_helper) to
+encrypt and decrypt the UltraVNC DSM stream. IN ADDITION TO
+THAT supply -ultradsm to tell THIS viewer to modify the RFB
+data sent so as to work with the UltraVNC Server. For some
+reason, each RFB msg type must be sent twice under DSM.
+.TP
+\fB\-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\-printres\fR
+Print out the Ssvnc X resources (appdefaults) and
+then exit. You can save them to a file and customize them (e.g. the
+keybindings and Popup menu) Then point to the file via
+XENVIRONMENT or XAPPLRESDIR.
+.TP
+\fB New Popup actions:\fR
+
+ ViewOnly: ~ -viewonly
+ Disable Bell: ~ -nobell
+ Cursor Shape: ~ -nocursorshape
+ X11 Cursor: ~ -x11cursor
+ Cursor Alphablend: ~ -alpha
+ Toggle Tight/ZRLE: ~ -encodings ...
+ Toggle ZRLE/ZYWRLE: ~ -encodings zywrle...
+ Quality Level ~ -quality (both Tight and ZYWRLE)
+ Compress Level ~ -compresslevel
+ Disable JPEG: ~ -nojpeg (Tight)
+ Full Color ~ as many colors as local screen allows.
+ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes.
+ 16 bit color (BGR565) ~ -16bpp / -bgr565
+ 8 bit color (BGR233) ~ -bgr233
+ 256 colors ~ -bgr233 default # of colors.
+ 64 colors ~ -bgr222 / -use64
+ 8 colors ~ -bgr111 / -use8
+ Scale Viewer ~ -scale
+ 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 a single window.
+ (click on the window you want).
+ Disable Remote Input Ultravnc ext. Try to prevent input and
+ viewing of monitor at physical display.
+
+ Note: the Ultravnc extensions only apply to servers that
+ support them. x11vnc/libvncserver supports some of them.
+
.SH ENCODINGS
The server supplies information in whatever format is desired by the
client, in order to make the client as easy as possible to implement.
@@ -238,6 +489,15 @@
\-quality and \-nojpeg options above). Tight encoding is usually the
best choice for low\-bandwidth network environments (e.g. slow modem
connections).
+.TP
+.B ZRLE
+The SSVNC viewer has ported the RealVNC (www.realvnc.com) ZRLE encoding
+to the unix tightvnc viewer.
+.TP
+.B ZYWRLE
+The SSVNC viewer has ported the Hitachi lossy wavelet based ZRLE
+encoding from http://mobile.hitachi-system.co.jp/publications/ZYWRLE/
+to the unix tightvnc viewer.
.SH RESOURCES
X resources that \fBvncviewer\fR knows about, aside from the
normal Xt resources, are as follows:
@@ -364,8 +624,8 @@
.B %R
remote TCP port number.
.SH SEE ALSO
-\fBvncserver\fR(1), \fBXvnc\fR(1), \fBvncpasswd\fR(1),
-\fBvncconnect\fR(1), \fBssh\fR(1)
+\fBvncserver\fR(1), \fBx11vnc\fR(1), \fBssvnc\fR(1), \fBXvnc\fR(1), \fBvncpasswd\fR(1),
+\fBvncconnect\fR(1), \fBssh\fR(1), http://www.karlrunge.com/x11vnc, http://www.karlrunge.com/x11vnc/ssvnc.html
.SH AUTHORS
Original VNC was developed in AT&T Laboratories Cambridge. TightVNC
additions was implemented by Constantin Kaplinsky. Many other people
@@ -380,3 +640,5 @@
Tim Waugh <twaugh@redhat.com>,
.br
Constantin Kaplinsky <const@ce.cctpu.edu.ru>
+.br
+Karl 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 2008-10-08 00:04:43.000000000 -0400
@@ -0,0 +1,618 @@
+/*
+ * 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;
+ 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;
+ 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 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 2008-09-05 17:01:18.000000000 -0400
@@ -381,6 +381,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 +408,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 +452,11 @@
#define rfbEncodingTight 7
#define rfbEncodingZlibHex 8
+#define rfbEncodingZRLE 16
+// nyama/2006/08/02:new YUV-Wavlet lossy codec based on ZRLE (ZYWRLE)
+#define rfbEncodingZYWRLE 17
+
+
/* signatures for basic encoding types */
#define sig_rfbEncodingRaw "RAW_____"
#define sig_rfbEncodingCopyRect "COPYRECT"
@@ -955,6 +977,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 +1035,8 @@
rfbFileDownloadDataMsg fdd;
rfbFileUploadCancelMsg fuc;
rfbFileDownloadFailedMsg fdf;
+ rfbRestartConnectionMsg rc;
+ rfbTextChatMsg tc;
} rfbServerToClientMsg;
@@ -1221,6 +1290,41 @@
#define sz_rfbFileCreateDirRequestMsg 4
+/* ultra */
+typedef struct _rfbSetScaleMsg {
+ CARD8 type; /* always rfbSetScale */
+ CARD8 scale; /* Scale value 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 +1345,9 @@
rfbFileDownloadCancelMsg fdc;
rfbFileUploadFailedMsg fuf;
rfbFileCreateDirRequestMsg fcdr;
+ rfbSetScaleMsg ssc;
+ rfbPalmVNCSetScaleFactorMsg pssf;
+ rfbSetServerInputMsg sim;
+ rfbSetSWMsg sw;
+ rfbTextChatMsg tc;
} rfbClientToServerMsg;