1 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/Vncviewer vnc_unixsrc/vncviewer/Vncviewer 2 --- vnc_unixsrc.orig/vncviewer/Vncviewer 2003-02-07 05:30:57.000000000 -0500 3 +++ vnc_unixsrc/vncviewer/Vncviewer 2008-08-24 16:26:01.000000000 -0400 4 @@ -1,20 +1,22 @@ 5 ! 6 -! Application defaults file for vncviewer. 7 +! Application defaults file for SSVNC vncviewer. 8 +! 9 +! N.B.: You will need to rename this file to be "Ssvnc" instead of "Vncviewer" 10 ! 11 12 13 ! 14 ! The title of the main window. "%s" will be replaced by the desktop name. 15 -! 16 +! 17 18 -Vncviewer.title: TightVNC: %s 19 +Ssvnc.title: SSVNC: %s Press F8 for Menu 20 21 22 ! 23 ! Translations on the main window. 24 ! 25 26 -Vncviewer.translations:\ 27 +Ssvnc.translations:\ 28 <Enter>: SelectionToVNC()\n\ 29 <Leave>: SelectionFromVNC() 30 31 @@ -23,7 +25,7 @@ 32 ! Uncomment to grab the keyboard in full-screen mode. 33 ! 34 35 -! Vncviewer.grabKeyboard: True 36 +! Ssvnc.grabKeyboard: True 37 38 39 ! 40 @@ -43,6 +45,9 @@ 41 *viewport.useRight: True 42 *viewport*Scrollbar*thumb: None 43 44 +*viewport.horizontal.height: 6 45 +*viewport.vertical.width: 6 46 + 47 48 ! 49 ! Default translations on desktop window. 50 @@ -50,89 +55,591 @@ 51 52 *desktop.baseTranslations:\ 53 <Key>F8: ShowPopup()\n\ 54 + <Key>F9: ToggleFullScreen()\n\ 55 <ButtonPress>: SendRFBEvent()\n\ 56 <ButtonRelease>: SendRFBEvent()\n\ 57 <Motion>: SendRFBEvent()\n\ 58 <KeyPress>: SendRFBEvent()\n\ 59 <KeyRelease>: SendRFBEvent() 60 61 +*viewport.horizontal.translations: #override\n\ 62 + <KeyPress>Right: StartScroll(Forward)\n\ 63 + <KeyRelease>Right: NotifyScroll(FullLength) EndScroll()\n\ 64 + <KeyPress>Left: StartScroll(Backward)\n\ 65 + <KeyRelease>Left: NotifyScroll(FullLength) EndScroll()\n\ 66 + <KeyPress>Next: StartScroll(Forward)\n\ 67 + <KeyRelease>Next: NotifyScroll(FullLength) EndScroll()\n\ 68 + <KeyPress>Prior: StartScroll(Backward)\n\ 69 + <KeyRelease>Prior: NotifyScroll(FullLength) EndScroll()\n\ 70 + <KeyPress>z: StartScroll(Forward)\n\ 71 + <KeyRelease>z: NotifyScroll(FullLength) EndScroll()\n\ 72 + <KeyPress>a: StartScroll(Backward)\n\ 73 + <KeyRelease>a: NotifyScroll(FullLength) EndScroll()\n\ 74 + <KeyPress>f: StartScroll(Forward)\n\ 75 + <KeyRelease>f: NotifyScroll(FullLength) EndScroll()\n\ 76 + <KeyPress>b: StartScroll(Backward)\n\ 77 + <KeyRelease>b: NotifyScroll(FullLength) EndScroll()\n\ 78 + <KeyPress>Down: StartScroll(Forward)\n\ 79 + <KeyRelease>Down: NotifyScroll(FullLength) EndScroll()\n\ 80 + <KeyPress>Up: StartScroll(Backward)\n\ 81 + <KeyRelease>Up: NotifyScroll(FullLength) EndScroll() 82 + 83 +*viewport.vertical.translations: #override\n\ 84 + <KeyPress>Down: StartScroll(Forward)\n\ 85 + <KeyRelease>Down: NotifyScroll(FullLength) EndScroll()\n\ 86 + <KeyPress>Up: StartScroll(Backward)\n\ 87 + <KeyRelease>Up: NotifyScroll(FullLength) EndScroll()\n\ 88 + <KeyPress>Next: StartScroll(Forward)\n\ 89 + <KeyRelease>Next: NotifyScroll(FullLength) EndScroll()\n\ 90 + <KeyPress>Prior: StartScroll(Backward)\n\ 91 + <KeyRelease>Prior: NotifyScroll(FullLength) EndScroll()\n\ 92 + <KeyPress>z: StartScroll(Forward)\n\ 93 + <KeyRelease>z: NotifyScroll(FullLength) EndScroll()\n\ 94 + <KeyPress>a: StartScroll(Backward)\n\ 95 + <KeyRelease>a: NotifyScroll(FullLength) EndScroll()\n\ 96 + <KeyPress>f: StartScroll(Forward)\n\ 97 + <KeyRelease>f: NotifyScroll(FullLength) EndScroll()\n\ 98 + <KeyPress>b: StartScroll(Backward)\n\ 99 + <KeyRelease>b: NotifyScroll(FullLength) EndScroll()\n\ 100 + <KeyPress>Right: StartScroll(Forward)\n\ 101 + <KeyRelease>Right: NotifyScroll(FullLength) EndScroll()\n\ 102 + <KeyPress>Left: StartScroll(Backward)\n\ 103 + <KeyRelease>Left: NotifyScroll(FullLength) EndScroll() 104 + 105 106 ! 107 ! Dialog boxes 108 ! 109 110 *serverDialog.dialog.label: VNC server: 111 + 112 *serverDialog.dialog.value: 113 + 114 *serverDialog.dialog.value.translations: #override\n\ 115 - <Key>Return: ServerDialogDone() 116 + <Key>Return: ServerDialogDone() 117 + 118 +*ycropDialog.dialog.label: Y Crop (max-height in pixels): 119 + 120 +*ycropDialog.dialog.value: 121 + 122 +*ycropDialog.dialog.value.translations: #override\n\ 123 + <Key>Return: YCropDialogDone() 124 + 125 +*scbarDialog.dialog.label: Scroll Bars width: 126 + 127 +*scbarDialog.dialog.value: 128 + 129 +*scbarDialog.dialog.value.translations: #override\n\ 130 + <Key>Return: ScbarDialogDone() 131 + 132 +*scaleDialog.dialog.label: Integer n for 1/n server scaling: 133 + 134 +*scaleDialog.dialog.value: 135 + 136 +*scaleDialog.dialog.value.translations: #override\n\ 137 + <Key>Return: ScaleDialogDone() 138 139 *passwordDialog.dialog.label: Password: 140 + 141 *passwordDialog.dialog.value: 142 + 143 *passwordDialog.dialog.value.AsciiSink.echo: False 144 + 145 *passwordDialog.dialog.value.translations: #override\n\ 146 - <Key>Return: PasswordDialogDone() 147 + <Key>Return: PasswordDialogDone() 148 149 150 ! 151 ! Popup window appearance 152 ! 153 154 -*popup.title: TightVNC popup 155 +*popup.title: SSVNC popup 156 + 157 *popup*background: grey 158 -*popup*font: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-* 159 -*popup.buttonForm.Command.borderWidth: 0 160 -*popup.buttonForm.Toggle.borderWidth: 0 161 + 162 +*popup*font_old: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-* 163 + 164 +*popup*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* 165 + 166 +*popup.buttonForm*.Command.borderWidth: 0 167 + 168 +*popup.buttonForm*.Toggle.borderWidth: 0 169 + 170 +*scaleN.title: 1/n scale 171 + 172 +*scaleN*background: grey 173 + 174 +*scaleN*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* 175 + 176 +*scaleN.buttonForm.Command.borderWidth: 0 177 + 178 +*scaleN.buttonForm.Toggle.borderWidth: 0 179 + 180 +*quality.title: quality 181 + 182 +*quality*background: grey 183 + 184 +*quality*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* 185 + 186 +*quality.buttonForm.Command.borderWidth: 0 187 + 188 +*quality.buttonForm.Toggle.borderWidth: 0 189 + 190 +*compress.title: compress 191 + 192 +*compress*background: grey 193 + 194 +*compress*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-* 195 + 196 +*compress.buttonForm.Command.borderWidth: 0 197 + 198 +*compress.buttonForm.Toggle.borderWidth: 0 199 + 200 201 ! 202 ! Translations on popup window - send key presses through 203 ! 204 205 *popup.translations: #override <Message>WM_PROTOCOLS: HidePopup() 206 + 207 *popup.buttonForm.translations: #override\n\ 208 - <KeyPress>: SendRFBEvent() HidePopup() 209 + <KeyPress>: SendRFBEvent() HidePopup() 210 211 212 ! 213 ! Popup buttons 214 ! 215 216 -*popupButtonCount: 8 217 +*popupButtonCount: 38 218 + 219 +*popupButtonBreak: 19 220 221 *popup*button1.label: Dismiss popup 222 + 223 *popup*button1.translations: #override\n\ 224 - <Btn1Down>,<Btn1Up>: HidePopup() 225 + <Btn1Down>,<Btn1Up>: HidePopup() 226 227 *popup*button2.label: Quit viewer 228 + 229 *popup*button2.translations: #override\n\ 230 - <Btn1Down>,<Btn1Up>: Quit() 231 + <Btn1Down>,<Btn1Up>: Quit() 232 + 233 +*popup*button3.label: Full screen (also F9) 234 235 -*popup*button3.label: Full screen 236 *popup*button3.type: toggle 237 + 238 *popup*button3.translations: #override\n\ 239 - <Visible>: SetFullScreenState()\n\ 240 - <Btn1Down>,<Btn1Up>: toggle() HidePopup() ToggleFullScreen() 241 + <Visible>: SetFullScreenState()\n\ 242 + <Btn1Down>,<Btn1Up>: toggle() ToggleFullScreen() HidePopup() 243 244 *popup*button4.label: Clipboard: local -> remote 245 + 246 *popup*button4.translations: #override\n\ 247 - <Btn1Down>,<Btn1Up>: SelectionToVNC(always) HidePopup() 248 + <Btn1Down>,<Btn1Up>: SelectionToVNC(always) HidePopup() 249 250 *popup*button5.label: Clipboard: local <- remote 251 + 252 *popup*button5.translations: #override\n\ 253 - <Btn1Down>,<Btn1Up>: SelectionFromVNC(always) HidePopup() 254 + <Btn1Down>,<Btn1Up>: SelectionFromVNC(always) HidePopup() 255 256 *popup*button6.label: Request refresh 257 + 258 *popup*button6.translations: #override\n\ 259 - <Btn1Down>,<Btn1Up>: SendRFBEvent(fbupdate) HidePopup() 260 + <Btn1Down>,<Btn1Up>: SendRFBEvent(fbupdate) HidePopup() 261 262 *popup*button7.label: Send ctrl-alt-del 263 + 264 *popup*button7.translations: #override\n\ 265 - <Btn1Down>,<Btn1Up>: SendRFBEvent(keydown,Control_L)\ 266 - SendRFBEvent(keydown,Alt_L)\ 267 - SendRFBEvent(key,Delete)\ 268 - SendRFBEvent(keyup,Alt_L)\ 269 - SendRFBEvent(keyup,Control_L)\ 270 - HidePopup() 271 + <Btn1Down>,<Btn1Up>: SendRFBEvent(keydown,Control_L) SendRFBEvent(keydown,Alt_L) SendRFBEvent(key,Delete) SendRFBEvent(keyup,Alt_L) SendRFBEvent(keyup,Control_L) HidePopup() 272 273 *popup*button8.label: Send F8 274 + 275 *popup*button8.translations: #override\n\ 276 - <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup() 277 + <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup() 278 + 279 +*popup*button9.label: Send F9 280 + 281 +*popup*button9.translations: #override\n\ 282 + <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F9) HidePopup() 283 + 284 +*popup*button10.label: ViewOnly 285 + 286 +*popup*button10.type: toggle 287 + 288 +*popup*button10.translations: #override\n\ 289 + <Visible>: SetViewOnlyState()\n\ 290 + <Btn1Down>,<Btn1Up>: toggle() ToggleViewOnly() HidePopup() 291 + 292 +*popup*button11.label: Disable Bell 293 + 294 +*popup*button11.type: toggle 295 + 296 +*popup*button11.translations: #override\n\ 297 + <Visible>: SetBellState()\n\ 298 + <Btn1Down>,<Btn1Up>: toggle() ToggleBell() HidePopup() 299 + 300 +*popup*button12.label: Cursor Shape 301 + 302 +*popup*button12.type: toggle 303 + 304 +*popup*button12.translations: #override\n\ 305 + <Visible>: SetCursorShapeState()\n\ 306 + <Btn1Down>,<Btn1Up>: toggle() ToggleCursorShape() HidePopup() 307 + 308 +*popup*button13.label: X11 Cursor 309 + 310 +*popup*button13.type: toggle 311 + 312 +*popup*button13.translations: #override\n\ 313 + <Visible>: SetX11CursorState()\n\ 314 + <Btn1Down>,<Btn1Up>: toggle() ToggleX11Cursor() HidePopup() 315 + 316 +*popup*button14.label: Cursor Alphablend 317 + 318 +*popup*button14.type: toggle 319 + 320 +*popup*button14.translations: #override\n\ 321 + <Visible>: SetCursorAlphaState()\n\ 322 + <Btn1Down>,<Btn1Up>: toggle() ToggleCursorAlpha() HidePopup() 323 + 324 +*popup*button15.label: Toggle Tight/ZRLE 325 + 326 +*popup*button15.type: toggle 327 + 328 +*popup*button15.translations: #override\n\ 329 + <Visible>: SetZRLEState()\n\ 330 + <Btn1Down>,<Btn1Up>: toggle() ToggleTightZRLE() HidePopup() 331 + 332 +*popup*button16.label: Toggle ZRLE/ZYWRLE 333 + 334 +*popup*button16.type: toggle 335 + 336 +*popup*button16.translations: #override\n\ 337 + <Visible>: SetZYWRLEState()\n\ 338 + <Btn1Down>,<Btn1Up>: toggle() ToggleZRLEZYWRLE() HidePopup() 339 + 340 +*popup*button17.label: Quality Level 341 + 342 +*popup*button17.translations: #override\n\ 343 + <Btn1Down>,<Btn1Up>: HidePopup() ShowQuality() 344 + 345 +*popup*button18.label: Compress Level 346 + 347 +*popup*button18.translations: #override\n\ 348 + <Btn1Down>,<Btn1Up>: HidePopup() ShowCompress() 349 + 350 +*popup*button19.label: Disable JPEG 351 + 352 +*popup*button19.type: toggle 353 + 354 +*popup*button19.translations: #override\n\ 355 + <Visible>: SetNOJPEGState()\n\ 356 + <Btn1Down>,<Btn1Up>: toggle() ToggleJPEG() HidePopup() 357 + 358 +*popup*button20.label: Full Color 359 + 360 +*popup*button20.type: toggle 361 + 362 +*popup*button20.translations: #override\n\ 363 + <Visible>: SetFullColorState()\n\ 364 + <Btn1Down>,<Btn1Up>: toggle() ToggleFullColor() HidePopup() 365 + 366 +*popup*button21.label: Grey Scale (16 & 8-bpp) 367 + 368 +*popup*button21.type: toggle 369 + 370 +*popup*button21.translations: #override\n\ 371 + <Visible>: SetGreyScaleState()\n\ 372 + <Btn1Down>,<Btn1Up>: toggle() ToggleGreyScale() HidePopup() 373 + 374 +*popup*button22.label: 16 bit color (BGR565) 375 + 376 +*popup*button22.type: toggle 377 + 378 +*popup*button22.translations: #override\n\ 379 + <Visible>: Set16bppState()\n\ 380 + <Btn1Down>,<Btn1Up>: toggle() Toggle16bpp() HidePopup() 381 + 382 +*popup*button23.label: 8 bit color (BGR233) 383 + 384 +*popup*button23.type: toggle 385 + 386 +*popup*button23.translations: #override\n\ 387 + <Visible>: Set8bppState()\n\ 388 + <Btn1Down>,<Btn1Up>: toggle() Toggle8bpp() HidePopup() 389 + 390 +*popup*button24.label: - 256 colors 391 + 392 +*popup*button24.type: toggle 393 + 394 +*popup*button24.translations: #override\n\ 395 + <Visible>: Set256ColorsState()\n\ 396 + <Btn1Down>,<Btn1Up>: toggle() Toggle256Colors() HidePopup() 397 + 398 +*popup*button25.label: - 64 colors 399 + 400 +*popup*button25.type: toggle 401 + 402 +*popup*button25.translations: #override\n\ 403 + <Visible>: Set64ColorsState()\n\ 404 + <Btn1Down>,<Btn1Up>: toggle() Toggle64Colors() HidePopup() 405 + 406 +*popup*button26.label: - 8 colors 407 + 408 +*popup*button26.type: toggle 409 + 410 +*popup*button26.translations: #override\n\ 411 + <Visible>: Set8ColorsState()\n\ 412 + <Btn1Down>,<Btn1Up>: toggle() Toggle8Colors() HidePopup() 413 + 414 +*popup*button27.label: Set Y Crop (y-max) 415 + 416 +*popup*button27.translations: #override\n\ 417 + <Btn1Down>,<Btn1Up>: HidePopup() SetYCrop() 418 + 419 +*popup*button28.label: Set Scrollbar Width 420 + 421 +*popup*button28.translations: #override\n\ 422 + <Btn1Down>,<Btn1Up>: HidePopup() SetScbar() 423 + 424 +*popup*button29.label: UltraVNC Extensions: 425 + 426 +*popup*button29.translations: #override\n\ 427 + <Btn1Down>,<Btn1Up>: HidePopup() 428 + 429 +*popup*button30.label: - Set 1/n Server Scale 430 + 431 +*popup*button30.translations: #override\n\ 432 + <Btn1Down>,<Btn1Up>: HidePopup() ShowScaleN() 433 + 434 +*popup*button31.label: - Text Chat 435 + 436 +*popup*button31.type: toggle 437 + 438 +*popup*button31.translations: #override\n\ 439 + <Visible>: SetTextChatState()\n\ 440 + <Btn1Down>,<Btn1Up>: toggle() ToggleTextChat() HidePopup() 441 + 442 +*popup*button32.label: - File Transfer 443 + 444 +*popup*button32.type: toggle 445 + 446 +*popup*button32.translations: #override\n\ 447 + <Visible>: SetFileXferState()\n\ 448 + <Btn1Down>,<Btn1Up>: toggle() ToggleFileXfer() HidePopup() 449 + 450 +*popup*button33.label: - Single Window 451 + 452 +*popup*button33.type: toggle 453 + 454 +*popup*button33.translations: #override\n\ 455 + <Visible>: SetSingleWindowState()\n\ 456 + <Btn1Down>,<Btn1Up>: toggle() ToggleSingleWindow() HidePopup() 457 + 458 +*popup*button34.label: - Disable Remote Input 459 + 460 +*popup*button34.type: toggle 461 + 462 +*popup*button34.translations: #override\n\ 463 + <Visible>: SetServerInputState()\n\ 464 + <Btn1Down>,<Btn1Up>: toggle() ToggleServerInput() HidePopup() 465 + 466 +*popup*button35.label: 467 + 468 +*popup*button36.label: 469 + 470 +*popup*button37.label: 471 + 472 +*popup*button38.label: 473 + 474 +*scaleN*button0.label: Dismiss 475 + 476 +*scaleN*button0.translations: #override\n\ 477 + <Btn1Down>,<Btn1Up>: HideScaleN() 478 + 479 +*scaleN*button1.label: 1/1 480 + 481 +*scaleN*button1.translations: #override\n\ 482 + <Visible>: SetScaleNState(1)\n\ 483 + <Btn1Down>,<Btn1Up>: SetScaleN(1) HideScaleN() 484 + 485 +*scaleN*button2.label: 1/2 486 + 487 +*scaleN*button2.translations: #override\n\ 488 + <Visible>: SetScaleNState(2)\n\ 489 + <Btn1Down>,<Btn1Up>: SetScaleN(2) HideScaleN() 490 + 491 +*scaleN*button3.label: 1/3 492 + 493 +*scaleN*button3.translations: #override\n\ 494 + <Visible>: SetScaleNState(3)\n\ 495 + <Btn1Down>,<Btn1Up>: SetScaleN(3) HideScaleN() 496 + 497 +*scaleN*button4.label: 1/4 498 + 499 +*scaleN*button4.translations: #override\n\ 500 + <Visible>: SetScaleNState(4)\n\ 501 + <Btn1Down>,<Btn1Up>: SetScaleN(4) HideScaleN() 502 + 503 +*scaleN*button5.label: 1/5 504 + 505 +*scaleN*button5.translations: #override\n\ 506 + <Visible>: SetScaleNState(5)\n\ 507 + <Btn1Down>,<Btn1Up>: SetScaleN(5) HideScaleN() 508 + 509 +*scaleN*button6.label: Other 510 + 511 +*scaleN*button6.translations: #override\n\ 512 + <Visible>: SetScaleNState(6)\n\ 513 + <Btn1Down>,<Btn1Up>: HideScaleN() DoServerScale() 514 + 515 +*quality*buttonD.label: Dismiss 516 + 517 +*quality*buttonD.translations: #override\n\ 518 + <Btn1Down>,<Btn1Up>: HideQuality() 519 + 520 +*quality*button0.label: 0 521 + 522 +*quality*button0.type: toggle 523 + 524 +*quality*button0.translations: #override\n\ 525 + <Visible>: SetQualityState(0)\n\ 526 + <Btn1Down>,<Btn1Up>: SetQuality(0) HideQuality() 527 + 528 +*quality*button1.label: 1 529 + 530 +*quality*button1.type: toggle 531 + 532 +*quality*button1.translations: #override\n\ 533 + <Visible>: SetQualityState(1)\n\ 534 + <Btn1Down>,<Btn1Up>: SetQuality(1) HideQuality() 535 + 536 +*quality*button2.label: 2 537 + 538 +*quality*button2.type: toggle 539 + 540 +*quality*button2.translations: #override\n\ 541 + <Visible>: SetQualityState(2)\n\ 542 + <Btn1Down>,<Btn1Up>: SetQuality(2) HideQuality() 543 + 544 +*quality*button3.label: 3 545 + 546 +*quality*button3.type: toggle 547 + 548 +*quality*button3.translations: #override\n\ 549 + <Visible>: SetQualityState(3)\n\ 550 + <Btn1Down>,<Btn1Up>: SetQuality(3) HideQuality() 551 + 552 +*quality*button4.label: 4 553 + 554 +*quality*button4.type: toggle 555 + 556 +*quality*button4.translations: #override\n\ 557 + <Visible>: SetQualityState(4)\n\ 558 + <Btn1Down>,<Btn1Up>: SetQuality(4) HideQuality() 559 + 560 +*quality*button5.label: 5 561 + 562 +*quality*button5.type: toggle 563 + 564 +*quality*button5.translations: #override\n\ 565 + <Visible>: SetQualityState(5)\n\ 566 + <Btn1Down>,<Btn1Up>: SetQuality(5) HideQuality() 567 + 568 +*quality*button6.label: 6 569 + 570 +*quality*button6.type: toggle 571 + 572 +*quality*button6.translations: #override\n\ 573 + <Visible>: SetQualityState(6)\n\ 574 + <Btn1Down>,<Btn1Up>: SetQuality(6) HideQuality() 575 + 576 +*quality*button7.label: 7 577 + 578 +*quality*button7.type: toggle 579 + 580 +*quality*button7.translations: #override\n\ 581 + <Visible>: SetQualityState(7)\n\ 582 + <Btn1Down>,<Btn1Up>: SetQuality(7) HideQuality() 583 + 584 +*quality*button8.label: 8 585 + 586 +*quality*button8.type: toggle 587 + 588 +*quality*button8.translations: #override\n\ 589 + <Visible>: SetQualityState(8)\n\ 590 + <Btn1Down>,<Btn1Up>: SetQuality(8) HideQuality() 591 + 592 +*quality*button9.label: 9 593 + 594 +*quality*button9.type: toggle 595 + 596 +*quality*button9.translations: #override\n\ 597 + <Visible>: SetQualityState(9)\n\ 598 + <Btn1Down>,<Btn1Up>: SetQuality(9) HideQuality() 599 + 600 +*compress*buttonD.label: Dismiss 601 + 602 +*compress*buttonD.translations: #override\n\ 603 + <Btn1Down>,<Btn1Up>: HideCompress() 604 + 605 +*compress*button0.label: 0 606 + 607 +*compress*button0.translations: #override\n\ 608 + <Visible>: SetCompressState(0)\n\ 609 + <Btn1Down>,<Btn1Up>: SetCompress(0) HideCompress() 610 + 611 +*compress*button1.label: 1 612 + 613 +*compress*button1.translations: #override\n\ 614 + <Visible>: SetCompressState(1)\n\ 615 + <Btn1Down>,<Btn1Up>: SetCompress(1) HideCompress() 616 + 617 +*compress*button2.label: 2 618 + 619 +*compress*button2.translations: #override\n\ 620 + <Visible>: SetCompressState(2)\n\ 621 + <Btn1Down>,<Btn1Up>: SetCompress(2) HideCompress() 622 + 623 +*compress*button3.label: 3 624 + 625 +*compress*button3.translations: #override\n\ 626 + <Visible>: SetCompressState(3)\n\ 627 + <Btn1Down>,<Btn1Up>: SetCompress(3) HideCompress() 628 + 629 +*compress*button4.label: 4 630 + 631 +*compress*button4.translations: #override\n\ 632 + <Visible>: SetCompressState(4)\n\ 633 + <Btn1Down>,<Btn1Up>: SetCompress(4) HideCompress() 634 + 635 +*compress*button5.label: 5 636 + 637 +*compress*button5.translations: #override\n\ 638 + <Visible>: SetCompressState(5)\n\ 639 + <Btn1Down>,<Btn1Up>: SetCompress(5) HideCompress() 640 + 641 +*compress*button6.label: 6 642 + 643 +*compress*button6.translations: #override\n\ 644 + <Visible>: SetCompressState(6)\n\ 645 + <Btn1Down>,<Btn1Up>: SetCompress(6) HideCompress() 646 + 647 +*compress*button7.label: 7 648 + 649 +*compress*button7.translations: #override\n\ 650 + <Visible>: SetCompressState(7)\n\ 651 + <Btn1Down>,<Btn1Up>: SetCompress(7) HideCompress() 652 + 653 +*compress*button8.label: 8 654 + 655 +*compress*button8.translations: #override\n\ 656 + <Visible>: SetCompressState(8)\n\ 657 + <Btn1Down>,<Btn1Up>: SetCompress(8) HideCompress() 658 + 659 +*compress*button9.label: 9 660 + 661 +*compress*button9.translations: #override\n\ 662 + <Visible>: SetCompressState(9)\n\ 663 + <Btn1Down>,<Btn1Up>: SetCompress(9) HideCompress() 664 + 665 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/vncviewer/argsresources.c 666 --- vnc_unixsrc.orig/vncviewer/argsresources.c 2007-02-04 17:10:31.000000000 -0500 667 +++ vnc_unixsrc/vncviewer/argsresources.c 2010-04-18 12:39:55.000000000 -0400 668 @@ -31,9 +31,9 @@ 669 670 char *fallback_resources[] = { 671 672 - "Vncviewer.title: TightVNC: %s", 673 + "Ssvnc.title: SSVNC: %s - Press F8 for Menu", 674 675 - "Vncviewer.translations:\ 676 + "Ssvnc.translations:\ 677 <Enter>: SelectionToVNC()\\n\ 678 <Leave>: SelectionFromVNC()", 679 680 @@ -45,8 +45,60 @@ 681 "*viewport.useRight: True", 682 "*viewport*Scrollbar*thumb: None", 683 684 + "*viewport.horizontal.height: 6 ", 685 + "*viewport.vertical.width: 6 ", 686 + "ssvnc*viewport.horizontal.height: 6 ", 687 + "ssvnc*viewport.vertical.width: 6 ", 688 + 689 + "*viewport.horizontal.translations: #override\\n\ 690 + <KeyPress>Right: StartScroll(Forward)\\n\ 691 + <KeyRelease>Right: NotifyScroll(FullLength) EndScroll()\\n\ 692 + <KeyPress>Left: StartScroll(Backward)\\n\ 693 + <KeyRelease>Left: NotifyScroll(FullLength) EndScroll()\\n\ 694 + <KeyPress>Next: StartScroll(Forward)\\n\ 695 + <KeyRelease>Next: NotifyScroll(FullLength) EndScroll()\\n\ 696 + <KeyPress>Prior: StartScroll(Backward)\\n\ 697 + <KeyRelease>Prior: NotifyScroll(FullLength) EndScroll()\\n\ 698 + <KeyPress>z: StartScroll(Forward)\\n\ 699 + <KeyRelease>z: NotifyScroll(FullLength) EndScroll()\\n\ 700 + <KeyPress>a: StartScroll(Backward)\\n\ 701 + <KeyRelease>a: NotifyScroll(FullLength) EndScroll()\\n\ 702 + <KeyPress>f: StartScroll(Forward)\\n\ 703 + <KeyRelease>f: NotifyScroll(FullLength) EndScroll()\\n\ 704 + <KeyPress>b: StartScroll(Backward)\\n\ 705 + <KeyRelease>b: NotifyScroll(FullLength) EndScroll()\\n\ 706 + <KeyPress>Down: StartScroll(Forward)\\n\ 707 + <KeyRelease>Down: NotifyScroll(FullLength) EndScroll()\\n\ 708 + <KeyPress>Up: StartScroll(Backward)\\n\ 709 + <KeyRelease>Up: NotifyScroll(FullLength) EndScroll()", 710 + 711 + "*viewport.vertical.translations: #override\\n\ 712 + <KeyPress>Down: StartScroll(Forward)\\n\ 713 + <KeyRelease>Down: NotifyScroll(FullLength) EndScroll()\\n\ 714 + <KeyPress>Up: StartScroll(Backward)\\n\ 715 + <KeyRelease>Up: NotifyScroll(FullLength) EndScroll()\\n\ 716 + <KeyPress>Next: StartScroll(Forward)\\n\ 717 + <KeyRelease>Next: NotifyScroll(FullLength) EndScroll()\\n\ 718 + <KeyPress>Prior: StartScroll(Backward)\\n\ 719 + <KeyRelease>Prior: NotifyScroll(FullLength) EndScroll()\\n\ 720 + <KeyPress>z: StartScroll(Forward)\\n\ 721 + <KeyRelease>z: NotifyScroll(FullLength) EndScroll()\\n\ 722 + <KeyPress>a: StartScroll(Backward)\\n\ 723 + <KeyRelease>a: NotifyScroll(FullLength) EndScroll()\\n\ 724 + <KeyPress>f: StartScroll(Forward)\\n\ 725 + <KeyRelease>f: NotifyScroll(FullLength) EndScroll()\\n\ 726 + <KeyPress>b: StartScroll(Backward)\\n\ 727 + <KeyRelease>b: NotifyScroll(FullLength) EndScroll()\\n\ 728 + <KeyPress>Right: StartScroll(Forward)\\n\ 729 + <KeyRelease>Right: NotifyScroll(FullLength) EndScroll()\\n\ 730 + <KeyPress>Left: StartScroll(Backward)\\n\ 731 + <KeyRelease>Left: NotifyScroll(FullLength) EndScroll()", 732 + 733 "*desktop.baseTranslations:\ 734 - <Key>F8: ShowPopup()\\n\ 735 + <KeyPress>F8: ShowPopup()\\n\ 736 + <KeyRelease>F8: Noop()\\n\ 737 + <KeyPress>F9: ToggleFullScreen()\\n\ 738 + <KeyRelease>F9: Noop()\\n\ 739 <ButtonPress>: SendRFBEvent()\\n\ 740 <ButtonRelease>: SendRFBEvent()\\n\ 741 <Motion>: SendRFBEvent()\\n\ 742 @@ -55,26 +107,137 @@ 743 744 "*serverDialog.dialog.label: VNC server:", 745 "*serverDialog.dialog.value:", 746 + "*serverDialog.dialog.value.width: 150", 747 "*serverDialog.dialog.value.translations: #override\\n\ 748 <Key>Return: ServerDialogDone()", 749 750 - "*passwordDialog.dialog.label: Password:", 751 + "*userDialog.dialog.label: SSVNC: Enter Username", 752 + "*userDialog.dialog.value:", 753 + "*userDialog.dialog.value.width: 150", 754 + "*userDialog.dialog.value.translations: #override\\n\ 755 + <Key>Return: UserDialogDone()", 756 + 757 + "*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:", 758 + "*scaleDialog.dialog.value:", 759 + "*scaleDialog.dialog.value.translations: #override\\n\ 760 + <KeyRelease>Return: ScaleDialogDone()", 761 + 762 + "*escapeDialog.dialog.label: Escape Keys: Enter a comma separated list of modifier keys to be the\\n" 763 + "'escape sequence'. When these keys are held down, the next keystroke is\\n" 764 + "interpreted locally to invoke a special action instead of being sent to\\n" 765 + "the remote VNC server. In other words, a set of 'Hot Keys'.\\n" 766 + "\\n" 767 + "To enable or disable this, click on 'Escape Keys: Toggle' in the Popup.\\n" 768 + "\\n" 769 + "Here is the list of hot-key mappings to special actions:\\n" 770 + "\\n" 771 + " r: refresh desktop b: toggle bell c: toggle full-color\\n" 772 + " f: file transfer x: x11cursor z: toggle Tight/ZRLE\\n" 773 + " l: full screen g: graball e: escape keys dialog\\n" 774 + " s: scale dialog +: scale up (=) -: scale down (_)\\n" 775 + " t: text chat a: alphablend cursor\\n" 776 + " V: toggle viewonly Q: quit viewer 1 2 3 4 5 6: UltraVNC scale 1/n\\n" 777 + "\\n" 778 + " Arrow keys: pan the viewport about 10% for each keypress.\\n" 779 + " PageUp / PageDown: pan the viewport by a screenful vertically.\\n" 780 + " Home / End: pan the viewport by a screenful horizontally.\\n" 781 + " KeyPad Arrow keys: pan the viewport by 1 pixel for each keypress.\\n" 782 + " Dragging the Mouse with Button1 pressed also pans the viewport.\\n" 783 + " Clicking Mouse Button3 brings up the Popup Menu.\\n" 784 + "\\n" 785 + "The above mappings are *always* active in ViewOnly mode, unless you set the\\n" 786 + "Escape Keys value to 'never'.\\n" 787 + "\\n" 788 + "x11vnc -appshare hot-keys: x11vnc has a simple application sharing mode\\n" 789 + "that enables the viewer-side to move, resize, or raise the remote toplevel\\n" 790 + "windows. To enable it, hold down Shift + the Escape Keys and press these:\\n" 791 + "\\n" 792 + " Arrow keys: move the remote window around in its desktop.\\n" 793 + " PageUp/PageDn/Home/End: resize the remote window.\\n" 794 + " +/- raise or lower the remote window.\\n" 795 + " M or Button1 move win to local position; D or Button3: delete remote win.\\n" 796 + "\\n" 797 + "If the Escape Keys value below is set to 'default' then a fixed list of\\n" 798 + "modifier keys is used. For Unix it is: Alt_L,Super_L and for MacOSX it is\\n" 799 + "Control_L,Meta_L. Note: the Super_L key usually has a Windows(TM) Flag.\\n" 800 + "Also note the _L and _R mean the key is on the LEFT or RIGHT side of keyboard.\\n" 801 + "\\n" 802 + "On Unix the default is Alt and Windows keys on Left side of keyboard.\\n" 803 + "On MacOSX the default is Control and Command keys on Left side of keyboard.\\n" 804 + "\\n" 805 + "Example: Press and hold the Alt and Windows keys on the LEFT side of the\\n" 806 + "keyboard and then press 'c' to toggle the full-color state. Or press 't'\\n" 807 + "to toggle the ultravnc Text Chat window, etc.\\n" 808 + "\\n" 809 + "To use something besides the default, supply a comma separated list (or a\\n" 810 + "single one) from: Shift_L Shift_R Control_L Control_R Alt_L Alt_R Meta_L\\n" 811 + "Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch.\\n" 812 + "\\n" 813 + "Current Escape Keys Value:", 814 + "*escapeDialog.dialog.value:", 815 + "*escapeDialog.dialog.value.width: 280", 816 + "*escapeDialog.dialog.value.translations: #override\\n\ 817 + <KeyRelease>Return: EscapeDialogDone()", 818 + 819 + "*ycropDialog.dialog.label: Y Crop (max-height in pixels):", 820 + "*ycropDialog.dialog.value:", 821 + "*ycropDialog.dialog.value.translations: #override\\n\ 822 + <KeyRelease>Return: YCropDialogDone()", 823 + 824 + "*scbarDialog.dialog.label: Scroll Bars width:", 825 + "*scbarDialog.dialog.value:", 826 + "*scbarDialog.dialog.value.translations: #override\\n\ 827 + <KeyRelease>Return: ScbarDialogDone()", 828 + 829 + "*scaleNDialog.dialog.label: Integer n for 1/n server scaling:", 830 + "*scaleNDialog.dialog.value:", 831 + "*scaleNDialog.dialog.value.translations: #override\\n\ 832 + <KeyRelease>Return: ScaleNDialogDone()", 833 + 834 + "*passwordDialog.dialog.label: SSVNC: Enter Password", 835 "*passwordDialog.dialog.value:", 836 + "*passwordDialog.dialog.value.width: 150", 837 "*passwordDialog.dialog.value.AsciiSink.echo: False", 838 "*passwordDialog.dialog.value.translations: #override\\n\ 839 <Key>Return: PasswordDialogDone()", 840 841 - "*popup.title: TightVNC popup", 842 + "*popup.title: SSVNC popup", 843 "*popup*background: grey", 844 - "*popup*font: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-*", 845 - "*popup.buttonForm.Command.borderWidth: 0", 846 - "*popup.buttonForm.Toggle.borderWidth: 0", 847 + "*popup*font_old: -*-helvetica-bold-r-*-*-16-*-*-*-*-*-*-*", 848 + "*popup*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", 849 + "*popup.buttonForm*.Command.borderWidth: 0", 850 + "*popup.buttonForm*.Toggle.borderWidth: 0", 851 + 852 + "*scaleN.title: 1/n scale", 853 + "*scaleN*background: grey", 854 + "*scaleN*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", 855 + "*scaleN.buttonForm.Command.borderWidth: 0", 856 + "*scaleN.buttonForm.Toggle.borderWidth: 0", 857 + 858 + "*turboVNC.title: TurboVNC", 859 + "*turboVNC*background: grey", 860 + "*turboVNC*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", 861 + "*turboVNC.buttonForm.Command.borderWidth: 0", 862 + "*turboVNC.buttonForm.Toggle.borderWidth: 0", 863 + 864 + "*quality.title: quality", 865 + "*quality*background: grey", 866 + "*quality*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", 867 + "*quality.buttonForm.Command.borderWidth: 0", 868 + "*quality.buttonForm.Toggle.borderWidth: 0", 869 + 870 + "*compress.title: compress", 871 + "*compress*background: grey", 872 + "*compress*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", 873 + "*compress.buttonForm.Command.borderWidth: 0", 874 + "*compress.buttonForm.Toggle.borderWidth: 0", 875 876 "*popup.translations: #override <Message>WM_PROTOCOLS: HidePopup()", 877 "*popup.buttonForm.translations: #override\\n\ 878 <KeyPress>: SendRFBEvent() HidePopup()", 879 880 - "*popupButtonCount: 8", 881 + "*popupButtonCount: 44", 882 + "*popupButtonBreak: 22", 883 884 "*popup*button1.label: Dismiss popup", 885 "*popup*button1.translations: #override\\n\ 886 @@ -84,7 +247,7 @@ 887 "*popup*button2.translations: #override\\n\ 888 <Btn1Down>,<Btn1Up>: Quit()", 889 890 - "*popup*button3.label: Full screen", 891 + "*popup*button3.label: Full screen (also F9)", 892 "*popup*button3.type: toggle", 893 "*popup*button3.translations: #override\\n\ 894 <Visible>: SetFullScreenState()\\n\ 895 @@ -105,16 +268,426 @@ 896 "*popup*button7.label: Send ctrl-alt-del", 897 "*popup*button7.translations: #override\\n\ 898 <Btn1Down>,<Btn1Up>: SendRFBEvent(keydown,Control_L)\ 899 - SendRFBEvent(keydown,Alt_L)\ 900 - SendRFBEvent(key,Delete)\ 901 - SendRFBEvent(keyup,Alt_L)\ 902 - SendRFBEvent(keyup,Control_L)\ 903 - HidePopup()", 904 + SendRFBEvent(keydown,Alt_L)\ 905 + SendRFBEvent(key,Delete)\ 906 + SendRFBEvent(keyup,Alt_L)\ 907 + SendRFBEvent(keyup,Control_L)\ 908 + HidePopup()", 909 910 "*popup*button8.label: Send F8", 911 "*popup*button8.translations: #override\\n\ 912 <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F8) HidePopup()", 913 914 + "*popup*button9.label: Send F9", 915 + "*popup*button9.translations: #override\\n\ 916 + <Btn1Down>,<Btn1Up>: SendRFBEvent(key,F9) HidePopup()", 917 + 918 + "*popup*button10.label: ViewOnly", 919 + "*popup*button10.type: toggle", 920 + "*popup*button10.translations: #override\\n\ 921 + <Visible>: SetViewOnlyState()\\n\ 922 + <Btn1Down>,<Btn1Up>: toggle() ToggleViewOnly() HidePopup()", 923 + 924 + "*popup*button11.label: Disable Bell", 925 + "*popup*button11.type: toggle", 926 + "*popup*button11.translations: #override\\n\ 927 + <Visible>: SetBellState()\\n\ 928 + <Btn1Down>,<Btn1Up>: toggle() ToggleBell() HidePopup()", 929 + 930 + "*popup*button12.label: Cursor Shape", 931 + "*popup*button12.type: toggle", 932 + "*popup*button12.translations: #override\\n\ 933 + <Visible>: SetCursorShapeState()\\n\ 934 + <Btn1Down>,<Btn1Up>: toggle() ToggleCursorShape() HidePopup()", 935 + 936 + "*popup*button13.label: X11 Cursor", 937 + "*popup*button13.type: toggle", 938 + "*popup*button13.translations: #override\\n\ 939 + <Visible>: SetX11CursorState()\\n\ 940 + <Btn1Down>,<Btn1Up>: toggle() ToggleX11Cursor() HidePopup()", 941 + 942 + "*popup*button14.label: Cursor Alphablend", 943 + "*popup*button14.type: toggle", 944 + "*popup*button14.translations: #override\\n\ 945 + <Visible>: SetCursorAlphaState()\\n\ 946 + <Btn1Down>,<Btn1Up>: toggle() ToggleCursorAlpha() HidePopup()", 947 + 948 + "*popup*button15.label: Toggle Tight/Hextile", 949 + "*popup*button15.type: toggle", 950 + "*popup*button15.translations: #override\\n\ 951 + <Visible>: SetHextileState()\\n\ 952 + <Btn1Down>,<Btn1Up>: toggle() ToggleTightHextile() HidePopup()", 953 + 954 + "*popup*button16.label: Toggle Tight/ZRLE", 955 + "*popup*button16.type: toggle", 956 + "*popup*button16.translations: #override\\n\ 957 + <Visible>: SetZRLEState()\\n\ 958 + <Btn1Down>,<Btn1Up>: toggle() ToggleTightZRLE() HidePopup()", 959 + 960 + "*popup*button17.label: Toggle ZRLE/ZYWRLE", 961 + "*popup*button17.type: toggle", 962 + "*popup*button17.translations: #override\\n\ 963 + <Visible>: SetZYWRLEState()\\n\ 964 + <Btn1Down>,<Btn1Up>: toggle() ToggleZRLEZYWRLE() HidePopup()", 965 + 966 + "*popup*button18.label: Quality Level", 967 + "*popup*button18.translations: #override\\n\ 968 + <Btn1Down>,<Btn1Up>: HidePopup() ShowQuality()", 969 + 970 + "*popup*button19.label: Compress Level", 971 + "*popup*button19.translations: #override\\n\ 972 + <Btn1Down>,<Btn1Up>: HidePopup() ShowCompress()", 973 + 974 + "*popup*button20.label: Disable JPEG", 975 + "*popup*button20.type: toggle", 976 + "*popup*button20.translations: #override\\n\ 977 + <Visible>: SetNOJPEGState()\\n\ 978 + <Btn1Down>,<Btn1Up>: toggle() ToggleJPEG() HidePopup()", 979 + 980 + "*popup*button21.label: TurboVNC Settings", 981 + "*popup*button21.translations: #override\\n\ 982 + <Btn1Down>,<Btn1Up>: HidePopup() ShowTurboVNC()", 983 + 984 + "*popup*button22.label: Pipeline Updates", 985 + "*popup*button22.type: toggle", 986 + "*popup*button22.translations: #override\\n\ 987 + <Visible>: SetPipelineUpdates()\\n\ 988 + <Btn1Down>,<Btn1Up>: toggle() TogglePipelineUpdates() HidePopup()", 989 + 990 + "*popup*button23.label: Full Color", 991 + "*popup*button23.type: toggle", 992 + "*popup*button23.translations: #override\\n\ 993 + <Visible>: SetFullColorState()\\n\ 994 + <Btn1Down>,<Btn1Up>: toggle() ToggleFullColor() HidePopup()", 995 + 996 + "*popup*button24.label: Grey Scale (16 & 8-bpp)", 997 + "*popup*button24.type: toggle", 998 + "*popup*button24.translations: #override\\n\ 999 + <Visible>: SetGreyScaleState()\\n\ 1000 + <Btn1Down>,<Btn1Up>: toggle() ToggleGreyScale() HidePopup()", 1001 + 1002 + "*popup*button25.label: 16 bit color (BGR565)", 1003 + "*popup*button25.type: toggle", 1004 + "*popup*button25.translations: #override\\n\ 1005 + <Visible>: Set16bppState()\\n\ 1006 + <Btn1Down>,<Btn1Up>: toggle() Toggle16bpp() HidePopup()", 1007 + 1008 + "*popup*button26.label: 8 bit color (BGR233)", 1009 + "*popup*button26.type: toggle", 1010 + "*popup*button26.translations: #override\\n\ 1011 + <Visible>: Set8bppState()\\n\ 1012 + <Btn1Down>,<Btn1Up>: toggle() Toggle8bpp() HidePopup()", 1013 + 1014 + "*popup*button27.label: - 256 colors", 1015 + "*popup*button27.type: toggle", 1016 + "*popup*button27.translations: #override\\n\ 1017 + <Visible>: Set256ColorsState()\\n\ 1018 + <Btn1Down>,<Btn1Up>: toggle() Toggle256Colors() HidePopup()", 1019 + 1020 + "*popup*button28.label: - 64 colors", 1021 + "*popup*button28.type: toggle", 1022 + "*popup*button28.translations: #override\\n\ 1023 + <Visible>: Set64ColorsState()\\n\ 1024 + <Btn1Down>,<Btn1Up>: toggle() Toggle64Colors() HidePopup()", 1025 + 1026 + "*popup*button29.label: - 8 colors", 1027 + "*popup*button29.type: toggle", 1028 + "*popup*button29.translations: #override\\n\ 1029 + <Visible>: Set8ColorsState()\\n\ 1030 + <Btn1Down>,<Btn1Up>: toggle() Toggle8Colors() HidePopup()", 1031 + 1032 + "*popup*button30.label: Scale Viewer", 1033 + "*popup*button30.translations: #override\\n\ 1034 + <Btn1Down>,<Btn1Up>: HidePopup() SetScale()", 1035 + 1036 + "*popup*button31.label: Escape Keys: Toggle", 1037 + "*popup*button31.type: toggle", 1038 + "*popup*button31.translations: #override\\n\ 1039 + <Visible>: SetEscapeKeysState()\\n\ 1040 + <Btn1Down>, <Btn1Up>: toggle() ToggleEscapeActive() HidePopup()", 1041 + 1042 + "*popup*button32.label: Escape Keys: Help+Set", 1043 + "*popup*button32.translations: #override\\n\ 1044 + <Btn1Down>, <Btn1Up>: HidePopup() SetEscapeKeys()", 1045 + 1046 + "*popup*button33.label: Set Y Crop (y-max)", 1047 + "*popup*button33.translations: #override\\n\ 1048 + <Btn1Down>,<Btn1Up>: HidePopup() SetYCrop()", 1049 + 1050 + "*popup*button34.label: Set Scrollbar Width", 1051 + "*popup*button34.translations: #override\\n\ 1052 + <Btn1Down>,<Btn1Up>: HidePopup() SetScbar()", 1053 + 1054 + "*popup*button35.label: XGrabServer", 1055 + "*popup*button35.type: toggle", 1056 + "*popup*button35.translations: #override\\n\ 1057 + <Visible>: SetXGrabState()\\n\ 1058 + <Btn1Down>,<Btn1Up>: toggle() ToggleXGrab() HidePopup()", 1059 + 1060 + "*popup*button36.label: UltraVNC Extensions:", 1061 + "*popup*button36.translations: #override\\n\ 1062 + <Btn1Down>,<Btn1Up>: HidePopup()", 1063 + 1064 + "*popup*button37.label: - Set 1/n Server Scale", 1065 + "*popup*button37.translations: #override\\n\ 1066 + <Btn1Down>,<Btn1Up>: HidePopup() ShowScaleN()", 1067 + 1068 + "*popup*button38.label: - Text Chat", 1069 + "*popup*button38.type: toggle", 1070 + "*popup*button38.translations: #override\\n\ 1071 + <Visible>: SetTextChatState()\\n\ 1072 + <Btn1Down>,<Btn1Up>: toggle() ToggleTextChat() HidePopup()", 1073 + 1074 + "*popup*button39.label: - File Transfer", 1075 + "*popup*button39.type: toggle", 1076 + "*popup*button39.translations: #override\\n\ 1077 + <Visible>: SetFileXferState()\\n\ 1078 + <Btn1Down>,<Btn1Up>: toggle() ToggleFileXfer() HidePopup()", 1079 + 1080 + "*popup*button40.label: - Single Window", 1081 + "*popup*button40.type: toggle", 1082 + "*popup*button40.translations: #override\\n\ 1083 + <Visible>: SetSingleWindowState()\\n\ 1084 + <Btn1Down>,<Btn1Up>: toggle() ToggleSingleWindow() HidePopup()", 1085 + 1086 + "*popup*button41.label: - Disable Remote Input", 1087 + "*popup*button41.type: toggle", 1088 + "*popup*button41.translations: #override\\n\ 1089 + <Visible>: SetServerInputState()\\n\ 1090 + <Btn1Down>,<Btn1Up>: toggle() ToggleServerInput() HidePopup()", 1091 + 1092 + "*popup*button42.label: Send Clipboard not Primary", 1093 + "*popup*button42.type: toggle", 1094 + "*popup*button42.translations: #override\\n\ 1095 + <Visible>: SetSendClipboard()\\n\ 1096 + <Btn1Down>,<Btn1Up>: toggle() ToggleSendClipboard() HidePopup()", 1097 + 1098 + "*popup*button43.label: Send Selection Every time", 1099 + "*popup*button43.type: toggle", 1100 + "*popup*button43.translations: #override\\n\ 1101 + <Visible>: SetSendAlways()\\n\ 1102 + <Btn1Down>,<Btn1Up>: toggle() ToggleSendAlways() HidePopup()", 1103 + 1104 + "*popup*button44.label: ", 1105 + 1106 + "*turboVNC*button0.label: Dismiss", 1107 + "*turboVNC*button0.translations: #override\\n\ 1108 + <Btn1Down>,<Btn1Up>: HideTurboVNC()", 1109 + 1110 + "*turboVNC*button1.label: High Quality (LAN)", 1111 + "*turboVNC*button1.translations: #override\\n\ 1112 + <Btn1Down>,<Btn1Up>: SetTurboVNC(1)", 1113 + 1114 + "*turboVNC*button2.label: Medium Quality", 1115 + "*turboVNC*button2.translations: #override\\n\ 1116 + <Btn1Down>,<Btn1Up>: SetTurboVNC(2)", 1117 + 1118 + "*turboVNC*button3.label: Low Quality (WAN)", 1119 + "*turboVNC*button3.translations: #override\\n\ 1120 + <Btn1Down>,<Btn1Up>: SetTurboVNC(3)", 1121 + 1122 + "*turboVNC*button4.label: Lossless (Gigabit)", 1123 + "*turboVNC*button4.translations: #override\\n\ 1124 + <Btn1Down>,<Btn1Up>: SetTurboVNC(4)", 1125 + 1126 + "*turboVNC*button5.label: Lossless Zlib (WAN)", 1127 + "*turboVNC*button5.translations: #override\\n\ 1128 + <Btn1Down>,<Btn1Up>: SetTurboVNC(5)", 1129 + 1130 + "*turboVNC*button6.label: Subsampling:", 1131 + 1132 + "*turboVNC*button7.label: - None", 1133 + "*turboVNC*button7.translations: #override\\n\ 1134 + <Btn1Down>,<Btn1Up>: SetTurboVNC(6)", 1135 + 1136 + "*turboVNC*button8.label: - 2X", 1137 + "*turboVNC*button8.translations: #override\\n\ 1138 + <Btn1Down>,<Btn1Up>: SetTurboVNC(7)", 1139 + 1140 + "*turboVNC*button9.label: - 4X", 1141 + "*turboVNC*button9.translations: #override\\n\ 1142 + <Btn1Down>,<Btn1Up>: SetTurboVNC(8)", 1143 + 1144 + "*turboVNC*button10.label: - Gray", 1145 + "*turboVNC*button10.translations: #override\\n\ 1146 + <Btn1Down>,<Btn1Up>: SetTurboVNC(9)", 1147 + 1148 + "*turboVNC*button11.label: Lossless Refresh", 1149 + "*turboVNC*button11.translations: #override\\n\ 1150 + <Btn1Down>,<Btn1Up>: SetTurboVNC(10)", 1151 + 1152 + "*turboVNC*button12.label: Lossy Refresh", 1153 + "*turboVNC*button12.translations: #override\\n\ 1154 + <Btn1Down>,<Btn1Up>: SendRFBEvent(fbupdate)", 1155 + 1156 + "*turboVNC*buttonNone.label: Not Compiled with\\nTurboVNC Support.", 1157 + "*turboVNC*buttonNone.translations: #override\\n\ 1158 + <Btn1Down>,<Btn1Up>: HideTurboVNC()", 1159 + 1160 + "*qualLabel.label: JPEG Image Quality:", 1161 + "*qualBar.length: 100", 1162 + "*qualBar.width: 130", 1163 + "*qualBar.orientation: horizontal", 1164 + "*qualBar.translations: #override\\n\ 1165 + <Btn1Down>: StartScroll(Continuous) MoveThumb() NotifyThumb()\\n\ 1166 + <Btn1Motion>: MoveThumb() NotifyThumb()\\n\ 1167 + <Btn3Down>: StartScroll(Continuous) MoveThumb() NotifyThumb()\\n\ 1168 + <Btn3Motion>: MoveThumb() NotifyThumb()", 1169 + 1170 + "*qualText.label: 000", 1171 + 1172 + "*scaleN*button0.label: Dismiss", 1173 + "*scaleN*button0.translations: #override\\n\ 1174 + <Btn1Down>,<Btn1Up>: HideScaleN()", 1175 + 1176 + "*scaleN*button1.label: 1/1", 1177 + "*scaleN*button1.translations: #override\\n\ 1178 + <Visible>: SetScaleNState(1)\\n\ 1179 + <Btn1Down>,<Btn1Up>: SetScaleN(1) HideScaleN()", 1180 + 1181 + "*scaleN*button2.label: 1/2", 1182 + "*scaleN*button2.translations: #override\\n\ 1183 + <Visible>: SetScaleNState(2)\\n\ 1184 + <Btn1Down>,<Btn1Up>: SetScaleN(2) HideScaleN()", 1185 + 1186 + "*scaleN*button3.label: 1/3", 1187 + "*scaleN*button3.translations: #override\\n\ 1188 + <Visible>: SetScaleNState(3)\\n\ 1189 + <Btn1Down>,<Btn1Up>: SetScaleN(3) HideScaleN()", 1190 + 1191 + "*scaleN*button4.label: 1/4", 1192 + "*scaleN*button4.translations: #override\\n\ 1193 + <Visible>: SetScaleNState(4)\\n\ 1194 + <Btn1Down>,<Btn1Up>: SetScaleN(4) HideScaleN()", 1195 + 1196 + "*scaleN*button5.label: 1/5", 1197 + "*scaleN*button5.translations: #override\\n\ 1198 + <Visible>: SetScaleNState(5)\\n\ 1199 + <Btn1Down>,<Btn1Up>: SetScaleN(5) HideScaleN()", 1200 + 1201 + "*scaleN*button6.label: Other", 1202 + "*scaleN*button6.translations: #override\\n\ 1203 + <Visible>: SetScaleNState(6)\\n\ 1204 + <Btn1Down>,<Btn1Up>: HideScaleN() DoServerScale()", 1205 + 1206 + "*quality*buttonD.label: Dismiss", 1207 + "*quality*buttonD.translations: #override\\n\ 1208 + <Btn1Down>,<Btn1Up>: HideQuality()", 1209 + 1210 + "*quality*button0.label: 0", 1211 + "*quality*button0.type: toggle", 1212 + "*quality*button0.translations: #override\\n\ 1213 + <Visible>: SetQualityState(0)\\n\ 1214 + <Btn1Down>,<Btn1Up>: SetQuality(0) HideQuality()", 1215 + 1216 + "*quality*button1.label: 1", 1217 + "*quality*button1.type: toggle", 1218 + "*quality*button1.translations: #override\\n\ 1219 + <Visible>: SetQualityState(1)\\n\ 1220 + <Btn1Down>,<Btn1Up>: SetQuality(1) HideQuality()", 1221 + 1222 + "*quality*button2.label: 2", 1223 + "*quality*button2.type: toggle", 1224 + "*quality*button2.translations: #override\\n\ 1225 + <Visible>: SetQualityState(2)\\n\ 1226 + <Btn1Down>,<Btn1Up>: SetQuality(2) HideQuality()", 1227 + 1228 + "*quality*button3.label: 3", 1229 + "*quality*button3.type: toggle", 1230 + "*quality*button3.translations: #override\\n\ 1231 + <Visible>: SetQualityState(3)\\n\ 1232 + <Btn1Down>,<Btn1Up>: SetQuality(3) HideQuality()", 1233 + 1234 + "*quality*button4.label: 4", 1235 + "*quality*button4.type: toggle", 1236 + "*quality*button4.translations: #override\\n\ 1237 + <Visible>: SetQualityState(4)\\n\ 1238 + <Btn1Down>,<Btn1Up>: SetQuality(4) HideQuality()", 1239 + 1240 + "*quality*button5.label: 5", 1241 + "*quality*button5.type: toggle", 1242 + "*quality*button5.translations: #override\\n\ 1243 + <Visible>: SetQualityState(5)\\n\ 1244 + <Btn1Down>,<Btn1Up>: SetQuality(5) HideQuality()", 1245 + 1246 + "*quality*button6.label: 6", 1247 + "*quality*button6.type: toggle", 1248 + "*quality*button6.translations: #override\\n\ 1249 + <Visible>: SetQualityState(6)\\n\ 1250 + <Btn1Down>,<Btn1Up>: SetQuality(6) HideQuality()", 1251 + 1252 + "*quality*button7.label: 7", 1253 + "*quality*button7.type: toggle", 1254 + "*quality*button7.translations: #override\\n\ 1255 + <Visible>: SetQualityState(7)\\n\ 1256 + <Btn1Down>,<Btn1Up>: SetQuality(7) HideQuality()", 1257 + 1258 + "*quality*button8.label: 8", 1259 + "*quality*button8.type: toggle", 1260 + "*quality*button8.translations: #override\\n\ 1261 + <Visible>: SetQualityState(8)\\n\ 1262 + <Btn1Down>,<Btn1Up>: SetQuality(8) HideQuality()", 1263 + 1264 + "*quality*button9.label: 9", 1265 + "*quality*button9.type: toggle", 1266 + "*quality*button9.translations: #override\\n\ 1267 + <Visible>: SetQualityState(9)\\n\ 1268 + <Btn1Down>,<Btn1Up>: SetQuality(9) HideQuality()", 1269 + 1270 + "*compress*buttonD.label: Dismiss", 1271 + "*compress*buttonD.translations: #override\\n\ 1272 + <Btn1Down>,<Btn1Up>: HideCompress()", 1273 + 1274 + "*compress*button0.label: 0", 1275 + "*compress*button0.translations: #override\\n\ 1276 + <Visible>: SetCompressState(0)\\n\ 1277 + <Btn1Down>,<Btn1Up>: SetCompress(0) HideCompress()", 1278 + 1279 + "*compress*button1.label: 1", 1280 + "*compress*button1.translations: #override\\n\ 1281 + <Visible>: SetCompressState(1)\\n\ 1282 + <Btn1Down>,<Btn1Up>: SetCompress(1) HideCompress()", 1283 + 1284 + "*compress*button2.label: 2", 1285 + "*compress*button2.translations: #override\\n\ 1286 + <Visible>: SetCompressState(2)\\n\ 1287 + <Btn1Down>,<Btn1Up>: SetCompress(2) HideCompress()", 1288 + 1289 + "*compress*button3.label: 3", 1290 + "*compress*button3.translations: #override\\n\ 1291 + <Visible>: SetCompressState(3)\\n\ 1292 + <Btn1Down>,<Btn1Up>: SetCompress(3) HideCompress()", 1293 + 1294 + "*compress*button4.label: 4", 1295 + "*compress*button4.translations: #override\\n\ 1296 + <Visible>: SetCompressState(4)\\n\ 1297 + <Btn1Down>,<Btn1Up>: SetCompress(4) HideCompress()", 1298 + 1299 + "*compress*button5.label: 5", 1300 + "*compress*button5.translations: #override\\n\ 1301 + <Visible>: SetCompressState(5)\\n\ 1302 + <Btn1Down>,<Btn1Up>: SetCompress(5) HideCompress()", 1303 + 1304 + "*compress*button6.label: 6", 1305 + "*compress*button6.translations: #override\\n\ 1306 + <Visible>: SetCompressState(6)\\n\ 1307 + <Btn1Down>,<Btn1Up>: SetCompress(6) HideCompress()", 1308 + 1309 + "*compress*button7.label: 7", 1310 + "*compress*button7.translations: #override\\n\ 1311 + <Visible>: SetCompressState(7)\\n\ 1312 + <Btn1Down>,<Btn1Up>: SetCompress(7) HideCompress()", 1313 + 1314 + "*compress*button8.label: 8", 1315 + "*compress*button8.translations: #override\\n\ 1316 + <Visible>: SetCompressState(8)\\n\ 1317 + <Btn1Down>,<Btn1Up>: SetCompress(8) HideCompress()", 1318 + 1319 + "*compress*button9.label: 9", 1320 + "*compress*button9.translations: #override\\n\ 1321 + <Visible>: SetCompressState(9)\\n\ 1322 + <Btn1Down>,<Btn1Up>: SetCompress(9) HideCompress()", 1323 + 1324 NULL 1325 }; 1326 1327 @@ -124,7 +697,7 @@ 1328 * from a dialog box. 1329 */ 1330 1331 -char vncServerHost[256]; 1332 +char vncServerHost[1024]; 1333 int vncServerPort = 0; 1334 1335 1336 @@ -135,6 +708,7 @@ 1337 */ 1338 1339 AppData appData; 1340 +AppData appDataNew; 1341 1342 static XtResource appDataResourceList[] = { 1343 {"shareDesktop", "ShareDesktop", XtRBool, sizeof(Bool), 1344 @@ -155,14 +729,44 @@ 1345 {"userLogin", "UserLogin", XtRString, sizeof(String), 1346 XtOffsetOf(AppData, userLogin), XtRImmediate, (XtPointer) 0}, 1347 1348 + {"unixPW", "UnixPW", XtRString, sizeof(String), 1349 + XtOffsetOf(AppData, unixPW), XtRImmediate, (XtPointer) 0}, 1350 + 1351 + {"msLogon", "MSLogon", XtRString, sizeof(String), 1352 + XtOffsetOf(AppData, msLogon), XtRImmediate, (XtPointer) 0}, 1353 + 1354 + {"repeaterUltra", "RepeaterUltra", XtRString, sizeof(String), 1355 + XtOffsetOf(AppData, repeaterUltra), XtRImmediate, (XtPointer) 0}, 1356 + 1357 + {"ultraDSM", "UltraDSM", XtRBool, sizeof(Bool), 1358 + XtOffsetOf(AppData, ultraDSM), XtRImmediate, (XtPointer) False}, 1359 + 1360 + {"acceptPopup", "AcceptPopup", XtRBool, sizeof(Bool), 1361 + XtOffsetOf(AppData, acceptPopup), XtRImmediate, (XtPointer) False}, 1362 + 1363 + {"rfbVersion", "RfbVersion", XtRString, sizeof(String), 1364 + XtOffsetOf(AppData, rfbVersion), XtRImmediate, (XtPointer) 0}, 1365 + 1366 {"passwordDialog", "PasswordDialog", XtRBool, sizeof(Bool), 1367 XtOffsetOf(AppData, passwordDialog), XtRImmediate, (XtPointer) False}, 1368 1369 {"encodings", "Encodings", XtRString, sizeof(String), 1370 XtOffsetOf(AppData, encodingsString), XtRImmediate, (XtPointer) 0}, 1371 1372 - {"useBGR233", "UseBGR233", XtRBool, sizeof(Bool), 1373 - XtOffsetOf(AppData, useBGR233), XtRImmediate, (XtPointer) False}, 1374 + {"useBGR233", "UseBGR233", XtRInt, sizeof(int), 1375 + XtOffsetOf(AppData, useBGR233), XtRImmediate, (XtPointer) 0}, 1376 + 1377 + {"useBGR565", "UseBGR565", XtRBool, sizeof(Bool), 1378 + XtOffsetOf(AppData, useBGR565), XtRImmediate, (XtPointer) False}, 1379 + 1380 + {"useGreyScale", "UseGreyScale", XtRBool, sizeof(Bool), 1381 + XtOffsetOf(AppData, useGreyScale), XtRImmediate, (XtPointer) False}, 1382 + 1383 + {"yCrop", "yCrop", XtRInt, sizeof(int), 1384 + XtOffsetOf(AppData, yCrop), XtRImmediate, (XtPointer) 0}, 1385 + 1386 + {"sbWidth", "sbWidth", XtRInt, sizeof(int), 1387 + XtOffsetOf(AppData, sbWidth), XtRImmediate, (XtPointer) 2}, 1388 1389 {"nColours", "NColours", XtRInt, sizeof(int), 1390 XtOffsetOf(AppData, nColours), XtRImmediate, (XtPointer) 256}, 1391 @@ -179,9 +783,12 @@ 1392 {"requestedDepth", "RequestedDepth", XtRInt, sizeof(int), 1393 XtOffsetOf(AppData, requestedDepth), XtRImmediate, (XtPointer) 0}, 1394 1395 - {"useSharedMemory", "UseSharedMemory", XtRBool, sizeof(Bool), 1396 + {"useShm", "UseShm", XtRBool, sizeof(Bool), 1397 XtOffsetOf(AppData, useShm), XtRImmediate, (XtPointer) True}, 1398 1399 + {"termChat", "TermChat", XtRBool, sizeof(Bool), 1400 + XtOffsetOf(AppData, termChat), XtRImmediate, (XtPointer) False}, 1401 + 1402 {"wmDecorationWidth", "WmDecorationWidth", XtRInt, sizeof(int), 1403 XtOffsetOf(AppData, wmDecorationWidth), XtRImmediate, (XtPointer) 4}, 1404 1405 @@ -191,6 +798,9 @@ 1406 {"popupButtonCount", "PopupButtonCount", XtRInt, sizeof(int), 1407 XtOffsetOf(AppData, popupButtonCount), XtRImmediate, (XtPointer) 0}, 1408 1409 + {"popupButtonBreak", "PopupButtonBreak", XtRInt, sizeof(int), 1410 + XtOffsetOf(AppData, popupButtonBreak), XtRImmediate, (XtPointer) 0}, 1411 + 1412 {"debug", "Debug", XtRBool, sizeof(Bool), 1413 XtOffsetOf(AppData, debug), XtRImmediate, (XtPointer) False}, 1414 1415 @@ -206,11 +816,13 @@ 1416 {"bumpScrollPixels", "BumpScrollPixels", XtRInt, sizeof(int), 1417 XtOffsetOf(AppData, bumpScrollPixels), XtRImmediate, (XtPointer) 20}, 1418 1419 + /* hardwired compress -1 vs . 7 */ 1420 {"compressLevel", "CompressionLevel", XtRInt, sizeof(int), 1421 XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) -1}, 1422 1423 + /* hardwired quality was 6 */ 1424 {"qualityLevel", "QualityLevel", XtRInt, sizeof(int), 1425 - XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) 6}, 1426 + XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) -1}, 1427 1428 {"enableJPEG", "EnableJPEG", XtRBool, sizeof(Bool), 1429 XtOffsetOf(AppData, enableJPEG), XtRImmediate, (XtPointer) True}, 1430 @@ -218,14 +830,97 @@ 1431 {"useRemoteCursor", "UseRemoteCursor", XtRBool, sizeof(Bool), 1432 XtOffsetOf(AppData, useRemoteCursor), XtRImmediate, (XtPointer) True}, 1433 1434 + {"useCursorAlpha", "UseCursorAlpha", XtRBool, sizeof(Bool), 1435 + XtOffsetOf(AppData, useCursorAlpha), XtRImmediate, (XtPointer) False}, 1436 + 1437 + {"useRawLocal", "UseRawLocal", XtRBool, sizeof(Bool), 1438 + XtOffsetOf(AppData, useRawLocal), XtRImmediate, (XtPointer) False}, 1439 + 1440 + {"notty", "NoTty", XtRBool, sizeof(Bool), 1441 + XtOffsetOf(AppData, notty), XtRImmediate, (XtPointer) False}, 1442 + 1443 {"useX11Cursor", "UseX11Cursor", XtRBool, sizeof(Bool), 1444 XtOffsetOf(AppData, useX11Cursor), XtRImmediate, (XtPointer) False}, 1445 1446 + {"useBell", "UseBell", XtRBool, sizeof(Bool), 1447 + XtOffsetOf(AppData, useBell), XtRImmediate, (XtPointer) True}, 1448 + 1449 {"grabKeyboard", "GrabKeyboard", XtRBool, sizeof(Bool), 1450 - XtOffsetOf(AppData, grabKeyboard), XtRImmediate, (XtPointer) False}, 1451 + XtOffsetOf(AppData, grabKeyboard), XtRImmediate, (XtPointer) True}, 1452 1453 {"autoPass", "AutoPass", XtRBool, sizeof(Bool), 1454 - XtOffsetOf(AppData, autoPass), XtRImmediate, (XtPointer) False} 1455 + XtOffsetOf(AppData, autoPass), XtRImmediate, (XtPointer) False}, 1456 + 1457 + {"grabAll", "GrabAll", XtRBool, sizeof(Bool), 1458 + XtOffsetOf(AppData, grabAll), XtRImmediate, (XtPointer) False}, 1459 + 1460 + {"useXserverBackingStore", "UseXserverBackingStore", XtRBool, sizeof(Bool), 1461 + XtOffsetOf(AppData, useXserverBackingStore), XtRImmediate, (XtPointer) False}, 1462 + 1463 + {"overrideRedir", "OverrideRedir", XtRBool, sizeof(Bool), 1464 + XtOffsetOf(AppData, overrideRedir), XtRImmediate, (XtPointer) True}, 1465 + 1466 + {"serverInput", "ServerInput", XtRBool, sizeof(Bool), 1467 + XtOffsetOf(AppData, serverInput), XtRImmediate, (XtPointer) True}, 1468 + 1469 + {"singleWindow", "SingleWindow", XtRBool, sizeof(Bool), 1470 + XtOffsetOf(AppData, singleWindow), XtRImmediate, (XtPointer) False}, 1471 + 1472 + {"serverScale", "ServerScale", XtRInt, sizeof(int), 1473 + XtOffsetOf(AppData, serverScale), XtRImmediate, (XtPointer) 1}, 1474 + 1475 + {"chatActive", "ChatActive", XtRBool, sizeof(Bool), 1476 + XtOffsetOf(AppData, chatActive), XtRImmediate, (XtPointer) False}, 1477 + 1478 + {"chatOnly", "ChatOnly", XtRBool, sizeof(Bool), 1479 + XtOffsetOf(AppData, chatOnly), XtRImmediate, (XtPointer) False}, 1480 + 1481 + {"fileActive", "FileActive", XtRBool, sizeof(Bool), 1482 + XtOffsetOf(AppData, fileActive), XtRImmediate, (XtPointer) False}, 1483 + 1484 + {"popupFix", "PopupFix", XtRBool, sizeof(Bool), 1485 + XtOffsetOf(AppData, popupFix), XtRImmediate, (XtPointer) False}, 1486 + 1487 + {"scale", "Scale", XtRString, sizeof(String), 1488 + XtOffsetOf(AppData, scale), XtRImmediate, (XtPointer) 0}, 1489 + 1490 + {"pipelineUpdates", "PipelineUpdates", XtRBool, sizeof(Bool), 1491 + XtOffsetOf(AppData, pipelineUpdates), XtRImmediate, (XtPointer) 1492 +#ifdef TURBOVNC 1493 + True}, 1494 +#else 1495 +#if 0 1496 + False}, 1497 +#else 1498 + True}, 1499 +#endif 1500 +#endif 1501 + 1502 + {"noipv4", "noipv4", XtRBool, sizeof(Bool), 1503 + XtOffsetOf(AppData, noipv4), XtRImmediate, (XtPointer) False}, 1504 + 1505 + {"noipv6", "noipv6", XtRBool, sizeof(Bool), 1506 + XtOffsetOf(AppData, noipv6), XtRImmediate, (XtPointer) False}, 1507 + 1508 + {"sendClipboard", "SendClipboard", XtRBool, sizeof(Bool), 1509 + XtOffsetOf(AppData, sendClipboard), XtRImmediate, (XtPointer) False}, 1510 + 1511 + {"sendAlways", "SendAlways", XtRBool, sizeof(Bool), 1512 + XtOffsetOf(AppData, sendAlways), XtRImmediate, (XtPointer) False}, 1513 + 1514 + {"recvText", "RecvText", XtRString, sizeof(String), 1515 + XtOffsetOf(AppData, recvText), XtRImmediate, (XtPointer) 0}, 1516 + 1517 + {"appShare", "AppShare", XtRBool, sizeof(Bool), 1518 + XtOffsetOf(AppData, appShare), XtRImmediate, (XtPointer) False}, 1519 + 1520 + {"escapeKeys", "EscapeKeys", XtRString, sizeof(String), 1521 + XtOffsetOf(AppData, escapeKeys), XtRImmediate, (XtPointer) 0}, 1522 + 1523 + {"escapeActive", "EscapeActive", XtRBool, sizeof(Bool), 1524 + XtOffsetOf(AppData, escapeActive), XtRImmediate, (XtPointer) False} 1525 + 1526 + /* check commas */ 1527 }; 1528 1529 1530 @@ -242,8 +937,29 @@ 1531 {"-noraiseonbeep", "*raiseOnBeep", XrmoptionNoArg, "False"}, 1532 {"-passwd", "*passwordFile", XrmoptionSepArg, 0}, 1533 {"-user", "*userLogin", XrmoptionSepArg, 0}, 1534 + {"-unixpw", "*unixPW", XrmoptionSepArg, 0}, 1535 + {"-mslogon", "*msLogon", XrmoptionSepArg, 0}, 1536 + {"-repeater", "*repeaterUltra", XrmoptionSepArg, 0}, 1537 + {"-ultradsm", "*ultraDSM", XrmoptionNoArg, "True"}, 1538 + {"-acceptpopup", "*acceptPopup", XrmoptionNoArg, "True"}, 1539 + {"-acceptpopupsc", "*acceptPopup", XrmoptionNoArg, "True"}, 1540 + {"-rfbversion", "*rfbVersion", XrmoptionSepArg, 0}, 1541 {"-encodings", "*encodings", XrmoptionSepArg, 0}, 1542 - {"-bgr233", "*useBGR233", XrmoptionNoArg, "True"}, 1543 + {"-bgr233", "*useBGR233", XrmoptionNoArg, "256"}, 1544 + {"-use64", "*useBGR233", XrmoptionNoArg, "64"}, 1545 + {"-bgr222", "*useBGR233", XrmoptionNoArg, "64"}, 1546 + {"-use8", "*useBGR233", XrmoptionNoArg, "8"}, 1547 + {"-bgr111", "*useBGR233", XrmoptionNoArg, "8"}, 1548 + {"-16bpp", "*useBGR565", XrmoptionNoArg, "True"}, 1549 + {"-bgr565", "*useBGR565", XrmoptionNoArg, "True"}, 1550 + {"-grey", "*useGreyScale", XrmoptionNoArg, "True"}, 1551 + {"-gray", "*useGreyScale", XrmoptionNoArg, "True"}, 1552 + {"-sbwidth", "*sbwidth", XrmoptionSepArg, 0}, 1553 + {"-env", "*envDummy", XrmoptionSepArg, 0}, 1554 + {"-ycrop", "*yCrop", XrmoptionSepArg, 0}, 1555 + {"-rawlocal", "*useRawLocal", XrmoptionNoArg, "True"}, 1556 + {"-notty", "*notty", XrmoptionNoArg, "True"}, 1557 + {"-alpha", "*useCursorAlpha", XrmoptionNoArg, "True"}, 1558 {"-owncmap", "*forceOwnCmap", XrmoptionNoArg, "True"}, 1559 {"-truecolor", "*forceTrueColour", XrmoptionNoArg, "True"}, 1560 {"-truecolour", "*forceTrueColour", XrmoptionNoArg, "True"}, 1561 @@ -253,8 +969,30 @@ 1562 {"-nojpeg", "*enableJPEG", XrmoptionNoArg, "False"}, 1563 {"-nocursorshape", "*useRemoteCursor", XrmoptionNoArg, "False"}, 1564 {"-x11cursor", "*useX11Cursor", XrmoptionNoArg, "True"}, 1565 - {"-autopass", "*autoPass", XrmoptionNoArg, "True"} 1566 - 1567 + {"-nobell", "*useBell", XrmoptionNoArg, "False"}, 1568 + {"-autopass", "*autoPass", XrmoptionNoArg, "True"}, 1569 + {"-graball", "*grabAll", XrmoptionNoArg, "True"}, 1570 + {"-grabkbd", "*grabKeyboard", XrmoptionNoArg, "True"}, 1571 + {"-nograbkbd", "*grabKeyboard", XrmoptionNoArg, "False"}, 1572 + {"-grabkeyboard", "*grabKeyboard", XrmoptionNoArg, "True"}, 1573 + {"-nograbkeyboard","*grabKeyboard", XrmoptionNoArg, "False"}, 1574 + {"-nooverride", "*overrideRedir", XrmoptionNoArg, "False"}, 1575 + {"-bs", "*useXserverBackingStore", XrmoptionNoArg, "True"}, 1576 + {"-nobs", "*useXserverBackingStore", XrmoptionNoArg, "False"}, 1577 + {"-popupfix", "*popupFix", XrmoptionNoArg, "True"}, 1578 + {"-noshm", "*useShm", XrmoptionNoArg, "False"}, 1579 + {"-termchat", "*termChat", XrmoptionNoArg, "True"}, 1580 + {"-chatonly", "*chatOnly", XrmoptionNoArg, "True"}, 1581 + {"-scale", "*scale", XrmoptionSepArg, 0}, 1582 + {"-appshare", "*appShare", XrmoptionNoArg, "True"}, 1583 + {"-escape", "*escapeKeys", XrmoptionSepArg, 0}, 1584 + {"-sendclipboard", "*sendClipboard", XrmoptionNoArg, "True"}, 1585 + {"-sendalways", "*sendAlways", XrmoptionNoArg, "True"}, 1586 + {"-recvtext", "*recvText", XrmoptionSepArg, 0}, 1587 + {"-pipeline", "*pipelineUpdates", XrmoptionNoArg, "True"}, 1588 + {"-nopipeline", "*pipelineUpdates", XrmoptionNoArg, "False"}, 1589 + {"-noipv4", "*noipv4", XrmoptionNoArg, "True"}, 1590 + {"-noipv6", "*noipv6", XrmoptionNoArg, "True"} 1591 }; 1592 1593 int numCmdLineOptions = XtNumber(cmdLineOptions); 1594 @@ -267,16 +1005,100 @@ 1595 static XtActionsRec actions[] = { 1596 {"SendRFBEvent", SendRFBEvent}, 1597 {"ShowPopup", ShowPopup}, 1598 + {"Noop", Noop}, 1599 {"HidePopup", HidePopup}, 1600 + {"HideScaleN", HideScaleN}, 1601 + {"HideTurboVNC", HideTurboVNC}, 1602 + {"HideQuality", HideQuality}, 1603 + {"HideCompress", HideCompress}, 1604 {"ToggleFullScreen", ToggleFullScreen}, 1605 + {"JumpLeft", JumpLeft}, 1606 + {"JumpRight", JumpRight}, 1607 + {"JumpUp", JumpUp}, 1608 + {"JumpDown", JumpDown}, 1609 {"SetFullScreenState", SetFullScreenState}, 1610 {"SelectionFromVNC", SelectionFromVNC}, 1611 {"SelectionToVNC", SelectionToVNC}, 1612 {"ServerDialogDone", ServerDialogDone}, 1613 + {"UserDialogDone", UserDialogDone}, 1614 + {"YCropDialogDone", YCropDialogDone}, 1615 + {"ScbarDialogDone", ScbarDialogDone}, 1616 + {"ScaleNDialogDone", ScaleNDialogDone}, 1617 + {"ScaleDialogDone", ScaleDialogDone}, 1618 {"PasswordDialogDone", PasswordDialogDone}, 1619 {"Pause", Pause}, 1620 {"RunCommand", RunCommand}, 1621 {"Quit", Quit}, 1622 + {"HideChat", HideChat}, 1623 + {"Toggle8bpp", Toggle8bpp}, 1624 + {"Toggle16bpp", Toggle16bpp}, 1625 + {"ToggleFullColor", ToggleFullColor}, 1626 + {"Toggle256Colors", Toggle256Colors}, 1627 + {"Toggle64Colors", Toggle64Colors}, 1628 + {"Toggle8Colors", Toggle8Colors}, 1629 + {"ToggleGreyScale", ToggleGreyScale}, 1630 + {"ToggleTightZRLE", ToggleTightZRLE}, 1631 + {"ToggleTightHextile", ToggleTightHextile}, 1632 + {"ToggleZRLEZYWRLE", ToggleZRLEZYWRLE}, 1633 + {"ToggleViewOnly", ToggleViewOnly}, 1634 + {"ToggleJPEG", ToggleJPEG}, 1635 + {"ToggleCursorShape", ToggleCursorShape}, 1636 + {"ToggleCursorAlpha", ToggleCursorAlpha}, 1637 + {"ToggleX11Cursor", ToggleX11Cursor}, 1638 + {"ToggleBell", ToggleBell}, 1639 + {"ToggleRawLocal", ToggleRawLocal}, 1640 + {"ToggleServerInput", ToggleServerInput}, 1641 + {"TogglePipelineUpdates", TogglePipelineUpdates}, 1642 + {"ToggleSendClipboard", ToggleSendClipboard}, 1643 + {"ToggleSendAlways", ToggleSendAlways}, 1644 + {"ToggleSingleWindow", ToggleSingleWindow}, 1645 + {"ToggleTextChat", ToggleTextChat}, 1646 + {"ToggleFileXfer", ToggleFileXfer}, 1647 + {"ToggleXGrab", ToggleXGrab}, 1648 + {"DoServerScale", DoServerScale}, 1649 + {"SetScale", SetScale}, 1650 + {"SetYCrop", SetYCrop}, 1651 + {"SetScbar", SetScbar}, 1652 + {"ShowScaleN", ShowScaleN}, 1653 + {"ShowTurboVNC", ShowTurboVNC}, 1654 + {"ShowQuality", ShowQuality}, 1655 + {"ShowCompress", ShowCompress}, 1656 + {"SetScaleN", SetScaleN}, 1657 + {"SetTurboVNC", SetTurboVNC}, 1658 + {"SetQuality", SetQuality}, 1659 + {"SetCompress", SetCompress}, 1660 + {"Set8bppState", Set8bppState}, 1661 + {"Set16bppState", Set16bppState}, 1662 + {"SetFullColorState", SetFullColorState}, 1663 + {"Set256ColorsState", Set256ColorsState}, 1664 + {"Set64ColorsState", Set64ColorsState}, 1665 + {"Set8ColorsState", Set8ColorsState}, 1666 + {"SetGreyScaleState", SetGreyScaleState}, 1667 + {"SetZRLEState", SetZRLEState}, 1668 + {"SetHextileState", SetHextileState}, 1669 + {"SetZYWRLEState", SetZYWRLEState}, 1670 + {"SetNOJPEGState", SetNOJPEGState}, 1671 + {"SetScaleNState", SetScaleNState}, 1672 + {"SetQualityState", SetQualityState}, 1673 + {"SetCompressState", SetCompressState}, 1674 + {"SetViewOnlyState", SetViewOnlyState}, 1675 + {"SetCursorShapeState", SetCursorShapeState}, 1676 + {"SetCursorAlphaState", SetCursorAlphaState}, 1677 + {"SetX11CursorState", SetX11CursorState}, 1678 + {"SetBellState", SetBellState}, 1679 + {"SetRawLocalState", SetRawLocalState}, 1680 + {"SetServerInputState", SetServerInputState}, 1681 + {"SetPipelineUpdates", SetPipelineUpdates}, 1682 + {"SetSendClipboard", SetSendClipboard}, 1683 + {"SetSendAlways", SetSendAlways}, 1684 + {"SetSingleWindowState", SetSingleWindowState}, 1685 + {"SetTextChatState", SetTextChatState}, 1686 + {"SetFileXferState", SetFileXferState}, 1687 + {"SetXGrabState", SetXGrabState}, 1688 + {"SetEscapeKeysState", SetEscapeKeysState}, 1689 + {"ToggleEscapeActive", ToggleEscapeActive}, 1690 + {"EscapeDialogDone", EscapeDialogDone}, 1691 + {"SetEscapeKeys", SetEscapeKeys} 1692 }; 1693 1694 1695 @@ -302,11 +1124,14 @@ 1696 void 1697 usage(void) 1698 { 1699 - fprintf(stderr, 1700 - "TightVNC viewer version 1.3dev7\n" 1701 + fprintf(stdout, 1702 + "SSVNC Viewer (based on TightVNC viewer version 1.3.9)\n" 1703 "\n" 1704 "Usage: %s [<OPTIONS>] [<HOST>][:<DISPLAY#>]\n" 1705 " %s [<OPTIONS>] [<HOST>][::<PORT#>]\n" 1706 + " %s [<OPTIONS>] exec=[CMD ARGS...]\n" 1707 + " %s [<OPTIONS>] fd=n\n" 1708 + " %s [<OPTIONS>] /path/to/unix/socket\n" 1709 " %s [<OPTIONS>] -listen [<DISPLAY#>]\n" 1710 " %s -help\n" 1711 "\n" 1712 @@ -319,7 +1144,7 @@ 1713 " -noraiseonbeep\n" 1714 " -passwd <PASSWD-FILENAME> (standard VNC authentication)\n" 1715 " -user <USERNAME> (Unix login authentication)\n" 1716 - " -encodings <ENCODING-LIST> (e.g. \"tight copyrect\")\n" 1717 + " -encodings <ENCODING-LIST> (e.g. \"tight,copyrect\")\n" 1718 " -bgr233\n" 1719 " -owncmap\n" 1720 " -truecolour\n" 1721 @@ -332,10 +1157,390 @@ 1722 " -autopass\n" 1723 "\n" 1724 "Option names may be abbreviated, e.g. -bgr instead of -bgr233.\n" 1725 - "See the manual page for more information." 1726 - "\n", programName, programName, programName, programName); 1727 + "See the manual page for more information.\n" 1728 + "\n" 1729 + "\n" 1730 + "Enhanced TightVNC viewer (SSVNC) options:\n" 1731 + "\n" 1732 + " URL http://www.karlrunge.com/x11vnc/ssvnc.html\n" 1733 + "\n" 1734 + " Note: ZRLE and ZYWRLE encodings are now supported.\n" 1735 + "\n" 1736 + " Note: F9 is shortcut to Toggle FullScreen mode.\n" 1737 + "\n" 1738 + " Note: In -listen mode set the env var. SSVNC_MULTIPLE_LISTEN=1\n" 1739 + " to allow more than one incoming VNC server at a time.\n" 1740 + " This is the same as -multilisten described below. Set\n" 1741 + " SSVNC_MULTIPLE_LISTEN=MAX:n to allow no more than \"n\"\n" 1742 + " simultaneous reverse connections.\n" 1743 + "\n" 1744 + " Note: If the host:port is specified as \"exec=command args...\"\n" 1745 + " then instead of making a TCP/IP socket connection to the\n" 1746 + " remote VNC server, \"command args...\" is executed and the\n" 1747 + " viewer is attached to its stdio. This enables tunnelling\n" 1748 + " established via an external command, e.g. an stunnel(8)\n" 1749 + " that does not involve a listening socket. This mode does\n" 1750 + " not work for -listen reverse connections.\n" 1751 + "\n" 1752 + " If the host:port is specified as \"fd=n\" then it is assumed\n" 1753 + " n is an already opened file descriptor to the socket. (i.e\n" 1754 + " the parent did fork+exec)\n" 1755 + "\n" 1756 + " If the host:port contains a '/' it is interpreted as a\n" 1757 + " unix-domain socket (AF_LOCAL insead of AF_INET)\n" 1758 + "\n" 1759 + " -multilisten As in -listen (reverse connection listening) except\n" 1760 + " allow more than one incoming VNC server to be connected\n" 1761 + " at a time. The default for -listen of only one at a\n" 1762 + " time tries to play it safe by not allowing anyone on\n" 1763 + " the network to put (many) desktops on your screen over\n" 1764 + " a long window of time. Use -multilisten for no limit.\n" 1765 + "\n" 1766 + " -acceptpopup In -listen (reverse connection listening) mode when\n" 1767 + " a reverse VNC connection comes in show a popup asking\n" 1768 + " whether to Accept or Reject the connection. The IP\n" 1769 + " address of the connecting host is shown. Same as\n" 1770 + " setting the env. var. SSVNC_ACCEPT_POPUP=1.\n" 1771 + "\n" 1772 + " -acceptpopupsc As in -acceptpopup except assume UltraVNC Single\n" 1773 + " Click (SC) server. Retrieve User and ComputerName\n" 1774 + " info from UltraVNC Server and display in the Popup.\n" 1775 + "\n" 1776 + " -use64 In -bgr233 mode, use 64 colors instead of 256.\n" 1777 + " -bgr222 Same as -use64.\n" 1778 + "\n" 1779 + " -use8 In -bgr233 mode, use 8 colors instead of 256.\n" 1780 + " -bgr111 Same as -use8.\n" 1781 + "\n" 1782 + " -16bpp If the vnc viewer X display is depth 24 at 32bpp\n" 1783 + " request a 16bpp format from the VNC server to cut\n" 1784 + " network traffic by up to 2X, then tranlate the\n" 1785 + " pixels to 32bpp locally.\n" 1786 + " -bgr565 Same as -16bpp.\n" 1787 + "\n" 1788 + " -grey Use a grey scale for the 16- and 8-bpp modes.\n" 1789 + "\n" 1790 + " -alpha Use alphablending transparency for local cursors\n" 1791 + " requires: x11vnc server, both client and server\n" 1792 + " must be 32bpp and same endianness.\n" 1793 + "\n" 1794 + " -scale str Scale the desktop locally. The string \"str\" can\n" 1795 + " a floating point ratio, e.g. \"0.9\", or a fraction,\n" 1796 + " e.g. \"3/4\", or WxH, e.g. 1280x1024. Use \"fit\"\n" 1797 + " to fit in the current screen size. Use \"auto\" to\n" 1798 + " fit in the window size. \"str\" can also be set by\n" 1799 + " the env. var. SSVNC_SCALE.\n" 1800 + "\n" 1801 + " If you observe mouse trail painting errors, enable\n" 1802 + " X11 Cursor mode (either via Popup or -x11cursor.)\n" 1803 + "\n" 1804 + " Note that scaling is done in software and so can be\n" 1805 + " slow and requires more memory. Some speedup Tips:\n" 1806 + "\n" 1807 + " ZRLE is faster than Tight in this mode. When\n" 1808 + " scaling is first detected, the encoding will\n" 1809 + " be automatically switched to ZRLE. Use the\n" 1810 + " Popup menu if you want to go back to Tight.\n" 1811 + " Set SSVNC_PRESERVE_ENCODING=1 to disable this.\n" 1812 + "\n" 1813 + " Use a solid background on the remote side.\n" 1814 + " (e.g. manually or via x11vnc -solid ...)\n" 1815 + "\n" 1816 + " If the remote server is x11vnc, try client\n" 1817 + " side caching: x11vnc -ncache 10 ...\n" 1818 + "\n" 1819 + " -ycrop n Only show the top n rows of the framebuffer. For\n" 1820 + " use with x11vnc -ncache client caching option\n" 1821 + " to help \"hide\" the pixel cache region.\n" 1822 + " Use a negative value (e.g. -1) for autodetection.\n" 1823 + " Autodetection will always take place if the remote\n" 1824 + " fb height is more than 2 times the width.\n" 1825 + "\n" 1826 + " -sbwidth n Scrollbar width for x11vnc -ncache mode (-ycrop),\n" 1827 + " default is very narrow: 2 pixels, it is narrow to\n" 1828 + " avoid distraction in -ycrop mode.\n" 1829 + "\n" 1830 + " -nobell Disable bell.\n" 1831 + "\n" 1832 + " -rawlocal Prefer raw encoding for localhost, default is\n" 1833 + " no, i.e. assumes you have a SSH tunnel instead.\n" 1834 + "\n" 1835 + " -notty Try to avoid using the terminal for interactive\n" 1836 + " responses: use windows for messages and prompting\n" 1837 + " instead. Messages will also be printed to terminal.\n" 1838 + "\n" 1839 + " -sendclipboard Send the X CLIPBOARD selection (i.e. Ctrl+C,\n" 1840 + " Ctrl+V) instead of the X PRIMARY selection (mouse\n" 1841 + " select and middle button paste.)\n" 1842 + "\n" 1843 + " -sendalways Whenever the mouse enters the VNC viewer main\n" 1844 + " window, send the selection to the VNC server even if\n" 1845 + " it has not changed. This is like the Xt resource\n" 1846 + " translation SelectionToVNC(always)\n" 1847 + "\n" 1848 + " -recvtext str When cut text is received from the VNC server,\n" 1849 + " ssvncviewer will set both the X PRIMARY and the\n" 1850 + " X CLIPBOARD local selections. To control which\n" 1851 + " is set, specify 'str' as 'primary', 'clipboard',\n" 1852 + " or 'both' (the default.)\n" 1853 + "\n" 1854 + " -graball Grab the entire X server when in fullscreen mode,\n" 1855 + " needed by some old window managers like fvwm2.\n" 1856 + "\n" 1857 + " -popupfix Warp the popup back to the pointer position,\n" 1858 + " needed by some old window managers like fvwm2.\n" 1859 + " -sendclipboard Send the X CLIPBOARD selection (i.e. Ctrl+C,\n" 1860 + " Ctrl+V) instead of the X PRIMARY selection (mouse\n" 1861 + " select and middle button paste.)\n" 1862 + "\n" 1863 + " -sendalways Whenever the mouse enters the VNC viewer main\n" 1864 + " window, send the selection to the VNC server even if\n" 1865 + " it has not changed. This is like the Xt resource\n" 1866 + " translation SelectionToVNC(always)\n" 1867 + "\n" 1868 + " -recvtext str When cut text is received from the VNC server,\n" 1869 + " ssvncviewer will set both the X PRIMARY and the\n" 1870 + " X CLIPBOARD local selections. To control which\n" 1871 + " is set, specify 'str' as 'primary', 'clipboard',\n" 1872 + " or 'both' (the default.)\n" 1873 + "\n" 1874 + " -graball Grab the entire X server when in fullscreen mode,\n" 1875 + " needed by some old window managers like fvwm2.\n" 1876 + "\n" 1877 + " -popupfix Warp the popup back to the pointer position,\n" 1878 + " needed by some old window managers like fvwm2.\n" 1879 + "\n" 1880 + " -grabkbd Grab the X keyboard when in fullscreen mode,\n" 1881 + " needed by some window managers. Same as -grabkeyboard.\n" 1882 + " -grabkbd is the default, use -nograbkbd to disable.\n" 1883 + "\n" 1884 + " -bs, -nobs Whether or not to use X server Backingstore for the\n" 1885 + " main viewer window. The default is to not, mainly\n" 1886 + " because most Linux, etc, systems X servers disable\n" 1887 + " *all* Backingstore by default. To re-enable it put\n" 1888 + "\n" 1889 + " Option \"Backingstore\"\n" 1890 + "\n" 1891 + " in the Device section of /etc/X11/xorg.conf.\n" 1892 + " In -bs mode with no X server backingstore, whenever an\n" 1893 + " area of the screen is re-exposed it must go out to the\n" 1894 + " VNC server to retrieve the pixels. This is too slow.\n" 1895 + "\n" 1896 + " In -nobs mode, memory is allocated by the viewer to\n" 1897 + " provide its own backing of the main viewer window. This\n" 1898 + " actually makes some activities faster (changes in large\n" 1899 + " regions) but can appear to \"flash\" too much.\n" 1900 + "\n" 1901 + " -noshm Disable use of MIT shared memory extension (not recommended)\n" 1902 + "\n" 1903 + " -termchat Do the UltraVNC chat in the terminal vncviewer is in\n" 1904 + " instead of in an independent window.\n" 1905 + "\n" 1906 + " -unixpw str Useful for logging into x11vnc in -unixpw mode. \"str\" is a\n" 1907 + " string that allows many ways to enter the Unix Username\n" 1908 + " and Unix Password. These characters: username, newline,\n" 1909 + " password, newline are sent to the VNC server after any VNC\n" 1910 + " authentication has taken place. Under x11vnc they are\n" 1911 + " used for the -unixpw login. Other VNC servers could do\n" 1912 + " something similar.\n" 1913 + "\n" 1914 + " You can also indicate \"str\" via the environment\n" 1915 + " variable SSVNC_UNIXPW.\n" 1916 + "\n" 1917 + " Note that the Escape key is actually sent first to tell\n" 1918 + " x11vnc to not echo the Unix Username back to the VNC\n" 1919 + " viewer. Set SSVNC_UNIXPW_NOESC=1 to override this.\n" 1920 + "\n" 1921 + " If str is \".\", then you are prompted at the command line\n" 1922 + " for the username and password in the normal way. If str is\n" 1923 + " \"-\" the stdin is read via getpass(3) for username@password.\n" 1924 + " Otherwise if str is a file, it is opened and the first line\n" 1925 + " read is taken as the Unix username and the 2nd as the\n" 1926 + " password. If str prefixed by \"rm:\" the file is removed\n" 1927 + " after reading. Otherwise, if str has a \"@\" character,\n" 1928 + " it is taken as username@password. Otherwise, the program\n" 1929 + " exits with an error. Got all that?\n" 1930 + "\n" 1931 + " -repeater str This is for use with UltraVNC repeater proxy described\n" 1932 + " here: http://www.uvnc.com/addons/repeater.html. The \"str\"\n" 1933 + " is the ID string to be sent to the repeater. E.g. ID:1234\n" 1934 + " It can also be the hostname and port or display of the VNC\n" 1935 + " server, e.g. 12.34.56.78:0 or snoopy.com:1. Note that when\n" 1936 + " using -repeater, the host:dpy on the cmdline is the repeater\n" 1937 + " server, NOT the VNC server. The repeater will connect you.\n" 1938 + "\n" 1939 + " Example: vncviewer ... -repeater ID:3333 repeat.host:5900\n" 1940 + " Example: vncviewer ... -repeater vhost:0 repeat.host:5900\n" 1941 + "\n" 1942 + " Use, e.g., '-repeater SCIII=ID:3210' if the repeater is a\n" 1943 + " Single Click III (SSL) repeater (repeater_SSL.exe) and you\n" 1944 + " are passing the SSL part of the connection through stunnel,\n" 1945 + " socat, etc. This way the magic UltraVNC string 'testB'\n" 1946 + " needed to work with the repeater is sent to it.\n" 1947 + "\n" 1948 + " -rfbversion str Set the advertised RFB version. E.g.: -rfbversion 3.6\n" 1949 + " For some servers, e.g. UltraVNC this needs to be done.\n" 1950 + "\n" 1951 + " -ultradsm UltraVNC has symmetric private key encryption DSM plugins:\n" 1952 + " http://www.uvnc.com/features/encryption.html. It is assumed\n" 1953 + " you are using a unix program (e.g. our ultravnc_dsm_helper)\n" 1954 + " to encrypt and decrypt the UltraVNC DSM stream. IN ADDITION\n" 1955 + " TO THAT supply -ultradsm to tell THIS viewer to modify the\n" 1956 + " RFB data sent so as to work with the UltraVNC Server. For\n" 1957 + " some reason, each RFB msg type must be sent twice under DSM.\n" 1958 + "\n" 1959 + " -mslogon user Use Windows MS Logon to an UltraVNC server. Supply the\n" 1960 + " username or \"1\" to be prompted. The default is to\n" 1961 + " autodetect the UltraVNC MS Logon server and prompt for\n" 1962 + " the username and password.\n" 1963 + "\n" 1964 + " IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman\n" 1965 + " exchange is very weak and can be brute forced to recover\n" 1966 + " your username and password in a few seconds of CPU time.\n" 1967 + " To be safe, be sure to use an additional encrypted tunnel\n" 1968 + " (e.g. SSL or SSH) for the entire VNC session.\n" 1969 + "\n" 1970 + " -chatonly Try to be a client that only does UltraVNC text chat. This\n" 1971 + " mode is used by x11vnc to present a chat window on the\n" 1972 + " physical X11 console (i.e. chat with the person at the\n" 1973 + " display).\n" 1974 + "\n" 1975 + " -env VAR=VALUE To save writing a shell script to set environment variables,\n" 1976 + " specify as many as you need on the command line. For\n" 1977 + " example, -env SSVNC_MULTIPLE_LISTEN=MAX:5 -env EDITOR=vi\n" 1978 + "\n" 1979 + " -noipv6 Disable all IPv6 sockets. Same as VNCVIEWER_NO_IPV6=1.\n" 1980 + "\n" 1981 + " -noipv4 Disable all IPv4 sockets. Same as VNCVIEWER_NO_IPV4=1.\n" 1982 + "\n" 1983 + " -printres Print out the Ssvnc X resources (appdefaults) and then exit\n" 1984 + " You can save them to a file and customize them (e.g. the\n" 1985 + " keybindings and Popup menu) Then point to the file via\n" 1986 + " XENVIRONMENT or XAPPLRESDIR.\n" 1987 + "\n" 1988 + " -pipeline Like TurboVNC, request the next framebuffer update as soon\n" 1989 + " as possible instead of waiting until the end of the current\n" 1990 + " framebuffer update coming in. Helps 'pipeline' the updates.\n" 1991 + " This is currently the default, use -nopipeline to disable.\n" 1992 + "\n" 1993 + " -appshare Enable features for use with x11vnc's -appshare mode where\n" 1994 + " instead of sharing the full desktop only the application's\n" 1995 + " windows are shared. Viewer multilisten mode is used to\n" 1996 + " create the multiple windows: -multilisten is implied.\n" 1997 + " See 'x11vnc -appshare -help' more information on the mode.\n" 1998 + "\n" 1999 + " Features enabled in the viewer under -appshare are:\n" 2000 + " Minimum extra text in the title, auto -ycrop is disabled,\n" 2001 + " x11vnc -remote_prefix X11VNC_APPSHARE_CMD: message channel,\n" 2002 + " x11vnc initial window position hints. See also Escape Keys\n" 2003 + " below for additional key and mouse bindings.\n" 2004 + "\n" 2005 + " -escape str This sets the 'Escape Keys' modifier sequence and enables\n" 2006 + " escape keys mode. When the modifier keys escape sequence\n" 2007 + " is held down, the next keystroke is interpreted locally\n" 2008 + " to perform a special action instead of being sent to the\n" 2009 + " remote VNC server.\n" 2010 + "\n" 2011 + " Use '-escape default' for the default modifier sequence.\n" 2012 + " (Unix: Alt_L,Super_L and MacOSX: Control_L,Meta_L)\n" 2013 + "\n" 2014 + " Here are the 'Escape Keys: Help+Set' instructions from the Popup Menu:\n" 2015 + "\n" 2016 + " Escape Keys: Enter a comma separated list of modifier keys to be the\n" 2017 + " 'escape sequence'. When these keys are held down, the next keystroke is\n" 2018 + " interpreted locally to invoke a special action instead of being sent to\n" 2019 + " the remote VNC server. In other words, a set of 'Hot Keys'.\n" 2020 + " \n" 2021 + " To enable or disable this, click on 'Escape Keys: Toggle' in the Popup.\n" 2022 + " \n" 2023 + " Here is the list of hot-key mappings to special actions:\n" 2024 + " \n" 2025 + " r: refresh desktop b: toggle bell c: toggle full-color\n" 2026 + " f: file transfer x: x11cursor z: toggle Tight/ZRLE\n" 2027 + " l: full screen g: graball e: escape keys dialog\n" 2028 + " s: scale dialog +: scale up (=) -: scale down (_)\n" 2029 + " t: text chat a: alphablend cursor\n" 2030 + " V: toggle viewonly Q: quit viewer 1 2 3 4 5 6: UltraVNC scale 1/n\n" 2031 + " \n" 2032 + " Arrow keys: pan the viewport about 10%% for each keypress.\n" 2033 + " PageUp / PageDown: pan the viewport by a screenful vertically.\n" 2034 + " Home / End: pan the viewport by a screenful horizontally.\n" 2035 + " KeyPad Arrow keys: pan the viewport by 1 pixel for each keypress.\n" 2036 + " Dragging the Mouse with Button1 pressed also pans the viewport.\n" 2037 + " Clicking Mouse Button3 brings up the Popup Menu.\n" 2038 + " \n" 2039 + " The above mappings are *always* active in ViewOnly mode, unless you set the\n" 2040 + " Escape Keys value to 'never'.\n" 2041 + " \n" 2042 + " If the Escape Keys value below is set to 'default' then a default list of\n" 2043 + " of modifier keys is used. For Unix it is: Alt_L,Super_L and for MacOSX it\n" 2044 + " is Control_L,Meta_L. Note: the Super_L key usually has a Windows(TM) Flag\n" 2045 + " on it. Also note the _L and _R mean the key is on the LEFT or RIGHT side\n" 2046 + " of the keyboard.\n" 2047 + " \n" 2048 + " On Unix the default is Alt and Windows keys on Left side of keyboard.\n" 2049 + " On MacOSX the default is Control and Command keys on Left side of keyboard.\n" 2050 + " \n" 2051 + " Example: Press and hold the Alt and Windows keys on the LEFT side of the\n" 2052 + " keyboard and then press 'c' to toggle the full-color state. Or press 't'\n" 2053 + " to toggle the ultravnc Text Chat window, etc.\n" 2054 + " \n" 2055 + " To use something besides the default, supply a comma separated list (or a\n" 2056 + " single one) from: Shift_L Shift_R Control_L Control_R Alt_L Alt_R Meta_L\n" 2057 + " Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch.\n" 2058 + "\n" 2059 + "\n" 2060 + " New Popup actions:\n" 2061 + "\n" 2062 + " ViewOnly: ~ -viewonly\n" 2063 + " Disable Bell: ~ -nobell\n" 2064 + " Cursor Shape: ~ -nocursorshape\n" 2065 + " X11 Cursor: ~ -x11cursor\n" 2066 + " Cursor Alphablend: ~ -alpha\n" 2067 + " Toggle Tight/Hextile: ~ -encodings hextile...\n" 2068 + " Toggle Tight/ZRLE: ~ -encodings zrle...\n" 2069 + " Toggle ZRLE/ZYWRLE: ~ -encodings zywrle...\n" 2070 + " Quality Level ~ -quality (both Tight and ZYWRLE)\n" 2071 + " Compress Level ~ -compresslevel\n" 2072 + " Disable JPEG: ~ -nojpeg (Tight)\n" 2073 + " Pipeline Updates ~ -pipeline\n" 2074 + "\n" 2075 + " Full Color as many colors as local screen allows.\n" 2076 + " Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only.\n" 2077 + " 16 bit color (BGR565) ~ -16bpp / -bgr565\n" 2078 + " 8 bit color (BGR233) ~ -bgr233\n" 2079 + " 256 colors ~ -bgr233 default # of colors.\n" 2080 + " 64 colors ~ -bgr222 / -use64\n" 2081 + " 8 colors ~ -bgr111 / -use8\n" 2082 + " Scale Viewer ~ -scale\n" 2083 + " Escape Keys: Toggle ~ -escape\n" 2084 + " Escape Keys: Help+Set ~ -escape\n" 2085 + " Set Y Crop (y-max) ~ -ycrop\n" 2086 + " Set Scrollbar Width ~ -sbwidth\n" 2087 + " XGrabServer ~ -graball\n" 2088 + "\n" 2089 + " UltraVNC Extensions:\n" 2090 + "\n" 2091 + " Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n.\n" 2092 + " Text Chat Ultravnc ext. Do Text Chat.\n" 2093 + " File Transfer Ultravnc ext. File xfer via Java helper.\n" 2094 + " Single Window Ultravnc ext. Grab and view a single window.\n" 2095 + " (select then click on the window you want).\n" 2096 + " Disable Remote Input Ultravnc ext. Try to prevent input and\n" 2097 + " viewing of monitor at physical display.\n" 2098 + "\n" 2099 + " Note: the Ultravnc extensions only apply to servers that support\n" 2100 + " them. x11vnc/libvncserver supports some of them.\n" 2101 + "\n" 2102 + " Send Clipboard not Primary ~ -sendclipboard\n" 2103 + " Send Selection Every time ~ -sendalways\n" 2104 + "\n" 2105 + "\n", programName, programName, programName, programName, programName, programName, programName); 2106 exit(1); 2107 } 2108 +#if 0 2109 + " -nooverride Do not apply OverrideRedirect in fullscreen mode.\n" 2110 +#endif 2111 2112 2113 /* 2114 @@ -343,77 +1548,247 @@ 2115 * not already processed by XtVaAppInitialize(). It sets vncServerHost and 2116 * vncServerPort and all the fields in appData. 2117 */ 2118 +extern int saw_appshare; 2119 2120 void 2121 GetArgsAndResources(int argc, char **argv) 2122 { 2123 - int i; 2124 - char *vncServerName, *colonPos; 2125 - int len, portOffset; 2126 + char *vncServerName = NULL, *colonPos, *bracketPos; 2127 + int len, portOffset; 2128 + int disp; 2129 2130 /* Turn app resource specs into our appData structure for the rest of the 2131 program to use */ 2132 2133 - XtGetApplicationResources(toplevel, &appData, appDataResourceList, 2134 - XtNumber(appDataResourceList), 0, 0); 2135 + XtGetApplicationResources(toplevel, &appData, appDataResourceList, 2136 + XtNumber(appDataResourceList), 0, 0); 2137 + 2138 + /* 2139 + * we allow setting of some by env, to avoid clash with other 2140 + * viewer's cmdlines (e.g. change viewer in SSVNC). 2141 + */ 2142 + if (getenv("VNCVIEWER_ALPHABLEND")) { 2143 + appData.useCursorAlpha = True; 2144 + } 2145 + if (getenv("VNCVIEWER_POPUP_FIX")) { 2146 + if (getenv("NOPOPUPFIX")) { 2147 + ; 2148 + } else if (!strcmp(getenv("VNCVIEWER_POPUP_FIX"), "0")) { 2149 + ; 2150 + } else { 2151 + appData.popupFix = True; 2152 + } 2153 + } 2154 + if (getenv("VNCVIEWER_GRAB_SERVER")) { 2155 + appData.grabAll = True; 2156 + } 2157 + if (getenv("VNCVIEWER_YCROP")) { 2158 + int n = atoi(getenv("VNCVIEWER_YCROP")); 2159 + if (n != 0) { 2160 + appData.yCrop = n; 2161 + } 2162 + } 2163 + if (getenv("VNCVIEWER_RFBVERSION") && strcmp(getenv("VNCVIEWER_RFBVERSION"), "")) { 2164 + appData.rfbVersion = strdup(getenv("VNCVIEWER_RFBVERSION")); 2165 + } 2166 + if (getenv("VNCVIEWER_ENCODINGS") && strcmp(getenv("VNCVIEWER_ENCODINGS"), "")) { 2167 + appData.encodingsString = strdup(getenv("VNCVIEWER_ENCODINGS")); 2168 + } 2169 + if (getenv("VNCVIEWER_NOBELL")) { 2170 + appData.useBell = False; 2171 + } 2172 + if (getenv("VNCVIEWER_X11CURSOR")) { 2173 + appData.useX11Cursor = True; 2174 + } 2175 + if (getenv("VNCVIEWER_RAWLOCAL")) { 2176 + appData.useRawLocal = True; 2177 + } 2178 + if (getenv("VNCVIEWER_NOTTY") || getenv("SSVNC_VNCVIEWER_NOTTY")) { 2179 + appData.notty = True; 2180 + } 2181 + if (getenv("VNCVIEWER_SBWIDTH")) { 2182 + int n = atoi(getenv("VNCVIEWER_SBWIDTH")); 2183 + if (n != 0) { 2184 + appData.sbWidth = n; 2185 + } 2186 + } 2187 + if (getenv("VNCVIEWER_ULTRADSM")) { 2188 + appData.ultraDSM = True; 2189 + } 2190 + if (getenv("SSVNC_ULTRA_DSM") && strcmp(getenv("SSVNC_ULTRA_DSM"), "")) { 2191 + appData.ultraDSM = True; 2192 + } 2193 + if (getenv("SSVNC_NO_ULTRA_DSM")) { 2194 + appData.ultraDSM = False; 2195 + } 2196 + if (getenv("SSVNC_SCALE") && strcmp(getenv("SSVNC_SCALE"), "")) { 2197 + if (appData.scale == NULL) { 2198 + appData.scale = strdup(getenv("SSVNC_SCALE")); 2199 + } 2200 + } 2201 + if (getenv("VNCVIEWER_ESCAPE") && strcmp(getenv("VNCVIEWER_ESCAPE"), "")) { 2202 + if (appData.escapeKeys == NULL) { 2203 + appData.escapeKeys = strdup(getenv("VNCVIEWER_ESCAPE")); 2204 + } 2205 + } 2206 + if (saw_appshare) { 2207 + appData.appShare = True; 2208 + } 2209 + if (appData.appShare && appData.escapeKeys == NULL) { 2210 + appData.escapeKeys = strdup("default"); 2211 + } 2212 + if (appData.escapeKeys != NULL) { 2213 + appData.escapeActive = True; 2214 + } 2215 + if (getenv("VNCVIEWER_SEND_CLIPBOARD")) { 2216 + appData.sendClipboard = True; 2217 + } 2218 + if (getenv("VNCVIEWER_SEND_ALWAYS")) { 2219 + appData.sendAlways = True; 2220 + } 2221 + if (getenv("VNCVIEWER_RECV_TEXT")) { 2222 + char *s = getenv("VNCVIEWER_RECV_TEXT"); 2223 + if (!strcasecmp(s, "clipboard")) { 2224 + appData.recvText = strdup("clipboard"); 2225 + } else if (!strcasecmp(s, "primary")) { 2226 + appData.recvText = strdup("primary"); 2227 + } else if (!strcasecmp(s, "both")) { 2228 + appData.recvText = strdup("both"); 2229 + } 2230 + } 2231 + if (getenv("VNCVIEWER_PIPELINE_UPDATES")) { 2232 + appData.pipelineUpdates = True; 2233 + } else if (getenv("VNCVIEWER_NO_PIPELINE_UPDATES")) { 2234 + appData.pipelineUpdates = False; 2235 + } 2236 + 2237 + if (getenv("VNCVIEWER_NO_IPV4")) { 2238 + appData.noipv4 = True; 2239 + } 2240 + if (getenv("VNCVIEWER_NO_IPV6")) { 2241 + appData.noipv6 = True; 2242 + } 2243 + 2244 + if (appData.useBGR233 && appData.useBGR565) { 2245 + appData.useBGR233 = 0; 2246 + } 2247 + 2248 + if (getenv("SSVNC_ULTRA_FTP_JAR") == NULL && programName != NULL) { 2249 + int len = strlen(programName) + 200; 2250 + char *q, *jar = (char *) malloc(len); 2251 + 2252 + sprintf(jar, "%s", programName); 2253 + q = strrchr(jar, '/'); 2254 + if (q) { 2255 + struct stat sb; 2256 + *(q+1) = '\0'; 2257 + strcat(jar, "../lib/ssvnc/util/ultraftp.jar"); 2258 + if (stat(jar, &sb) == 0) { 2259 + char *put = (char *) malloc(len); 2260 + sprintf(put, "SSVNC_ULTRA_FTP_JAR=%s", jar); 2261 + fprintf(stderr, "Setting: %s\n\n", put); 2262 + putenv(put); 2263 + } else { 2264 + sprintf(jar, "%s", programName); 2265 + q = strrchr(jar, '/'); 2266 + *(q+1) = '\0'; 2267 + strcat(jar, "util/ultraftp.jar"); 2268 + if (stat(jar, &sb) == 0) { 2269 + char *put = (char *) malloc(len); 2270 + sprintf(put, "SSVNC_ULTRA_FTP_JAR=%s", jar); 2271 + fprintf(stderr, "Setting: %s\n\n", put); 2272 + putenv(put); 2273 + } 2274 + } 2275 + } 2276 + free(jar); 2277 + } 2278 + 2279 2280 /* Add our actions to the actions table so they can be used in widget 2281 resource specs */ 2282 2283 - XtAppAddActions(appContext, actions, XtNumber(actions)); 2284 + XtAppAddActions(appContext, actions, XtNumber(actions)); 2285 2286 /* Check any remaining command-line arguments. If -listen was specified 2287 there should be none. Otherwise the only argument should be the VNC 2288 server name. If not given then pop up a dialog box and wait for the 2289 server name to be entered. */ 2290 2291 - if (listenSpecified) { 2292 - if (argc != 1) { 2293 - fprintf(stderr,"\n%s -listen: invalid command line argument: %s\n", 2294 - programName, argv[1]); 2295 - usage(); 2296 - } 2297 - return; 2298 - } 2299 - 2300 - if (argc == 1) { 2301 - vncServerName = DoServerDialog(); 2302 - appData.passwordDialog = True; 2303 - } else if (argc != 2) { 2304 - usage(); 2305 - } else { 2306 - vncServerName = argv[1]; 2307 - 2308 - if (!isatty(0)) 2309 - appData.passwordDialog = True; 2310 - if (vncServerName[0] == '-') 2311 - usage(); 2312 - } 2313 - 2314 - if (strlen(vncServerName) > 255) { 2315 - fprintf(stderr,"VNC server name too long\n"); 2316 - exit(1); 2317 - } 2318 - 2319 - colonPos = strchr(vncServerName, ':'); 2320 - if (colonPos == NULL) { 2321 - /* No colon -- use default port number */ 2322 - strcpy(vncServerHost, vncServerName); 2323 - vncServerPort = SERVER_PORT_OFFSET; 2324 - } else { 2325 - memcpy(vncServerHost, vncServerName, colonPos - vncServerName); 2326 - vncServerHost[colonPos - vncServerName] = '\0'; 2327 - len = strlen(colonPos + 1); 2328 - portOffset = SERVER_PORT_OFFSET; 2329 - if (colonPos[1] == ':') { 2330 - /* Two colons -- interpret as a port number */ 2331 - colonPos++; 2332 - len--; 2333 - portOffset = 0; 2334 - } 2335 - if (!len || strspn(colonPos + 1, "0123456789") != len) { 2336 - usage(); 2337 - } 2338 - vncServerPort = atoi(colonPos + 1) + portOffset; 2339 - } 2340 + if (listenSpecified) { 2341 + if (argc != 1) { 2342 + fprintf(stderr,"\n%s -listen: invalid command line argument: %s\n", 2343 + programName, argv[1]); 2344 + usage(); 2345 + } 2346 + return; 2347 + } 2348 + 2349 + if (argc == 1) { 2350 + vncServerName = DoServerDialog(); 2351 + if (!use_tty()) { 2352 + appData.passwordDialog = True; 2353 + } 2354 + } else if (argc != 2) { 2355 + usage(); 2356 + } else { 2357 + vncServerName = argv[1]; 2358 + 2359 + if (!use_tty()) { 2360 + appData.passwordDialog = True; 2361 + } 2362 + if (vncServerName[0] == '-') { 2363 + usage(); 2364 + } 2365 + } 2366 + 2367 + if (strlen(vncServerName) > 255) { 2368 + fprintf(stderr,"VNC server name too long\n"); 2369 + exit(1); 2370 + } 2371 + 2372 + colonPos = strrchr(vncServerName, ':'); 2373 + bracketPos = strrchr(vncServerName, ']'); 2374 + if (strstr(vncServerName, "exec=") == vncServerName) { 2375 + /* special exec-external-command case */ 2376 + strcpy(vncServerHost, vncServerName); 2377 + vncServerPort = SERVER_PORT_OFFSET; 2378 + } else if (strstr(vncServerName, "fd=") == vncServerName) { 2379 + /* special exec-external-command case */ 2380 + strcpy(vncServerHost, vncServerName); 2381 + vncServerPort = SERVER_PORT_OFFSET; 2382 + } else if (colonPos == NULL) { 2383 + /* No colon -- use default port number */ 2384 + strcpy(vncServerHost, vncServerName); 2385 + vncServerPort = SERVER_PORT_OFFSET; 2386 + } else if (bracketPos != NULL && colonPos < bracketPos) { 2387 + strcpy(vncServerHost, vncServerName); 2388 + vncServerPort = SERVER_PORT_OFFSET; 2389 + } else { 2390 + if (colonPos > vncServerName && *(colonPos - 1) == ':') { 2391 + colonPos--; 2392 + } 2393 + memcpy(vncServerHost, vncServerName, colonPos - vncServerName); 2394 + vncServerHost[colonPos - vncServerName] = '\0'; 2395 + len = strlen(colonPos + 1); 2396 + portOffset = SERVER_PORT_OFFSET; 2397 + if (colonPos[1] == ':') { 2398 + /* Two colons -- interpret as a port number */ 2399 + colonPos++; 2400 + len--; 2401 + portOffset = 0; 2402 + } 2403 + if (!len || strspn(colonPos + 1, "0123456789") != (size_t) len) { 2404 + usage(); 2405 + } 2406 +#if 0 2407 + vncServerPort = atoi(colonPos + 1) + portOffset; 2408 +#else 2409 + disp = atoi(colonPos + 1); 2410 + if (portOffset != 0 && disp >= 100) { 2411 + portOffset = 0; 2412 + } 2413 + vncServerPort = disp + portOffset; 2414 +#endif 2415 + } 2416 } 2417 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/colour.c vnc_unixsrc/vncviewer/colour.c 2418 --- vnc_unixsrc.orig/vncviewer/colour.c 2002-04-30 09:07:31.000000000 -0400 2419 +++ vnc_unixsrc/vncviewer/colour.c 2010-02-25 22:02:19.000000000 -0500 2420 @@ -31,9 +31,12 @@ 2421 #define BGR233_SIZE 256 2422 unsigned long BGR233ToPixel[BGR233_SIZE]; 2423 2424 +#define BGR565_SIZE 65536 2425 +unsigned long BGR565ToPixel[BGR565_SIZE]; 2426 + 2427 Colormap cmap; 2428 Visual *vis; 2429 -unsigned int visdepth, visbpp; 2430 +unsigned int visdepth, visbpp, isLSB; 2431 Bool allocColorFailed = False; 2432 2433 static int nBGR233ColoursAllocated; 2434 @@ -45,6 +48,8 @@ 2435 static void AllocateExactBGR233Colours(); 2436 static Bool AllocateBGR233Colour(int r, int g, int b); 2437 2438 +static void SetupBGR565Map(unsigned long red_mask, unsigned long green_mask, unsigned long blue_mask); 2439 + 2440 2441 /* 2442 * SetVisualAndCmap() deals with the wonderful world of X "visuals" (which are 2443 @@ -97,6 +102,44 @@ 2444 visbpp = GetBPPForDepth(visdepth); 2445 cmap = DefaultColormap(dpy,DefaultScreen(dpy)); 2446 2447 + if (ImageByteOrder(dpy) == LSBFirst) { 2448 + isLSB = 1; 2449 + } else { 2450 + isLSB = 0; 2451 + } 2452 + if (visbpp == 24) { 2453 + if (!appData.useBGR233) { 2454 + fprintf(stderr, "Warning: for 24bpp enabling -bgr565 -- Don't use FullColor!\n"); 2455 + appData.useBGR565 = True; 2456 + } else { 2457 + fprintf(stderr, "Warning: for 24bpp using -bgr233 -- Don't use FullColor!\n"); 2458 + } 2459 + } 2460 + 2461 + if (appData.useBGR565) { 2462 + if (visdepth < 24 || visbpp < 24 || vis->class != TrueColor) { 2463 + fprintf(stderr, "disabling -16bpp BGR565 on non-depth 24 machine\n"); 2464 + appData.useBGR565 = False; 2465 + } else { 2466 + myFormat.bitsPerPixel = 16; 2467 + myFormat.depth = 16; 2468 + myFormat.trueColour = 1; 2469 + myFormat.bigEndian = 0; 2470 + myFormat.redMax = 31; 2471 + myFormat.greenMax = 63; 2472 + myFormat.blueMax = 31; 2473 + myFormat.redShift = 11; 2474 + myFormat.greenShift = 5; 2475 + myFormat.blueShift = 0; 2476 + 2477 + fprintf(stderr, "Using default colormap and translating from BGR565 (65536 colors). Pixel format:\n"); 2478 + PrintPixelFormat(&myFormat); 2479 + 2480 + SetupBGR565Map(vis->red_mask, vis->green_mask, vis->blue_mask); 2481 + return; 2482 + } 2483 + } 2484 + 2485 if (!appData.useBGR233 && (vis->class == TrueColor)) { 2486 2487 myFormat.bitsPerPixel = visbpp; 2488 @@ -116,21 +159,42 @@ 2489 return; 2490 } 2491 2492 - appData.useBGR233 = True; 2493 + if (appData.useBGR233 == 0) { 2494 + appData.useBGR233 = 256; 2495 + } 2496 2497 myFormat.bitsPerPixel = 8; 2498 myFormat.depth = 8; 2499 myFormat.trueColour = 1; 2500 myFormat.bigEndian = 0; 2501 - myFormat.redMax = 7; 2502 + myFormat.redMax = 7; 2503 myFormat.greenMax = 7; 2504 - myFormat.blueMax = 3; 2505 - myFormat.redShift = 0; 2506 + myFormat.blueMax = 3; 2507 + myFormat.redShift = 0; 2508 myFormat.greenShift = 3; 2509 - myFormat.blueShift = 6; 2510 + myFormat.blueShift = 6; 2511 + 2512 + if (appData.useBGR233 == 64) { 2513 + /* BGR222 */ 2514 + myFormat.redMax = 3; 2515 + myFormat.greenMax = 3; 2516 + myFormat.blueMax = 3; 2517 + myFormat.redShift = 0; 2518 + myFormat.greenShift = 2; 2519 + myFormat.blueShift = 4; 2520 + } 2521 + if (appData.useBGR233 == 8) { 2522 + /* BGR111 */ 2523 + myFormat.redMax = 2; 2524 + myFormat.greenMax = 2; 2525 + myFormat.blueMax = 2; 2526 + myFormat.redShift = 0; 2527 + myFormat.greenShift = 1; 2528 + myFormat.blueShift = 2; 2529 + } 2530 2531 fprintf(stderr, 2532 - "Using default colormap and translating from BGR233. Pixel format:\n"); 2533 + "Using default colormap and translating from BGR233 (%d colors). Pixel format:\n", appData.useBGR233); 2534 PrintPixelFormat(&myFormat); 2535 2536 SetupBGR233Map(); 2537 @@ -282,8 +346,12 @@ 2538 XFree(format); 2539 2540 if (bpp != 1 && bpp != 8 && bpp != 16 && bpp != 32) { 2541 - fprintf(stderr,"Can't cope with %d bits-per-pixel. Sorry.\n", bpp); 2542 - exit(1); 2543 + if (bpp == 24) { 2544 + fprintf(stderr,"Warning: 24 bits-per-pixel may have problems...\n"); 2545 + } else { 2546 + fprintf(stderr,"Can't cope with %d bits-per-pixel. Sorry.\n", bpp); 2547 + exit(1); 2548 + } 2549 } 2550 2551 return bpp; 2552 @@ -374,7 +442,7 @@ 2553 if (!exactBGR233[i] && 2554 XAllocColor(dpy, cmap, &cmapEntry[i])) { 2555 2556 - if (cmapEntry[i].pixel == i) { 2557 + if ((long) cmapEntry[i].pixel == i) { 2558 2559 shared[i] = True; /* probably shared */ 2560 2561 @@ -394,16 +462,43 @@ 2562 for (r = 0; r < 8; r++) { 2563 for (g = 0; g < 8; g++) { 2564 for (b = 0; b < 4; b++) { 2565 - if (BGR233ToPixel[(b<<6) | (g<<3) | r] == INVALID_PIXEL) { 2566 + int bs = 6, gs = 3, rs = 0; 2567 + int bm = 3, gm = 7, rm = 7; 2568 + if (appData.useBGR233 == 64) { 2569 + bs = 4; gs = 2; rs = 0; 2570 + bm = 3; gm = 3; rm = 3; 2571 + } 2572 + if (appData.useBGR233 == 8) { 2573 + bs = 2; gs = 1; rs = 0; 2574 + bm = 1; gm = 1; rm = 1; 2575 + } 2576 + if ((b > bm || g > gm || r > rm)) { 2577 + continue; 2578 + } 2579 + if (BGR233ToPixel[(b<<bs) | (g<<gs) | (r<<rs)] == INVALID_PIXEL) { 2580 2581 unsigned long minDistance = ULONG_MAX; 2582 2583 for (i = 0; i < cmapSize; i++) { 2584 if (exactBGR233[i] || shared[i]) { 2585 - unsigned long distance 2586 - = (abs(cmapEntry[i].red - r * 65535 / 7) 2587 - + abs(cmapEntry[i].green - g * 65535 / 7) 2588 - + abs(cmapEntry[i].blue - b * 65535 / 3)); 2589 + unsigned long distance; 2590 + int r1, g1, b1; 2591 + if (appData.useGreyScale) { 2592 + int ave; 2593 + ave = (r + g + 2*b)/3; 2594 + r1 = ave; 2595 + g1 = ave; 2596 + b1 = ave/2; 2597 + } else { 2598 + r1 = r; 2599 + g1 = g; 2600 + b1 = b; 2601 + } 2602 + distance 2603 + = ( abs(cmapEntry[i].red - r1 * 65535 / rm) 2604 + + abs(cmapEntry[i].green - g1 * 65535 / gm) 2605 + + abs(cmapEntry[i].blue - b1 * 65535 / bm)); 2606 + 2607 2608 if (distance < minDistance) { 2609 minDistance = distance; 2610 @@ -412,7 +507,7 @@ 2611 } 2612 } 2613 2614 - BGR233ToPixel[(b<<6) | (g<<3) | r] = nearestPixel; 2615 + BGR233ToPixel[(b<<bs) | (g<<gs) | (r<<rs)] = nearestPixel; 2616 if (shared[nearestPixel] && !usedAsNearest[nearestPixel]) 2617 nSharedUsed++; 2618 usedAsNearest[nearestPixel] = True; 2619 @@ -433,6 +528,59 @@ 2620 } 2621 } 2622 2623 +static void 2624 +SetupBGR565Map(unsigned long red_mask, unsigned long green_mask, unsigned long blue_mask) 2625 +{ 2626 + int r, g, b; 2627 + int r2, g2, b2; 2628 + long idx; 2629 + int cnt = 0; 2630 + unsigned long pixel = 0; 2631 + 2632 + for (r = 0; r < 32; r++) { 2633 + for (g = 0; g < 64; g++) { 2634 + for (b = 0; b < 32; b++) { 2635 + int bs = 0, gs = 5, rs = 11; 2636 + int bm = 31, gm = 63, rm = 31; 2637 + if ((b > bm || g > gm || r > rm)) { 2638 + continue; 2639 + } 2640 + r2 = (255 * r) / rm; 2641 + g2 = (255 * g) / gm; 2642 + b2 = (255 * b) / bm; 2643 + 2644 + pixel = (r2 << 16) | (g2 << 8) | (b2 << 0); 2645 + if (appData.useGreyScale) { 2646 + int ave; 2647 + int r1, g1, b1; 2648 + ave = (2*r + g + 2*b)/3; 2649 + r1 = ave/2; 2650 + g1 = ave; 2651 + b1 = ave/2; 2652 + 2653 + r2 = (255 * r1) / rm; 2654 + g2 = (255 * g1) / gm; 2655 + b2 = (255 * b1) / bm; 2656 + 2657 + pixel = (r2 << 16) | (g2 << 8) | (b2 << 0); 2658 + } 2659 + 2660 + if (red_mask == 0xff) { 2661 + idx = (r<<bs) | (g<<gs) | (b<<rs); 2662 + } else { 2663 + idx = (b<<bs) | (g<<gs) | (r<<rs); 2664 + } 2665 + if (0) fprintf(stderr, "cnt: %5d idx: %lu pixel: 0x%08x\n", cnt, idx, (unsigned int) pixel); 2666 + BGR565ToPixel[idx] = pixel; 2667 + cnt++; 2668 + } 2669 + } 2670 + } 2671 + green_mask = 0; 2672 + blue_mask = 0; 2673 +} 2674 + 2675 + 2676 2677 /* 2678 * AllocateExactBGR233Colours() attempts to allocate each of the colours in the 2679 @@ -484,8 +632,13 @@ 2680 ri = rn; 2681 for (gi = 0; gi < gn; gi++) { 2682 for (bi = 0; bi < bn; bi++) { 2683 - if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) 2684 - return; 2685 + if (appData.useBGR233 == 64 && (bv[bi] > 3 || gv[gi] > 3 || rv[ri] > 3)) { 2686 + nBGR233ColoursAllocated++; 2687 + } else if (appData.useBGR233 == 8 && (bv[bi] > 1 || gv[gi] > 1 || rv[ri] > 1)) { 2688 + nBGR233ColoursAllocated++; 2689 + } else if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) { 2690 + return; 2691 + } 2692 } 2693 } 2694 rn++; 2695 @@ -496,8 +649,13 @@ 2696 gi = gn; 2697 for (ri = 0; ri < rn; ri++) { 2698 for (bi = 0; bi < bn; bi++) { 2699 - if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) 2700 - return; 2701 + if (appData.useBGR233 == 64 && (bv[bi] > 3 || gv[gi] > 3 || rv[ri] > 3)) { 2702 + nBGR233ColoursAllocated++; 2703 + } else if (appData.useBGR233 == 8 && (bv[bi] > 1 || gv[gi] > 1 || rv[ri] > 1)) { 2704 + nBGR233ColoursAllocated++; 2705 + } else if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) { 2706 + return; 2707 + } 2708 } 2709 } 2710 gn++; 2711 @@ -507,8 +665,13 @@ 2712 bi = bn; 2713 for (ri = 0; ri < rn; ri++) { 2714 for (gi = 0; gi < gn; gi++) { 2715 - if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) 2716 - return; 2717 + if (appData.useBGR233 == 64 && (bv[bi] > 3 || gv[gi] > 3 || rv[ri] > 3)) { 2718 + nBGR233ColoursAllocated++; 2719 + } else if (appData.useBGR233 == 8 && (bv[bi] > 1 || gv[gi] > 1 || rv[ri] > 1)) { 2720 + nBGR233ColoursAllocated++; 2721 + } else if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) { 2722 + return; 2723 + } 2724 } 2725 } 2726 bn++; 2727 @@ -529,18 +692,36 @@ 2728 AllocateBGR233Colour(int r, int g, int b) 2729 { 2730 XColor c; 2731 + int bs = 6, gs = 3, rs = 0; 2732 + int bm = 3, gm = 7, rm = 7; 2733 2734 if (nBGR233ColoursAllocated >= appData.nColours) 2735 return False; 2736 2737 - c.red = r * 65535 / 7; 2738 - c.green = g * 65535 / 7; 2739 - c.blue = b * 65535 / 3; 2740 + if (appData.useBGR233 == 64) { 2741 + bs = 4; gs = 2, rs = 0; 2742 + bm = 3; gm = 3; rm = 3; 2743 + } 2744 + if (appData.useBGR233 == 8) { 2745 + bs = 2; gs = 1, rs = 0; 2746 + bm = 1; gm = 1; rm = 1; 2747 + } 2748 + 2749 + c.red = r * 65535 / rm; 2750 + c.green = g * 65535 / gm; 2751 + c.blue = b * 65535 / bm; 2752 + if (appData.useGreyScale) { 2753 + int ave; 2754 + ave = (c.red + c.green + c.blue)/3; 2755 + c.red = ave; 2756 + c.green = ave; 2757 + c.blue = ave; 2758 + } 2759 2760 if (!XAllocColor(dpy, cmap, &c)) 2761 return False; 2762 2763 - BGR233ToPixel[(b<<6) | (g<<3) | r] = c.pixel; 2764 + BGR233ToPixel[(b<<bs) | (g<<gs) | r] = c.pixel; 2765 2766 nBGR233ColoursAllocated++; 2767 2768 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/corre.c vnc_unixsrc/vncviewer/corre.c 2769 --- vnc_unixsrc.orig/vncviewer/corre.c 2000-06-11 08:00:53.000000000 -0400 2770 +++ vnc_unixsrc/vncviewer/corre.c 2008-10-05 15:16:01.000000000 -0400 2771 @@ -29,6 +29,18 @@ 2772 #define HandleCoRREBPP CONCAT2E(HandleCoRRE,BPP) 2773 #define CARDBPP CONCAT2E(CARD,BPP) 2774 2775 +#define FillRectangle(x, y, w, h, color) \ 2776 + { \ 2777 + XGCValues _gcv; \ 2778 + _gcv.foreground = color; \ 2779 + if (!appData.useXserverBackingStore) { \ 2780 + FillScreen(x, y, w, h, _gcv.foreground); \ 2781 + } else { \ 2782 + XChangeGC(dpy, gc, GCForeground, &_gcv); \ 2783 + XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \ 2784 + } \ 2785 + } 2786 + 2787 static Bool 2788 HandleCoRREBPP (int rx, int ry, int rw, int rh) 2789 { 2790 @@ -50,11 +62,19 @@ 2791 #if (BPP == 8) 2792 gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix); 2793 #else 2794 +#if (BPP == 16) 2795 + gcv.foreground = (appData.useBGR565 ? BGR565ToPixel[pix] : pix); 2796 +#else 2797 gcv.foreground = pix; 2798 #endif 2799 +#endif 2800 2801 +#if 0 2802 XChangeGC(dpy, gc, GCForeground, &gcv); 2803 XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); 2804 +#else 2805 + FillRectangle(rx, ry, rw, rh, gcv.foreground); 2806 +#endif 2807 2808 if (!ReadFromRFBServer(buffer, hdr.nSubrects * (4 + (BPP / 8)))) 2809 return False; 2810 @@ -72,12 +92,22 @@ 2811 #if (BPP == 8) 2812 gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix); 2813 #else 2814 +#if (BPP == 16) 2815 + gcv.foreground = (appData.useBGR565 ? BGR565ToPixel[pix] : pix); 2816 +#else 2817 gcv.foreground = pix; 2818 #endif 2819 +#endif 2820 2821 +#if 0 2822 XChangeGC(dpy, gc, GCForeground, &gcv); 2823 XFillRectangle(dpy, desktopWin, gc, rx + x, ry + y, w, h); 2824 +#else 2825 + FillRectangle(rx + x, ry + y, w, h, gcv.foreground); 2826 +#endif 2827 } 2828 2829 return True; 2830 } 2831 + 2832 +#undef FillRectangle 2833 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cp_it vnc_unixsrc/vncviewer/cp_it 2834 --- vnc_unixsrc.orig/vncviewer/cp_it 1969-12-31 19:00:00.000000000 -0500 2835 +++ vnc_unixsrc/vncviewer/cp_it 2009-03-06 20:02:05.000000000 -0500 2836 @@ -0,0 +1,18 @@ 2837 +#!/bin/sh 2838 + 2839 +dest=/dist/bin/vncviewerz-1.3dev5-resize 2840 +suc "cp -p $dest $dest.back; mv $dest $dest.unlink; mv $dest.back $dest; rm $dest.unlink" 2841 +strip ./vncviewer 2842 +cat ./vncviewer > $dest 2843 +touch -r ./vncviewer $dest 2844 +yy=/dist/src/apps/VNC/etc/libvncserver_cvs/expts/etv/ssvnc/bin/Linux.i686/vncviewer 2845 +mv $yy $yy.unlink 2846 +cp -p ./vncviewer $yy 2847 +mv $yy.turbovnc $yy.unlink.turbovnc 2848 +cp -p ./vncviewer $HOME/etv_col/Linux.i686 2849 +cp -p ./vncviewer.turbovnc $yy.turbovnc 2850 +cp -p ./vncviewer.turbovnc $HOME/etv_col/Linux.i686/vncviewer.turbovnc 2851 +chmod 755 $yy* 2852 + 2853 +rm -f $yy.unlink* 2854 +ls -l ./vncviewer* $dest $yy* $HOME/etv_col/Linux.i686/vncviewer* 2855 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewer/cursor.c 2856 --- vnc_unixsrc.orig/vncviewer/cursor.c 2003-01-15 04:46:52.000000000 -0500 2857 +++ vnc_unixsrc/vncviewer/cursor.c 2010-02-25 22:04:28.000000000 -0500 2858 @@ -38,8 +38,11 @@ 2859 2860 2861 static Bool prevSoftCursorSet = False; 2862 -static Pixmap rcSavedArea; 2863 -static CARD8 *rcSource, *rcMask; 2864 +static Pixmap rcSavedArea, rcSavedArea_0; 2865 +static int rcSavedArea_w = -1, rcSavedArea_h = -1; 2866 +static char *rcSavedScale = NULL; 2867 +static int rcSavedScale_len = 0; 2868 +static CARD8 *rcSource = NULL, *rcMask; 2869 static int rcHotX, rcHotY, rcWidth, rcHeight; 2870 static int rcCursorX = 0, rcCursorY = 0; 2871 static int rcLockX, rcLockY, rcLockWidth, rcLockHeight; 2872 @@ -48,8 +51,13 @@ 2873 static Bool SoftCursorInLockedArea(void); 2874 static void SoftCursorCopyArea(int oper); 2875 static void SoftCursorDraw(void); 2876 -static void FreeSoftCursor(void); 2877 -static void FreeX11Cursor(); 2878 +void FreeSoftCursor(void); 2879 +void FreeX11Cursor(); 2880 + 2881 +extern XImage *image; 2882 +extern XImage *image_scale; 2883 +extern int scale_x, scale_y; 2884 +int scale_round(int n, double factor); 2885 2886 /* Copied from Xvnc/lib/font/util/utilbitmap.c */ 2887 static unsigned char _reverse_byte[0x100] = { 2888 @@ -91,6 +99,8 @@ 2889 static Bool prevXCursorSet = False; 2890 static Cursor prevXCursor; 2891 2892 +extern double scale_factor_x; 2893 +extern double scale_factor_y; 2894 2895 Bool HandleXCursor(int xhot, int yhot, int width, int height) 2896 { 2897 @@ -124,7 +134,7 @@ 2898 XQueryBestCursor(dpy, dr, width, height, &wret, &hret); 2899 } 2900 2901 - if (width * height == 0 || wret < width || hret < height) { 2902 + if (width * height == 0 || (int) wret < width || (int) hret < height) { 2903 /* Free resources */ 2904 if (buf != NULL) 2905 free(buf); 2906 @@ -139,7 +149,7 @@ 2907 fg.green = (unsigned short)colors.foreGreen << 8 | colors.foreGreen; 2908 fg.blue = (unsigned short)colors.foreBlue << 8 | colors.foreBlue; 2909 2910 - for (i = 0; i < bytesData * 2; i++) 2911 + for (i = 0; (size_t) i < bytesData * 2; i++) 2912 buf[i] = (char)_reverse_byte[(int)buf[i] & 0xFF]; 2913 2914 source = XCreateBitmapFromData(dpy, dr, buf, width, height); 2915 @@ -167,148 +177,179 @@ 2916 2917 Bool HandleCursorShape(int xhot, int yhot, int width, int height, CARD32 enc) 2918 { 2919 - int bytesPerPixel; 2920 - size_t bytesPerRow, bytesMaskData; 2921 - Drawable dr; 2922 - rfbXCursorColors rgb; 2923 - CARD32 colors[2]; 2924 - char *buf; 2925 - CARD8 *ptr; 2926 - int x, y, b; 2927 - 2928 - bytesPerPixel = myFormat.bitsPerPixel / 8; 2929 - bytesPerRow = (width + 7) / 8; 2930 - bytesMaskData = bytesPerRow * height; 2931 - dr = DefaultRootWindow(dpy); 2932 - 2933 - FreeSoftCursor(); 2934 + int bytesPerPixel; 2935 + size_t bytesPerRow, bytesMaskData; 2936 + Drawable dr; 2937 + rfbXCursorColors rgb; 2938 + CARD32 colors[2]; 2939 + char *buf; 2940 + CARD8 *ptr; 2941 + int x, y, b; 2942 + 2943 + bytesPerPixel = myFormat.bitsPerPixel / 8; 2944 + bytesPerRow = (width + 7) / 8; 2945 + bytesMaskData = bytesPerRow * height; 2946 + dr = DefaultRootWindow(dpy); 2947 2948 - if (width * height == 0) 2949 - return True; 2950 - 2951 - /* Allocate memory for pixel data and temporary mask data. */ 2952 + FreeSoftCursor(); 2953 2954 - rcSource = malloc(width * height * bytesPerPixel); 2955 - if (rcSource == NULL) 2956 - return False; 2957 - 2958 - buf = malloc(bytesMaskData); 2959 - if (buf == NULL) { 2960 - free(rcSource); 2961 - return False; 2962 - } 2963 + if (width * height == 0) { 2964 + return True; 2965 + } 2966 2967 - /* Read and decode cursor pixel data, depending on the encoding type. */ 2968 + /* Allocate memory for pixel data and temporary mask data. */ 2969 2970 - if (enc == rfbEncodingXCursor) { 2971 - if (appData.useX11Cursor) { 2972 - HandleXCursor(xhot, yhot, width, height); 2973 - return True; 2974 - } 2975 + rcSource = malloc(width * height * bytesPerPixel); 2976 + if (rcSource == NULL) { 2977 + return False; 2978 + } 2979 2980 - /* Read and convert background and foreground colors. */ 2981 - if (!ReadFromRFBServer((char *)&rgb, sz_rfbXCursorColors)) { 2982 - free(rcSource); 2983 - free(buf); 2984 - return False; 2985 - } 2986 - colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue); 2987 - colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue); 2988 + buf = malloc(bytesMaskData); 2989 + if (buf == NULL) { 2990 + free(rcSource); 2991 + rcSource = NULL; 2992 + return False; 2993 + } 2994 2995 - /* Read 1bpp pixel data into a temporary buffer. */ 2996 - if (!ReadFromRFBServer(buf, bytesMaskData)) { 2997 - free(rcSource); 2998 - free(buf); 2999 - return False; 3000 - } 3001 + /* Read and decode cursor pixel data, depending on the encoding type. */ 3002 3003 - /* Convert 1bpp data to byte-wide color indices. */ 3004 - ptr = rcSource; 3005 - for (y = 0; y < height; y++) { 3006 - for (x = 0; x < width / 8; x++) { 3007 - for (b = 7; b >= 0; b--) { 3008 - *ptr = buf[y * bytesPerRow + x] >> b & 1; 3009 - ptr += bytesPerPixel; 3010 - } 3011 - } 3012 - for (b = 7; b > 7 - width % 8; b--) { 3013 - *ptr = buf[y * bytesPerRow + x] >> b & 1; 3014 - ptr += bytesPerPixel; 3015 - } 3016 - } 3017 + if (enc == rfbEncodingXCursor) { 3018 + if (appData.useX11Cursor) { 3019 + HandleXCursor(xhot, yhot, width, height); 3020 + return True; 3021 + } 3022 + 3023 + /* Read and convert background and foreground colors. */ 3024 + if (!ReadFromRFBServer((char *)&rgb, sz_rfbXCursorColors)) { 3025 + free(rcSource); 3026 + rcSource = NULL; 3027 + free(buf); 3028 + return False; 3029 + } 3030 + colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue); 3031 + colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue); 3032 + 3033 + /* Read 1bpp pixel data into a temporary buffer. */ 3034 + if (!ReadFromRFBServer(buf, bytesMaskData)) { 3035 + free(rcSource); 3036 + rcSource = NULL; 3037 + free(buf); 3038 + return False; 3039 + } 3040 + 3041 + /* Convert 1bpp data to byte-wide color indices. */ 3042 + ptr = rcSource; 3043 + for (y = 0; y < height; y++) { 3044 + for (x = 0; x < width / 8; x++) { 3045 + for (b = 7; b >= 0; b--) { 3046 + *ptr = buf[y * bytesPerRow + x] >> b & 1; 3047 + ptr += bytesPerPixel; 3048 + } 3049 + } 3050 + for (b = 7; b > 7 - width % 8; b--) { 3051 + *ptr = buf[y * bytesPerRow + x] >> b & 1; 3052 + ptr += bytesPerPixel; 3053 + } 3054 + } 3055 + 3056 + /* Convert indices into the actual pixel values. */ 3057 + switch (bytesPerPixel) { 3058 + case 1: 3059 + for (x = 0; x < width * height; x++) { 3060 + rcSource[x] = (CARD8)colors[rcSource[x]]; 3061 + } 3062 + break; 3063 + case 2: 3064 + for (x = 0; x < width * height; x++) { 3065 + ((CARD16 *)rcSource)[x] = (CARD16)colors[rcSource[x * 2]]; 3066 + } 3067 + break; 3068 + case 4: 3069 + for (x = 0; x < width * height; x++) { 3070 + ((CARD32 *)rcSource)[x] = colors[rcSource[x * 4]]; 3071 + } 3072 + break; 3073 + } 3074 + 3075 + } else { /* enc == rfbEncodingRichCursor */ 3076 + if (!ReadFromRFBServer((char *)rcSource, width * height * bytesPerPixel)) { 3077 + free(rcSource); 3078 + rcSource = NULL; 3079 + free(buf); 3080 + return False; 3081 + } 3082 + } 3083 3084 - /* Convert indices into the actual pixel values. */ 3085 - switch (bytesPerPixel) { 3086 - case 1: 3087 - for (x = 0; x < width * height; x++) 3088 - rcSource[x] = (CARD8)colors[rcSource[x]]; 3089 - break; 3090 - case 2: 3091 - for (x = 0; x < width * height; x++) 3092 - ((CARD16 *)rcSource)[x] = (CARD16)colors[rcSource[x * 2]]; 3093 - break; 3094 - case 4: 3095 - for (x = 0; x < width * height; x++) 3096 - ((CARD32 *)rcSource)[x] = colors[rcSource[x * 4]]; 3097 - break; 3098 - } 3099 + /* Read and decode mask data. */ 3100 3101 - } else { /* enc == rfbEncodingRichCursor */ 3102 + if (!ReadFromRFBServer(buf, bytesMaskData)) { 3103 + free(rcSource); 3104 + rcSource = NULL; 3105 + free(buf); 3106 + return False; 3107 + } 3108 3109 - if (!ReadFromRFBServer((char *)rcSource, width * height * bytesPerPixel)) { 3110 - free(rcSource); 3111 - free(buf); 3112 - return False; 3113 - } 3114 + rcMask = malloc(width * height); 3115 + if (rcMask == NULL) { 3116 + free(rcSource); 3117 + rcSource = NULL; 3118 + free(buf); 3119 + return False; 3120 + } 3121 3122 - } 3123 + ptr = rcMask; 3124 + for (y = 0; y < height; y++) { 3125 + for (x = 0; x < width / 8; x++) { 3126 + for (b = 7; b >= 0; b--) { 3127 + *ptr++ = buf[y * bytesPerRow + x] >> b & 1; 3128 + } 3129 + } 3130 + for (b = 7; b > 7 - width % 8; b--) { 3131 + *ptr++ = buf[y * bytesPerRow + x] >> b & 1; 3132 + } 3133 + } 3134 3135 - /* Read and decode mask data. */ 3136 + free(buf); 3137 3138 - if (!ReadFromRFBServer(buf, bytesMaskData)) { 3139 - free(rcSource); 3140 - free(buf); 3141 - return False; 3142 - } 3143 + /* Set remaining data associated with cursor. */ 3144 3145 - rcMask = malloc(width * height); 3146 - if (rcMask == NULL) { 3147 - free(rcSource); 3148 - free(buf); 3149 - return False; 3150 - } 3151 + dr = DefaultRootWindow(dpy); 3152 3153 - ptr = rcMask; 3154 - for (y = 0; y < height; y++) { 3155 - for (x = 0; x < width / 8; x++) { 3156 - for (b = 7; b >= 0; b--) { 3157 - *ptr++ = buf[y * bytesPerRow + x] >> b & 1; 3158 - } 3159 - } 3160 - for (b = 7; b > 7 - width % 8; b--) { 3161 - *ptr++ = buf[y * bytesPerRow + x] >> b & 1; 3162 - } 3163 - } 3164 + if (scale_x > 0) { 3165 + int w = scale_round(width, scale_factor_x) + 2; 3166 + int h = scale_round(height, scale_factor_y) + 2; 3167 + rcSavedArea = XCreatePixmap(dpy, dr, w, h, visdepth); 3168 + rcSavedArea_w = w; 3169 + rcSavedArea_h = h; 3170 + } else { 3171 + rcSavedArea = XCreatePixmap(dpy, dr, width, height, visdepth); 3172 + rcSavedArea_w = width; 3173 + rcSavedArea_h = height; 3174 + } 3175 + rcSavedArea_0 = XCreatePixmap(dpy, dr, width, height, visdepth); 3176 3177 - free(buf); 3178 +if (0) fprintf(stderr, "rcSavedArea_wh: %d %d scale_x: %d\n", rcSavedArea_w, rcSavedArea_h, scale_x); 3179 3180 - /* Set remaining data associated with cursor. */ 3181 + if (rcSavedScale_len < 4 * width * height + 4096) { 3182 + if (rcSavedScale) { 3183 + free(rcSavedScale); 3184 + } 3185 + rcSavedScale = (char *) malloc(2 * 4 * width * height + 4096); 3186 + } 3187 3188 - dr = DefaultRootWindow(dpy); 3189 - rcSavedArea = XCreatePixmap(dpy, dr, width, height, visdepth); 3190 - rcHotX = xhot; 3191 - rcHotY = yhot; 3192 - rcWidth = width; 3193 - rcHeight = height; 3194 + rcHotX = xhot; 3195 + rcHotY = yhot; 3196 + rcWidth = width; 3197 + rcHeight = height; 3198 3199 - SoftCursorCopyArea(OPER_SAVE); 3200 - SoftCursorDraw(); 3201 + SoftCursorCopyArea(OPER_SAVE); 3202 + SoftCursorDraw(); 3203 3204 - rcCursorHidden = False; 3205 - rcLockSet = False; 3206 + rcCursorHidden = False; 3207 + rcLockSet = False; 3208 3209 - prevSoftCursorSet = True; 3210 - return True; 3211 + prevSoftCursorSet = True; 3212 + return True; 3213 } 3214 3215 /********************************************************************* 3216 @@ -319,20 +360,27 @@ 3217 3218 Bool HandleCursorPos(int x, int y) 3219 { 3220 - if (appData.useX11Cursor) { 3221 - if (appData.fullScreen) 3222 - XWarpPointer(dpy, None, desktopWin, 0, 0, 0, 0, x, y); 3223 - 3224 - return True; 3225 - } 3226 + if (x < 0) x = 0; 3227 + if (y < 0) y = 0; 3228 3229 - if (x >= si.framebufferWidth) 3230 - x = si.framebufferWidth - 1; 3231 - if (y >= si.framebufferHeight) 3232 - y = si.framebufferHeight - 1; 3233 + /* fprintf(stderr, "xy: %d %d\n", x, y); */ 3234 3235 - SoftCursorMove(x, y); 3236 - return True; 3237 + if (x >= si.framebufferWidth) { 3238 + x = si.framebufferWidth - 1; 3239 + } 3240 + if (y >= si.framebufferHeight) { 3241 + y = si.framebufferHeight - 1; 3242 + } 3243 + 3244 + if (appData.useX11Cursor) { 3245 + if (appData.fullScreen) { 3246 + XWarpPointer(dpy, None, desktopWin, 0, 0, 0, 0, x, y); 3247 + } 3248 + return True; 3249 + } 3250 + 3251 + SoftCursorMove(x, y); 3252 + return True; 3253 } 3254 3255 /********************************************************************* 3256 @@ -348,30 +396,31 @@ 3257 { 3258 int newX, newY; 3259 3260 - if (!prevSoftCursorSet) 3261 - return; 3262 + if (!prevSoftCursorSet) { 3263 + return; 3264 + } 3265 3266 - if (!rcLockSet) { 3267 - rcLockX = x; 3268 - rcLockY = y; 3269 - rcLockWidth = w; 3270 - rcLockHeight = h; 3271 - rcLockSet = True; 3272 - } else { 3273 - newX = (x < rcLockX) ? x : rcLockX; 3274 - newY = (y < rcLockY) ? y : rcLockY; 3275 - rcLockWidth = (x + w > rcLockX + rcLockWidth) ? 3276 - (x + w - newX) : (rcLockX + rcLockWidth - newX); 3277 - rcLockHeight = (y + h > rcLockY + rcLockHeight) ? 3278 - (y + h - newY) : (rcLockY + rcLockHeight - newY); 3279 - rcLockX = newX; 3280 - rcLockY = newY; 3281 - } 3282 + if (!rcLockSet) { 3283 + rcLockX = x; 3284 + rcLockY = y; 3285 + rcLockWidth = w; 3286 + rcLockHeight = h; 3287 + rcLockSet = True; 3288 + } else { 3289 + newX = (x < rcLockX) ? x : rcLockX; 3290 + newY = (y < rcLockY) ? y : rcLockY; 3291 + rcLockWidth = (x + w > rcLockX + rcLockWidth) ? 3292 + (x + w - newX) : (rcLockX + rcLockWidth - newX); 3293 + rcLockHeight = (y + h > rcLockY + rcLockHeight) ? 3294 + (y + h - newY) : (rcLockY + rcLockHeight - newY); 3295 + rcLockX = newX; 3296 + rcLockY = newY; 3297 + } 3298 3299 - if (!rcCursorHidden && SoftCursorInLockedArea()) { 3300 - SoftCursorCopyArea(OPER_RESTORE); 3301 - rcCursorHidden = True; 3302 - } 3303 + if (!rcCursorHidden && SoftCursorInLockedArea()) { 3304 + SoftCursorCopyArea(OPER_RESTORE); 3305 + rcCursorHidden = True; 3306 + } 3307 } 3308 3309 /********************************************************************* 3310 @@ -381,15 +430,16 @@ 3311 3312 void SoftCursorUnlockScreen(void) 3313 { 3314 - if (!prevSoftCursorSet) 3315 - return; 3316 + if (!prevSoftCursorSet) { 3317 + return; 3318 + } 3319 3320 - if (rcCursorHidden) { 3321 - SoftCursorCopyArea(OPER_SAVE); 3322 - SoftCursorDraw(); 3323 - rcCursorHidden = False; 3324 - } 3325 - rcLockSet = False; 3326 + if (rcCursorHidden) { 3327 + SoftCursorCopyArea(OPER_SAVE); 3328 + SoftCursorDraw(); 3329 + rcCursorHidden = False; 3330 + } 3331 + rcLockSet = False; 3332 } 3333 3334 /********************************************************************* 3335 @@ -401,19 +451,19 @@ 3336 3337 void SoftCursorMove(int x, int y) 3338 { 3339 - if (prevSoftCursorSet && !rcCursorHidden) { 3340 - SoftCursorCopyArea(OPER_RESTORE); 3341 - rcCursorHidden = True; 3342 - } 3343 + if (prevSoftCursorSet && !rcCursorHidden) { 3344 + SoftCursorCopyArea(OPER_RESTORE); 3345 + rcCursorHidden = True; 3346 + } 3347 3348 - rcCursorX = x; 3349 - rcCursorY = y; 3350 + rcCursorX = x; 3351 + rcCursorY = y; 3352 3353 - if (prevSoftCursorSet && !(rcLockSet && SoftCursorInLockedArea())) { 3354 - SoftCursorCopyArea(OPER_SAVE); 3355 - SoftCursorDraw(); 3356 - rcCursorHidden = False; 3357 - } 3358 + if (prevSoftCursorSet && !(rcLockSet && SoftCursorInLockedArea())) { 3359 + SoftCursorCopyArea(OPER_SAVE); 3360 + SoftCursorDraw(); 3361 + rcCursorHidden = False; 3362 + } 3363 } 3364 3365 3366 @@ -429,41 +479,169 @@ 3367 rcLockY + rcLockHeight > rcCursorY - rcHotY); 3368 } 3369 3370 -static void SoftCursorCopyArea(int oper) 3371 -{ 3372 - int x, y, w, h; 3373 +void new_pixmap(int w, int h) { 3374 3375 - x = rcCursorX - rcHotX; 3376 - y = rcCursorY - rcHotY; 3377 - if (x >= si.framebufferWidth || y >= si.framebufferHeight) 3378 - return; 3379 - 3380 - w = rcWidth; 3381 - h = rcHeight; 3382 - if (x < 0) { 3383 - w += x; 3384 - x = 0; 3385 - } else if (x + w > si.framebufferWidth) { 3386 - w = si.framebufferWidth - x; 3387 - } 3388 - if (y < 0) { 3389 - h += y; 3390 - y = 0; 3391 - } else if (y + h > si.framebufferHeight) { 3392 - h = si.framebufferHeight - y; 3393 - } 3394 + XFreePixmap(dpy, rcSavedArea); 3395 3396 - if (oper == OPER_SAVE) { 3397 - /* Save screen area in memory. */ 3398 -#ifdef MITSHM 3399 - if (appData.useShm) 3400 - XSync(dpy, False); 3401 -#endif 3402 - XCopyArea(dpy, desktopWin, rcSavedArea, gc, x, y, w, h, 0, 0); 3403 - } else { 3404 - /* Restore screen area. */ 3405 - XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y); 3406 - } 3407 + if (w > 0 && h > 0) { 3408 + rcSavedArea = XCreatePixmap(dpy, DefaultRootWindow(dpy), w, h, visdepth); 3409 + rcSavedArea_w = w; 3410 + rcSavedArea_h = h; 3411 + 3412 + } else if (image_scale != NULL && scale_x > 0) { 3413 + int w2 = scale_round(rcWidth, scale_factor_x) + 2; 3414 + int h2 = scale_round(rcHeight, scale_factor_y) + 2; 3415 + rcSavedArea = XCreatePixmap(dpy, DefaultRootWindow(dpy), w2, h2, visdepth); 3416 + rcSavedArea_w = w2; 3417 + rcSavedArea_h = h2; 3418 + } else { 3419 + rcSavedArea = XCreatePixmap(dpy, DefaultRootWindow(dpy), rcWidth, rcHeight, visdepth); 3420 + rcSavedArea_w = rcWidth; 3421 + rcSavedArea_h = rcHeight; 3422 + } 3423 +} 3424 + 3425 +extern int XError_ign; 3426 + 3427 +static void SoftCursorCopyArea(int oper) { 3428 + int x, y, w, h; 3429 + int xs = 0, ys = 0, ws = 0, hs = 0; 3430 + static int scale_saved = 0, ss_w, ss_h; 3431 + int db = 0; 3432 + 3433 + x = rcCursorX - rcHotX; 3434 + y = rcCursorY - rcHotY; 3435 + if (x >= si.framebufferWidth || y >= si.framebufferHeight) { 3436 + return; 3437 + } 3438 + 3439 + w = rcWidth; 3440 + h = rcHeight; 3441 + if (x < 0) { 3442 + w += x; 3443 + x = 0; 3444 + } else if (x + w > si.framebufferWidth) { 3445 + w = si.framebufferWidth - x; 3446 + } 3447 + if (y < 0) { 3448 + h += y; 3449 + y = 0; 3450 + } else if (y + h > si.framebufferHeight) { 3451 + h = si.framebufferHeight - y; 3452 + } 3453 + 3454 + if (image_scale != NULL && scale_x > 0) { 3455 + xs = (int) (x * scale_factor_x); 3456 + ys = (int) (y * scale_factor_y); 3457 + ws = scale_round(w, scale_factor_x); 3458 + hs = scale_round(h, scale_factor_y); 3459 + 3460 + if (xs > 0) xs -= 1; 3461 + if (ys > 0) ys -= 1; 3462 + ws += 2; 3463 + hs += 2; 3464 + } 3465 + 3466 + XError_ign = 1; 3467 + 3468 + if (oper == OPER_SAVE) { 3469 + /* Save screen area in memory. */ 3470 + scale_saved = 0; 3471 + if (appData.useXserverBackingStore) { 3472 + XSync(dpy, False); 3473 + XCopyArea(dpy, desktopWin, rcSavedArea, gc, x, y, w, h, 0, 0); 3474 + } else { 3475 + if (image_scale != NULL && scale_x > 0) { 3476 + int Bpp = image_scale->bits_per_pixel / 8; 3477 + int Bpl = image_scale->bytes_per_line; 3478 + int i; 3479 + char *src = image_scale->data + y * Bpl + x * Bpp; 3480 + char *dst = rcSavedScale; 3481 + 3482 + if (ws > rcSavedArea_w || hs > rcSavedArea_h) { 3483 + new_pixmap(0, 0); 3484 + } 3485 + 3486 +if (db) fprintf(stderr, "save: %dx%d+%d+%d\n", ws, hs, xs, ys); 3487 + 3488 + XPutImage(dpy, rcSavedArea, gc, image, xs, ys, 0, 0, ws, hs); 3489 + 3490 + XPutImage(dpy, rcSavedArea_0, gc, image_scale, x, y, 0, 0, w, h); 3491 + 3492 + scale_saved = 1; 3493 + ss_w = ws; 3494 + ss_h = hs; 3495 + 3496 + for (i=0; i < h; i++) { 3497 + memcpy(dst, src, Bpp * w); 3498 + src += Bpl; 3499 + dst += Bpp * w; 3500 + } 3501 + } else { 3502 +if (db) fprintf(stderr, "SAVE: %dx%d+%d+%d\n", w, h, x, y); 3503 + if (w > rcSavedArea_w || h > rcSavedArea_h) { 3504 + new_pixmap(0, 0); 3505 + } 3506 + 3507 + XPutImage(dpy, rcSavedArea, gc, image, x, y, 0, 0, w, h); 3508 + } 3509 + } 3510 + } else { 3511 + 3512 +#define XE(s) if (XError_ign > 1) {fprintf(stderr, "X-%d\n", (s)); db = 1;} 3513 + 3514 + /* Restore screen area. */ 3515 + if (appData.useXserverBackingStore) { 3516 + XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y); 3517 +XE(1) 3518 + XGetSubImage(dpy, rcSavedArea, 0, 0, w, h, AllPlanes, ZPixmap, image, x, y); 3519 +XE(2) 3520 + 3521 + } else { 3522 + if (image_scale != NULL && scale_x > 0) { 3523 + int Bpp = image_scale->bits_per_pixel / 8; 3524 + int Bpl = image_scale->bytes_per_line; 3525 + int i; 3526 + char *dst = image_scale->data + y * Bpl + x * Bpp; 3527 + char *src = rcSavedScale; 3528 + 3529 + XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, ws, hs, xs, ys); 3530 +XE(3) 3531 + XGetSubImage(dpy, rcSavedArea, 0, 0, ws, hs, AllPlanes, ZPixmap, image, xs, ys); 3532 +XE(4) 3533 +if (db) fprintf(stderr, "rstr: %dx%d+%d+%d\n", ws, hs, xs, ys); 3534 + 3535 + for (i=0; i < h; i++) { 3536 + memcpy(dst, src, Bpp * w); 3537 + src += Bpp * w; 3538 + dst += Bpl; 3539 + } 3540 + } else { 3541 + 3542 + if (scale_saved) { 3543 + XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, ss_w, ss_h, x, y); 3544 +XE(5) 3545 + XGetSubImage(dpy, rcSavedArea, 0, 0, ss_w, ss_h, AllPlanes, ZPixmap, image, x, y); 3546 +XE(6) 3547 + new_pixmap(w, h); 3548 + } else { 3549 + XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y); 3550 +XE(7) 3551 + XGetSubImage(dpy, rcSavedArea, 0, 0, w, h, AllPlanes, ZPixmap, image, x, y); 3552 +XE(8) 3553 + } 3554 + 3555 +if (db) fprintf(stderr, "RSTR: %dx%d+%d+%d\n", w, h, x, y); 3556 + 3557 + } 3558 + } 3559 + } 3560 + 3561 + if (XError_ign > 1) { 3562 + fprintf(stderr, "XError_ign: %d, oper: %s\n", XError_ign, oper ? "restore" : "save"); 3563 + } 3564 + 3565 + XError_ign = 0; 3566 } 3567 3568 static void SoftCursorDraw(void) 3569 @@ -472,43 +650,182 @@ 3570 int offset, bytesPerPixel; 3571 char *pos; 3572 3573 +#define alphahack 3574 +#ifdef alphahack 3575 + /* hack to have cursor transparency at 32bpp <runge (a] karlrunge.com> */ 3576 + int alphablend = 0; 3577 + 3578 + if (!rcSource) { 3579 + return; 3580 + } 3581 + 3582 + if (appData.useCursorAlpha) { 3583 + alphablend = 1; 3584 + } 3585 + 3586 bytesPerPixel = myFormat.bitsPerPixel / 8; 3587 3588 - /* FIXME: Speed optimization is possible. */ 3589 - for (y = 0; y < rcHeight; y++) { 3590 - y0 = rcCursorY - rcHotY + y; 3591 - if (y0 >= 0 && y0 < si.framebufferHeight) { 3592 - for (x = 0; x < rcWidth; x++) { 3593 - x0 = rcCursorX - rcHotX + x; 3594 - if (x0 >= 0 && x0 < si.framebufferWidth) { 3595 - offset = y * rcWidth + x; 3596 - if (rcMask[offset]) { 3597 - pos = (char *)&rcSource[offset * bytesPerPixel]; 3598 - CopyDataToScreen(pos, x0, y0, 1, 1); 3599 - } 3600 + if (alphablend && bytesPerPixel == 4) { 3601 + unsigned long pixel, put, *upos, *upix; 3602 + int got_alpha = 0, rsX, rsY, rsW, rsH; 3603 + static XImage *alpha_image = NULL; 3604 + static int iwidth = 192; 3605 + 3606 + if (! alpha_image) { 3607 + /* watch out for tiny fb (rare) */ 3608 + if (iwidth > si.framebufferWidth) { 3609 + iwidth = si.framebufferWidth; 3610 + } 3611 + if (iwidth > si.framebufferHeight) { 3612 + iwidth = si.framebufferHeight; 3613 + } 3614 + 3615 + /* initialize an XImage with a chunk of desktopWin */ 3616 + alpha_image = XGetImage(dpy, desktopWin, 0, 0, iwidth, iwidth, 3617 + AllPlanes, ZPixmap); 3618 } 3619 - } 3620 - } 3621 + 3622 + /* first check if there is any non-zero alpha channel data at all: */ 3623 + for (y = 0; y < rcHeight; y++) { 3624 + for (x = 0; x < rcWidth; x++) { 3625 + int alpha; 3626 + 3627 + offset = y * rcWidth + x; 3628 + pos = (char *)&rcSource[offset * bytesPerPixel]; 3629 + 3630 + upos = (unsigned long *) pos; 3631 + alpha = (*upos & 0xff000000) >> 24; 3632 + if (alpha) { 3633 + got_alpha = 1; 3634 + break; 3635 + } 3636 + } 3637 + if (got_alpha) { 3638 + break; 3639 + } 3640 + } 3641 + 3642 + if (!got_alpha) { 3643 + /* no alpha channel data, fallback to the old way */ 3644 + goto oldway; 3645 + } 3646 + 3647 + /* load the saved fb patch in to alpha_image (faster way?) */ 3648 + if (image_scale != NULL && scale_x > 0) { 3649 + XGetSubImage(dpy, rcSavedArea_0, 0, 0, rcWidth, rcHeight, AllPlanes, ZPixmap, alpha_image, 0, 0); 3650 + } else { 3651 + XGetSubImage(dpy, rcSavedArea, 0, 0, rcWidth, rcHeight, AllPlanes, ZPixmap, alpha_image, 0, 0); 3652 + } 3653 + 3654 + upix = (unsigned long *)alpha_image->data; 3655 + 3656 + /* if the richcursor is clipped, the fb patch will be smaller */ 3657 + rsW = rcWidth; 3658 + rsX = 0; /* used to denote a shift from the left side */ 3659 + x = rcCursorX - rcHotX; 3660 + if (x < 0) { 3661 + rsW += x; 3662 + rsX = -x; 3663 + } else if (x + rsW > si.framebufferWidth) { 3664 + rsW = si.framebufferWidth - x; 3665 + } 3666 + rsH = rcHeight; 3667 + rsY = 0; /* used to denote a shift from the top side */ 3668 + y = rcCursorY - rcHotY; 3669 + if (y < 0) { 3670 + rsH += y; 3671 + rsY = -y; 3672 + } else if (y + rsH > si.framebufferHeight) { 3673 + rsH = si.framebufferHeight - y; 3674 + } 3675 + 3676 + /* 3677 + * now loop over the cursor data, blend in the fb values, 3678 + * and then overwrite the fb (CopyDataToScreen()) 3679 + */ 3680 + for (y = 0; y < rcHeight; y++) { 3681 + y0 = rcCursorY - rcHotY + y; 3682 + if (y0 < 0 || y0 >= si.framebufferHeight) { 3683 + continue; /* clipped */ 3684 + } 3685 + for (x = 0; x < rcWidth; x++) { 3686 + int alpha, color_curs, color_fb, i; 3687 + 3688 + x0 = rcCursorX - rcHotX + x; 3689 + if (x0 < 0 || x0 >= si.framebufferWidth) { 3690 + continue; /* clipped */ 3691 + } 3692 + 3693 + offset = y * rcWidth + x; 3694 + pos = (char *)&rcSource[offset * bytesPerPixel]; 3695 + 3696 + /* extract secret alpha byte from rich cursor: */ 3697 + upos = (unsigned long *) pos; 3698 + alpha = (*upos & 0xff000000) >> 24; /* XXX MSB? */ 3699 + 3700 + /* extract the pixel from the fb: */ 3701 + pixel = *(upix + (y-rsY)*iwidth + (x-rsX)); 3702 + 3703 + put = 0; 3704 + /* for simplicity, blend all 4 bytes */ 3705 + for (i = 0; i < 4; i++) { 3706 + int sh = i*8; 3707 + color_curs = ((0xff << sh) & *upos) >> sh; 3708 + color_fb = ((0xff << sh) & pixel) >> sh; 3709 + 3710 + /* XXX assumes pre-multipled color_curs */ 3711 + color_fb = color_curs 3712 + + ((0xff - alpha) * color_fb)/0xff; 3713 + put |= color_fb << sh; 3714 + } 3715 + /* place in the fb: */ 3716 + CopyDataToScreen((char *)&put, x0, y0, 1, 1); 3717 + } 3718 + } 3719 + return; 3720 } 3721 +oldway: 3722 +#endif 3723 + 3724 + bytesPerPixel = myFormat.bitsPerPixel / 8; 3725 + 3726 + /* FIXME: Speed optimization is possible. */ 3727 + for (y = 0; y < rcHeight; y++) { 3728 + y0 = rcCursorY - rcHotY + y; 3729 + if (y0 >= 0 && y0 < si.framebufferHeight) { 3730 + for (x = 0; x < rcWidth; x++) { 3731 + x0 = rcCursorX - rcHotX + x; 3732 + if (x0 >= 0 && x0 < si.framebufferWidth) { 3733 + offset = y * rcWidth + x; 3734 + if (rcMask[offset]) { 3735 + pos = (char *)&rcSource[offset * bytesPerPixel]; 3736 + CopyDataToScreen(pos, x0, y0, 1, 1); 3737 + } 3738 + } 3739 + } 3740 + } 3741 + } 3742 + XSync(dpy, False); 3743 } 3744 3745 -static void FreeSoftCursor(void) 3746 +void FreeSoftCursor(void) 3747 { 3748 - if (prevSoftCursorSet) { 3749 - SoftCursorCopyArea(OPER_RESTORE); 3750 - XFreePixmap(dpy, rcSavedArea); 3751 - free(rcSource); 3752 - free(rcMask); 3753 - prevSoftCursorSet = False; 3754 - } 3755 + if (prevSoftCursorSet) { 3756 + SoftCursorCopyArea(OPER_RESTORE); 3757 + XFreePixmap(dpy, rcSavedArea); 3758 + XFreePixmap(dpy, rcSavedArea_0); 3759 + free(rcSource); 3760 + rcSource = NULL; 3761 + free(rcMask); 3762 + prevSoftCursorSet = False; 3763 + } 3764 } 3765 3766 3767 -static void FreeX11Cursor() 3768 +void FreeX11Cursor() 3769 { 3770 - if (prevXCursorSet) { 3771 - XFreeCursor(dpy, prevXCursor); 3772 - prevXCursorSet = False; 3773 - } 3774 + if (prevXCursorSet) { 3775 + XFreeCursor(dpy, prevXCursor); 3776 + prevXCursorSet = False; 3777 + } 3778 } 3779 - 3780 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncviewer/desktop.c 3781 --- vnc_unixsrc.orig/vncviewer/desktop.c 2004-05-28 13:29:29.000000000 -0400 3782 +++ vnc_unixsrc/vncviewer/desktop.c 2010-02-25 22:32:49.000000000 -0500 3783 @@ -28,28 +28,497 @@ 3784 #include <X11/extensions/XShm.h> 3785 #endif 3786 3787 +#include <X11/cursorfont.h> 3788 + 3789 GC gc; 3790 GC srcGC, dstGC; /* used for debugging copyrect */ 3791 Window desktopWin; 3792 -Cursor dotCursor; 3793 +Cursor dotCursor3 = None; 3794 +Cursor dotCursor4 = None; 3795 +Cursor bogoCursor = None; 3796 +Cursor waitCursor = None; 3797 Widget form, viewport, desktop; 3798 3799 +int appshare_0_hint = -10000; 3800 +int appshare_x_hint = -10000; 3801 +int appshare_y_hint = -10000; 3802 + 3803 static Bool modifierPressed[256]; 3804 3805 -static XImage *image = NULL; 3806 +XImage *image = NULL; 3807 +XImage *image_ycrop = NULL; 3808 +XImage *image_scale = NULL; 3809 + 3810 +int image_is_shm = 0; 3811 3812 static Cursor CreateDotCursor(); 3813 static void CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width,int height); 3814 static void HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev, 3815 Boolean *cont); 3816 3817 +static void CopyBGR565ToScreen(CARD16 *buf, int x, int y, int width,int height); 3818 + 3819 static XtResource desktopBackingStoreResources[] = { 3820 { 3821 - XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof(int), 0, 3822 - XtRImmediate, (XtPointer) Always, 3823 + XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof(int), 0, 3824 + XtRImmediate, (XtPointer) Always, 3825 }, 3826 }; 3827 3828 +double scale_factor_x = 0.0; 3829 +double scale_factor_y = 0.0; 3830 +int scale_x = 0, scale_y = 0; 3831 +int scale_round(int len, double fac); 3832 + 3833 +double last_rescale = 0.0; 3834 +double last_fullscreen = 0.0; 3835 +double start_time = 0.0; 3836 + 3837 +int prev_fb_width = -1; 3838 +int prev_fb_height = -1; 3839 + 3840 +void get_scale_values(double *fx, double *fy) { 3841 + char *s = appData.scale; 3842 + double f, frac_x = -1.0, frac_y = -1.0; 3843 + int n, m; 3844 + int xmax = si.framebufferWidth; 3845 + int ymax = si.framebufferHeight; 3846 + 3847 + if (appData.yCrop > 0) { 3848 + ymax = appData.yCrop; 3849 + } 3850 + 3851 + if (sscanf(s, "%d/%d", &n, &m) == 2) { 3852 + if (m == 0) { 3853 + frac_x = 1.0; 3854 + } else { 3855 + frac_x = ((double) n) / ((double) m); 3856 + } 3857 + } 3858 + if (sscanf(s, "%dx%d", &n, &m) == 2) { 3859 + frac_x = ((double) n) / ((double) xmax); 3860 + frac_y = ((double) m) / ((double) ymax); 3861 + } 3862 + if (!strcasecmp(s, "fit")) { 3863 + frac_x = ((double) dpyWidth) / ((double) xmax); 3864 + frac_y = ((double) dpyHeight) / ((double) ymax); 3865 + } 3866 + if (!strcasecmp(s, "auto")) { 3867 + Dimension w, h; 3868 + XtVaGetValues(toplevel, XtNheight, &h, XtNwidth, &w, NULL); 3869 + fprintf(stderr, "auto: %dx%d\n", w, h); 3870 + if (w > 32 && h > 32) { 3871 + frac_x = ((double) w) / ((double) xmax); 3872 + frac_y = ((double) h) / ((double) ymax); 3873 + } 3874 + } 3875 + if (frac_x < 0.0 && sscanf(s, "%lf", &f) == 1) { 3876 + if (f > 0.0) { 3877 + frac_x = f; 3878 + } 3879 + } 3880 + 3881 + if (frac_y < 0.0) { 3882 + frac_y = frac_x; 3883 + } 3884 + 3885 + if (frac_y > 0.0 && frac_x > 0.0) { 3886 + if (fx != NULL) { 3887 + *fx = frac_x; 3888 + } 3889 + if (fy != NULL) { 3890 + *fy = frac_y; 3891 + } 3892 + } else { 3893 + if (appData.scale) { 3894 + fprintf(stderr, "Invalid scale string: '%s'\n", appData.scale); 3895 + } else { 3896 + fprintf(stderr, "Invalid scale string.\n"); 3897 + } 3898 + appData.scale = NULL; 3899 + } 3900 +} 3901 + 3902 +void try_create_image(void); 3903 +void put_image(int src_x, int src_y, int dst_x, int dst_y, int width, int height, int solid); 3904 +void create_image(); 3905 + 3906 +/* toplevel -> form -> viewport -> desktop */ 3907 + 3908 +void adjust_Xt_win(int w, int h) { 3909 + int x, y, dw, dh, h0 = h; 3910 + int mw = w, mh = h; 3911 + int autoscale = 0; 3912 + 3913 + if (!appData.fullScreen && appData.scale != NULL && !strcmp(appData.scale, "auto")) { 3914 + autoscale = 1; 3915 + mw = dpyWidth; 3916 + mh = dpyHeight; 3917 + } 3918 + 3919 + if (appData.yCrop > 0) { 3920 + int ycrop = appData.yCrop; 3921 + if (image_scale && scale_factor_y > 0.0) { 3922 + ycrop = scale_round(ycrop, scale_factor_y); 3923 + if (!autoscale) { 3924 + mh = ycrop; 3925 + } 3926 + } 3927 + XtVaSetValues(toplevel, XtNmaxWidth, mw, XtNmaxHeight, mh, XtNwidth, w, XtNheight, ycrop, NULL); 3928 + XtVaSetValues(form, XtNmaxWidth, mw, XtNmaxHeight, mh, XtNwidth, w, XtNheight, ycrop, NULL); 3929 + h0 = ycrop; 3930 + } else { 3931 + XtVaSetValues(toplevel, XtNmaxWidth, mw, XtNmaxHeight, mh, XtNwidth, w, XtNheight, h, NULL); 3932 + } 3933 + 3934 + fprintf(stderr, "adjust_Xt_win: %dx%d & %dx%d\n", w, h, w, h0); 3935 + 3936 + XtVaSetValues(desktop, XtNwidth, w, XtNheight, h, NULL); 3937 + 3938 + XtResizeWidget(desktop, w, h, 0); 3939 + 3940 + if (!autoscale) { 3941 + dw = appData.wmDecorationWidth; 3942 + dh = appData.wmDecorationHeight; 3943 + 3944 + x = (dpyWidth - w - dw)/2; 3945 + y = (dpyHeight - h0 - dh)/2; 3946 + 3947 + XtConfigureWidget(toplevel, x + dw, y + dh, w, h0, 0); 3948 + } 3949 +} 3950 + 3951 +void rescale_image(void) { 3952 + double frac_x, frac_y; 3953 + int w, h; 3954 + 3955 + if (image == NULL) { 3956 + create_image(); 3957 + return; 3958 + } 3959 + 3960 + if (appData.useXserverBackingStore) { 3961 + create_image(); 3962 + return; 3963 + } 3964 + 3965 + if (image == NULL && image_scale == NULL) { 3966 + create_image(); 3967 + return; 3968 + } 3969 + 3970 + if (appData.scale == NULL) { 3971 + /* switching to not scaled */ 3972 + frac_x = frac_y = 1.0; 3973 + } else { 3974 + get_scale_values(&frac_x, &frac_y); 3975 + if (frac_x < 0.0 || frac_y < 0.0) { 3976 + create_image(); 3977 + return; 3978 + } 3979 + } 3980 + 3981 + last_rescale = dnow(); 3982 + 3983 + SoftCursorLockArea(0, 0, si.framebufferWidth, si.framebufferHeight); 3984 + 3985 + if (image_scale == NULL) { 3986 + /* switching from not scaled */ 3987 + int i; 3988 + int Bpl = image->bytes_per_line; 3989 + char *dst, *src = image->data; 3990 + 3991 + image_scale = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL, 3992 + si.framebufferWidth, si.framebufferHeight, BitmapPad(dpy), 0); 3993 + 3994 + image_scale->data = (char *) malloc(image_scale->bytes_per_line * image_scale->height); 3995 + 3996 + fprintf(stderr, "rescale_image: switching from not scaled. created image_scale %dx%d\n", image_scale->width, image_scale->height); 3997 + fprintf(stderr, "rescale_image: copying image -> image_scale %dx%d -> %dx%d\n", image->width, image->height, image_scale->width, image_scale->height); 3998 + 3999 + dst = image_scale->data; 4000 + 4001 + /* copy from image->data */ 4002 + for (i=0; i < image->height; i++) { 4003 + memcpy(dst, src, Bpl); 4004 + dst += Bpl; 4005 + src += Bpl; 4006 + } 4007 + } 4008 + 4009 + /* now destroy image */ 4010 + if (image && image->data) { 4011 + if (UsingShm()) { 4012 + ShmDetach(); 4013 + } 4014 + XDestroyImage(image); 4015 + fprintf(stderr, "rescale_image: destroyed 'image'\n"); 4016 + if (UsingShm()) { 4017 + ShmCleanup(); 4018 + } 4019 + image = NULL; 4020 + } 4021 + if (image_ycrop && image_ycrop->data) { 4022 + XDestroyImage(image_ycrop); 4023 + fprintf(stderr, "rescale_image: destroyed 'image_ycrop'\n"); 4024 + image_ycrop = NULL; 4025 + } 4026 + 4027 + if (frac_x == 1.0 && frac_y == 1.0) { 4028 + /* switching to not scaled */ 4029 + fprintf(stderr, "rescale_image: switching to not scaled.\n"); 4030 + w = si.framebufferWidth; 4031 + h = si.framebufferHeight; 4032 + 4033 + scale_factor_x = 0.0; 4034 + scale_factor_y = 0.0; 4035 + scale_x = 0; 4036 + scale_y = 0; 4037 + } else { 4038 + w = scale_round(si.framebufferWidth, frac_x); 4039 + h = scale_round(si.framebufferHeight, frac_y); 4040 + 4041 + scale_factor_x = frac_x; 4042 + scale_factor_y = frac_y; 4043 + scale_x = w; 4044 + scale_y = h; 4045 + } 4046 + 4047 + adjust_Xt_win(w, h); 4048 + 4049 + fprintf(stderr, "rescale: %dx%d %.4f %.4f\n", w, h, scale_factor_x, scale_factor_y); 4050 + 4051 + try_create_image(); 4052 + 4053 + if (image && image->data && image_scale && frac_x == 1.0 && frac_y == 1.0) { 4054 + /* switched to not scaled */ 4055 + int i; 4056 + int Bpl = image->bytes_per_line; 4057 + char *dst = image->data; 4058 + char *src = image_scale->data; 4059 + 4060 + fprintf(stderr, "rescale_image: switching to not scaled.\n"); 4061 + 4062 + for (i=0; i < image->height; i++) { 4063 + memcpy(dst, src, Bpl); 4064 + dst += Bpl; 4065 + src += Bpl; 4066 + } 4067 + XDestroyImage(image_scale); 4068 + fprintf(stderr, "rescale_image: destroyed 'image_scale'\n"); 4069 + image_scale = NULL; 4070 + } 4071 + 4072 + if (appData.yCrop > 0) { 4073 + int ycrop = appData.yCrop; 4074 + /* do the top part first so they can see it earlier */ 4075 + put_image(0, 0, 0, 0, si.framebufferWidth, ycrop, 0); 4076 + if (si.framebufferHeight > ycrop) { 4077 + /* this is a big fb and so will take a long time */ 4078 + if (waitCursor != None) { 4079 + XDefineCursor(dpy, desktopWin, waitCursor); 4080 + XSync(dpy, False); 4081 + } 4082 + put_image(0, 0, 0, 0, si.framebufferWidth, si.framebufferHeight - ycrop, 0); 4083 + if (waitCursor != None) { 4084 + Xcursors(1); 4085 + if (appData.useX11Cursor) { 4086 + XSetWindowAttributes attr; 4087 + unsigned long valuemask = 0; 4088 + if (appData.viewOnly) { 4089 + attr.cursor = dotCursor4; 4090 + } else { 4091 + attr.cursor = dotCursor3; 4092 + } 4093 + valuemask |= CWCursor; 4094 + XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); 4095 + } 4096 + } 4097 + } 4098 + } else { 4099 + put_image(0, 0, 0, 0, si.framebufferWidth, si.framebufferHeight, 0); 4100 + } 4101 + 4102 + SoftCursorUnlockScreen(); 4103 + 4104 + fprintf(stderr, "rescale: image_scale=%p image=%p image_ycrop=%p\n", (void *) image_scale, (void *) image, (void *) image_ycrop); 4105 + last_rescale = dnow(); 4106 + 4107 +} 4108 + 4109 +void try_create_image(void) { 4110 + 4111 + image_is_shm = 0; 4112 + if (appData.useShm) { 4113 +#ifdef MITSHM 4114 + image = CreateShmImage(0); 4115 + if (!image) { 4116 + if (appData.yCrop > 0) { 4117 + if (appData.scale != NULL && scale_x > 0) { 4118 + ; 4119 + } else { 4120 + image_ycrop = CreateShmImage(1); 4121 + if (!image_ycrop) { 4122 + appData.useShm = False; 4123 + } else { 4124 + fprintf(stderr, "created smaller image_ycrop shm image: %dx%d\n", 4125 + image_ycrop->width, image_ycrop->height); 4126 + } 4127 + } 4128 + } else { 4129 + appData.useShm = False; 4130 + } 4131 + } else { 4132 + image_is_shm = 1; 4133 + fprintf(stderr, "created shm image: %dx%d\n", image->width, image->height); 4134 + } 4135 +#endif 4136 + } 4137 + 4138 + if (!image) { 4139 + fprintf(stderr, "try_create_image: shm image create fail: image == NULL\n"); 4140 + if (scale_x > 0) { 4141 + image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL, 4142 + scale_x, scale_y, BitmapPad(dpy), 0); 4143 + } else { 4144 + image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL, 4145 + si.framebufferWidth, si.framebufferHeight, BitmapPad(dpy), 0); 4146 + } 4147 + 4148 + image->data = malloc(image->bytes_per_line * image->height); 4149 + 4150 + if (!image->data) { 4151 + fprintf(stderr, "try_create_image: malloc failed\n"); 4152 + exit(1); 4153 + } else { 4154 + fprintf(stderr, "try_create_image: created *non-shm* image: %dx%d\n", image->width, image->height); 4155 + } 4156 + } 4157 + fprintf(stderr, "try_create_image: image->bytes_per_line: %d\n", image->bytes_per_line); 4158 +} 4159 + 4160 +void create_image() { 4161 + image = NULL; 4162 + image_ycrop = NULL; 4163 + image_scale = NULL; 4164 + 4165 + fprintf(stderr, "create_image()\n"); 4166 + 4167 + if (CreateShmImage(-1) == NULL) { 4168 + appData.useShm = False; 4169 + } 4170 + if (appData.scale != NULL) { 4171 + if (appData.useXserverBackingStore) { 4172 + fprintf(stderr, "Cannot scale when using X11 backingstore.\n"); 4173 + } else { 4174 + double frac_x = -1.0, frac_y = -1.0; 4175 + 4176 + get_scale_values(&frac_x, &frac_y); 4177 + 4178 + if (frac_x < 0.0 || frac_y < 0.0) { 4179 + fprintf(stderr, "Cannot figure out scale factor!\n"); 4180 + goto bork; 4181 + } 4182 + 4183 + scale_factor_x = 0.0; 4184 + scale_factor_y = 0.0; 4185 + scale_x = 0; 4186 + scale_y = 0; 4187 + 4188 + 4189 + if (1) { 4190 + int w, h, hyc; 4191 + 4192 + w = scale_round(si.framebufferWidth, frac_x); 4193 + h = scale_round(si.framebufferHeight, frac_y); 4194 + hyc = h; 4195 + if (appData.yCrop > 0) { 4196 + hyc = scale_round(appData.yCrop, frac_y); 4197 + } 4198 + 4199 + /* image scale is full framebuffer */ 4200 + image_scale = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL, 4201 + si.framebufferWidth, si.framebufferHeight, BitmapPad(dpy), 0); 4202 + 4203 + image_scale->data = (char *) malloc(image_scale->bytes_per_line * image_scale->height); 4204 + 4205 + fprintf(stderr, "create_image: created image_scale %dx%d\n", image_scale->width, image_scale->height); 4206 + 4207 + if (!image_scale->data) { 4208 + fprintf(stderr, "create_image: malloc failed\n"); 4209 + XDestroyImage(image_scale); 4210 + fprintf(stderr, "create_image: destroyed 'image_scale'\n"); 4211 + image_scale = NULL; 4212 + } else { 4213 + int h2; 4214 + scale_factor_x = frac_x; 4215 + scale_factor_y = frac_y; 4216 + scale_x = w; 4217 + scale_y = h; 4218 + 4219 + XtVaSetValues(toplevel, XtNmaxWidth, w, XtNmaxHeight, hyc, NULL); 4220 + 4221 + h2 = scale_round(si.framebufferHeight, frac_y); 4222 + XtVaSetValues(desktop, XtNwidth, w, XtNheight, h2, NULL); 4223 + 4224 + } 4225 + fprintf(stderr, "create_image: scale: %dx%d %.4f %.4f\n", w, h, 4226 + scale_factor_x, scale_factor_y); 4227 + } 4228 + } 4229 + } 4230 + bork: 4231 + try_create_image(); 4232 +} 4233 + 4234 +int old_width = 0; 4235 +int old_height = 0; 4236 + 4237 +int guessCrop(void) { 4238 + int w = si.framebufferWidth; 4239 + 4240 + if (w == 320) { 4241 + return 240; 4242 + } else if (w == 400) { 4243 + return 300; 4244 + } else if (w == 640) { 4245 + return 480; 4246 + } else if (w == 800) { 4247 + return 600; 4248 + } else if (w == 1024) { 4249 + return 768; 4250 + } else if (w == 1152) { 4251 + return 864; 4252 + } else if (w == 1280) { 4253 + return 1024; 4254 + } else if (w == 1440) { 4255 + return 900; 4256 + } else if (w == 1600) { 4257 + return 1200; 4258 + } else if (w == 1680) { 4259 + return 1050; 4260 + } else if (w == 1920) { 4261 + return 1200; 4262 + } else { 4263 + int h = (3 * w) / 4; 4264 + return h; 4265 + } 4266 +} 4267 + 4268 +void check_tall(void) { 4269 + if (appData.appShare) { 4270 + return; 4271 + } 4272 + if (! appData.yCrop) { 4273 + int w = si.framebufferWidth; 4274 + int h = si.framebufferHeight; 4275 + if (h > 2 * w) { 4276 + fprintf(stderr, "Tall display (%dx%d) suspect 'x11vnc -ncache' mode,\n", w, h); 4277 + fprintf(stderr, " setting auto -ycrop detection.\n"); 4278 + appData.yCrop = -1; 4279 + } 4280 + } 4281 +} 4282 4283 /* 4284 * DesktopInitBeforeRealization creates the "desktop" widget and the viewport 4285 @@ -59,91 +528,1023 @@ 4286 void 4287 DesktopInitBeforeRealization() 4288 { 4289 - int i; 4290 + int i; 4291 + int h = si.framebufferHeight; 4292 + int w = si.framebufferWidth; 4293 + double frac_x = 1.0, frac_y = 1.0; 4294 + 4295 + start_time = dnow(); 4296 + 4297 + prev_fb_width = si.framebufferWidth; 4298 + prev_fb_height = si.framebufferHeight; 4299 + 4300 + if (appData.scale != NULL) { 4301 + get_scale_values(&frac_x, &frac_y); 4302 + if (frac_x > 0.0 && frac_y > 0.0) { 4303 + w = scale_round(w, frac_x); 4304 + h = scale_round(h, frac_y); 4305 + } else { 4306 + appData.scale = NULL; 4307 + } 4308 + } 4309 4310 - form = XtVaCreateManagedWidget("form", formWidgetClass, toplevel, 4311 - XtNborderWidth, 0, 4312 - XtNdefaultDistance, 0, NULL); 4313 + form = XtVaCreateManagedWidget("form", formWidgetClass, toplevel, 4314 + XtNborderWidth, 0, XtNdefaultDistance, 0, NULL); 4315 4316 - viewport = XtVaCreateManagedWidget("viewport", viewportWidgetClass, form, 4317 - XtNborderWidth, 0, 4318 - NULL); 4319 + viewport = XtVaCreateManagedWidget("viewport", viewportWidgetClass, form, 4320 + XtNborderWidth, 0, NULL); 4321 4322 - desktop = XtVaCreateManagedWidget("desktop", coreWidgetClass, viewport, 4323 - XtNborderWidth, 0, 4324 - NULL); 4325 + desktop = XtVaCreateManagedWidget("desktop", coreWidgetClass, viewport, 4326 + XtNborderWidth, 0, NULL); 4327 4328 - XtVaSetValues(desktop, XtNwidth, si.framebufferWidth, 4329 - XtNheight, si.framebufferHeight, NULL); 4330 + XtVaSetValues(desktop, XtNwidth, w, XtNheight, h, NULL); 4331 4332 - XtAddEventHandler(desktop, LeaveWindowMask|ExposureMask, 4333 - True, HandleBasicDesktopEvent, NULL); 4334 + XtAddEventHandler(desktop, LeaveWindowMask|EnterWindowMask|ExposureMask, 4335 + True, HandleBasicDesktopEvent, NULL); 4336 4337 - for (i = 0; i < 256; i++) 4338 - modifierPressed[i] = False; 4339 + if (appData.yCrop) { 4340 + int hm; 4341 + if (appData.yCrop < 0) { 4342 + appData.yCrop = guessCrop(); 4343 + fprintf(stderr, "Set -ycrop to: %d\n", appData.yCrop); 4344 + } 4345 + hm = appData.yCrop; 4346 4347 - image = NULL; 4348 + fprintf(stderr, "ycrop h: %d -> %d\n", hm, (int) (hm*frac_y)); 4349 4350 -#ifdef MITSHM 4351 - if (appData.useShm) { 4352 - image = CreateShmImage(); 4353 - if (!image) 4354 - appData.useShm = False; 4355 - } 4356 + hm *= frac_y; 4357 + 4358 + XtVaSetValues(toplevel, XtNmaxHeight, hm, XtNheight, hm, NULL); 4359 + XtVaSetValues(form, XtNmaxHeight, hm, XtNheight, hm, NULL); 4360 + XtVaSetValues(viewport, XtNforceBars, False, NULL); 4361 + XSync(dpy, False); 4362 + } 4363 + 4364 + old_width = si.framebufferWidth; 4365 + old_height = si.framebufferHeight; 4366 + 4367 + for (i = 0; i < 256; i++) { 4368 + modifierPressed[i] = False; 4369 + } 4370 + 4371 + create_image(); 4372 +} 4373 + 4374 +#if 0 4375 +static Widget scrollbar_y = NULL; 4376 +static int xsst = 2; 4377 #endif 4378 4379 - if (!image) { 4380 - image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL, 4381 - si.framebufferWidth, si.framebufferHeight, 4382 - BitmapPad(dpy), 0); 4383 - 4384 - image->data = malloc(image->bytes_per_line * image->height); 4385 - if (!image->data) { 4386 - fprintf(stderr,"malloc failed\n"); 4387 - exit(1); 4388 - } 4389 - } 4390 +#include <X11/Xaw/Scrollbar.h> 4391 + 4392 +#if 0 4393 +static XtCallbackProc Scrolled(Widget w, XtPointer closure, XtPointer call_data) { 4394 + Position x, y; 4395 + XtVaGetValues(desktop, XtNx, &x, XtNy, &y, NULL); 4396 + if (0) fprintf(stderr, "scrolled by %d pixels x=%d y=%d\n", (int) call_data, x, y); 4397 + if (xsst == 2) { 4398 + x = 0; 4399 + y = 0; 4400 + XtVaSetValues(desktop, XtNx, x, XtNy, y, NULL); 4401 + } else if (xsst) { 4402 + XawScrollbarSetThumb(w, 0.0, 0.0); 4403 + } else { 4404 + float t = 0.0; 4405 + XtVaSetValues(w, XtNtopOfThumb, &t, NULL); 4406 + } 4407 + if (closure) {} 4408 } 4409 4410 +static XtCallbackProc Jumped(Widget w, XtPointer closure, XtPointer call_data) { 4411 + float top = *((float *) call_data); 4412 + Position x, y; 4413 + XtVaGetValues(desktop, XtNx, &x, XtNy, &y, NULL); 4414 + if (0) fprintf(stderr, "thumb value: %.4f x=%d y=%d\n", top, x, y); 4415 + if (top > 0.01) { 4416 + if (xsst == 2) { 4417 + x = 0; 4418 + y = 0; 4419 + XtVaSetValues(desktop, XtNx, x, XtNy, y, NULL); 4420 + } else if (xsst) { 4421 + XawScrollbarSetThumb(w, 0.0, 0.0); 4422 + } else { 4423 + float t = 0.0, s = 1.0; 4424 + XtVaSetValues(w, XtNtopOfThumb, *(XtArgVal*)&t, XtNshown, *(XtArgVal*)&s, NULL); 4425 + } 4426 + } 4427 + if (closure) {} 4428 +} 4429 +#endif 4430 + 4431 +extern double dnow(void); 4432 + 4433 +void check_things() { 4434 + static int first = 1; 4435 + static double last_scrollbar = 0.0; 4436 + int w = si.framebufferWidth; 4437 + int h = si.framebufferHeight; 4438 + double now = dnow(); 4439 + static double last = 0; 4440 + double fac = image_scale ? scale_factor_y : 1.0; 4441 + 4442 + if (first) { 4443 + first = 0; 4444 + SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False); 4445 + } 4446 + if (appData.yCrop > 0 && appData.yCrop * fac < dpyHeight && h > 2*w && now > last_scrollbar + 0.25) { 4447 + Widget wv, wh, wc; 4448 + Position x0, y0; 4449 + Position x1, y1; 4450 + Dimension w0, h0, b0; 4451 + Dimension w1, h1, b1; 4452 + Dimension w2, h2, b2; 4453 + 4454 + wc = XtNameToWidget(viewport, "clip"); 4455 + wv = XtNameToWidget(viewport, "vertical"); 4456 + wh = XtNameToWidget(viewport, "horizontal"); 4457 + if (wc && wv && wh) { 4458 + int sb = appData.sbWidth; 4459 + XtVaGetValues(wv, XtNwidth, &w0, XtNheight, &h0, XtNborderWidth, &b0, XtNx, &x0, XtNy, &y0, NULL); 4460 + XtVaGetValues(wh, XtNwidth, &w1, XtNheight, &h1, XtNborderWidth, &b1, XtNx, &x1, XtNy, &y1, NULL); 4461 + XtVaGetValues(wc, XtNwidth, &w2, XtNheight, &h2, XtNborderWidth, &b2, NULL); 4462 + if (!sb) { 4463 + sb = 2; 4464 + } 4465 + if (w0 != sb || h1 != sb) { 4466 + fprintf(stderr, "Very tall (-ncache) fb, setting scrollbar thickness to: %d pixels (%d/%d)\n\n", sb, w0, h1); 4467 + 4468 + XtUnmanageChild(wv); 4469 + XtUnmanageChild(wh); 4470 + XtUnmanageChild(wc); 4471 + 4472 + XtVaSetValues(wv, XtNwidth, sb, XtNx, x0 + (w0 - sb), NULL); 4473 + XtVaSetValues(wh, XtNheight, sb, XtNy, y1 + (h1 - sb), NULL); 4474 + w2 = w2 + (w0 - sb); 4475 + h2 = h2 + (h1 - sb); 4476 + if (w2 > 10 && h2 > 10) { 4477 + XtVaSetValues(wc, XtNwidth, w2, XtNheight, h2, NULL); 4478 + } 4479 + 4480 + XtManageChild(wv); 4481 + XtManageChild(wh); 4482 + XtManageChild(wc); 4483 + 4484 + appData.sbWidth = sb; 4485 + } 4486 + } 4487 + last_scrollbar = dnow(); 4488 + } 4489 + 4490 + if (now <= last + 0.25) { 4491 + return; 4492 + } 4493 + 4494 + if (image_scale) { 4495 + scale_check_zrle(); 4496 + } 4497 + 4498 + /* e.g. xrandr resize */ 4499 + dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy)); 4500 + dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy)); 4501 + 4502 + if (appData.scale != NULL) { 4503 + static Dimension last_w = 0, last_h = 0; 4504 + static double last_resize = 0.0; 4505 + Dimension w, h; 4506 + if (last_w == 0) { 4507 + XtVaGetValues(toplevel, XtNwidth, &last_w, XtNheight, &last_h, NULL); 4508 + last_resize = now; 4509 + } 4510 + if (now < last_resize + 0.5) { 4511 + ; 4512 + } else if (appData.fullScreen) { 4513 + ; 4514 + } else if (!strcmp(appData.scale, "auto")) { 4515 + XtVaGetValues(toplevel, XtNwidth, &w, XtNheight, &h, NULL); 4516 + if (w < 32 || h < 32) { 4517 + ; 4518 + } else if (last_w != w || last_h != h) { 4519 + Window rr, cr, r = DefaultRootWindow(dpy); 4520 + int rx, ry, wx, wy; 4521 + unsigned int mask; 4522 + /* make sure mouse buttons not pressed */ 4523 + if (XQueryPointer(dpy, r, &rr, &cr, &rx, &ry, &wx, &wy, &mask)) { 4524 + if (mask == 0) { 4525 + rescale_image(); 4526 + last_w = w; 4527 + last_h = h; 4528 + last_resize = dnow(); 4529 + } 4530 + } 4531 + } 4532 + } 4533 + } 4534 + 4535 + last = dnow(); 4536 +} 4537 4538 /* 4539 * DesktopInitAfterRealization does things which require the X windows to 4540 * exist. It creates some GCs and sets the dot cursor. 4541 */ 4542 4543 +void Xcursors(int set) { 4544 + if (dotCursor3 == None) { 4545 + dotCursor3 = CreateDotCursor(3); 4546 + } 4547 + if (dotCursor4 == None) { 4548 + dotCursor4 = CreateDotCursor(4); 4549 + } 4550 + if (set) { 4551 + XSetWindowAttributes attr; 4552 + unsigned long valuemask = 0; 4553 + 4554 + if (!appData.useX11Cursor) { 4555 + if (appData.viewOnly) { 4556 + attr.cursor = dotCursor4; 4557 + } else { 4558 + attr.cursor = dotCursor3; 4559 + } 4560 + valuemask |= CWCursor; 4561 + XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); 4562 + } 4563 + } 4564 +} 4565 + 4566 void 4567 DesktopInitAfterRealization() 4568 { 4569 - XGCValues gcv; 4570 - XSetWindowAttributes attr; 4571 - unsigned long valuemask; 4572 - 4573 - desktopWin = XtWindow(desktop); 4574 - 4575 - gc = XCreateGC(dpy,desktopWin,0,NULL); 4576 - 4577 - gcv.function = GXxor; 4578 - gcv.foreground = 0x0f0f0f0f; 4579 - srcGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv); 4580 - gcv.foreground = 0xf0f0f0f0; 4581 - dstGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv); 4582 - 4583 - XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore, 4584 - NULL, 0); 4585 - 4586 - XtVaGetApplicationResources(desktop, (XtPointer)&attr.backing_store, 4587 - desktopBackingStoreResources, 1, NULL); 4588 - valuemask = CWBackingStore; 4589 - 4590 - if (!appData.useX11Cursor) { 4591 - dotCursor = CreateDotCursor(); 4592 - attr.cursor = dotCursor; 4593 - valuemask |= CWCursor; 4594 - } 4595 + XGCValues gcv; 4596 + XSetWindowAttributes attr; 4597 + XWindowAttributes gattr; 4598 + unsigned long valuemask = 0; 4599 + 4600 + desktopWin = XtWindow(desktop); 4601 + 4602 + gc = XCreateGC(dpy,desktopWin,0,NULL); 4603 + 4604 + gcv.function = GXxor; 4605 + gcv.foreground = 0x0f0f0f0f; 4606 + srcGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv); 4607 + gcv.foreground = 0xf0f0f0f0; 4608 + dstGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv); 4609 + 4610 + XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore, 4611 + NULL, 0); 4612 + 4613 + if (appData.useXserverBackingStore) { 4614 + Screen *s = DefaultScreenOfDisplay(dpy); 4615 + if (DoesBackingStore(s) != Always) { 4616 + fprintf(stderr, "X server does not do backingstore, disabling it.\n"); 4617 + appData.useXserverBackingStore = False; 4618 + } 4619 + } 4620 + 4621 + if (appData.useXserverBackingStore) { 4622 + XtVaGetApplicationResources(desktop, (XtPointer)&attr.backing_store, 4623 + desktopBackingStoreResources, 1, NULL); 4624 + valuemask |= CWBackingStore; 4625 + } else { 4626 + attr.background_pixel = BlackPixel(dpy, DefaultScreen(dpy)); 4627 + valuemask |= CWBackPixel; 4628 + } 4629 + 4630 + Xcursors(0); 4631 + if (!appData.useX11Cursor) { 4632 + if (appData.viewOnly) { 4633 + attr.cursor = dotCursor4; 4634 + } else { 4635 + attr.cursor = dotCursor3; 4636 + } 4637 + valuemask |= CWCursor; 4638 + } 4639 + bogoCursor = XCreateFontCursor(dpy, XC_bogosity); 4640 + waitCursor = XCreateFontCursor(dpy, XC_watch); 4641 + 4642 + XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); 4643 + 4644 + if (XGetWindowAttributes(dpy, desktopWin, &gattr)) { 4645 +#if 0 4646 + fprintf(stderr, "desktopWin backingstore: %d save_under: %d\n", gattr.backing_store, gattr.save_under); 4647 +#endif 4648 + } 4649 + fprintf(stderr, "\n"); 4650 +} 4651 + 4652 +extern void FreeX11Cursor(void); 4653 +extern void FreeSoftCursor(void); 4654 4655 - XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); 4656 +void 4657 +DesktopCursorOff() 4658 +{ 4659 + if (dotCursor3 == None) { 4660 + dotCursor3 = CreateDotCursor(3); 4661 + dotCursor4 = CreateDotCursor(4); 4662 + } 4663 + if (appData.viewOnly) { 4664 + XDefineCursor(dpy, desktopWin, dotCursor4); 4665 + } else { 4666 + XDefineCursor(dpy, desktopWin, dotCursor3); 4667 + } 4668 + FreeX11Cursor(); 4669 + FreeSoftCursor(); 4670 +} 4671 + 4672 + 4673 +#define CEIL(x) ( (double) ((int) (x)) == (x) ? \ 4674 + (double) ((int) (x)) : (double) ((int) (x) + 1) ) 4675 +#define FLOOR(x) ( (double) ((int) (x)) ) 4676 + 4677 +#if 0 4678 +static int nfix(int i, int n) { 4679 + if (i < 0) { 4680 + i = 0; 4681 + } else if (i >= n) { 4682 + i = n - 1; 4683 + } 4684 + return i; 4685 } 4686 +#else 4687 +#define nfix(i, n) ( i < 0 ? 0 : ( (i >= n) ? (n - 1) : i ) ) 4688 +#endif 4689 + 4690 +int scale_round(int len, double fac) { 4691 + double eps = 0.000001; 4692 + 4693 + len = (int) (len * fac + eps); 4694 + if (len < 1) { 4695 + len = 1; 4696 + } 4697 + return len; 4698 +} 4699 + 4700 +static void scale_rect(double factor_x, double factor_y, int blend, int interpolate, 4701 + int *px, int *py, int *pw, int *ph, int solid) { 4702 + 4703 + int i, j, i1, i2, j1, j2; /* indices for scaled fb (dest) */ 4704 + int I, J, I1, I2, J1, J2; /* indices for main fb (source) */ 4705 + 4706 + double w, wx, wy, wtot; /* pixel weights */ 4707 + 4708 + double x1 = 0, y1, x2 = 0, y2; /* x-y coords for destination pixels edges */ 4709 + double dx, dy; /* size of destination pixel */ 4710 + double ddx=0, ddy=0; /* for interpolation expansion */ 4711 + 4712 + char *src, *dest; /* pointers to the two framebuffers */ 4713 + 4714 + unsigned short us = 0; 4715 + unsigned char uc = 0; 4716 + unsigned int ui = 0; 4717 + 4718 + int use_noblend_shortcut = 1; 4719 + int shrink; /* whether shrinking or expanding */ 4720 + static int constant_weights = -1, mag_int = -1; 4721 + static int last_Nx = -1, last_Ny = -1, cnt = 0; 4722 + static double last_factor = -1.0; 4723 + int b, k; 4724 + double pixave[4]; /* for averaging pixel values */ 4725 + 4726 + /* internal */ 4727 + 4728 + int X1, X2, Y1, Y2; 4729 4730 + int Nx = si.framebufferWidth; 4731 + int Ny = si.framebufferHeight; 4732 + 4733 + int nx = scale_round(Nx, factor_x); 4734 + int ny = scale_round(Ny, factor_y); 4735 + 4736 + int Bpp = image->bits_per_pixel / 8; 4737 + int dst_bytes_per_line = image->bytes_per_line; 4738 + int src_bytes_per_line = image_scale->bytes_per_line; 4739 + 4740 + unsigned long main_red_mask = image->red_mask; 4741 + unsigned long main_green_mask = image->green_mask; 4742 + unsigned long main_blue_mask = image->blue_mask; 4743 + int mark = 1; 4744 + 4745 + char *src_fb = image_scale->data; 4746 + char *dst_fb = image->data; 4747 + 4748 + static int nosolid = -1; 4749 + int sbdy = 3; 4750 + double fmax = factor_x > factor_y ? factor_x : factor_y; 4751 +#if 0 4752 + double fmin = factor_x < factor_y ? factor_x : factor_y; 4753 +#endif 4754 + 4755 + X1 = *px; 4756 + X2 = *px + *pw; 4757 + Y1 = *py; 4758 + Y2 = *py + *ph; 4759 + 4760 + if (fmax > 1.0) { 4761 + /* try to avoid problems with bleeding... */ 4762 + sbdy = (int) (2.0 * fmax * sbdy); 4763 + } 4764 + 4765 + /* fprintf(stderr, "scale_rect: %dx%d+%d+%d\n", *pw, *ph, *px, *py); */ 4766 + 4767 + *px = (int) (*px * factor_x); 4768 + *py = (int) (*py * factor_y); 4769 + *pw = scale_round(*pw, factor_x); 4770 + *ph = scale_round(*ph, factor_y); 4771 + 4772 + if (nosolid < 0) { 4773 + if (getenv("SSVNC_NOSOLID")) { 4774 + nosolid = 1; 4775 + } else { 4776 + nosolid = 0; 4777 + } 4778 + } 4779 + if (nosolid) solid = 0; 4780 + 4781 +#define rfbLog printf 4782 +/* Begin taken from x11vnc scale: */ 4783 + 4784 + if (factor_x <= 1.0 || factor_y <= 1.0) { 4785 + shrink = 1; 4786 + } else { 4787 + shrink = 0; 4788 + interpolate = 1; 4789 + } 4790 + 4791 + /* 4792 + * N.B. width and height (real numbers) of a scaled pixel. 4793 + * both are > 1 (e.g. 1.333 for -scale 3/4) 4794 + * they should also be equal but we don't assume it. 4795 + * 4796 + * This new way is probably the best we can do, take the inverse 4797 + * of the scaling factor to double precision. 4798 + */ 4799 + dx = 1.0/factor_x; 4800 + dy = 1.0/factor_y; 4801 + 4802 + /* 4803 + * There is some speedup if the pixel weights are constant, so 4804 + * let's special case these. 4805 + * 4806 + * If scale = 1/n and n divides Nx and Ny, the pixel weights 4807 + * are constant (e.g. 1/2 => equal on 2x2 square). 4808 + */ 4809 + if (factor_x != last_factor || Nx != last_Nx || Ny != last_Ny) { 4810 + constant_weights = -1; 4811 + mag_int = -1; 4812 + last_Nx = Nx; 4813 + last_Ny = Ny; 4814 + last_factor = factor_x; 4815 + } 4816 + 4817 + if (constant_weights < 0 && factor_x != factor_y) { 4818 + constant_weights = 0; 4819 + mag_int = 0; 4820 + } else if (constant_weights < 0) { 4821 + int n = 0; 4822 + double factor = factor_x; 4823 + 4824 + constant_weights = 0; 4825 + mag_int = 0; 4826 + 4827 + for (i = 2; i<=128; i++) { 4828 + double test = ((double) 1)/ i; 4829 + double diff, eps = 1.0e-7; 4830 + diff = factor - test; 4831 + if (-eps < diff && diff < eps) { 4832 + n = i; 4833 + break; 4834 + } 4835 + } 4836 + if (! blend || ! shrink || interpolate) { 4837 + ; 4838 + } else if (n != 0) { 4839 + if (Nx % n == 0 && Ny % n == 0) { 4840 + static int didmsg = 0; 4841 + if (mark && ! didmsg) { 4842 + didmsg = 1; 4843 + rfbLog("scale_and_mark_rect: using " 4844 + "constant pixel weight speedup " 4845 + "for 1/%d\n", n); 4846 + } 4847 + constant_weights = 1; 4848 + } 4849 + } 4850 + 4851 + n = 0; 4852 + for (i = 2; i<=32; i++) { 4853 + double test = (double) i; 4854 + double diff, eps = 1.0e-7; 4855 + diff = factor - test; 4856 + if (-eps < diff && diff < eps) { 4857 + n = i; 4858 + break; 4859 + } 4860 + } 4861 + if (! blend && factor > 1.0 && n) { 4862 + mag_int = n; 4863 + } 4864 + } 4865 +if (0) fprintf(stderr, "X1: %d Y1: %d X2: %d Y2: %d\n", X1, Y1, X2, Y2); 4866 + 4867 + if (mark && !shrink && blend) { 4868 + /* 4869 + * kludge: correct for interpolating blurring leaking 4870 + * up or left 1 destination pixel. 4871 + */ 4872 + if (X1 > 0) X1--; 4873 + if (Y1 > 0) Y1--; 4874 + } 4875 + 4876 + /* 4877 + * find the extent of the change the input rectangle induces in 4878 + * the scaled framebuffer. 4879 + */ 4880 + 4881 + /* Left edges: find largest i such that i * dx <= X1 */ 4882 + i1 = FLOOR(X1/dx); 4883 + 4884 + /* Right edges: find smallest i such that (i+1) * dx >= X2+1 */ 4885 + i2 = CEIL( (X2+1)/dx ) - 1; 4886 + 4887 + /* To be safe, correct any overflows: */ 4888 + i1 = nfix(i1, nx); 4889 + i2 = nfix(i2, nx) + 1; /* add 1 to make a rectangle upper boundary */ 4890 + 4891 + /* Repeat above for y direction: */ 4892 + j1 = FLOOR(Y1/dy); 4893 + j2 = CEIL( (Y2+1)/dy ) - 1; 4894 + 4895 + j1 = nfix(j1, ny); 4896 + j2 = nfix(j2, ny) + 1; 4897 + 4898 + /* 4899 + * special case integer magnification with no blending. 4900 + * vision impaired magnification usage is interested in this case. 4901 + */ 4902 + if (mark && ! blend && mag_int && Bpp != 3) { 4903 + int jmin, jmax, imin, imax; 4904 + 4905 + /* outer loop over *source* pixels */ 4906 + for (J=Y1; J < Y2; J++) { 4907 + jmin = J * mag_int; 4908 + jmax = jmin + mag_int; 4909 + for (I=X1; I < X2; I++) { 4910 + /* extract value */ 4911 + src = src_fb + J*src_bytes_per_line + I*Bpp; 4912 + if (Bpp == 4) { 4913 + ui = *((unsigned int *)src); 4914 + } else if (Bpp == 2) { 4915 + us = *((unsigned short *)src); 4916 + } else if (Bpp == 1) { 4917 + uc = *((unsigned char *)src); 4918 + } 4919 + imin = I * mag_int; 4920 + imax = imin + mag_int; 4921 + /* inner loop over *dest* pixels */ 4922 + for (j=jmin; j<jmax; j++) { 4923 + dest = dst_fb + j*dst_bytes_per_line + imin*Bpp; 4924 + for (i=imin; i<imax; i++) { 4925 + if (Bpp == 4) { 4926 + *((unsigned int *)dest) = ui; 4927 + } else if (Bpp == 2) { 4928 + *((unsigned short *)dest) = us; 4929 + } else if (Bpp == 1) { 4930 + *((unsigned char *)dest) = uc; 4931 + } 4932 + dest += Bpp; 4933 + } 4934 + } 4935 + } 4936 + } 4937 + goto markit; 4938 + } 4939 + 4940 + /* set these all to 1.0 to begin with */ 4941 + wx = 1.0; 4942 + wy = 1.0; 4943 + w = 1.0; 4944 + 4945 + /* 4946 + * Loop over destination pixels in scaled fb: 4947 + */ 4948 + for (j=j1; j<j2; j++) { 4949 + int jbdy = 1, I1_solid = 0; 4950 + 4951 + y1 = j * dy; /* top edge */ 4952 + if (y1 > Ny - 1) { 4953 + /* can go over with dy = 1/scale_fac */ 4954 + y1 = Ny - 1; 4955 + } 4956 + y2 = y1 + dy; /* bottom edge */ 4957 + 4958 + /* Find main fb indices covered by this dest pixel: */ 4959 + J1 = (int) FLOOR(y1); 4960 + J1 = nfix(J1, Ny); 4961 + 4962 + if (shrink && ! interpolate) { 4963 + J2 = (int) CEIL(y2) - 1; 4964 + J2 = nfix(J2, Ny); 4965 + } else { 4966 + J2 = J1 + 1; /* simple interpolation */ 4967 + ddy = y1 - J1; 4968 + } 4969 + 4970 + /* destination char* pointer: */ 4971 + dest = dst_fb + j*dst_bytes_per_line + i1*Bpp; 4972 + 4973 + if (solid) { 4974 + if (j1+sbdy <= j && j < j2-sbdy) { 4975 + jbdy = 0; 4976 + x1 = (i1+sbdy) * dx; 4977 + if (x1 > Nx - 1) { 4978 + x1 = Nx - 1; 4979 + } 4980 + I1_solid = (int) FLOOR(x1); 4981 + if (I1_solid >= Nx) I1_solid = Nx - 1; 4982 + } 4983 + } 4984 + 4985 + for (i=i1; i<i2; i++) { 4986 + int solid_skip = 0; 4987 + 4988 + if (solid) { 4989 + /* if the region is solid, we can use the noblend speedup */ 4990 + if (!jbdy && i1+sbdy <= i && i < i2-sbdy) { 4991 + solid_skip = 1; 4992 + /* pixels all the same so use X1: */ 4993 + I1 = I1_solid; 4994 + goto jsolid; 4995 + } 4996 + } 4997 + 4998 + x1 = i * dx; /* left edge */ 4999 + if (x1 > Nx - 1) { 5000 + /* can go over with dx = 1/scale_fac */ 5001 + x1 = Nx - 1; 5002 + } 5003 + x2 = x1 + dx; /* right edge */ 5004 + 5005 + /* Find main fb indices covered by this dest pixel: */ 5006 + I1 = (int) FLOOR(x1); 5007 + if (I1 >= Nx) I1 = Nx - 1; 5008 + 5009 + jsolid: 5010 + cnt++; 5011 + 5012 + if ((!blend && use_noblend_shortcut) || solid_skip) { 5013 + /* 5014 + * The noblend case involves no weights, 5015 + * and 1 pixel, so just copy the value 5016 + * directly. 5017 + */ 5018 + src = src_fb + J1*src_bytes_per_line + I1*Bpp; 5019 + if (Bpp == 4) { 5020 + *((unsigned int *)dest) 5021 + = *((unsigned int *)src); 5022 + } else if (Bpp == 2) { 5023 + *((unsigned short *)dest) 5024 + = *((unsigned short *)src); 5025 + } else if (Bpp == 1) { 5026 + *(dest) = *(src); 5027 + } else if (Bpp == 3) { 5028 + /* rare case */ 5029 + for (k=0; k<=2; k++) { 5030 + *(dest+k) = *(src+k); 5031 + } 5032 + } 5033 + dest += Bpp; 5034 + continue; 5035 + } 5036 + 5037 + if (shrink && ! interpolate) { 5038 + I2 = (int) CEIL(x2) - 1; 5039 + if (I2 >= Nx) I2 = Nx - 1; 5040 + } else { 5041 + I2 = I1 + 1; /* simple interpolation */ 5042 + ddx = x1 - I1; 5043 + } 5044 +#if 0 5045 +if (first) fprintf(stderr, " I1=%d I2=%d J1=%d J2=%d\n", I1, I2, J1, J2); 5046 +#endif 5047 + 5048 + /* Zero out accumulators for next pixel average: */ 5049 + for (b=0; b<4; b++) { 5050 + pixave[b] = 0.0; /* for RGB weighted sums */ 5051 + } 5052 + 5053 + /* 5054 + * wtot is for accumulating the total weight. 5055 + * It should always sum to 1/(scale_fac * scale_fac). 5056 + */ 5057 + wtot = 0.0; 5058 + 5059 + /* 5060 + * Loop over source pixels covered by this dest pixel. 5061 + * 5062 + * These "extra" loops over "J" and "I" make 5063 + * the cache/cacheline performance unclear. 5064 + * For example, will the data brought in from 5065 + * src for j, i, and J=0 still be in the cache 5066 + * after the J > 0 data have been accessed and 5067 + * we are at j, i+1, J=0? The stride in J is 5068 + * main_bytes_per_line, and so ~4 KB. 5069 + * 5070 + * Typical case when shrinking are 2x2 loop, so 5071 + * just two lines to worry about. 5072 + */ 5073 + for (J=J1; J<=J2; J++) { 5074 + /* see comments for I, x1, x2, etc. below */ 5075 + if (constant_weights) { 5076 + ; 5077 + } else if (! blend) { 5078 + if (J != J1) { 5079 + continue; 5080 + } 5081 + wy = 1.0; 5082 + 5083 + /* interpolation scheme: */ 5084 + } else if (! shrink || interpolate) { 5085 + if (J >= Ny) { 5086 + continue; 5087 + } else if (J == J1) { 5088 + wy = 1.0 - ddy; 5089 + } else if (J != J1) { 5090 + wy = ddy; 5091 + } 5092 + 5093 + /* integration scheme: */ 5094 + } else if (J < y1) { 5095 + wy = J+1 - y1; 5096 + } else if (J+1 > y2) { 5097 + wy = y2 - J; 5098 + } else { 5099 + wy = 1.0; 5100 + } 5101 + 5102 + src = src_fb + J*src_bytes_per_line + I1*Bpp; 5103 + 5104 + for (I=I1; I<=I2; I++) { 5105 + 5106 + /* Work out the weight: */ 5107 + 5108 + if (constant_weights) { 5109 + ; 5110 + } else if (! blend) { 5111 + /* 5112 + * Ugh, PseudoColor colormap is 5113 + * bad news, to avoid random 5114 + * colors just take the first 5115 + * pixel. Or user may have 5116 + * specified :nb to fraction. 5117 + * The :fb will force blending 5118 + * for this case. 5119 + */ 5120 + if (I != I1) { 5121 + continue; 5122 + } 5123 + wx = 1.0; 5124 + 5125 + /* interpolation scheme: */ 5126 + } else if (! shrink || interpolate) { 5127 + if (I >= Nx) { 5128 + continue; /* off edge */ 5129 + } else if (I == I1) { 5130 + wx = 1.0 - ddx; 5131 + } else if (I != I1) { 5132 + wx = ddx; 5133 + } 5134 + 5135 + /* integration scheme: */ 5136 + } else if (I < x1) { 5137 + /* 5138 + * source left edge (I) to the 5139 + * left of dest left edge (x1): 5140 + * fractional weight 5141 + */ 5142 + wx = I+1 - x1; 5143 + } else if (I+1 > x2) { 5144 + /* 5145 + * source right edge (I+1) to the 5146 + * right of dest right edge (x2): 5147 + * fractional weight 5148 + */ 5149 + wx = x2 - I; 5150 + } else { 5151 + /* 5152 + * source edges (I and I+1) completely 5153 + * inside dest edges (x1 and x2): 5154 + * full weight 5155 + */ 5156 + wx = 1.0; 5157 + } 5158 + 5159 + w = wx * wy; 5160 + wtot += w; 5161 + 5162 + /* 5163 + * We average the unsigned char value 5164 + * instead of char value: otherwise 5165 + * the minimum (char 0) is right next 5166 + * to the maximum (char -1)! This way 5167 + * they are spread between 0 and 255. 5168 + */ 5169 + if (Bpp == 4) { 5170 + /* unroll the loops, can give 20% */ 5171 + pixave[0] += w * ((unsigned char) *(src )); 5172 + pixave[1] += w * ((unsigned char) *(src+1)); 5173 + pixave[2] += w * ((unsigned char) *(src+2)); 5174 + pixave[3] += w * ((unsigned char) *(src+3)); 5175 + } else if (Bpp == 2) { 5176 + /* 5177 + * 16bpp: trickier with green 5178 + * split over two bytes, so we 5179 + * use the masks: 5180 + */ 5181 + us = *((unsigned short *) src); 5182 + pixave[0] += w*(us & main_red_mask); 5183 + pixave[1] += w*(us & main_green_mask); 5184 + pixave[2] += w*(us & main_blue_mask); 5185 + } else if (Bpp == 1) { 5186 + pixave[0] += w * 5187 + ((unsigned char) *(src)); 5188 + } else { 5189 + for (b=0; b<Bpp; b++) { 5190 + pixave[b] += w * 5191 + ((unsigned char) *(src+b)); 5192 + } 5193 + } 5194 + src += Bpp; 5195 + } 5196 + } 5197 + 5198 + if (wtot <= 0.0) { 5199 + wtot = 1.0; 5200 + } 5201 + wtot = 1.0/wtot; /* normalization factor */ 5202 + 5203 + /* place weighted average pixel in the scaled fb: */ 5204 + if (Bpp == 4) { 5205 + *(dest ) = (char) (wtot * pixave[0]); 5206 + *(dest+1) = (char) (wtot * pixave[1]); 5207 + *(dest+2) = (char) (wtot * pixave[2]); 5208 + *(dest+3) = (char) (wtot * pixave[3]); 5209 + } else if (Bpp == 2) { 5210 + /* 16bpp / 565 case: */ 5211 + pixave[0] *= wtot; 5212 + pixave[1] *= wtot; 5213 + pixave[2] *= wtot; 5214 + us = (main_red_mask & (int) pixave[0]) 5215 + | (main_green_mask & (int) pixave[1]) 5216 + | (main_blue_mask & (int) pixave[2]); 5217 + *( (unsigned short *) dest ) = us; 5218 + } else if (Bpp == 1) { 5219 + *(dest) = (char) (wtot * pixave[0]); 5220 + } else { 5221 + for (b=0; b<Bpp; b++) { 5222 + *(dest+b) = (char) (wtot * pixave[b]); 5223 + } 5224 + } 5225 + dest += Bpp; 5226 + } 5227 + } 5228 + markit: 5229 +/* End taken from x11vnc scale: */ 5230 + if (0) {} 5231 +} 5232 + 5233 +void do_scale_stats(int width, int height) { 5234 + static double calls = 0.0, sum = 0.0, var = 0.0, last = 0.0; 5235 + double A = width * height; 5236 + 5237 + if (last == 0.0) { 5238 + last = dnow(); 5239 + } 5240 + 5241 + calls += 1.0; 5242 + sum += A; 5243 + var += A*A; 5244 + 5245 + if (dnow() > last + 4.0) { 5246 + double cnt = calls; 5247 + if (cnt <= 0.0) cnt = 1.0; 5248 + var /= cnt; 5249 + sum /= cnt; 5250 + var = var - sum * sum; 5251 + if (sum > 0.0) { 5252 + var = var / (sum*sum); 5253 + } 5254 + fprintf(stderr, "scale_rect stats: %10d %10.1f ave: %10.3f var-rat: %10.3f\n", (int) calls, sum * cnt, sum, var); 5255 + 5256 + calls = 0.0; 5257 + sum = 0.0; 5258 + var = 0.0; 5259 + last = dnow(); 5260 + } 5261 +} 5262 + 5263 +void put_image(int src_x, int src_y, int dst_x, int dst_y, int width, 5264 + int height, int solid) { 5265 + int db = 0; 5266 + int xmax = si.framebufferWidth; 5267 + int ymax = si.framebufferHeight; 5268 + 5269 +if (db || 0) fprintf(stderr, "put_image(%d %d %d %d %d %d)\n", src_x, src_y, dst_x, dst_y, width, height); 5270 + 5271 + if (image_scale) { 5272 + int i; 5273 + static int scale_stats = -1; 5274 + 5275 + for (i=0; i < 2; i++) { 5276 + if (src_x > 0) src_x--; 5277 + if (src_y > 0) src_y--; 5278 + } 5279 + for (i=0; i < 4; i++) { 5280 + if (src_x + width < xmax) width++; 5281 + if (src_y + height < ymax) height++; 5282 + } 5283 + 5284 + if (db) fprintf(stderr, "put_image(%d %d %d %d %d %d)\n", src_x, src_y, dst_x, dst_y, width, height); 5285 + if (db) fprintf(stderr, "scale_rect(%d %d %d %d)\n", src_x, src_y, width, height); 5286 + 5287 + if (scale_stats < 0) { 5288 + if (getenv("SSVNC_SCALE_STATS")) { 5289 + scale_stats = 1; 5290 + } else { 5291 + scale_stats = 0; 5292 + } 5293 + } 5294 + if (scale_stats) { 5295 + do_scale_stats(width, height); 5296 + } 5297 + 5298 + scale_rect(scale_factor_x, scale_factor_y, 1, 0, &src_x, &src_y, &width, &height, solid); 5299 + dst_x = src_x; 5300 + dst_y = src_y; 5301 + } 5302 + 5303 +#ifdef MITSHM 5304 + if (appData.useShm) { 5305 + double fac = image_scale ? scale_factor_y : 1.0; 5306 + if (image_ycrop == NULL) { 5307 + if (image_is_shm) { 5308 + XShmPutImage(dpy, desktopWin, gc, image, src_x, src_y, 5309 + dst_x, dst_y, width, height, False); 5310 + } else { 5311 + XPutImage(dpy, desktopWin, gc, image, src_x, src_y, 5312 + dst_x, dst_y, width, height); 5313 + } 5314 + } else if ((width < 32 && height < 32) || height > appData.yCrop * fac) { 5315 + XPutImage(dpy, desktopWin, gc, image, src_x, src_y, 5316 + dst_x, dst_y, width, height); 5317 + } else { 5318 + char *src, *dst; 5319 + int Bpp = image->bits_per_pixel / 8; 5320 + int Bpl = image->bytes_per_line, h; 5321 + int Bpl2 = image_ycrop->bytes_per_line; 5322 + src = image->data + src_y * Bpl + src_x * Bpp; 5323 + dst = image_ycrop->data; 5324 + for (h = 0; h < height; h++) { 5325 + memcpy(dst, src, width * Bpp); 5326 + src += Bpl; 5327 + dst += Bpl2; 5328 + } 5329 + XShmPutImage(dpy, desktopWin, gc, image_ycrop, 0, 0, 5330 + dst_x, dst_y, width, height, False); 5331 + } 5332 + } else 5333 +#endif 5334 + { 5335 + XPutImage(dpy, desktopWin, gc, image, src_x, src_y, 5336 + dst_x, dst_y, width, height); 5337 + } 5338 +} 5339 + 5340 +#if 0 5341 +fprintf(stderr, "non-shmB image %d %d %d %d %d %d\n", src_x, src_y, dst_x, dst_y, width, height); 5342 +fprintf(stderr, "shm image_ycrop %d %d %d %d %d %d\n", 0, 0, dst_x, dst_y, width, height); 5343 +fprintf(stderr, "non-shmA image %d %d %d %d %d %d\n", src_x, src_y, dst_x, dst_y, width, height); 5344 +#endif 5345 + 5346 +void releaseAllPressedModifiers(void) { 5347 + int i; 5348 + static int debug_release = -1; 5349 + if (debug_release < 0) { 5350 + if (getenv("SSVNC_DEBUG_RELEASE")) { 5351 + debug_release = 1; 5352 + } else { 5353 + debug_release = 0; 5354 + } 5355 + } 5356 + if (debug_release) fprintf(stderr, "into releaseAllPressedModifiers()\n"); 5357 + for (i = 0; i < 256; i++) { 5358 + if (modifierPressed[i]) { 5359 + SendKeyEvent(XKeycodeToKeysym(dpy, i, 0), False); 5360 + modifierPressed[i] = False; 5361 + if (debug_release) fprintf(stderr, "releasing[%d] %s\n", i, XKeysymToString(XKeycodeToKeysym(dpy, i, 0))); 5362 + } 5363 + } 5364 +} 5365 + 5366 +#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); 5367 5368 /* 5369 * HandleBasicDesktopEvent - deal with expose and leave events. 5370 @@ -152,42 +1553,529 @@ 5371 static void 5372 HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont) 5373 { 5374 - int i; 5375 + int x, y, width, height; 5376 + double now = dnow(); 5377 5378 - switch (ev->type) { 5379 + if (w || ptr || cont) {} 5380 + 5381 + if (0) { 5382 + PR_EXPOSE; 5383 + } 5384 5385 + 5386 + switch (ev->type) { 5387 case Expose: 5388 case GraphicsExpose: 5389 /* sometimes due to scrollbars being added/removed we get an expose outside 5390 the actual desktop area. Make sure we don't pass it on to the RFB 5391 server. */ 5392 + x = ev->xexpose.x; 5393 + y = ev->xexpose.y; 5394 + width = ev->xexpose.width; 5395 + height = ev->xexpose.height; 5396 + 5397 + if (image_scale) { 5398 + int i; 5399 + x /= scale_factor_x; 5400 + y /= scale_factor_y; 5401 + width /= scale_factor_x; 5402 + height /= scale_factor_y; 5403 + /* make them a little wider to avoid painting errors */ 5404 + for (i=0; i < 3; i++) { 5405 + if (x > 0) x--; 5406 + if (y > 0) y--; 5407 + } 5408 + for (i=0; i < 6; i++) { 5409 + if (x + width < si.framebufferWidth) width++; 5410 + if (y + height < si.framebufferHeight) height++; 5411 + } 5412 + } 5413 5414 - if (ev->xexpose.x + ev->xexpose.width > si.framebufferWidth) { 5415 - ev->xexpose.width = si.framebufferWidth - ev->xexpose.x; 5416 - if (ev->xexpose.width <= 0) break; 5417 - } 5418 - 5419 - if (ev->xexpose.y + ev->xexpose.height > si.framebufferHeight) { 5420 - ev->xexpose.height = si.framebufferHeight - ev->xexpose.y; 5421 - if (ev->xexpose.height <= 0) break; 5422 - } 5423 - 5424 - SendFramebufferUpdateRequest(ev->xexpose.x, ev->xexpose.y, 5425 - ev->xexpose.width, ev->xexpose.height, False); 5426 - break; 5427 + if (x + width > si.framebufferWidth) { 5428 + width = si.framebufferWidth - x; 5429 + if (width <= 0) { 5430 + break; 5431 + } 5432 + } 5433 + 5434 + if (y + height > si.framebufferHeight) { 5435 + height = si.framebufferHeight - y; 5436 + if (height <= 0) { 5437 + break; 5438 + } 5439 + } 5440 + 5441 + if (appData.useXserverBackingStore) { 5442 + SendFramebufferUpdateRequest(x, y, width, height, False); 5443 + } else { 5444 + int ok = 1; 5445 + double delay = 2.5; 5446 + if (appData.fullScreen && now < last_fullscreen + delay) { 5447 + int xmax = si.framebufferWidth; 5448 + int ymax = si.framebufferHeight; 5449 + if (appData.yCrop > 0) { 5450 + ymax = appData.yCrop; 5451 + } 5452 + xmax = scale_round(xmax, scale_factor_x); 5453 + ymax = scale_round(ymax, scale_factor_y); 5454 + if (dpyWidth < xmax) { 5455 + xmax = dpyWidth; 5456 + } 5457 + if (dpyHeight < ymax) { 5458 + ymax = dpyHeight; 5459 + } 5460 + if (x != 0 && y != 0) { 5461 + ok = 0; 5462 + } 5463 + if (width < 0.9 * xmax) { 5464 + ok = 0; 5465 + } 5466 + if (height < 0.9 * ymax) { 5467 + ok = 0; 5468 + } 5469 + } 5470 + if (appData.yCrop > 0) { 5471 + if (now < last_fullscreen + delay || now < last_rescale + delay) { 5472 + if (y + height > appData.yCrop) { 5473 + height = appData.yCrop - y; 5474 + } 5475 + } 5476 + } 5477 + if (ok) { 5478 + put_image(x, y, x, y, width, height, 0); 5479 + XSync(dpy, False); 5480 + } else { 5481 + fprintf(stderr, "Skip "); 5482 + PR_EXPOSE; 5483 + } 5484 + } 5485 + break; 5486 5487 case LeaveNotify: 5488 - for (i = 0; i < 256; i++) { 5489 - if (modifierPressed[i]) { 5490 - SendKeyEvent(XKeycodeToKeysym(dpy, i, 0), False); 5491 - modifierPressed[i] = False; 5492 - } 5493 - } 5494 - break; 5495 + releaseAllPressedModifiers(); 5496 + if (appData.fullScreen) { 5497 + fs_ungrab(1); 5498 + } 5499 + break; 5500 + case EnterNotify: 5501 + if (appData.fullScreen) { 5502 + fs_grab(1); 5503 + } 5504 + break; 5505 + case ClientMessage: 5506 + if (ev->xclient.window == XtWindow(desktop) && ev->xclient.message_type == XA_INTEGER && 5507 + ev->xclient.format == 8 && !strcmp(ev->xclient.data.b, "SendRFBUpdate")) { 5508 + SendIncrementalFramebufferUpdateRequest(); 5509 + } 5510 + break; 5511 } 5512 + check_things(); 5513 +} 5514 + 5515 +extern Position desktopX, desktopY; 5516 + 5517 +void x11vnc_appshare(char *cmd) { 5518 + char send[200], str[100]; 5519 + char *id = "cmd=id_cmd"; 5520 + int m_big = 80, m_fine = 15; 5521 + int resize = 100, db = 0; 5522 + 5523 + if (getenv("X11VNC_APPSHARE_DEBUG")) { 5524 + db = atoi(getenv("X11VNC_APPSHARE_DEBUG")); 5525 + } 5526 + 5527 + if (db) fprintf(stderr, "x11vnc_appshare: cmd=%s\n", cmd); 5528 + 5529 + str[0] = '\0'; 5530 + 5531 + if (!strcmp(cmd, "left")) { 5532 + sprintf(str, "%s:move:-%d+0", id, m_big); 5533 + } else if (!strcmp(cmd, "right")) { 5534 + sprintf(str, "%s:move:+%d+0", id, m_big); 5535 + } else if (!strcmp(cmd, "up")) { 5536 + sprintf(str, "%s:move:+0-%d", id, m_big); 5537 + } else if (!strcmp(cmd, "down")) { 5538 + sprintf(str, "%s:move:+0+%d", id, m_big); 5539 + } else if (!strcmp(cmd, "left-fine")) { 5540 + sprintf(str, "%s:move:-%d+0", id, m_fine); 5541 + } else if (!strcmp(cmd, "right-fine")) { 5542 + sprintf(str, "%s:move:+%d+0", id, m_fine); 5543 + } else if (!strcmp(cmd, "up-fine")) { 5544 + sprintf(str, "%s:move:+0-%d", id, m_fine); 5545 + } else if (!strcmp(cmd, "down-fine")) { 5546 + sprintf(str, "%s:move:+0+%d", id, m_fine); 5547 + } else if (!strcmp(cmd, "taller")) { 5548 + sprintf(str, "%s:resize:+0+%d", id, resize); 5549 + } else if (!strcmp(cmd, "shorter")) { 5550 + sprintf(str, "%s:resize:+0-%d", id, resize); 5551 + } else if (!strcmp(cmd, "wider")) { 5552 + sprintf(str, "%s:resize:+%d+0", id, resize); 5553 + } else if (!strcmp(cmd, "narrower")) { 5554 + sprintf(str, "%s:resize:-%d+0", id, resize); 5555 + } else if (!strcmp(cmd, "lower")) { 5556 + sprintf(str, "%s:lower", id); 5557 + } else if (!strcmp(cmd, "raise")) { 5558 + sprintf(str, "%s:raise", id); 5559 + } else if (!strcmp(cmd, "delete")) { 5560 + sprintf(str, "%s:wm_delete", id); 5561 + } else if (!strcmp(cmd, "position")) { 5562 + Position x, y; 5563 + int xi, yi; 5564 + 5565 + XtVaGetValues(toplevel, XtNx, &x, XtNy, &y, NULL); 5566 + xi = (int) x; 5567 + yi = (int) y; 5568 + if (appData.scale) { 5569 + double fx = 1.0, fy = 1.0; 5570 + get_scale_values(&fx, &fy); 5571 + if (fx > 0.0 && fy > 0.0) { 5572 + xi /= fx; 5573 + yi /= fx; 5574 + } 5575 + } 5576 + sprintf(str, "%s:geom:0x0+%d+%d", id, xi, yi); 5577 + fprintf(stderr, "str=%s\n", str); 5578 + } 5579 + if (strcmp(str, "")) { 5580 + Bool vo = appData.viewOnly; 5581 + strcpy(send, "X11VNC_APPSHARE_CMD:"); 5582 + strcat(send, str); 5583 + if (db) fprintf(stderr, "x11vnc_appshare: send=%s\n", send); 5584 + if (vo) appData.viewOnly = False; 5585 + SendClientCutText(send, strlen(send)); 5586 + if (vo) appData.viewOnly = True; 5587 + } 5588 +} 5589 + 5590 +void scroll_desktop(int horiz, int vert, double amount) { 5591 + Dimension h, w; 5592 + Position x, y; 5593 + Position x2, y2; 5594 + static int db = -1; 5595 + 5596 + if (db < 0) { 5597 + if (getenv("SSVNC_DEBUG_ESCAPE_KEYS")) { 5598 + db = 1; 5599 + } else { 5600 + db = 0; 5601 + } 5602 + } 5603 + 5604 + XtVaGetValues(form, XtNheight, &h, XtNwidth, &w, NULL); 5605 + XtVaGetValues(desktop, XtNx, &x, XtNy, &y, NULL); 5606 + 5607 + x2 = -x; 5608 + y2 = -y; 5609 + 5610 + if (amount == -1.0) { 5611 + int dx = horiz; 5612 + int dy = vert; 5613 + if (dx == 0 && dy == 0) { 5614 + return; 5615 + } 5616 + x2 -= dx; 5617 + y2 -= dy; 5618 + } else { 5619 + if (horiz) { 5620 + int dx = (int) (amount * w); 5621 + if (dx < 0) dx = -dx; 5622 + if (amount == 0.0) dx = 1; 5623 + if (horiz > 0) { 5624 + x2 += dx; 5625 + } else { 5626 + x2 -= dx; 5627 + } 5628 + if (x2 < 0) x2 = 0; 5629 + } 5630 + if (vert) { 5631 + int dy = (int) (amount * h); 5632 + if (amount == 0.0) dy = 1; 5633 + if (dy < 0) dy = -dy; 5634 + if (vert < 0) { 5635 + y2 += dy; 5636 + } else { 5637 + y2 -= dy; 5638 + } 5639 + if (y2 < 0) y2 = 0; 5640 + } 5641 + } 5642 + 5643 + if (db) fprintf(stderr, "%d %d %f viewport(%dx%d): %d %d -> %d %d\n", horiz, vert, amount, w, h, -x, -y, x2, y2); 5644 + XawViewportSetCoordinates(viewport, x2, y2); 5645 + 5646 + if (appData.fullScreen) { 5647 + XSync(dpy, False); 5648 + XtVaGetValues(desktop, XtNx, &x, XtNy, &y, NULL); 5649 + desktopX = -x; 5650 + desktopY = -y; 5651 + } else if (amount == -1.0) { 5652 + XSync(dpy, False); 5653 + } 5654 } 5655 5656 +void scale_desktop(int bigger, double frac) { 5657 + double current, new; 5658 + char tmp[100]; 5659 + char *s; 5660 + int fs; 5661 + 5662 + if (appData.scale == NULL) { 5663 + s = "1.0"; 5664 + } else { 5665 + s = appData.scale; 5666 + } 5667 + if (!strcmp(s, "auto")) { 5668 + fprintf(stderr, "scale_desktop: skipping scale mode '%s'\n", s); 5669 + return; 5670 + } else if (!strcmp(s, "fit")) { 5671 + fprintf(stderr, "scale_desktop: skipping scale mode '%s'\n", s); 5672 + return; 5673 + } else if (strstr(s, "x")) { 5674 + fprintf(stderr, "scale_desktop: skipping scale mode '%s'\n", s); 5675 + return; 5676 + } else if (!strcmp(s, "none")) { 5677 + s = "1.0"; 5678 + } 5679 + 5680 + if (sscanf(s, "%lf", ¤t) != 1) { 5681 + fprintf(stderr, "scale_desktop: skipping scale mode '%s'\n", s); 5682 + return; 5683 + } 5684 + if (bigger) { 5685 + new = current * (1.0 + frac); 5686 + } else { 5687 + new = current / (1.0 + frac); 5688 + } 5689 + if (0.99 < new && new < 1.01) { 5690 + new = 1.0; 5691 + } 5692 5693 + if (new > 5.0) { 5694 + fprintf(stderr, "scale_desktop: not scaling > 5.0: %f\n", new); 5695 + return; 5696 + } else if (new < 0.05) { 5697 + fprintf(stderr, "scale_desktop: not scaling < 0.05: %f\n", new); 5698 + return; 5699 + } 5700 + sprintf(tmp, "%.16f", new); 5701 + appData.scale = strdup(tmp); 5702 + 5703 + fs = 0; 5704 + if (appData.fullScreen) { 5705 + fs = 1; 5706 + FullScreenOff(); 5707 + } 5708 + if (1) { 5709 + double fx, fy; 5710 + get_scale_values(&fx, &fy); 5711 + if (fx > 0.0 && fy > 0.0) { 5712 + rescale_image(); 5713 + } 5714 + } 5715 + if (fs) { 5716 + FullScreenOn(); 5717 + } 5718 +} 5719 + 5720 +static int escape_mods[8]; 5721 +static int escape_drag_in_progress = 0, last_x = 0, last_y = 0; 5722 +static double last_drag = 0.0; 5723 +static double last_key = 0.0; 5724 + 5725 +static int escape_sequence_pressed(void) { 5726 + static char *prev = NULL; 5727 + char *str = "default"; 5728 + int sum, i, init = 0, pressed; 5729 + static int db = -1; 5730 + 5731 + if (db < 0) { 5732 + if (getenv("SSVNC_DEBUG_ESCAPE_KEYS")) { 5733 + db = 1; 5734 + } else { 5735 + db = 0; 5736 + } 5737 + } 5738 + 5739 + if (appData.escapeKeys != NULL) { 5740 + str = appData.escapeKeys; 5741 + } 5742 + if (prev == NULL) { 5743 + init = 1; 5744 + prev = strdup(str); 5745 + } else { 5746 + if (strcmp(prev, str)) { 5747 + init = 1; 5748 + free(prev); 5749 + prev = strdup(str); 5750 + } 5751 + } 5752 + if (db) fprintf(stderr, "str: %s\n", str); 5753 + 5754 + if (init) { 5755 + char *p, *s; 5756 + KeySym ks; 5757 + int k = 0, failed = 0; 5758 + 5759 + for (i = 0; i < 8; i++) { 5760 + escape_mods[i] = -1; 5761 + } 5762 + 5763 + if (!strcasecmp(str, "default")) { 5764 +#if (defined(__MACH__) && defined(__APPLE__)) 5765 + s = strdup("Control_L,Meta_L"); 5766 +#else 5767 + s = strdup("Alt_L,Super_L"); 5768 +#endif 5769 + } else { 5770 + s = strdup(str); 5771 + } 5772 + 5773 + p = strtok(s, ",+ "); 5774 + while (p) { 5775 + ks = XStringToKeysym(p); 5776 + if (ks == XK_Shift_L || ks == XK_Shift_R) { 5777 + putenv("NO_X11VNC_APPSHARE=1"); 5778 + } 5779 + if (k >= 8) { 5780 + fprintf(stderr, "EscapeKeys: more than 8 modifier keys.\n"); 5781 + failed = 1; 5782 + break; 5783 + } 5784 + if (ks == NoSymbol) { 5785 + fprintf(stderr, "EscapeKeys: failed lookup for '%s'\n", p); 5786 + failed = 1; 5787 + break; 5788 + } else if (!IsModifierKey(ks)) { 5789 + fprintf(stderr, "EscapeKeys: not a modifier key '%s'\n", p); 5790 + failed = 1; 5791 + break; 5792 + } else { 5793 + KeyCode kc = XKeysymToKeycode(dpy, ks); 5794 + if (kc == NoSymbol) { 5795 + fprintf(stderr, "EscapeKeys: no keycode for modifier key '%s'\n", p); 5796 + failed = 1; 5797 + break; 5798 + } 5799 + if (db) fprintf(stderr, "set: %d %d\n", k, kc); 5800 + escape_mods[k++] = kc; 5801 + } 5802 + 5803 + p = strtok(NULL, ",+ "); 5804 + } 5805 + free(s); 5806 + 5807 + if (failed) { 5808 + for (i = 0; i < 8; i++) { 5809 + escape_mods[i] = -1; 5810 + } 5811 + } 5812 + } 5813 + 5814 + pressed = 1; 5815 + sum = 0; 5816 + for (i = 0; i < 8; i++) { 5817 + int kc = escape_mods[i]; 5818 + if (kc != -1 && kc < 256) { 5819 + if (db) fprintf(stderr, "try1: %d %d = %d\n", i, kc, modifierPressed[kc]); 5820 + if (!modifierPressed[kc]) { 5821 + pressed = 0; 5822 + break; 5823 + } else { 5824 + sum++; 5825 + } 5826 + } 5827 + } 5828 + if (sum == 0) pressed = 0; 5829 + 5830 + if (!pressed) { 5831 + /* user may have dragged mouse outside of toplevel window */ 5832 + int i, k; 5833 + int keystate[256]; 5834 + char keys[32]; 5835 + 5836 + /* so query server instead of modifierPressed[] */ 5837 + XQueryKeymap(dpy, keys); 5838 + for (i=0; i<32; i++) { 5839 + char c = keys[i]; 5840 + 5841 + for (k=0; k < 8; k++) { 5842 + if (c & 0x1) { 5843 + keystate[8*i + k] = 1; 5844 + } else { 5845 + keystate[8*i + k] = 0; 5846 + } 5847 + c = c >> 1; 5848 + } 5849 + } 5850 + 5851 + /* check again using keystate[] */ 5852 + pressed = 2; 5853 + sum = 0; 5854 + for (i = 0; i < 8; i++) { 5855 + int kc = escape_mods[i]; 5856 + if (kc != -1 && kc < 256) { 5857 + if (db) fprintf(stderr, "try2: %d %d = %d\n", i, kc, keystate[kc]); 5858 + if (!keystate[kc]) { 5859 + pressed = 0; 5860 + break; 5861 + } else { 5862 + sum++; 5863 + } 5864 + } 5865 + } 5866 + if (sum == 0) pressed = 0; 5867 + } 5868 + 5869 + return pressed; 5870 +} 5871 + 5872 +static int shift_is_down(void) { 5873 + int shift_down = 0; 5874 + KeyCode kc; 5875 + 5876 + if (appData.viewOnly) { 5877 + int i, k; 5878 + char keys[32]; 5879 + int keystate[256]; 5880 + 5881 + XQueryKeymap(dpy, keys); 5882 + for (i=0; i<32; i++) { 5883 + char c = keys[i]; 5884 + 5885 + for (k=0; k < 8; k++) { 5886 + if (c & 0x1) { 5887 + keystate[8*i + k] = 1; 5888 + } else { 5889 + keystate[8*i + k] = 0; 5890 + } 5891 + c = c >> 1; 5892 + } 5893 + } 5894 + 5895 + kc = XKeysymToKeycode(dpy, XK_Shift_L); 5896 + if (kc != NoSymbol && keystate[kc]) { 5897 + shift_down = 1; 5898 + } else { 5899 + kc = XKeysymToKeycode(dpy, XK_Shift_R); 5900 + if (kc != NoSymbol && keystate[kc]) { 5901 + shift_down = 1; 5902 + } 5903 + } 5904 + return shift_down; 5905 + } else { 5906 + kc = XKeysymToKeycode(dpy, XK_Shift_L); 5907 + if (kc != NoSymbol && modifierPressed[kc]) { 5908 + shift_down = 1; 5909 + } else { 5910 + kc = XKeysymToKeycode(dpy, XK_Shift_R); 5911 + if (kc != NoSymbol && modifierPressed[kc]) { 5912 + shift_down = 1; 5913 + } 5914 + } 5915 + return shift_down; 5916 + } 5917 +} 5918 + 5919 /* 5920 * SendRFBEvent is an action which sends an RFB event. It can be used in two 5921 * ways. Without any parameters it simply sends an RFB event corresponding to 5922 @@ -201,127 +2089,406 @@ 5923 * button2 down, 3 for both, etc). 5924 */ 5925 5926 +extern Bool selectingSingleWindow; 5927 + 5928 +extern Cursor dotCursor3; 5929 +extern Cursor dotCursor4; 5930 + 5931 +extern void set_server_scale(int); 5932 + 5933 void 5934 SendRFBEvent(Widget w, XEvent *ev, String *params, Cardinal *num_params) 5935 { 5936 - KeySym ks; 5937 - char keyname[256]; 5938 - int buttonMask, x, y; 5939 - 5940 - if (appData.fullScreen && ev->type == MotionNotify) { 5941 - if (BumpScroll(ev)) 5942 - return; 5943 - } 5944 + KeySym ks; 5945 + char keyname[256]; 5946 + int buttonMask, x, y; 5947 + int do_escape; 5948 + static int db = -1; 5949 + char *ek = appData.escapeKeys; 5950 + 5951 + if (db < 0) { 5952 + if (getenv("SSVNC_DEBUG_ESCAPE_KEYS")) { 5953 + db = 1; 5954 + } else { 5955 + db = 0; 5956 + } 5957 + } 5958 + 5959 + if (ev->type == MotionNotify || ev->type == KeyRelease) { 5960 + static double last = 0.0; 5961 + double now = dnow(); 5962 + if (now > last + 0.25) { 5963 + check_things(); 5964 + last = now; 5965 + } 5966 + } 5967 + 5968 + if (selectingSingleWindow && ev->type == ButtonPress) { 5969 + selectingSingleWindow = False; 5970 + SendSingleWindow(ev->xbutton.x, ev->xbutton.y); 5971 + if (appData.viewOnly) { 5972 + XDefineCursor(dpy, desktopWin, dotCursor4); 5973 + } else { 5974 + XDefineCursor(dpy, desktopWin, dotCursor3); 5975 + } 5976 + return; 5977 + } 5978 5979 - if (appData.viewOnly) return; 5980 + if (appData.fullScreen && ev->type == MotionNotify && !escape_drag_in_progress) { 5981 + if (BumpScroll(ev)) { 5982 + return; 5983 + } 5984 + } 5985 + 5986 + do_escape = 0; 5987 + if (ek != NULL && (ek[0] == 'n' || ek[0] == 'N') && !strcasecmp(ek, "never")) { 5988 + ; 5989 + } else if (appData.viewOnly) { 5990 + do_escape = 1; 5991 + } else if (appData.escapeActive) { 5992 + int skip = 0, is_key = 0; 5993 + 5994 + if (ev->type == KeyPress || ev->type == KeyRelease) { 5995 + is_key = 1; 5996 + XLookupString(&ev->xkey, keyname, 256, &ks, NULL); 5997 + if (IsModifierKey(ks)) { 5998 + skip = 1; 5999 + } 6000 + } 6001 + if (!skip) { 6002 + int es = escape_sequence_pressed(); 6003 + if (es == 1) { 6004 + do_escape = 1; 6005 + } else if (es == 2) { 6006 + if (is_key) { 6007 + if (dnow() < last_key + 5.0) { 6008 + do_escape = 1; 6009 + } 6010 + } else { 6011 + if (dnow() < last_drag + 5.0) { 6012 + do_escape = 1; 6013 + } 6014 + } 6015 + } 6016 + } 6017 + } 6018 + if (!do_escape) { 6019 + escape_drag_in_progress = 0; 6020 + } 6021 + if (db) fprintf(stderr, "do_escape: %d\n", do_escape); 6022 + 6023 + if (do_escape) { 6024 + int W = si.framebufferWidth; 6025 + int H = si.framebufferHeight; 6026 + int shift_down = 0; 6027 + 6028 + if (!getenv("NO_X11VNC_APPSHARE")) { 6029 + shift_down = shift_is_down(); 6030 + } 6031 + if (db) fprintf(stderr, "shift_down: %d\n", shift_down); 6032 + 6033 + if (*num_params != 0) { 6034 + if (strcasecmp(params[0],"fbupdate") == 0) { 6035 + SendFramebufferUpdateRequest(0, 0, W, H, False); 6036 + } 6037 + } 6038 + if (ev->type == ButtonRelease) { 6039 + XButtonEvent *b = (XButtonEvent *) ev; 6040 + if (db) fprintf(stderr, "ButtonRelease: %d %d %d\n", b->x_root, b->y_root, b->state); 6041 + if (b->button == 3) { 6042 + if (shift_down) { 6043 + x11vnc_appshare("delete"); 6044 + } else { 6045 + ShowPopup(w, ev, params, num_params); 6046 + } 6047 + } else if (escape_drag_in_progress && b->button == 1) { 6048 + escape_drag_in_progress = 0; 6049 + } 6050 + } else if (ev->type == ButtonPress) { 6051 + XButtonEvent *b = (XButtonEvent *) ev; 6052 + if (db) fprintf(stderr, "ButtonPress: %d %d %d\n", b->x_root, b->y_root, b->state); 6053 + if (b->button == 1) { 6054 + if (shift_down) { 6055 + x11vnc_appshare("position"); 6056 + } else { 6057 + escape_drag_in_progress = 1; 6058 + last_x = b->x_root; 6059 + last_y = b->y_root; 6060 + } 6061 + } else { 6062 + escape_drag_in_progress = 0; 6063 + } 6064 + } else if (ev->type == MotionNotify) { 6065 + XMotionEvent *m = (XMotionEvent *) ev; 6066 + if (escape_drag_in_progress) { 6067 + if (db) fprintf(stderr, "MotionNotify: %d %d %d\n", m->x_root, m->y_root, m->state); 6068 + scroll_desktop(m->x_root - last_x, m->y_root - last_y, -1.0); 6069 + last_x = m->x_root; 6070 + last_y = m->y_root; 6071 + } 6072 + } else if (ev->type == KeyRelease) { 6073 + int did = 1; 6074 + 6075 + XLookupString(&ev->xkey, keyname, 256, &ks, NULL); 6076 + if (ks == XK_1 || ks == XK_KP_1) { 6077 + set_server_scale(1); 6078 + } else if (ks == XK_2 || ks == XK_KP_2) { 6079 + set_server_scale(2); 6080 + } else if (ks == XK_3 || ks == XK_KP_3) { 6081 + set_server_scale(3); 6082 + } else if (ks == XK_4 || ks == XK_KP_4) { 6083 + set_server_scale(4); 6084 + } else if (ks == XK_5 || ks == XK_KP_5) { 6085 + set_server_scale(5); 6086 + } else if (ks == XK_6 || ks == XK_KP_6) { 6087 + set_server_scale(6); 6088 + } else if (ks == XK_r || ks == XK_R) { 6089 + SendFramebufferUpdateRequest(0, 0, W, H, False); 6090 + } else if (ks == XK_b || ks == XK_B) { 6091 + ToggleBell(w, ev, params, num_params); 6092 + } else if (ks == XK_c || ks == XK_C) { 6093 + Toggle8bpp(w, ev, params, num_params); 6094 + } else if (ks == XK_x || ks == XK_X) { 6095 + ToggleX11Cursor(w, ev, params, num_params); 6096 + } else if (ks == XK_z || ks == XK_Z) { 6097 + ToggleTightZRLE(w, ev, params, num_params); 6098 + } else if (ks == XK_h || ks == XK_H) { 6099 + ToggleTightHextile(w, ev, params, num_params); 6100 + } else if (ks == XK_f || ks == XK_F) { 6101 + ToggleFileXfer(w, ev, params, num_params); 6102 + } else if (ks == XK_V) { 6103 + ToggleViewOnly(w, ev, params, num_params); 6104 + } else if (ks == XK_Q) { 6105 + Quit(w, ev, params, num_params); 6106 + } else if (ks == XK_l || ks == XK_L) { 6107 + ToggleFullScreen(w, ev, params, num_params); 6108 + } else if (ks == XK_a || ks == XK_A) { 6109 + ToggleCursorAlpha(w, ev, params, num_params); 6110 + } else if (ks == XK_s || ks == XK_S) { 6111 + SetScale(w, ev, params, num_params); 6112 + } else if (ks == XK_t || ks == XK_T) { 6113 + ToggleTextChat(w, ev, params, num_params); 6114 + } else if (ks == XK_e || ks == XK_E) { 6115 + SetEscapeKeys(w, ev, params, num_params); 6116 + } else if (ks == XK_g || ks == XK_G) { 6117 + ToggleXGrab(w, ev, params, num_params); 6118 + } else if (ks == XK_D) { 6119 + if (shift_down || appData.appShare) { 6120 + x11vnc_appshare("delete"); 6121 + } 6122 + } else if (ks == XK_M) { 6123 + if (shift_down || appData.appShare) { 6124 + x11vnc_appshare("position"); 6125 + } 6126 + } else if (ks == XK_Left) { 6127 + if (shift_down) { 6128 + x11vnc_appshare("left"); 6129 + } else { 6130 + scroll_desktop(-1, 0, 0.1); 6131 + } 6132 + } else if (ks == XK_Right) { 6133 + if (shift_down) { 6134 + x11vnc_appshare("right"); 6135 + } else { 6136 + scroll_desktop(+1, 0, 0.1); 6137 + } 6138 + } else if (ks == XK_Up) { 6139 + if (shift_down) { 6140 + x11vnc_appshare("up"); 6141 + } else { 6142 + scroll_desktop(0, +1, 0.1); 6143 + } 6144 + } else if (ks == XK_Down) { 6145 + if (shift_down) { 6146 + x11vnc_appshare("down"); 6147 + } else { 6148 + scroll_desktop(0, -1, 0.1); 6149 + } 6150 + } else if (ks == XK_KP_Left) { 6151 + if (shift_down) { 6152 + x11vnc_appshare("left-fine"); 6153 + } else { 6154 + scroll_desktop(-1, 0, 0.0); 6155 + } 6156 + } else if (ks == XK_KP_Right) { 6157 + if (shift_down) { 6158 + x11vnc_appshare("right-fine"); 6159 + } else { 6160 + scroll_desktop(+1, 0, 0.0); 6161 + } 6162 + } else if (ks == XK_KP_Up) { 6163 + if (shift_down) { 6164 + x11vnc_appshare("up-fine"); 6165 + } else { 6166 + scroll_desktop(0, +1, 0.0); 6167 + } 6168 + } else if (ks == XK_KP_Down) { 6169 + if (shift_down) { 6170 + x11vnc_appshare("down-fine"); 6171 + } else { 6172 + scroll_desktop(0, -1, 0.0); 6173 + } 6174 + } else if (ks == XK_Next || ks == XK_KP_Next) { 6175 + if (shift_down && ks == XK_Next) { 6176 + x11vnc_appshare("shorter"); 6177 + } else { 6178 + scroll_desktop(0, -1, 1.0); 6179 + } 6180 + } else if (ks == XK_Prior || ks == XK_KP_Prior) { 6181 + if (shift_down && ks == XK_Prior) { 6182 + x11vnc_appshare("taller"); 6183 + } else { 6184 + scroll_desktop(0, +1, 1.0); 6185 + } 6186 + } else if (ks == XK_End || ks == XK_KP_End) { 6187 + if (shift_down && ks == XK_End) { 6188 + x11vnc_appshare("narrower"); 6189 + } else { 6190 + scroll_desktop(+1, 0, 1.0); 6191 + } 6192 + } else if (ks == XK_Home || ks == XK_KP_Home) { 6193 + if (shift_down && ks == XK_Home) { 6194 + x11vnc_appshare("wider"); 6195 + } else { 6196 + scroll_desktop(-1, 0, 1.0); 6197 + } 6198 + } else if (ks == XK_equal || ks == XK_plus) { 6199 + if (shift_down) { 6200 + x11vnc_appshare("raise"); 6201 + } else { 6202 + scale_desktop(1, 0.1); 6203 + } 6204 + } else if (ks == XK_underscore || ks == XK_minus) { 6205 + if (shift_down) { 6206 + x11vnc_appshare("lower"); 6207 + } else { 6208 + scale_desktop(0, 0.1); 6209 + } 6210 + } else { 6211 + did = 0; 6212 + } 6213 + if (did) { 6214 + last_key = dnow(); 6215 + } 6216 + } 6217 + if (escape_drag_in_progress) { 6218 + last_drag = dnow(); 6219 + } 6220 + return; 6221 + } 6222 + if (appData.viewOnly) { 6223 + return; 6224 + } 6225 + 6226 + if (*num_params != 0) { 6227 + if (strncasecmp(params[0],"key",3) == 0) { 6228 + if (*num_params != 2) { 6229 + fprintf(stderr, "Invalid params: " 6230 + "SendRFBEvent(key|keydown|keyup,<keysym>)\n"); 6231 + return; 6232 + } 6233 + ks = XStringToKeysym(params[1]); 6234 + if (ks == NoSymbol) { 6235 + fprintf(stderr,"Invalid keysym '%s' passed to " 6236 + "SendRFBEvent\n", params[1]); 6237 + return; 6238 + } 6239 + if (strcasecmp(params[0],"keydown") == 0) { 6240 + SendKeyEvent(ks, 1); 6241 + } else if (strcasecmp(params[0],"keyup") == 0) { 6242 + SendKeyEvent(ks, 0); 6243 + } else if (strcasecmp(params[0],"key") == 0) { 6244 + SendKeyEvent(ks, 1); 6245 + SendKeyEvent(ks, 0); 6246 + } else { 6247 + fprintf(stderr,"Invalid event '%s' passed to " 6248 + "SendRFBEvent\n", params[0]); 6249 + return; 6250 + } 6251 + } else if (strcasecmp(params[0],"fbupdate") == 0) { 6252 + if (*num_params != 1) { 6253 + fprintf(stderr, "Invalid params: " 6254 + "SendRFBEvent(fbupdate)\n"); 6255 + return; 6256 + } 6257 + SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, 6258 + si.framebufferHeight, False); 6259 + 6260 + } else if (strcasecmp(params[0],"ptr") == 0) { 6261 + if (*num_params == 4) { 6262 + x = atoi(params[1]); 6263 + y = atoi(params[2]); 6264 + buttonMask = atoi(params[3]); 6265 + SendPointerEvent(x, y, buttonMask); 6266 + } else if (*num_params == 2) { 6267 + switch (ev->type) { 6268 + case ButtonPress: 6269 + case ButtonRelease: 6270 + x = ev->xbutton.x; 6271 + y = ev->xbutton.y; 6272 + break; 6273 + case KeyPress: 6274 + case KeyRelease: 6275 + x = ev->xkey.x; 6276 + y = ev->xkey.y; 6277 + break; 6278 + default: 6279 + fprintf(stderr, "Invalid event caused " 6280 + "SendRFBEvent(ptr,<buttonMask>)\n"); 6281 + return; 6282 + } 6283 + buttonMask = atoi(params[1]); 6284 + SendPointerEvent(x, y, buttonMask); 6285 + } else { 6286 + fprintf(stderr, "Invalid params: " 6287 + "SendRFBEvent(ptr,<x>,<y>,<buttonMask>)\n" 6288 + " or SendRFBEvent(ptr,<buttonMask>)\n"); 6289 + return; 6290 + } 6291 + } else { 6292 + fprintf(stderr,"Invalid event '%s' passed to " 6293 + "SendRFBEvent\n", params[0]); 6294 + } 6295 + return; 6296 + } 6297 6298 - if (*num_params != 0) { 6299 - if (strncasecmp(params[0],"key",3) == 0) { 6300 - if (*num_params != 2) { 6301 - fprintf(stderr, 6302 - "Invalid params: SendRFBEvent(key|keydown|keyup,<keysym>)\n"); 6303 - return; 6304 - } 6305 - ks = XStringToKeysym(params[1]); 6306 - if (ks == NoSymbol) { 6307 - fprintf(stderr,"Invalid keysym '%s' passed to SendRFBEvent\n", 6308 - params[1]); 6309 - return; 6310 - } 6311 - if (strcasecmp(params[0],"keydown") == 0) { 6312 - SendKeyEvent(ks, 1); 6313 - } else if (strcasecmp(params[0],"keyup") == 0) { 6314 - SendKeyEvent(ks, 0); 6315 - } else if (strcasecmp(params[0],"key") == 0) { 6316 - SendKeyEvent(ks, 1); 6317 - SendKeyEvent(ks, 0); 6318 - } else { 6319 - fprintf(stderr,"Invalid event '%s' passed to SendRFBEvent\n", 6320 - params[0]); 6321 - return; 6322 - } 6323 - } else if (strcasecmp(params[0],"fbupdate") == 0) { 6324 - if (*num_params != 1) { 6325 - fprintf(stderr, "Invalid params: SendRFBEvent(fbupdate)\n"); 6326 - return; 6327 - } 6328 - SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, 6329 - si.framebufferHeight, False); 6330 - } else if (strcasecmp(params[0],"ptr") == 0) { 6331 - if (*num_params == 4) { 6332 - x = atoi(params[1]); 6333 - y = atoi(params[2]); 6334 - buttonMask = atoi(params[3]); 6335 - SendPointerEvent(x, y, buttonMask); 6336 - } else if (*num_params == 2) { 6337 switch (ev->type) { 6338 + case MotionNotify: 6339 + while (XCheckTypedWindowEvent(dpy, desktopWin, MotionNotify, ev)) { 6340 + ; /* discard all queued motion notify events */ 6341 + } 6342 + 6343 + SendPointerEvent(ev->xmotion.x, ev->xmotion.y, 6344 + (ev->xmotion.state & 0x1f00) >> 8); 6345 + return; 6346 + 6347 case ButtonPress: 6348 + SendPointerEvent(ev->xbutton.x, ev->xbutton.y, 6349 + (((ev->xbutton.state & 0x1f00) >> 8) | 6350 + (1 << (ev->xbutton.button - 1)))); 6351 + return; 6352 + 6353 case ButtonRelease: 6354 - x = ev->xbutton.x; 6355 - y = ev->xbutton.y; 6356 - break; 6357 + SendPointerEvent(ev->xbutton.x, ev->xbutton.y, 6358 + (((ev->xbutton.state & 0x1f00) >> 8) & 6359 + ~(1 << (ev->xbutton.button - 1)))); 6360 + return; 6361 + 6362 case KeyPress: 6363 case KeyRelease: 6364 - x = ev->xkey.x; 6365 - y = ev->xkey.y; 6366 - break; 6367 - default: 6368 - fprintf(stderr, 6369 - "Invalid event caused SendRFBEvent(ptr,<buttonMask>)\n"); 6370 - return; 6371 - } 6372 - buttonMask = atoi(params[1]); 6373 - SendPointerEvent(x, y, buttonMask); 6374 - } else { 6375 - fprintf(stderr, 6376 - "Invalid params: SendRFBEvent(ptr,<x>,<y>,<buttonMask>)\n" 6377 - " or SendRFBEvent(ptr,<buttonMask>)\n"); 6378 - return; 6379 - } 6380 - 6381 - } else { 6382 - fprintf(stderr,"Invalid event '%s' passed to SendRFBEvent\n", params[0]); 6383 - } 6384 - return; 6385 - } 6386 - 6387 - switch (ev->type) { 6388 + XLookupString(&ev->xkey, keyname, 256, &ks, NULL); 6389 6390 - case MotionNotify: 6391 - while (XCheckTypedWindowEvent(dpy, desktopWin, MotionNotify, ev)) 6392 - ; /* discard all queued motion notify events */ 6393 - 6394 - SendPointerEvent(ev->xmotion.x, ev->xmotion.y, 6395 - (ev->xmotion.state & 0x1f00) >> 8); 6396 - return; 6397 - 6398 - case ButtonPress: 6399 - SendPointerEvent(ev->xbutton.x, ev->xbutton.y, 6400 - (((ev->xbutton.state & 0x1f00) >> 8) | 6401 - (1 << (ev->xbutton.button - 1)))); 6402 - return; 6403 - 6404 - case ButtonRelease: 6405 - SendPointerEvent(ev->xbutton.x, ev->xbutton.y, 6406 - (((ev->xbutton.state & 0x1f00) >> 8) & 6407 - ~(1 << (ev->xbutton.button - 1)))); 6408 - return; 6409 - 6410 - case KeyPress: 6411 - case KeyRelease: 6412 - XLookupString(&ev->xkey, keyname, 256, &ks, NULL); 6413 - 6414 - if (IsModifierKey(ks)) { 6415 - ks = XKeycodeToKeysym(dpy, ev->xkey.keycode, 0); 6416 - modifierPressed[ev->xkey.keycode] = (ev->type == KeyPress); 6417 - } 6418 + if (IsModifierKey(ks)) { 6419 + ks = XKeycodeToKeysym(dpy, ev->xkey.keycode, 0); 6420 + modifierPressed[ev->xkey.keycode] = (ev->type == KeyPress); 6421 + } 6422 6423 - SendKeyEvent(ks, (ev->type == KeyPress)); 6424 - return; 6425 + SendKeyEvent(ks, (ev->type == KeyPress)); 6426 + return; 6427 6428 - default: 6429 - fprintf(stderr,"Invalid event passed to SendRFBEvent\n"); 6430 - } 6431 + default: 6432 + fprintf(stderr,"Invalid event passed to SendRFBEvent\n"); 6433 + } 6434 } 6435 6436 6437 @@ -329,68 +2496,255 @@ 6438 * CreateDotCursor. 6439 */ 6440 6441 +#ifndef very_small_dot_cursor 6442 static Cursor 6443 -CreateDotCursor() 6444 +CreateDotCursor(int which) 6445 { 6446 - Cursor cursor; 6447 - Pixmap src, msk; 6448 - static char srcBits[] = { 0, 14,14,14, 0 }; 6449 - static char mskBits[] = { 14,31,31,31,14 }; 6450 - XColor fg, bg; 6451 - 6452 - src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits, 5, 5); 6453 - msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits, 5, 5); 6454 - XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "black", 6455 - &fg, &fg); 6456 - XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "white", 6457 - &bg, &bg); 6458 - cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 2, 2); 6459 - XFreePixmap(dpy, src); 6460 - XFreePixmap(dpy, msk); 6461 + Cursor cursor; 6462 + Pixmap src, msk; 6463 + static char srcBits3[] = { 0x00, 0x02, 0x00 }; 6464 + static char mskBits3[] = { 0x02, 0x07, 0x02 }; 6465 + static char srcBits4[] = { 0x00, 0x06, 0x06, 0x00 }; 6466 + static char mskBits4[] = { 0x06, 0x0f, 0x0f, 0x06 }; 6467 + XColor fg, bg; 6468 + 6469 + if (which == 3) { 6470 + src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits3, 3, 3); 6471 + msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits3, 3, 3); 6472 + } else { 6473 + src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits4, 4, 4); 6474 + msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits4, 4, 4); 6475 + } 6476 + XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "black", 6477 + &fg, &fg); 6478 + XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "white", 6479 + &bg, &bg); 6480 + cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 1, 1); 6481 + XFreePixmap(dpy, src); 6482 + XFreePixmap(dpy, msk); 6483 6484 - return cursor; 6485 + return cursor; 6486 } 6487 +#else 6488 +static Cursor 6489 +CreateDotCursor() 6490 +{ 6491 + Cursor cursor; 6492 + Pixmap src, msk; 6493 + static char srcBits[] = { 0, 14, 0 }; 6494 + static char mskBits[] = { 14,31,14 }; 6495 + XColor fg, bg; 6496 + 6497 + src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits, 3, 3); 6498 + msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits, 3, 3); 6499 + XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "black", 6500 + &fg, &fg); 6501 + XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "white", 6502 + &bg, &bg); 6503 + cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 1, 1); 6504 + XFreePixmap(dpy, src); 6505 + XFreePixmap(dpy, msk); 6506 6507 + return cursor; 6508 +} 6509 +#endif 6510 6511 +int skip_maybe_sync = 0; 6512 +void maybe_sync(int width, int height) { 6513 + static int singles = 0, always_skip = -1; 6514 + int singles_max = 64; 6515 + 6516 + if (always_skip < 0) { 6517 + if (getenv("SSVNC_NO_MAYBE_SYNC")) { 6518 + always_skip = 1; 6519 + } else { 6520 + always_skip = 0; 6521 + } 6522 + } 6523 + if (skip_maybe_sync || always_skip) { 6524 + return; 6525 + } 6526 +#if 0 6527 + if (width > 1 || height > 1) { 6528 + XSync(dpy, False); 6529 + singles = 0; 6530 + } else { 6531 + if (++singles >= singles_max) { 6532 + singles = 0; 6533 + XSync(dpy, False); 6534 + } 6535 + } 6536 +#else 6537 + if (width * height >= singles_max) { 6538 + XSync(dpy, False); 6539 + singles = 0; 6540 + } else { 6541 + singles += width * height; 6542 + if (singles >= singles_max) { 6543 + XSync(dpy, False); 6544 + singles = 0; 6545 + } 6546 + } 6547 +#endif 6548 +} 6549 /* 6550 - * CopyDataToScreen. 6551 + * FillImage. 6552 */ 6553 6554 void 6555 -CopyDataToScreen(char *buf, int x, int y, int width, int height) 6556 +FillScreen(int x, int y, int width, int height, unsigned long fill) 6557 { 6558 - if (appData.rawDelay != 0) { 6559 - XFillRectangle(dpy, desktopWin, gc, x, y, width, height); 6560 + XImage *im = image_scale ? image_scale : image; 6561 + int bpp = im->bits_per_pixel; 6562 + int Bpp = im->bits_per_pixel / 8; 6563 + int Bpl = im->bytes_per_line; 6564 + int h, widthInBytes = width * Bpp; 6565 + static char *buf = NULL; 6566 + static int buflen = 0; 6567 + unsigned char *ucp; 6568 + unsigned short *usp; 6569 + unsigned int *uip; 6570 + char *scr; 6571 + int b0, b1, b2; 6572 6573 - XSync(dpy,False); 6574 +#if 0 6575 +fprintf(stderr, "FillImage bpp=%d %04dx%04d+%04d+%04d -- 0x%x\n", bpp, width, height, x, y, fill); 6576 +#endif 6577 + if (appData.chatOnly) { 6578 + return; 6579 + } 6580 6581 - usleep(appData.rawDelay * 1000); 6582 - } 6583 + if (widthInBytes > buflen || !buf) { 6584 + if (buf) { 6585 + free(buf); 6586 + } 6587 + buflen = widthInBytes * 2; 6588 + buf = (char *)malloc(buflen); 6589 + } 6590 + ucp = (unsigned char*) buf; 6591 + usp = (unsigned short*) buf; 6592 + uip = (unsigned int*) buf; 6593 + 6594 + if (isLSB) { 6595 + b0 = 0; b1 = 1; b2 = 2; 6596 + } else { 6597 + b0 = 2; b1 = 1; b2 = 0; 6598 + } 6599 6600 - if (!appData.useBGR233) { 6601 - int h; 6602 - int widthInBytes = width * myFormat.bitsPerPixel / 8; 6603 - int scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8; 6604 - 6605 - char *scr = (image->data + y * scrWidthInBytes 6606 - + x * myFormat.bitsPerPixel / 8); 6607 - 6608 - for (h = 0; h < height; h++) { 6609 - memcpy(scr, buf, widthInBytes); 6610 - buf += widthInBytes; 6611 - scr += scrWidthInBytes; 6612 - } 6613 - } else { 6614 - CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height); 6615 - } 6616 + for (h = 0; h < width; h++) { 6617 + if (bpp == 8) { 6618 + *(ucp+h) = (unsigned char) fill; 6619 + } else if (bpp == 16) { 6620 + *(usp+h) = (unsigned short) fill; 6621 + } else if (bpp == 24) { 6622 + *(ucp + 3*h + b0) = (unsigned char) ((fill & 0x0000ff) >> 0); 6623 + *(ucp + 3*h + b1) = (unsigned char) ((fill & 0x00ff00) >> 8); 6624 + *(ucp + 3*h + b2) = (unsigned char) ((fill & 0xff0000) >> 16); 6625 + } else if (bpp == 32) { 6626 + *(uip+h) = (unsigned int) fill; 6627 + } 6628 + } 6629 6630 -#ifdef MITSHM 6631 - if (appData.useShm) { 6632 - XShmPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height, False); 6633 - return; 6634 - } 6635 + scr = im->data + y * Bpl + x * Bpp; 6636 + 6637 + for (h = 0; h < height; h++) { 6638 + memcpy(scr, buf, widthInBytes); 6639 + scr += Bpl; 6640 + } 6641 + put_image(x, y, x, y, width, height, 1); 6642 + maybe_sync(width, height); 6643 +} 6644 + 6645 +void copy_rect(int x, int y, int width, int height, int src_x, int src_y) { 6646 + char *src, *dst; 6647 + int i; 6648 + XImage *im = image_scale ? image_scale : image; 6649 + int Bpp = im->bits_per_pixel / 8; 6650 + int Bpl = im->bytes_per_line; 6651 + int did2 = 0; 6652 + 6653 +#if 0 6654 +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); 6655 #endif 6656 - XPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height); 6657 + copyrect2: 6658 + 6659 + if (y < src_y) { 6660 + src = im->data + src_y * Bpl + src_x * Bpp; 6661 + dst = im->data + y * Bpl + x * Bpp; 6662 + for (i = 0; i < height; i++) { 6663 + memmove(dst, src, Bpp * width); 6664 + src += Bpl; 6665 + dst += Bpl; 6666 + } 6667 + } else { 6668 + src = im->data + (src_y + height - 1) * Bpl + src_x * Bpp; 6669 + dst = im->data + (y + height - 1) * Bpl + x * Bpp; 6670 + for (i = 0; i < height; i++) { 6671 + memmove(dst, src, Bpp * width); 6672 + src -= Bpl; 6673 + dst -= Bpl; 6674 + } 6675 + } 6676 + 6677 + if (image_scale && !did2) { 6678 + im = image; 6679 + Bpp = im->bits_per_pixel / 8; 6680 + Bpl = im->bytes_per_line; 6681 + 6682 + x *= scale_factor_x; 6683 + y *= scale_factor_y; 6684 + src_x *= scale_factor_x; 6685 + src_y *= scale_factor_y; 6686 + width = scale_round(width, scale_factor_x); 6687 + height = scale_round(height, scale_factor_y); 6688 + 6689 + did2 = 1; 6690 + goto copyrect2; 6691 + } 6692 +} 6693 + 6694 + 6695 +/* 6696 + * CopyDataToScreen. 6697 + */ 6698 + 6699 +void 6700 +CopyDataToScreen(char *buf, int x, int y, int width, int height) 6701 +{ 6702 + if (appData.chatOnly) { 6703 + return; 6704 + } 6705 + if (appData.rawDelay != 0) { 6706 + XFillRectangle(dpy, desktopWin, gc, x, y, width, height); 6707 + XSync(dpy,False); 6708 + usleep(appData.rawDelay * 1000); 6709 + } 6710 + 6711 + if (appData.useBGR233) { 6712 + CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height); 6713 + } else if (appData.useBGR565) { 6714 + CopyBGR565ToScreen((CARD16 *)buf, x, y, width, height); 6715 + } else { 6716 + int h; 6717 + int widthInBytes = width * myFormat.bitsPerPixel / 8; 6718 + int scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8; 6719 + char *scr; 6720 + XImage *im = image_scale ? image_scale : image; 6721 + 6722 + if (scrWidthInBytes != im->bytes_per_line) scrWidthInBytes = im->bytes_per_line; 6723 + 6724 + scr = (im->data + y * scrWidthInBytes 6725 + + x * myFormat.bitsPerPixel / 8); 6726 + 6727 + for (h = 0; h < height; h++) { 6728 + memcpy(scr, buf, widthInBytes); 6729 + buf += widthInBytes; 6730 + scr += scrWidthInBytes; 6731 + } 6732 + } 6733 + 6734 + put_image(x, y, x, y, width, height, 0); 6735 + maybe_sync(width, height); 6736 } 6737 6738 6739 @@ -401,62 +2755,338 @@ 6740 static void 6741 CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width, int height) 6742 { 6743 - int p, q; 6744 - int xoff = 7 - (x & 7); 6745 - int xcur; 6746 - int fbwb = si.framebufferWidth / 8; 6747 - CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8; 6748 - CARD8 *scrt; 6749 - CARD8 *scr8 = ((CARD8 *)image->data) + y * si.framebufferWidth + x; 6750 - CARD16 *scr16 = ((CARD16 *)image->data) + y * si.framebufferWidth + x; 6751 - CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x; 6752 + XImage *im = image_scale ? image_scale : image; 6753 + int p, q; 6754 + int xoff = 7 - (x & 7); 6755 + int xcur; 6756 + int fbwb = si.framebufferWidth / 8; 6757 + int src_width8 = im->bytes_per_line/1; 6758 + int src_width16 = im->bytes_per_line/2; 6759 + int src_width32 = im->bytes_per_line/4; 6760 + CARD8 *src1 = ((CARD8 *)im->data) + y * fbwb + x / 8; 6761 + CARD8 *srct; 6762 + CARD8 *src8 = ( (CARD8 *)im->data) + y * src_width8 + x; 6763 + CARD16 *src16 = ((CARD16 *)im->data) + y * src_width16 + x; 6764 + CARD32 *src32 = ((CARD32 *)im->data) + y * src_width32 + x; 6765 + int b0, b1, b2; 6766 6767 - switch (visbpp) { 6768 + switch (visbpp) { 6769 6770 /* thanks to Chris Hooper for single bpp support */ 6771 6772 - case 1: 6773 - for (q = 0; q < height; q++) { 6774 - xcur = xoff; 6775 - scrt = scr1; 6776 - for (p = 0; p < width; p++) { 6777 - *scrt = ((*scrt & ~(1 << xcur)) 6778 - | (BGR233ToPixel[*(buf++)] << xcur)); 6779 - 6780 - if (xcur-- == 0) { 6781 - xcur = 7; 6782 - scrt++; 6783 - } 6784 - } 6785 - scr1 += fbwb; 6786 - } 6787 - break; 6788 - 6789 - case 8: 6790 - for (q = 0; q < height; q++) { 6791 - for (p = 0; p < width; p++) { 6792 - *(scr8++) = BGR233ToPixel[*(buf++)]; 6793 - } 6794 - scr8 += si.framebufferWidth - width; 6795 - } 6796 - break; 6797 - 6798 - case 16: 6799 - for (q = 0; q < height; q++) { 6800 - for (p = 0; p < width; p++) { 6801 - *(scr16++) = BGR233ToPixel[*(buf++)]; 6802 - } 6803 - scr16 += si.framebufferWidth - width; 6804 - } 6805 - break; 6806 - 6807 - case 32: 6808 - for (q = 0; q < height; q++) { 6809 - for (p = 0; p < width; p++) { 6810 - *(scr32++) = BGR233ToPixel[*(buf++)]; 6811 - } 6812 - scr32 += si.framebufferWidth - width; 6813 - } 6814 - break; 6815 - } 6816 + case 1: 6817 + for (q = 0; q < height; q++) { 6818 + xcur = xoff; 6819 + srct = src1; 6820 + for (p = 0; p < width; p++) { 6821 + *srct = ((*srct & ~(1 << xcur)) 6822 + | (BGR233ToPixel[*(buf++)] << xcur)); 6823 + 6824 + if (xcur-- == 0) { 6825 + xcur = 7; 6826 + srct++; 6827 + } 6828 + } 6829 + src1 += fbwb; 6830 + } 6831 + break; 6832 + 6833 + case 8: 6834 + for (q = 0; q < height; q++) { 6835 + for (p = 0; p < width; p++) { 6836 + *(src8++) = BGR233ToPixel[*(buf++)]; 6837 + } 6838 + src8 += src_width8 - width; 6839 + } 6840 + break; 6841 + 6842 + case 16: 6843 + for (q = 0; q < height; q++) { 6844 + for (p = 0; p < width; p++) { 6845 + *(src16++) = BGR233ToPixel[*(buf++)]; 6846 + } 6847 + src16 += src_width16 - width; 6848 + } 6849 + break; 6850 + 6851 + case 24: 6852 + if (isLSB) { 6853 + b0 = 0; b1 = 1; b2 = 2; 6854 + } else { 6855 + b0 = 2; b1 = 1; b2 = 0; 6856 + } 6857 + src8 = ((CARD8 *)im->data) + (y * si.framebufferWidth + x) * 3; 6858 + for (q = 0; q < height; q++) { 6859 + for (p = 0; p < width; p++) { 6860 + CARD32 v = BGR233ToPixel[*(buf++)]; 6861 + *(src8 + b0) = (unsigned char) ((v & 0x0000ff) >> 0); 6862 + *(src8 + b1) = (unsigned char) ((v & 0x00ff00) >> 8); 6863 + *(src8 + b2) = (unsigned char) ((v & 0xff0000) >> 16); 6864 + src8 += 3; 6865 + } 6866 + src8 += (si.framebufferWidth - width) * 3; 6867 + } 6868 + break; 6869 + 6870 + case 32: 6871 + for (q = 0; q < height; q++) { 6872 + for (p = 0; p < width; p++) { 6873 + *(src32++) = BGR233ToPixel[*(buf++)]; 6874 + } 6875 + src32 += src_width32 - width; 6876 + } 6877 + break; 6878 + } 6879 +} 6880 + 6881 +static void 6882 +BGR565_24bpp(CARD16 *buf, int x, int y, int width, int height) 6883 +{ 6884 + int p, q; 6885 + int b0, b1, b2; 6886 + XImage *im = image_scale ? image_scale : image; 6887 + unsigned char *src= (unsigned char *)im->data + (y * si.framebufferWidth + x) * 3; 6888 + 6889 + if (isLSB) { 6890 + b0 = 0; b1 = 1; b2 = 2; 6891 + } else { 6892 + b0 = 2; b1 = 1; b2 = 0; 6893 + } 6894 + 6895 + /* case 24: */ 6896 + for (q = 0; q < height; q++) { 6897 + for (p = 0; p < width; p++) { 6898 + CARD32 v = BGR565ToPixel[*(buf++)]; 6899 + *(src + b0) = (unsigned char) ((v & 0x0000ff) >> 0); 6900 + *(src + b1) = (unsigned char) ((v & 0x00ff00) >> 8); 6901 + *(src + b2) = (unsigned char) ((v & 0xff0000) >> 16); 6902 + src += 3; 6903 + } 6904 + src += (si.framebufferWidth - width) * 3; 6905 + } 6906 +} 6907 + 6908 +static void 6909 +CopyBGR565ToScreen(CARD16 *buf, int x, int y, int width, int height) 6910 +{ 6911 + int p, q; 6912 + XImage *im = image_scale ? image_scale : image; 6913 + int src_width32 = im->bytes_per_line/4; 6914 + CARD32 *src32 = ((CARD32 *)im->data) + y * src_width32 + x; 6915 + 6916 + if (visbpp == 24) { 6917 + BGR565_24bpp(buf, x, y, width, height); 6918 + return; 6919 + } 6920 + 6921 + /* case 32: */ 6922 + for (q = 0; q < height; q++) { 6923 + for (p = 0; p < width; p++) { 6924 + *(src32++) = BGR565ToPixel[*(buf++)]; 6925 + } 6926 + src32 += src_width32 - width; 6927 + } 6928 +} 6929 + 6930 +static void reset_image(void) { 6931 + if (UsingShm()) { 6932 + ShmDetach(); 6933 + } 6934 + if (image && image->data) { 6935 + XDestroyImage(image); 6936 + fprintf(stderr, "reset_image: destroyed 'image'\n"); 6937 + } 6938 + image = NULL; 6939 + if (image_ycrop && image_ycrop->data) { 6940 + XDestroyImage(image_ycrop); 6941 + fprintf(stderr, "reset_image: destroyed 'image_ycrop'\n"); 6942 + } 6943 + image_ycrop = NULL; 6944 + if (image_scale && image_scale->data) { 6945 + XDestroyImage(image_scale); 6946 + fprintf(stderr, "reset_image: destroyed 'image_scale'\n"); 6947 + } 6948 + image_scale = NULL; 6949 + 6950 + if (UsingShm()) { 6951 + ShmCleanup(); 6952 + } 6953 + create_image(); 6954 + XFlush(dpy); 6955 +} 6956 + 6957 +void ReDoDesktop(void) { 6958 + int w, w0, h, h0, x, y, dw, dh; 6959 + int fs = 0; 6960 + int autoscale = 0; 6961 + Position x_orig, y_orig; 6962 + Dimension w_orig, h_orig; 6963 + 6964 + if (!appData.fullScreen && appData.scale != NULL && !strcmp(appData.scale, "auto")) { 6965 + autoscale = 1; 6966 + } 6967 + 6968 + fprintf(stderr, "ReDoDesktop: ycrop: %d\n", appData.yCrop); 6969 + 6970 + XtVaGetValues(toplevel, XtNx, &x_orig, XtNy, &y_orig, NULL); 6971 + XtVaGetValues(toplevel, XtNheight, &h_orig, XtNwidth, &w_orig, NULL); 6972 + 6973 + check_tall(); 6974 + 6975 + if (appData.yCrop) { 6976 + if (appData.yCrop < 0 || old_width <= 0) { 6977 + appData.yCrop = guessCrop(); 6978 + fprintf(stderr, "Set -ycrop to: %d\n", appData.yCrop); 6979 + } else { 6980 + int w1 = si.framebufferWidth; 6981 + appData.yCrop = (w1 * appData.yCrop) / old_width; 6982 + if (appData.yCrop <= 100) { 6983 + appData.yCrop = guessCrop(); 6984 + fprintf(stderr, "Set small -ycrop to: %d\n", appData.yCrop); 6985 + } 6986 + } 6987 + fprintf(stderr, "Using -ycrop: %d\n", appData.yCrop); 6988 + } 6989 + 6990 + old_width = si.framebufferWidth; 6991 + old_height = si.framebufferHeight; 6992 + 6993 + if (appData.fullScreen) { 6994 + if (prev_fb_width != si.framebufferWidth || prev_fb_height != si.framebufferHeight) { 6995 + int xmax = si.framebufferWidth; 6996 + int ymax = si.framebufferHeight; 6997 + if (appData.yCrop > 0) { 6998 + ymax = appData.yCrop; 6999 + } 7000 + if (scale_x > 0) { 7001 + xmax = scale_round(xmax, scale_factor_x); 7002 + ymax = scale_round(ymax, scale_factor_y); 7003 + } 7004 + if (xmax < dpyWidth || ymax < dpyHeight) { 7005 + FullScreenOff(); 7006 + fs = 1; 7007 + } 7008 + } 7009 + } 7010 + 7011 + prev_fb_width = si.framebufferWidth; 7012 + prev_fb_height = si.framebufferHeight; 7013 + 7014 + if (appData.fullScreen) { 7015 + 7016 + int xmax = si.framebufferWidth; 7017 + int ymax = si.framebufferHeight; 7018 + if (scale_x > 0) { 7019 + xmax = scale_round(xmax, scale_factor_x); 7020 + ymax = scale_round(ymax, scale_factor_y); 7021 + } 7022 + 7023 + if (image && image->data) { 7024 + int len; 7025 + int h = image->height; 7026 + int w = image->width; 7027 + len = image->bytes_per_line * image->height; 7028 + /* black out window first: */ 7029 + memset(image->data, 0, len); 7030 + XPutImage(dpy, XtWindow(desktop), gc, image, 0, 0, 0, 0, w, h); 7031 + XFlush(dpy); 7032 + } 7033 + 7034 + /* XXX scaling?? */ 7035 + XtResizeWidget(desktop, xmax, ymax, 0); 7036 + 7037 + XSync(dpy, False); 7038 + usleep(100*1000); 7039 + FullScreenOn(); 7040 + XSync(dpy, False); 7041 + usleep(100*1000); 7042 + reset_image(); 7043 + return; 7044 + } 7045 + 7046 + dw = appData.wmDecorationWidth; 7047 + dh = appData.wmDecorationHeight; 7048 + 7049 + w = si.framebufferWidth; 7050 + h = si.framebufferHeight; 7051 + w0 = w; 7052 + h0 = h; 7053 + if (appData.yCrop > 0) { 7054 + h = appData.yCrop; 7055 + } 7056 + if (image_scale) { 7057 + w = scale_round(w, scale_factor_x); 7058 + h = scale_round(h, scale_factor_y); 7059 + w0 = scale_round(w0, scale_factor_x); 7060 + h0 = scale_round(h0, scale_factor_y); 7061 + } 7062 + 7063 + if (w + dw >= dpyWidth) { 7064 + w = dpyWidth - dw; 7065 + } 7066 + if (h + dh >= dpyHeight) { 7067 + h = dpyHeight - dh; 7068 + } 7069 + 7070 + if (!autoscale) { 7071 + XtVaSetValues(toplevel, XtNmaxWidth, w, XtNmaxHeight, h, NULL); 7072 + } else { 7073 + XtVaSetValues(toplevel, XtNmaxWidth, dpyWidth, XtNmaxHeight, dpyHeight, NULL); 7074 + } 7075 + 7076 + XtVaSetValues(desktop, XtNwidth, w0, XtNheight, h0, NULL); 7077 + 7078 + XtResizeWidget(desktop, w0, h0, 0); 7079 + 7080 + if (appData.yCrop > 0) { 7081 + int ycrop = appData.yCrop; 7082 + if (image_scale) { 7083 + ycrop *= scale_factor_y; 7084 + } 7085 + XtVaSetValues(toplevel, XtNmaxHeight, ycrop, NULL); 7086 + XtVaSetValues(form, XtNmaxHeight, ycrop, NULL); 7087 + } 7088 + 7089 + x = (dpyWidth - w - dw)/2; 7090 + y = (dpyHeight - h - dh)/2; 7091 + 7092 + if (!autoscale) { 7093 + 7094 + if (!getenv("VNCVIEWER_ALWAYS_RECENTER")) { 7095 + int x_cm_old, y_cm_old; 7096 + int x_cm_new, y_cm_new; 7097 + int x_try, y_try; 7098 + 7099 + x_cm_old = (int) x_orig + ((int) w_orig)/2; 7100 + y_cm_old = (int) y_orig + ((int) h_orig)/2; 7101 + 7102 + x_cm_new = dpyWidth/2; 7103 + y_cm_new = dpyHeight/2; 7104 + 7105 + x_try = x + (x_cm_old - x_cm_new); 7106 + y_try = y + (y_cm_old - y_cm_new); 7107 + if (x_try < 0) { 7108 + x_try = 0; 7109 + } 7110 + if (y_try < 0) { 7111 + y_try = 0; 7112 + } 7113 + if (x_try + w + dw > dpyWidth) { 7114 + x_try = dpyWidth - w - dw; 7115 + } 7116 + if (y_try + h + dh > dpyHeight) { 7117 + y_try = dpyHeight - h - dh; 7118 + } 7119 + x = x_try; 7120 + y = y_try; 7121 + } 7122 + 7123 + XtConfigureWidget(toplevel, x + dw, y + dh, w, h, 0); 7124 + } 7125 + 7126 + reset_image(); 7127 + 7128 + if (fs) { 7129 + FullScreenOn(); 7130 + } 7131 } 7132 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncviewer/dialogs.c 7133 --- vnc_unixsrc.orig/vncviewer/dialogs.c 2000-10-26 15:19:19.000000000 -0400 7134 +++ vnc_unixsrc/vncviewer/dialogs.c 2010-02-25 22:33:06.000000000 -0500 7135 @@ -25,75 +25,564 @@ 7136 #include <X11/Xaw/Dialog.h> 7137 7138 static Bool serverDialogDone = False; 7139 +static Bool userDialogDone = False; 7140 static Bool passwordDialogDone = False; 7141 +static Bool ycropDialogDone = False; 7142 +static Bool scaleDialogDone = False; 7143 +static Bool escapeDialogDone = False; 7144 +static Bool scbarDialogDone = False; 7145 +static Bool scaleNDialogDone = False; 7146 +static Bool qualityDialogDone = False; 7147 +static Bool compressDialogDone = False; 7148 + 7149 +extern void popupFixer(Widget wid); 7150 + 7151 +int use_tty(void) { 7152 + if (appData.notty) { 7153 + return 0; 7154 + } else if (!isatty(0)) { 7155 + return 0; 7156 + } 7157 + return 1; 7158 +} 7159 + 7160 +void 7161 +ScaleDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) 7162 +{ 7163 + scaleDialogDone = True; 7164 + if (w || event || params || num_params) {} 7165 +} 7166 + 7167 +void 7168 +EscapeDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) 7169 +{ 7170 + escapeDialogDone = True; 7171 + if (w || event || params || num_params) {} 7172 +} 7173 + 7174 +void dialog_over(Widget wid) { 7175 + if (appData.fullScreen) { 7176 + if (!net_wm_supported()) { 7177 + XtVaSetValues(wid, XtNoverrideRedirect, True, NULL); 7178 + XSync(dpy, True); 7179 + } 7180 + } 7181 +} 7182 + 7183 +extern int XError_ign; 7184 + 7185 +void dialog_input(Widget wid) { 7186 + XError_ign = 1; 7187 + XSetInputFocus(dpy, XtWindow(wid), RevertToParent, CurrentTime); 7188 + XSync(dpy, False); 7189 + usleep(30 * 1000); 7190 + XSync(dpy, False); 7191 + usleep(20 * 1000); 7192 + XSync(dpy, False); 7193 + XError_ign = 0; 7194 +} 7195 + 7196 +static void rmNL(char *s) { 7197 + int len; 7198 + if (s == NULL) { 7199 + return; 7200 + } 7201 + len = strlen(s); 7202 + if (len > 0 && s[len-1] == '\n') { 7203 + s[len-1] = '\0'; 7204 + } 7205 +} 7206 + 7207 +static void wm_delete(Widget w, char *func) { 7208 + char str[1024]; 7209 + Atom wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 7210 + XSetWMProtocols(dpy, XtWindow(w), &wmDeleteWindow, 1); 7211 + if (func) { 7212 + sprintf(str, "<Message>WM_PROTOCOLS: %s", func); 7213 + XtOverrideTranslations(w, XtParseTranslationTable (str)); 7214 + } 7215 +} 7216 + 7217 +static void xtmove(Widget w) { 7218 + XtMoveWidget(w, WidthOfScreen(XtScreen(w))*2/5, HeightOfScreen(XtScreen(w))*2/5); 7219 +} 7220 + 7221 +char * 7222 +DoScaleDialog() 7223 +{ 7224 + Widget pshell, dialog; 7225 + char *scaleValue; 7226 + char *valueString; 7227 + 7228 + pshell = XtVaCreatePopupShell("scaleDialog", transientShellWidgetClass, 7229 + toplevel, NULL); 7230 + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); 7231 + 7232 + dialog_over(pshell); 7233 + 7234 + if (0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); 7235 + XtPopup(pshell, XtGrabNonexclusive); 7236 + XtRealizeWidget(pshell); 7237 + 7238 + if (appData.scale != NULL) { 7239 + String label; 7240 + char tmp[410]; 7241 + XtVaGetValues(dialog, XtNlabel, &label, NULL); 7242 + if (strlen(label) + strlen(appData.scale) < 400) { 7243 + sprintf(tmp, "%s %s", label, appData.scale); 7244 + XtVaSetValues(dialog, XtNlabel, tmp, NULL); 7245 + } 7246 + } 7247 + 7248 + 7249 + if (1 && appData.popupFix) { 7250 + popupFixer(pshell); 7251 + } else { 7252 + xtmove(pshell); 7253 + } 7254 + dialog_input(pshell); 7255 + wm_delete(pshell, "ScaleDialogDone()"); 7256 + 7257 + scaleDialogDone = False; 7258 + 7259 + while (!scaleDialogDone) { 7260 + XtAppProcessEvent(appContext, XtIMAll); 7261 + } 7262 + 7263 + valueString = XawDialogGetValueString(dialog); 7264 + rmNL(valueString); 7265 + scaleValue = XtNewString(valueString); 7266 + 7267 + XtPopdown(pshell); 7268 + return scaleValue; 7269 +} 7270 + 7271 +char * 7272 +DoEscapeKeysDialog() 7273 +{ 7274 + Widget pshell, dialog; 7275 + char *escapeValue; 7276 + char *valueString; 7277 + char *curr = appData.escapeKeys ? appData.escapeKeys : "default"; 7278 + 7279 + pshell = XtVaCreatePopupShell("escapeDialog", transientShellWidgetClass, 7280 + toplevel, NULL); 7281 + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); 7282 + 7283 + dialog_over(pshell); 7284 + 7285 + if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); 7286 + XtPopup(pshell, XtGrabNonexclusive); 7287 + XtRealizeWidget(pshell); 7288 + 7289 + if (curr != NULL) { 7290 + String label; 7291 + char tmp[3010]; 7292 + XtVaGetValues(dialog, XtNlabel, &label, NULL); 7293 + if (strlen(label) + strlen(curr) < 3000) { 7294 + sprintf(tmp, "%s %s", label, curr); 7295 + XtVaSetValues(dialog, XtNlabel, tmp, NULL); 7296 + } 7297 + } 7298 + 7299 + if (appData.popupFix) { 7300 + popupFixer(pshell); 7301 + } else { 7302 + /* too big */ 7303 + if (0) xtmove(pshell); 7304 + } 7305 + dialog_input(pshell); 7306 + wm_delete(pshell, "EscapeDialogDone()"); 7307 + 7308 + escapeDialogDone = False; 7309 + 7310 + while (!escapeDialogDone) { 7311 + XtAppProcessEvent(appContext, XtIMAll); 7312 + } 7313 + 7314 + valueString = XawDialogGetValueString(dialog); 7315 + rmNL(valueString); 7316 + escapeValue = XtNewString(valueString); 7317 + 7318 + XtPopdown(pshell); 7319 + return escapeValue; 7320 +} 7321 + 7322 +void 7323 +YCropDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) 7324 +{ 7325 + ycropDialogDone = True; 7326 + if (w || event || params || num_params) {} 7327 +} 7328 + 7329 +char * 7330 +DoYCropDialog() 7331 +{ 7332 + Widget pshell, dialog; 7333 + char *ycropValue; 7334 + char *valueString; 7335 + 7336 + pshell = XtVaCreatePopupShell("ycropDialog", transientShellWidgetClass, 7337 + toplevel, NULL); 7338 + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); 7339 + 7340 + dialog_over(pshell); 7341 + 7342 + if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); 7343 + XtPopup(pshell, XtGrabNonexclusive); 7344 + XtRealizeWidget(pshell); 7345 + 7346 + if (1 && appData.popupFix) { 7347 + popupFixer(pshell); 7348 + } else { 7349 + xtmove(pshell); 7350 + } 7351 + dialog_input(pshell); 7352 + wm_delete(pshell, "YCropDialogDone()"); 7353 + 7354 + ycropDialogDone = False; 7355 + 7356 + while (!ycropDialogDone) { 7357 + XtAppProcessEvent(appContext, XtIMAll); 7358 + } 7359 + 7360 + valueString = XawDialogGetValueString(dialog); 7361 + rmNL(valueString); 7362 + ycropValue = XtNewString(valueString); 7363 + 7364 + XtPopdown(pshell); 7365 + return ycropValue; 7366 +} 7367 + 7368 +void 7369 +ScbarDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) 7370 +{ 7371 + scbarDialogDone = True; 7372 + if (w || event || params || num_params) {} 7373 +} 7374 + 7375 +char * 7376 +DoScbarDialog() 7377 +{ 7378 + Widget pshell, dialog; 7379 + char *scbarValue; 7380 + char *valueString; 7381 + 7382 + pshell = XtVaCreatePopupShell("scbarDialog", transientShellWidgetClass, 7383 + toplevel, NULL); 7384 + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); 7385 + 7386 + dialog_over(pshell); 7387 + 7388 + if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); 7389 + XtPopup(pshell, XtGrabNonexclusive); 7390 + XtRealizeWidget(pshell); 7391 + 7392 + if (1 && appData.popupFix) { 7393 + popupFixer(pshell); 7394 + } else { 7395 + xtmove(pshell); 7396 + } 7397 + dialog_input(pshell); 7398 + wm_delete(pshell, "ScbarDialogDone()"); 7399 + 7400 + scbarDialogDone = False; 7401 + 7402 + while (!scbarDialogDone) { 7403 + XtAppProcessEvent(appContext, XtIMAll); 7404 + } 7405 + 7406 + valueString = XawDialogGetValueString(dialog); 7407 + rmNL(valueString); 7408 + scbarValue = XtNewString(valueString); 7409 + 7410 + XtPopdown(pshell); 7411 + return scbarValue; 7412 +} 7413 + 7414 +void 7415 +ScaleNDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) 7416 +{ 7417 + scaleNDialogDone = True; 7418 + if (w || event || params || num_params) {} 7419 +} 7420 + 7421 +char * 7422 +DoScaleNDialog() 7423 +{ 7424 + Widget pshell, dialog; 7425 + char *scaleNValue; 7426 + char *valueString; 7427 + 7428 + pshell = XtVaCreatePopupShell("scaleNDialog", transientShellWidgetClass, 7429 + toplevel, NULL); 7430 + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); 7431 + 7432 + dialog_over(pshell); 7433 + wm_delete(pshell, "ScaleNDialogDone()"); 7434 + 7435 + if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); 7436 + XtPopup(pshell, XtGrabNonexclusive); 7437 + XtRealizeWidget(pshell); 7438 + 7439 + if (appData.popupFix) { 7440 + popupFixer(pshell); 7441 + } else { 7442 + xtmove(pshell); 7443 + } 7444 + dialog_input(pshell); 7445 + wm_delete(pshell, "ScaleNDialogDone()"); 7446 + 7447 + scaleNDialogDone = False; 7448 + 7449 + while (!scaleNDialogDone) { 7450 + XtAppProcessEvent(appContext, XtIMAll); 7451 + } 7452 + 7453 + valueString = XawDialogGetValueString(dialog); 7454 + rmNL(valueString); 7455 + scaleNValue = XtNewString(valueString); 7456 + 7457 + XtPopdown(pshell); 7458 + return scaleNValue; 7459 +} 7460 + 7461 +void 7462 +QualityDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) 7463 +{ 7464 + qualityDialogDone = True; 7465 + if (w || event || params || num_params) {} 7466 +} 7467 + 7468 +char * 7469 +DoQualityDialog() 7470 +{ 7471 + Widget pshell, dialog; 7472 + char *qualityValue; 7473 + char *valueString; 7474 + 7475 + pshell = XtVaCreatePopupShell("qualityDialog", transientShellWidgetClass, 7476 + toplevel, NULL); 7477 + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); 7478 + 7479 + dialog_over(pshell); 7480 + 7481 + if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); 7482 + XtPopup(pshell, XtGrabNonexclusive); 7483 + XtRealizeWidget(pshell); 7484 + 7485 + if (1 && appData.popupFix) { 7486 + popupFixer(pshell); 7487 + } else { 7488 + xtmove(pshell); 7489 + } 7490 + dialog_input(pshell); 7491 + wm_delete(pshell, "QualityDialogDone() HideQuality()"); 7492 + 7493 + qualityDialogDone = False; 7494 + 7495 + while (!qualityDialogDone) { 7496 + XtAppProcessEvent(appContext, XtIMAll); 7497 + } 7498 + 7499 + valueString = XawDialogGetValueString(dialog); 7500 + rmNL(valueString); 7501 + qualityValue = XtNewString(valueString); 7502 + 7503 + XtPopdown(pshell); 7504 + return qualityValue; 7505 +} 7506 + 7507 +void 7508 +CompressDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) 7509 +{ 7510 + compressDialogDone = True; 7511 + if (w || event || params || num_params) {} 7512 +} 7513 + 7514 +char * 7515 +DoCompressDialog() 7516 +{ 7517 + Widget pshell, dialog; 7518 + char *compressValue; 7519 + char *valueString; 7520 + 7521 + fprintf(stderr, "compress start:\n"); 7522 + 7523 + pshell = XtVaCreatePopupShell("compressDialog", transientShellWidgetClass, 7524 + toplevel, NULL); 7525 + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); 7526 + 7527 + dialog_over(pshell); 7528 + 7529 + if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); 7530 + XtPopup(pshell, XtGrabNonexclusive); 7531 + XtRealizeWidget(pshell); 7532 + 7533 + if (1 && appData.popupFix) { 7534 + popupFixer(pshell); 7535 + } else { 7536 + xtmove(pshell); 7537 + } 7538 + dialog_input(pshell); 7539 + wm_delete(pshell, "CompressDialogDone() HideCompress()"); 7540 + 7541 + compressDialogDone = False; 7542 + 7543 + while (!compressDialogDone) { 7544 + XtAppProcessEvent(appContext, XtIMAll); 7545 + } 7546 + 7547 + valueString = XawDialogGetValueString(dialog); 7548 + rmNL(valueString); 7549 + compressValue = XtNewString(valueString); 7550 + 7551 + fprintf(stderr, "compress done: %s\n", compressValue); 7552 + 7553 + XtPopdown(pshell); 7554 + return compressValue; 7555 +} 7556 7557 void 7558 ServerDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) 7559 { 7560 - serverDialogDone = True; 7561 + serverDialogDone = True; 7562 + if (w || event || params || num_params) {} 7563 } 7564 7565 char * 7566 DoServerDialog() 7567 { 7568 - Widget pshell, dialog; 7569 - char *vncServerName; 7570 - char *valueString; 7571 + Widget pshell, dialog; 7572 + char *vncServerName; 7573 + char *valueString; 7574 7575 - pshell = XtVaCreatePopupShell("serverDialog", transientShellWidgetClass, 7576 + pshell = XtVaCreatePopupShell("serverDialog", transientShellWidgetClass, 7577 toplevel, NULL); 7578 - dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); 7579 + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); 7580 7581 - XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, 7582 - HeightOfScreen(XtScreen(pshell))*2/5); 7583 - XtPopup(pshell, XtGrabNonexclusive); 7584 - XtRealizeWidget(pshell); 7585 + dialog_over(pshell); 7586 7587 - serverDialogDone = False; 7588 + if (0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); 7589 + XtPopup(pshell, XtGrabNonexclusive); 7590 + XtRealizeWidget(pshell); 7591 + 7592 + if (0 && appData.popupFix) { 7593 + popupFixer(pshell); 7594 + } else { 7595 + xtmove(pshell); 7596 + } 7597 +#if 0 7598 + dialog_input(pshell); 7599 +#endif 7600 + wm_delete(pshell, "ServerDialogDone()"); 7601 + 7602 + serverDialogDone = False; 7603 + 7604 + while (!serverDialogDone) { 7605 + XtAppProcessEvent(appContext, XtIMAll); 7606 + } 7607 + 7608 + valueString = XawDialogGetValueString(dialog); 7609 + rmNL(valueString); 7610 + vncServerName = XtNewString(valueString); 7611 7612 - while (!serverDialogDone) { 7613 - XtAppProcessEvent(appContext, XtIMAll); 7614 - } 7615 + XtPopdown(pshell); 7616 + return vncServerName; 7617 +} 7618 7619 - valueString = XawDialogGetValueString(dialog); 7620 - vncServerName = XtNewString(valueString); 7621 +void 7622 +UserDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) 7623 +{ 7624 + userDialogDone = True; 7625 + if (w || event || params || num_params) {} 7626 +} 7627 7628 - XtPopdown(pshell); 7629 - return vncServerName; 7630 +char * 7631 +DoUserDialog() 7632 +{ 7633 + Widget pshell, dialog; 7634 + char *userName; 7635 + char *valueString; 7636 + 7637 + pshell = XtVaCreatePopupShell("userDialog", transientShellWidgetClass, 7638 + toplevel, NULL); 7639 + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); 7640 + 7641 + dialog_over(pshell); 7642 + 7643 + if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); 7644 + XtPopup(pshell, XtGrabNonexclusive); 7645 + XtRealizeWidget(pshell); 7646 + 7647 + if (0 && appData.popupFix) { 7648 + popupFixer(pshell); 7649 + } else { 7650 + xtmove(pshell); 7651 + } 7652 +#if 0 7653 + dialog_input(pshell); 7654 +#endif 7655 + wm_delete(pshell, "UserDialogDone()"); 7656 + 7657 + userDialogDone = False; 7658 + 7659 + while (!userDialogDone) { 7660 + XtAppProcessEvent(appContext, XtIMAll); 7661 + } 7662 + 7663 + valueString = XawDialogGetValueString(dialog); 7664 + rmNL(valueString); 7665 + userName = XtNewString(valueString); 7666 + 7667 + XtPopdown(pshell); 7668 + return userName; 7669 } 7670 7671 void 7672 -PasswordDialogDone(Widget w, XEvent *event, String *params, 7673 - Cardinal *num_params) 7674 +PasswordDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) 7675 { 7676 - passwordDialogDone = True; 7677 + passwordDialogDone = True; 7678 + if (w || event || params || num_params) {} 7679 } 7680 7681 char * 7682 DoPasswordDialog() 7683 { 7684 - Widget pshell, dialog; 7685 - char *password; 7686 - char *valueString; 7687 + Widget pshell, dialog; 7688 + char *password; 7689 + char *valueString; 7690 7691 - pshell = XtVaCreatePopupShell("passwordDialog", transientShellWidgetClass, 7692 + pshell = XtVaCreatePopupShell("passwordDialog", transientShellWidgetClass, 7693 toplevel, NULL); 7694 - dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); 7695 - 7696 - XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, 7697 - HeightOfScreen(XtScreen(pshell))*2/5); 7698 - XtPopup(pshell, XtGrabNonexclusive); 7699 - XtRealizeWidget(pshell); 7700 - 7701 - passwordDialogDone = False; 7702 + dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); 7703 7704 - while (!passwordDialogDone) { 7705 - XtAppProcessEvent(appContext, XtIMAll); 7706 - } 7707 + dialog_over(pshell); 7708 7709 - valueString = XawDialogGetValueString(dialog); 7710 - password = XtNewString(valueString); 7711 + if(0) XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, HeightOfScreen(XtScreen(pshell))*2/5); 7712 + XtPopup(pshell, XtGrabNonexclusive); 7713 + XtRealizeWidget(pshell); 7714 + 7715 + if (0 && appData.popupFix) { 7716 + popupFixer(pshell); 7717 + } else { 7718 + xtmove(pshell); 7719 + } 7720 +#if 0 7721 + dialog_input(pshell); 7722 +#endif 7723 + wm_delete(pshell, "PasswordDialogDone()"); 7724 + 7725 + passwordDialogDone = False; 7726 + 7727 + while (!passwordDialogDone) { 7728 + XtAppProcessEvent(appContext, XtIMAll); 7729 + } 7730 + 7731 + valueString = XawDialogGetValueString(dialog); 7732 + rmNL(valueString); 7733 + password = XtNewString(valueString); 7734 7735 - XtPopdown(pshell); 7736 - return password; 7737 + XtPopdown(pshell); 7738 + return password; 7739 } 7740 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/fullscreen.c vnc_unixsrc/vncviewer/fullscreen.c 7741 --- vnc_unixsrc.orig/vncviewer/fullscreen.c 2003-10-09 05:23:49.000000000 -0400 7742 +++ vnc_unixsrc/vncviewer/fullscreen.c 2010-02-25 22:37:49.000000000 -0500 7743 @@ -22,20 +22,24 @@ 7744 */ 7745 7746 #include <vncviewer.h> 7747 +#include <time.h> 7748 #include <X11/Xaw/Form.h> 7749 #include <X11/Xaw/Viewport.h> 7750 #include <X11/Xaw/Toggle.h> 7751 7752 static Bool DoBumpScroll(); 7753 +static Bool DoJumpScroll(); 7754 static void BumpScrollTimerCallback(XtPointer clientData, XtIntervalId *id); 7755 +static void JumpScrollTimerCallback(XtPointer clientData, XtIntervalId *id); 7756 static XtIntervalId timer; 7757 static Bool timerSet = False; 7758 static Bool scrollLeft, scrollRight, scrollUp, scrollDown; 7759 -static Position desktopX, desktopY; 7760 +Position desktopX, desktopY; 7761 static Dimension viewportWidth, viewportHeight; 7762 static Dimension scrollbarWidth, scrollbarHeight; 7763 7764 7765 +int scale_round(int len, double fac); 7766 7767 /* 7768 * FullScreenOn goes into full-screen mode. It makes the toplevel window 7769 @@ -78,112 +82,456 @@ 7770 * variables so that FullScreenOff can use them. 7771 */ 7772 7773 -void 7774 -FullScreenOn() 7775 -{ 7776 - Dimension toplevelWidth, toplevelHeight; 7777 - Dimension oldViewportWidth, oldViewportHeight, clipWidth, clipHeight; 7778 - Position viewportX, viewportY; 7779 - 7780 - appData.fullScreen = True; 7781 - 7782 - if (si.framebufferWidth > dpyWidth || si.framebufferHeight > dpyHeight) { 7783 - 7784 - XtVaSetValues(viewport, XtNforceBars, True, NULL); 7785 - XtVaGetValues(viewport, XtNwidth, &oldViewportWidth, 7786 - XtNheight, &oldViewportHeight, NULL); 7787 - XtVaGetValues(XtNameToWidget(viewport, "clip"), 7788 - XtNwidth, &clipWidth, XtNheight, &clipHeight, NULL); 7789 - 7790 - scrollbarWidth = oldViewportWidth - clipWidth; 7791 - scrollbarHeight = oldViewportHeight - clipHeight; 7792 - 7793 - if (si.framebufferWidth > dpyWidth) { 7794 - viewportWidth = toplevelWidth = dpyWidth + scrollbarWidth; 7795 - } else { 7796 - viewportWidth = si.framebufferWidth + scrollbarWidth; 7797 - toplevelWidth = dpyWidth; 7798 - } 7799 - 7800 - if (si.framebufferHeight > dpyHeight) { 7801 - viewportHeight = toplevelHeight = dpyHeight + scrollbarHeight; 7802 - } else { 7803 - viewportHeight = si.framebufferHeight + scrollbarHeight; 7804 - toplevelHeight = dpyHeight; 7805 - } 7806 - 7807 - } else { 7808 - viewportWidth = si.framebufferWidth; 7809 - viewportHeight = si.framebufferHeight; 7810 - toplevelWidth = dpyWidth; 7811 - toplevelHeight = dpyHeight; 7812 - } 7813 +int net_wm_supported(void) { 7814 + unsigned char *data; 7815 + unsigned long items_read, items_left, i; 7816 + int ret, format; 7817 + Window wm; 7818 + Atom type; 7819 + Atom _NET_SUPPORTING_WM_CHECK; 7820 + Atom _NET_SUPPORTED; 7821 + Atom _NET_WM_STATE; 7822 + Atom _NET_WM_STATE_FULLSCREEN; 7823 + 7824 + static time_t last_check = 0; 7825 + static int fs_supported = -1; 7826 + 7827 + if (fs_supported >= 0 && time(NULL) < last_check + 600) { 7828 + static int first = 1; 7829 + if (first) { 7830 + fprintf(stderr, "fs_supported: %d\n", fs_supported); 7831 + } 7832 + first = 0; 7833 + return fs_supported; 7834 + } 7835 + last_check = time(NULL); 7836 + 7837 + fs_supported = 0; 7838 + 7839 + _NET_SUPPORTING_WM_CHECK = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); 7840 + _NET_SUPPORTED = XInternAtom(dpy, "_NET_SUPPORTED", False); 7841 + _NET_WM_STATE = XInternAtom(dpy, "_NET_WM_STATE", False); 7842 + _NET_WM_STATE_FULLSCREEN = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); 7843 + 7844 + ret = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _NET_SUPPORTING_WM_CHECK, 7845 + 0L, 1L, False, XA_WINDOW, &type, &format, &items_read, &items_left, &data); 7846 + 7847 + if (ret != Success || !items_read) { 7848 + if (ret == Success) { 7849 + XFree(data); 7850 + } 7851 + return fs_supported; 7852 + } 7853 + 7854 + wm = ((Window*) data)[0]; 7855 + XFree(data); 7856 + 7857 + ret = XGetWindowProperty(dpy, wm, _NET_SUPPORTING_WM_CHECK, 7858 + 0L, 1L, False, XA_WINDOW, &type, &format, &items_read, &items_left, &data); 7859 + 7860 + if (ret != Success || !items_read) { 7861 + if (ret == Success) { 7862 + XFree(data); 7863 + } 7864 + return fs_supported; 7865 + } 7866 + 7867 + if (wm != ((Window*) data)[0]) { 7868 + XFree(data); 7869 + return fs_supported; 7870 + } 7871 + 7872 + ret = XGetWindowProperty(dpy, DefaultRootWindow(dpy), _NET_SUPPORTED, 7873 + 0L, 8192L, False, XA_ATOM, &type, &format, &items_read, &items_left, &data); 7874 + 7875 + if (ret != Success || !items_read) { 7876 + if (ret == Success) { 7877 + XFree(data); 7878 + } 7879 + return fs_supported; 7880 + } 7881 + 7882 + for (i=0; i < items_read; i++) { 7883 + if ( ((Atom*) data)[i] == _NET_WM_STATE_FULLSCREEN) { 7884 + fs_supported = 1; 7885 + } 7886 + } 7887 + XFree(data); 7888 7889 - viewportX = (toplevelWidth - viewportWidth) / 2; 7890 - viewportY = (toplevelHeight - viewportHeight) / 2; 7891 + return fs_supported; 7892 +} 7893 7894 +static void net_wm_fullscreen(int to_fs) { 7895 + 7896 + int _NET_WM_STATE_REMOVE = 0; 7897 + int _NET_WM_STATE_ADD = 1; 7898 +#if 0 7899 + int _NET_WM_STATE_TOGGLE = 2; 7900 +#endif 7901 + Atom _NET_WM_STATE = XInternAtom(dpy, "_NET_WM_STATE", False); 7902 + Atom _NET_WM_STATE_FULLSCREEN = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); 7903 + XEvent xev; 7904 + 7905 + if (to_fs == 2) { 7906 + XChangeProperty(dpy, XtWindow(toplevel), _NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char*)&_NET_WM_STATE_FULLSCREEN, 1); 7907 + } else { 7908 + xev.xclient.type = ClientMessage; 7909 + xev.xclient.window = XtWindow(toplevel); 7910 + xev.xclient.message_type = _NET_WM_STATE; 7911 + xev.xclient.serial = 0; 7912 + xev.xclient.display = dpy; 7913 + xev.xclient.send_event = True; 7914 + xev.xclient.format = 32; 7915 + xev.xclient.data.l[0] = to_fs ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; 7916 + xev.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN; 7917 + xev.xclient.data.l[2] = 0; 7918 + xev.xclient.data.l[3] = 0; 7919 + xev.xclient.data.l[4] = 0; 7920 + XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); 7921 + } 7922 7923 - /* We want to stop the window manager from managing our toplevel window. 7924 - This is not really a nice thing to do, so may not work properly with every 7925 - window manager. We do this simply by setting overrideRedirect and 7926 - reparenting our window to the root. The window manager will get a 7927 - ReparentNotify and hopefully clean up its frame window. */ 7928 + XSync(dpy, False); 7929 +} 7930 7931 - XtVaSetValues(toplevel, XtNoverrideRedirect, True, NULL); 7932 +time_t main_grab = 0; 7933 7934 - XReparentWindow(dpy, XtWindow(toplevel), DefaultRootWindow(dpy), 0, 0); 7935 +void fs_ungrab(int check) { 7936 + if (check) { 7937 + if (time(NULL) <= main_grab + 2) { 7938 + return; 7939 + } 7940 + if (net_wm_supported()) { 7941 + return; 7942 + } 7943 + } 7944 + fprintf(stderr, "calling fs_ungrab()\n"); 7945 + if (appData.grabAll) { /* runge top of FullScreenOff */ 7946 + fprintf(stderr, "calling XUngrabServer(dpy)\n"); 7947 + XUngrabServer(dpy); 7948 + } 7949 + if (appData.grabKeyboard) { 7950 + fprintf(stderr, "calling XUngrabKeyboard(dpy)\n"); 7951 + XtUngrabKeyboard(desktop, CurrentTime); 7952 + } 7953 +} 7954 7955 - /* Some WMs does not obey x,y values of XReparentWindow; the window 7956 - is not placed in the upper, left corner. The code below fixes 7957 - this: It manually moves the window, after the Xserver is done 7958 - with XReparentWindow. The last XSync seems to prevent losing 7959 - focus, but I don't know why. */ 7960 - XSync(dpy, False); 7961 - XMoveWindow(dpy, XtWindow(toplevel), 0, 0); 7962 - XSync(dpy, False); 7963 - 7964 - /* Now we want to fix the size of "viewport". We shouldn't just change it 7965 - directly. Instead we set "toplevel" to the required size (which should 7966 - propagate through "form" to "viewport"). Then we remove "viewport" from 7967 - being managed by "form", change its resources to position it and make sure 7968 - that "form" won't attempt to resize it, then ask "form" to manage it 7969 - again. */ 7970 - 7971 - XtResizeWidget(toplevel, viewportWidth, viewportHeight, 0); 7972 - 7973 - XtUnmanageChild(viewport); 7974 - 7975 - XtVaSetValues(viewport, 7976 - XtNhorizDistance, viewportX, 7977 - XtNvertDistance, viewportY, 7978 - XtNleft, XtChainLeft, 7979 - XtNright, XtChainLeft, 7980 - XtNtop, XtChainTop, 7981 - XtNbottom, XtChainTop, 7982 - NULL); 7983 +void fs_grab(int check) { 7984 + if (check) { 7985 + if (time(NULL) <= main_grab + 2) { 7986 + return; 7987 + } 7988 + if (net_wm_supported()) { 7989 + return; 7990 + } 7991 + } 7992 + 7993 + main_grab = time(NULL); 7994 + 7995 + fprintf(stderr, "calling fs_grab()\n"); 7996 + 7997 +#define FORCE_UP \ 7998 + XSync(dpy, False); \ 7999 + XUnmapWindow(dpy, XtWindow(toplevel)); \ 8000 + XSync(dpy, False); \ 8001 + XMapWindow(dpy, XtWindow(toplevel)); \ 8002 + XRaiseWindow(dpy, XtWindow(toplevel)); \ 8003 + XSync(dpy, False); 8004 + 8005 + if (appData.grabKeyboard && XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) { 8006 + fprintf(stderr, "XtGrabKeyboard() failed.\n"); 8007 + XSync(dpy, False); 8008 + usleep(100 * 1000); 8009 + FORCE_UP 8010 + 8011 + if (XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) { 8012 + fprintf(stderr, "XtGrabKeyboard() failed again.\n"); 8013 + usleep(200 * 1000); 8014 + XSync(dpy, False); 8015 + if (XtGrabKeyboard(desktop, True, GrabModeAsync, GrabModeAsync, CurrentTime) != GrabSuccess) { 8016 + fprintf(stderr, "XtGrabKeyboard() failed 3rd time.\n"); 8017 + } else { 8018 + fprintf(stderr, "XtGrabKeyboard() OK 3rd try.\n"); 8019 + } 8020 + } else { 8021 + fprintf(stderr, "XtGrabKeyboard() OK 2nd try.\n"); 8022 + } 8023 + XRaiseWindow(dpy, XtWindow(toplevel)); 8024 + } 8025 + 8026 + if (appData.grabAll) { 8027 + fprintf(stderr, "calling XGrabServer(dpy)\n"); 8028 + if (! XGrabServer(dpy)) { 8029 + XSync(dpy, False); 8030 + usleep(100 * 1000); 8031 + fprintf(stderr, "calling XGrabServer(dpy) 2nd time\n"); 8032 + if (!XGrabServer(dpy)) { 8033 + XSync(dpy, False); 8034 + usleep(200 * 1000); 8035 + fprintf(stderr, "calling XGrabServer(dpy) 3rd time\n"); 8036 + if (XGrabServer(dpy)) { 8037 + fprintf(stderr, "XGrabServer(dpy) OK 3rd time\n"); 8038 + } 8039 + } else { 8040 + fprintf(stderr, "XGrabServer(dpy) OK 2nd time\n"); 8041 + } 8042 + XSync(dpy, False); 8043 + } 8044 + if (getenv("VNCVIEWER_FORCE_UP")) { 8045 + fprintf(stderr, "FORCE_UP\n"); 8046 + FORCE_UP 8047 + } 8048 + } 8049 +} 8050 + 8051 +extern int fullscreen_startup; 8052 +extern double last_fullscreen; 8053 + 8054 +#define set_size_hints() \ 8055 +{ \ 8056 + long supplied; \ 8057 + XSizeHints *sizehints = XAllocSizeHints(); \ 8058 + XGetWMSizeHints(dpy, topwin, sizehints, &supplied, XA_WM_NORMAL_HINTS); \ 8059 + if (sizehints->base_width < toplevelWidth) { \ 8060 + sizehints->base_width = toplevelWidth; \ 8061 + } \ 8062 + if (sizehints->base_height < toplevelHeight) { \ 8063 + sizehints->base_height = toplevelHeight; \ 8064 + } \ 8065 + if (sizehints->max_width < toplevelWidth) { \ 8066 + sizehints->max_width = toplevelWidth; \ 8067 + } \ 8068 + if (sizehints->max_height < toplevelHeight) { \ 8069 + sizehints->max_height = toplevelHeight; \ 8070 + } \ 8071 + XSetWMSizeHints(dpy, topwin, sizehints, XA_WM_NORMAL_HINTS); \ 8072 + XFree(sizehints); \ 8073 +} 8074 8075 - XtManageChild(viewport); 8076 +extern int scale_x, scale_y; 8077 +extern double scale_factor_y; 8078 + 8079 +void 8080 +FullScreenOn() 8081 +{ 8082 + Dimension toplevelWidth, toplevelHeight; 8083 + Dimension oldViewportWidth, oldViewportHeight, clipWidth, clipHeight; 8084 + Position viewportX, viewportY; 8085 + int do_net_wm = net_wm_supported(); 8086 + int fbW = si.framebufferWidth; 8087 + int fbH = si.framebufferHeight; 8088 + int eff_height; 8089 + 8090 + Bool fsAlready = appData.fullScreen, toobig = False; 8091 + Window topwin = XtWindow(toplevel); 8092 + 8093 + appData.fullScreen = True; 8094 + 8095 + last_fullscreen = dnow(); 8096 + 8097 + if (scale_x > 0) { 8098 + fbW = scale_x; 8099 + fbH = scale_y; 8100 + } 8101 + 8102 + eff_height = fbH; 8103 + if (appData.yCrop > 0) { 8104 + eff_height = appData.yCrop; 8105 + if (scale_y > 0) { 8106 + eff_height = scale_round(eff_height, scale_factor_y); 8107 + } 8108 + } 8109 + 8110 + if (fbW > dpyWidth || eff_height > dpyHeight) { 8111 + 8112 + toobig = True; 8113 + 8114 + /* 8115 + * This is a crazy thing to have the scrollbars hang 8116 + * just a bit offscreen to the right and below. the user 8117 + * will not see them and bumpscroll will work. 8118 + */ 8119 + 8120 + XtVaSetValues(viewport, XtNforceBars, True, NULL); 8121 + XtVaGetValues(viewport, XtNwidth, &oldViewportWidth, XtNheight, &oldViewportHeight, NULL); 8122 + XtVaGetValues(XtNameToWidget(viewport, "clip"), XtNwidth, &clipWidth, XtNheight, &clipHeight, NULL); 8123 + 8124 + scrollbarWidth = oldViewportWidth - clipWidth; 8125 + scrollbarHeight = oldViewportHeight - clipHeight; 8126 + 8127 + if (fbW > dpyWidth) { 8128 + viewportWidth = toplevelWidth = dpyWidth + scrollbarWidth; 8129 + } else { 8130 + viewportWidth = fbW + scrollbarWidth; 8131 + toplevelWidth = dpyWidth; 8132 + } 8133 + 8134 + if (eff_height > dpyHeight) { 8135 + viewportHeight = toplevelHeight = dpyHeight + scrollbarHeight; 8136 + } else { 8137 + viewportHeight = eff_height + scrollbarHeight; 8138 + toplevelHeight = dpyHeight; 8139 + } 8140 + if (do_net_wm) { 8141 + /* but for _NET_WM we make toplevel be correct dpy size */ 8142 + toplevelWidth = dpyWidth; 8143 + toplevelHeight = dpyHeight; 8144 + } 8145 + 8146 + } else { 8147 + viewportWidth = fbW; 8148 + viewportHeight = eff_height; 8149 + toplevelWidth = dpyWidth; 8150 + toplevelHeight = dpyHeight; 8151 + } 8152 8153 - /* Now we can set "toplevel" to its proper size. */ 8154 + viewportX = (toplevelWidth - viewportWidth) / 2; 8155 + viewportY = (toplevelHeight - viewportHeight) / 2; 8156 8157 - XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0); 8158 + if (viewportX < 0) viewportX = 0; 8159 + if (viewportY < 0) viewportY = 0; 8160 8161 - /* Set the popup to overrideRedirect too */ 8162 8163 - XtVaSetValues(popup, XtNoverrideRedirect, True, NULL); 8164 + /* We want to stop the window manager from managing our toplevel window. 8165 + This is not really a nice thing to do, so may not work properly with every 8166 + window manager. We do this simply by setting overrideRedirect and 8167 + reparenting our window to the root. The window manager will get a 8168 + ReparentNotify and hopefully clean up its frame window. */ 8169 8170 - /* Try to get the input focus. */ 8171 + if (! fsAlready) { 8172 + if (!do_net_wm) { 8173 + /* added to try to raise it on top for some cirumstances */ 8174 + XUnmapWindow(dpy, topwin); 8175 + 8176 + XtVaSetValues(toplevel, XtNoverrideRedirect, True, NULL); 8177 +#if 0 8178 + XtVaSetValues(viewport, XtNoverrideRedirect, True, NULL); 8179 + XtVaSetValues(desktop, XtNoverrideRedirect, True, NULL); 8180 +#endif 8181 + XtVaSetValues(popup, XtNoverrideRedirect, True, NULL); 8182 + 8183 + XReparentWindow(dpy, topwin, DefaultRootWindow(dpy), 0, 0); 8184 + 8185 + /* Some WMs does not obey x,y values of XReparentWindow; the window 8186 + is not placed in the upper, left corner. The code below fixes 8187 + this: It manually moves the window, after the Xserver is done 8188 + with XReparentWindow. The last XSync seems to prevent losing 8189 + focus, but I don't know why. */ 8190 + 8191 + XSync(dpy, False); 8192 + 8193 + /* added to try to raise it on top for some cirumstances */ 8194 + XMapRaised(dpy, topwin); 8195 + 8196 + XMoveWindow(dpy, topwin, 0, 0); 8197 + XSync(dpy, False); 8198 + } 8199 + 8200 + /* Now we want to fix the size of "viewport". We shouldn't just change it 8201 + directly. Instead we set "toplevel" to the required size (which should 8202 + propagate through "form" to "viewport"). Then we remove "viewport" from 8203 + being managed by "form", change its resources to position it and make sure 8204 + that "form" won't attempt to resize it, then ask "form" to manage it 8205 + again. */ 8206 + 8207 + XtResizeWidget(toplevel, viewportWidth, viewportHeight, 0); 8208 + 8209 + XtUnmanageChild(viewport); 8210 + 8211 + XtVaSetValues(viewport, 8212 + XtNhorizDistance, viewportX, 8213 + XtNvertDistance, viewportY, 8214 + XtNleft, XtChainLeft, 8215 + XtNright, XtChainLeft, 8216 + XtNtop, XtChainTop, 8217 + XtNbottom, XtChainTop, 8218 + NULL); 8219 + 8220 + XtManageChild(viewport); 8221 + XSync(dpy, False); 8222 + } else { 8223 + XSync(dpy, False); 8224 + } 8225 + 8226 + /* Now we can set "toplevel" to its proper size. */ 8227 + 8228 +#if 0 8229 + XtVaSetValues(toplevel, XtNwidth, toplevelWidth, XtNheight, toplevelHeight, NULL); 8230 + XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0); 8231 +#endif 8232 + XResizeWindow(dpy, topwin, toplevelWidth, toplevelHeight); 8233 + 8234 + if (do_net_wm) { 8235 + XWindowAttributes attr; 8236 + int ok = 0, i, delay = 20; 8237 + 8238 + usleep(delay * 1000); 8239 + 8240 +#define GSIZE() \ 8241 + XGetWindowAttributes(dpy, topwin, &attr); 8242 + 8243 +#define PSIZE(s) \ 8244 + XSync(dpy, False); \ 8245 + XGetWindowAttributes(dpy, topwin, &attr); \ 8246 + fprintf(stderr, "%s %dx%d+%d+%d\n", s, attr.width, attr.height, attr.x, attr.y); 8247 + 8248 + PSIZE("size-A:"); 8249 + 8250 + set_size_hints(); 8251 + 8252 + net_wm_fullscreen(1); 8253 + 8254 + PSIZE("size-B:"); 8255 + 8256 + for (i=0; i < 30; i++) { 8257 + usleep(delay * 1000); 8258 + GSIZE(); 8259 + fprintf(stderr, "size[%d] %dx%d+%d+%d\n", i, attr.width, attr.height, attr.x, attr.y); 8260 + if (attr.width == toplevelWidth && attr.height == toplevelHeight) { 8261 + ok = 1; 8262 + fprintf(stderr, "size ok.\n"); 8263 + XSync(dpy, False); 8264 + break; 8265 + } 8266 + set_size_hints(); 8267 + XResizeWindow(dpy, topwin, toplevelWidth, toplevelHeight); 8268 + XMoveWindow(dpy, topwin, 0, 0); 8269 + XSync(dpy, False); 8270 + } 8271 + 8272 + PSIZE("size-C:"); 8273 + } 8274 + 8275 + fprintf(stderr, "\ntoplevel: %dx%d viewport: %dx%d\n", toplevelWidth, toplevelHeight, viewportWidth, viewportHeight); 8276 + 8277 +#if defined (__SVR4) && defined (__sun) 8278 + if (!do_net_wm) { 8279 + /* CDE */ 8280 + XSync(dpy, False); 8281 + usleep(200 * 1000); 8282 + XMoveWindow(dpy, topwin, 0, 0); 8283 + XMapRaised(dpy, topwin); 8284 + XSync(dpy, False); 8285 + } 8286 +#endif 8287 + 8288 + if (fsAlready) { 8289 + XtResizeWidget(viewport, viewportWidth, viewportHeight, 0); 8290 + if (! toobig) { 8291 + XtVaSetValues(viewport, XtNforceBars, False, NULL); 8292 + } 8293 + XMoveWindow(dpy, topwin, viewportX, viewportY); 8294 + XSync(dpy, False); 8295 + } 8296 + 8297 + /* Try to get the input focus. */ 8298 8299 - XSetInputFocus(dpy, DefaultRootWindow(dpy), RevertToPointerRoot, 8300 - CurrentTime); 8301 + /* original vnc: DefaultRootWindow(dpy) instead of PointerRoot */ 8302 + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); 8303 8304 - /* Optionally, grab the keyboard. */ 8305 + /* Optionally, grab the keyboard. */ 8306 + fs_grab(0); 8307 8308 - if (appData.grabKeyboard && 8309 - XtGrabKeyboard(desktop, True, GrabModeAsync, 8310 - GrabModeAsync, CurrentTime) != GrabSuccess) { 8311 - fprintf(stderr, "XtGrabKeyboard() failed.\n"); 8312 - } 8313 + /* finally done. */ 8314 } 8315 8316 8317 @@ -205,28 +553,52 @@ 8318 void 8319 FullScreenOff() 8320 { 8321 - int toplevelWidth = si.framebufferWidth; 8322 - int toplevelHeight = si.framebufferHeight; 8323 - 8324 - appData.fullScreen = False; 8325 + int toplevelWidth, toplevelHeight; 8326 + int do_net_wm = net_wm_supported(); 8327 + int fbW = si.framebufferWidth; 8328 + int fbH = si.framebufferHeight; 8329 + int eff_height; 8330 + 8331 + appData.fullScreen = False; 8332 + 8333 + last_fullscreen = dnow(); 8334 + 8335 + if (scale_x > 0) { 8336 + fbW = scale_x; 8337 + fbH = scale_y; 8338 + } 8339 + 8340 + eff_height = fbH; 8341 + if (appData.yCrop > 0) { 8342 + eff_height = appData.yCrop; 8343 + if (scale_y > 0) { 8344 + eff_height = scale_round(eff_height, scale_factor_y); 8345 + } 8346 + } 8347 + 8348 + toplevelWidth = fbW; 8349 + toplevelHeight = eff_height; 8350 + 8351 + fs_ungrab(0); 8352 + 8353 + if (do_net_wm) { 8354 + net_wm_fullscreen(0); 8355 + } else { 8356 + XtUnmapWidget(toplevel); 8357 + } 8358 8359 - if (appData.grabKeyboard) 8360 - XtUngrabKeyboard(desktop, CurrentTime); 8361 - 8362 - XtUnmapWidget(toplevel); 8363 - 8364 - XtResizeWidget(toplevel, 8365 + XtResizeWidget(toplevel, 8366 viewportWidth - scrollbarWidth, 8367 viewportHeight - scrollbarHeight, 0); 8368 - XtResizeWidget(viewport, 8369 + XtResizeWidget(viewport, 8370 viewportWidth - scrollbarWidth, 8371 viewportHeight - scrollbarHeight, 0); 8372 8373 - XtVaSetValues(viewport, XtNforceBars, False, NULL); 8374 + XtVaSetValues(viewport, XtNforceBars, False, NULL); 8375 8376 - XtUnmanageChild(viewport); 8377 + XtUnmanageChild(viewport); 8378 8379 - XtVaSetValues(viewport, 8380 + XtVaSetValues(viewport, 8381 XtNhorizDistance, 0, 8382 XtNvertDistance, 0, 8383 XtNleft, XtChainLeft, 8384 @@ -235,24 +607,42 @@ 8385 XtNbottom, XtChainBottom, 8386 NULL); 8387 8388 - XtManageChild(viewport); 8389 - 8390 - XtVaSetValues(toplevel, XtNoverrideRedirect, False, NULL); 8391 - 8392 - if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth) 8393 - toplevelWidth = dpyWidth - appData.wmDecorationWidth; 8394 - 8395 - if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight) 8396 - toplevelHeight = dpyHeight - appData.wmDecorationHeight; 8397 - 8398 - XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0); 8399 - 8400 - XtMapWidget(toplevel); 8401 - XSync(dpy, False); 8402 + XtManageChild(viewport); 8403 8404 - /* Set the popup back to non-overrideRedirect */ 8405 - 8406 - XtVaSetValues(popup, XtNoverrideRedirect, False, NULL); 8407 + if (!do_net_wm) { 8408 + XtVaSetValues(toplevel, XtNoverrideRedirect, False, NULL); 8409 +#if 0 8410 + XtVaSetValues(viewport, XtNoverrideRedirect, False, NULL); 8411 + XtVaSetValues(desktop, XtNoverrideRedirect, False, NULL); 8412 +#endif 8413 + XtVaSetValues(popup, XtNoverrideRedirect, False, NULL); 8414 + } 8415 + 8416 + if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth) 8417 + toplevelWidth = dpyWidth - appData.wmDecorationWidth; 8418 + 8419 + if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight) 8420 + toplevelHeight = dpyHeight - appData.wmDecorationHeight; 8421 + 8422 + XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0); 8423 + 8424 + if (!do_net_wm) { 8425 + XtMapWidget(toplevel); 8426 + } 8427 + XSync(dpy, False); 8428 + 8429 + /* Set the popup back to non-overrideRedirect */ 8430 + 8431 + XtVaSetValues(popup, XtNoverrideRedirect, False, NULL); 8432 + 8433 + if (!do_net_wm) { 8434 + int x = (dpyWidth - toplevelWidth) / 2; 8435 + int y = (dpyHeight - toplevelHeight) / 2; 8436 + if (x > 0 && y > 0) { 8437 + XSync(dpy, False); 8438 + XMoveWindow(dpy, XtWindow(toplevel), x, y); 8439 + } 8440 + } 8441 } 8442 8443 8444 @@ -264,10 +654,12 @@ 8445 void 8446 SetFullScreenState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 8447 { 8448 - if (appData.fullScreen) 8449 - XtVaSetValues(w, XtNstate, True, NULL); 8450 - else 8451 - XtVaSetValues(w, XtNstate, False, NULL); 8452 + if (appData.fullScreen) { 8453 + XtVaSetValues(w, XtNstate, True, NULL); 8454 + } else { 8455 + XtVaSetValues(w, XtNstate, False, NULL); 8456 + } 8457 + if (w || ev || params || num_params) {} 8458 } 8459 8460 8461 @@ -278,11 +670,12 @@ 8462 void 8463 ToggleFullScreen(Widget w, XEvent *ev, String *params, Cardinal *num_params) 8464 { 8465 - if (appData.fullScreen) { 8466 - FullScreenOff(); 8467 - } else { 8468 - FullScreenOn(); 8469 - } 8470 + if (appData.fullScreen) { 8471 + FullScreenOff(); 8472 + } else { 8473 + FullScreenOn(); 8474 + } 8475 + if (w || ev || params || num_params) {} 8476 } 8477 8478 8479 @@ -294,84 +687,226 @@ 8480 Bool 8481 BumpScroll(XEvent *ev) 8482 { 8483 - scrollLeft = scrollRight = scrollUp = scrollDown = False; 8484 + scrollLeft = scrollRight = scrollUp = scrollDown = False; 8485 8486 - if (ev->xmotion.x_root >= dpyWidth - 3) 8487 - scrollRight = True; 8488 - else if (ev->xmotion.x_root <= 2) 8489 - scrollLeft = True; 8490 - 8491 - if (ev->xmotion.y_root >= dpyHeight - 3) 8492 - scrollDown = True; 8493 - else if (ev->xmotion.y_root <= 2) 8494 - scrollUp = True; 8495 - 8496 - if (scrollLeft || scrollRight || scrollUp || scrollDown) { 8497 - if (timerSet) 8498 - return True; 8499 - 8500 - XtVaGetValues(desktop, XtNx, &desktopX, XtNy, &desktopY, NULL); 8501 - desktopX = -desktopX; 8502 - desktopY = -desktopY; 8503 - 8504 - return DoBumpScroll(); 8505 - } 8506 - 8507 - if (timerSet) { 8508 - XtRemoveTimeOut(timer); 8509 - timerSet = False; 8510 - } 8511 + if (ev->xmotion.x_root >= dpyWidth - 3) 8512 + scrollRight = True; 8513 + else if (ev->xmotion.x_root <= 2) 8514 + scrollLeft = True; 8515 + 8516 + if (ev->xmotion.y_root >= dpyHeight - 3) 8517 + scrollDown = True; 8518 + else if (ev->xmotion.y_root <= 2) 8519 + scrollUp = True; 8520 + 8521 + if (scrollLeft || scrollRight || scrollUp || scrollDown) { 8522 + if (timerSet) 8523 + return True; 8524 + 8525 + XtVaGetValues(desktop, XtNx, &desktopX, XtNy, &desktopY, NULL); 8526 + desktopX = -desktopX; 8527 + desktopY = -desktopY; 8528 + 8529 + return DoBumpScroll(); 8530 + } 8531 + 8532 + if (timerSet) { 8533 + XtRemoveTimeOut(timer); 8534 + timerSet = False; 8535 + } 8536 8537 - return False; 8538 + return False; 8539 } 8540 8541 static Bool 8542 DoBumpScroll() 8543 { 8544 - int oldx = desktopX, oldy = desktopY; 8545 - 8546 - if (scrollRight) { 8547 - if (desktopX < si.framebufferWidth - dpyWidth) { 8548 - desktopX += appData.bumpScrollPixels; 8549 - if (desktopX > si.framebufferWidth - dpyWidth) 8550 - desktopX = si.framebufferWidth - dpyWidth; 8551 - } 8552 - } else if (scrollLeft) { 8553 - if (desktopX > 0) { 8554 - desktopX -= appData.bumpScrollPixels; 8555 - if (desktopX < 0) 8556 - desktopX = 0; 8557 - } 8558 - } 8559 - 8560 - if (scrollDown) { 8561 - if (desktopY < si.framebufferHeight - dpyHeight) { 8562 - desktopY += appData.bumpScrollPixels; 8563 - if (desktopY > si.framebufferHeight - dpyHeight) 8564 - desktopY = si.framebufferHeight - dpyHeight; 8565 - } 8566 - } else if (scrollUp) { 8567 - if (desktopY > 0) { 8568 - desktopY -= appData.bumpScrollPixels; 8569 - if (desktopY < 0) 8570 - desktopY = 0; 8571 - } 8572 - } 8573 - 8574 - if (oldx != desktopX || oldy != desktopY) { 8575 - XawViewportSetCoordinates(viewport, desktopX, desktopY); 8576 - timer = XtAppAddTimeOut(appContext, appData.bumpScrollTime, 8577 - BumpScrollTimerCallback, NULL); 8578 - timerSet = True; 8579 - return True; 8580 - } 8581 + int oldx = desktopX, oldy = desktopY; 8582 + int fbW = si.framebufferWidth; 8583 + int fbH = si.framebufferHeight; 8584 + 8585 + if (scale_x > 0) { 8586 + fbW = scale_x; 8587 + fbH = scale_y; 8588 + } 8589 + 8590 + if (scrollRight) { 8591 + if (desktopX < fbW - dpyWidth) { 8592 + desktopX += appData.bumpScrollPixels; 8593 + if (desktopX > fbW - dpyWidth) { 8594 + desktopX = fbW - dpyWidth; 8595 + } 8596 + } 8597 + } else if (scrollLeft) { 8598 + if (desktopX > 0) { 8599 + desktopX -= appData.bumpScrollPixels; 8600 + if (desktopX < 0) { 8601 + desktopX = 0; 8602 + } 8603 + } 8604 + } 8605 + 8606 + if (scrollDown) { 8607 + int ycrop = appData.yCrop; 8608 + if (scale_y > 0) { 8609 + ycrop = scale_round(ycrop, scale_factor_y); 8610 + } 8611 + if (ycrop > 0 && desktopY + dpyHeight >= ycrop) { 8612 + ; 8613 + } else if (desktopY < fbH - dpyHeight) { 8614 + desktopY += appData.bumpScrollPixels; 8615 + if (desktopY > fbH - dpyHeight) { 8616 + desktopY = fbH - dpyHeight; 8617 + } 8618 + } 8619 + } else if (scrollUp) { 8620 + if (desktopY > 0) { 8621 + desktopY -= appData.bumpScrollPixels; 8622 + if (desktopY < 0) { 8623 + desktopY = 0; 8624 + } 8625 + } 8626 + } 8627 + 8628 + if (oldx != desktopX || oldy != desktopY) { 8629 + XawViewportSetCoordinates(viewport, desktopX, desktopY); 8630 + timer = XtAppAddTimeOut(appContext, appData.bumpScrollTime, BumpScrollTimerCallback, NULL); 8631 + timerSet = True; 8632 + return True; 8633 + } 8634 8635 - timerSet = False; 8636 - return False; 8637 + timerSet = False; 8638 + return False; 8639 } 8640 8641 static void 8642 BumpScrollTimerCallback(XtPointer clientData, XtIntervalId *id) 8643 { 8644 - DoBumpScroll(); 8645 + DoBumpScroll(); 8646 + if (clientData || id) {} 8647 +} 8648 + 8649 +/* not working: */ 8650 + 8651 +Bool 8652 +JumpScroll(int up, int vert) { 8653 + scrollLeft = scrollRight = scrollUp = scrollDown = False; 8654 + 8655 + 8656 + if (appData.fullScreen) { 8657 + return True; 8658 + } 8659 + fprintf(stderr, "JumpScroll(%d, %d)\n", up, vert); 8660 + 8661 + if (vert) { 8662 + if (up) { 8663 + scrollUp = True; 8664 + } else { 8665 + scrollDown = True; 8666 + } 8667 + } else { 8668 + if (up) { 8669 + scrollRight = True; 8670 + } else { 8671 + scrollLeft = True; 8672 + } 8673 + } 8674 + 8675 + if (scrollLeft || scrollRight || scrollUp || scrollDown) { 8676 + if (timerSet) { 8677 + return True; 8678 + } 8679 + 8680 + XtVaGetValues(desktop, XtNx, &desktopX, XtNy, &desktopY, NULL); 8681 + desktopX = -desktopX; 8682 + desktopY = -desktopY; 8683 + return DoJumpScroll(); 8684 + } 8685 + 8686 + if (timerSet) { 8687 + XtRemoveTimeOut(timer); 8688 + timerSet = False; 8689 + } 8690 + 8691 + return False; 8692 +} 8693 + 8694 +static Bool 8695 +DoJumpScroll() { 8696 + int oldx = desktopX, oldy = desktopY; 8697 + int jumpH, jumpV; 8698 + int fbW = si.framebufferWidth; 8699 + int fbH = si.framebufferHeight; 8700 + 8701 + if (scale_x > 0) { 8702 + fbW = scale_x; 8703 + fbH = scale_y; 8704 + } 8705 + jumpH = fbW / 4; 8706 + jumpV = fbH / 4; 8707 + 8708 + if (scrollRight) { 8709 + if (desktopX < fbW - dpyWidth) { 8710 + desktopX += jumpH; 8711 + if (desktopX > fbW - dpyWidth) 8712 + desktopX = fbW - dpyWidth; 8713 + } 8714 + } else if (scrollLeft) { 8715 + if (desktopX > 0) { 8716 + desktopX -= jumpH; 8717 + if (desktopX < 0) 8718 + desktopX = 0; 8719 + } 8720 + } 8721 + 8722 + if (scrollDown) { 8723 + if (appData.yCrop > 0 && desktopY + dpyHeight >= appData.yCrop) { 8724 + ; 8725 + } else if (desktopY < fbH - dpyHeight) { 8726 + desktopY += jumpV; 8727 + if (desktopY > fbH - dpyHeight) 8728 + desktopY = fbH - dpyHeight; 8729 + } 8730 + } else if (scrollUp) { 8731 + if (desktopY > 0) { 8732 + desktopY -= jumpV; 8733 + if (desktopY < 0) 8734 + desktopY = 0; 8735 + } 8736 + } 8737 + 8738 + if (oldx != desktopX || oldy != desktopY) { 8739 + XawViewportSetCoordinates(viewport, desktopX, desktopY); 8740 + timer = XtAppAddTimeOut(appContext, appData.bumpScrollTime, 8741 + JumpScrollTimerCallback, NULL); 8742 + timerSet = True; 8743 + return True; 8744 + } 8745 + 8746 + timerSet = False; 8747 + return False; 8748 +} 8749 + 8750 +static void 8751 +JumpScrollTimerCallback(XtPointer clientData, XtIntervalId *id) { 8752 + DoJumpScroll(); 8753 + if (clientData || id) {} 8754 +} 8755 +void JumpRight(Widget w, XEvent *ev, String *params, Cardinal *num_params) { 8756 + JumpScroll(1, 0); 8757 + if (w || ev || params || num_params) {} 8758 +} 8759 +void JumpLeft(Widget w, XEvent *ev, String *params, Cardinal *num_params) { 8760 + JumpScroll(0, 0); 8761 + if (w || ev || params || num_params) {} 8762 +} 8763 +void JumpUp(Widget w, XEvent *ev, String *params, Cardinal *num_params) { 8764 + JumpScroll(1, 1); 8765 + if (w || ev || params || num_params) {} 8766 } 8767 +void JumpDown(Widget w, XEvent *ev, String *params, Cardinal *num_params) { 8768 + JumpScroll(0, 1); 8769 + if (w || ev || params || num_params) {} 8770 +} 8771 + 8772 + 8773 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/h2html.pl vnc_unixsrc/vncviewer/h2html.pl 8774 --- vnc_unixsrc.orig/vncviewer/h2html.pl 1969-12-31 19:00:00.000000000 -0500 8775 +++ vnc_unixsrc/vncviewer/h2html.pl 2008-08-30 20:34:45.000000000 -0400 8776 @@ -0,0 +1,10 @@ 8777 +#!/usr/bin/perl 8778 + 8779 +open(HELP, "./vncviewer -help|"); 8780 + 8781 +while (<HELP>) { 8782 + $_ =~ s/&/&/g; 8783 + $_ =~ s/</</g; 8784 + $_ =~ s/>/>/g; 8785 + print; 8786 +} 8787 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/hextile.c vnc_unixsrc/vncviewer/hextile.c 8788 --- vnc_unixsrc.orig/vncviewer/hextile.c 2007-02-17 22:33:46.000000000 -0500 8789 +++ vnc_unixsrc/vncviewer/hextile.c 2009-10-16 22:54:40.000000000 -0400 8790 @@ -30,6 +30,21 @@ 8791 #define CARDBPP CONCAT2E(CARD,BPP) 8792 #define GET_PIXEL CONCAT2E(GET_PIXEL,BPP) 8793 8794 +#define FillRectangle(x, y, w, h, color) \ 8795 + { \ 8796 + XGCValues _gcv; \ 8797 + _gcv.foreground = color; \ 8798 + if (!appData.useXserverBackingStore) { \ 8799 + FillScreen(x, y, w, h, _gcv.foreground); \ 8800 + } else { \ 8801 + XChangeGC(dpy, gc, GCForeground, &_gcv); \ 8802 + XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \ 8803 + } \ 8804 + } 8805 + 8806 +extern int skip_maybe_sync; 8807 +extern void maybe_sync(int w, int h); 8808 + 8809 static Bool 8810 HandleHextileBPP (int rx, int ry, int rw, int rh) 8811 { 8812 @@ -41,21 +56,43 @@ 8813 int sx, sy, sw, sh; 8814 CARD8 subencoding; 8815 CARD8 nSubrects; 8816 + int irect = 0, nrects = (rw * rh) / (16 * 16); 8817 + static int nosync_ycrop = -1; 8818 + 8819 + if (nosync_ycrop < 0) { 8820 + nosync_ycrop = 0; 8821 + if (getenv("HEXTILE_YCROP_TOO")) { 8822 + nosync_ycrop = 1; 8823 + } 8824 + } 8825 8826 for (y = ry; y < ry+rh; y += 16) { 8827 for (x = rx; x < rx+rw; x += 16) { 8828 w = h = 16; 8829 - if (rx+rw - x < 16) 8830 + if (rx+rw - x < 16) { 8831 w = rx+rw - x; 8832 - if (ry+rh - y < 16) 8833 + } 8834 + if (ry+rh - y < 16) { 8835 h = ry+rh - y; 8836 + } 8837 + 8838 + if (nrects > 400 && (appData.yCrop == 0 || nosync_ycrop)) { 8839 + skip_maybe_sync = 0; 8840 + if (irect++ % 2000 != 0) { 8841 + if (x < rx+rw-16 || y < ry+rh-16) { 8842 + skip_maybe_sync = 1; 8843 + } 8844 + } 8845 + } 8846 8847 - if (!ReadFromRFBServer((char *)&subencoding, 1)) 8848 + if (!ReadFromRFBServer((char *)&subencoding, 1)) { 8849 return False; 8850 + } 8851 8852 if (subencoding & rfbHextileRaw) { 8853 - if (!ReadFromRFBServer(buffer, w * h * (BPP / 8))) 8854 + if (!ReadFromRFBServer(buffer, w * h * (BPP / 8))) { 8855 return False; 8856 + } 8857 8858 CopyDataToScreen(buffer, x, y, w, h); 8859 continue; 8860 @@ -66,14 +103,25 @@ 8861 return False; 8862 8863 #if (BPP == 8) 8864 - if (appData.useBGR233) 8865 + if (appData.useBGR233) { 8866 gcv.foreground = BGR233ToPixel[bg]; 8867 - else 8868 + } else 8869 +#endif 8870 +#if (BPP == 16) 8871 + if (appData.useBGR565) { 8872 + gcv.foreground = BGR565ToPixel[bg]; 8873 + } else 8874 #endif 8875 + { 8876 gcv.foreground = bg; 8877 + } 8878 8879 - XChangeGC(dpy, gc, GCForeground, &gcv); 8880 - XFillRectangle(dpy, desktopWin, gc, x, y, w, h); 8881 +#if 0 8882 + XChangeGC(dpy, gc, GCForeground, &gcv); 8883 + XFillRectangle(dpy, desktopWin, gc, x, y, w, h); 8884 +#else 8885 + FillRectangle(x, y, w, h, gcv.foreground); 8886 +#endif 8887 8888 if (subencoding & rfbHextileForegroundSpecified) 8889 if (!ReadFromRFBServer((char *)&fg, sizeof(fg))) 8890 @@ -101,14 +149,25 @@ 8891 sh = rfbHextileExtractH(*ptr); 8892 ptr++; 8893 #if (BPP == 8) 8894 - if (appData.useBGR233) 8895 + if (appData.useBGR233) { 8896 gcv.foreground = BGR233ToPixel[fg]; 8897 - else 8898 + } else 8899 #endif 8900 +#if (BPP == 16) 8901 + if (appData.useBGR565) { 8902 + gcv.foreground = BGR565ToPixel[fg]; 8903 + } else 8904 +#endif 8905 + { 8906 gcv.foreground = fg; 8907 + } 8908 8909 - XChangeGC(dpy, gc, GCForeground, &gcv); 8910 - XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh); 8911 +#if 0 8912 + XChangeGC(dpy, gc, GCForeground, &gcv); 8913 + XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh); 8914 +#else 8915 + FillRectangle(x+sx, y+sy, sw, sh, gcv.foreground); 8916 +#endif 8917 } 8918 8919 } else { 8920 @@ -116,13 +175,22 @@ 8921 return False; 8922 8923 #if (BPP == 8) 8924 - if (appData.useBGR233) 8925 + if (appData.useBGR233) { 8926 gcv.foreground = BGR233ToPixel[fg]; 8927 - else 8928 + } else 8929 #endif 8930 +#if (BPP == 16) 8931 + if (appData.useBGR565) { 8932 + gcv.foreground = BGR565ToPixel[fg]; 8933 + } else 8934 +#endif 8935 + { 8936 gcv.foreground = fg; 8937 + } 8938 8939 +#if 0 8940 XChangeGC(dpy, gc, GCForeground, &gcv); 8941 +#endif 8942 8943 for (i = 0; i < nSubrects; i++) { 8944 sx = rfbHextileExtractX(*ptr); 8945 @@ -131,7 +199,11 @@ 8946 sw = rfbHextileExtractW(*ptr); 8947 sh = rfbHextileExtractH(*ptr); 8948 ptr++; 8949 +#if 0 8950 XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh); 8951 +#else 8952 + FillRectangle(x+sx, y+sy, sw, sh, gcv.foreground); 8953 +#endif 8954 } 8955 } 8956 } 8957 @@ -139,3 +211,5 @@ 8958 8959 return True; 8960 } 8961 + 8962 +#undef FillRectangle 8963 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/listen.c vnc_unixsrc/vncviewer/listen.c 8964 --- vnc_unixsrc.orig/vncviewer/listen.c 2001-01-16 03:07:57.000000000 -0500 8965 +++ vnc_unixsrc/vncviewer/listen.c 2010-04-11 23:14:21.000000000 -0400 8966 @@ -32,14 +32,88 @@ 8967 #define FLASHDELAY 1 /* seconds */ 8968 8969 Bool listenSpecified = False; 8970 +pid_t listenParent = 0; 8971 int listenPort = 0, flashPort = 0; 8972 8973 +#if 0 8974 static Font flashFont; 8975 - 8976 static void getFlashFont(Display *d); 8977 static void flashDisplay(Display *d, char *user); 8978 +#endif 8979 + 8980 static Bool AllXEventsPredicate(Display *d, XEvent *ev, char *arg); 8981 8982 +void raiseme(int force); 8983 + 8984 +static int accept_popup_check(int *argc, char **argv, char *sip, char *sih) { 8985 + char line[16]; 8986 + char msg[1000]; 8987 + int dopopup = 1; 8988 + 8989 + if (!getenv("SSVNC_ACCEPT_POPUP")) { 8990 + return 1; 8991 + } 8992 + 8993 + if (!dopopup && use_tty()) { 8994 + raiseme(1); 8995 + fprintf(stderr, "Accept VNC connection? y/[n] "); 8996 + fgets(line, sizeof(line), stdin); 8997 + if (!strchr(line, 'y') && !strchr(line, 'Y')) { 8998 + fprintf(stderr, "Refusing connection.\n"); 8999 + return 0; 9000 + } else { 9001 + fprintf(stderr, "Accepting connection.\n"); 9002 + return 1; 9003 + } 9004 + } else { 9005 + int pid, pid2, accept_it = 0; 9006 + 9007 + pid = fork(); 9008 + if (pid == -1) { 9009 + perror("fork"); 9010 + exit(1); 9011 + } 9012 + if (pid == 0) { 9013 + char *geometry = "2x2+0+0"; 9014 + String fb[] = { "*message.Scroll: whenNeeded", NULL}; 9015 + close(rfbsock); 9016 + 9017 + toplevel = XtAppInitialize(&appContext, "Ssvnc", cmdLineOptions, numCmdLineOptions, 9018 + argc, argv, fb, NULL, 0); 9019 + XtVaSetValues(toplevel, XtNmaxWidth, 2, XtNmaxHeight, 2, NULL); 9020 + XtVaSetValues(toplevel, XtNgeometry, geometry, NULL); 9021 + XtRealizeWidget(toplevel); 9022 + dpy = XtDisplay(toplevel); 9023 + sprintf(msg, "\n(LISTEN) Reverse VNC connection from IP: %s\n Hostname: %s\n\n", sip, sih); 9024 + strcat(msg, "Accept or Reject VNC connection?"); 9025 + if (CreateMsg(msg, 2)) { 9026 + XCloseDisplay(dpy); 9027 + exit(0); 9028 + } else { 9029 + XCloseDisplay(dpy); 9030 + exit(1); 9031 + } 9032 + } else { 9033 + int status; 9034 + pid2 = waitpid(pid, &status, 0); 9035 + fprintf(stderr, "waitpid: %d/%d status: %d\n", pid, pid2, status); 9036 + if (pid2 == pid) { 9037 + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 9038 + accept_it = 1; 9039 + } 9040 + } 9041 + } 9042 + if (accept_it) { 9043 + fprintf(stderr, "Accepting connection.\n"); 9044 + return 1; 9045 + } else { 9046 + fprintf(stderr, "Refusing connection.\n"); 9047 + return 0; 9048 + } 9049 + } 9050 + return 0; 9051 +} 9052 + 9053 /* 9054 * listenForIncomingConnections() - listen for incoming connections from 9055 * servers, and fork a new process to deal with each connection. We must do 9056 @@ -47,145 +121,291 @@ 9057 * cope with forking very well. 9058 */ 9059 9060 +extern char *accept6_hostname; 9061 +extern char *accept6_ipaddr; 9062 + 9063 void 9064 listenForIncomingConnections(int *argc, char **argv, int listenArgIndex) 9065 { 9066 - Display *d; 9067 - XEvent ev; 9068 - int listenSocket, flashSocket, sock; 9069 - fd_set fds; 9070 - char flashUser[256]; 9071 - int n; 9072 - int i; 9073 - char *displayname = NULL; 9074 - 9075 - listenSpecified = True; 9076 - 9077 - for (i = 1; i < *argc; i++) { 9078 - if (strcmp(argv[i], "-display") == 0 && i+1 < *argc) { 9079 - displayname = argv[i+1]; 9080 - } 9081 - } 9082 + Display *d; 9083 + XEvent ev; 9084 + int listenSocket, listenSocket6, flashSocket, sock; 9085 + fd_set fds; 9086 + char flashUser[256]; 9087 + int n; 9088 + int i; 9089 + char *displayname = NULL; 9090 + int children = 0; 9091 + int totalconn = 0, maxconn = 0; 9092 + 9093 + listenSpecified = True; 9094 + listenParent = getpid(); 9095 + 9096 + for (i = 1; i < *argc; i++) { 9097 + if (strcmp(argv[i], "-display") == 0 && i+1 < *argc) { 9098 + displayname = argv[i+1]; 9099 + } 9100 + } 9101 + if (sock || flashUser || n) {} 9102 9103 - if (listenArgIndex+1 < *argc && argv[listenArgIndex+1][0] >= '0' && 9104 + if (listenArgIndex+1 < *argc && argv[listenArgIndex+1][0] >= '0' && 9105 argv[listenArgIndex+1][0] <= '9') { 9106 9107 - listenPort = LISTEN_PORT_OFFSET + atoi(argv[listenArgIndex+1]); 9108 - flashPort = FLASH_PORT_OFFSET + atoi(argv[listenArgIndex+1]); 9109 - removeArgs(argc, argv, listenArgIndex, 2); 9110 + listenPort = LISTEN_PORT_OFFSET + atoi(argv[listenArgIndex+1]); 9111 + flashPort = FLASH_PORT_OFFSET + atoi(argv[listenArgIndex+1]); 9112 + removeArgs(argc, argv, listenArgIndex, 2); 9113 9114 - } else { 9115 + } else { 9116 9117 - char *display; 9118 - char *colonPos; 9119 - struct utsname hostinfo; 9120 + char *display; 9121 + char *colonPos; 9122 + struct utsname hostinfo; 9123 9124 - removeArgs(argc, argv, listenArgIndex, 1); 9125 + removeArgs(argc, argv, listenArgIndex, 1); 9126 9127 - display = XDisplayName(displayname); 9128 - colonPos = strchr(display, ':'); 9129 + display = XDisplayName(displayname); 9130 + colonPos = strchr(display, ':'); 9131 9132 - uname(&hostinfo); 9133 + uname(&hostinfo); 9134 9135 - if (colonPos && ((colonPos == display) || 9136 - (strncmp(hostinfo.nodename, display, 9137 - strlen(hostinfo.nodename)) == 0))) { 9138 + if (colonPos && ((colonPos == display) || 9139 + (strncmp(hostinfo.nodename, display, 9140 + strlen(hostinfo.nodename)) == 0))) { 9141 9142 - listenPort = LISTEN_PORT_OFFSET + atoi(colonPos+1); 9143 - flashPort = FLASH_PORT_OFFSET + atoi(colonPos+1); 9144 + listenPort = LISTEN_PORT_OFFSET + atoi(colonPos+1); 9145 + flashPort = FLASH_PORT_OFFSET + atoi(colonPos+1); 9146 9147 - } else { 9148 - fprintf(stderr,"%s: cannot work out which display number to " 9149 - "listen on.\n", programName); 9150 - fprintf(stderr,"Please specify explicitly with -listen <num>\n"); 9151 - exit(1); 9152 - } 9153 - } 9154 + } else { 9155 + fprintf(stderr,"%s: cannot work out which display number to " 9156 + "listen on.\n", programName); 9157 + fprintf(stderr,"Please specify explicitly with -listen <num>\n"); 9158 + exit(1); 9159 + } 9160 9161 - if (!(d = XOpenDisplay(displayname))) { 9162 - fprintf(stderr,"%s: unable to open display %s\n", 9163 - programName, XDisplayName(displayname)); 9164 - exit(1); 9165 - } 9166 + } 9167 9168 - getFlashFont(d); 9169 + if (!(d = XOpenDisplay(displayname))) { 9170 + fprintf(stderr,"%s: unable to open display %s\n", 9171 + programName, XDisplayName(displayname)); 9172 + exit(1); 9173 + } 9174 9175 - listenSocket = ListenAtTcpPort(listenPort); 9176 - flashSocket = ListenAtTcpPort(flashPort); 9177 +#if 0 9178 + getFlashFont(d); 9179 +#endif 9180 9181 - if ((listenSocket < 0) || (flashSocket < 0)) exit(1); 9182 + listenSocket = ListenAtTcpPort(listenPort); 9183 + listenSocket6 = ListenAtTcpPort6(listenPort); 9184 + 9185 +#if 0 9186 + flashSocket = ListenAtTcpPort(flashPort); 9187 +#endif 9188 + flashSocket = 1234; 9189 + 9190 + if (listenSocket < 0 && listenSocket6 < 0) { 9191 + fprintf(stderr,"%s -listen: could not obtain a listening socket on port %d\n", 9192 + programName, listenPort); 9193 + exit(1); 9194 + } 9195 9196 - fprintf(stderr,"%s -listen: Listening on port %d (flash port %d)\n", 9197 - programName,listenPort,flashPort); 9198 - fprintf(stderr,"%s -listen: Command line errors are not reported until " 9199 + fprintf(stderr,"%s -listen: Listening on port %d ipv4_fd: %d ipv6_fd: %d\n", 9200 + programName, listenPort, listenSocket, listenSocket6); 9201 + fprintf(stderr,"%s -listen: Cmdline errors are not reported until " 9202 "a connection comes in.\n", programName); 9203 9204 - while (True) { 9205 + /* this will only work if X events drives this loop -- they don't */ 9206 + if (getenv("SSVNC_MAX_LISTEN")) { 9207 + maxconn = atoi(getenv("SSVNC_MAX_LISTEN")); 9208 + } 9209 9210 - /* reap any zombies */ 9211 - int status, pid; 9212 - while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0); 9213 - 9214 - /* discard any X events */ 9215 - while (XCheckIfEvent(d, &ev, AllXEventsPredicate, NULL)) 9216 - ; 9217 - 9218 - FD_ZERO(&fds); 9219 - 9220 - FD_SET(flashSocket, &fds); 9221 - FD_SET(listenSocket, &fds); 9222 - FD_SET(ConnectionNumber(d), &fds); 9223 - 9224 - select(FD_SETSIZE, &fds, NULL, NULL, NULL); 9225 - 9226 - if (FD_ISSET(flashSocket, &fds)) { 9227 - 9228 - sock = AcceptTcpConnection(flashSocket); 9229 - if (sock < 0) exit(1); 9230 - n = read(sock, flashUser, 255); 9231 - if (n > 0) { 9232 - flashUser[n] = 0; 9233 - flashDisplay(d, flashUser); 9234 - } else { 9235 - flashDisplay(d, NULL); 9236 - } 9237 - close(sock); 9238 - } 9239 + while (True) { 9240 + int lsock = -1; 9241 9242 - if (FD_ISSET(listenSocket, &fds)) { 9243 - rfbsock = AcceptTcpConnection(listenSocket); 9244 - if (rfbsock < 0) exit(1); 9245 - if (!SetNonBlocking(rfbsock)) exit(1); 9246 + /* reap any zombies */ 9247 + int status, pid; 9248 + while ((pid = wait3(&status, WNOHANG, (struct rusage *)0))>0) { 9249 + if (pid > 0 && children > 0) { 9250 + children--; 9251 + /* this will only work if X events drives this loop -- they don't */ 9252 + if (maxconn > 0 && totalconn >= maxconn) { 9253 + fprintf(stderr,"%s -listen: Finished final connection %d\n", 9254 + programName, maxconn); 9255 + exit(0); 9256 + } 9257 + } 9258 + } 9259 9260 - XCloseDisplay(d); 9261 + /* discard any X events */ 9262 + while (XCheckIfEvent(d, &ev, AllXEventsPredicate, NULL)) { 9263 + ; 9264 + } 9265 9266 - /* Now fork off a new process to deal with it... */ 9267 + FD_ZERO(&fds); 9268 9269 - switch (fork()) { 9270 +#if 0 9271 + FD_SET(flashSocket, &fds); 9272 +#endif 9273 + if (listenSocket >= 0) { 9274 + FD_SET(listenSocket, &fds); 9275 + } 9276 + if (listenSocket6 >= 0) { 9277 + FD_SET(listenSocket6, &fds); 9278 + } 9279 + FD_SET(ConnectionNumber(d), &fds); 9280 9281 - case -1: 9282 - perror("fork"); 9283 - exit(1); 9284 + select(FD_SETSIZE, &fds, NULL, NULL, NULL); 9285 9286 - case 0: 9287 - /* child - return to caller */ 9288 - close(listenSocket); 9289 - close(flashSocket); 9290 - return; 9291 + while ((pid = wait3(&status, WNOHANG, (struct rusage *)0))>0) { 9292 + if (pid > 0 && children > 0) { 9293 + children--; 9294 + if (maxconn > 0 && totalconn >= maxconn) { 9295 + fprintf(stderr,"%s -listen: Finished final connection %d\n", 9296 + programName, maxconn); 9297 + exit(0); 9298 + } 9299 + } 9300 + } 9301 9302 - default: 9303 - /* parent - go round and listen again */ 9304 - close(rfbsock); 9305 - if (!(d = XOpenDisplay(displayname))) { 9306 - fprintf(stderr,"%s: unable to open display %s\n", 9307 - programName, XDisplayName(displayname)); 9308 - exit(1); 9309 +#if 0 9310 + if (FD_ISSET(flashSocket, &fds)) { 9311 + sock = AcceptTcpConnection(flashSocket); 9312 + if (sock < 0) exit(1); 9313 + n = read(sock, flashUser, 255); 9314 + if (n > 0) { 9315 + flashUser[n] = 0; 9316 + flashDisplay(d, flashUser); 9317 + } else { 9318 + flashDisplay(d, NULL); 9319 + } 9320 + close(sock); 9321 + } 9322 +#endif 9323 + 9324 + lsock = -1; 9325 + if (listenSocket >= 0 && FD_ISSET(listenSocket, &fds)) { 9326 + lsock = listenSocket; 9327 + } else if (listenSocket6 >= 0 && FD_ISSET(listenSocket6, &fds)) { 9328 + lsock = listenSocket6; 9329 + } 9330 + 9331 + if (lsock >= 0) { 9332 + int multi_ok = 0; 9333 + char *sml = getenv("SSVNC_MULTIPLE_LISTEN"); 9334 + char *sip = NULL; 9335 + char *sih = NULL; 9336 + 9337 + if (lsock == listenSocket) { 9338 + rfbsock = AcceptTcpConnection(lsock); 9339 + } else { 9340 + rfbsock = AcceptTcpConnection6(lsock); 9341 + } 9342 + 9343 + if (sml != NULL) { 9344 + if (strstr(sml, "MAX:") == sml || strstr(sml, "max:") == sml) { 9345 + char *q = strchr(sml, ':'); 9346 + int maxc = atoi(q+1); 9347 + if (maxc == 0 && strcmp(q+1, "0")) { 9348 + maxc = -99; 9349 + } 9350 + if (maxc < 0) { 9351 + fprintf(stderr, "invalid SSVNC_MULTIPLE_LISTEN=MAX:n, %s, must be 0 or positive, using 1\n", sml); 9352 + } else if (maxc == 0) { 9353 + multi_ok = 1; 9354 + } else if (children < maxc) { 9355 + multi_ok = 1; 9356 + } 9357 + } else if (strcmp(sml, "") && strcmp(sml, "0")) { 9358 + multi_ok = 1; 9359 + } 9360 + } 9361 + 9362 + if (rfbsock < 0) exit(1); 9363 + if (!SetNonBlocking(rfbsock)) exit(1); 9364 + 9365 + if (children > 0 && !multi_ok) { 9366 + fprintf(stderr,"\n"); 9367 + fprintf(stderr,"%s: denying extra incoming connection (%d already)\n", 9368 + programName, children); 9369 + fprintf(stderr,"%s: to override: use '-multilisten' or set SSVNC_MULTIPLE_LISTEN=1\n", 9370 + programName); 9371 + fprintf(stderr,"\n"); 9372 + close(rfbsock); 9373 + rfbsock = -1; 9374 + continue; 9375 + } 9376 + 9377 + if (lsock == listenSocket) { 9378 + sip = get_peer_ip(rfbsock); 9379 + if (strlen(sip) > 100) sip = "0.0.0.0"; 9380 + sih = ip2host(sip); 9381 + if (strlen(sih) > 300) sih = "unknown"; 9382 + } else { 9383 + if (accept6_hostname != NULL) { 9384 + sip = accept6_ipaddr; 9385 + accept6_ipaddr = NULL; 9386 + sih = accept6_hostname; 9387 + accept6_hostname = NULL; 9388 + } else { 9389 + sip = "unknown"; 9390 + sih = "unknown"; 9391 + } 9392 + } 9393 + 9394 + fprintf(stderr, "\n"); 9395 + fprintf(stderr, "(LISTEN) Reverse VNC connection from IP: %s\n", sip); 9396 + fprintf(stderr, " Hostname: %s\n\n", sih); 9397 + 9398 + if (sml == NULL && !accept_popup_check(argc, argv, sip, sih)) { 9399 + close(rfbsock); 9400 + rfbsock = -1; 9401 + continue; 9402 + } 9403 + 9404 + totalconn++; 9405 + 9406 + XCloseDisplay(d); 9407 + 9408 + /* Now fork off a new process to deal with it... */ 9409 + 9410 + switch (fork()) { 9411 + 9412 + case -1: 9413 + perror("fork"); 9414 + exit(1); 9415 + 9416 + case 0: 9417 + /* child - return to caller */ 9418 + close(listenSocket); 9419 +#if 0 9420 + close(flashSocket); 9421 +#endif 9422 + if (sml != NULL && !accept_popup_check(argc, argv, sip, sih)) { 9423 + close(rfbsock); 9424 + rfbsock = -1; 9425 + exit(0); 9426 + } 9427 + return; 9428 + 9429 + default: 9430 + /* parent - go round and listen again */ 9431 + children++; 9432 + close(rfbsock); 9433 + if (!(d = XOpenDisplay(displayname))) { 9434 + fprintf(stderr,"%s: unable to open display %s\n", 9435 + programName, XDisplayName(displayname)); 9436 + exit(1); 9437 + } 9438 +#if 0 9439 + getFlashFont(d); 9440 +#endif 9441 + fprintf(stderr,"\n\n%s -listen: Listening on port %d\n", 9442 + programName,listenPort); 9443 + fprintf(stderr,"%s -listen: Cmdline errors are not reported until " 9444 + "a connection comes in.\n\n", programName); 9445 + break; 9446 + } 9447 } 9448 - getFlashFont(d); 9449 - break; 9450 - } 9451 } 9452 - } 9453 } 9454 9455 9456 @@ -193,9 +413,16 @@ 9457 * getFlashFont 9458 */ 9459 9460 +#if 0 9461 static void 9462 getFlashFont(Display *d) 9463 { 9464 + 9465 +#if 1 9466 + /* no longer used */ 9467 + if (d) {} 9468 + return; 9469 +#else 9470 char fontName[256]; 9471 char **fontNames; 9472 int nFontNames; 9473 @@ -209,6 +436,9 @@ 9474 sprintf(fontName,"fixed"); 9475 } 9476 flashFont = XLoadFont(d, fontName); 9477 + 9478 +#endif 9479 + 9480 } 9481 9482 9483 @@ -219,6 +449,11 @@ 9484 static void 9485 flashDisplay(Display *d, char *user) 9486 { 9487 +#if 1 9488 + /* no longer used */ 9489 + if (d || user) {} 9490 + return; 9491 +#else 9492 Window w1, w2, w3, w4; 9493 XSetWindowAttributes attr; 9494 9495 @@ -284,7 +519,11 @@ 9496 XDestroyWindow(d, w3); 9497 XDestroyWindow(d, w4); 9498 XFlush(d); 9499 + 9500 +#endif 9501 + 9502 } 9503 +#endif 9504 9505 /* 9506 * AllXEventsPredicate is needed to make XCheckIfEvent return all events. 9507 @@ -293,5 +532,6 @@ 9508 static Bool 9509 AllXEventsPredicate(Display *d, XEvent *ev, char *arg) 9510 { 9511 - return True; 9512 + if (d || ev || arg) {} 9513 + return True; 9514 } 9515 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/misc.c vnc_unixsrc/vncviewer/misc.c 9516 --- vnc_unixsrc.orig/vncviewer/misc.c 2003-01-15 02:58:32.000000000 -0500 9517 +++ vnc_unixsrc/vncviewer/misc.c 2010-02-25 22:44:09.000000000 -0500 9518 @@ -23,6 +23,7 @@ 9519 9520 #include <vncviewer.h> 9521 #include <signal.h> 9522 +#include <sys/wait.h> 9523 #include <fcntl.h> 9524 9525 static void CleanupSignalHandler(int sig); 9526 @@ -33,12 +34,20 @@ 9527 9528 Dimension dpyWidth, dpyHeight; 9529 Atom wmDeleteWindow, wmState; 9530 +int fullscreen_startup = 0; 9531 9532 static Bool xloginIconified = False; 9533 static XErrorHandler defaultXErrorHandler; 9534 static XIOErrorHandler defaultXIOErrorHandler; 9535 static XtErrorHandler defaultXtErrorHandler; 9536 9537 +int XError_ign = 0; 9538 + 9539 +void check_tall(void); 9540 +int guessCrop(void); 9541 +void get_scale_values(double *fx, double *fy); 9542 +int scale_round(int n, double factor); 9543 +Bool SendTextChatFinished(void); 9544 9545 /* 9546 * ToplevelInitBeforeRealization sets the title, geometry and other resources 9547 @@ -48,87 +57,122 @@ 9548 void 9549 ToplevelInitBeforeRealization() 9550 { 9551 - char *titleFormat; 9552 - char *title; 9553 - char *geometry; 9554 - 9555 - XtVaGetValues(toplevel, XtNtitle, &titleFormat, NULL); 9556 - title = XtMalloc(strlen(titleFormat) + strlen(desktopName) + 1); 9557 - sprintf(title, titleFormat, desktopName); 9558 - XtVaSetValues(toplevel, XtNtitle, title, XtNiconName, title, NULL); 9559 - 9560 - XtVaSetValues(toplevel, XtNmaxWidth, si.framebufferWidth, 9561 - XtNmaxHeight, si.framebufferHeight, NULL); 9562 - 9563 - dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy)); 9564 - dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy)); 9565 - 9566 - if (appData.fullScreen) { 9567 - 9568 - /* full screen - set position to 0,0, but defer size calculation until 9569 - widgets are realized */ 9570 - 9571 - XtVaSetValues(toplevel, XtNoverrideRedirect, True, 9572 - XtNgeometry, "+0+0", NULL); 9573 - 9574 - } else { 9575 - 9576 - /* not full screen - work out geometry for middle of screen unless 9577 - specified by user */ 9578 - 9579 - XtVaGetValues(toplevel, XtNgeometry, &geometry, NULL); 9580 - 9581 - if (geometry == NULL) { 9582 - Dimension toplevelX, toplevelY; 9583 - Dimension toplevelWidth = si.framebufferWidth; 9584 - Dimension toplevelHeight = si.framebufferHeight; 9585 - 9586 - if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth) 9587 - toplevelWidth = dpyWidth - appData.wmDecorationWidth; 9588 - 9589 - if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight) 9590 - toplevelHeight = dpyHeight - appData.wmDecorationHeight; 9591 - 9592 - toplevelX = (dpyWidth - toplevelWidth - appData.wmDecorationWidth) / 2; 9593 - 9594 - toplevelY = (dpyHeight - toplevelHeight - appData.wmDecorationHeight) /2; 9595 - 9596 - /* set position via "geometry" so that window manager thinks it's a 9597 - user-specified position and therefore honours it */ 9598 - 9599 - geometry = XtMalloc(256); 9600 - 9601 - sprintf(geometry, "%dx%d+%d+%d", 9602 - toplevelWidth, toplevelHeight, toplevelX, toplevelY); 9603 - XtVaSetValues(toplevel, XtNgeometry, geometry, NULL); 9604 - } 9605 - } 9606 + char *titleFormat; 9607 + char *title; 9608 + char *geometry; 9609 + int h = si.framebufferHeight; 9610 + int w = si.framebufferWidth; 9611 + 9612 + check_tall(); 9613 + if (appData.yCrop < 0) { 9614 + appData.yCrop = guessCrop(); 9615 + fprintf(stderr, "Set -ycrop to: %d\n", appData.yCrop); 9616 + if (appData.yCrop > 0) { 9617 + h = appData.yCrop; 9618 + } 9619 + } 9620 + 9621 + XtVaGetValues(toplevel, XtNtitle, &titleFormat, NULL); 9622 + title = XtMalloc(strlen(titleFormat) + strlen(desktopName) + 1); 9623 + sprintf(title, titleFormat, desktopName); 9624 + XtVaSetValues(toplevel, XtNtitle, title, XtNiconName, title, NULL); 9625 + 9626 + if (appData.scale != NULL) { 9627 + /* switched to not scaled */ 9628 + double frac_x, frac_y; 9629 + get_scale_values(&frac_x, &frac_y); 9630 + if (frac_x > 0.0 && frac_y > 0.0) { 9631 + w = scale_round(w, frac_x); 9632 + h = scale_round(h, frac_y); 9633 + } 9634 + } 9635 + XtVaSetValues(toplevel, XtNmaxWidth, w, XtNmaxHeight, h, NULL); 9636 + 9637 + dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy)); 9638 + dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy)); 9639 + 9640 + if (appData.fullScreen) { 9641 + /* full screen - set position to 0,0, but defer size calculation until widgets are realized */ 9642 + 9643 + if (!net_wm_supported()) { 9644 + XtVaSetValues(toplevel, XtNoverrideRedirect, True, XtNgeometry, "+0+0", NULL); 9645 + } else { 9646 + fullscreen_startup = 1; 9647 + } 9648 + 9649 + } else { 9650 + 9651 + /* not full screen - work out geometry for middle of screen unless specified by user */ 9652 + 9653 + XtVaGetValues(toplevel, XtNgeometry, &geometry, NULL); 9654 + 9655 + if (geometry == NULL) { 9656 + Dimension toplevelX, toplevelY; 9657 + Dimension toplevelWidth = w; 9658 + Dimension toplevelHeight = h; 9659 + 9660 + if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth) { 9661 + toplevelWidth = dpyWidth - appData.wmDecorationWidth; 9662 + } 9663 + 9664 + if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight) { 9665 + toplevelHeight = dpyHeight - appData.wmDecorationHeight; 9666 + } 9667 + 9668 + toplevelX = (dpyWidth - toplevelWidth - appData.wmDecorationWidth) / 2; 9669 + toplevelY = (dpyHeight - toplevelHeight - appData.wmDecorationHeight) /2; 9670 + 9671 + if (appData.appShare) { 9672 + int X = appshare_x_hint; 9673 + int Y = appshare_y_hint; 9674 + if (appData.scale) { 9675 + double fx = 1.0, fy = 1.0; 9676 + get_scale_values(&fx, &fy); 9677 + if (fx > 0.0 && fy > 0.0) { 9678 + X *= fx; 9679 + Y *= fy; 9680 + } 9681 + } 9682 + if (appshare_x_hint != appshare_0_hint) { 9683 + toplevelX = X; 9684 + } 9685 + if (appshare_y_hint != appshare_0_hint) { 9686 + toplevelY = Y; 9687 + } 9688 + } 9689 + 9690 + /* set position via "geometry" so that window manager thinks it's a 9691 + user-specified position and therefore honours it */ 9692 + 9693 + geometry = XtMalloc(256); 9694 + 9695 + sprintf(geometry, "%dx%d+%d+%d", toplevelWidth, toplevelHeight, toplevelX, toplevelY); 9696 + fprintf(stderr, "geometry: %s ycrop: %d\n", geometry, appData.yCrop); 9697 + XtVaSetValues(toplevel, XtNgeometry, geometry, NULL); 9698 + } 9699 + } 9700 9701 /* Test if the keyboard is grabbed. If so, it's probably because the 9702 XDM login window is up, so try iconifying it to release the grab */ 9703 9704 - if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), False, GrabModeSync, 9705 - GrabModeSync, CurrentTime) == GrabSuccess) { 9706 - XUngrabKeyboard(dpy, CurrentTime); 9707 - } else { 9708 - wmState = XInternAtom(dpy, "WM_STATE", False); 9709 - 9710 - if (IconifyNamedWindow(DefaultRootWindow(dpy), "xlogin", False)) { 9711 - xloginIconified = True; 9712 - XSync(dpy, False); 9713 - sleep(1); 9714 - } 9715 - } 9716 - 9717 - /* Set handlers for signals and X errors to perform cleanup */ 9718 - 9719 - signal(SIGHUP, CleanupSignalHandler); 9720 - signal(SIGINT, CleanupSignalHandler); 9721 - signal(SIGTERM, CleanupSignalHandler); 9722 - defaultXErrorHandler = XSetErrorHandler(CleanupXErrorHandler); 9723 - defaultXIOErrorHandler = XSetIOErrorHandler(CleanupXIOErrorHandler); 9724 - defaultXtErrorHandler = XtAppSetErrorHandler(appContext, 9725 - CleanupXtErrorHandler); 9726 + if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), False, GrabModeSync, GrabModeSync, CurrentTime) == GrabSuccess) { 9727 + XUngrabKeyboard(dpy, CurrentTime); 9728 + } else { 9729 + wmState = XInternAtom(dpy, "WM_STATE", False); 9730 + if (IconifyNamedWindow(DefaultRootWindow(dpy), "xlogin", False)) { 9731 + xloginIconified = True; 9732 + XSync(dpy, False); 9733 + sleep(1); 9734 + } 9735 + } 9736 + 9737 + /* Set handlers for signals and X errors to perform cleanup */ 9738 + signal(SIGHUP, CleanupSignalHandler); 9739 + signal(SIGINT, CleanupSignalHandler); 9740 + signal(SIGTERM, CleanupSignalHandler); 9741 + defaultXErrorHandler = XSetErrorHandler(CleanupXErrorHandler); 9742 + defaultXIOErrorHandler = XSetIOErrorHandler(CleanupXIOErrorHandler); 9743 + defaultXtErrorHandler = XtAppSetErrorHandler(appContext, CleanupXtErrorHandler); 9744 } 9745 9746 9747 @@ -141,14 +185,22 @@ 9748 void 9749 ToplevelInitAfterRealization() 9750 { 9751 - if (appData.fullScreen) { 9752 - FullScreenOn(); 9753 - } 9754 - 9755 - wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 9756 - XSetWMProtocols(dpy, XtWindow(toplevel), &wmDeleteWindow, 1); 9757 - XtOverrideTranslations 9758 - (toplevel, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()")); 9759 + if (appData.fullScreen) { 9760 + FullScreenOn(); 9761 + if (net_wm_supported()) { 9762 + /* problem with scroll bars sticking: */ 9763 + XSync(dpy, False); 9764 + usleep(50 * 1000); 9765 + FullScreenOff(); 9766 + XSync(dpy, False); 9767 + usleep(50 * 1000); 9768 + FullScreenOn(); 9769 + } 9770 + } 9771 + 9772 + wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 9773 + XSetWMProtocols(dpy, XtWindow(toplevel), &wmDeleteWindow, 1); 9774 + XtOverrideTranslations(toplevel, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()")); 9775 } 9776 9777 9778 @@ -157,9 +209,7 @@ 9779 * CurrentTime if the event has no time field. 9780 */ 9781 9782 -Time 9783 -TimeFromEvent(XEvent *ev) 9784 -{ 9785 +Time TimeFromEvent(XEvent *ev) { 9786 switch (ev->type) { 9787 case KeyPress: 9788 case KeyRelease: 9789 @@ -192,18 +242,16 @@ 9790 * generated by SendRFBEvent. 9791 */ 9792 9793 -void 9794 -Pause(Widget w, XEvent *event, String *params, Cardinal *num_params) 9795 -{ 9796 - int msec; 9797 +void Pause(Widget w, XEvent *event, String *params, Cardinal *num_params) { 9798 + int msec; 9799 9800 - if (*num_params == 0) { 9801 - msec = 100; 9802 - } else { 9803 - msec = atoi(params[0]); 9804 - } 9805 - 9806 - usleep(msec * 1000); 9807 + if (*num_params == 0) { 9808 + msec = 100; 9809 + } else { 9810 + msec = atoi(params[0]); 9811 + } 9812 + usleep(msec * 1000); 9813 + if (w || event || params || num_params) {} 9814 } 9815 9816 9817 @@ -256,6 +304,7 @@ 9818 /* Wait for Child 1 to die */ 9819 wait(&childstatus); 9820 9821 + if (w || event || params || num_params) {} 9822 return; 9823 } 9824 9825 @@ -264,11 +313,10 @@ 9826 * Quit action - called when we get a "delete window" message. 9827 */ 9828 9829 -void 9830 -Quit(Widget w, XEvent *event, String *params, Cardinal *num_params) 9831 -{ 9832 - Cleanup(); 9833 - exit(0); 9834 +void Quit(Widget w, XEvent *event, String *params, Cardinal *num_params) { 9835 + Cleanup(); 9836 + if (w || event || params || num_params) {} 9837 + exit(0); 9838 } 9839 9840 9841 @@ -276,49 +324,94 @@ 9842 * Cleanup - perform any cleanup operations prior to exiting. 9843 */ 9844 9845 -void 9846 -Cleanup() 9847 -{ 9848 - if (xloginIconified) { 9849 - IconifyNamedWindow(DefaultRootWindow(dpy), "xlogin", True); 9850 - XFlush(dpy); 9851 - } 9852 +void Cleanup() { 9853 + 9854 + if (appData.chatActive) { 9855 + appData.chatActive = False; 9856 + fprintf(stderr,"Sending SendTextChatClose()\n"); 9857 + SendTextChatClose(); 9858 + SendTextChatFinished(); 9859 + } 9860 + 9861 + if (xloginIconified) { 9862 + IconifyNamedWindow(DefaultRootWindow(dpy), "xlogin", True); 9863 + XFlush(dpy); 9864 + } 9865 #ifdef MITSHM 9866 - if (appData.useShm) 9867 - ShmCleanup(); 9868 + if (appData.useShm) { 9869 + if (UsingShm()) { 9870 + ShmDetach(); 9871 + } 9872 + ShmCleanup(); 9873 + } 9874 #endif 9875 + 9876 + releaseAllPressedModifiers(); 9877 + 9878 + fprintf(stderr,"\nVNC Viewer exiting.\n\n"); 9879 + if (listenSpecified) { 9880 + if (listenParent != 0 && getenv("SSVNC_LISTEN_ONCE") && listenParent != getpid()) { 9881 + fprintf(stderr, "SSVNC_LISTEN_ONCE: Trying to kill Listening Parent: %d\n", (int) listenParent); 9882 + fprintf(stderr, "SSVNC_LISTEN_ONCE: Press Ctrl-C if it continues to Listen.\n\n"); 9883 + kill(listenParent, SIGTERM); 9884 + } else { 9885 + fprintf(stderr,"(NOTE: You may need to Press Ctrl-C to make the Viewer Stop Listening.)\n\n"); 9886 + } 9887 + } 9888 +} 9889 + 9890 +static void check_dbg(void) { 9891 + if (getenv("SSVNC_EXIT_DEBUG")) { 9892 + fprintf(stderr, "Press any key to continue: "); 9893 + getc(stdin); 9894 + } 9895 } 9896 9897 static int 9898 CleanupXErrorHandler(Display *dpy, XErrorEvent *error) 9899 { 9900 - fprintf(stderr,"CleanupXErrorHandler called\n"); 9901 - Cleanup(); 9902 - return (*defaultXErrorHandler)(dpy, error); 9903 + if (XError_ign) { 9904 + char str[4096]; 9905 + XError_ign++; 9906 + fprintf(stderr,"XError_ign called.\n"); 9907 + str[0] = '\0'; 9908 + if (XGetErrorText(dpy, error->error_code, str, 4096)) { 9909 + fprintf(stderr, "%s", str); 9910 + } 9911 + return 0; 9912 + } 9913 + fprintf(stderr,"CleanupXErrorHandler called\n"); 9914 + check_dbg(); 9915 + Cleanup(); 9916 + return (*defaultXErrorHandler)(dpy, error); 9917 } 9918 9919 static int 9920 CleanupXIOErrorHandler(Display *dpy) 9921 { 9922 - fprintf(stderr,"CleanupXIOErrorHandler called\n"); 9923 - Cleanup(); 9924 - return (*defaultXIOErrorHandler)(dpy); 9925 + fprintf(stderr,"CleanupXIOErrorHandler called\n"); 9926 + check_dbg(); 9927 + Cleanup(); 9928 + return (*defaultXIOErrorHandler)(dpy); 9929 } 9930 9931 static void 9932 CleanupXtErrorHandler(String message) 9933 { 9934 - fprintf(stderr,"CleanupXtErrorHandler called\n"); 9935 - Cleanup(); 9936 - (*defaultXtErrorHandler)(message); 9937 + fprintf(stderr,"CleanupXtErrorHandler called\n"); 9938 + check_dbg(); 9939 + Cleanup(); 9940 + (*defaultXtErrorHandler)(message); 9941 } 9942 9943 static void 9944 CleanupSignalHandler(int sig) 9945 { 9946 - fprintf(stderr,"CleanupSignalHandler called\n"); 9947 - Cleanup(); 9948 - exit(1); 9949 + fprintf(stderr,"CleanupSignalHandler called\n"); 9950 + check_dbg(); 9951 + Cleanup(); 9952 + if (sig) {} 9953 + exit(1); 9954 } 9955 9956 9957 @@ -362,7 +455,7 @@ 9958 if (!XQueryTree(dpy, w, &dummy, &dummy, &children, &nchildren)) 9959 return False; 9960 9961 - for (i = 0; i < nchildren; i++) { 9962 + for (i = 0; i < (int) nchildren; i++) { 9963 if (IconifyNamedWindow(children[i], name, undo)) { 9964 XFree ((char *)children); 9965 return True; 9966 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer/popup.c 9967 --- vnc_unixsrc.orig/vncviewer/popup.c 2000-06-11 08:00:53.000000000 -0400 9968 +++ vnc_unixsrc/vncviewer/popup.c 2010-04-11 22:03:32.000000000 -0400 9969 @@ -22,25 +22,69 @@ 9970 */ 9971 9972 #include "vncviewer.h" 9973 +#include <time.h> 9974 +#include <sys/wait.h> 9975 9976 #include <X11/Xaw/Form.h> 9977 #include <X11/Xaw/Command.h> 9978 +#include <X11/Xaw/AsciiText.h> 9979 #include <X11/Xaw/Toggle.h> 9980 9981 +#include <X11/Xaw/Box.h> 9982 +#include <X11/Xaw/Scrollbar.h> 9983 + 9984 Widget popup, fullScreenToggle; 9985 9986 +Bool SendTextChatFinished(void); 9987 + 9988 +void popupFixer(Widget wid) { 9989 + Window rr, cr; 9990 + unsigned int m; 9991 + int x0 = 500, y0 = 500; 9992 + int xr, yr, wxr, wyr; 9993 + Dimension ph; 9994 + if (XQueryPointer(dpy, DefaultRootWindow(dpy), &rr, &cr, &xr, &yr, &wxr, &wyr, &m)) { 9995 + x0 = xr; 9996 + y0 = yr; 9997 + } 9998 + XtPopup(wid, XtGrabNone); 9999 + XtVaGetValues(wid, XtNheight, &ph, NULL); 10000 + if (y0 + (int) ph > dpyHeight) { 10001 + y0 = dpyHeight - (int) ph; 10002 + if (y0 < 0) { 10003 + y0 = 0; 10004 + } 10005 + } 10006 + XtMoveWidget(wid, x0, y0); 10007 +} 10008 + 10009 +void Noop(Widget w, XEvent *event, String *params, Cardinal *num_params) { 10010 + if (0) fprintf(stderr, "No-op\n"); 10011 + if (w || event || params || num_params) {} 10012 +} 10013 + 10014 void 10015 ShowPopup(Widget w, XEvent *event, String *params, Cardinal *num_params) 10016 { 10017 - XtMoveWidget(popup, event->xbutton.x_root, event->xbutton.y_root); 10018 - XtPopup(popup, XtGrabNone); 10019 - XSetWMProtocols(dpy, XtWindow(popup), &wmDeleteWindow, 1); 10020 + if (appData.popupFix) { 10021 + popupFixer(popup); 10022 + } else { 10023 + XtMoveWidget(popup, event->xbutton.x_root, event->xbutton.y_root); 10024 + XtPopup(popup, XtGrabNone); 10025 + } 10026 + if (appData.grabAll) { 10027 + XSync(dpy, False); 10028 + XRaiseWindow(dpy, XtWindow(popup)); 10029 + } 10030 + XSetWMProtocols(dpy, XtWindow(popup), &wmDeleteWindow, 1); 10031 + XtOverrideTranslations(popup, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HidePopup()")); 10032 + if (w || event || params || num_params) {} 10033 } 10034 10035 void 10036 -HidePopup(Widget w, XEvent *event, String *params, Cardinal *num_params) 10037 -{ 10038 - XtPopdown(popup); 10039 +HidePopup(Widget w, XEvent *event, String *params, Cardinal *num_params) { 10040 + XtPopdown(popup); 10041 + if (w || event || params || num_params) {} 10042 } 10043 10044 10045 @@ -52,42 +96,808 @@ 10046 }; 10047 10048 void 10049 -CreatePopup() 10050 +CreatePopup() { 10051 + Widget buttonForm1, buttonForm2, twoForm, button = 0, prevButton = NULL; 10052 + int i; 10053 + char buttonName[12]; 10054 + String buttonType; 10055 + 10056 + popup = XtVaCreatePopupShell("popup", transientShellWidgetClass, toplevel, NULL); 10057 + 10058 + twoForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, popup, NULL); 10059 + buttonForm1 = XtVaCreateManagedWidget("buttonForm", formWidgetClass, twoForm, NULL); 10060 + buttonForm2 = XtVaCreateManagedWidget("buttonForm", formWidgetClass, twoForm, XtNfromHoriz, (XtArgVal) buttonForm1, NULL); 10061 + 10062 + if (appData.popupButtonCount > 100) { 10063 + fprintf(stderr,"Too many popup buttons\n"); 10064 + exit(1); 10065 + } 10066 + 10067 + for (i = 1; i <= appData.popupButtonCount; i++) { 10068 + Widget bform; 10069 + sprintf(buttonName, "button%d", i); 10070 + 10071 + if (i <= appData.popupButtonBreak) { 10072 + bform = buttonForm1; 10073 + } else { 10074 + if (i == appData.popupButtonBreak+1) { 10075 + prevButton = NULL; 10076 + } 10077 + bform = buttonForm2; 10078 + } 10079 + XtVaGetSubresources(bform, (XtPointer)&buttonType, buttonName, "Button", resources, 1, NULL); 10080 + 10081 + if (strcmp(buttonType, "command") == 0) { 10082 + button = XtVaCreateManagedWidget(buttonName, commandWidgetClass, bform, NULL); 10083 + XtVaSetValues(button, XtNfromVert, prevButton, XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); 10084 + } else if (strcmp(buttonType, "toggle") == 0) { 10085 + button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, bform, NULL); 10086 + XtVaSetValues(button, XtNfromVert, prevButton, XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); 10087 + } else { 10088 + fprintf(stderr,"unknown button type '%s'\n", buttonType); 10089 + } 10090 + prevButton = button; 10091 + } 10092 +} 10093 + 10094 + 10095 +Widget scaleN; 10096 + 10097 +void 10098 +ShowScaleN(Widget w, XEvent *event, String *params, Cardinal *num_params) 10099 +{ 10100 + if (appData.popupFix) { 10101 + popupFixer(scaleN); 10102 + } else { 10103 + XtMoveWidget(scaleN, event->xbutton.x_root, event->xbutton.y_root); 10104 + XtPopup(scaleN, XtGrabNone); 10105 + } 10106 + if (appData.grabAll) { 10107 + XRaiseWindow(dpy, XtWindow(scaleN)); 10108 + } 10109 + XSetWMProtocols(dpy, XtWindow(scaleN), &wmDeleteWindow, 1); 10110 + XtOverrideTranslations(scaleN, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HideScaleN()")); 10111 + if (w || event || params || num_params) {} 10112 +} 10113 + 10114 +void 10115 +HideScaleN(Widget w, XEvent *event, String *params, Cardinal *num_params) 10116 +{ 10117 + XtPopdown(scaleN); 10118 + if (w || event || params || num_params) {} 10119 +} 10120 + 10121 + 10122 +void 10123 +CreateScaleN() 10124 { 10125 Widget buttonForm, button, prevButton = NULL; 10126 int i; 10127 - char buttonName[12]; 10128 + char buttonName[32]; 10129 String buttonType; 10130 10131 - popup = XtVaCreatePopupShell("popup", transientShellWidgetClass, toplevel, 10132 + scaleN = XtVaCreatePopupShell("scaleN", transientShellWidgetClass, toplevel, 10133 NULL); 10134 10135 - buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, popup, 10136 + buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, scaleN, 10137 NULL); 10138 10139 - if (appData.popupButtonCount > 100) { 10140 - fprintf(stderr,"Too many popup buttons\n"); 10141 - exit(1); 10142 - } 10143 - 10144 - for (i = 1; i <= appData.popupButtonCount; i++) { 10145 + for (i = 0; i <= 6; i++) { 10146 sprintf(buttonName, "button%d", i); 10147 XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName, 10148 "Button", resources, 1, NULL); 10149 10150 - if (strcmp(buttonType, "command") == 0) { 10151 - button = XtVaCreateManagedWidget(buttonName, commandWidgetClass, 10152 + button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, 10153 buttonForm, NULL); 10154 - XtVaSetValues(button, XtNfromVert, prevButton, 10155 + XtVaSetValues(button, XtNfromVert, prevButton, 10156 XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); 10157 - } else if (strcmp(buttonType, "toggle") == 0) { 10158 - button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, 10159 + prevButton = button; 10160 + } 10161 +} 10162 + 10163 +Widget turbovncW; 10164 + 10165 +static Widget turboButtons[32]; 10166 + 10167 +Widget qualtext, qualslider; 10168 + 10169 +void UpdateQualSlider(void) { 10170 +#ifdef TURBOVNC 10171 + char text[16]; 10172 + XawScrollbarSetThumb(qualslider, (float)appData.qualityLevel/100., 0.); 10173 + sprintf(text, "%3d", appData.qualityLevel); 10174 + XtVaSetValues(qualtext, XtNlabel, text, NULL); 10175 +#endif 10176 +} 10177 + 10178 +void qualScrollProc(Widget w, XtPointer client, XtPointer p) { 10179 +#ifdef TURBOVNC 10180 + float size, val; int qual, pos=(int)p; 10181 + XtVaGetValues(w, XtNshown, &size, XtNtopOfThumb, &val, 0); 10182 + if(pos<0) val-=.1; else val+=.1; 10183 + qual=(int)(val*100.); if(qual<1) qual=1; if(qual>100) qual=100; 10184 + XawScrollbarSetThumb(w, val, 0.); 10185 + appData.qualityLevel=qual; 10186 + UpdateQual(); 10187 +#endif 10188 + if (w || client || p) {} 10189 +} 10190 + 10191 +void qualJumpProc(Widget w, XtPointer client, XtPointer p) { 10192 +#ifdef TURBOVNC 10193 + float val=*(float *)p; int qual; 10194 + qual=(int)(val*100.); if(qual<1) qual=1; if(qual>100) qual=100; 10195 + appData.qualityLevel=qual; 10196 + UpdateQual(); 10197 +#endif 10198 + if (w || client || p) {} 10199 +} 10200 + 10201 +void UpdateSubsampButtons(void) { 10202 +#ifdef TURBOVNC 10203 + int i; 10204 + for (i=7; i <= 10; i++) { 10205 + XtVaSetValues(turboButtons[i], XtNstate, 0, NULL); 10206 + } 10207 + if (appData.subsampLevel==TVNC_1X) { 10208 + i = 7; 10209 + } else if (appData.subsampLevel==TVNC_2X) { 10210 + i = 8; 10211 + } else if (appData.subsampLevel==TVNC_4X) { 10212 + i = 9; 10213 + } else if (appData.subsampLevel==TVNC_GRAY) { 10214 + i = 10; 10215 + } else { 10216 + return; 10217 + } 10218 + XtVaSetValues(turboButtons[i], XtNstate, 1, NULL); 10219 +#endif 10220 +} 10221 + 10222 +void 10223 +ShowTurboVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) 10224 +{ 10225 + UpdateSubsampButtons(); 10226 + UpdateQualSlider(); 10227 + if (appData.popupFix) { 10228 + popupFixer(turbovncW); 10229 + } else { 10230 + XtMoveWidget(turbovncW, event->xbutton.x_root, event->xbutton.y_root); 10231 + XtPopup(turbovncW, XtGrabNone); 10232 + } 10233 + if (appData.grabAll) { 10234 + XRaiseWindow(dpy, XtWindow(turbovncW)); 10235 + } 10236 + XSetWMProtocols(dpy, XtWindow(turbovncW), &wmDeleteWindow, 1); 10237 + XtOverrideTranslations(turbovncW, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HideTurboVNC()")); 10238 + if (w || event || params || num_params) {} 10239 +} 10240 + 10241 +void 10242 +HideTurboVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) 10243 +{ 10244 + XtPopdown(turbovncW); 10245 + if (w || event || params || num_params) {} 10246 +} 10247 + 10248 +void 10249 +CreateTurboVNC() { 10250 + Widget buttonForm, button, prevButton = NULL; 10251 + Widget label; 10252 + int i; 10253 + char buttonName[32]; 10254 + String buttonType; 10255 + 10256 + turbovncW = XtVaCreatePopupShell("turboVNC", transientShellWidgetClass, toplevel, NULL); 10257 + 10258 + buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, turbovncW, NULL); 10259 + 10260 + for (i = 0; i <= 12; i++) { 10261 + sprintf(buttonName, "button%d", i); 10262 +#ifndef TURBOVNC 10263 + if (i == 0) { 10264 + sprintf(buttonName, "buttonNone"); 10265 + } else if (i > 0) { 10266 + return; 10267 + } 10268 +#endif 10269 + XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName, 10270 + "Button", resources, 1, NULL); 10271 + 10272 + button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, 10273 + buttonForm, NULL); 10274 + turboButtons[i] = button; 10275 + XtVaSetValues(button, XtNfromVert, prevButton, 10276 + XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); 10277 + prevButton = button; 10278 + } 10279 + 10280 + label = XtCreateManagedWidget("qualLabel", toggleWidgetClass, buttonForm, NULL, 0); 10281 + XtVaSetValues(label, XtNfromVert, prevButton, XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); 10282 + 10283 + qualslider = XtCreateManagedWidget("qualBar", scrollbarWidgetClass, buttonForm, NULL, 0); 10284 + XtVaSetValues(qualslider, XtNfromVert, label, XtNleft, XawChainLeft, NULL); 10285 + XtAddCallback(qualslider, XtNscrollProc, qualScrollProc, NULL) ; 10286 + XtAddCallback(qualslider, XtNjumpProc, qualJumpProc, NULL) ; 10287 + 10288 + qualtext = XtCreateManagedWidget("qualText", labelWidgetClass, buttonForm, NULL, 0); 10289 + XtVaSetValues(qualtext, XtNfromVert, label, XtNfromHoriz, qualslider, XtNright, XawChainRight, NULL); 10290 +} 10291 + 10292 +Widget qualityW; 10293 + 10294 +void 10295 +ShowQuality(Widget w, XEvent *event, String *params, Cardinal *num_params) 10296 +{ 10297 + if (appData.popupFix) { 10298 + popupFixer(qualityW); 10299 + } else { 10300 + XtMoveWidget(qualityW, event->xbutton.x_root, event->xbutton.y_root); 10301 + XtPopup(qualityW, XtGrabNone); 10302 + } 10303 + if (appData.grabAll) { 10304 + XRaiseWindow(dpy, XtWindow(qualityW)); 10305 + } 10306 + XSetWMProtocols(dpy, XtWindow(qualityW), &wmDeleteWindow, 1); 10307 + XtOverrideTranslations(qualityW, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HideQuality()")); 10308 + if (w || event || params || num_params) {} 10309 +} 10310 + 10311 +void 10312 +HideQuality(Widget w, XEvent *event, String *params, Cardinal *num_params) 10313 +{ 10314 + XtPopdown(qualityW); 10315 + if (w || event || params || num_params) {} 10316 +} 10317 + 10318 + 10319 +void 10320 +CreateQuality() 10321 +{ 10322 + Widget buttonForm, button, prevButton = NULL; 10323 + int i; 10324 + char buttonName[32]; 10325 + String buttonType; 10326 + 10327 + qualityW = XtVaCreatePopupShell("quality", transientShellWidgetClass, toplevel, 10328 + NULL); 10329 + 10330 + buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, qualityW, 10331 + NULL); 10332 + 10333 + for (i = -1; i <= 9; i++) { 10334 + if (i < 0) { 10335 + sprintf(buttonName, "buttonD"); 10336 + } else { 10337 + sprintf(buttonName, "button%d", i); 10338 + } 10339 + XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName, 10340 + "Button", resources, 1, NULL); 10341 + 10342 + button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, 10343 buttonForm, NULL); 10344 - XtVaSetValues(button, XtNfromVert, prevButton, 10345 + XtVaSetValues(button, XtNfromVert, prevButton, 10346 XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); 10347 + prevButton = button; 10348 + } 10349 +} 10350 + 10351 +Widget compressW; 10352 + 10353 +void 10354 +ShowCompress(Widget w, XEvent *event, String *params, Cardinal *num_params) 10355 +{ 10356 + if (appData.popupFix) { 10357 + popupFixer(compressW); 10358 + } else { 10359 + XtMoveWidget(compressW, event->xbutton.x_root, event->xbutton.y_root); 10360 + XtPopup(compressW, XtGrabNone); 10361 + } 10362 + if (appData.grabAll) { 10363 + XRaiseWindow(dpy, XtWindow(compressW)); 10364 + } 10365 + XSetWMProtocols(dpy, XtWindow(compressW), &wmDeleteWindow, 1); 10366 + XtOverrideTranslations(compressW, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HideCompress()")); 10367 + if (w || event || params || num_params) {} 10368 +} 10369 + 10370 +void 10371 +HideCompress(Widget w, XEvent *event, String *params, Cardinal *num_params) 10372 +{ 10373 + XtPopdown(compressW); 10374 + if (w || event || params || num_params) {} 10375 +} 10376 + 10377 + 10378 +void 10379 +CreateCompress() 10380 +{ 10381 + Widget buttonForm, button, prevButton = NULL; 10382 + int i; 10383 + char buttonName[32]; 10384 + String buttonType; 10385 + 10386 + compressW = XtVaCreatePopupShell("compress", transientShellWidgetClass, toplevel, 10387 + NULL); 10388 + 10389 + buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, compressW, 10390 + NULL); 10391 + 10392 + for (i = -1; i <= 9; i++) { 10393 + if (i < 0) { 10394 + sprintf(buttonName, "buttonD"); 10395 } else { 10396 - fprintf(stderr,"unknown button type '%s'\n",buttonType); 10397 + sprintf(buttonName, "button%d", i); 10398 } 10399 + XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName, 10400 + "Button", resources, 1, NULL); 10401 + 10402 + button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, 10403 + buttonForm, NULL); 10404 + XtVaSetValues(button, XtNfromVert, prevButton, 10405 + XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); 10406 prevButton = button; 10407 } 10408 } 10409 + 10410 + 10411 +int filexfer_sock = -1; 10412 +int filexfer_listen = -1; 10413 + 10414 +void HideFile(Widget w, XEvent *event, String *params, Cardinal *num_params) { 10415 + if (filexfer_sock >= 0) { 10416 + close(filexfer_sock); 10417 + filexfer_sock = -1; 10418 + } 10419 + if (filexfer_listen >= 0) { 10420 + close(filexfer_listen); 10421 + filexfer_listen = -1; 10422 + } 10423 + if (w || event || params || num_params) {} 10424 +} 10425 + 10426 +extern int use_loopback; 10427 +time_t start_listen = 0; 10428 +pid_t java_helper = 0; 10429 + 10430 +void ShowFile(Widget w, XEvent *event, String *params, Cardinal *num_params) { 10431 + int i, port0 = 7200, port, sock = -1; 10432 + char *cmd, *jar; 10433 + char fmt[] = "java -cp '%s' VncViewer HOST localhost PORT %d delayAuthPanel yes ignoreMSLogonCheck yes disableSSL yes ftpOnly yes graftFtp yes dsmActive no &"; 10434 + 10435 + if (getenv("SSVNC_ULTRA_FTP_JAR")) { 10436 + jar = getenv("SSVNC_ULTRA_FTP_JAR"); 10437 + cmd = (char *) malloc(strlen(fmt) + strlen(jar) + 100); 10438 + } else { 10439 + fprintf(stderr, "Cannot find UltraVNC FTP jar file.\n"); 10440 + return; 10441 + } 10442 + 10443 + use_loopback = 1; 10444 + for (i = 0; i < 100; i++) { 10445 + port = port0 + i; 10446 + sock = ListenAtTcpPort(port); 10447 + if (sock < 0) { 10448 + sock = ListenAtTcpPort6(port); 10449 + } 10450 + if (sock >= 0) { 10451 + fprintf(stderr, "listening for filexfer on port: %d sock: %d\n", port, sock); 10452 + break; 10453 + } 10454 + } 10455 + use_loopback = 0; 10456 + 10457 + if (sock >= 0) { 10458 + int st; 10459 + pid_t pid = fork(); 10460 + if (pid < 0) { 10461 + free(cmd); 10462 + return; 10463 + } else if (pid == 0) { 10464 + int i; 10465 + sprintf(cmd, fmt, jar, port); 10466 + if (appData.ultraDSM) { 10467 + char *q = strstr(cmd, "dsmActive"); 10468 + if (q) { 10469 + q = strstr(q, "no "); 10470 + if (q) { 10471 + q[0] = 'y'; 10472 + q[1] = 'e'; 10473 + q[2] = 's'; 10474 + } 10475 + } 10476 + } 10477 + for (i = 3; i < 100; i++) { 10478 + close(i); 10479 + } 10480 + fprintf(stderr, "\n-- Experimental UltraVNC File Transfer --\n\nRunning cmd:\n\n %s\n\n", cmd); 10481 + system(cmd); 10482 + exit(0); 10483 + } 10484 + fprintf(stderr, "java helper pid is: %d\n", (int) pid); 10485 + waitpid(pid, &st, 0); 10486 + java_helper = pid; 10487 + start_listen = time(NULL); 10488 + } 10489 + free(cmd); 10490 + filexfer_listen = sock; 10491 + if (w || event || params || num_params) {} 10492 +} 10493 + 10494 +Widget chat, entry, text; 10495 + 10496 +static int chat_visible = 0; 10497 + 10498 +void 10499 +ShowChat(Widget w, XEvent *event, String *params, Cardinal *num_params) 10500 +{ 10501 + if (appData.termChat) { 10502 + return; 10503 + } 10504 + if (! chat_visible) { 10505 + XtPopup(chat, XtGrabNone); 10506 + chat_visible = 1; 10507 + wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 10508 + XSetWMProtocols(dpy, XtWindow(chat), &wmDeleteWindow, 1); 10509 + if (appData.chatOnly) { 10510 + XtOverrideTranslations(chat, XtParseTranslationTable ("<Message>WM_PROTOCOLS: Quit()")); 10511 + } else { 10512 + XtOverrideTranslations(chat, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HideChat()")); 10513 + } 10514 + XSync(dpy, False); 10515 + usleep(200 * 1000); 10516 + } 10517 + if (w || event || params || num_params) {} 10518 +} 10519 + 10520 +void hidechat(void) { 10521 + appData.chatActive = False; 10522 + if (appData.termChat) { 10523 + return; 10524 + } 10525 + if (chat_visible) { 10526 + XtPopdown(chat); 10527 + chat_visible = 0; 10528 + XSync(dpy, False); 10529 + usleep(200 * 1000); 10530 + } 10531 + if (appData.chatOnly) { 10532 + Quit(0, NULL, NULL, NULL); 10533 + } 10534 +} 10535 + 10536 +void HideChat(Widget w, XEvent *event, String *params, Cardinal *num_params) { 10537 + SendTextChatClose(); 10538 + SendTextChatFinished(); 10539 + hidechat(); 10540 + if (w || event || params || num_params) {} 10541 +} 10542 + 10543 +void dismiss_proc(Widget w, XtPointer client_data, XtPointer call_data) { 10544 + SendTextChatClose(); 10545 + SendTextChatFinished(); 10546 + hidechat(); 10547 + if (w || client_data || call_data) {} 10548 +} 10549 + 10550 +extern void printChat(char *, Bool); 10551 + 10552 +static void ChatTextCallback(XtPointer clientData, XtIntervalId *id); 10553 +static XtIntervalId timer; 10554 +static Bool timerSet = False; 10555 + 10556 +void CheckTextInput(void); 10557 +extern double start_time; 10558 + 10559 +static void ChatTextCallback(XtPointer clientData, XtIntervalId *id) { 10560 + static int db = -1; 10561 + if (db < 0) { 10562 + if (getenv("SSVNC_DEBUG_CHAT")) { 10563 + db = 1; 10564 + } else { 10565 + db = 0; 10566 + } 10567 + } 10568 + if (db) fprintf(stderr, "ChatTextCallback: %.4f\n", dnow() - start_time); 10569 + CheckTextInput(); 10570 + if (clientData || id) {} 10571 +} 10572 + 10573 +void CheckTextInput(void) { 10574 + Arg args[2]; 10575 + String str; 10576 + int len; 10577 + static int db = -1; 10578 + 10579 + if (timerSet) { 10580 + XtRemoveTimeOut(timer); 10581 + timerSet = False; 10582 + } 10583 + if (appData.chatActive) { 10584 + timer = XtAppAddTimeOut(appContext, 333, ChatTextCallback, NULL); 10585 + timerSet = True; 10586 + } 10587 + if (appData.chatOnly && !appData.chatActive) { 10588 + Quit(0, NULL, NULL, NULL); 10589 + } 10590 + 10591 + if (appData.termChat) { 10592 + return; 10593 + } 10594 +#if 0 10595 + if (!appData.chatActive) { 10596 + return; 10597 + } 10598 +#endif 10599 + 10600 + if (db < 0) { 10601 + if (getenv("SSVNC_DEBUG_CHAT")) { 10602 + db = 1; 10603 + } else { 10604 + db = 0; 10605 + } 10606 + } 10607 + 10608 + XtSetArg(args[0], XtNstring, &str); 10609 + XtGetValues(entry, args, 1); 10610 + 10611 + if (db) fprintf(stderr, "CheckTextInput\n"); 10612 + 10613 + if (str == NULL || str[0] == '\0') { 10614 + return; 10615 + } else { 10616 + char *q; 10617 + len = strlen(str); 10618 + if (db) fprintf(stderr, "CheckTextInput: len: %d '%s'\n", len, str); 10619 + if (len <= 0) { 10620 + return; 10621 + } 10622 + q = strrchr(str, '\n'); 10623 + if (q) { 10624 + char *send, save[2]; 10625 + save[0] = *(q+1); 10626 + *(q+1) = '\0'; 10627 + send = strdup(str); 10628 + *(q+1) = save[0]; 10629 + if (send) { 10630 + SendTextChat(send); 10631 + printChat("Send: ", True); 10632 + printChat(send, True); 10633 + free(send); 10634 + if (save[0] == '\0') { 10635 + XtVaSetValues(entry, XtNtype, XawAsciiString, XtNstring, "", NULL); 10636 + } else { 10637 + char *leak = strdup(q+1); 10638 + XtVaSetValues(entry, XtNtype, XawAsciiString, XtNstring, leak, NULL); 10639 + if (strlen(leak) > 0) { 10640 + XSync(dpy, False); 10641 + XtVaSetValues(entry, XtNinsertPosition, strlen(leak), NULL); 10642 + } 10643 + } 10644 + } 10645 + } 10646 + } 10647 +} 10648 + 10649 +void AppendChatInput0(char *in) { 10650 + Arg args[10]; 10651 + int n; 10652 + String str; 10653 + int len; 10654 + static char *s = NULL; 10655 + static int slen = -1; 10656 + XawTextPosition pos; 10657 + 10658 + fprintf(stderr, "AppendChatInput: in= '%s'\n", in); 10659 + 10660 + XtSetArg(args[0], XtNstring, &str); 10661 + XtGetValues(text, args, 1); 10662 + fprintf(stderr, "AppendChatInput: str='%s'\n", str); 10663 + 10664 + len = strlen(str) + strlen(in); 10665 + 10666 + if (slen <= len) { 10667 + slen = 2 * (len + 10); 10668 + if (s) free(s); 10669 + s = (char *) malloc(slen+1); 10670 + } 10671 + 10672 + s[0] = '\0'; 10673 + strcat(s, str); 10674 + strcat(s, in); 10675 + fprintf(stderr, "AppendChatInput s= '%s'\n", s); 10676 + pos = (XawTextPosition) (len-1); 10677 + n = 0; 10678 + XtSetArg(args[n], XtNtype, XawAsciiString); n++; 10679 + XtSetArg(args[n], XtNstring, s); n++; 10680 + XtSetArg(args[n], XtNdisplayPosition, pos); n++; 10681 + XtSetArg(args[n], XtNinsertPosition, pos); n++; 10682 + XtSetValues(text, args, n); 10683 + fprintf(stderr, "AppendChatInput done\n"); 10684 +} 10685 + 10686 +void AppendChatInput(char *in) { 10687 + XawTextPosition beg, end; 10688 + static XawTextPosition pos = 0; 10689 + XawTextBlock txt; 10690 + 10691 + if (appData.termChat) { 10692 + return; 10693 + } 10694 + 10695 + XawTextSetInsertionPoint(text, pos); 10696 + beg = XawTextGetInsertionPoint(text); 10697 + end = beg; 10698 +#if 0 10699 + fprintf(stderr, "AppendChatInput: pos=%d in= '%s'\n", beg, in); 10700 +#endif 10701 + 10702 + txt.firstPos = 0; 10703 + txt.length = strlen(in); 10704 + txt.ptr = in; 10705 + txt.format = FMT8BIT; 10706 + 10707 + XawTextReplace(text, beg, end, &txt); 10708 + XawTextSetInsertionPoint(text, beg + txt.length); 10709 + 10710 + pos = XawTextGetInsertionPoint(text); 10711 +#if 0 10712 + fprintf(stderr, "AppendChatInput done pos=%d\n", pos); 10713 +#endif 10714 +} 10715 + 10716 +#if 0 10717 +static char errorbuf[1] = {0}; 10718 +#endif 10719 + 10720 +void CreateChat(void) { 10721 + 10722 + Widget myform, dismiss; 10723 + Dimension w = 400, h = 300; 10724 + 10725 + chat = XtVaCreatePopupShell("chat", topLevelShellWidgetClass, toplevel, XtNmappedWhenManaged, False, NULL); 10726 + 10727 + myform = XtVaCreateManagedWidget("myform", formWidgetClass, chat, NULL); 10728 + 10729 + text = XtVaCreateManagedWidget("text", asciiTextWidgetClass, myform, 10730 + XtNresize, XawtextResizeBoth, XtNresizable, True, XtNwrap, XawtextWrapWord, 10731 + XtNscrollHorizontal, XawtextScrollNever, XtNscrollVertical, XawtextScrollAlways, 10732 + XtNwidth, w, XtNheight, h, XtNdisplayCaret, False, 10733 + XtNeditType, XawtextAppend, XtNtype, XawAsciiString, 10734 + XtNuseStringInPlace, False, NULL); 10735 + 10736 + entry = XtVaCreateManagedWidget("entry", asciiTextWidgetClass, myform, 10737 + XtNresize, XawtextResizeWidth, XtNresizable, True, XtNwrap, XawtextWrapNever, 10738 + XtNscrollHorizontal, XawtextScrollNever, XtNscrollVertical, XawtextScrollNever, 10739 + XtNheight, 20, XtNwidth, 400, XtNfromVert, text, XtNeditType, XawtextEdit, 10740 + XtNdisplayCaret, True, XtNeditType, XawtextEdit, NULL); 10741 + 10742 + dismiss = XtVaCreateManagedWidget("dismiss", commandWidgetClass, myform, XtNlabel, "Close Chat", XtNfromVert, entry, NULL); 10743 + 10744 + AppendChatInput(""); 10745 + 10746 + XtAddCallback(dismiss, XtNcallback, dismiss_proc, NULL); 10747 + 10748 + XtRealizeWidget(chat); 10749 + 10750 + XtSetKeyboardFocus(chat, entry); 10751 +} 10752 + 10753 +Widget msgwin, msgtext; 10754 + 10755 +void AppendMsg(char *in) { 10756 + XawTextPosition beg, end; 10757 + static XawTextPosition pos = 0; 10758 + XawTextBlock txt; 10759 + 10760 + XawTextSetInsertionPoint(msgtext, pos); 10761 + beg = XawTextGetInsertionPoint(msgtext); 10762 + end = beg; 10763 + 10764 + txt.firstPos = 0; 10765 + txt.length = strlen(in); 10766 + txt.ptr = in; 10767 + txt.format = FMT8BIT; 10768 + 10769 + XawTextReplace(msgtext, beg, end, &txt); 10770 + XawTextSetInsertionPoint(msgtext, beg + txt.length); 10771 + 10772 + pos = XawTextGetInsertionPoint(msgtext); 10773 +} 10774 + 10775 +static int msg_visible = 0; 10776 +static int msg_NO_clicked = 0; 10777 + 10778 +void msg_dismiss_proc(Widget w, XtPointer client_data, XtPointer call_data) { 10779 + XtPopdown(msgwin); 10780 + msg_visible = 0; 10781 + XSync(dpy, False); 10782 + usleep(200 * 1000); 10783 + if (w || client_data || call_data) {} 10784 +} 10785 + 10786 +void msg_NO_proc(Widget w, XtPointer client_data, XtPointer call_data) { 10787 + XtPopdown(msgwin); 10788 + msg_visible = 0; 10789 + msg_NO_clicked = 1; 10790 + XSync(dpy, False); 10791 + usleep(200 * 1000); 10792 + if (w || client_data || call_data) {} 10793 +} 10794 + 10795 +int CreateMsg(char *msg, int wait) { 10796 + 10797 + Widget myform, dismiss, reject; 10798 + char *p; 10799 + int n, run, wmax = 0; 10800 + int ret = 1; 10801 + Dimension w, h; 10802 + 10803 + 10804 + n = 0; 10805 + run = 0; 10806 + p = msg; 10807 + while (*p != '\0') { 10808 + if (*p == '\n') { 10809 + run = 0; 10810 + n++; 10811 + } 10812 + run++; 10813 + if (run > wmax) wmax = run; 10814 + p++; 10815 + } 10816 + if (wmax > 80) { 10817 + if (wmax > 120) n++; 10818 + if (wmax > 80) n++; 10819 + wmax = 80; 10820 + } 10821 + h = (Dimension) (n+2) * 14; 10822 + w = (Dimension) (wmax+10) * 8; 10823 + 10824 + msgwin = XtVaCreatePopupShell("Message", topLevelShellWidgetClass, toplevel, XtNmappedWhenManaged, False, NULL); 10825 + 10826 + myform = XtVaCreateManagedWidget("myform", formWidgetClass, msgwin, NULL); 10827 + 10828 + msgtext = XtVaCreateManagedWidget("msgtext", asciiTextWidgetClass, myform, 10829 + XtNresize, XawtextResizeBoth, XtNresizable, True, XtNwrap, XawtextWrapWord, 10830 + XtNscrollHorizontal, XawtextScrollNever, XtNscrollVertical, XawtextScrollAlways, 10831 + XtNwidth, w, XtNheight, h, XtNdisplayCaret, False, 10832 + XtNeditType, XawtextAppend, XtNtype, XawAsciiString, 10833 + XtNuseStringInPlace, False, NULL); 10834 + 10835 + if (wait == 2) { 10836 + msg_NO_clicked = 0; 10837 + 10838 + dismiss = XtVaCreateManagedWidget("dismiss", commandWidgetClass, myform, XtNlabel, "Accept", XtNfromVert, msgtext, NULL); 10839 + XtAddCallback(dismiss, XtNcallback, msg_dismiss_proc, NULL); 10840 + 10841 + reject = XtVaCreateManagedWidget("reject", commandWidgetClass, myform, XtNlabel, "Reject", XtNfromVert, dismiss, NULL); 10842 + XtAddCallback(reject, XtNcallback, msg_NO_proc, NULL); 10843 + } else { 10844 + dismiss = XtVaCreateManagedWidget("dismiss", commandWidgetClass, myform, XtNlabel, "OK", XtNfromVert, msgtext, NULL); 10845 + XtAddCallback(dismiss, XtNcallback, msg_dismiss_proc, NULL); 10846 + 10847 + } 10848 + 10849 + AppendMsg(""); 10850 + AppendMsg(msg); 10851 + 10852 + XtRealizeWidget(msgwin); 10853 + 10854 + XtPopup(msgwin, XtGrabNone); 10855 + 10856 + XSync(dpy, False); 10857 + msg_visible = 1; 10858 + while (wait && msg_visible) { 10859 + if (0) fprintf(stderr, "mv: %d\n", msg_visible); 10860 + XtAppProcessEvent(appContext, XtIMAll); 10861 + } 10862 + if (wait == 2) { 10863 + if (msg_NO_clicked) { 10864 + ret = 0; 10865 + } else { 10866 + ret = 1; 10867 + } 10868 + } 10869 + return ret; 10870 +} 10871 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup_ad vnc_unixsrc/vncviewer/popup_ad 10872 --- vnc_unixsrc.orig/vncviewer/popup_ad 1969-12-31 19:00:00.000000000 -0500 10873 +++ vnc_unixsrc/vncviewer/popup_ad 2008-02-17 13:32:34.000000000 -0500 10874 @@ -0,0 +1,20 @@ 10875 +#!/usr/bin/perl 10876 + 10877 +$ok = 0; 10878 + 10879 +open(A, "<argsresources.c") || die; 10880 + 10881 +while (<A>) { 10882 + if (/popupButtonCount:/) { 10883 + $on = 1; 10884 + } elsif (/^\s*NULL/) { 10885 + $on = 0; 10886 + } 10887 + next unless $on; 10888 + chomp; 10889 + last if /NULL/; 10890 + $_ =~ s/^\s*"//; 10891 + $_ =~ s/",//; 10892 + $_ .= "\n" unless $_ =~ /\n/; 10893 + print; 10894 +} 10895 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncviewer/rfbproto.c 10896 --- vnc_unixsrc.orig/vncviewer/rfbproto.c 2008-09-05 19:51:24.000000000 -0400 10897 +++ vnc_unixsrc/vncviewer/rfbproto.c 2010-04-17 22:34:38.000000000 -0400 10898 @@ -23,7 +23,10 @@ 10899 * rfbproto.c - functions to deal with client side of RFB protocol. 10900 */ 10901 10902 +#include <sys/stat.h> 10903 #include <unistd.h> 10904 +#include <time.h> 10905 +#include <ctype.h> 10906 #include <errno.h> 10907 #include <pwd.h> 10908 #include <vncviewer.h> 10909 @@ -31,6 +34,9 @@ 10910 #include <zlib.h> 10911 #include <jpeglib.h> 10912 10913 +int server_major = 0, server_minor = 0; 10914 +int viewer_major = 0, viewer_minor = 0; 10915 + 10916 static void InitCapabilities(void); 10917 static Bool SetupTunneling(void); 10918 static int ReadSecurityType(void); 10919 @@ -57,6 +63,47 @@ 10920 static Bool HandleTight16(int rx, int ry, int rw, int rh); 10921 static Bool HandleTight32(int rx, int ry, int rw, int rh); 10922 10923 +/* runge add zrle */ 10924 +static Bool HandleZRLE8(int rx, int ry, int rw, int rh); 10925 +static Bool HandleZRLE15(int rx, int ry, int rw, int rh); 10926 +static Bool HandleZRLE16(int rx, int ry, int rw, int rh); 10927 +static Bool HandleZRLE24(int rx, int ry, int rw, int rh); 10928 +static Bool HandleZRLE24Up(int rx, int ry, int rw, int rh); 10929 +static Bool HandleZRLE24Down(int rx, int ry, int rw, int rh); 10930 +static Bool HandleZRLE32(int rx, int ry, int rw, int rh); 10931 + 10932 +extern Bool HandleCursorPos(int x, int y); 10933 +extern void printChat(char *, Bool); 10934 + 10935 +typedef struct { 10936 + unsigned long length; 10937 +} rfbZRLEHeader; 10938 + 10939 +#define sz_rfbZRLEHeader 4 10940 + 10941 +#define rfbZRLETileWidth 64 10942 +#define rfbZRLETileHeight 64 10943 + 10944 +#define DO_ZYWRLE 1 10945 + 10946 +#if DO_ZYWRLE 10947 + 10948 +#ifndef ZRLE_ONCE 10949 +#define ZRLE_ONCE 10950 + 10951 +static const int bitsPerPackedPixel[] = { 10952 + 0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 10953 +}; 10954 + 10955 +int zywrle_level; 10956 +int zywrleBuf[rfbZRLETileWidth*rfbZRLETileHeight]; 10957 + 10958 +#include "zrlepalettehelper.h" 10959 +static zrlePaletteHelper paletteHelper; 10960 + 10961 +#endif /* ZRLE_ONCE */ 10962 +#endif /* DO_ZYWRLE */ 10963 + 10964 static void ReadConnFailedReason(void); 10965 static long ReadCompactLen (void); 10966 10967 @@ -67,6 +114,25 @@ 10968 static void JpegSetSrcManager(j_decompress_ptr cinfo, CARD8 *compressedData, 10969 int compressedLen); 10970 10971 +extern void deskey(unsigned char *, int); 10972 +extern void des(unsigned char *, unsigned char *); 10973 + 10974 +extern int currentMsg; 10975 +extern double scale_factor_x; 10976 +extern double scale_factor_y; 10977 + 10978 +extern int skip_maybe_sync; 10979 + 10980 +int sent_FBU = 0; 10981 +int skip_XtUpdate = 0; 10982 +int skip_XtUpdateAll = 0; 10983 + 10984 +static double dt_out = 0.0; 10985 +static double dt_out_sc = 0.0; 10986 +double latency = 0.0; 10987 +double connect_time = 0.0; 10988 + 10989 +void raiseme(int force); 10990 10991 int rfbsock; 10992 char *desktopName; 10993 @@ -75,6 +141,14 @@ 10994 char *serverCutText = NULL; 10995 Bool newServerCutText = False; 10996 10997 +/* ultravnc mslogon */ 10998 +#define rfbUltraVncMsLogon 0xfffffffa 10999 +static Bool AuthUltraVncMsLogon(void); 11000 +extern void UvncEncryptPasswd_MSLOGON(unsigned char *encryptedPasswd, char *passwd); 11001 +extern void UvncEncryptBytes2(unsigned char *where, int length, unsigned char *key); 11002 +extern void UvncDecryptBytes2(unsigned char *where, int length, unsigned char *key); 11003 +extern unsigned int urandom(void); 11004 + 11005 int endianTest = 1; 11006 11007 static Bool tightVncProtocol = False; 11008 @@ -177,8 +251,26 @@ 11009 sig_rfbEncodingPointerPos, "Pointer position update"); 11010 CapsAdd(encodingCaps, rfbEncodingLastRect, rfbTightVncVendor, 11011 sig_rfbEncodingLastRect, "LastRect protocol extension"); 11012 + 11013 + CapsAdd(encodingCaps, rfbEncodingNewFBSize, rfbTightVncVendor, 11014 + sig_rfbEncodingNewFBSize, "New FB size protocol extension"); 11015 + 11016 +#ifdef TURBOVNC 11017 + CapsAdd(encodingCaps, rfbJpegQualityLevel1, rfbTurboVncVendor, 11018 + sig_rfbEncodingNewFBSize, "TurboJPEG quality level"); 11019 + CapsAdd(encodingCaps, rfbJpegSubsamp1X, rfbTurboVncVendor, 11020 + sig_rfbEncodingNewFBSize, "TurboJPEG subsampling level"); 11021 +#endif 11022 } 11023 11024 +static char msgbuf[10000]; 11025 + 11026 +static void wmsg(char *msg, int wait) { 11027 + fprintf(stderr, "%s", msg); 11028 + if (!use_tty() && !getenv("SSVNC_NO_MESSAGE_POPUP")) { 11029 + CreateMsg(msg, wait); 11030 + } 11031 +} 11032 11033 /* 11034 * ConnectToRFBServer. 11035 @@ -187,24 +279,179 @@ 11036 Bool 11037 ConnectToRFBServer(const char *hostname, int port) 11038 { 11039 - unsigned int host; 11040 - 11041 - if (!StringToIPAddr(hostname, &host)) { 11042 - fprintf(stderr,"Couldn't convert '%s' to host address\n", hostname); 11043 - return False; 11044 - } 11045 + char *q, *cmd = NULL; 11046 + Bool setnb; 11047 + struct stat sb; 11048 + 11049 + if (strstr(hostname, "exec=") == hostname) { 11050 + cmd = strdup(hostname); 11051 + q = strchr(cmd, '='); 11052 + *q = ' '; 11053 + if (getenv("SSVNC_BASEDIR")) { 11054 + char *base = getenv("SSVNC_BASEDIR"); 11055 + char *newcmd = (char *)malloc(strlen(base) + strlen(cmd) + 1000); 11056 + sprintf(newcmd, "%s/unwrap.so", base); 11057 + if (stat(newcmd, &sb) == 0) { 11058 +#if (defined(__MACH__) && defined(__APPLE__)) 11059 + 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); 11060 +#else 11061 + sprintf(newcmd, "LD_PRELOAD='%s/unwrap.so'; export LD_PRELOAD; %s", base, cmd); 11062 +#endif 11063 + cmd = newcmd; 11064 + } 11065 + } 11066 + } 11067 11068 - rfbsock = ConnectToTcpAddr(host, port); 11069 + if (cmd != NULL) { 11070 + int sfd[2]; 11071 + char *q, *cmd2 = strdup(cmd); 11072 + pid_t pid; 11073 + 11074 + q = strstr(cmd2, "pw="); 11075 + if (q && !getenv("SSVNC_SHOW_ULTRAVNC_DSM_PASSWORD")) { 11076 + q += strlen("pw="); 11077 + while (*q != '\0' && !isspace(*q)) { 11078 + *q = '*'; 11079 + q++; 11080 + } 11081 + } 11082 + 11083 + fprintf(stderr, "exec-cmd: %s\n\n", cmd2); 11084 + free(cmd2); 11085 + 11086 + if (! SocketPair(sfd)) { 11087 + return False; 11088 + } 11089 + if (0) { 11090 + fprintf(stderr, "sfd: %d %d\n", sfd[0], sfd[1]); 11091 + fflush(stderr); 11092 + } 11093 + 11094 + pid = fork(); 11095 + if (pid == -1) { 11096 + perror("fork"); 11097 + return False; 11098 + } 11099 + if (pid == 0) { 11100 + char *args[4]; 11101 + int d; 11102 + args[0] = "/bin/sh"; 11103 + args[1] = "-c"; 11104 + args[2] = cmd; 11105 + args[3] = NULL; 11106 + 11107 + close(sfd[1]); 11108 + dup2(sfd[0], 0); 11109 + dup2(sfd[0], 1); 11110 + for (d=3; d < 256; d++) { 11111 + if (d != sfd[0]) { 11112 + close(d); 11113 + } 11114 + } 11115 + execvp(args[0], args); 11116 + perror("exec"); 11117 + exit(1); 11118 + } else { 11119 + close(sfd[0]); 11120 + rfbsock = sfd[1]; 11121 + } 11122 + if (rfbsock < 0) { 11123 + sprintf(msgbuf,"Unable to connect to exec'd command: %s\n", cmd); 11124 + wmsg(msgbuf, 1); 11125 + return False; 11126 + } 11127 + } else if (strstr(hostname, "fd=") == hostname) { 11128 + rfbsock = atoi(hostname + strlen("fd=")); 11129 + } else if (strchr(hostname, '/') && stat(hostname, &sb) == 0) { 11130 + /* assume unix domain socket */ 11131 + char *thost = strdup(hostname); 11132 + 11133 + rfbsock = ConnectToUnixSocket(thost); 11134 + free(thost); 11135 + 11136 + if (rfbsock < 0) { 11137 + sprintf(msgbuf,"Unable to connect to VNC server (unix-domain socket: %s)\n", hostname); 11138 + wmsg(msgbuf, 1); 11139 + return False; 11140 + } 11141 + 11142 + } else { 11143 + rfbsock = ConnectToTcpAddr(hostname, port); 11144 + 11145 + if (rfbsock < 0 && !appData.noipv4) { 11146 + char *q, *hosttmp; 11147 + if (hostname[0] == '[') { 11148 + hosttmp = strdup(hostname+1); 11149 + } else { 11150 + hosttmp = strdup(hostname); 11151 + } 11152 + q = strrchr(hosttmp, ']'); 11153 + if (q) *q = '\0'; 11154 + if (strstr(hosttmp, "::ffff:") == hosttmp || strstr(hosttmp, "::FFFF:") == hosttmp) { 11155 + char *host = hosttmp + strlen("::ffff:"); 11156 + if (dotted_ip(host, 0)) { 11157 + fprintf(stderr, "ConnectToTcpAddr[ipv4]: re-trying connection using '%s'\n", host); 11158 + rfbsock = ConnectToTcpAddr(host, port); 11159 + } 11160 + } 11161 + free(hosttmp); 11162 + } 11163 + 11164 + if (rfbsock < 0) { 11165 + sprintf(msgbuf,"Unable to connect to VNC server (%s:%d)\n", hostname, port); 11166 + wmsg(msgbuf, 1); 11167 + return False; 11168 + } 11169 + } 11170 11171 - if (rfbsock < 0) { 11172 - fprintf(stderr,"Unable to connect to VNC server\n"); 11173 - return False; 11174 - } 11175 + setnb = SetNonBlocking(rfbsock); 11176 + return setnb; 11177 +} 11178 11179 - return SetNonBlocking(rfbsock); 11180 +static void printFailureReason(void) { 11181 + CARD32 reasonLen; 11182 + ReadFromRFBServer((char *)&reasonLen, 4); 11183 + reasonLen = Swap32IfLE(reasonLen); 11184 + if (reasonLen < 4096) { 11185 + char *reason = (char *) malloc(reasonLen+1); 11186 + memset(reason, 0, reasonLen+1); 11187 + ReadFromRFBServer(reason, reasonLen); 11188 + sprintf(msgbuf, "Reason: %s\n", reason); 11189 + wmsg(msgbuf, 1); 11190 + free(reason); 11191 + } 11192 } 11193 11194 +static char *pr_sec_type(int type) { 11195 + char *str = "unknown"; 11196 + if (type == rfbSecTypeInvalid) str = "rfbSecTypeInvalid"; 11197 + if (type == rfbSecTypeNone) str = "rfbSecTypeNone"; 11198 + if (type == rfbSecTypeVncAuth) str = "rfbSecTypeVncAuth"; 11199 + if (type == rfbSecTypeRA2) str = "rfbSecTypeRA2"; 11200 + if (type == rfbSecTypeRA2ne) str = "rfbSecTypeRA2ne"; 11201 + if (type == rfbSecTypeTight) str = "rfbSecTypeTight"; 11202 + if (type == rfbSecTypeUltra) str = "rfbSecTypeUltra"; 11203 + 11204 + if (type == rfbSecTypeAnonTls) str = "rfbSecTypeAnonTls"; 11205 + if (type == rfbSecTypeVencrypt) str = "rfbSecTypeVencrypt"; 11206 + 11207 + if (type == (int) rfbUltraVncMsLogon) str = "rfbUltraVncMsLogon"; 11208 + return str; 11209 +} 11210 + 11211 +static char *pr_sec_subtype(int type) { 11212 + char *str = "unknown"; 11213 + if (type == rfbVencryptPlain) str = "rfbVencryptPlain"; 11214 + if (type == rfbVencryptTlsNone) str = "rfbVencryptTlsNone"; 11215 + if (type == rfbVencryptTlsVnc) str = "rfbVencryptTlsVnc"; 11216 + if (type == rfbVencryptTlsPlain) str = "rfbVencryptTlsPlain"; 11217 + if (type == rfbVencryptX509None) str = "rfbVencryptX509None"; 11218 + if (type == rfbVencryptX509Vnc) str = "rfbVencryptX509Vnc"; 11219 + if (type == rfbVencryptX509Plain) str = "rfbVencryptX509Plain"; 11220 + return str; 11221 +} 11222 11223 +extern void ProcessXtEvents(void); 11224 /* 11225 * InitialiseRFBConnection. 11226 */ 11227 @@ -212,211 +459,654 @@ 11228 Bool 11229 InitialiseRFBConnection(void) 11230 { 11231 - rfbProtocolVersionMsg pv; 11232 - int server_major, server_minor; 11233 - int viewer_major, viewer_minor; 11234 - rfbClientInitMsg ci; 11235 - int secType; 11236 + rfbProtocolVersionMsg pv; 11237 + rfbClientInitMsg ci; 11238 + int i, secType, anon_dh = 0, accept_uvnc = 0; 11239 + FILE *pd; 11240 + char *hsfile = NULL; 11241 + char *hsparam[128]; 11242 + char *envsetsec = getenv("SSVNC_SET_SECURITY_TYPE"); 11243 + char line[128]; 11244 + double dt = 0.0; 11245 11246 - /* if the connection is immediately closed, don't report anything, so 11247 - that pmw's monitor can make test connections */ 11248 + /* if the connection is immediately closed, don't report anything, so 11249 + that pmw's monitor can make test connections */ 11250 11251 - if (listenSpecified) 11252 - errorMessageOnReadFailure = False; 11253 + if (listenSpecified) { 11254 + errorMessageOnReadFailure = False; 11255 + } 11256 11257 - if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) 11258 - return False; 11259 + for (i=0; i < 128; i++) { 11260 + hsparam[i] = NULL; 11261 + } 11262 11263 - errorMessageOnReadFailure = True; 11264 + skip_XtUpdateAll = 1; 11265 + ProcessXtEvents(); 11266 + skip_XtUpdateAll = 0; 11267 + 11268 + if (getenv("SSVNC_PREDIGESTED_HANDSHAKE")) { 11269 + double start = dnow(); 11270 + hsfile = getenv("SSVNC_PREDIGESTED_HANDSHAKE"); 11271 + while (dnow() < start + 10.0) { 11272 + int done = 0; 11273 + usleep(100 * 1000); 11274 + if ((pd = fopen(hsfile, "r")) != NULL) { 11275 + while (fgets(line, 128, pd) != NULL) { 11276 + if (strstr(line, "done") == line) { 11277 + done = 1; 11278 + usleep(100 * 1000); 11279 + break; 11280 + } 11281 + } 11282 + fclose(pd); 11283 + } 11284 + if (done) { 11285 + break; 11286 + } 11287 + } 11288 + if ((pd = fopen(hsfile, "r")) != NULL) { 11289 + i = 0; 11290 + while (fgets(line, 128, pd) != NULL) { 11291 + hsparam[i] = strdup(line); 11292 + fprintf(stderr, "%s", line); 11293 + if (i++ > 100) break; 11294 + } 11295 + fclose(pd); 11296 + } 11297 + unlink(hsfile); 11298 + } 11299 11300 - pv[sz_rfbProtocolVersionMsg] = 0; 11301 + if (getenv("SSVNC_SKIP_RFB_PROTOCOL_VERSION")) { 11302 + viewer_major = 3; 11303 + viewer_minor = 8; 11304 + goto end_of_proto_msg; 11305 + } else if (hsfile) { 11306 + int k = 0; 11307 + while (hsparam[k] != NULL) { 11308 + char *str = hsparam[k++]; 11309 + if (strstr(str, "server=") == str) { 11310 + sprintf(pv, "%s", str + strlen("server=")); 11311 + goto readed_pv; 11312 + } 11313 + } 11314 + } 11315 11316 - if (sscanf(pv, rfbProtocolVersionFormat, 11317 - &server_major, &server_minor) != 2) { 11318 - fprintf(stderr,"Not a valid VNC server\n"); 11319 - return False; 11320 - } 11321 + dt = dnow(); 11322 + if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) { 11323 + return False; 11324 + } 11325 + if (getenv("PRINT_DELAY1")) fprintf(stderr, "delay1: %.3f ms\n", (dnow() - dt) * 1000); 11326 + dt = 0.0; 11327 11328 - viewer_major = rfbProtocolMajorVersion; 11329 - if (server_major == 3 && server_minor >= rfbProtocolMinorVersion) { 11330 - /* the server supports at least the standard protocol 3.7 */ 11331 - viewer_minor = rfbProtocolMinorVersion; 11332 - } else { 11333 - /* any other server version, request the standard 3.3 */ 11334 - viewer_minor = rfbProtocolFallbackMinorVersion; 11335 - } 11336 + readed_pv: 11337 11338 - fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n", 11339 - viewer_major, viewer_minor); 11340 + errorMessageOnReadFailure = True; 11341 11342 - sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor); 11343 + pv[sz_rfbProtocolVersionMsg] = 0; 11344 11345 - if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) 11346 - return False; 11347 + if (strstr(pv, "ID:") == pv) { 11348 + ; 11349 + } else if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) { 11350 + if (strstr(pv, "test") == pv) { 11351 + /* now some hacks for ultraVNC SC III (SSL) ... testA, etc */ 11352 + int i; 11353 + char *se = NULL; 11354 + 11355 + fprintf(stderr,"Trying UltraVNC Single Click III workaround: %s\n", pv); 11356 + for (i=0; i < 7 ; i++) { 11357 + pv[i] = pv[i+5]; 11358 + } 11359 + if (!ReadFromRFBServer(pv+7, 5)) { 11360 + return False; 11361 + } 11362 + 11363 + se = getenv("STUNNEL_EXTRA_OPTS"); 11364 + if (se == NULL) { 11365 + se = getenv("STUNNEL_EXTRA_OPTS_USER"); 11366 + } 11367 + if (se != NULL) { 11368 + if (strstr(se, "options")) { 11369 + if (strstr(se, "ALL") || strstr(se, "DONT_INSERT_EMPTY_FRAGMENTS")) { 11370 + ; /* good */ 11371 + } else { 11372 + se = NULL; 11373 + } 11374 + } else { 11375 + se = NULL; 11376 + } 11377 + } 11378 + if (se == NULL) { 11379 + msgbuf[0] = '\0'; 11380 + strcat(msgbuf, "\n"); 11381 + strcat(msgbuf, "***************************************************************\n"); 11382 + strcat(msgbuf, "To work around UltraVNC SC III SSL dropping after a few minutes\n"); 11383 + strcat(msgbuf, "you may need to set STUNNEL_EXTRA_OPTS_USER='options = ALL'.\n"); 11384 + strcat(msgbuf, "***************************************************************\n"); 11385 + strcat(msgbuf, "\n"); 11386 + wmsg(msgbuf, 0); 11387 + } 11388 + if (strstr(pv, "ID:") == pv) { 11389 + goto check_ID_string; 11390 + } 11391 + if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) == 2) { 11392 + goto ultra_vnc_nonsense; 11393 + } 11394 + } 11395 + sprintf(msgbuf, "Not a valid VNC server: '%s'\n", pv); 11396 + wmsg(msgbuf, 1); 11397 + return False; 11398 + } 11399 11400 - /* Read or select the security type. */ 11401 - if (viewer_minor == rfbProtocolMinorVersion) { 11402 - secType = SelectSecurityType(); 11403 - } else { 11404 - secType = ReadSecurityType(); 11405 - } 11406 - if (secType == rfbSecTypeInvalid) 11407 - return False; 11408 + check_ID_string: 11409 + if (strstr(pv, "ID:") == pv) { 11410 + char tmp[256]; 11411 + fprintf(stderr, "UltraVNC Repeater string detected: %s\n", pv); 11412 + fprintf(stderr, "Pretending to be UltraVNC repeater: reading 250 bytes...\n\n"); 11413 + if (!ReadFromRFBServer(tmp, 250 - 12)) { 11414 + return False; 11415 + } 11416 + if (!ReadFromRFBServer(pv, 12)) { 11417 + return False; 11418 + } 11419 + if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) { 11420 + sprintf(msgbuf,"Not a valid VNC server: '%s'\n", pv); 11421 + wmsg(msgbuf, 1); 11422 + return False; 11423 + } 11424 + } 11425 11426 - switch (secType) { 11427 - case rfbSecTypeNone: 11428 - fprintf(stderr, "No authentication needed\n"); 11429 - break; 11430 - case rfbSecTypeVncAuth: 11431 - if (!AuthenticateVNC()) 11432 - return False; 11433 - break; 11434 - case rfbSecTypeTight: 11435 - tightVncProtocol = True; 11436 - InitCapabilities(); 11437 - if (!SetupTunneling()) 11438 - return False; 11439 - if (!PerformAuthenticationTight()) 11440 - return False; 11441 - break; 11442 - default: /* should never happen */ 11443 - fprintf(stderr, "Internal error: Invalid security type\n"); 11444 - return False; 11445 - } 11446 + ultra_vnc_nonsense: 11447 + fprintf(stderr,"\nProto: %s\n", pv); 11448 11449 - ci.shared = (appData.shareDesktop ? 1 : 0); 11450 + viewer_major = 3; 11451 11452 - if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) 11453 - return False; 11454 + if (appData.rfbVersion != NULL && sscanf(appData.rfbVersion, "%d.%d", &viewer_major, &viewer_minor) == 2) { 11455 + fprintf(stderr,"Setting RFB version to %d.%d from -rfbversion.\n\n", viewer_major, viewer_minor); 11456 11457 - if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg)) 11458 - return False; 11459 + } else if (getenv("SSVNC_RFB_VERSION") != NULL && sscanf(getenv("SSVNC_RFB_VERSION"), "%d.%d", &viewer_major, &viewer_minor) == 2) { 11460 + fprintf(stderr,"Setting RFB version to %d.%d from SSVNC_RFB_VERSION.\n\n", viewer_major, viewer_minor); 11461 + 11462 + } else if (server_major > 3) { 11463 + viewer_minor = 8; 11464 + } else if (server_major == 3 && (server_minor == 14 || server_minor == 16)) { 11465 + /* hack for UltraVNC Single Click. They misuse rfb proto version */ 11466 + fprintf(stderr,"Setting RFB version to 3.3 for UltraVNC Single Click.\n\n"); 11467 + viewer_minor = 3; 11468 + 11469 + } else if (server_major == 3 && server_minor >= 8) { 11470 + /* the server supports at least the standard protocol 3.8 */ 11471 + viewer_minor = 8; 11472 + 11473 + } else if (server_major == 3 && server_minor == 7) { 11474 + /* the server supports at least the standard protocol 3.7 */ 11475 + viewer_minor = 7; 11476 + 11477 + } else { 11478 + /* any other server version, request the standard 3.3 */ 11479 + viewer_minor = 3; 11480 + } 11481 + /* n.b. Apple Remote Desktop uses 003.889, but we should be OK with 3.8 */ 11482 11483 - si.framebufferWidth = Swap16IfLE(si.framebufferWidth); 11484 - si.framebufferHeight = Swap16IfLE(si.framebufferHeight); 11485 - si.format.redMax = Swap16IfLE(si.format.redMax); 11486 - si.format.greenMax = Swap16IfLE(si.format.greenMax); 11487 - si.format.blueMax = Swap16IfLE(si.format.blueMax); 11488 - si.nameLength = Swap32IfLE(si.nameLength); 11489 - 11490 - /* FIXME: Check arguments to malloc() calls. */ 11491 - desktopName = malloc(si.nameLength + 1); 11492 - if (!desktopName) { 11493 - fprintf(stderr, "Error allocating memory for desktop name, %lu bytes\n", 11494 - (unsigned long)si.nameLength); 11495 - return False; 11496 - } 11497 + if (appData.msLogon) { 11498 + if (server_minor == 4) { 11499 + fprintf(stderr,"Setting RFB version to 3.4 for UltraVNC MS Logon.\n\n"); 11500 + viewer_minor = 4; 11501 + } 11502 + } 11503 + if (getenv("SSVNC_ACCEPT_POPUP_SC")) { 11504 + if (server_minor == -4 || server_minor == -6 || server_minor == 14 || server_minor == 16) { 11505 + /* 4 and 6 work too? */ 11506 + viewer_minor = server_minor; 11507 + accept_uvnc = 1; 11508 + fprintf(stderr,"Reset RFB version to 3.%d for UltraVNC SSVNC_ACCEPT_POPUP_SC.\n\n", viewer_minor); 11509 + } 11510 + } 11511 11512 - if (!ReadFromRFBServer(desktopName, si.nameLength)) return False; 11513 + fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n", viewer_major, viewer_minor); 11514 11515 - desktopName[si.nameLength] = 0; 11516 + if (hsfile) { 11517 + int k = 0; 11518 + while (hsparam[k] != NULL) { 11519 + char *str = hsparam[k++]; 11520 + if (strstr(str, "latency=") == str) { 11521 + latency = 1000. * atof(str + strlen("latency=")); 11522 + } 11523 + } 11524 + k = 0; 11525 + while (hsparam[k] != NULL) { 11526 + char *str = hsparam[k++]; 11527 + int v1, v2; 11528 + if (sscanf(str, "viewer=RFB %d.%d\n", &v1, &v2) == 2) { 11529 + viewer_major = v1; 11530 + viewer_minor = v2; 11531 + fprintf(stderr, "\nPre-Handshake set protocol version to: %d.%d Latency: %.2f ms\n", viewer_major, viewer_minor, latency); 11532 + goto end_of_proto_msg; 11533 + } 11534 + } 11535 + } 11536 + sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor); 11537 11538 - fprintf(stderr,"Desktop name \"%s\"\n",desktopName); 11539 + if (!appData.appShare) { 11540 + usleep(100*1000); 11541 + } 11542 + dt = dnow(); 11543 + if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) { 11544 + return False; 11545 + } 11546 11547 - fprintf(stderr,"VNC server default format:\n"); 11548 - PrintPixelFormat(&si.format); 11549 + end_of_proto_msg: 11550 11551 - if (tightVncProtocol) { 11552 - /* Read interaction capabilities (protocol 3.7t) */ 11553 - if (!ReadInteractionCaps()) 11554 - return False; 11555 - } 11556 + if (envsetsec) { 11557 + secType = atoi(getenv("SSVNC_SET_SECURITY_TYPE")); 11558 + goto sec_type; 11559 + } 11560 + if (hsfile) { 11561 + int k = 0; 11562 + while (hsparam[k] != NULL) { 11563 + char *str = hsparam[k++]; 11564 + int st; 11565 + if (sscanf(str, "sectype=%d\n", &st) == 1) { 11566 + secType = st; 11567 + fprintf(stderr, "Pre-Handshake set Security-Type to: %d (%s)\n", st, pr_sec_type(st)); 11568 + if (secType == rfbSecTypeVencrypt) { 11569 + goto sec_type; 11570 + } else if (secType == rfbSecTypeAnonTls) { 11571 + break; 11572 + } 11573 + } 11574 + } 11575 + } 11576 11577 - return True; 11578 + if (accept_uvnc) { 11579 + unsigned int msg_sz = 0; 11580 + unsigned int nimmer = 0; 11581 + char msg[3000]; 11582 + char *msg_buf, *sip = NULL, *sih = NULL; 11583 + 11584 + if (!ReadFromRFBServer((char *) &msg_sz, 4)) { 11585 + return False; 11586 + } 11587 + dt_out_sc = dnow(); 11588 + msg_sz = Swap32IfBE(msg_sz); 11589 + if (msg_sz > 1024) { 11590 + fprintf(stderr, "UVNC msg size too big: %d\n", msg_sz); 11591 + exit(1); 11592 + } 11593 + msg_buf = (char *)calloc(msg_sz + 100, 1); 11594 + if (!ReadFromRFBServer(msg_buf, msg_sz)) { 11595 + return False; 11596 + } 11597 + 11598 + if (0) { 11599 + fprintf(stderr, "msg_buf: "); 11600 + write(2, msg_buf, msg_sz); 11601 + fprintf(stderr, "\n"); 11602 + } 11603 + 11604 + sip = get_peer_ip(rfbsock); 11605 + if (strlen(sip) > 100) sip = "0.0.0.0"; 11606 + sih = ip2host(sip); 11607 + if (strlen(sih) > 300) sih = "unknown"; 11608 + 11609 + sprintf(msg, "\n(LISTEN) Reverse VNC connection from IP: %s\n Hostname: %s\n\n", sip, sih); 11610 + strcat(msg, "UltraVNC Server Message:\n"); 11611 + strcat(msg, msg_buf); 11612 + free(msg_buf); 11613 + strcat(msg, "\n\n"); 11614 + strcat(msg, "Accept or Reject VNC connection?"); 11615 + if (CreateMsg(msg, 2)) { 11616 + nimmer = 1; 11617 + fprintf(stderr, "Accepting connection.\n\n"); 11618 + } else { 11619 + nimmer = 0; 11620 + fprintf(stderr, "Refusing connection.\n\n"); 11621 + } 11622 + if (!WriteExact(rfbsock, (char *) &nimmer, 4)) { 11623 + return False; 11624 + } 11625 + } 11626 + 11627 + /* Read or select the security type. */ 11628 + dt_out = 0.0; 11629 + 11630 + skip_XtUpdateAll = 1; 11631 + if (viewer_minor >= 7 && !accept_uvnc) { 11632 + secType = SelectSecurityType(); 11633 + } else { 11634 + secType = ReadSecurityType(); 11635 + } 11636 + skip_XtUpdateAll = 0; 11637 + 11638 + if (accept_uvnc) { 11639 + dt_out = dt_out_sc; 11640 + } 11641 + 11642 + if (dt > 0.0 && dt_out > dt) { 11643 + latency = (dt_out - dt) * 1000; 11644 + } 11645 + 11646 + fprintf(stderr, "Security-Type: %d (%s) Latency: %.2f ms\n", (int) secType, pr_sec_type(secType), latency); 11647 + if (secType == rfbSecTypeInvalid) { 11648 + return False; 11649 + } 11650 + 11651 + sec_type: 11652 + 11653 + if (hsfile) { 11654 + int subsectype = 0; 11655 + int k = 0; 11656 + while (hsparam[k] != NULL) { 11657 + char *str = hsparam[k++]; 11658 + int st; 11659 + if (sscanf(str, "subtype=%d\n", &st) == 1) { 11660 + subsectype = st; 11661 + fprintf(stderr, "Pre-Handshake set Sub-Security-Type to: %d (%s)\n\n", st, pr_sec_subtype(st)); 11662 + break; 11663 + } 11664 + } 11665 + 11666 + if (!subsectype) { 11667 + ; 11668 + } else if (secType == rfbSecTypeVencrypt) { 11669 + if (subsectype == rfbVencryptTlsNone) { 11670 + anon_dh = 1; 11671 + secType = rfbSecTypeNone; 11672 + } else if (subsectype == rfbVencryptTlsVnc) { 11673 + anon_dh = 1; 11674 + secType = rfbSecTypeVncAuth; 11675 + } else if (subsectype == rfbVencryptTlsPlain) { 11676 + anon_dh = 1; 11677 + secType = rfbSecTypeNone; 11678 + } else if (subsectype == rfbVencryptX509None) { 11679 + secType = rfbSecTypeNone; 11680 + } else if (subsectype == rfbVencryptX509Vnc) { 11681 + secType = rfbSecTypeVncAuth; 11682 + } else if (subsectype == rfbVencryptX509Plain) { 11683 + secType = rfbSecTypeNone; 11684 + } 11685 + if (subsectype == rfbVencryptTlsPlain || subsectype == rfbVencryptX509Plain) { 11686 + usleep(300*1000); 11687 + } 11688 + if (subsectype == rfbVencryptTlsNone || subsectype == rfbVencryptTlsVnc || subsectype == rfbVencryptTlsPlain) { 11689 + char tmp[1000], line[100]; 11690 + tmp[0] = '\0'; 11691 + strcat(tmp, "\n"); 11692 + sprintf(line, "WARNING: Anonymous Diffie-Hellman TLS used (%s),\n", pr_sec_subtype(subsectype)); 11693 + strcat(tmp, line); 11694 + strcat(tmp, "WARNING: there will be *NO* Authentication of the VNC Server.\n"); 11695 + strcat(tmp, "WARNING: I.e. a Man-In-The-Middle attack is possible.\n"); 11696 + strcat(tmp, "WARNING: Configure the server to use X509 certs and verify them.\n\n"); 11697 + wmsg(tmp, 1); 11698 + } 11699 + if (subsectype == rfbVencryptTlsPlain || subsectype == rfbVencryptX509Plain) { 11700 + fprintf(stderr, "\nVeNCrypt Plain (username + passwd) selected.\n\n"); 11701 + if (appData.unixPW != NULL) { 11702 + unixpw(appData.unixPW, 1); 11703 + } else if (getenv("SSVNC_UNIXPW")) { 11704 + unixpw(getenv("SSVNC_UNIXPW"), 1); 11705 + } else { 11706 + unixpw(".", 1); 11707 + } 11708 + } 11709 + } 11710 + } 11711 + 11712 + switch (secType) { 11713 + case rfbSecTypeNone: 11714 + fprintf(stderr, "No VNC authentication needed\n"); 11715 + if (viewer_minor >= 8) { 11716 + CARD32 authResult; 11717 + 11718 + if (!ReadFromRFBServer((char *)&authResult, 4)) { 11719 + return False; 11720 + } 11721 + 11722 + authResult = Swap32IfLE(authResult); 11723 + 11724 + if (authResult == rfbVncAuthOK) { 11725 + fprintf(stderr, "VNC authentication succeeded (%d) for rfbSecTypeNone (RFB 3.8)\n", (int) authResult); 11726 + } else { 11727 + sprintf(msgbuf, "VNC authentication failed (%d) for rfbSecTypeNone (RFB 3.8)\n\n", (int) authResult); 11728 + wmsg(msgbuf, 1); 11729 + return False; 11730 + } 11731 + } 11732 + fprintf(stderr, "\n"); 11733 + break; 11734 + case rfbSecTypeVncAuth: 11735 + if (!AuthenticateVNC()) { 11736 + return False; 11737 + } 11738 + break; 11739 + case rfbSecTypeTight: 11740 + tightVncProtocol = True; 11741 + InitCapabilities(); 11742 + if (!SetupTunneling()) { 11743 + return False; 11744 + } 11745 + if (!PerformAuthenticationTight()) { 11746 + return False; 11747 + } 11748 + break; 11749 + case rfbUltraVncMsLogon: 11750 + if (!AuthUltraVncMsLogon()) { 11751 + return False; 11752 + } 11753 + break; 11754 + default: /* should never happen */ 11755 + sprintf(msgbuf, "Internal error: Invalid security type: %d\n", secType); 11756 + wmsg(msgbuf, 1); 11757 + return False; 11758 + } 11759 + 11760 + connect_time = dnow(); 11761 + 11762 + ci.shared = (appData.shareDesktop ? 1 : 0); 11763 + 11764 + if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) { 11765 + return False; 11766 + } 11767 + 11768 + if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg)) { 11769 + return False; 11770 + } 11771 + 11772 + si.framebufferWidth = Swap16IfLE(si.framebufferWidth); 11773 + si.framebufferHeight = Swap16IfLE(si.framebufferHeight); 11774 + si.format.redMax = Swap16IfLE(si.format.redMax); 11775 + si.format.greenMax = Swap16IfLE(si.format.greenMax); 11776 + si.format.blueMax = Swap16IfLE(si.format.blueMax); 11777 + si.nameLength = Swap32IfLE(si.nameLength); 11778 + 11779 + if (appData.chatOnly) { 11780 + si.framebufferWidth = 32; 11781 + si.framebufferHeight = 32; 11782 + } 11783 + 11784 + /* FIXME: Check arguments to malloc() calls. */ 11785 + desktopName = malloc(si.nameLength + 1); 11786 + memset(desktopName, 0, si.nameLength + 1); 11787 + if (!desktopName) { 11788 + fprintf(stderr, "Error allocating memory for desktop name, %lu bytes\n", 11789 + (unsigned long)si.nameLength); 11790 + return False; 11791 + } 11792 + 11793 + if (!ReadFromRFBServer(desktopName, si.nameLength)) { 11794 + return False; 11795 + } 11796 + 11797 + desktopName[si.nameLength] = 0; 11798 + 11799 + if (appData.appShare) { 11800 + int x_hint, y_hint; 11801 + char *p, *q = NULL; 11802 + p = desktopName; 11803 + while (*p != '\0') { 11804 + char *t = strstr(p, " XY="); 11805 + if (t) q = t; 11806 + p++; 11807 + } 11808 + if (q) { 11809 + int ok = 1; 11810 + p = q + strlen(" XY="); 11811 + while (*p != '\0') { 11812 + if (!strpbrk(p, "0123456789,+-")) { 11813 + ok = 0; 11814 + } 11815 + p++; 11816 + } 11817 + if (ok && sscanf(q+1, "XY=%d,%d", &x_hint, &y_hint) == 2) { 11818 + fprintf(stderr,"Using x11vnc appshare position: %s\n\n", q); 11819 + *q = '\0'; 11820 + appshare_x_hint = x_hint; 11821 + appshare_y_hint = y_hint; 11822 + } 11823 + } 11824 + } 11825 + 11826 + fprintf(stderr,"Desktop name \"%s\"\n\n", desktopName); 11827 + 11828 + fprintf(stderr,"VNC server default format:\n"); 11829 + PrintPixelFormat(&si.format); 11830 + 11831 + if (tightVncProtocol) { 11832 + /* Read interaction capabilities (protocol 3.7t) */ 11833 + if (!ReadInteractionCaps()) { 11834 + return False; 11835 + } 11836 + } 11837 + 11838 + return True; 11839 } 11840 11841 11842 /* 11843 - * Read security type from the server (protocol version 3.3) 11844 + * Read security type from the server (protocol 3.3) 11845 */ 11846 11847 static int 11848 ReadSecurityType(void) 11849 { 11850 - CARD32 secType; 11851 + CARD32 secType; 11852 11853 - /* Read the security type */ 11854 - if (!ReadFromRFBServer((char *)&secType, sizeof(secType))) 11855 - return rfbSecTypeInvalid; 11856 + /* Read the security type */ 11857 + if (!ReadFromRFBServer((char *)&secType, sizeof(secType))) { 11858 + return rfbSecTypeInvalid; 11859 + } 11860 + dt_out = dnow(); 11861 11862 - secType = Swap32IfLE(secType); 11863 + secType = Swap32IfLE(secType); 11864 11865 - if (secType == rfbSecTypeInvalid) { 11866 - ReadConnFailedReason(); 11867 - return rfbSecTypeInvalid; 11868 - } 11869 + if (secType == rfbSecTypeInvalid) { 11870 + ReadConnFailedReason(); 11871 + return rfbSecTypeInvalid; 11872 + } 11873 11874 - if (secType != rfbSecTypeNone && secType != rfbSecTypeVncAuth) { 11875 - fprintf(stderr, "Unknown security type from RFB server: %d\n", 11876 - (int)secType); 11877 - return rfbSecTypeInvalid; 11878 - } 11879 + if (secType == rfbSecTypeNone) { 11880 + ; /* OK */ 11881 + } else if (secType == rfbSecTypeVncAuth) { 11882 + ; /* OK */ 11883 + } else if (secType == rfbUltraVncMsLogon) { 11884 + ; /* OK */ 11885 + } else { 11886 + sprintf(msgbuf, "Unknown security type from RFB server: %d\n", (int)secType); 11887 + wmsg(msgbuf, 1); 11888 + return rfbSecTypeInvalid; 11889 + } 11890 11891 - return (int)secType; 11892 + return (int)secType; 11893 } 11894 11895 11896 /* 11897 - * Select security type from the server's list (protocol version 3.7) 11898 + * Select security type from the server's list (protocol 3.7) 11899 */ 11900 11901 static int 11902 SelectSecurityType(void) 11903 { 11904 - CARD8 nSecTypes; 11905 - char *secTypeNames[] = {"None", "VncAuth"}; 11906 - CARD8 knownSecTypes[] = {rfbSecTypeNone, rfbSecTypeVncAuth}; 11907 - int nKnownSecTypes = sizeof(knownSecTypes); 11908 - CARD8 *secTypes; 11909 - CARD8 secType = rfbSecTypeInvalid; 11910 - int i, j; 11911 - 11912 - /* Read the list of secutiry types. */ 11913 - if (!ReadFromRFBServer((char *)&nSecTypes, sizeof(nSecTypes))) 11914 - return rfbSecTypeInvalid; 11915 - 11916 - if (nSecTypes == 0) { 11917 - ReadConnFailedReason(); 11918 - return rfbSecTypeInvalid; 11919 - } 11920 + CARD8 nSecTypes; 11921 + char *secTypeNames[] = {"None", "VncAuth"}; 11922 + CARD8 knownSecTypes[] = {rfbSecTypeNone, rfbSecTypeVncAuth}; 11923 + int nKnownSecTypes = sizeof(knownSecTypes); 11924 + CARD8 *secTypes; 11925 + CARD8 secType = rfbSecTypeInvalid; 11926 + int i, j; 11927 + 11928 + if (secTypeNames) {} 11929 + 11930 + /* Read the list of security types. */ 11931 + if (!ReadFromRFBServer((char *)&nSecTypes, sizeof(nSecTypes))) { 11932 + return rfbSecTypeInvalid; 11933 + } 11934 + dt_out = dnow(); 11935 11936 - secTypes = malloc(nSecTypes); 11937 - if (!ReadFromRFBServer((char *)secTypes, nSecTypes)) 11938 - return rfbSecTypeInvalid; 11939 - 11940 - /* Find out if the server supports TightVNC protocol extensions */ 11941 - for (j = 0; j < (int)nSecTypes; j++) { 11942 - if (secTypes[j] == rfbSecTypeTight) { 11943 - free(secTypes); 11944 - secType = rfbSecTypeTight; 11945 - if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) 11946 - return rfbSecTypeInvalid; 11947 - fprintf(stderr, "Enabling TightVNC protocol extensions\n"); 11948 - return rfbSecTypeTight; 11949 - } 11950 - } 11951 + if (nSecTypes == 0) { 11952 + ReadConnFailedReason(); 11953 + return rfbSecTypeInvalid; 11954 + } 11955 11956 - /* Find first supported security type */ 11957 - for (j = 0; j < (int)nSecTypes; j++) { 11958 - for (i = 0; i < nKnownSecTypes; i++) { 11959 - if (secTypes[j] == knownSecTypes[i]) { 11960 - secType = secTypes[j]; 11961 - if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) { 11962 - free(secTypes); 11963 - return rfbSecTypeInvalid; 11964 - } 11965 - break; 11966 - } 11967 - } 11968 - if (secType != rfbSecTypeInvalid) break; 11969 - } 11970 + secTypes = malloc(nSecTypes); 11971 + if (!ReadFromRFBServer((char *)secTypes, nSecTypes)) { 11972 + return rfbSecTypeInvalid; 11973 + } 11974 + 11975 + if (getenv("SSVNC_DEBUG_SEC_TYPES")) { 11976 + for (j = 0; j < (int)nSecTypes; j++) { 11977 + fprintf(stderr, "sec-type[%d] %d\n", j, (int) secTypes[j]); 11978 + } 11979 + } 11980 + 11981 + /* Find out if the server supports TightVNC protocol extensions */ 11982 + for (j = 0; j < (int)nSecTypes; j++) { 11983 + if (getenv("VNCVIEWER_NO_SEC_TYPE_TIGHT")) { 11984 + break; 11985 + } 11986 + if (getenv("SSVNC_NO_SEC_TYPE_TIGHT")) { 11987 + break; 11988 + } 11989 +#ifdef TURBOVNC 11990 + break; 11991 +#endif 11992 + if (secTypes[j] == rfbSecTypeTight) { 11993 + free(secTypes); 11994 + secType = rfbSecTypeTight; 11995 + if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) { 11996 + return rfbSecTypeInvalid; 11997 + } 11998 + fprintf(stderr, "Enabling TightVNC protocol extensions\n"); 11999 + return rfbSecTypeTight; 12000 + } 12001 + } 12002 + 12003 + /* Find first supported security type */ 12004 + for (j = 0; j < (int)nSecTypes; j++) { 12005 + for (i = 0; i < nKnownSecTypes; i++) { 12006 + if (secTypes[j] == knownSecTypes[i]) { 12007 + secType = secTypes[j]; 12008 + if (!WriteExact(rfbsock, (char *)&secType, sizeof(secType))) { 12009 + free(secTypes); 12010 + return rfbSecTypeInvalid; 12011 + } 12012 + break; 12013 + } 12014 + } 12015 + if (secType != rfbSecTypeInvalid) { 12016 + break; 12017 + } 12018 + } 12019 12020 - free(secTypes); 12021 + if (secType == rfbSecTypeInvalid) { 12022 + fprintf(stderr, "Server did not offer supported security type:\n"); 12023 + for (j = 0; j < (int)nSecTypes; j++) { 12024 + fprintf(stderr, " sectype[%d] %d\n", j, (int) secTypes[j]); 12025 + } 12026 + } 12027 12028 - if (secType == rfbSecTypeInvalid) 12029 - fprintf(stderr, "Server did not offer supported security type\n"); 12030 + free(secTypes); 12031 12032 - return (int)secType; 12033 + return (int)secType; 12034 } 12035 12036 12037 @@ -451,6 +1141,9 @@ 12038 return True; 12039 } 12040 12041 +static char *restart_session_pw = NULL; 12042 +static int restart_session_len = 0; 12043 + 12044 12045 /* 12046 * Negotiate authentication scheme (protocol version 3.7t) 12047 @@ -459,58 +1152,406 @@ 12048 static Bool 12049 PerformAuthenticationTight(void) 12050 { 12051 - rfbAuthenticationCapsMsg caps; 12052 - CARD32 authScheme; 12053 - int i; 12054 + rfbAuthenticationCapsMsg caps; 12055 + CARD32 authScheme; 12056 + int i; 12057 12058 - /* In the protocol version 3.7t, the server informs us about supported 12059 - authentication schemes. Here we read this information. */ 12060 + /* In the protocol version 3.7t, the server informs us about supported 12061 + authentication schemes. Here we read this information. */ 12062 12063 - if (!ReadFromRFBServer((char *)&caps, sz_rfbAuthenticationCapsMsg)) 12064 - return False; 12065 + if (!ReadFromRFBServer((char *)&caps, sz_rfbAuthenticationCapsMsg)) { 12066 + return False; 12067 + } 12068 12069 - caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes); 12070 + caps.nAuthTypes = Swap32IfLE(caps.nAuthTypes); 12071 12072 - if (!caps.nAuthTypes) { 12073 - fprintf(stderr, "No authentication needed\n"); 12074 - return True; 12075 - } 12076 + if (!caps.nAuthTypes) { 12077 + fprintf(stderr, "No VNC authentication needed\n\n"); 12078 + if (viewer_minor >= 8) { 12079 + CARD32 authResult; 12080 + 12081 + if (!ReadFromRFBServer((char *)&authResult, 4)) { 12082 + return False; 12083 + } 12084 + 12085 + authResult = Swap32IfLE(authResult); 12086 + 12087 + if (authResult == rfbVncAuthOK) { 12088 + fprintf(stderr, "VNC authentication succeeded (%d) for PerformAuthenticationTight rfbSecTypeNone (RFB 3.8)\n", (int) authResult); 12089 + } else { 12090 + sprintf(msgbuf, "VNC authentication failed (%d) for PerformAuthenticationTight rfbSecTypeNone (RFB 3.8)\n\n", (int) authResult); 12091 + wmsg(msgbuf, 1); 12092 + return False; 12093 + } 12094 + } 12095 + return True; 12096 + } 12097 12098 - if (!ReadCapabilityList(authCaps, caps.nAuthTypes)) 12099 - return False; 12100 + if (!ReadCapabilityList(authCaps, caps.nAuthTypes)) { 12101 + return False; 12102 + } 12103 12104 - /* Prefer Unix login authentication if a user name was given. */ 12105 - if (appData.userLogin && CapsIsEnabled(authCaps, rfbAuthUnixLogin)) { 12106 - authScheme = Swap32IfLE(rfbAuthUnixLogin); 12107 - if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) 12108 - return False; 12109 - return AuthenticateUnixLogin(); 12110 - } 12111 + /* Prefer Unix login authentication if a user name was given. */ 12112 + if (appData.userLogin && CapsIsEnabled(authCaps, rfbAuthUnixLogin)) { 12113 + authScheme = Swap32IfLE(rfbAuthUnixLogin); 12114 + if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) { 12115 + return False; 12116 + } 12117 + return AuthenticateUnixLogin(); 12118 + } 12119 12120 - /* Otherwise, try server's preferred authentication scheme. */ 12121 - for (i = 0; i < CapsNumEnabled(authCaps); i++) { 12122 - authScheme = CapsGetByOrder(authCaps, i); 12123 - if (authScheme != rfbAuthUnixLogin && authScheme != rfbAuthVNC) 12124 - continue; /* unknown scheme - cannot use it */ 12125 - authScheme = Swap32IfLE(authScheme); 12126 - if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) 12127 - return False; 12128 - authScheme = Swap32IfLE(authScheme); /* convert it back */ 12129 - if (authScheme == rfbAuthUnixLogin) { 12130 - return AuthenticateUnixLogin(); 12131 - } else if (authScheme == rfbAuthVNC) { 12132 - return AuthenticateVNC(); 12133 - } else { 12134 - /* Should never happen. */ 12135 - fprintf(stderr, "Assertion failed: unknown authentication scheme\n"); 12136 - return False; 12137 - } 12138 - } 12139 + /* Otherwise, try server's preferred authentication scheme. */ 12140 + for (i = 0; i < CapsNumEnabled(authCaps); i++) { 12141 + authScheme = CapsGetByOrder(authCaps, i); 12142 + if (authScheme != rfbAuthUnixLogin && authScheme != rfbAuthVNC) { 12143 + continue; /* unknown scheme - cannot use it */ 12144 + } 12145 + authScheme = Swap32IfLE(authScheme); 12146 + if (!WriteExact(rfbsock, (char *)&authScheme, sizeof(authScheme))) { 12147 + return False; 12148 + } 12149 + authScheme = Swap32IfLE(authScheme); /* convert it back */ 12150 + if (authScheme == rfbAuthUnixLogin) { 12151 + return AuthenticateUnixLogin(); 12152 + } else if (authScheme == rfbAuthVNC) { 12153 + return AuthenticateVNC(); 12154 + } else { 12155 + /* Should never happen. */ 12156 + fprintf(stderr, "Assertion failed: unknown authentication scheme\n"); 12157 + return False; 12158 + } 12159 + } 12160 12161 - fprintf(stderr, "No suitable authentication schemes offered by server\n"); 12162 - return False; 12163 + sprintf(msgbuf, "No suitable authentication schemes offered by server\n"); 12164 + wmsg(msgbuf, 1); 12165 + return False; 12166 +} 12167 + 12168 +#if 0 12169 +unsigned char encPasswd[8]; 12170 +unsigned char encPasswd_MSLOGON[32]; 12171 +char clearPasswd_MSLOGIN[256]; 12172 +static Bool old_ultravnc_mslogon_code(void) { 12173 + char *passwd = NULL; 12174 + CARD8 challenge_mslogon[CHALLENGESIZE_MSLOGON]; 12175 + 12176 + /* code from the old uvnc way (1.0.2?) that would go into AuthenticateVNC() template */ 12177 + 12178 + if (appData.msLogon != NULL) { 12179 + raiseme(1); 12180 + if (!strcmp(appData.msLogon, "1")) { 12181 + char tmp[256]; 12182 + fprintf(stderr, "\nUltraVNC MS Logon Username[@Domain]: "); 12183 + if (fgets(tmp, 256, stdin) == NULL) { 12184 + exit(1); 12185 + } 12186 + appData.msLogon = strdup(tmp); 12187 + } 12188 + passwd = getpass("UltraVNC MS Logon Password: "); 12189 + if (! passwd) { 12190 + exit(1); 12191 + } 12192 + fprintf(stderr, "\n"); 12193 + 12194 + UvncEncryptPasswd_MSLOGON(encPasswd_MSLOGON, passwd); 12195 + } 12196 + if (appData.msLogon) { 12197 + if (!ReadFromRFBServer((char *)challenge_mslogon, CHALLENGESIZE_MSLOGON)) { 12198 + return False; 12199 + } 12200 + } 12201 + if (appData.msLogon) { 12202 + int i; 12203 + char tmp[256]; 12204 + char *q, *domain = "."; 12205 + for (i=0; i < 32; i++) { 12206 + challenge_mslogon[i] = encPasswd_MSLOGON[i] ^ challenge_mslogon[i]; 12207 + } 12208 + q = strchr(appData.msLogon, '@'); 12209 + if (q) { 12210 + *q = '\0'; 12211 + domain = strdup(q+1); 12212 + } 12213 + memset(tmp, 0, sizeof(tmp)); 12214 + strcat(tmp, appData.msLogon); 12215 + if (!WriteExact(rfbsock, tmp, 256)) { 12216 + return False; 12217 + } 12218 + memset(tmp, 0, sizeof(tmp)); 12219 + strcat(tmp, domain); 12220 + if (!WriteExact(rfbsock, tmp, 256)) { 12221 + return False; 12222 + } 12223 + memset(tmp, 0, sizeof(tmp)); 12224 + strcat(tmp, passwd); 12225 + if (!WriteExact(rfbsock, tmp, CHALLENGESIZE_MSLOGON)) { 12226 + return False; 12227 + } 12228 + } 12229 } 12230 +#endif 12231 12232 +static void hexprint(char *label, char *data, int len) { 12233 + int i; 12234 + fprintf(stderr, "%s: ", label); 12235 + for (i=0; i < len; i++) { 12236 + unsigned char c = (unsigned char) data[i]; 12237 + fprintf(stderr, "%02x ", (int) c); 12238 + if ((i+1) % 20 == 0) { 12239 + fprintf(stderr, "\n%s: ", label); 12240 + } 12241 + } 12242 + fprintf(stderr, "\n"); 12243 +} 12244 + 12245 +#define DH_MAX_BITS 31 12246 +static unsigned long long max_dh = ((unsigned long long) 1) << DH_MAX_BITS; 12247 + 12248 +static unsigned long long bytes_to_uint64(char *bytes) { 12249 + unsigned long long result = 0; 12250 + int i; 12251 + 12252 + for (i=0; i < 8; i++) { 12253 + result <<= 8; 12254 + result += (unsigned char) bytes[i]; 12255 + } 12256 + return result; 12257 +} 12258 + 12259 +static void uint64_to_bytes(unsigned long long n, char *bytes) { 12260 + int i; 12261 + 12262 + for (i=0; i < 8; i++) { 12263 + bytes[i] = (unsigned char) (n >> (8 * (7 - i))); 12264 + } 12265 +} 12266 + 12267 +static void try_invert(char *wireuser, char *wirepass, unsigned long long actual_key) { 12268 + if (wireuser || wirepass || actual_key) {} 12269 + return; 12270 +} 12271 + 12272 + 12273 +static unsigned long long XpowYmodN(unsigned long long x, unsigned long long y, unsigned long long N) { 12274 + unsigned long long result = 1; 12275 + unsigned long long oneShift63 = ((unsigned long long) 1) << 63; 12276 + int i; 12277 + 12278 + for (i = 0; i < 64; y <<= 1, i++) { 12279 + result = result * result % N; 12280 + if (y & oneShift63) { 12281 + result = result * x % N; 12282 + } 12283 + } 12284 + return result; 12285 +} 12286 + 12287 +/* 12288 + * UltraVNC MS-Logon authentication (for v1.0.5 and later.) 12289 + */ 12290 + 12291 +/* 12292 + * NOTE: The UltraVNC MS-Logon username and password exchange is 12293 + * VERY insecure. It can be brute forced in ~2e+9 operations. 12294 + * It's not clear we should support it... It is only worth using 12295 + * in an environment where no one is sniffing the network, in which 12296 + * case all of this DH exchange secrecy is unnecessary... 12297 + */ 12298 + 12299 +static Bool AuthUltraVncMsLogon(void) { 12300 + CARD32 authResult; 12301 + char gen[8], mod[8], pub[8], rsp[8]; 12302 + char user[256], passwd[64], *gpw; 12303 + unsigned char key[8]; 12304 + unsigned long long ugen, umod, ursp, upub, uprv, ukey; 12305 + double now = dnow(); 12306 + int db = 0; 12307 + 12308 + if (getenv("SSVNC_DEBUG_MSLOGON")) { 12309 + db = atoi(getenv("SSVNC_DEBUG_MSLOGON")); 12310 + } 12311 + 12312 + fprintf(stderr, "\nAuthUltraVncMsLogon()\n"); 12313 + 12314 + if (!ReadFromRFBServer(gen, sizeof(gen))) { 12315 + return False; 12316 + } 12317 + if (db) hexprint("gen", gen, sizeof(gen)); 12318 + 12319 + if (!ReadFromRFBServer(mod, sizeof(mod))) { 12320 + return False; 12321 + } 12322 + if (db) hexprint("mod", mod, sizeof(mod)); 12323 + 12324 + if (!ReadFromRFBServer(rsp, sizeof(rsp))) { 12325 + return False; 12326 + } 12327 + if (db) hexprint("rsp", rsp, sizeof(rsp)); 12328 + 12329 + ugen = bytes_to_uint64(gen); 12330 + umod = bytes_to_uint64(mod); 12331 + ursp = bytes_to_uint64(rsp); 12332 + 12333 + if (db) { 12334 + fprintf(stderr, "ugen: 0x%016llx %12llu\n", ugen, ugen); 12335 + fprintf(stderr, "umod: 0x%016llx %12llu\n", umod, umod); 12336 + fprintf(stderr, "ursp: 0x%016llx %12llu\n", ursp, ursp); 12337 + } 12338 + 12339 + if (ugen > max_dh) { 12340 + fprintf(stderr, "ugen: too big: 0x%016llx\n", ugen); 12341 + return False; 12342 + } 12343 + 12344 + if (umod > max_dh) { 12345 + fprintf(stderr, "umod: too big: 0x%016llx\n", umod); 12346 + return False; 12347 + } 12348 + 12349 + /* make a random long long: */ 12350 + uprv = 0xffffffff * (now - (unsigned int) now); 12351 + uprv = uprv << 32; 12352 + uprv |= (unsigned long long) urandom(); 12353 + uprv = uprv % max_dh; 12354 + 12355 + if (db) fprintf(stderr, "uprv: 0x%016llx %12llu\n", uprv, uprv); 12356 + 12357 + upub = XpowYmodN(ugen, uprv, umod); 12358 + 12359 + if (db) fprintf(stderr, "upub: 0x%016llx %12llu\n", upub, upub); 12360 + 12361 + uint64_to_bytes(upub, pub); 12362 + 12363 + if (db) hexprint("pub", pub, sizeof(pub)); 12364 + 12365 + if (!WriteExact(rfbsock, (char *)pub, sizeof(pub))) { 12366 + return False; 12367 + } 12368 + if (db) fprintf(stderr, "wrote pub.\n"); 12369 + 12370 + if (ursp > max_dh) { 12371 + fprintf(stderr, "ursp: too big: 0x%016llx\n", ursp); 12372 + return False; 12373 + } 12374 + 12375 + ukey = XpowYmodN(ursp, uprv, umod); 12376 + 12377 + if (db) fprintf(stderr, "ukey: 0x%016llx %12llu\n", ukey, ukey); 12378 + 12379 + if (1) { 12380 + char tmp[10000]; 12381 + tmp[0] = '\0'; 12382 + strcat(tmp, "\n"); 12383 + strcat(tmp, "WARNING: The UltraVNC Diffie-Hellman Key is weak (key < 2e+9, i.e. 31 bits)\n"); 12384 + strcat(tmp, "WARNING: and so an eavesdropper could recover your MS-Logon username and\n"); 12385 + strcat(tmp, "WARNING: password via brute force in a few seconds of CPU time. \n"); 12386 + strcat(tmp, "WARNING: If this connection is NOT being tunnelled through a separate SSL or\n"); 12387 + strcat(tmp, "WARNING: SSH encrypted tunnel, consider things carefully before proceeding...\n"); 12388 + strcat(tmp, "WARNING: Do not enter an important username+password when prompted below if\n"); 12389 + strcat(tmp, "WARNING: there is a risk of an eavesdropper sniffing this connection.\n"); 12390 + strcat(tmp, "WARNING: UltraVNC MSLogon encryption is VERY weak. You've been warned!\n"); 12391 + wmsg(tmp, 1); 12392 + } 12393 + 12394 + uint64_to_bytes(ukey, (char *) key); 12395 + 12396 + if (appData.msLogon == NULL || !strcmp(appData.msLogon, "1")) { 12397 + char tmp[256], *q, *s; 12398 + if (!use_tty()) { 12399 + fprintf(stderr, "\nEnter UltraVNC MS-Logon Username[@Domain] in the popup.\n"); 12400 + s = DoUserDialog(); 12401 + } else { 12402 + raiseme(1); 12403 + fprintf(stderr, "\nUltraVNC MS-Logon Username[@Domain]: "); 12404 + if (fgets(tmp, 256, stdin) == NULL) { 12405 + exit(1); 12406 + } 12407 + s = strdup(tmp); 12408 + } 12409 + q = strchr(s, '\n'); 12410 + if (q) *q = '\0'; 12411 + appData.msLogon = strdup(s); 12412 + } 12413 + 12414 + if (!use_tty()) { 12415 + gpw = DoPasswordDialog(); 12416 + } else { 12417 + raiseme(1); 12418 + gpw = getpass("UltraVNC MS-Logon Password: "); 12419 + } 12420 + if (! gpw) { 12421 + return False; 12422 + } 12423 + fprintf(stderr, "\n"); 12424 + 12425 + memset(user, 0, sizeof(user)); 12426 + strncpy(user, appData.msLogon, 255); 12427 + 12428 + memset(passwd, 0, sizeof(passwd)); 12429 + strncpy(passwd, gpw, 63); 12430 + 12431 + if (db > 1) { 12432 + fprintf(stderr, "user='%s'\n", user); 12433 + fprintf(stderr, "pass='%s'\n", passwd); 12434 + } 12435 + 12436 + UvncEncryptBytes2((unsigned char *) user, sizeof(user), key); 12437 + UvncEncryptBytes2((unsigned char *) passwd, sizeof(passwd), key); 12438 + 12439 + if (getenv("TRY_INVERT")) { 12440 + try_invert(user, passwd, ukey); 12441 + exit(0); 12442 + } 12443 + 12444 + if (db) { 12445 + hexprint("user", user, sizeof(user)); 12446 + hexprint("pass", passwd, sizeof(passwd)); 12447 + } 12448 + 12449 + if (!WriteExact(rfbsock, user, sizeof(user))) { 12450 + return False; 12451 + } 12452 + if (db) fprintf(stderr, "wrote user.\n"); 12453 + 12454 + if (!WriteExact(rfbsock, passwd, sizeof(passwd))) { 12455 + return False; 12456 + } 12457 + if (db) fprintf(stderr, "wrote passwd.\n"); 12458 + 12459 + if (!ReadFromRFBServer((char *) &authResult, 4)) { 12460 + return False; 12461 + } 12462 + authResult = Swap32IfLE(authResult); 12463 + 12464 + if (db) fprintf(stderr, "authResult: %d\n", (int) authResult); 12465 + 12466 + switch (authResult) { 12467 + case rfbVncAuthOK: 12468 + fprintf(stderr, "UVNC MS-Logon authentication succeeded.\n\n"); 12469 + break; 12470 + case rfbVncAuthFailed: 12471 + fprintf(stderr, "UVNC MS-Logon authentication failed.\n"); 12472 + if (viewer_minor >= 8) { 12473 + printFailureReason(); 12474 + } else { 12475 + sprintf(msgbuf, "UVNC MS-Logon authentication failed.\n"); 12476 + wmsg(msgbuf, 1); 12477 + } 12478 + fprintf(stderr, "\n"); 12479 + return False; 12480 + case rfbVncAuthTooMany: 12481 + sprintf(msgbuf, "UVNC MS-Logon authentication failed - too many tries.\n\n"); 12482 + wmsg(msgbuf, 1); 12483 + return False; 12484 + default: 12485 + sprintf(msgbuf, "Unknown UVNC MS-Logon authentication result: %d\n\n", 12486 + (int)authResult); 12487 + wmsg(msgbuf, 1); 12488 + return False; 12489 + } 12490 + 12491 + return True; 12492 +} 12493 12494 /* 12495 * Standard VNC authentication. 12496 @@ -519,80 +1560,119 @@ 12497 static Bool 12498 AuthenticateVNC(void) 12499 { 12500 - CARD32 authScheme, authResult; 12501 - CARD8 challenge[CHALLENGESIZE]; 12502 - char *passwd; 12503 - char buffer[64]; 12504 - char* cstatus; 12505 - int len; 12506 + CARD32 authScheme, authResult; 12507 + CARD8 challenge[CHALLENGESIZE]; 12508 + char *passwd = NULL; 12509 + char buffer[64]; 12510 + char* cstatus; 12511 + int len; 12512 + int restart = 0; 12513 12514 - fprintf(stderr, "Performing standard VNC authentication\n"); 12515 + if (authScheme) {} 12516 12517 - if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) 12518 - return False; 12519 + fprintf(stderr, "\nPerforming standard VNC authentication\n"); 12520 12521 - if (appData.passwordFile) { 12522 - passwd = vncDecryptPasswdFromFile(appData.passwordFile); 12523 - if (!passwd) { 12524 - fprintf(stderr, "Cannot read valid password from file \"%s\"\n", 12525 - appData.passwordFile); 12526 - return False; 12527 - } 12528 - } else if (appData.autoPass) { 12529 - passwd = buffer; 12530 - cstatus = fgets(buffer, sizeof buffer, stdin); 12531 - if (cstatus == NULL) 12532 - buffer[0] = '\0'; 12533 - else 12534 - { 12535 - len = strlen(buffer); 12536 - if (len > 0 && buffer[len - 1] == '\n') 12537 - buffer[len - 1] = '\0'; 12538 - } 12539 - } else if (appData.passwordDialog) { 12540 - passwd = DoPasswordDialog(); 12541 - } else { 12542 - passwd = getpass("Password: "); 12543 - } 12544 + if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) { 12545 + return False; 12546 + } 12547 + 12548 + if (restart_session_pw != NULL) { 12549 + passwd = restart_session_pw; 12550 + restart_session_pw = NULL; 12551 + restart = 1; 12552 + } else if (appData.passwordFile) { 12553 + passwd = vncDecryptPasswdFromFile(appData.passwordFile); 12554 + if (!passwd) { 12555 + sprintf(msgbuf, "Cannot read valid password from file \"%s\"\n", appData.passwordFile); 12556 + wmsg(msgbuf, 1); 12557 + return False; 12558 + } 12559 + } else if (appData.autoPass) { 12560 + passwd = buffer; 12561 + raiseme(1); 12562 + cstatus = fgets(buffer, sizeof buffer, stdin); 12563 + if (cstatus == NULL) { 12564 + buffer[0] = '\0'; 12565 + } else { 12566 + len = strlen(buffer); 12567 + if (len > 0 && buffer[len - 1] == '\n') { 12568 + buffer[len - 1] = '\0'; 12569 + } 12570 + } 12571 + } else if (getenv("VNCVIEWER_PASSWORD")) { 12572 + passwd = strdup(getenv("VNCVIEWER_PASSWORD")); 12573 + } else if (appData.passwordDialog || !use_tty()) { 12574 + passwd = DoPasswordDialog(); 12575 + } else { 12576 + raiseme(1); 12577 + passwd = getpass("VNC Password: "); 12578 + } 12579 12580 - if (!passwd || strlen(passwd) == 0) { 12581 - fprintf(stderr, "Reading password failed\n"); 12582 - return False; 12583 - } 12584 - if (strlen(passwd) > 8) { 12585 - passwd[8] = '\0'; 12586 - } 12587 + if (getenv("VNCVIEWER_PASSWORD")) { 12588 + putenv("VNCVIEWER_PASSWORD=none"); 12589 + } 12590 12591 - vncEncryptBytes(challenge, passwd); 12592 + if (restart) { 12593 +#define EN0 0 12594 +#define DE1 1 12595 + unsigned char s_fixedkey[8] = {23,82,107,6,35,78,88,7}; 12596 + deskey(s_fixedkey, DE1); 12597 + des(passwd, passwd); 12598 + } else { 12599 + if (!passwd || strlen(passwd) == 0) { 12600 + sprintf(msgbuf, "Reading password failed\n\n"); 12601 + wmsg(msgbuf, 1); 12602 + return False; 12603 + } 12604 + if (strlen(passwd) > 8) { 12605 + passwd[8] = '\0'; 12606 + } 12607 + } 12608 12609 - /* Lose the password from memory */ 12610 - memset(passwd, '\0', strlen(passwd)); 12611 + vncEncryptBytes(challenge, passwd); 12612 + 12613 12614 - if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) 12615 - return False; 12616 12617 - if (!ReadFromRFBServer((char *)&authResult, 4)) 12618 - return False; 12619 +#if 0 12620 + /* Lose the password from memory */ 12621 + memset(passwd, '\0', strlen(passwd)); 12622 +#endif 12623 12624 - authResult = Swap32IfLE(authResult); 12625 + if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) { 12626 + return False; 12627 + } 12628 12629 - switch (authResult) { 12630 - case rfbVncAuthOK: 12631 - fprintf(stderr, "VNC authentication succeeded\n"); 12632 - break; 12633 - case rfbVncAuthFailed: 12634 - fprintf(stderr, "VNC authentication failed\n"); 12635 - return False; 12636 - case rfbVncAuthTooMany: 12637 - fprintf(stderr, "VNC authentication failed - too many tries\n"); 12638 - return False; 12639 - default: 12640 - fprintf(stderr, "Unknown VNC authentication result: %d\n", 12641 - (int)authResult); 12642 - return False; 12643 - } 12644 + if (!ReadFromRFBServer((char *)&authResult, 4)) { 12645 + return False; 12646 + } 12647 12648 - return True; 12649 + authResult = Swap32IfLE(authResult); 12650 + 12651 + switch (authResult) { 12652 + case rfbVncAuthOK: 12653 + fprintf(stderr, "VNC authentication succeeded\n\n"); 12654 + break; 12655 + case rfbVncAuthFailed: 12656 + fprintf(stderr, "VNC authentication failed.\n"); 12657 + if (viewer_minor >= 8) { 12658 + printFailureReason(); 12659 + } else { 12660 + sprintf(msgbuf, "VNC authentication failed.\n"); 12661 + wmsg(msgbuf, 1); 12662 + } 12663 + fprintf(stderr, "\n"); 12664 + return False; 12665 + case rfbVncAuthTooMany: 12666 + sprintf(msgbuf, "VNC authentication failed - too many tries\n\n"); 12667 + wmsg(msgbuf, 1); 12668 + return False; 12669 + default: 12670 + sprintf(msgbuf, "Unknown VNC authentication result: %d\n\n", (int)authResult); 12671 + wmsg(msgbuf, 1); 12672 + return False; 12673 + } 12674 + 12675 + return True; 12676 } 12677 12678 /* 12679 @@ -602,68 +1682,77 @@ 12680 static Bool 12681 AuthenticateUnixLogin(void) 12682 { 12683 - CARD32 loginLen, passwdLen, authResult; 12684 - char *login; 12685 - char *passwd; 12686 - struct passwd *ps; 12687 - 12688 - fprintf(stderr, "Performing Unix login-style authentication\n"); 12689 - 12690 - if (appData.userLogin) { 12691 - login = appData.userLogin; 12692 - } else { 12693 - ps = getpwuid(getuid()); 12694 - login = ps->pw_name; 12695 - } 12696 + CARD32 loginLen, passwdLen, authResult; 12697 + char *login; 12698 + char *passwd; 12699 + struct passwd *ps; 12700 + 12701 + fprintf(stderr, "\nPerforming Unix login-style authentication\n"); 12702 + 12703 + if (appData.userLogin) { 12704 + login = appData.userLogin; 12705 + } else { 12706 + ps = getpwuid(getuid()); 12707 + login = ps->pw_name; 12708 + } 12709 12710 - fprintf(stderr, "Using user name \"%s\"\n", login); 12711 + fprintf(stderr, "Using user name \"%s\"\n", login); 12712 12713 - if (appData.passwordDialog) { 12714 - passwd = DoPasswordDialog(); 12715 - } else { 12716 - passwd = getpass("Password: "); 12717 - } 12718 - if (!passwd || strlen(passwd) == 0) { 12719 - fprintf(stderr, "Reading password failed\n"); 12720 - return False; 12721 - } 12722 + if (appData.passwordDialog || !use_tty()) { 12723 + passwd = DoPasswordDialog(); 12724 + } else { 12725 + raiseme(1); 12726 + passwd = getpass("VNC Password: "); 12727 + } 12728 + if (!passwd || strlen(passwd) == 0) { 12729 + fprintf(stderr, "Reading password failed\n"); 12730 + return False; 12731 + } 12732 12733 - loginLen = Swap32IfLE((CARD32)strlen(login)); 12734 - passwdLen = Swap32IfLE((CARD32)strlen(passwd)); 12735 + loginLen = Swap32IfLE((CARD32)strlen(login)); 12736 + passwdLen = Swap32IfLE((CARD32)strlen(passwd)); 12737 12738 - if (!WriteExact(rfbsock, (char *)&loginLen, sizeof(loginLen)) || 12739 - !WriteExact(rfbsock, (char *)&passwdLen, sizeof(passwdLen))) 12740 - return False; 12741 + if (!WriteExact(rfbsock, (char *)&loginLen, sizeof(loginLen)) || 12742 + !WriteExact(rfbsock, (char *)&passwdLen, sizeof(passwdLen))) { 12743 + return False; 12744 + } 12745 12746 - if (!WriteExact(rfbsock, login, strlen(login)) || 12747 - !WriteExact(rfbsock, passwd, strlen(passwd))) 12748 - return False; 12749 + if (!WriteExact(rfbsock, login, strlen(login)) || 12750 + !WriteExact(rfbsock, passwd, strlen(passwd))) { 12751 + return False; 12752 + } 12753 12754 - /* Lose the password from memory */ 12755 - memset(passwd, '\0', strlen(passwd)); 12756 +#if 0 12757 + /* Lose the password from memory */ 12758 + memset(passwd, '\0', strlen(passwd)); 12759 +#endif 12760 12761 - if (!ReadFromRFBServer((char *)&authResult, sizeof(authResult))) 12762 - return False; 12763 + if (!ReadFromRFBServer((char *)&authResult, sizeof(authResult))) { 12764 + return False; 12765 + } 12766 12767 - authResult = Swap32IfLE(authResult); 12768 + authResult = Swap32IfLE(authResult); 12769 12770 - switch (authResult) { 12771 - case rfbVncAuthOK: 12772 - fprintf(stderr, "Authentication succeeded\n"); 12773 - break; 12774 - case rfbVncAuthFailed: 12775 - fprintf(stderr, "Authentication failed\n"); 12776 - return False; 12777 - case rfbVncAuthTooMany: 12778 - fprintf(stderr, "Authentication failed - too many tries\n"); 12779 - return False; 12780 - default: 12781 - fprintf(stderr, "Unknown authentication result: %d\n", 12782 - (int)authResult); 12783 - return False; 12784 - } 12785 + switch (authResult) { 12786 + case rfbVncAuthOK: 12787 + fprintf(stderr, "Authentication succeeded\n\n"); 12788 + break; 12789 + case rfbVncAuthFailed: 12790 + sprintf(msgbuf, "Authentication failed\n\n"); 12791 + wmsg(msgbuf, 1); 12792 + return False; 12793 + case rfbVncAuthTooMany: 12794 + sprintf(msgbuf, "Authentication failed - too many tries\n\n"); 12795 + wmsg(msgbuf, 1); 12796 + return False; 12797 + default: 12798 + sprintf(msgbuf, "Unknown authentication result: %d\n\n", 12799 + (int)authResult); 12800 + wmsg(msgbuf, 1); 12801 + return False; 12802 + } 12803 12804 - return True; 12805 + return True; 12806 } 12807 12808 12809 @@ -675,19 +1764,20 @@ 12810 static Bool 12811 ReadInteractionCaps(void) 12812 { 12813 - rfbInteractionCapsMsg intr_caps; 12814 + rfbInteractionCapsMsg intr_caps; 12815 12816 - /* Read the counts of list items following */ 12817 - if (!ReadFromRFBServer((char *)&intr_caps, sz_rfbInteractionCapsMsg)) 12818 - return False; 12819 - intr_caps.nServerMessageTypes = Swap16IfLE(intr_caps.nServerMessageTypes); 12820 - intr_caps.nClientMessageTypes = Swap16IfLE(intr_caps.nClientMessageTypes); 12821 - intr_caps.nEncodingTypes = Swap16IfLE(intr_caps.nEncodingTypes); 12822 - 12823 - /* Read the lists of server- and client-initiated messages */ 12824 - return (ReadCapabilityList(serverMsgCaps, intr_caps.nServerMessageTypes) && 12825 - ReadCapabilityList(clientMsgCaps, intr_caps.nClientMessageTypes) && 12826 - ReadCapabilityList(encodingCaps, intr_caps.nEncodingTypes)); 12827 + /* Read the counts of list items following */ 12828 + if (!ReadFromRFBServer((char *)&intr_caps, sz_rfbInteractionCapsMsg)) { 12829 + return False; 12830 + } 12831 + intr_caps.nServerMessageTypes = Swap16IfLE(intr_caps.nServerMessageTypes); 12832 + intr_caps.nClientMessageTypes = Swap16IfLE(intr_caps.nClientMessageTypes); 12833 + intr_caps.nEncodingTypes = Swap16IfLE(intr_caps.nEncodingTypes); 12834 + 12835 + /* Read the lists of server- and client-initiated messages */ 12836 + return (ReadCapabilityList(serverMsgCaps, intr_caps.nServerMessageTypes) && 12837 + ReadCapabilityList(clientMsgCaps, intr_caps.nClientMessageTypes) && 12838 + ReadCapabilityList(encodingCaps, intr_caps.nEncodingTypes)); 12839 } 12840 12841 12842 @@ -697,22 +1787,70 @@ 12843 * many records to read from the socket. 12844 */ 12845 12846 -static Bool 12847 -ReadCapabilityList(CapsContainer *caps, int count) 12848 -{ 12849 - rfbCapabilityInfo msginfo; 12850 - int i; 12851 +static Bool 12852 +ReadCapabilityList(CapsContainer *caps, int count) 12853 +{ 12854 + rfbCapabilityInfo msginfo; 12855 + int i; 12856 + 12857 + for (i = 0; i < count; i++) { 12858 + if (!ReadFromRFBServer((char *)&msginfo, sz_rfbCapabilityInfo)) { 12859 + return False; 12860 + } 12861 + msginfo.code = Swap32IfLE(msginfo.code); 12862 + CapsEnable(caps, &msginfo); 12863 + } 12864 + 12865 + return True; 12866 +} 12867 + 12868 12869 - for (i = 0; i < count; i++) { 12870 - if (!ReadFromRFBServer((char *)&msginfo, sz_rfbCapabilityInfo)) 12871 - return False; 12872 - msginfo.code = Swap32IfLE(msginfo.code); 12873 - CapsEnable(caps, &msginfo); 12874 - } 12875 +/* used to have !tunnelSpecified */ 12876 12877 - return True; 12878 +static int guess_compresslevel(void) { 12879 + int n; 12880 + if (latency > 200.0) { 12881 + n = 8; 12882 + } else if (latency > 100.0) { 12883 + n = 7; 12884 + } else if (latency > 60.0) { 12885 + n = 6; 12886 + } else if (latency > 15.0) { 12887 + n = 4; 12888 + } else if (latency > 8.0) { 12889 + n = 2; 12890 + } else if (latency > 0.0) { 12891 + n = 1; 12892 + } else { 12893 + /* no latency measurement */ 12894 + n = 3; 12895 + } 12896 + return n; 12897 } 12898 12899 +static int guess_qualitylevel(void) { 12900 + int n; 12901 + if (latency > 200.0) { 12902 + n = 4; 12903 + } else if (latency > 100.0) { 12904 + n = 5; 12905 + } else if (latency > 60.0) { 12906 + n = 6; 12907 + } else if (latency > 15.0) { 12908 + n = 7; 12909 + } else if (latency > 8.0) { 12910 + n = 8; 12911 + } else if (latency > 0.0) { 12912 + n = 9; 12913 + } else { 12914 + /* no latency measurement */ 12915 + n = 6; 12916 + } 12917 +#ifdef TURBOVNC 12918 + n *= 10; 12919 +#endif 12920 + return n; 12921 +} 12922 12923 /* 12924 * SetFormatAndEncodings. 12925 @@ -729,6 +1867,21 @@ 12926 Bool requestCompressLevel = False; 12927 Bool requestQualityLevel = False; 12928 Bool requestLastRectEncoding = False; 12929 + Bool requestNewFBSizeEncoding = True; 12930 + Bool requestTextChatEncoding = True; 12931 + Bool requestSubsampLevel = False; 12932 + int dsm = 0; 12933 + int tQL, tQLmax = 9; 12934 + static int qlmsg = 0, clmsg = 0; 12935 +#ifdef TURBOVNC 12936 + tQLmax = 100; 12937 +#endif 12938 + 12939 + if (requestTextChatEncoding || requestSubsampLevel || tQL) {} 12940 + 12941 +#if 0 12942 + fprintf(stderr, "SetFormatAndEncodings: sent_FBU state: %2d\n", sent_FBU); 12943 +#endif 12944 12945 spf.type = rfbSetPixelFormat; 12946 spf.format = myFormat; 12947 @@ -736,15 +1889,32 @@ 12948 spf.format.greenMax = Swap16IfLE(spf.format.greenMax); 12949 spf.format.blueMax = Swap16IfLE(spf.format.blueMax); 12950 12951 + 12952 + currentMsg = rfbSetPixelFormat; 12953 if (!WriteExact(rfbsock, (char *)&spf, sz_rfbSetPixelFormatMsg)) 12954 return False; 12955 12956 se->type = rfbSetEncodings; 12957 se->nEncodings = 0; 12958 12959 + if (appData.ultraDSM) { 12960 + dsm = 1; 12961 + } 12962 + 12963 if (appData.encodingsString) { 12964 char *encStr = appData.encodingsString; 12965 int encStrLen; 12966 + if (strchr(encStr, ',')) { 12967 + char *p; 12968 + encStr = strdup(encStr); 12969 + p = encStr; 12970 + while (*p != '\0') { 12971 + if (*p == ',') { 12972 + *p = ' '; 12973 + } 12974 + p++; 12975 + } 12976 + } 12977 do { 12978 char *nextEncStr = strchr(encStr, ' '); 12979 if (nextEncStr) { 12980 @@ -754,50 +1924,102 @@ 12981 encStrLen = strlen(encStr); 12982 } 12983 12984 +if (getenv("DEBUG_SETFORMAT")) { 12985 + fprintf(stderr, "encs: "); 12986 + write(2, encStr, encStrLen); 12987 + fprintf(stderr, "\n"); 12988 +} 12989 + 12990 if (strncasecmp(encStr,"raw",encStrLen) == 0) { 12991 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw); 12992 } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) { 12993 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect); 12994 - } else if (strncasecmp(encStr,"tight",encStrLen) == 0) { 12995 + } else if (strncasecmp(encStr,"tight",encStrLen) == 0 && !dsm) { 12996 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight); 12997 requestLastRectEncoding = True; 12998 - if (appData.compressLevel >= 0 && appData.compressLevel <= 9) 12999 - requestCompressLevel = True; 13000 - if (appData.enableJPEG) 13001 - requestQualityLevel = True; 13002 + if (appData.compressLevel >= 0 && appData.compressLevel <= 9) { 13003 + requestCompressLevel = True; 13004 + } 13005 + if (appData.enableJPEG) { 13006 + requestQualityLevel = True; 13007 + } 13008 +#ifdef TURBOVNC 13009 + requestSubsampLevel = True; 13010 +#endif 13011 } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) { 13012 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile); 13013 - } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) { 13014 + } else if (strncasecmp(encStr,"zlib",encStrLen) == 0 && !dsm) { 13015 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib); 13016 - if (appData.compressLevel >= 0 && appData.compressLevel <= 9) 13017 - requestCompressLevel = True; 13018 - } else if (strncasecmp(encStr,"corre",encStrLen) == 0) { 13019 + if (appData.compressLevel >= 0 && appData.compressLevel <= 9) { 13020 + requestCompressLevel = True; 13021 + } 13022 + } else if (strncasecmp(encStr,"corre",encStrLen) == 0 && !dsm) { 13023 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE); 13024 } else if (strncasecmp(encStr,"rre",encStrLen) == 0) { 13025 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE); 13026 + } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) { 13027 + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZRLE); 13028 +#if DO_ZYWRLE 13029 + } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) { 13030 + int qlevel = appData.qualityLevel; 13031 + if (qlevel < 0 || qlevel > tQLmax) qlevel = guess_qualitylevel(); 13032 + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE); 13033 + requestQualityLevel = True; 13034 + if (qlevel < 3) { 13035 + zywrle_level = 3; 13036 + } else if (qlevel < 6) { 13037 + zywrle_level = 2; 13038 + } else { 13039 + zywrle_level = 1; 13040 + } 13041 +#endif 13042 } else { 13043 fprintf(stderr,"Unknown encoding '%.*s'\n",encStrLen,encStr); 13044 + if (dsm && strstr(encStr, "tight") == encStr) fprintf(stderr, "tight encoding does not yet work with ultraDSM, skipping it.\n"); 13045 + if (dsm && strstr(encStr, "corre") == encStr) fprintf(stderr, "corre encoding does not yet work with ultraDSM, skipping it.\n"); 13046 + if (dsm && strstr(encStr, "zlib" ) == encStr) fprintf(stderr, "zlib encoding does not yet work with ultraDSM, skipping it.\n"); 13047 } 13048 13049 encStr = nextEncStr; 13050 } while (encStr && se->nEncodings < MAX_ENCODINGS); 13051 13052 if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) { 13053 - encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + 13054 - rfbEncodingCompressLevel0); 13055 + ; 13056 + } else if (se->nEncodings < MAX_ENCODINGS) { 13057 + appData.compressLevel = guess_compresslevel(); 13058 + if (clmsg++ == 0) fprintf(stderr, "guessed: -compresslevel %d\n", appData.compressLevel); 13059 } 13060 + encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); 13061 13062 if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) { 13063 - if (appData.qualityLevel < 0 || appData.qualityLevel > 9) 13064 - appData.qualityLevel = 5; 13065 - encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + 13066 - rfbEncodingQualityLevel0); 13067 + if (appData.qualityLevel < 0 || appData.qualityLevel > tQLmax) { 13068 + appData.qualityLevel = guess_qualitylevel(); 13069 + if (qlmsg++ == 0) fprintf(stderr, "guessed: -qualitylevel %d\n", appData.qualityLevel); 13070 + } 13071 + } else if (se->nEncodings < MAX_ENCODINGS) { 13072 + appData.qualityLevel = guess_qualitylevel(); 13073 + if (qlmsg++ == 0) fprintf(stderr, "guessed: -qualitylevel %d\n", appData.qualityLevel); 13074 + } 13075 +#ifdef TURBOVNC 13076 + tQL = appData.qualityLevel / 10; 13077 + if (tQL < 0) tQL = 1; 13078 + if (tQL > 9) tQL = 9; 13079 + encs[se->nEncodings++] = Swap32IfLE(tQL + rfbEncodingQualityLevel0); 13080 + encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbJpegQualityLevel1 - 1); 13081 + if (se->nEncodings < MAX_ENCODINGS && requestSubsampLevel) { 13082 + if (appData.subsampLevel < 0 || appData.subsampLevel > TVNC_SAMPOPT - 1) { 13083 + appData.subsampLevel = TVNC_1X; 13084 + } 13085 + encs[se->nEncodings++] = Swap32IfLE(appData.subsampLevel + rfbJpegSubsamp1X); 13086 } 13087 +#else 13088 + encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbEncodingQualityLevel0); 13089 +#endif 13090 13091 if (appData.useRemoteCursor) { 13092 if (se->nEncodings < MAX_ENCODINGS) 13093 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor); 13094 - if (se->nEncodings < MAX_ENCODINGS) 13095 + if (se->nEncodings < MAX_ENCODINGS && !appData.useX11Cursor) 13096 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); 13097 if (se->nEncodings < MAX_ENCODINGS) 13098 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos); 13099 @@ -806,10 +2028,16 @@ 13100 if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) { 13101 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect); 13102 } 13103 - } 13104 - else { 13105 + 13106 + if (se->nEncodings < MAX_ENCODINGS && requestNewFBSizeEncoding) { 13107 + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize); 13108 + } 13109 + 13110 + } else { 13111 + /* DIFFERENT CASE */ 13112 + 13113 if (SameMachine(rfbsock)) { 13114 - if (!tunnelSpecified) { 13115 + if (!tunnelSpecified && appData.useRawLocal) { 13116 fprintf(stderr,"Same machine: preferring raw encoding\n"); 13117 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw); 13118 } else { 13119 @@ -818,44 +2046,84 @@ 13120 } 13121 13122 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect); 13123 - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight); 13124 + if (!dsm) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight); 13125 + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZRLE); 13126 + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE); 13127 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile); 13128 - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib); 13129 - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE); 13130 + if (!dsm) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib); 13131 + if (!dsm) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE); 13132 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE); 13133 13134 - if (appData.compressLevel >= 0 && appData.compressLevel <= 9) { 13135 - encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + 13136 - rfbEncodingCompressLevel0); 13137 - } else if (!tunnelSpecified) { 13138 - /* If -tunnel option was provided, we assume that server machine is 13139 - not in the local network so we use default compression level for 13140 - tight encoding instead of fast compression. Thus we are 13141 - requesting level 1 compression only if tunneling is not used. */ 13142 - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCompressLevel1); 13143 - } 13144 - 13145 - if (appData.enableJPEG) { 13146 - if (appData.qualityLevel < 0 || appData.qualityLevel > 9) 13147 - appData.qualityLevel = 5; 13148 - encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + 13149 - rfbEncodingQualityLevel0); 13150 + if (!dsm && appData.compressLevel >= 0 && appData.compressLevel <= 9) { 13151 + encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); 13152 + } else { 13153 + /* 13154 + * OUT OF DATE: If -tunnel option was provided, we assume that server machine is 13155 + * not in the local network so we use default compression level for 13156 + * tight encoding instead of fast compression. Thus we are 13157 + * requesting level 1 compression only if tunneling is not used. 13158 + */ 13159 + appData.compressLevel = guess_compresslevel(); 13160 + if (clmsg++ == 0) fprintf(stderr, "guessed: -compresslevel %d\n", appData.compressLevel); 13161 + encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); 13162 + } 13163 + 13164 + if (!dsm && appData.enableJPEG) { 13165 + if (appData.qualityLevel < 0 || appData.qualityLevel > tQLmax) { 13166 + appData.qualityLevel = guess_qualitylevel(); 13167 + if (qlmsg++ == 0) fprintf(stderr, "guessed: -qualitylevel %d\n", appData.qualityLevel); 13168 + } 13169 + 13170 +#ifdef TURBOVNC 13171 + requestSubsampLevel = True; 13172 + tQL = appData.qualityLevel / 10; 13173 + if (tQL < 0) tQL = 1; 13174 + if (tQL > 9) tQL = 9; 13175 + encs[se->nEncodings++] = Swap32IfLE(tQL + rfbEncodingQualityLevel0); 13176 + encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbJpegQualityLevel1 - 1); 13177 + if (se->nEncodings < MAX_ENCODINGS && requestSubsampLevel) { 13178 + if (appData.subsampLevel < 0 || appData.subsampLevel > TVNC_SAMPOPT - 1) { 13179 + appData.subsampLevel = TVNC_1X; 13180 + } 13181 + encs[se->nEncodings++] = Swap32IfLE(appData.subsampLevel + rfbJpegSubsamp1X); 13182 + } 13183 +#else 13184 + encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbEncodingQualityLevel0); 13185 +#endif 13186 + 13187 } 13188 13189 if (appData.useRemoteCursor) { 13190 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor); 13191 - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); 13192 + if (!appData.useX11Cursor) { 13193 + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); 13194 + } 13195 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos); 13196 } 13197 13198 encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect); 13199 + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize); 13200 } 13201 13202 len = sz_rfbSetEncodingsMsg + se->nEncodings * 4; 13203 13204 - se->nEncodings = Swap16IfLE(se->nEncodings); 13205 + if (!appData.ultraDSM) { 13206 + se->nEncodings = Swap16IfLE(se->nEncodings); 13207 13208 - if (!WriteExact(rfbsock, buf, len)) return False; 13209 + if (!WriteExact(rfbsock, buf, len)) return False; 13210 + } else { 13211 + /* for UltraVNC encryption DSM we have to send each encoding separately (why?) */ 13212 + int i, errs = 0, nenc = se->nEncodings; 13213 + 13214 + se->nEncodings = Swap16IfLE(se->nEncodings); 13215 + 13216 + currentMsg = rfbSetEncodings; 13217 + if (!WriteExact(rfbsock, buf, sz_rfbSetEncodingsMsg)) errs++; 13218 + for (i=0; i < nenc; i++) { 13219 + if (!WriteExact(rfbsock, (char *)&encs[i], sizeof(CARD32))) errs++; 13220 + } 13221 + if (errs) return False; 13222 + } 13223 13224 return True; 13225 } 13226 @@ -868,31 +2136,86 @@ 13227 Bool 13228 SendIncrementalFramebufferUpdateRequest() 13229 { 13230 - return SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, 13231 - si.framebufferHeight, True); 13232 + return SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, 13233 + si.framebufferHeight, True); 13234 } 13235 13236 +time_t last_filexfer = 0; 13237 +int delay_filexfer = 3; 13238 +extern void CheckFileXfer(void); 13239 +extern int rfbsock_is_ready(void); 13240 + 13241 + 13242 +static int dyn = -1; 13243 +extern int filexfer_sock; 13244 +extern int filexfer_listen; 13245 13246 /* 13247 * SendFramebufferUpdateRequest. 13248 */ 13249 - 13250 Bool 13251 SendFramebufferUpdateRequest(int x, int y, int w, int h, Bool incremental) 13252 { 13253 - rfbFramebufferUpdateRequestMsg fur; 13254 + rfbFramebufferUpdateRequestMsg fur; 13255 + static int db = -1; 13256 13257 - fur.type = rfbFramebufferUpdateRequest; 13258 - fur.incremental = incremental ? 1 : 0; 13259 - fur.x = Swap16IfLE(x); 13260 - fur.y = Swap16IfLE(y); 13261 - fur.w = Swap16IfLE(w); 13262 - fur.h = Swap16IfLE(h); 13263 + if (db < 0) { 13264 + if (getenv("SSVNC_DEBUG_RECTS")) { 13265 + db = atoi(getenv("SSVNC_DEBUG_RECTS")); 13266 + } else { 13267 + db = 0; 13268 + } 13269 + } 13270 13271 - if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) 13272 - return False; 13273 + if (db) fprintf(stderr, "SendFramebufferUpdateRequest(%d, %d, %d, %d, incremental=%d)\n", x, y, w, h, (int) incremental); 13274 13275 - return True; 13276 + if (dyn < 0) { 13277 + struct stat sb; 13278 + if (getenv("USER") && !strcmp(getenv("USER"), "runge")) { 13279 + if (stat("/tmp/nodyn", &sb) == 0) { 13280 + putenv("NOFTFBUPDATES=1"); 13281 + unlink("/tmp/nodyn"); 13282 + } 13283 + } 13284 + if (getenv("NOFTFBUPDATES")) { 13285 + dyn = 0; 13286 + } else { 13287 + dyn = 1; 13288 + } 13289 + } 13290 + 13291 + if (appData.fileActive && filexfer_sock >= 0) { 13292 + static int first = 1; 13293 + if (first) { 13294 + fprintf(stderr, "SFU: dynamic fb updates during filexfer: %d\n", dyn); 13295 + first = 0; 13296 + } 13297 +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)); 13298 + if (!dyn || time(NULL) < last_filexfer + delay_filexfer) { 13299 + return True; 13300 + } 13301 + } 13302 +if (db > 1) fprintf(stderr, "B sfur: %d %d %d %d\n", x, y, w, h); 13303 + 13304 + fur.type = rfbFramebufferUpdateRequest; 13305 + fur.incremental = incremental ? 1 : 0; 13306 + fur.x = Swap16IfLE(x); 13307 + fur.y = Swap16IfLE(y); 13308 + fur.w = Swap16IfLE(w); 13309 + fur.h = Swap16IfLE(h); 13310 + 13311 + if (incremental) { 13312 + sent_FBU = 1; 13313 + } else { 13314 + sent_FBU = 2; 13315 + } 13316 + 13317 + currentMsg = rfbFramebufferUpdateRequest; 13318 + if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) { 13319 + return False; 13320 + } 13321 + 13322 + return True; 13323 } 13324 13325 13326 @@ -903,19 +2226,38 @@ 13327 Bool 13328 SendPointerEvent(int x, int y, int buttonMask) 13329 { 13330 - rfbPointerEventMsg pe; 13331 + rfbPointerEventMsg pe; 13332 + 13333 + if (appData.fileActive) { 13334 + if (!dyn || time(NULL) < last_filexfer + delay_filexfer) { 13335 +#if 0 13336 + fprintf(stderr, "skip SendPointerEvent: %d - %d\n", last_filexfer, time(NULL)); 13337 +#endif 13338 + return True; 13339 + } 13340 + } 13341 13342 - pe.type = rfbPointerEvent; 13343 - pe.buttonMask = buttonMask; 13344 - if (x < 0) x = 0; 13345 - if (y < 0) y = 0; 13346 - 13347 - if (!appData.useX11Cursor) 13348 - SoftCursorMove(x, y); 13349 - 13350 - pe.x = Swap16IfLE(x); 13351 - pe.y = Swap16IfLE(y); 13352 - return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg); 13353 + pe.type = rfbPointerEvent; 13354 + pe.buttonMask = buttonMask; 13355 + 13356 + if (scale_factor_x > 0.0 && scale_factor_x != 1.0) { 13357 + x /= scale_factor_x; 13358 + } 13359 + if (scale_factor_y > 0.0 && scale_factor_y != 1.0) { 13360 + y /= scale_factor_y; 13361 + } 13362 + 13363 + if (x < 0) x = 0; 13364 + if (y < 0) y = 0; 13365 + 13366 + if (!appData.useX11Cursor) { 13367 + SoftCursorMove(x, y); 13368 + } 13369 + 13370 + pe.x = Swap16IfLE(x); 13371 + pe.y = Swap16IfLE(y); 13372 + currentMsg = rfbPointerEvent; 13373 + return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg); 13374 } 13375 13376 13377 @@ -926,12 +2268,22 @@ 13378 Bool 13379 SendKeyEvent(CARD32 key, Bool down) 13380 { 13381 - rfbKeyEventMsg ke; 13382 + rfbKeyEventMsg ke; 13383 + 13384 + if (appData.fileActive) { 13385 + if (!dyn || time(NULL) < last_filexfer + delay_filexfer) { 13386 +#if 0 13387 + fprintf(stderr, "skip SendPointerEvent: %d - %d\n", last_filexfer, time(NULL)); 13388 +#endif 13389 + return True; 13390 + } 13391 + } 13392 13393 - ke.type = rfbKeyEvent; 13394 - ke.down = down ? 1 : 0; 13395 - ke.key = Swap32IfLE(key); 13396 - return WriteExact(rfbsock, (char *)&ke, sz_rfbKeyEventMsg); 13397 + ke.type = rfbKeyEvent; 13398 + ke.down = down ? 1 : 0; 13399 + ke.key = Swap32IfLE(key); 13400 + currentMsg = rfbKeyEvent; 13401 + return WriteExact(rfbsock, (char *)&ke, sz_rfbKeyEventMsg); 13402 } 13403 13404 13405 @@ -942,281 +2294,1025 @@ 13406 Bool 13407 SendClientCutText(char *str, int len) 13408 { 13409 - rfbClientCutTextMsg cct; 13410 + rfbClientCutTextMsg cct; 13411 + 13412 + if (serverCutText) { 13413 + free(serverCutText); 13414 + } 13415 + serverCutText = NULL; 13416 + 13417 + if (appData.fileActive) { 13418 + if (!dyn || time(NULL) < last_filexfer + delay_filexfer) { 13419 + /* ultravnc java viewer lets this one through. */ 13420 + return True; 13421 + } 13422 + } 13423 + 13424 + if (appData.viewOnly) { 13425 + return True; 13426 + } 13427 13428 - if (serverCutText) 13429 - free(serverCutText); 13430 - serverCutText = NULL; 13431 - 13432 - cct.type = rfbClientCutText; 13433 - cct.length = Swap32IfLE(len); 13434 - return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) && 13435 - WriteExact(rfbsock, str, len)); 13436 + cct.type = rfbClientCutText; 13437 + cct.length = Swap32IfLE((unsigned int) len); 13438 + currentMsg = rfbClientCutText; 13439 + return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) && 13440 + WriteExact(rfbsock, str, len)); 13441 } 13442 13443 +static int ultra_scale = 0; 13444 13445 -/* 13446 - * HandleRFBServerMessage. 13447 - */ 13448 +Bool 13449 +SendServerScale(int nfac) 13450 +{ 13451 + rfbSetScaleMsg ssc; 13452 + if (nfac < 0 || nfac > 100) { 13453 + return True; 13454 + } 13455 + 13456 + ultra_scale = nfac; 13457 + ssc.type = rfbSetScale; 13458 + ssc.scale = nfac; 13459 + currentMsg = rfbSetScale; 13460 + return WriteExact(rfbsock, (char *)&ssc, sz_rfbSetScaleMsg); 13461 +} 13462 13463 Bool 13464 -HandleRFBServerMessage() 13465 +SendServerInput(Bool enabled) 13466 { 13467 - rfbServerToClientMsg msg; 13468 + rfbSetServerInputMsg sim; 13469 13470 - if (!ReadFromRFBServer((char *)&msg, 1)) 13471 - return False; 13472 + sim.type = rfbSetServerInput; 13473 + sim.status = enabled; 13474 + currentMsg = rfbSetServerInput; 13475 + return WriteExact(rfbsock, (char *)&sim, sz_rfbSetServerInputMsg); 13476 +} 13477 13478 - switch (msg.type) { 13479 +Bool 13480 +SendSingleWindow(int x, int y) 13481 +{ 13482 + static int w_old = -1, h_old = -1; 13483 + rfbSetSWMsg sw; 13484 13485 - case rfbSetColourMapEntries: 13486 - { 13487 - int i; 13488 - CARD16 rgb[3]; 13489 - XColor xc; 13490 + fprintf(stderr, "SendSingleWindow: %d %d\n", x, y); 13491 13492 - if (!ReadFromRFBServer(((char *)&msg) + 1, 13493 - sz_rfbSetColourMapEntriesMsg - 1)) 13494 - return False; 13495 + if (x == -1 && y == -1) { 13496 + sw.type = rfbSetSW; 13497 + sw.x = Swap16IfLE(1); 13498 + sw.y = Swap16IfLE(1); 13499 + if (w_old > 0) { 13500 + si.framebufferWidth = w_old; 13501 + si.framebufferHeight = h_old; 13502 + ReDoDesktop(); 13503 + } 13504 + w_old = h_old = -1; 13505 + } else { 13506 + sw.type = rfbSetSW; 13507 + sw.x = Swap16IfLE(x); 13508 + sw.y = Swap16IfLE(y); 13509 + w_old = si.framebufferWidth; 13510 + h_old = si.framebufferHeight; 13511 + 13512 + } 13513 + sw.status = True; 13514 + currentMsg = rfbSetSW; 13515 + return WriteExact(rfbsock, (char *)&sw, sz_rfbSetSWMsg); 13516 +} 13517 13518 - msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); 13519 - msg.scme.nColours = Swap16IfLE(msg.scme.nColours); 13520 +Bool 13521 +SendTextChat(char *str) 13522 +{ 13523 + static int db = -1; 13524 + rfbTextChatMsg chat; 13525 13526 - for (i = 0; i < msg.scme.nColours; i++) { 13527 - if (!ReadFromRFBServer((char *)rgb, 6)) 13528 - return False; 13529 - xc.pixel = msg.scme.firstColour + i; 13530 - xc.red = Swap16IfLE(rgb[0]); 13531 - xc.green = Swap16IfLE(rgb[1]); 13532 - xc.blue = Swap16IfLE(rgb[2]); 13533 - xc.flags = DoRed|DoGreen|DoBlue; 13534 - XStoreColor(dpy, cmap, &xc); 13535 - } 13536 + if (db < 0) { 13537 + if (getenv("SSVNC_DEBUG_CHAT")) { 13538 + db = 1; 13539 + } else { 13540 + db = 0; 13541 + } 13542 + } 13543 + if (!appData.chatActive) { 13544 + SendTextChatOpen(); 13545 + appData.chatActive = True; 13546 + } 13547 13548 - break; 13549 - } 13550 + chat.type = rfbTextChat; 13551 + chat.pad1 = 0; 13552 + chat.pad2 = 0; 13553 + chat.length = (unsigned int) strlen(str); 13554 + if (db) fprintf(stderr, "SendTextChat: %d '%s'\n", (int) chat.length, str); 13555 + chat.length = Swap32IfLE(chat.length); 13556 + if (!WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg)) { 13557 + return False; 13558 + } 13559 + currentMsg = rfbTextChat; 13560 + return WriteExact(rfbsock, str, strlen(str)); 13561 +} 13562 13563 - case rfbFramebufferUpdate: 13564 - { 13565 - rfbFramebufferUpdateRectHeader rect; 13566 - int linesToRead; 13567 - int bytesPerLine; 13568 - int i; 13569 - int usecs; 13570 +extern void raiseme(int force); 13571 13572 - if (!ReadFromRFBServer(((char *)&msg.fu) + 1, 13573 - sz_rfbFramebufferUpdateMsg - 1)) 13574 - return False; 13575 +Bool 13576 +SendTextChatOpen(void) 13577 +{ 13578 + rfbTextChatMsg chat; 13579 13580 - msg.fu.nRects = Swap16IfLE(msg.fu.nRects); 13581 + raiseme(0); 13582 + chat.type = rfbTextChat; 13583 + chat.pad1 = 0; 13584 + chat.pad2 = 0; 13585 + chat.length = Swap32IfLE(rfbTextChatOpen); 13586 + return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg); 13587 +} 13588 13589 - for (i = 0; i < msg.fu.nRects; i++) { 13590 - if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) 13591 - return False; 13592 +Bool 13593 +SendTextChatClose(void) 13594 +{ 13595 + rfbTextChatMsg chat; 13596 + chat.type = rfbTextChat; 13597 + chat.pad1 = 0; 13598 + chat.pad2 = 0; 13599 + chat.length = Swap32IfLE(rfbTextChatClose); 13600 + appData.chatActive = False; 13601 + return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg); 13602 +} 13603 13604 - rect.encoding = Swap32IfLE(rect.encoding); 13605 - if (rect.encoding == rfbEncodingLastRect) 13606 - break; 13607 +Bool 13608 +SendTextChatFinished(void) 13609 +{ 13610 + rfbTextChatMsg chat; 13611 + chat.type = rfbTextChat; 13612 + chat.pad1 = 0; 13613 + chat.pad2 = 0; 13614 + chat.length = Swap32IfLE(rfbTextChatFinished); 13615 + appData.chatActive = False; 13616 + return WriteExact(rfbsock, (char *)&chat, sz_rfbTextChatMsg); 13617 +} 13618 + 13619 +extern int do_format_change; 13620 +extern int do_cursor_change; 13621 +extern double do_fb_update; 13622 +extern void cutover_format_change(void); 13623 + 13624 +double dtime(double *t_old) { 13625 + /* 13626 + * usage: call with 0.0 to initialize, subsequent calls give 13627 + * the time difference since last call. 13628 + */ 13629 + double t_now, dt; 13630 + struct timeval now; 13631 + 13632 + gettimeofday(&now, NULL); 13633 + t_now = now.tv_sec + ( (double) now.tv_usec/1000000. ); 13634 + if (*t_old == 0.0) { 13635 + *t_old = t_now; 13636 + return t_now; 13637 + } 13638 + dt = t_now - *t_old; 13639 + *t_old = t_now; 13640 + return(dt); 13641 +} 13642 + 13643 +/* common dtime() activities: */ 13644 +double dtime0(double *t_old) { 13645 + *t_old = 0.0; 13646 + return dtime(t_old); 13647 +} 13648 + 13649 +double dnow(void) { 13650 + double t; 13651 + return dtime0(&t); 13652 +} 13653 + 13654 +static char fxfer[65536]; 13655 + 13656 +Bool HandleFileXfer(void) { 13657 + unsigned char hdr[12]; 13658 + unsigned int len; 13659 + 13660 + int rfbDirContentRequest = 1; 13661 + int rfbDirPacket = 2; /* Full directory name or full file name. */ 13662 + int rfbFileTransferRequest = 3; 13663 + int rfbFileHeader = 4; 13664 + int rfbFilePacket = 5; /* One slice of the file */ 13665 + int rfbEndOfFile = 6; 13666 + int rfbAbortFileTransfer = 7; 13667 + int rfbFileTransferOffer = 8; 13668 + int rfbFileAcceptHeader = 9; /* The server accepts or rejects the file */ 13669 + int rfbCommand = 10; 13670 + int rfbCommandReturn = 11; 13671 + int rfbFileChecksums = 12; 13672 + 13673 + int rfbRDirContent = 1; /* Request a Server Directory contents */ 13674 + int rfbRDrivesList = 2; /* Request the server's drives list */ 13675 + 13676 + int rfbADirectory = 1; /* Reception of a directory name */ 13677 + int rfbAFile = 2; /* Reception of a file name */ 13678 + int rfbADrivesList = 3; /* Reception of a list of drives */ 13679 + int rfbADirCreate = 4; /* Response to a create dir command */ 13680 + int rfbADirDelete = 5; /* Response to a delete dir command */ 13681 + int rfbAFileCreate = 6; /* Response to a create file command */ 13682 + int rfbAFileDelete = 7; /* Response to a delete file command */ 13683 + 13684 + int rfbCDirCreate = 1; /* Request the server to create the given directory */ 13685 + int rfbCDirDelete = 2; /* Request the server to delete the given directory */ 13686 + int rfbCFileCreate = 3; /* Request the server to create the given file */ 13687 + int rfbCFileDelete = 4; /* Request the server to delete the given file */ 13688 + 13689 + int rfbRErrorUnknownCmd = 1; /* Unknown FileTransfer command. */ 13690 +#define rfbRErrorCmd 0xFFFFFFFF 13691 + 13692 + static int db = -1; 13693 + static int guess_x11vnc = 0; 13694 + 13695 +#if 0 13696 + if (filexfer_sock < 0) { 13697 + return True; 13698 + } 13699 + /* instead, we read and discard the ft msg data. */ 13700 +#endif 13701 + 13702 +/*fprintf(stderr, "In HandleFileXfer\n"); */ 13703 13704 - rect.r.x = Swap16IfLE(rect.r.x); 13705 - rect.r.y = Swap16IfLE(rect.r.y); 13706 - rect.r.w = Swap16IfLE(rect.r.w); 13707 - rect.r.h = Swap16IfLE(rect.r.h); 13708 - 13709 - if (rect.encoding == rfbEncodingXCursor || 13710 - rect.encoding == rfbEncodingRichCursor) { 13711 - if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, 13712 - rect.encoding)) { 13713 - return False; 13714 + if (db < 0) { 13715 + if (getenv("DEBUG_HandleFileXfer")) { 13716 + db = 1; 13717 + } else { 13718 + db = 0; 13719 + } 13720 } 13721 - continue; 13722 - } 13723 13724 - if (rect.encoding == rfbEncodingPointerPos) { 13725 - if (!HandleCursorPos(rect.r.x, rect.r.y)) { 13726 - return False; 13727 + last_filexfer = time(NULL); 13728 + /*fprintf(stderr, "last_filexfer-1: %d\n", last_filexfer); */ 13729 + 13730 + /* load first byte to send to Java be the FT msg number: */ 13731 + hdr[0] = rfbFileTransfer; 13732 + 13733 + /* this is to avoid XtAppProcessEvent() calls induce by our ReadFromRFBServer calls below: */ 13734 + skip_XtUpdateAll = 1; 13735 + if (!ReadFromRFBServer(&hdr[1], 11)) { 13736 + skip_XtUpdateAll = 0; 13737 + return False; 13738 + } 13739 + if (filexfer_sock >= 0) { 13740 + write(filexfer_sock, hdr, 12); 13741 + } else { 13742 + fprintf(stderr, "filexfer_sock closed, discarding 12 bytes\n"); 13743 + } 13744 + if (db) fprintf(stderr, "\n"); 13745 + if (db) fprintf(stderr, "Got rfbFileTransfer hdr\n"); 13746 + if (db > 1) write(2, hdr, 12); 13747 + 13748 + if (db) { 13749 + int i; 13750 + fprintf(stderr, "HFX HDR:"); 13751 + for (i=0; i < 12; i++) { 13752 + fprintf(stderr, " %d", (int) hdr[i]); 13753 + } 13754 + fprintf(stderr, "\n"); 13755 } 13756 - continue; 13757 - } 13758 13759 - if ((rect.r.x + rect.r.w > si.framebufferWidth) || 13760 - (rect.r.y + rect.r.h > si.framebufferHeight)) 13761 - { 13762 - fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n", 13763 - rect.r.w, rect.r.h, rect.r.x, rect.r.y); 13764 - return False; 13765 + if (hdr[1] == rfbEndOfFile) { 13766 + goto read_no_more; 13767 + } else if (hdr[1] == rfbAbortFileTransfer) { 13768 + goto read_no_more; 13769 } 13770 13771 - if (rect.r.h * rect.r.w == 0) { 13772 - fprintf(stderr,"Zero size rect - ignoring\n"); 13773 - continue; 13774 - } 13775 + if (hdr[1] == rfbDirPacket && hdr[3] == rfbADirectory) { 13776 + 13777 + } 13778 + 13779 + len = (hdr[8] << 24) | (hdr[9] << 16) | (hdr[10] << 8) | hdr[11]; 13780 + if (db) fprintf(stderr, "Got rfbFileTransfer: len1 %u\n", len); 13781 + if (len > 0) { 13782 + if (!ReadFromRFBServer(fxfer, len)) { 13783 + skip_XtUpdateAll = 0; 13784 + return False; 13785 + } 13786 + if (db > 1) write(2, fxfer, len); 13787 + if (len >= 12 && hdr[1] == rfbDirPacket) { 13788 + /* try to guess if x11vnc or not... */ 13789 + if (db) { 13790 + int i; 13791 + fprintf(stderr, "HFX DIR PKT (attr, timeL, timeH):"); 13792 + for (i=0; i < 12; i++) { 13793 + fprintf(stderr, " %d", (unsigned char) fxfer[i]); 13794 + } 13795 + fprintf(stderr, "\n"); 13796 + } 13797 + if (hdr[2] == 1) { 13798 + int dattr = (unsigned char) fxfer[0]; 13799 + int timeL1 = (unsigned char) fxfer[4]; 13800 + int timeL2 = (unsigned char) fxfer[5]; 13801 + int timeL3 = (unsigned char) fxfer[6]; 13802 + int timeL4 = (unsigned char) fxfer[7]; 13803 + int timeH1 = (unsigned char) fxfer[8]; 13804 + int timeH2 = (unsigned char) fxfer[9]; 13805 + int timeH3 = (unsigned char) fxfer[10]; 13806 + int timeH4 = (unsigned char) fxfer[11]; 13807 + if (dattr != 0) { 13808 + if (timeH1 == 0 && timeH2 == 0 && timeH3 == 0 && timeH4 == 0) { 13809 + if ((timeL1 != 0 || timeL2 != 0) && timeL3 != 0 && timeL4 != 0) { 13810 + if (!guess_x11vnc) fprintf(stderr, "guessed x11vnc server\n"); 13811 + guess_x11vnc = 1; 13812 + } 13813 + } 13814 + } 13815 + } 13816 + } 13817 + if (db && 0) fprintf(stderr, "\n"); 13818 + if (filexfer_sock >= 0) { 13819 + write(filexfer_sock, fxfer, len); 13820 + } else { 13821 + fprintf(stderr, "filexfer_sock closed, discarding %d bytes\n", len); 13822 + } 13823 + } 13824 + 13825 + len = (hdr[4] << 24) | (hdr[5] << 16) | (hdr[6] << 8) | hdr[7]; 13826 + if (db) fprintf(stderr, "Got rfbFileTransfer: len2 %u\n", len); 13827 + 13828 +#if 0 13829 + if (hdr[1] == rfbFileHeader && len != rfbRErrorCmd) 13830 +#else 13831 + /* the extra 4 bytes get send on rfbRErrorCmd as well. */ 13832 + if (hdr[1] == rfbFileHeader) { 13833 +#endif 13834 + int is_err = 0; 13835 + if (len == rfbRErrorCmd) { 13836 + is_err = 1; 13837 + } 13838 + if (db) fprintf(stderr, "Got rfbFileTransfer: rfbFileHeader\n"); 13839 + if (is_err && guess_x11vnc) { 13840 + fprintf(stderr, "rfbRErrorCmd x11vnc skip read 4 bytes.\n"); 13841 + goto read_no_more; 13842 + } 13843 + len = 4; 13844 + if (!ReadFromRFBServer(fxfer, len)) { 13845 + skip_XtUpdateAll = 0; 13846 + return False; 13847 + } 13848 + if (db > 1) write(2, fxfer, len); 13849 + if (db && 0) fprintf(stderr, "\n"); 13850 + if (is_err) { 13851 + fprintf(stderr, "rfbRErrorCmd skip write 4 bytes.\n"); 13852 + goto read_no_more; 13853 + } 13854 + if (filexfer_sock >= 0) { 13855 + write(filexfer_sock, fxfer, len); 13856 + } else { 13857 + fprintf(stderr, "filexfer_sock closed, discarding %d bytes\n", len); 13858 + } 13859 + } 13860 13861 - /* If RichCursor encoding is used, we should prevent collisions 13862 - between framebuffer updates and cursor drawing operations. */ 13863 - SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h); 13864 + read_no_more: 13865 13866 - switch (rect.encoding) { 13867 + if (filexfer_sock < 0) { 13868 + int stop = 0; 13869 + static time_t last_stop = 0; 13870 +#if 0 13871 + /* this isn't working */ 13872 + if (hdr[1] == rfbFilePacket || hdr[1] == rfbFileHeader) { 13873 + fprintf(stderr, "filexfer_sock closed, trying to abort receive\n"); 13874 + stop = 1; 13875 + } 13876 +#endif 13877 + if (stop && time(NULL) > last_stop+1) { 13878 + unsigned char rpl[12]; 13879 + int k; 13880 + rpl[0] = rfbFileTransfer; 13881 + rpl[1] = rfbAbortFileTransfer; 13882 + for (k=2; k < 12; k++) { 13883 + rpl[k] = 0; 13884 + } 13885 + WriteExact(rfbsock, rpl, 12); 13886 + last_stop = time(NULL); 13887 + } 13888 + } 13889 13890 - case rfbEncodingRaw: 13891 + if (db) fprintf(stderr, "Got rfbFileTransfer done.\n"); 13892 + skip_XtUpdateAll = 0; 13893 13894 - bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8; 13895 - linesToRead = BUFFER_SIZE / bytesPerLine; 13896 + if (db) fprintf(stderr, "CFX: B\n"); 13897 + CheckFileXfer(); 13898 +/*fprintf(stderr, "Out HandleFileXfer\n"); */ 13899 + return True; 13900 +} 13901 13902 - while (rect.r.h > 0) { 13903 - if (linesToRead > rect.r.h) 13904 - linesToRead = rect.r.h; 13905 +/* 13906 + * HandleRFBServerMessage. 13907 + */ 13908 13909 - if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) 13910 - return False; 13911 13912 - CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, 13913 - linesToRead); 13914 +Bool 13915 +HandleRFBServerMessage() 13916 +{ 13917 + static int db = -1; 13918 + rfbServerToClientMsg msg; 13919 13920 - rect.r.h -= linesToRead; 13921 - rect.r.y += linesToRead; 13922 + if (db < 0) { 13923 + if (getenv("DEBUG_RFB_SMSG")) { 13924 + db = 1; 13925 + } else { 13926 + db = 0; 13927 + } 13928 + } 13929 13930 + if (!ReadFromRFBServer((char *)&msg, 1)) { 13931 + return False; 13932 } 13933 - break; 13934 + if (appData.ultraDSM) { 13935 + if (!ReadFromRFBServer((char *)&msg, 1)) { 13936 + return False; 13937 + } 13938 + } 13939 + 13940 +/*fprintf(stderr, "msg.type: %d\n", msg.type); */ 13941 13942 - case rfbEncodingCopyRect: 13943 - { 13944 - rfbCopyRect cr; 13945 - 13946 - if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) 13947 - return False; 13948 - 13949 - cr.srcX = Swap16IfLE(cr.srcX); 13950 - cr.srcY = Swap16IfLE(cr.srcY); 13951 - 13952 - /* If RichCursor encoding is used, we should extend our 13953 - "cursor lock area" (previously set to destination 13954 - rectangle) to the source rectangle as well. */ 13955 - SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h); 13956 - 13957 - if (appData.copyRectDelay != 0) { 13958 - XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, 13959 - rect.r.w, rect.r.h); 13960 - XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, 13961 - rect.r.w, rect.r.h); 13962 - XSync(dpy,False); 13963 - usleep(appData.copyRectDelay * 1000); 13964 - XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, 13965 - rect.r.w, rect.r.h); 13966 - XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, 13967 - rect.r.w, rect.r.h); 13968 + if (msg.type == rfbFileTransfer) { 13969 + return HandleFileXfer(); 13970 } 13971 13972 - XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY, 13973 - rect.r.w, rect.r.h, rect.r.x, rect.r.y); 13974 + switch (msg.type) { 13975 13976 - break; 13977 - } 13978 + case rfbSetColourMapEntries: 13979 + { 13980 + int i; 13981 + CARD16 rgb[3]; 13982 + XColor xc; 13983 13984 - case rfbEncodingRRE: 13985 - { 13986 - switch (myFormat.bitsPerPixel) { 13987 - case 8: 13988 - if (!HandleRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 13989 - return False; 13990 - break; 13991 - case 16: 13992 - if (!HandleRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 13993 - return False; 13994 - break; 13995 - case 32: 13996 - if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 13997 - return False; 13998 - break; 13999 + if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbSetColourMapEntriesMsg - 1)) { 14000 + return False; 14001 } 14002 - break; 14003 - } 14004 14005 - case rfbEncodingCoRRE: 14006 - { 14007 - switch (myFormat.bitsPerPixel) { 14008 - case 8: 14009 - if (!HandleCoRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 14010 - return False; 14011 - break; 14012 - case 16: 14013 - if (!HandleCoRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 14014 - return False; 14015 - break; 14016 - case 32: 14017 - if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 14018 - return False; 14019 - break; 14020 + msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); 14021 + msg.scme.nColours = Swap16IfLE(msg.scme.nColours); 14022 + 14023 + for (i = 0; i < msg.scme.nColours; i++) { 14024 + if (!ReadFromRFBServer((char *)rgb, 6)) { 14025 + return False; 14026 + } 14027 + xc.pixel = msg.scme.firstColour + i; 14028 + xc.red = Swap16IfLE(rgb[0]); 14029 + xc.green = Swap16IfLE(rgb[1]); 14030 + xc.blue = Swap16IfLE(rgb[2]); 14031 + if (appData.useGreyScale) { 14032 + int ave = (xc.red + xc.green + xc.blue)/3; 14033 + xc.red = ave; 14034 + xc.green = ave; 14035 + xc.blue = ave; 14036 + } 14037 + xc.flags = DoRed|DoGreen|DoBlue; 14038 + XStoreColor(dpy, cmap, &xc); 14039 } 14040 + 14041 break; 14042 - } 14043 + } 14044 + 14045 + case rfbFramebufferUpdate: 14046 + { 14047 + rfbFramebufferUpdateRectHeader rect; 14048 + int linesToRead; 14049 + int bytesPerLine; 14050 + int i; 14051 + 14052 + int area_copyrect = 0; 14053 + int area_tight = 0; 14054 + int area_zrle = 0; 14055 + int area_raw = 0; 14056 + static int rdb = -1; 14057 + static int delay_sync = -1; 14058 + static int delay_sync_env = -1; 14059 + int try_delay_sync = 0; 14060 + int cnt_pseudo = 0; 14061 + int cnt_image = 0; 14062 + 14063 + int skip_incFBU = 0; 14064 + 14065 + if (db) fprintf(stderr, "FBU-0: %.6f\n", dnow()); 14066 + if (rdb < 0) { 14067 + if (getenv("SSVNC_DEBUG_RECTS")) { 14068 + rdb = atoi(getenv("SSVNC_DEBUG_RECTS")); 14069 + } else { 14070 + rdb = 0; 14071 + } 14072 + } 14073 + if (delay_sync < 0) { 14074 + if (getenv("SSVNC_DELAY_SYNC")) { 14075 + delay_sync = atoi(getenv("SSVNC_DELAY_SYNC")); 14076 + delay_sync_env = delay_sync; 14077 + } else { 14078 + delay_sync = 0; 14079 + } 14080 + } 14081 + 14082 + sent_FBU = -1; 14083 14084 - case rfbEncodingHextile: 14085 - { 14086 - switch (myFormat.bitsPerPixel) { 14087 - case 8: 14088 - if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 14089 - return False; 14090 - break; 14091 - case 16: 14092 - if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 14093 - return False; 14094 - break; 14095 - case 32: 14096 - if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 14097 - return False; 14098 - break; 14099 + if (appData.pipelineUpdates) { 14100 + /* turbovnc speed idea */ 14101 + XEvent ev; 14102 + memset(&ev, 0, sizeof(ev)); 14103 + ev.xclient.type = ClientMessage; 14104 + ev.xclient.window = XtWindow(desktop); 14105 + ev.xclient.message_type = XA_INTEGER; 14106 + ev.xclient.format = 8; 14107 + strcpy(ev.xclient.data.b, "SendRFBUpdate"); 14108 + XSendEvent(dpy, XtWindow(desktop), False, 0, &ev); 14109 } 14110 - break; 14111 - } 14112 14113 - case rfbEncodingZlib: 14114 - { 14115 - switch (myFormat.bitsPerPixel) { 14116 - case 8: 14117 - if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 14118 - return False; 14119 - break; 14120 - case 16: 14121 - if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 14122 - return False; 14123 - break; 14124 - case 32: 14125 - if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 14126 - return False; 14127 - break; 14128 + if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) { 14129 + return False; 14130 } 14131 - break; 14132 - } 14133 14134 - case rfbEncodingTight: 14135 - { 14136 - switch (myFormat.bitsPerPixel) { 14137 - case 8: 14138 - if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 14139 - return False; 14140 - break; 14141 - case 16: 14142 - if (!HandleTight16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 14143 - return False; 14144 - break; 14145 - case 32: 14146 - if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) 14147 - return False; 14148 - break; 14149 + msg.fu.nRects = Swap16IfLE(msg.fu.nRects); 14150 + 14151 + if (rdb) fprintf(stderr, "Begin rect loop %d\n", msg.fu.nRects); 14152 + 14153 + if (delay_sync) { 14154 + try_delay_sync = 1; 14155 + } else { 14156 + if (delay_sync_env != -1 && delay_sync_env == 0) { 14157 + ; 14158 + } else if (appData.yCrop > 0) { 14159 + ; 14160 + } else if (scale_factor_x > 0.0 && scale_factor_x != 1.0) { 14161 + ; 14162 + } else if (scale_factor_y > 0.0 && scale_factor_y != 1.0) { 14163 + ; 14164 + } else { 14165 + static int msg = 0; 14166 + /* fullScreen? */ 14167 + /* useXserverBackingStore? */ 14168 + /* useX11Cursor & etc? */ 14169 + /* scrollbars? */ 14170 + if (!msg) { 14171 + fprintf(stderr, "enabling 'delay_sync' mode for faster local drawing,\ndisable via env SSVNC_DELAY_SYNC=0 if there are painting errors.\n"); 14172 + msg = 1; 14173 + } 14174 + try_delay_sync = 1; 14175 + } 14176 + } 14177 + if (try_delay_sync) { 14178 + skip_maybe_sync = 1; 14179 + } 14180 +#define STOP_DELAY_SYNC \ 14181 + if (try_delay_sync) { \ 14182 + if (cnt_image && skip_maybe_sync) { \ 14183 + XSync(dpy, False); \ 14184 + } \ 14185 + try_delay_sync = 0; \ 14186 + skip_maybe_sync = 0; \ 14187 } 14188 - break; 14189 - } 14190 14191 - default: 14192 - fprintf(stderr,"Unknown rect encoding %d\n", 14193 - (int)rect.encoding); 14194 - return False; 14195 - } 14196 + for (i = 0; i < msg.fu.nRects; i++) { 14197 + if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) { 14198 + return False; 14199 + } 14200 + 14201 + rect.encoding = Swap32IfLE(rect.encoding); 14202 + if (rect.encoding == rfbEncodingLastRect) { 14203 + break; 14204 + } 14205 + 14206 + rect.r.x = Swap16IfLE(rect.r.x); 14207 + rect.r.y = Swap16IfLE(rect.r.y); 14208 + rect.r.w = Swap16IfLE(rect.r.w); 14209 + rect.r.h = Swap16IfLE(rect.r.h); 14210 + 14211 + if (rdb > 1) fprintf(stderr, "nRects: %d i=%d enc: %d %dx%d+%d+%d\n", msg.fu.nRects, i, (int) rect.encoding, rect.r.w, rect.r.h, rect.r.x, rect.r.y); 14212 + 14213 + if (rect.encoding == rfbEncodingXCursor || rect.encoding == rfbEncodingRichCursor) { 14214 + cnt_pseudo++; 14215 + STOP_DELAY_SYNC 14216 + 14217 + if (db) fprintf(stderr, "FBU-Cur1 %.6f\n", dnow()); 14218 + if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rect.encoding)) { 14219 + return False; 14220 + } 14221 + if (db) fprintf(stderr, "FBU-Cur2 %.6f\n", dnow()); 14222 + continue; 14223 + } 14224 + 14225 + if (rect.encoding == rfbEncodingPointerPos) { 14226 + cnt_pseudo++; 14227 + STOP_DELAY_SYNC 14228 + if (db) fprintf(stderr, "FBU-Pos1 %.6f\n", dnow()); 14229 + if (0) fprintf(stderr, "CursorPos: %d %d / %d %d\n", rect.r.x, rect.r.y, rect.r.w, rect.r.h); 14230 + if (ultra_scale > 0) { 14231 + int f = ultra_scale; 14232 + if (!HandleCursorPos(rect.r.x/f, rect.r.y/f)) { 14233 + return False; 14234 + } 14235 + } else { 14236 + if (!HandleCursorPos(rect.r.x, rect.r.y)) { 14237 + return False; 14238 + } 14239 + } 14240 + if (db) fprintf(stderr, "FBU-Pos2 %.6f\n", dnow()); 14241 + continue; 14242 + } 14243 + if (rect.encoding == rfbEncodingNewFBSize) { 14244 + cnt_pseudo++; 14245 + STOP_DELAY_SYNC 14246 + if (appData.chatOnly) { 14247 + continue; 14248 + } 14249 + fprintf(stderr,"New Size: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); 14250 + si.framebufferWidth = rect.r.w; 14251 + si.framebufferHeight = rect.r.h; 14252 + /*fprintf(stderr, "si: %d %d\n", si.framebufferWidth, si.framebufferHeight); */ 14253 + ReDoDesktop(); 14254 + continue; 14255 + } 14256 + if (rdb) fprintf(stderr,"Rect: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); 14257 + cnt_image++; 14258 + 14259 + if (appData.ultraDSM) { 14260 + /* 14261 + * What a huge mess the UltraVNC DSM plugin is!!! 14262 + * We read and ignore their little "this much data" hint... 14263 + */ 14264 + switch (rect.encoding) 14265 + { 14266 + case rfbEncodingRaw: 14267 + case rfbEncodingRRE: 14268 + case rfbEncodingCoRRE: 14269 + case rfbEncodingHextile: 14270 + /*case rfbEncodingUltra: */ 14271 +/* case rfbEncodingZlib: */ 14272 + /*case rfbEncodingXOR_Zlib: */ 14273 + /*case rfbEncodingXORMultiColor_Zlib: */ 14274 + /*case rfbEncodingXORMonoColor_Zlib: */ 14275 + /*case rfbEncodingSolidColor: */ 14276 + case rfbEncodingTight: 14277 + case rfbEncodingZlibHex: 14278 + case rfbEncodingZRLE: 14279 + case rfbEncodingZYWRLE: 14280 + { 14281 + CARD32 discard; 14282 + ReadFromRFBServer((char *)&discard, sizeof(CARD32)); 14283 + } 14284 + break; 14285 + } 14286 + } 14287 + 14288 + if ((rect.r.x + rect.r.w > si.framebufferWidth) || 14289 + (rect.r.y + rect.r.h > si.framebufferHeight)) { 14290 + if (!appData.chatOnly) { 14291 + fprintf(stderr,"Rect too large: %dx%d at (%d, %d) encoding=%d\n", 14292 + rect.r.w, rect.r.h, rect.r.x, rect.r.y, (int) rect.encoding); 14293 + return False; 14294 + } 14295 + } 14296 + 14297 + if (rect.r.h * rect.r.w == 0) { 14298 + fprintf(stderr,"*** Warning *** Zero size rect: %dx%d+%d+%d encoding=%d\n", 14299 + rect.r.w, rect.r.h, rect.r.x, rect.r.y, (int) rect.encoding); 14300 + if (0) continue; 14301 + } 14302 + 14303 + /* If RichCursor encoding is used, we should prevent collisions 14304 + between framebuffer updates and cursor drawing operations. */ 14305 + if (db) fprintf(stderr, "FBU-SCL1 %.6f\n", dnow()); 14306 + 14307 + SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h); 14308 + 14309 + if (db) fprintf(stderr, "FBU-SCL2 %.6f\n", dnow()); 14310 + 14311 + 14312 + switch (rect.encoding) { 14313 + 14314 + case rfbEncodingRaw: 14315 + 14316 + bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8; 14317 + linesToRead = BUFFER_SIZE / bytesPerLine; 14318 + 14319 + if (db) fprintf(stderr, "Raw: %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); 14320 + area_raw += rect.r.w * rect.r.h; 14321 + 14322 + while (rect.r.h > 0) { 14323 + if (linesToRead > rect.r.h) { 14324 + linesToRead = rect.r.h; 14325 + } 14326 + 14327 + if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead)) { 14328 + return False; 14329 + } 14330 + 14331 + CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w, linesToRead); 14332 + 14333 + rect.r.h -= linesToRead; 14334 + rect.r.y += linesToRead; 14335 + } 14336 + break; 14337 + 14338 + case rfbEncodingCopyRect: 14339 + { 14340 + rfbCopyRect cr; 14341 + 14342 + STOP_DELAY_SYNC 14343 + XSync(dpy, False); 14344 + 14345 + if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) { 14346 + return False; 14347 + } 14348 + if (appData.chatOnly) { 14349 + break; 14350 + } 14351 + 14352 + cr.srcX = Swap16IfLE(cr.srcX); 14353 + cr.srcY = Swap16IfLE(cr.srcY); 14354 + 14355 + if (db) fprintf(stderr, "Copy: %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); 14356 + area_copyrect += rect.r.w * rect.r.h; 14357 + 14358 + /* If RichCursor encoding is used, we should extend our 14359 + "cursor lock area" (previously set to destination 14360 + rectangle) to the source rectangle as well. */ 14361 + 14362 + if (db) fprintf(stderr, "FBU-SCL3 %.6f\n", dnow()); 14363 + 14364 + SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h); 14365 + 14366 + if (db) fprintf(stderr, "FBU-SCL4 %.6f\n", dnow()); 14367 + 14368 + if (appData.copyRectDelay != 0) { 14369 + XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); 14370 + XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); 14371 + XSync(dpy,False); 14372 + usleep(appData.copyRectDelay * 1000); 14373 + XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y, rect.r.w, rect.r.h); 14374 + XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY, rect.r.w, rect.r.h); 14375 + } 14376 + 14377 + if (db) fprintf(stderr, "FBU-CPA1 %.6f\n", dnow()); 14378 + if (!appData.useXserverBackingStore) { 14379 + copy_rect(rect.r.x, rect.r.y, rect.r.w, rect.r.h, cr.srcX, cr.srcY); 14380 + put_image(rect.r.x, rect.r.y, rect.r.x, rect.r.y, rect.r.w, rect.r.h, 0); 14381 + XSync(dpy, False); 14382 + } else { 14383 + XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY, 14384 + rect.r.w, rect.r.h, rect.r.x, rect.r.y); 14385 + } 14386 + if (db) fprintf(stderr, "FBU-CPA2 %.6f\n", dnow()); 14387 + 14388 + break; 14389 + } 14390 + 14391 + case rfbEncodingRRE: 14392 + { 14393 + switch (myFormat.bitsPerPixel) { 14394 + case 8: 14395 + if (!HandleRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14396 + return False; 14397 + } 14398 + break; 14399 + case 16: 14400 + if (!HandleRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14401 + return False; 14402 + } 14403 + break; 14404 + case 32: 14405 + if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14406 + return False; 14407 + } 14408 + break; 14409 + } 14410 + break; 14411 + } 14412 + 14413 + case rfbEncodingCoRRE: 14414 + { 14415 + switch (myFormat.bitsPerPixel) { 14416 + case 8: 14417 + if (!HandleCoRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14418 + return False; 14419 + } 14420 + break; 14421 + case 16: 14422 + if (!HandleCoRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14423 + return False; 14424 + } 14425 + break; 14426 + case 32: 14427 + if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14428 + return False; 14429 + } 14430 + break; 14431 + } 14432 + break; 14433 + } 14434 + 14435 + case rfbEncodingHextile: 14436 + { 14437 + switch (myFormat.bitsPerPixel) { 14438 + case 8: 14439 + if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14440 + return False; 14441 + } 14442 + break; 14443 + case 16: 14444 + if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14445 + return False; 14446 + } 14447 + break; 14448 + case 32: 14449 + if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14450 + return False; 14451 + } 14452 + break; 14453 + } 14454 + break; 14455 + } 14456 + 14457 + case rfbEncodingZlib: 14458 + { 14459 + switch (myFormat.bitsPerPixel) { 14460 + case 8: 14461 + if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14462 + return False; 14463 + } 14464 + break; 14465 + case 16: 14466 + if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14467 + return False; 14468 + } 14469 + break; 14470 + case 32: 14471 + if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14472 + return False; 14473 + } 14474 + break; 14475 + } 14476 + break; 14477 + } 14478 + 14479 + case rfbEncodingTight: 14480 + { 14481 + if (db) fprintf(stderr, "Tight: %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); 14482 + area_tight += rect.r.w * rect.r.h; 14483 + if (db) fprintf(stderr, "FBU-TGH1 %.6f\n", dnow()); 14484 + 14485 + switch (myFormat.bitsPerPixel) { 14486 + case 8: 14487 + if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14488 + return False; 14489 + } 14490 + break; 14491 + case 16: 14492 + if (!HandleTight16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14493 + return False; 14494 + } 14495 + break; 14496 + case 32: 14497 + if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14498 + return False; 14499 + } 14500 + break; 14501 + } 14502 + if (db) fprintf(stderr, "FBU-TGH2 %.6f\n", dnow()); 14503 + break; 14504 + } 14505 + 14506 + /* runge adds zrle and zywrle: */ 14507 + case rfbEncodingZRLE: 14508 +#if DO_ZYWRLE 14509 + zywrle_level = 0; 14510 + case rfbEncodingZYWRLE: 14511 +#endif 14512 + { 14513 + if (db) fprintf(stderr, "ZRLE: %dx%d+%d+%d\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); 14514 + area_zrle += rect.r.w * rect.r.h; 14515 + switch (myFormat.bitsPerPixel) { 14516 + case 8: 14517 + if (!HandleZRLE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14518 + return False; 14519 + } 14520 + break; 14521 + case 16: 14522 + if (myFormat.greenMax > 0x1f) { 14523 + if (!HandleZRLE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14524 + return False; 14525 + } 14526 + } else { 14527 + if (!HandleZRLE15(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14528 + return False; 14529 + } 14530 + } 14531 + break; 14532 + case 32: 14533 + { 14534 + unsigned int maxColor=(myFormat.redMax<<myFormat.redShift)| 14535 + (myFormat.greenMax<<myFormat.greenShift)| 14536 + (myFormat.blueMax<<myFormat.blueShift); 14537 + static int ZRLE32 = -1; 14538 + 14539 + if (ZRLE32 < 0) { 14540 + /* for debugging or workaround e.g. BE display to LE */ 14541 + if (getenv("ZRLE32")) { 14542 + if (strstr(getenv("ZRLE32"), "24Up")) { 14543 + ZRLE32 = 3; 14544 + } else if (strstr(getenv("ZRLE32"), "24Down")) { 14545 + ZRLE32 = 2; 14546 + } else { 14547 + ZRLE32 = 1; 14548 + } 14549 + } else { 14550 + ZRLE32 = 0; 14551 + } 14552 + } 14553 + 14554 +if (db) fprintf(stderr, "maxColor: 0x%x mfbigEnding: %d\n", maxColor, myFormat.bigEndian); 14555 + 14556 + if (ZRLE32 == 1) { 14557 +if (db) fprintf(stderr, "HandleZRLE32\n"); 14558 + if (!HandleZRLE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14559 + return False; 14560 + } 14561 + } else if (ZRLE32 == 2) { 14562 +if (db) fprintf(stderr, "HandleZRLE24Down\n"); 14563 + if (!HandleZRLE24Down(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14564 + return False; 14565 + } 14566 + } else if (ZRLE32 == 3) { 14567 +if (db) fprintf(stderr, "HandleZRLE24Up\n"); 14568 + if (!HandleZRLE24Up(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14569 + return False; 14570 + } 14571 + } else if ((myFormat.bigEndian && (maxColor&0xff)==0) || (!myFormat.bigEndian && (maxColor&0xff000000)==0)) { 14572 +if (db) fprintf(stderr, "HandleZRLE24\n"); 14573 + if (!HandleZRLE24(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14574 + return False; 14575 + } 14576 + } else if (!myFormat.bigEndian && (maxColor&0xff)==0) { 14577 +if (db) fprintf(stderr, "HandleZRLE24Up\n"); 14578 + if (!HandleZRLE24Up(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14579 + return False; 14580 + } 14581 + } else if (myFormat.bigEndian && (maxColor&0xff000000)==0) { 14582 +if (db) fprintf(stderr, "HandleZRLE24Down\n"); 14583 + if (!HandleZRLE24Down(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14584 + return False; 14585 + } 14586 + } else if (!HandleZRLE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) { 14587 + return False; 14588 + } 14589 + break; 14590 + } 14591 + } 14592 + break; 14593 + } 14594 + 14595 + default: 14596 + fprintf(stderr,"Unknown rect encoding %d\n", (int)rect.encoding); 14597 + return False; 14598 + } 14599 14600 - /* Now we may discard "soft cursor locks". */ 14601 - SoftCursorUnlockScreen(); 14602 - } 14603 + /* Now we may discard "soft cursor locks". */ 14604 + if (db) fprintf(stderr, "FBU-SUL1 %.6f\n", dnow()); 14605 + 14606 + SoftCursorUnlockScreen(); 14607 + 14608 + if (db) fprintf(stderr, "FBU-SUL2 %.6f\n", dnow()); 14609 + } 14610 + 14611 + if (try_delay_sync) { 14612 + skip_maybe_sync = 0; 14613 + } 14614 + 14615 + if (1 || area_copyrect) { 14616 + /* we always do this now for some reason... */ 14617 + if (db) fprintf(stderr, "FBU-XSN1 %.6f\n", dnow()); 14618 + XSync(dpy, False); 14619 + if (db) fprintf(stderr, "FBU-XSN2 %.6f\n", dnow()); 14620 + } 14621 + sent_FBU = 0; 14622 + /* 14623 + * we need to be careful since Xt events are processed 14624 + * usually in the middle of FBU. So we do any scheduled ones now 14625 + * which is pretty safe but not absolutely safe. 14626 + */ 14627 + if (do_format_change) { 14628 + cutover_format_change(); 14629 + do_format_change = 0; 14630 + SetVisualAndCmap(); 14631 + SetFormatAndEncodings(); 14632 + if (do_cursor_change) { 14633 + if (do_cursor_change == 1) { 14634 + DesktopCursorOff(); 14635 + } 14636 + do_cursor_change = 0; 14637 + } else { 14638 + SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, 14639 + si.framebufferHeight, False); 14640 + skip_incFBU = 1; 14641 + } 14642 + } 14643 + if (do_fb_update != 0.0) { 14644 + if (dnow() > do_fb_update + 1.1) { 14645 + do_fb_update = 0.0; 14646 + SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, 14647 + si.framebufferHeight, False); 14648 + } 14649 + } 14650 14651 #ifdef MITSHM 14652 /* if using shared memory PutImage, make sure that the X server has 14653 @@ -1224,59 +3320,168 @@ 14654 mainly to avoid copyrect using invalid screen contents - not sure 14655 if we'd need it otherwise. */ 14656 14657 - if (appData.useShm) 14658 - XSync(dpy, False); 14659 + if (appData.useShm) { 14660 + XSync(dpy, False); 14661 + } else 14662 #endif 14663 + { 14664 + /* we do it always now. */ 14665 + XSync(dpy, False); 14666 + } 14667 + 14668 + if (skip_XtUpdate || skip_incFBU) { 14669 + ; 14670 + } else if (appData.pipelineUpdates) { 14671 + ; 14672 + } else if (!SendIncrementalFramebufferUpdateRequest()) { 14673 + return False; 14674 + } 14675 14676 - if (!SendIncrementalFramebufferUpdateRequest()) 14677 - return False; 14678 - 14679 - break; 14680 + break; 14681 } 14682 14683 case rfbBell: 14684 { 14685 - Window toplevelWin; 14686 + Window toplevelWin; 14687 14688 - XBell(dpy, 0); 14689 + if (appData.useBell) { 14690 + XBell(dpy, 0); 14691 + } 14692 + 14693 + if (appData.raiseOnBeep) { 14694 + toplevelWin = XtWindow(toplevel); 14695 + XMapRaised(dpy, toplevelWin); 14696 + } 14697 14698 - if (appData.raiseOnBeep) { 14699 - toplevelWin = XtWindow(toplevel); 14700 - XMapRaised(dpy, toplevelWin); 14701 + break; 14702 } 14703 14704 - break; 14705 - } 14706 + case rfbServerCutText: 14707 + { 14708 + if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbServerCutTextMsg - 1)) { 14709 + return False; 14710 + } 14711 14712 - case rfbServerCutText: 14713 - { 14714 - if (!ReadFromRFBServer(((char *)&msg) + 1, 14715 - sz_rfbServerCutTextMsg - 1)) 14716 - return False; 14717 + msg.sct.length = Swap32IfLE(msg.sct.length); 14718 14719 - msg.sct.length = Swap32IfLE(msg.sct.length); 14720 + if (serverCutText) { 14721 + free(serverCutText); 14722 + } 14723 14724 - if (serverCutText) 14725 - free(serverCutText); 14726 + serverCutText = malloc(msg.sct.length+1); 14727 14728 - serverCutText = malloc(msg.sct.length+1); 14729 + if (!ReadFromRFBServer(serverCutText, msg.sct.length)) { 14730 + return False; 14731 + } 14732 14733 - if (!ReadFromRFBServer(serverCutText, msg.sct.length)) 14734 - return False; 14735 + serverCutText[msg.sct.length] = 0; 14736 14737 - serverCutText[msg.sct.length] = 0; 14738 + newServerCutText = True; 14739 14740 - newServerCutText = True; 14741 + break; 14742 + } 14743 14744 - break; 14745 - } 14746 + case rfbTextChat: 14747 + { 14748 + char *buffer = NULL; 14749 + if (!ReadFromRFBServer(((char *)&msg) + 1, sz_rfbTextChatMsg - 1)) { 14750 + return False; 14751 + } 14752 + msg.tc.length = Swap32IfLE(msg.tc.length); 14753 + switch(msg.tc.length) { 14754 + case rfbTextChatOpen: 14755 + if (appData.termChat) { 14756 + printChat("\n*ChatOpen*\n\nSend: ", True); 14757 + } else { 14758 + printChat("\n*ChatOpen*\n", True); 14759 + } 14760 + appData.chatActive = True; 14761 + break; 14762 + case rfbTextChatClose: 14763 + printChat("\n*ChatClose*\n", False); 14764 + appData.chatActive = False; 14765 + break; 14766 + case rfbTextChatFinished: 14767 + printChat("\n*ChatFinished*\n", False); 14768 + appData.chatActive = False; 14769 + break; 14770 + default: 14771 + buffer = (char *)malloc(msg.tc.length+1); 14772 + if (!ReadFromRFBServer(buffer, msg.tc.length)) { 14773 + free(buffer); 14774 + return False; 14775 + } 14776 + buffer[msg.tc.length] = '\0'; 14777 + appData.chatActive = True; 14778 + GotChatText(buffer, msg.tc.length); 14779 + free(buffer); 14780 + } 14781 + break; 14782 + } 14783 14784 - default: 14785 - fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type); 14786 - return False; 14787 - } 14788 + case rfbResizeFrameBuffer: 14789 + { 14790 + rfbResizeFrameBufferMsg rsmsg; 14791 + if (!ReadFromRFBServer(((char *)&rsmsg) + 1, sz_rfbResizeFrameBufferMsg - 1)) { 14792 + return False; 14793 + } 14794 + si.framebufferWidth = Swap16IfLE(rsmsg.framebufferWidth); 14795 + si.framebufferHeight = Swap16IfLE(rsmsg.framebufferHeight); 14796 + fprintf(stderr,"UltraVNC ReSize: %dx%d\n", si.framebufferWidth, si.framebufferHeight); 14797 + ReDoDesktop(); 14798 + break; 14799 + } 14800 14801 - return True; 14802 + case rfbRestartConnection: 14803 + { 14804 + rfbRestartConnectionMsg rc; 14805 + int len; 14806 + char *rs_str; 14807 + char buf[5] = "\xff\xff\xff\xff"; 14808 + fprintf(stderr, "rfbRestartConnection. type=%d\n", (int) rc.type); 14809 + if (!ReadFromRFBServer((char *)&rc + 1, sz_rfbRestartConnectionMsg - 1)) { 14810 + return False; 14811 + } 14812 + len = Swap32IfLE(rc.length); 14813 + fprintf(stderr, "rfbRestartConnection. pad1=%d\n", (int) rc.pad1); 14814 + fprintf(stderr, "rfbRestartConnection. pad2=%d\n", (int) rc.pad2); 14815 + fprintf(stderr, "rfbRestartConnection. len=%d\n", len); 14816 + if (len) { 14817 + rs_str = (char *)malloc(2*len); 14818 + if (!ReadFromRFBServer(rs_str, len)) { 14819 + return False; 14820 + } 14821 + restart_session_pw = rs_str; 14822 + restart_session_len = len; 14823 + } 14824 + if (!WriteExact(rfbsock, buf, 4)) { 14825 + return False; 14826 + } 14827 + InitialiseRFBConnection(); 14828 + SetVisualAndCmap(); 14829 + SetFormatAndEncodings(); 14830 + DesktopCursorOff(); 14831 + SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False); 14832 + 14833 + break; 14834 + } 14835 + 14836 + default: 14837 + fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type); 14838 + return False; 14839 + } 14840 + 14841 + if (appData.fileActive) { 14842 + if (filexfer_sock < 0 && filexfer_listen < 0) { 14843 + appData.fileActive = False; 14844 + SendFramebufferUpdateRequest(0, 0, 1, 1, False); 14845 + } else { 14846 +/*fprintf(stderr, "CFX: A\n"); */ 14847 + CheckFileXfer(); 14848 + } 14849 + } 14850 + 14851 + return True; 14852 } 14853 14854 14855 @@ -1296,26 +3501,93 @@ 14856 #define CONCAT2(a,b) a##b 14857 #define CONCAT2E(a,b) CONCAT2(a,b) 14858 14859 +#define CONCAT3(a,b,c) a##b##c 14860 +#define CONCAT3E(a,b,c) CONCAT3(a,b,c) 14861 + 14862 +static unsigned char* frameBuffer = NULL; 14863 +static int frameBufferLen = 0; 14864 + 14865 +#ifdef TURBOVNC 14866 +#include "turbovnc/turbojpeg.h" 14867 +tjhandle tjhnd=NULL; 14868 +static char *compressedData = NULL; 14869 +static char *uncompressedData = NULL; 14870 +#define CopyDataToImage CopyDataToScreen 14871 +static void turbovnc_FillRectangle(XGCValues *gcv, int rx, int ry, int rw, int rh) { 14872 + if (!appData.useXserverBackingStore) { 14873 + FillScreen(rx, ry, rw, rh, gcv->foreground); 14874 + } else { 14875 + XChangeGC(dpy, gc, GCForeground, gcv); 14876 + XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); 14877 + } 14878 +} 14879 +static void CopyImageToScreen(int x, int y, int w, int h) { 14880 + put_image(x, y, x, y, w, h, 0); 14881 +} 14882 +#endif 14883 + 14884 #define BPP 8 14885 #include "rre.c" 14886 #include "corre.c" 14887 #include "hextile.c" 14888 #include "zlib.c" 14889 + 14890 +#ifdef TURBOVNC 14891 +#undef FillRectangle 14892 +#define FillRectangle turbovnc_FillRectangle 14893 +#include "turbovnc/tight.c" 14894 +#undef FillRectangle 14895 +#else 14896 #include "tight.c" 14897 +#endif 14898 + 14899 +#include "zrle.c" 14900 #undef BPP 14901 + 14902 #define BPP 16 14903 #include "rre.c" 14904 #include "corre.c" 14905 #include "hextile.c" 14906 #include "zlib.c" 14907 + 14908 +#ifdef TURBOVNC 14909 +#undef FillRectangle 14910 +#define FillRectangle turbovnc_FillRectangle 14911 +#include "turbovnc/tight.c" 14912 +#undef FillRectangle 14913 +#else 14914 #include "tight.c" 14915 +#endif 14916 + 14917 +#include "zrle.c" 14918 +#define REALBPP 15 14919 +#include "zrle.c" 14920 #undef BPP 14921 + 14922 #define BPP 32 14923 #include "rre.c" 14924 #include "corre.c" 14925 #include "hextile.c" 14926 #include "zlib.c" 14927 + 14928 +#ifdef TURBOVNC 14929 +#undef FillRectangle 14930 +#define FillRectangle turbovnc_FillRectangle 14931 +#include "turbovnc/tight.c" 14932 +#undef FillRectangle 14933 +#else 14934 #include "tight.c" 14935 +#endif 14936 + 14937 +#include "zrle.c" 14938 +#define REALBPP 24 14939 +#include "zrle.c" 14940 +#define REALBPP 24 14941 +#define UNCOMP 8 14942 +#include "zrle.c" 14943 +#define REALBPP 24 14944 +#define UNCOMP -8 14945 +#include "zrle.c" 14946 #undef BPP 14947 14948 /* 14949 @@ -1325,23 +3597,27 @@ 14950 static void 14951 ReadConnFailedReason(void) 14952 { 14953 - CARD32 reasonLen; 14954 - char *reason = NULL; 14955 + CARD32 reasonLen; 14956 + char *reason = NULL; 14957 14958 - if (ReadFromRFBServer((char *)&reasonLen, sizeof(reasonLen))) { 14959 - reasonLen = Swap32IfLE(reasonLen); 14960 - if ((reason = malloc(reasonLen)) != NULL && 14961 - ReadFromRFBServer(reason, reasonLen)) { 14962 - fprintf(stderr,"VNC connection failed: %.*s\n", (int)reasonLen, reason); 14963 - free(reason); 14964 - return; 14965 - } 14966 - } 14967 + if (ReadFromRFBServer((char *)&reasonLen, sizeof(reasonLen))) { 14968 + reasonLen = Swap32IfLE(reasonLen); 14969 + if ((reason = malloc(reasonLen)) != NULL && 14970 + ReadFromRFBServer(reason, reasonLen)) { 14971 + int len = (int) reasonLen < sizeof(msgbuf) - 10 ? (int) reasonLen : sizeof(msgbuf) - 10; 14972 + sprintf(msgbuf,"VNC connection failed: %.*s\n", len, reason); 14973 + wmsg(msgbuf, 1); 14974 + free(reason); 14975 + return; 14976 + } 14977 + } 14978 14979 - fprintf(stderr, "VNC connection failed\n"); 14980 + sprintf(msgbuf, "VNC connection failed\n"); 14981 + wmsg(msgbuf, 1); 14982 14983 - if (reason != NULL) 14984 - free(reason); 14985 + if (reason != NULL) { 14986 + free(reason); 14987 + } 14988 } 14989 14990 /* 14991 @@ -1358,9 +3634,9 @@ 14992 " %s significant bit in each byte is leftmost on the screen.\n", 14993 (format->bigEndian ? "Most" : "Least")); 14994 } else { 14995 - fprintf(stderr," %d bits per pixel.\n",format->bitsPerPixel); 14996 + fprintf(stderr," %d bits per pixel. ",format->bitsPerPixel); 14997 if (format->bitsPerPixel != 8) { 14998 - fprintf(stderr," %s significant byte first in each pixel.\n", 14999 + fprintf(stderr,"%s significant byte first in each pixel.\n", 15000 (format->bigEndian ? "Most" : "Least")); 15001 } 15002 if (format->trueColour) { 15003 @@ -1462,4 +3738,3 @@ 15004 15005 cinfo->src = &jpegSrcManager; 15006 } 15007 - 15008 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rre.c vnc_unixsrc/vncviewer/rre.c 15009 --- vnc_unixsrc.orig/vncviewer/rre.c 2000-06-11 08:00:53.000000000 -0400 15010 +++ vnc_unixsrc/vncviewer/rre.c 2008-10-05 15:16:30.000000000 -0400 15011 @@ -29,6 +29,18 @@ 15012 #define HandleRREBPP CONCAT2E(HandleRRE,BPP) 15013 #define CARDBPP CONCAT2E(CARD,BPP) 15014 15015 +#define FillRectangle(x, y, w, h, color) \ 15016 + { \ 15017 + XGCValues _gcv; \ 15018 + _gcv.foreground = color; \ 15019 + if (!appData.useXserverBackingStore) { \ 15020 + FillScreen(x, y, w, h, _gcv.foreground); \ 15021 + } else { \ 15022 + XChangeGC(dpy, gc, GCForeground, &_gcv); \ 15023 + XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \ 15024 + } \ 15025 + } 15026 + 15027 static Bool 15028 HandleRREBPP (int rx, int ry, int rw, int rh) 15029 { 15030 @@ -49,11 +61,19 @@ 15031 #if (BPP == 8) 15032 gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix); 15033 #else 15034 +#if (BPP == 16) 15035 + gcv.foreground = (appData.useBGR565 ? BGR565ToPixel[pix] : pix); 15036 +#else 15037 gcv.foreground = pix; 15038 #endif 15039 +#endif 15040 15041 +#if 0 15042 XChangeGC(dpy, gc, GCForeground, &gcv); 15043 XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); 15044 +#else 15045 + FillRectangle(rx, ry, rw, rh, gcv.foreground); 15046 +#endif 15047 15048 for (i = 0; i < hdr.nSubrects; i++) { 15049 if (!ReadFromRFBServer((char *)&pix, sizeof(pix))) 15050 @@ -70,13 +90,23 @@ 15051 #if (BPP == 8) 15052 gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix); 15053 #else 15054 +#if (BPP == 16) 15055 + gcv.foreground = (appData.useBGR565 ? BGR565ToPixel[pix] : pix); 15056 +#else 15057 gcv.foreground = pix; 15058 #endif 15059 +#endif 15060 15061 +#if 0 15062 XChangeGC(dpy, gc, GCForeground, &gcv); 15063 XFillRectangle(dpy, desktopWin, gc, rx + subrect.x, ry + subrect.y, 15064 subrect.w, subrect.h); 15065 +#else 15066 + FillRectangle(rx + subrect.x, ry + subrect.y, subrect.w, subrect.h, gcv.foreground); 15067 +#endif 15068 } 15069 15070 return True; 15071 } 15072 + 15073 +#undef FillRectangle 15074 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/selection.c vnc_unixsrc/vncviewer/selection.c 15075 --- vnc_unixsrc.orig/vncviewer/selection.c 2004-03-03 04:11:52.000000000 -0500 15076 +++ vnc_unixsrc/vncviewer/selection.c 2010-02-25 23:28:48.000000000 -0500 15077 @@ -43,13 +43,16 @@ 15078 unsigned long* length, int* format); 15079 static void LoseSelection(Widget w, Atom *selection); 15080 15081 -static Bool iAmSelectionOwner = False; 15082 +static Bool PrimarySelectionOwner = False; 15083 +static Bool ClipboardSelectionOwner = False; 15084 static Time prevSelectionTime = 0L; 15085 static Time cutBufferTime = 0L; 15086 15087 #define TIME_LATER(a, b) ((a) != 0 && ((b) == 0 || (INT32)((a) - (b)) > 0)) 15088 15089 15090 +static Atom clipboard_atom = None; 15091 + 15092 /* 15093 * InitialiseSelection() must be called after realizing widgets (because 15094 * otherwise XtGetSelectionValue() fails). We register events on the root 15095 @@ -62,22 +65,28 @@ 15096 * available. 15097 */ 15098 15099 -void 15100 -InitialiseSelection() 15101 -{ 15102 +static int dbg_sel = -1; 15103 + 15104 +void InitialiseSelection() { 15105 #if XtSpecificationRelease >= 6 15106 - XtRegisterDrawable(dpy, DefaultRootWindow(dpy), toplevel); 15107 + XtRegisterDrawable(dpy, DefaultRootWindow(dpy), toplevel); 15108 #else 15109 - _XtRegisterWindow(DefaultRootWindow(dpy), toplevel); 15110 + _XtRegisterWindow(DefaultRootWindow(dpy), toplevel); 15111 #endif 15112 - XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask); 15113 + XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask); 15114 15115 - XtAddRawEventHandler(toplevel, PropertyChangeMask, False, CutBufferChange, 15116 - NULL); 15117 + XtAddRawEventHandler(toplevel, PropertyChangeMask, False, CutBufferChange, NULL); 15118 15119 - XtGetSelectionValue(toplevel, XA_PRIMARY, 15120 + clipboard_atom = XInternAtom(dpy, "CLIPBOARD", False); 15121 + 15122 + XtGetSelectionValue(toplevel, XA_PRIMARY, 15123 XInternAtom(dpy, "TIMESTAMP", False), 15124 GetInitialSelectionTimeCallback, NULL, CurrentTime); 15125 + 15126 + if (dbg_sel < 0) { 15127 + dbg_sel = 0; 15128 + if (getenv("SSVNC_DEBUG_SELECTION")) dbg_sel = 1; 15129 + } 15130 } 15131 15132 15133 @@ -93,13 +102,16 @@ 15134 Atom* selection, Atom* type, XtPointer value, 15135 unsigned long* length, int* format) 15136 { 15137 - if (value && *format == 32 && *length == 1) 15138 - prevSelectionTime = *(CARD32 *)value; 15139 - else 15140 - prevSelectionTime = 0L; 15141 - 15142 - if (value) 15143 - XtFree(value); 15144 + if (value && *format == 32 && *length == 1) { 15145 + prevSelectionTime = *(CARD32 *)value; 15146 + } else { 15147 + prevSelectionTime = 0L; 15148 + } 15149 + 15150 + if (value) { 15151 + XtFree(value); 15152 + } 15153 + if (w || clientData || selection || type || value || length || format) {} 15154 } 15155 15156 15157 @@ -121,26 +133,30 @@ 15158 void 15159 SelectionToVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) 15160 { 15161 - Bool always = False; 15162 + Bool always = appData.sendAlways; 15163 + Atom sendsel = XA_PRIMARY; 15164 15165 - if (*num_params != 0) { 15166 - if (strcmp(params[0],"always") == 0) { 15167 - always = True; 15168 - } else if (strcmp(params[0],"new") == 0) { 15169 - always = False; 15170 - } else { 15171 - fprintf(stderr,"Invalid params: SelectionToVNC(always|new)\n"); 15172 - return; 15173 - } 15174 - } 15175 - 15176 - if (always) { 15177 - XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, 15178 - TimeFromEvent(event)); 15179 - } else { 15180 - XtGetSelectionValue(w, XA_PRIMARY, XInternAtom(dpy, "TIMESTAMP", False), 15181 - GetSelectionTimeCallback, NULL, TimeFromEvent(event)); 15182 - } 15183 + if (*num_params != 0) { 15184 + if (strcmp(params[0],"always") == 0) { 15185 + always = True; 15186 + } else if (strcmp(params[0],"new") == 0) { 15187 + always = False; 15188 + } else { 15189 + fprintf(stderr,"Invalid params: SelectionToVNC(always|new)\n"); 15190 + return; 15191 + } 15192 + } 15193 + if (appData.sendClipboard && clipboard_atom != None) { 15194 + sendsel = clipboard_atom; 15195 + } 15196 + if (dbg_sel) fprintf(stderr, "SelectionToVNC %s\n", sendsel == XA_PRIMARY ? "PRIMARY" : "CLIPBOARD"); 15197 + 15198 + if (always) { 15199 + XtGetSelectionValue(w, sendsel, XA_STRING, GetSelectionCallback, NULL, TimeFromEvent(event)); 15200 + } else { 15201 + XtGetSelectionValue(w, sendsel, XInternAtom(dpy, "TIMESTAMP", False), GetSelectionTimeCallback, NULL, TimeFromEvent(event)); 15202 + } 15203 + if (w || event || params || num_params) {} 15204 } 15205 15206 15207 @@ -158,10 +174,13 @@ 15208 int len = *length; 15209 char *str = (char *)value; 15210 15211 - if (str) 15212 - SendClientCutText(str, len); 15213 - else 15214 - SendCutBuffer(); 15215 + if (str) { 15216 + if (dbg_sel) fprintf(stderr, "SendClientCutText len: %d\n", len); 15217 + SendClientCutText(str, len); 15218 + } else if (!getenv("VNCVIEWER_NO_CUTBUFFER")) { 15219 + SendCutBuffer(); 15220 + } 15221 + if (w || clientData || selection || type || value || length || format) {} 15222 } 15223 15224 15225 @@ -180,26 +199,24 @@ 15226 Atom* type, XtPointer value, unsigned long* length, 15227 int* format) 15228 { 15229 - if (value && *format == 32 && *length == 1) { 15230 + if (value && *format == 32 && *length == 1) { 15231 + Time t = *(CARD32 *)value; 15232 15233 - Time t = *(CARD32 *)value; 15234 - 15235 - if (TIME_LATER(t, prevSelectionTime)) { 15236 - prevSelectionTime = t; 15237 - XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, 15238 - CurrentTime); 15239 - } 15240 - 15241 - } else { 15242 - 15243 - if (TIME_LATER(cutBufferTime, prevSelectionTime)) { 15244 - prevSelectionTime = cutBufferTime; 15245 - SendCutBuffer(); 15246 - } 15247 - } 15248 - 15249 - if (value) 15250 - XtFree(value); 15251 + if (TIME_LATER(t, prevSelectionTime)) { 15252 + prevSelectionTime = t; 15253 + XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, CurrentTime); 15254 + } 15255 + } else if (!getenv("VNCVIEWER_NO_CUTBUFFER")) { 15256 + if (TIME_LATER(cutBufferTime, prevSelectionTime)) { 15257 + prevSelectionTime = cutBufferTime; 15258 + SendCutBuffer(); 15259 + } 15260 + } 15261 + 15262 + if (value) { 15263 + XtFree(value); 15264 + } 15265 + if (w || clientData || selection || type || value || length || format) {} 15266 } 15267 15268 15269 @@ -209,16 +226,17 @@ 15270 */ 15271 15272 static void 15273 -SendCutBuffer() 15274 -{ 15275 - char *str; 15276 - int len; 15277 +SendCutBuffer() { 15278 + char *str; 15279 + int len; 15280 15281 - str = XFetchBytes(dpy, &len); 15282 - if (!str) return; 15283 + if (dbg_sel) fprintf(stderr, "SendCutBuffer len: %d\n", len); 15284 15285 - SendClientCutText(str, len); 15286 - XFree(str); 15287 + str = XFetchBytes(dpy, &len); 15288 + if (!str) return; 15289 + 15290 + SendClientCutText(str, len); 15291 + XFree(str); 15292 } 15293 15294 15295 @@ -230,10 +248,12 @@ 15296 static void 15297 CutBufferChange(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont) 15298 { 15299 - if (ev->type != PropertyNotify || ev->xproperty.atom != XA_CUT_BUFFER0) 15300 - return; 15301 + if (ev->type != PropertyNotify || ev->xproperty.atom != XA_CUT_BUFFER0) { 15302 + return; 15303 + } 15304 15305 - cutBufferTime = ev->xproperty.time; 15306 + cutBufferTime = ev->xproperty.time; 15307 + if (w || ptr || cont) {} 15308 } 15309 15310 15311 @@ -249,36 +269,69 @@ 15312 void 15313 SelectionFromVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) 15314 { 15315 - Bool always = False; 15316 - Time t = TimeFromEvent(event); 15317 - 15318 - if (*num_params != 0) { 15319 - if (strcmp(params[0],"always") == 0) { 15320 - always = True; 15321 - } else if (strcmp(params[0],"new") == 0) { 15322 - always = False; 15323 - } else { 15324 - fprintf(stderr,"Invalid params: SelectionFromVNC(always|new)\n"); 15325 - return; 15326 - } 15327 - } 15328 - 15329 - if (t == CurrentTime) { 15330 - fprintf(stderr,"Error in translations: SelectionFromVNC() must act on " 15331 - "event with time field\n"); 15332 - return; 15333 - } 15334 - 15335 - if (!serverCutText || (!always && !newServerCutText)) 15336 - return; 15337 - 15338 - newServerCutText = False; 15339 - 15340 - XStoreBytes(dpy, serverCutText, strlen(serverCutText)); 15341 - if (XtOwnSelection(desktop, XA_PRIMARY, t, ConvertSelection, LoseSelection, 15342 - NULL)) { 15343 - iAmSelectionOwner = True; 15344 - } 15345 + Bool always = False; 15346 + Time t = TimeFromEvent(event); 15347 + int hold_primary = 0; 15348 + int hold_clipboard = 0; 15349 + 15350 + if (dbg_sel) fprintf(stderr, "SelectionFromVNC\n"); 15351 + 15352 + if (*num_params != 0) { 15353 + if (strcmp(params[0],"always") == 0) { 15354 + always = True; 15355 + } else if (strcmp(params[0],"new") == 0) { 15356 + always = False; 15357 + } else { 15358 + fprintf(stderr,"Invalid params: SelectionFromVNC(always|new)\n"); 15359 + return; 15360 + } 15361 + } 15362 + 15363 + if (t == CurrentTime) { 15364 + fprintf(stderr,"Error in translations: SelectionFromVNC() must act on " 15365 + "event with time field\n"); 15366 + return; 15367 + } 15368 + 15369 + if (!serverCutText || (!always && !newServerCutText)) { 15370 + return; 15371 + } 15372 + 15373 + newServerCutText = False; 15374 + 15375 + if (appData.appShare) { 15376 + if (strstr(serverCutText, "X11VNC_APPSHARE_CMD:") == serverCutText) { 15377 + /* do something with it? */ 15378 + return; 15379 + } 15380 + } 15381 + 15382 + XStoreBytes(dpy, serverCutText, strlen(serverCutText)); 15383 + 15384 + if (appData.recvText == NULL) { 15385 + appData.recvText = strdup("both"); 15386 + } 15387 + if (!strcasecmp(appData.recvText, "primary")) { 15388 + hold_primary = 1; 15389 + } else if (!strcasecmp(appData.recvText, "clipboard")) { 15390 + hold_clipboard = 1; 15391 + } else { 15392 + hold_primary = hold_clipboard = 1; 15393 + } 15394 + 15395 + if (!hold_primary) { 15396 + ; 15397 + } else if (XtOwnSelection(desktop, XA_PRIMARY, t, ConvertSelection, LoseSelection, NULL)) { 15398 + PrimarySelectionOwner = True; 15399 + if (dbg_sel) fprintf(stderr, "Own PRIMARY\n"); 15400 + } 15401 + if (!hold_clipboard || clipboard_atom == None) { 15402 + ; 15403 + } else if (XtOwnSelection(desktop, clipboard_atom, t, ConvertSelection, LoseSelection, NULL)) { 15404 + ClipboardSelectionOwner = True; 15405 + if (dbg_sel) fprintf(stderr, "Own CLIPBOARD\n"); 15406 + } 15407 + if (w || event || params || num_params) {} 15408 } 15409 15410 15411 @@ -293,37 +346,36 @@ 15412 XtPointer* value, unsigned long* length, int* format) 15413 { 15414 15415 - if (*target == XA_STRING && serverCutText != NULL) { 15416 - *type = XA_STRING; 15417 - *length = strlen(serverCutText); 15418 - *value = (XtPointer)XtMalloc(*length); 15419 - memcpy((char*)*value, serverCutText, *length); 15420 - *format = 8; 15421 - return True; 15422 - } 15423 + if (*target == XA_STRING && serverCutText != NULL) { 15424 + *type = XA_STRING; 15425 + *length = strlen(serverCutText); 15426 + *value = (XtPointer)XtMalloc(*length); 15427 + memcpy((char*)*value, serverCutText, *length); 15428 + *format = 8; 15429 + return True; 15430 + } 15431 15432 - if (XmuConvertStandardSelection(w, CurrentTime, selection, target, type, 15433 + if (XmuConvertStandardSelection(w, CurrentTime, selection, target, type, 15434 (XPointer*)value, length, format)) { 15435 - if (*target == XInternAtom(dpy, "TARGETS", False)) { 15436 - /* add STRING to list of standard targets */ 15437 - Atom* targetP; 15438 - Atom* std_targets = (Atom*)*value; 15439 - unsigned long std_length = *length; 15440 - 15441 - *length = std_length + 1; 15442 - *value = (XtPointer)XtMalloc(sizeof(Atom)*(*length)); 15443 - targetP = *(Atom**)value; 15444 - *targetP++ = XA_STRING; 15445 - memmove((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); 15446 - XtFree((char*)std_targets); 15447 - *type = XA_ATOM; 15448 - *format = 32; 15449 - return True; 15450 - } 15451 - 15452 - return True; 15453 - } 15454 - return False; 15455 + if (*target == XInternAtom(dpy, "TARGETS", False)) { 15456 + /* add STRING to list of standard targets */ 15457 + Atom* targetP; 15458 + Atom* std_targets = (Atom*)*value; 15459 + unsigned long std_length = *length; 15460 + 15461 + *length = std_length + 1; 15462 + *value = (XtPointer)XtMalloc(sizeof(Atom)*(*length)); 15463 + targetP = *(Atom**)value; 15464 + *targetP++ = XA_STRING; 15465 + memmove((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); 15466 + XtFree((char*)std_targets); 15467 + *type = XA_ATOM; 15468 + *format = 32; 15469 + return True; 15470 + } 15471 + return True; 15472 + } 15473 + return False; 15474 } 15475 15476 15477 @@ -332,7 +384,13 @@ 15478 */ 15479 15480 static void 15481 -LoseSelection(Widget w, Atom *selection) 15482 -{ 15483 - iAmSelectionOwner = False; 15484 +LoseSelection(Widget w, Atom *selection) { 15485 + if (*selection == XA_PRIMARY) { 15486 + if (dbg_sel) fprintf(stderr, "lost PRIMARY\n"); 15487 + PrimarySelectionOwner = False; 15488 + } else if (clipboard_atom != None && *selection == clipboard_atom) { 15489 + if (dbg_sel) fprintf(stderr, "lost CLIPBOARD\n"); 15490 + ClipboardSelectionOwner = False; 15491 + } 15492 + if (w) {} 15493 } 15494 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/shm.c 15495 --- vnc_unixsrc.orig/vncviewer/shm.c 2000-06-11 08:00:53.000000000 -0400 15496 +++ vnc_unixsrc/vncviewer/shm.c 2010-02-25 23:40:58.000000000 -0500 15497 @@ -30,71 +30,113 @@ 15498 static Bool caughtShmError = False; 15499 static Bool needShmCleanup = False; 15500 15501 -void 15502 -ShmCleanup() 15503 -{ 15504 - fprintf(stderr,"ShmCleanup called\n"); 15505 - if (needShmCleanup) { 15506 - shmdt(shminfo.shmaddr); 15507 - shmctl(shminfo.shmid, IPC_RMID, 0); 15508 - needShmCleanup = False; 15509 - } 15510 +static int ShmCreationXErrorHandler(Display *dpy, XErrorEvent *error) { 15511 + caughtShmError = True; 15512 + if (dpy || error) {} 15513 + return 0; 15514 } 15515 15516 -static int 15517 -ShmCreationXErrorHandler(Display *dpy, XErrorEvent *error) 15518 -{ 15519 - caughtShmError = True; 15520 - return 0; 15521 +void ShmDetach() { 15522 + if (needShmCleanup) { 15523 + XErrorHandler oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler); 15524 + fprintf(stderr,"ShmDetach called.\n"); 15525 + XShmDetach(dpy, &shminfo); 15526 + XSync(dpy, False); 15527 + XSetErrorHandler(oldXErrorHandler); 15528 + } 15529 } 15530 15531 -XImage * 15532 -CreateShmImage() 15533 -{ 15534 - XImage *image; 15535 - XErrorHandler oldXErrorHandler; 15536 - 15537 - if (!XShmQueryExtension(dpy)) 15538 - return NULL; 15539 - 15540 - image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo, 15541 - si.framebufferWidth, si.framebufferHeight); 15542 - if (!image) return NULL; 15543 - 15544 - shminfo.shmid = shmget(IPC_PRIVATE, 15545 - image->bytes_per_line * image->height, 15546 - IPC_CREAT|0777); 15547 +void ShmCleanup() { 15548 + if (needShmCleanup) { 15549 + fprintf(stderr,"ShmCleanup called.\n"); 15550 + XSync(dpy, False); 15551 + shmdt(shminfo.shmaddr); 15552 + shmctl(shminfo.shmid, IPC_RMID, 0); 15553 15554 - if (shminfo.shmid == -1) { 15555 - XDestroyImage(image); 15556 - return NULL; 15557 - } 15558 - 15559 - shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0); 15560 - 15561 - if (shminfo.shmaddr == (char *)-1) { 15562 - XDestroyImage(image); 15563 - shmctl(shminfo.shmid, IPC_RMID, 0); 15564 - return NULL; 15565 - } 15566 + needShmCleanup = False; 15567 + } 15568 +} 15569 15570 - shminfo.readOnly = True; 15571 +Bool UsingShm() { 15572 + return needShmCleanup; 15573 +} 15574 15575 - oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler); 15576 - XShmAttach(dpy, &shminfo); 15577 - XSync(dpy, False); 15578 - XSetErrorHandler(oldXErrorHandler); 15579 +int scale_round(int len, double fac); 15580 +extern int scale_x, scale_y; 15581 +extern double scale_factor_x, scale_factor_y; 15582 15583 - if (caughtShmError) { 15584 - XDestroyImage(image); 15585 - shmdt(shminfo.shmaddr); 15586 - shmctl(shminfo.shmid, IPC_RMID, 0); 15587 - return NULL; 15588 - } 15589 +XImage * 15590 +CreateShmImage(int do_ycrop) 15591 +{ 15592 + XImage *image; 15593 + XErrorHandler oldXErrorHandler; 15594 + int ymax = si.framebufferHeight; 15595 + int xmax = si.framebufferWidth; 15596 + 15597 + if (!XShmQueryExtension(dpy)) { 15598 + return NULL; 15599 + } 15600 + if (!appData.useShm) { 15601 + return NULL; 15602 + } 15603 + if (do_ycrop == -1) { 15604 + /* kludge to test for shm prescence */ 15605 + return (XImage *) 0x1; 15606 + } 15607 + 15608 + if (do_ycrop) { 15609 + ymax = appData.yCrop; 15610 + } 15611 + 15612 + if (scale_x > 0) { 15613 + xmax = scale_round(xmax, scale_factor_x); 15614 + ymax = scale_round(ymax, scale_factor_y); 15615 + } 15616 + 15617 + image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo, xmax, ymax); 15618 + if (!image) { 15619 + return NULL; 15620 + } 15621 + 15622 + shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT|0777); 15623 + 15624 + if (shminfo.shmid == -1) { 15625 + XDestroyImage(image); 15626 + if (0) fprintf(stderr, "CreateShmImage: destroyed 'image' (1)\n"); 15627 + return NULL; 15628 + } 15629 + 15630 + shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0); 15631 + 15632 + if (shminfo.shmaddr == (char *)-1) { 15633 + XDestroyImage(image); 15634 +#if 0 15635 + fprintf(stderr, "CreateShmImage: destroyed 'image' (2)\n"); 15636 +#endif 15637 + shmctl(shminfo.shmid, IPC_RMID, 0); 15638 + return NULL; 15639 + } 15640 + 15641 + shminfo.readOnly = True; 15642 + 15643 + oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler); 15644 + XShmAttach(dpy, &shminfo); 15645 + XSync(dpy, False); 15646 + XSetErrorHandler(oldXErrorHandler); 15647 + 15648 + if (caughtShmError) { 15649 + XDestroyImage(image); 15650 +#if 0 15651 + fprintf(stderr, "CreateShmImage: destroyed 'image' (3)\n"); 15652 +#endif 15653 + shmdt(shminfo.shmaddr); 15654 + shmctl(shminfo.shmid, IPC_RMID, 0); 15655 + return NULL; 15656 + } 15657 15658 - needShmCleanup = True; 15659 + needShmCleanup = True; 15660 15661 - fprintf(stderr,"Using shared memory PutImage\n"); 15662 + fprintf(stderr,"Using shared memory (PutImage ycrop=%d, Size %dx%d)\n", do_ycrop, xmax, ymax); 15663 15664 - return image; 15665 + return image; 15666 } 15667 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/smake vnc_unixsrc/vncviewer/smake 15668 --- vnc_unixsrc.orig/vncviewer/smake 1969-12-31 19:00:00.000000000 -0500 15669 +++ vnc_unixsrc/vncviewer/smake 2007-02-19 12:28:05.000000000 -0500 15670 @@ -0,0 +1,11 @@ 15671 +#!/bin/sh 15672 + 15673 +PATH=`pwd`/../..:/usr/sfw/bin:/usr/ccs/bin:$PATH 15674 +export PATH 15675 +if [ "X$1" != "X" ]; then 15676 + "$@" 15677 +else 15678 + make 15679 + strip vncviewer 15680 + ls -l vncviewer 15681 +fi 15682 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncviewer/sockets.c 15683 --- vnc_unixsrc.orig/vncviewer/sockets.c 2001-01-14 22:54:18.000000000 -0500 15684 +++ vnc_unixsrc/vncviewer/sockets.c 2010-04-18 11:41:07.000000000 -0400 15685 @@ -22,17 +22,31 @@ 15686 */ 15687 15688 #include <unistd.h> 15689 +#include <time.h> 15690 #include <sys/socket.h> 15691 #include <errno.h> 15692 #include <netinet/in.h> 15693 #include <netinet/tcp.h> 15694 #include <arpa/inet.h> 15695 +#include <sys/un.h> 15696 #include <netdb.h> 15697 #include <fcntl.h> 15698 #include <assert.h> 15699 #include <vncviewer.h> 15700 15701 +#ifndef SOL_IPV6 15702 +#ifdef IPPROTO_IPV6 15703 +#define SOL_IPV6 IPPROTO_IPV6 15704 +#endif 15705 +#endif 15706 + 15707 +/* Solaris (sysv?) needs INADDR_NONE */ 15708 +#ifndef INADDR_NONE 15709 +#define INADDR_NONE ((in_addr_t) 0xffffffff) 15710 +#endif 15711 + 15712 void PrintInHex(char *buf, int len); 15713 +extern void printChat(char *, Bool); 15714 15715 Bool errorMessageOnReadFailure = True; 15716 15717 @@ -56,31 +70,396 @@ 15718 */ 15719 15720 static Bool rfbsockReady = False; 15721 +static Bool xfrsockReady = False; 15722 +static XtInputId rfbsockId = 0; 15723 +static XtInputId xfrsockId = 0; 15724 +static int do_rfbsockId = 0; 15725 +static int do_xfrsockId = 0; 15726 + 15727 static void 15728 rfbsockReadyCallback(XtPointer clientData, int *fd, XtInputId *id) 15729 { 15730 - rfbsockReady = True; 15731 - XtRemoveInput(*id); 15732 + rfbsockReady = True; 15733 +#if 0 15734 + XtRemoveInput(*id); 15735 +#endif 15736 + XtRemoveInput(rfbsockId); 15737 + if (do_xfrsockId) { 15738 + XtRemoveInput(xfrsockId); 15739 + } 15740 + if (clientData || fd || id) {} 15741 } 15742 15743 static void 15744 -ProcessXtEvents() 15745 +xfrsockReadyCallback(XtPointer clientData, int *fd, XtInputId *id) 15746 { 15747 - rfbsockReady = False; 15748 - XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask, 15749 - rfbsockReadyCallback, NULL); 15750 - while (!rfbsockReady) { 15751 - XtAppProcessEvent(appContext, XtIMAll); 15752 - } 15753 + xfrsockReady = True; 15754 + XtRemoveInput(xfrsockId); 15755 + if (do_rfbsockId) { 15756 + XtRemoveInput(rfbsockId); 15757 + } 15758 + if (clientData || fd || id) {} 15759 +} 15760 + 15761 + 15762 +extern int skip_XtUpdate; 15763 +extern int skip_XtUpdateAll; 15764 +extern int filexfer_sock, filexfer_listen; 15765 +extern time_t start_listen; 15766 +extern void CheckTextInput(void); 15767 +extern time_t last_filexfer; 15768 + 15769 +static char fxfer[65536]; 15770 +int fxfer_size = 65536; 15771 + 15772 +int rfbsock_is_ready(void) { 15773 + fd_set fds; 15774 + struct timeval tv; 15775 + 15776 + if (rfbsock < 0) { 15777 + return 0; 15778 + } 15779 + FD_ZERO(&fds); 15780 + FD_SET(rfbsock,&fds); 15781 + tv.tv_sec = 0; 15782 + tv.tv_usec = 0; 15783 + if (select(rfbsock+1, &fds, NULL, NULL, &tv) > 0) { 15784 + if (FD_ISSET(rfbsock, &fds)) { 15785 + return 1; 15786 + } 15787 + } 15788 + return 0; 15789 +} 15790 + 15791 +time_t filexfer_start = 0; 15792 + 15793 +void CheckFileXfer() { 15794 + fd_set fds; 15795 + struct timeval tv; 15796 + int i, icnt = 0, igot = 0, bytes0 = 0, bytes = 0, grace = 0, n, list = 0; 15797 + int db = 0; 15798 + 15799 + if (!appData.fileActive || (filexfer_sock < 0 && filexfer_listen < 0)) { 15800 + return; 15801 + } 15802 + 15803 + if (filexfer_listen >= 0 && time(NULL) > start_listen + 30) { 15804 + fprintf(stderr, "filexfer closing aging listen socket.\n"); 15805 + close(filexfer_listen); 15806 + filexfer_listen = -1; 15807 + return; 15808 + } 15809 +if (0) fprintf(stderr, "In CheckFileXfer\n"); 15810 + 15811 + if (filexfer_listen >=0) { 15812 + n = filexfer_listen; 15813 + list = 1; 15814 + } else { 15815 + n = filexfer_sock; 15816 + } 15817 + 15818 + while (1) { 15819 + icnt++; 15820 + FD_ZERO(&fds); 15821 + FD_SET(n,&fds); 15822 + tv.tv_sec = 0; 15823 + tv.tv_usec = 0; 15824 + if (select(n+1, &fds, NULL, NULL, &tv) > 0) { 15825 + if (FD_ISSET(n, &fds)) { 15826 + if (list) { 15827 + if (filexfer_sock >= 0) { 15828 + fprintf(stderr, "filexfer close stale(?) filexfer_sock.\n"); 15829 + close(filexfer_sock); 15830 + filexfer_sock = -1; 15831 + } 15832 + filexfer_sock = AcceptTcpConnection(filexfer_listen); 15833 + if (filexfer_sock >= 0) { 15834 + fprintf(stderr, "filexfer accept OK.\n"); 15835 + close(filexfer_listen); 15836 + filexfer_listen = -1; 15837 + filexfer_start = last_filexfer = time(NULL); 15838 + } else { 15839 + fprintf(stderr, "filexfer accept failed.\n"); 15840 + } 15841 + break; 15842 + } else { 15843 + ssize_t rn; 15844 + unsigned char hdr[12]; 15845 + unsigned int len; 15846 + if (db) fprintf(stderr, "try read filexfer...\n"); 15847 + if (hdr || len || i) {} 15848 +#if 1 15849 + rn = read(n, fxfer, 1*8192); 15850 +if (db) { 15851 + int i; 15852 + fprintf(stderr, "CFX HDR:"); 15853 + for (i=0; i < 12; i++) { 15854 + fprintf(stderr, " %d", (int) fxfer[i]); 15855 + } 15856 + fprintf(stderr, " ?\n"); 15857 +} 15858 + if (0 || db) fprintf(stderr, "filexfer read[%d] %d.\n", icnt, rn); 15859 + if (rn < 0) { 15860 + fprintf(stderr, "filexfer bad read: %d\n", errno); 15861 + break; 15862 + } else if (rn == 0) { 15863 + fprintf(stderr, "filexfer gone.\n"); 15864 + close(n); 15865 + filexfer_sock = -1; 15866 + last_filexfer = time(NULL); 15867 +#if 0 15868 + fprintf(stderr, "last_filexfer-2a: %d\n", last_filexfer); 15869 +#endif 15870 + appData.fileActive = False; 15871 + SendFramebufferUpdateRequest(0, 0, 1, 1, False); 15872 + return; 15873 + } else if (rn > 0) { 15874 + if (db > 1) write(2, fxfer, rn); 15875 + if (db) fprintf(stderr, "\n"); 15876 + bytes += rn; 15877 + last_filexfer = time(NULL); 15878 +#if 0 15879 + fprintf(stderr, "last_filexfer-2b: %d\n", last_filexfer); 15880 +#endif 15881 + 15882 + if (0) { 15883 + /* WE TRY TO FIX THIS IN THE JAVA NOW */ 15884 + if (appData.ultraDSM) { 15885 + unsigned char msg = rfbFileTransfer; 15886 + unsigned char hdc = (unsigned char) fxfer[0]; 15887 + if (msg == hdc) { 15888 + /* cross your fingers... */ 15889 + WriteExact(rfbsock, (char *)&msg, 1); 15890 + } 15891 + } 15892 + } 15893 + if (!WriteExact(rfbsock, fxfer, rn)) { 15894 + return; 15895 + } 15896 + igot = 1; 15897 + } 15898 +#else 15899 + /* not working, not always 7 msg type. */ 15900 + rn = read(n, hdr, 12); 15901 + if (db) fprintf(stderr, "filexfer read %d.\n", rn); 15902 + if (rn == 0) { 15903 + fprintf(stderr, "filexfer gone.\n"); 15904 + close(n); 15905 + filexfer_sock = -1; 15906 + last_filexfer = time(NULL); 15907 + return; 15908 + } 15909 + if (rn == 12) { 15910 + len = (hdr[8] << 24) | (hdr[9] << 16) | (hdr[10] << 8) | hdr[11]; 15911 + if (db) fprintf(stderr, "n=%d len=%d\n", rn, len); 15912 + if (db > 1) write(2, hdr, rn); 15913 + if (db) fprintf(stderr, "\n"); 15914 + WriteExact(rfbsock, hdr, rn); 15915 + if (len > 0) { 15916 + rn = read(len, fxfer, len); 15917 + if (!WriteExact(rfbsock, fxfer, len)) { 15918 + last_filexfer = time(NULL); 15919 + return; 15920 + } 15921 + if (db > 1) write(2, fxfer, len); 15922 + } 15923 + if (db) fprintf(stderr, "\n"); 15924 + } else { 15925 + if (db) fprintf(stderr, "bad rn: %d\n", rn); 15926 + } 15927 + igot = 1; 15928 +#endif 15929 + } 15930 + } 15931 + } else { 15932 + if (bytes >= 8192) { 15933 + int ok = 0; 15934 + if (bytes0 == 0) { 15935 + ok = 1; 15936 + } else if (bytes >= bytes0 + 12) { 15937 + ok = 1; 15938 + } else if (grace < 20) { 15939 + ok = 1; 15940 + } 15941 + if (ok) { 15942 + grace++; 15943 + bytes0 = bytes; 15944 +#if 0 15945 + fprintf(stderr, "grace: %d\n", grace); 15946 + /* forgot that this is about... */ 15947 +#endif 15948 + usleep(10 * 1000); 15949 + continue; 15950 + } 15951 + } 15952 + break; 15953 + } 15954 + } 15955 + if (igot) { 15956 + last_filexfer = time(NULL); 15957 +#if 0 15958 + fprintf(stderr, "last_filexfer-2c: %d\n", last_filexfer); 15959 +#endif 15960 + } 15961 +#if 0 15962 +fprintf(stderr, "Out CheckFileXfer\n"); 15963 +#endif 15964 + return; 15965 +} 15966 + 15967 +static void check_term_chat(void) { 15968 + fd_set fds; 15969 + struct timeval tv; 15970 + int i, igot = -1, n = fileno(stdin); 15971 + char strs[100][512]; 15972 + char buf[rfbTextMaxSize]; 15973 + 15974 + for (i=0; i < 100; i++) { 15975 + FD_ZERO(&fds); 15976 + FD_SET(n,&fds); 15977 + tv.tv_sec = 0; 15978 + tv.tv_usec = 0; 15979 + if (select(n+1, &fds, NULL, NULL, &tv) > 0) { 15980 + if (FD_ISSET(n, &fds)) { 15981 + fgets(strs[i], 512, stdin); 15982 + igot = i; 15983 + } else { 15984 + break; 15985 + } 15986 + } else { 15987 + break; 15988 + } 15989 + } 15990 + buf[0] = '\0'; 15991 + for (i=0; i <= igot; i++) { 15992 + if (strlen(buf) + strlen(strs[i]) < rfbTextMaxSize) { 15993 + strcat(buf, strs[i]); 15994 + } else { 15995 + SendTextChat(buf); 15996 + buf[0] = '0'; 15997 + } 15998 + } 15999 + if (buf[0] != '\0') { 16000 + SendTextChat(buf); 16001 + } 16002 + if (igot >= 0) printChat("Send: ", False); 16003 +} 16004 + 16005 +static time_t time_mark; 16006 +extern int delay_filexfer; 16007 +#include <sys/stat.h> 16008 + 16009 +extern double start_time; 16010 + 16011 +void ProcessXtEvents() 16012 +{ 16013 + int db = 0; 16014 + static int dyn = -1; 16015 + static int chat_was_active = 0; 16016 + int check_chat = 0; 16017 + 16018 + if (dyn < 0) { 16019 + struct stat sb; 16020 + if (getenv("USER") && !strcmp(getenv("USER"), "runge")) { 16021 + if (stat("/tmp/nodyn", &sb) == 0) { 16022 + putenv("NOFTFBUPDATES=1"); 16023 + unlink("/tmp/nodyn"); 16024 + } 16025 + } 16026 + if (getenv("NOFTFBUPDATES")) { 16027 + dyn = 0; 16028 + } else { 16029 + dyn = 1; 16030 + } 16031 + } 16032 + 16033 +#if 0 16034 + if (0) fprintf(stderr, "ProcessXtEvents: %d %.4f\n", skip_XtUpdateAll, dnow() - start_time); 16035 +#endif 16036 + 16037 + if (skip_XtUpdateAll) { 16038 + return; 16039 + } 16040 + 16041 + /* text chat */ 16042 + if (appData.chatActive ) { 16043 + check_chat = 1; 16044 + } else if (chat_was_active) { 16045 + static double last_check = 0.0; 16046 + double now = dnow(); 16047 + if (now > last_check + 0.75) { 16048 + check_chat = 1; 16049 + last_check = now; 16050 + } 16051 + } 16052 + if (check_chat) { 16053 + if (appData.chatActive) { 16054 + chat_was_active = 1; 16055 + } 16056 + if (!appData.termChat) { 16057 + CheckTextInput(); 16058 + } else { 16059 + check_term_chat(); 16060 + } 16061 + } 16062 + 16063 + if (skip_XtUpdate) { 16064 + return; 16065 + } 16066 + 16067 + rfbsockReady = False; 16068 + xfrsockReady = False; 16069 + do_rfbsockId = 1; 16070 + rfbsockId = XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask, 16071 + rfbsockReadyCallback, NULL); 16072 + 16073 + do_xfrsockId = 0; 16074 + if (filexfer_sock >= 0) { 16075 + do_xfrsockId = 1; 16076 + xfrsockId = XtAppAddInput(appContext, filexfer_sock, (XtPointer)XtInputReadMask, 16077 + xfrsockReadyCallback, NULL); 16078 + } 16079 + 16080 + time_mark = time(NULL); 16081 + 16082 + if (appData.fileActive) { 16083 + static int first = 1; 16084 + if (first) { 16085 + fprintf(stderr, "PXT: dynamic fb updates during filexfer: %d\n", dyn); 16086 + first = 0; 16087 + } 16088 + } 16089 + 16090 + if (db) fprintf(stderr, "XtAppAddInput: "); 16091 + while (!rfbsockReady && !xfrsockReady) { 16092 + int w = si.framebufferWidth; 16093 + int h = si.framebufferHeight; 16094 + if (db) fprintf(stderr, "."); 16095 + if (dyn && filexfer_sock >= 0 && time(NULL) > time_mark + delay_filexfer) { 16096 + SendFramebufferUpdateRequest(0, 0, w, h, False); 16097 + } 16098 + XtAppProcessEvent(appContext, XtIMAll); 16099 + } 16100 + if (db) fprintf(stderr, " done. r: %d x: %d\n", rfbsockReady, xfrsockReady); 16101 + 16102 + if (xfrsockReady) { 16103 + CheckFileXfer(); 16104 + } 16105 } 16106 16107 Bool 16108 ReadFromRFBServer(char *out, unsigned int n) 16109 { 16110 +#if 0 16111 + double start = dnow(), dn = n; 16112 +#endif 16113 if (n <= buffered) { 16114 memcpy(out, bufoutptr, n); 16115 bufoutptr += n; 16116 buffered -= n; 16117 +#if 0 16118 +fprintf(stderr, "R0: %06d\n", (int) dn); 16119 +#endif 16120 return True; 16121 } 16122 16123 @@ -119,6 +498,9 @@ 16124 memcpy(out, bufoutptr, n); 16125 bufoutptr += n; 16126 buffered -= n; 16127 +#if 0 16128 +fprintf(stderr, "R1: %06d %06d %10.2f KB/sec\n", (int) dn, buffered+n, 1e-3 * (buffered+n)/(dnow() - start)); 16129 +#endif 16130 return True; 16131 16132 } else { 16133 @@ -146,11 +528,16 @@ 16134 n -= i; 16135 } 16136 16137 +#if 0 16138 +fprintf(stderr, "R2: %06d %06d %10.2f KB/sec\n", (int) dn, (int) dn, 1e-3 * (dn)/(dnow() - start)); 16139 +#endif 16140 return True; 16141 } 16142 } 16143 16144 16145 +int currentMsg = -1; 16146 + 16147 /* 16148 * Write an exact number of bytes, and don't return until you've sent them. 16149 */ 16150 @@ -158,81 +545,321 @@ 16151 Bool 16152 WriteExact(int sock, char *buf, int n) 16153 { 16154 - fd_set fds; 16155 - int i = 0; 16156 - int j; 16157 - 16158 - while (i < n) { 16159 - j = write(sock, buf + i, (n - i)); 16160 - if (j <= 0) { 16161 - if (j < 0) { 16162 - if (errno == EWOULDBLOCK || errno == EAGAIN) { 16163 - FD_ZERO(&fds); 16164 - FD_SET(rfbsock,&fds); 16165 + fd_set fds; 16166 + int i = 0; 16167 + int j; 16168 + 16169 + if (appData.ultraDSM && currentMsg >= 0) { 16170 + /* this is for goofy UltraVNC DSM send RFB msg char twice: */ 16171 + unsigned char msg = (unsigned char) currentMsg; 16172 + currentMsg = -1; 16173 + if (!WriteExact(sock, (char *)&msg, sizeof(msg))) { 16174 + return False; 16175 + } 16176 + } 16177 + currentMsg = -1; 16178 16179 - if (select(rfbsock+1, NULL, &fds, NULL, NULL) <= 0) { 16180 - fprintf(stderr,programName); 16181 - perror(": select"); 16182 - return False; 16183 - } 16184 - j = 0; 16185 - } else { 16186 - fprintf(stderr,programName); 16187 - perror(": write"); 16188 - return False; 16189 + while (i < n) { 16190 + j = write(sock, buf + i, (n - i)); 16191 + if (j <= 0) { 16192 + if (j < 0) { 16193 + if (errno == EWOULDBLOCK || errno == EAGAIN) { 16194 + FD_ZERO(&fds); 16195 + FD_SET(rfbsock,&fds); 16196 + 16197 + if (select(rfbsock+1, NULL, &fds, NULL, NULL) <= 0) { 16198 + fprintf(stderr,programName); 16199 + perror(": select"); 16200 + return False; 16201 + } 16202 + j = 0; 16203 + } else { 16204 + fprintf(stderr,programName); 16205 + perror(": write"); 16206 + return False; 16207 + } 16208 + } else { 16209 + fprintf(stderr,"%s: write failed\n",programName); 16210 + return False; 16211 + } 16212 + } 16213 + i += j; 16214 } 16215 - } else { 16216 - fprintf(stderr,"%s: write failed\n",programName); 16217 - return False; 16218 - } 16219 - } 16220 - i += j; 16221 - } 16222 - return True; 16223 + return True; 16224 } 16225 16226 +int 16227 +ConnectToUnixSocket(char *file) { 16228 + int sock; 16229 + struct sockaddr_un addr; 16230 + int i; 16231 + 16232 + memset(&addr, 0, sizeof(struct sockaddr_un)); 16233 + 16234 + addr.sun_family = AF_UNIX; 16235 + 16236 + for (i=0; i < 108; i++) { 16237 + addr.sun_path[i] = file[i]; 16238 + if (file[i] == '\0') { 16239 + break; 16240 + } 16241 + } 16242 + 16243 + sock = socket(AF_UNIX, SOCK_STREAM, 0); 16244 + if (sock < 0) { 16245 + fprintf(stderr,programName); 16246 + perror(": ConnectToUnixSocket: socket"); 16247 + return -1; 16248 + } 16249 + 16250 + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 16251 + fprintf(stderr, programName); 16252 + perror(": ConnectToUnixSocket: connect"); 16253 + close(sock); 16254 + return -1; 16255 + } 16256 + 16257 + return sock; 16258 +} 16259 + 16260 +char *ipv6_getipaddr(struct sockaddr *paddr, int addrlen) { 16261 +#if defined(AF_INET6) && defined(NI_NUMERICHOST) 16262 + char name[200]; 16263 + if (appData.noipv6) { 16264 + return strdup("unknown"); 16265 + } 16266 + if (getnameinfo(paddr, addrlen, name, sizeof(name), NULL, 0, NI_NUMERICHOST) == 0) { 16267 + return strdup(name); 16268 + } 16269 +#endif 16270 + if (paddr || addrlen) {} 16271 + return strdup("unknown"); 16272 +} 16273 + 16274 +char *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen) { 16275 +#if defined(AF_INET6) 16276 + char name[200]; 16277 + if (appData.noipv6) { 16278 + return strdup("unknown"); 16279 + } 16280 + if (getnameinfo(paddr, addrlen, name, sizeof(name), NULL, 0, 0) == 0) { 16281 + return strdup(name); 16282 + } 16283 +#endif 16284 + if (paddr || addrlen) {} 16285 + return strdup("unknown"); 16286 +} 16287 + 16288 +int dotted_ip(char *host, int partial) { 16289 + int len, dots = 0; 16290 + char *p = host; 16291 + 16292 + if (!host) { 16293 + return 0; 16294 + } 16295 + 16296 + if (!isdigit((unsigned char) host[0])) { 16297 + return 0; 16298 + } 16299 + 16300 + len = strlen(host); 16301 + if (!partial && !isdigit((unsigned char) host[len-1])) { 16302 + return 0; 16303 + } 16304 + 16305 + while (*p != '\0') { 16306 + if (*p == '.') dots++; 16307 + if (*p == '.' || isdigit((unsigned char) (*p))) { 16308 + p++; 16309 + continue; 16310 + } 16311 + return 0; 16312 + } 16313 + if (!partial && dots != 3) { 16314 + return 0; 16315 + } 16316 + return 1; 16317 +} 16318 16319 /* 16320 * ConnectToTcpAddr connects to the given TCP port. 16321 */ 16322 16323 -int 16324 -ConnectToTcpAddr(unsigned int host, int port) 16325 -{ 16326 - int sock; 16327 - struct sockaddr_in addr; 16328 - int one = 1; 16329 - 16330 - addr.sin_family = AF_INET; 16331 - addr.sin_port = htons(port); 16332 - addr.sin_addr.s_addr = host; 16333 +int ConnectToTcpAddr(const char *hostname, int port) { 16334 + int sock = -1, one = 1; 16335 + unsigned int host; 16336 + struct sockaddr_in addr; 16337 + 16338 + if (appData.noipv4) { 16339 + fprintf(stderr, "ipv4 is disabled via VNCVIEWER_NO_IPV4/-noipv4.\n"); 16340 + goto try6; 16341 + } 16342 16343 - sock = socket(AF_INET, SOCK_STREAM, 0); 16344 - if (sock < 0) { 16345 - fprintf(stderr,programName); 16346 - perror(": ConnectToTcpAddr: socket"); 16347 - return -1; 16348 - } 16349 + if (!StringToIPAddr(hostname, &host)) { 16350 + fprintf(stderr, "Could not convert '%s' to ipv4 host address.\n", hostname); 16351 + goto try6; 16352 + } 16353 16354 - if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 16355 - fprintf(stderr,programName); 16356 - perror(": ConnectToTcpAddr: connect"); 16357 - close(sock); 16358 - return -1; 16359 - } 16360 + memset(&addr, 0, sizeof(struct sockaddr_in)); 16361 16362 - if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, 16363 - (char *)&one, sizeof(one)) < 0) { 16364 - fprintf(stderr,programName); 16365 - perror(": ConnectToTcpAddr: setsockopt"); 16366 - close(sock); 16367 - return -1; 16368 - } 16369 + addr.sin_family = AF_INET; 16370 + addr.sin_port = htons(port); 16371 + addr.sin_addr.s_addr = host; 16372 + 16373 + sock = socket(AF_INET, SOCK_STREAM, 0); 16374 + if (sock < 0) { 16375 + perror("ConnectToTcpAddr[ipv4]: socket"); 16376 + sock = -1; 16377 + goto try6; 16378 + } 16379 + 16380 + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 16381 + perror("ConnectToTcpAddr[ipv4]: connect"); 16382 + close(sock); 16383 + sock = -1; 16384 + goto try6; 16385 + } 16386 + 16387 + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { 16388 + perror("ConnectToTcpAddr[ipv4]: setsockopt"); 16389 + close(sock); 16390 + sock = -1; 16391 + goto try6; 16392 + } 16393 16394 - return sock; 16395 + if (sock >= 0) { 16396 + return sock; 16397 + } 16398 + 16399 + try6: 16400 + 16401 +#ifdef AF_INET6 16402 + if (!appData.noipv6) { 16403 + int err; 16404 + struct addrinfo *ai; 16405 + struct addrinfo hints; 16406 + char service[32], *host2, *q; 16407 + 16408 + fprintf(stderr, "Trying ipv6 connection to '%s'\n", hostname); 16409 + 16410 + memset(&hints, 0, sizeof(hints)); 16411 + sprintf(service, "%d", port); 16412 + 16413 + hints.ai_family = AF_UNSPEC; 16414 + hints.ai_socktype = SOCK_STREAM; 16415 +#ifdef AI_ADDRCONFIG 16416 + hints.ai_flags |= AI_ADDRCONFIG; 16417 +#endif 16418 +#ifdef AI_NUMERICSERV 16419 + hints.ai_flags |= AI_NUMERICSERV; 16420 +#endif 16421 + if (!strcmp(hostname, "localhost")) { 16422 + host2 = strdup("::1"); 16423 + } else if (!strcmp(hostname, "127.0.0.1")) { 16424 + host2 = strdup("::1"); 16425 + } else if (hostname[0] == '[') { 16426 + host2 = strdup(hostname+1); 16427 + } else { 16428 + host2 = strdup(hostname); 16429 + } 16430 + q = strrchr(host2, ']'); 16431 + if (q) { 16432 + *q = '\0'; 16433 + } 16434 + 16435 + err = getaddrinfo(host2, service, &hints, &ai); 16436 + if (err != 0) { 16437 + fprintf(stderr, "ConnectToTcpAddr[ipv6]: getaddrinfo[%d]: %s\n", err, gai_strerror(err)); 16438 + usleep(100 * 1000); 16439 + err = getaddrinfo(host2, service, &hints, &ai); 16440 + } 16441 + free(host2); 16442 + 16443 + if (err != 0) { 16444 + fprintf(stderr, "ConnectToTcpAddr[ipv6]: getaddrinfo[%d]: %s (2nd try)\n", err, gai_strerror(err)); 16445 + } else { 16446 + struct addrinfo *ap = ai; 16447 + while (ap != NULL) { 16448 + int fd = -1; 16449 + char *s = ipv6_getipaddr(ap->ai_addr, ap->ai_addrlen); 16450 + if (s) { 16451 + fprintf(stderr, "ConnectToTcpAddr[ipv6]: trying ip-addr: '%s'\n", s); 16452 + free(s); 16453 + } 16454 + if (appData.noipv4) { 16455 + struct sockaddr_in6 *s6ptr; 16456 + if (ap->ai_family != AF_INET6) { 16457 + fprintf(stderr, "ConnectToTcpAddr[ipv6]: skipping AF_INET address under VNCVIEWER_NO_IPV4/-noipv4\n"); 16458 + ap = ap->ai_next; 16459 + continue; 16460 + } 16461 +#ifdef IN6_IS_ADDR_V4MAPPED 16462 + s6ptr = (struct sockaddr_in6 *) ap->ai_addr; 16463 + if (IN6_IS_ADDR_V4MAPPED(&(s6ptr->sin6_addr))) { 16464 + fprintf(stderr, "ConnectToTcpAddr[ipv6]: skipping V4MAPPED address under VNCVIEWER_NO_IPV4/-noipv4\n"); 16465 + ap = ap->ai_next; 16466 + continue; 16467 + } 16468 +#endif 16469 + } 16470 + 16471 + fd = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol); 16472 + if (fd == -1) { 16473 + perror("ConnectToTcpAddr[ipv6]: socket"); 16474 + } else { 16475 + int dmsg = 0; 16476 + int res = connect(fd, ap->ai_addr, ap->ai_addrlen); 16477 +#if defined(SOL_IPV6) && defined(IPV6_V6ONLY) 16478 + if (res != 0) { 16479 + int zero = 0; 16480 + perror("ConnectToTcpAddr[ipv6]: connect"); 16481 + dmsg = 1; 16482 + if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (char *)&zero, sizeof(zero)) == 0) { 16483 + fprintf(stderr, "ConnectToTcpAddr[ipv6]: trying again with IPV6_V6ONLY=0\n"); 16484 + res = connect(fd, ap->ai_addr, ap->ai_addrlen); 16485 + dmsg = 0; 16486 + } 16487 + } 16488 +#endif 16489 + if (res == 0) { 16490 + fprintf(stderr, "ConnectToTcpAddr[ipv6]: connect OK\n"); 16491 + sock = fd; 16492 + break; 16493 + } else { 16494 + if (!dmsg) perror("ConnectToTcpAddr[ipv6]: connect"); 16495 + close(fd); 16496 + } 16497 + } 16498 + ap = ap->ai_next; 16499 + } 16500 + freeaddrinfo(ai); 16501 + } 16502 + if (sock >= 0 && setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { 16503 + perror("ConnectToTcpAddr: setsockopt"); 16504 + close(sock); 16505 + sock = -1; 16506 + } 16507 + } 16508 +#endif 16509 + return sock; 16510 } 16511 16512 +Bool SocketPair(int fd[2]) { 16513 + if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd) == -1) { 16514 + perror("socketpair"); 16515 + return False; 16516 + } 16517 + return True; 16518 +} 16519 16520 +Bool SetNoDelay(int sock) { 16521 + const int one = 1; 16522 + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { 16523 + perror("setsockopt"); 16524 + return False; 16525 + } 16526 + return True; 16527 +} 16528 16529 /* 16530 * FindFreeTcpPort tries to find unused TCP port in the range 16531 @@ -242,29 +869,31 @@ 16532 int 16533 FindFreeTcpPort(void) 16534 { 16535 - int sock, port; 16536 - struct sockaddr_in addr; 16537 + int sock, port; 16538 + struct sockaddr_in addr; 16539 16540 - addr.sin_family = AF_INET; 16541 - addr.sin_addr.s_addr = INADDR_ANY; 16542 + memset(&addr, 0, sizeof(struct sockaddr_in)); 16543 16544 - sock = socket(AF_INET, SOCK_STREAM, 0); 16545 - if (sock < 0) { 16546 - fprintf(stderr,programName); 16547 - perror(": FindFreeTcpPort: socket"); 16548 - return 0; 16549 - } 16550 + addr.sin_family = AF_INET; 16551 + addr.sin_addr.s_addr = INADDR_ANY; 16552 16553 - for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) { 16554 - addr.sin_port = htons((unsigned short)port); 16555 - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { 16556 - close(sock); 16557 - return port; 16558 - } 16559 - } 16560 + sock = socket(AF_INET, SOCK_STREAM, 0); 16561 + if (sock < 0) { 16562 + fprintf(stderr,programName); 16563 + perror(": FindFreeTcpPort: socket"); 16564 + return 0; 16565 + } 16566 + 16567 + for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) { 16568 + addr.sin_port = htons((unsigned short)port); 16569 + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { 16570 + close(sock); 16571 + return port; 16572 + } 16573 + } 16574 16575 - close(sock); 16576 - return 0; 16577 + close(sock); 16578 + return 0; 16579 } 16580 16581 16582 @@ -272,47 +901,110 @@ 16583 * ListenAtTcpPort starts listening at the given TCP port. 16584 */ 16585 16586 -int 16587 -ListenAtTcpPort(int port) 16588 -{ 16589 - int sock; 16590 - struct sockaddr_in addr; 16591 - int one = 1; 16592 - 16593 - addr.sin_family = AF_INET; 16594 - addr.sin_port = htons(port); 16595 - addr.sin_addr.s_addr = INADDR_ANY; 16596 +int use_loopback = 0; 16597 16598 - sock = socket(AF_INET, SOCK_STREAM, 0); 16599 - if (sock < 0) { 16600 - fprintf(stderr,programName); 16601 - perror(": ListenAtTcpPort: socket"); 16602 - return -1; 16603 - } 16604 +int ListenAtTcpPort(int port) { 16605 + int sock; 16606 + struct sockaddr_in addr; 16607 + int one = 1; 16608 + 16609 + if (appData.noipv4) { 16610 + fprintf(stderr, "ipv4 is disabled via VNCVIEWER_NO_IPV4/-noipv4.\n"); 16611 + return -1; 16612 + } 16613 16614 - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 16615 - (const char *)&one, sizeof(one)) < 0) { 16616 - fprintf(stderr,programName); 16617 - perror(": ListenAtTcpPort: setsockopt"); 16618 - close(sock); 16619 - return -1; 16620 - } 16621 + memset(&addr, 0, sizeof(struct sockaddr_in)); 16622 16623 - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 16624 - fprintf(stderr,programName); 16625 - perror(": ListenAtTcpPort: bind"); 16626 - close(sock); 16627 - return -1; 16628 - } 16629 + addr.sin_family = AF_INET; 16630 + addr.sin_port = htons(port); 16631 + addr.sin_addr.s_addr = INADDR_ANY; 16632 16633 - if (listen(sock, 5) < 0) { 16634 - fprintf(stderr,programName); 16635 - perror(": ListenAtTcpPort: listen"); 16636 - close(sock); 16637 - return -1; 16638 - } 16639 + if (getenv("VNCVIEWER_LISTEN_LOCALHOST") || use_loopback) { 16640 + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 16641 + } 16642 + 16643 + sock = socket(AF_INET, SOCK_STREAM, 0); 16644 + if (sock < 0) { 16645 + perror("ListenAtTcpPort: socket"); 16646 + return -1; 16647 + } 16648 16649 - return sock; 16650 + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, sizeof(one)) < 0) { 16651 + perror("ListenAtTcpPort: setsockopt"); 16652 + close(sock); 16653 + return -1; 16654 + } 16655 + 16656 + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 16657 + perror("ListenAtTcpPort: bind"); 16658 + close(sock); 16659 + return -1; 16660 + } 16661 + 16662 + if (listen(sock, 32) < 0) { 16663 + perror("ListenAtTcpPort: listen"); 16664 + close(sock); 16665 + return -1; 16666 + } 16667 + 16668 + return sock; 16669 +} 16670 + 16671 +int ListenAtTcpPort6(int port) { 16672 + int sock = -1; 16673 +#ifdef AF_INET6 16674 + struct sockaddr_in6 sin; 16675 + int one = 1; 16676 + 16677 + if (appData.noipv6) { 16678 + fprintf(stderr, "ipv6 is disabled via VNCVIEWER_NO_IPV6/-noipv6.\n"); 16679 + return -1; 16680 + } 16681 + 16682 + sock = socket(AF_INET6, SOCK_STREAM, 0); 16683 + if (sock < 0) { 16684 + perror("ListenAtTcpPort[ipv6]: socket"); 16685 + return -1; 16686 + } 16687 + 16688 + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) { 16689 + perror("ListenAtTcpPort[ipv6]: setsockopt1"); 16690 + close(sock); 16691 + return -1; 16692 + } 16693 + 16694 +#if defined(SOL_IPV6) && defined(IPV6_V6ONLY) 16695 + if (setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) < 0) { 16696 + perror("ListenAtTcpPort[ipv6]: setsockopt2"); 16697 + close(sock); 16698 + return -1; 16699 + } 16700 +#endif 16701 + 16702 + memset((char *)&sin, 0, sizeof(sin)); 16703 + sin.sin6_family = AF_INET6; 16704 + sin.sin6_port = htons(port); 16705 + sin.sin6_addr = in6addr_any; 16706 + 16707 + if (getenv("VNCVIEWER_LISTEN_LOCALHOST") || use_loopback) { 16708 + sin.sin6_addr = in6addr_loopback; 16709 + } 16710 + 16711 + if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { 16712 + perror("ListenAtTcpPort[ipv6]: bind"); 16713 + close(sock); 16714 + return -1; 16715 + } 16716 + 16717 + if (listen(sock, 32) < 0) { 16718 + perror("ListenAtTcpPort[ipv6]: listen"); 16719 + close(sock); 16720 + return -1; 16721 + } 16722 + 16723 +#endif 16724 + if (port) {} 16725 + return sock; 16726 } 16727 16728 16729 @@ -320,33 +1012,69 @@ 16730 * AcceptTcpConnection accepts a TCP connection. 16731 */ 16732 16733 -int 16734 -AcceptTcpConnection(int listenSock) 16735 -{ 16736 - int sock; 16737 - struct sockaddr_in addr; 16738 - int addrlen = sizeof(addr); 16739 - int one = 1; 16740 +int AcceptTcpConnection(int listenSock) { 16741 + int sock; 16742 + struct sockaddr_in addr; 16743 + int addrlen = sizeof(addr); 16744 + int one = 1; 16745 + 16746 + sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen); 16747 + if (sock < 0) { 16748 + perror("AcceptTcpConnection: accept"); 16749 + return -1; 16750 + } 16751 16752 - sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen); 16753 - if (sock < 0) { 16754 - fprintf(stderr,programName); 16755 - perror(": AcceptTcpConnection: accept"); 16756 - return -1; 16757 - } 16758 + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { 16759 + perror("AcceptTcpConnection: setsockopt"); 16760 + close(sock); 16761 + return -1; 16762 + } 16763 16764 - if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, 16765 - (char *)&one, sizeof(one)) < 0) { 16766 - fprintf(stderr,programName); 16767 - perror(": AcceptTcpConnection: setsockopt"); 16768 - close(sock); 16769 - return -1; 16770 - } 16771 + return sock; 16772 +} 16773 + 16774 +char *accept6_ipaddr = NULL; 16775 +char *accept6_hostname = NULL; 16776 + 16777 +int AcceptTcpConnection6(int listenSock) { 16778 + int sock = -1; 16779 +#ifdef AF_INET6 16780 + struct sockaddr_in6 addr; 16781 + socklen_t addrlen = sizeof(addr); 16782 + int one = 1; 16783 + char *name; 16784 + 16785 + if (appData.noipv6) { 16786 + return -1; 16787 + } 16788 + 16789 + sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen); 16790 + if (sock < 0) { 16791 + perror("AcceptTcpConnection[ipv6]: accept"); 16792 + return -1; 16793 + } 16794 + 16795 + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) { 16796 + perror("AcceptTcpConnection[ipv6]: setsockopt"); 16797 + close(sock); 16798 + return -1; 16799 + } 16800 16801 - return sock; 16802 + name = ipv6_getipaddr((struct sockaddr *) &addr, addrlen); 16803 + if (!name) name = strdup("unknown"); 16804 + accept6_ipaddr = name; 16805 + fprintf(stderr, "AcceptTcpConnection6: ipv6 connection from: '%s'\n", name); 16806 + 16807 + name = ipv6_getnameinfo((struct sockaddr *) &addr, addrlen); 16808 + if (!name) name = strdup("unknown"); 16809 + accept6_hostname = name; 16810 +#endif 16811 + if (listenSock) {} 16812 + return sock; 16813 } 16814 16815 16816 + 16817 /* 16818 * SetNonBlocking sets a socket into non-blocking mode. 16819 */ 16820 @@ -379,7 +1107,7 @@ 16821 16822 *addr = inet_addr(str); 16823 16824 - if (*addr != -1) 16825 + if (*addr != (unsigned int) -1) 16826 return True; 16827 16828 hp = gethostbyname(str); 16829 @@ -392,6 +1120,42 @@ 16830 return False; 16831 } 16832 16833 +char *get_peer_ip(int sock) { 16834 + struct sockaddr_in saddr; 16835 + unsigned int saddr_len; 16836 + int saddr_port; 16837 + char *saddr_ip_str = NULL; 16838 + 16839 + saddr_len = sizeof(saddr); 16840 + memset(&saddr, 0, sizeof(saddr)); 16841 + saddr_port = -1; 16842 + if (!getpeername(sock, (struct sockaddr *)&saddr, &saddr_len)) { 16843 + saddr_ip_str = inet_ntoa(saddr.sin_addr); 16844 + } 16845 + if (! saddr_ip_str) { 16846 + saddr_ip_str = "unknown"; 16847 + } 16848 + return strdup(saddr_ip_str); 16849 +} 16850 + 16851 +char *ip2host(char *ip) { 16852 + char *str; 16853 + struct hostent *hp; 16854 + in_addr_t iaddr; 16855 + 16856 + iaddr = inet_addr(ip); 16857 + if (iaddr == htonl(INADDR_NONE)) { 16858 + return strdup("unknown"); 16859 + } 16860 + 16861 + hp = gethostbyaddr((char *)&iaddr, sizeof(in_addr_t), AF_INET); 16862 + if (!hp) { 16863 + return strdup("unknown"); 16864 + } 16865 + str = strdup(hp->h_name); 16866 + return str; 16867 +} 16868 + 16869 16870 /* 16871 * Test if the other end of a socket is on the same machine. 16872 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tight.c vnc_unixsrc/vncviewer/tight.c 16873 --- vnc_unixsrc.orig/vncviewer/tight.c 2002-04-30 09:07:31.000000000 -0400 16874 +++ vnc_unixsrc/vncviewer/tight.c 2008-10-05 15:16:35.000000000 -0400 16875 @@ -129,14 +129,21 @@ 16876 #endif 16877 16878 #if (BPP == 8) 16879 - gcv.foreground = (appData.useBGR233) ? 16880 - BGR233ToPixel[fill_colour] : fill_colour; 16881 + gcv.foreground = (appData.useBGR233) ? BGR233ToPixel[fill_colour] : fill_colour; 16882 +#else 16883 +#if (BPP == 16) 16884 + gcv.foreground = (appData.useBGR565) ? BGR565ToPixel[fill_colour] : fill_colour; 16885 #else 16886 gcv.foreground = fill_colour; 16887 #endif 16888 +#endif 16889 16890 - XChangeGC(dpy, gc, GCForeground, &gcv); 16891 - XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); 16892 + if (!appData.useXserverBackingStore) { 16893 + FillScreen(rx, ry, rw, rh, gcv.foreground); 16894 + } else { 16895 + XChangeGC(dpy, gc, GCForeground, &gcv); 16896 + XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); 16897 + } 16898 return True; 16899 } 16900 16901 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tmake vnc_unixsrc/vncviewer/tmake 16902 --- vnc_unixsrc.orig/vncviewer/tmake 1969-12-31 19:00:00.000000000 -0500 16903 +++ vnc_unixsrc/vncviewer/tmake 2009-10-25 10:31:22.000000000 -0400 16904 @@ -0,0 +1,17 @@ 16905 +#!/bin/sh 16906 +TURBOVNC_DIR=/home/runge/turbojpeg 16907 +make clean 16908 +(cd ../libvncauth || exit 1; make) 16909 +if [ "X$1" = "X-a" ]; then 16910 + exit 16911 +fi 16912 +make CCOPTIONS=-DTURBOVNC EXTRA_LIBRARIES="-L$TURBOVNC_DIR -Xlinker --rpath=$TURBOVNC_DIR -Xlinker --rpath=/usr/local/lib -lturbojpeg" 16913 +cp -p vncviewer vncviewer.turbovnc 16914 +strip vncviewer.turbovnc 16915 +ls -l vncviewer.turbovnc 16916 +ldd vncviewer.turbovnc 16917 + 16918 +echo 16919 +make clean all 16920 +ls -l vncviewer 16921 +ldd vncviewer 16922 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tunnel.c vnc_unixsrc/vncviewer/tunnel.c 16923 --- vnc_unixsrc.orig/vncviewer/tunnel.c 2003-07-31 04:03:49.000000000 -0400 16924 +++ vnc_unixsrc/vncviewer/tunnel.c 2010-02-25 23:39:24.000000000 -0500 16925 @@ -100,7 +100,6 @@ 16926 int *pargc, char **argv, int tunnelArgIndex) 16927 { 16928 char *pdisplay; 16929 - int port; 16930 16931 if (tunnelArgIndex >= *pargc - 1) 16932 usage(); 16933 @@ -132,6 +131,7 @@ 16934 { 16935 char *colonPos; 16936 int len, portOffset; 16937 + int disp; 16938 16939 if (tunnelArgIndex >= *pargc - 2) 16940 usage(); 16941 @@ -150,10 +150,17 @@ 16942 len--; 16943 portOffset = 0; 16944 } 16945 - if (!len || strspn(colonPos, "-0123456789") != len) { 16946 + if (!len || (int) strspn(colonPos, "-0123456789") != len) { 16947 usage(); 16948 } 16949 +#if 0 16950 *remotePort = atoi(colonPos) + portOffset; 16951 +#else 16952 + disp = atoi(colonPos); 16953 + if (portOffset != 0 && disp >= 100) 16954 + portOffset = 0; 16955 + *remotePort = disp + portOffset; 16956 +#endif 16957 } 16958 16959 sprintf(lastArgv, "localhost::%d", localPort); 16960 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/turbovnc/tight.c vnc_unixsrc/vncviewer/turbovnc/tight.c 16961 --- vnc_unixsrc.orig/vncviewer/turbovnc/tight.c 1969-12-31 19:00:00.000000000 -0500 16962 +++ vnc_unixsrc/vncviewer/turbovnc/tight.c 2008-08-20 13:35:58.000000000 -0400 16963 @@ -0,0 +1,613 @@ 16964 +/* 16965 + * Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved. 16966 + * Copyright (C) 2004 Landmark Graphics Corporation. All Rights Reserved. 16967 + * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. 16968 + * 16969 + * This is free software; you can redistribute it and/or modify 16970 + * it under the terms of the GNU General Public License as published by 16971 + * the Free Software Foundation; either version 2 of the License, or 16972 + * (at your option) any later version. 16973 + * 16974 + * This software is distributed in the hope that it will be useful, 16975 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16976 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16977 + * GNU General Public License for more details. 16978 + * 16979 + * You should have received a copy of the GNU General Public License 16980 + * along with this software; if not, write to the Free Software 16981 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 16982 + * USA. 16983 + */ 16984 + 16985 +/* 16986 + * tight.c - handle ``tight'' encoding. 16987 + * 16988 + * This file shouldn't be compiled directly. It is included multiple 16989 + * times by rfbproto.c, each time with a different definition of the 16990 + * macro BPP. For each value of BPP, this file defines a function 16991 + * which handles a tight-encoded rectangle with BPP bits per pixel. 16992 + * 16993 + */ 16994 + 16995 +#define TIGHT_MIN_TO_COMPRESS 12 16996 + 16997 +#define CARDBPP CONCAT2E(CARD,BPP) 16998 +#define filterPtrBPP CONCAT2E(filterPtr,BPP) 16999 + 17000 +#define HandleTightBPP CONCAT2E(HandleTight,BPP) 17001 +#define InitFilterCopyBPP CONCAT2E(InitFilterCopy,BPP) 17002 +#define InitFilterPaletteBPP CONCAT2E(InitFilterPalette,BPP) 17003 +#define InitFilterGradientBPP CONCAT2E(InitFilterGradient,BPP) 17004 +#define FilterCopyBPP CONCAT2E(FilterCopy,BPP) 17005 +#define FilterPaletteBPP CONCAT2E(FilterPalette,BPP) 17006 +#define FilterGradientBPP CONCAT2E(FilterGradient,BPP) 17007 + 17008 +#if BPP != 8 17009 +#define DecompressJpegRectBPP CONCAT2E(DecompressJpegRect,BPP) 17010 +#endif 17011 + 17012 +#ifndef RGB_TO_PIXEL 17013 + 17014 +#define RGB_TO_PIXEL(bpp,r,g,b) \ 17015 + (((CARD##bpp)(r) & myFormat.redMax) << myFormat.redShift | \ 17016 + ((CARD##bpp)(g) & myFormat.greenMax) << myFormat.greenShift | \ 17017 + ((CARD##bpp)(b) & myFormat.blueMax) << myFormat.blueShift) 17018 + 17019 +#define RGB24_TO_PIXEL(bpp,r,g,b) \ 17020 + ((((CARD##bpp)(r) & 0xFF) * myFormat.redMax + 127) / 255 \ 17021 + << myFormat.redShift | \ 17022 + (((CARD##bpp)(g) & 0xFF) * myFormat.greenMax + 127) / 255 \ 17023 + << myFormat.greenShift | \ 17024 + (((CARD##bpp)(b) & 0xFF) * myFormat.blueMax + 127) / 255 \ 17025 + << myFormat.blueShift) 17026 + 17027 +#define RGB24_TO_PIXEL32(r,g,b) \ 17028 + (((CARD32)(r) & 0xFF) << myFormat.redShift | \ 17029 + ((CARD32)(g) & 0xFF) << myFormat.greenShift | \ 17030 + ((CARD32)(b) & 0xFF) << myFormat.blueShift) 17031 + 17032 +#endif 17033 + 17034 +extern XImage *image; 17035 + 17036 +/* Type declarations */ 17037 + 17038 +typedef void (*filterPtrBPP)(int, int, int); 17039 + 17040 +/* Prototypes */ 17041 + 17042 +static int InitFilterCopyBPP (int rw, int rh); 17043 +static int InitFilterPaletteBPP (int rw, int rh); 17044 +static int InitFilterGradientBPP (int rw, int rh); 17045 +static void FilterCopyBPP (int srcx, int srcy, int numRows); 17046 +static void FilterPaletteBPP (int srcx, int srcy, int numRows); 17047 +static void FilterGradientBPP (int srcx, int srcy, int numRows); 17048 + 17049 +static Bool DecompressJpegRectBPP(int x, int y, int w, int h); 17050 + 17051 +/* Definitions */ 17052 + 17053 +static Bool 17054 +HandleTightBPP (int rx, int ry, int rw, int rh) 17055 +{ 17056 + CARDBPP fill_colour; 17057 + XGCValues gcv; 17058 + CARD8 comp_ctl; 17059 + CARD8 filter_id; 17060 + filterPtrBPP filterFn; 17061 + z_streamp zs; 17062 + int err, stream_id, compressedLen, bitsPixel; 17063 + int bufferSize, rowSize, numRows; 17064 + Bool readUncompressed = False; 17065 + CARDBPP *rawData; 17066 + 17067 + if (!ReadFromRFBServer((char *)&comp_ctl, 1)) 17068 + return False; 17069 + 17070 + /* Flush zlib streams if we are told by the server to do so. */ 17071 + for (stream_id = 0; stream_id < 4; stream_id++) { 17072 + if ((comp_ctl & 1) && zlibStreamActive[stream_id]) { 17073 + if (inflateEnd (&zlibStream[stream_id]) != Z_OK && 17074 + zlibStream[stream_id].msg != NULL) 17075 + fprintf(stderr, "inflateEnd: %s\n", zlibStream[stream_id].msg); 17076 + zlibStreamActive[stream_id] = False; 17077 + } 17078 + comp_ctl >>= 1; 17079 + } 17080 + 17081 + if ((comp_ctl & rfbTightNoZlib) == rfbTightNoZlib) { 17082 + comp_ctl &= ~(rfbTightNoZlib); 17083 + readUncompressed = True; 17084 + } 17085 + 17086 + /* Handle solid rectangles. */ 17087 + if (comp_ctl == rfbTightFill) { 17088 +#if BPP == 32 17089 + if (myFormat.depth == 24 && myFormat.redMax == 0xFF && 17090 + myFormat.greenMax == 0xFF && myFormat.blueMax == 0xFF) { 17091 + if (!ReadFromRFBServer(buffer, 3)) 17092 + return False; 17093 + fill_colour = RGB24_TO_PIXEL32(buffer[0], buffer[1], buffer[2]); 17094 + } else { 17095 + if (!ReadFromRFBServer((char*)&fill_colour, sizeof(fill_colour))) 17096 + return False; 17097 + } 17098 +#else 17099 + if (!ReadFromRFBServer((char*)&fill_colour, sizeof(fill_colour))) 17100 + return False; 17101 +#endif 17102 + 17103 +#if (BPP == 8) 17104 + gcv.foreground = (appData.useBGR233) ? 17105 + BGR233ToPixel[fill_colour] : fill_colour; 17106 +#else 17107 + gcv.foreground = fill_colour; 17108 +#endif 17109 + 17110 + FillRectangle(&gcv, rx, ry, rw, rh); 17111 + return True; 17112 + } 17113 + 17114 +#if BPP == 8 17115 + if (comp_ctl == rfbTightJpeg) { 17116 + fprintf(stderr, "Tight encoding: JPEG is not supported in 8 bpp mode.\n"); 17117 + return False; 17118 + } 17119 +#else 17120 + if (comp_ctl == rfbTightJpeg) { 17121 + return DecompressJpegRectBPP(rx, ry, rw, rh); 17122 + } 17123 +#endif 17124 + 17125 + /* Quit on unsupported subencoding value. */ 17126 + if (comp_ctl > rfbTightMaxSubencoding) { 17127 + fprintf(stderr, "Tight encoding: bad subencoding value received.\n"); 17128 + return False; 17129 + } 17130 + 17131 + /* 17132 + * Here primary compression mode handling begins. 17133 + * Data was processed with optional filter + zlib compression. 17134 + */ 17135 + 17136 + /* First, we should identify a filter to use. */ 17137 + if ((comp_ctl & rfbTightExplicitFilter) != 0) { 17138 + if (!ReadFromRFBServer((char*)&filter_id, 1)) 17139 + return False; 17140 + 17141 + switch (filter_id) { 17142 + case rfbTightFilterCopy: 17143 + filterFn = FilterCopyBPP; 17144 + bitsPixel = InitFilterCopyBPP(rw, rh); 17145 + break; 17146 + case rfbTightFilterPalette: 17147 + filterFn = FilterPaletteBPP; 17148 + bitsPixel = InitFilterPaletteBPP(rw, rh); 17149 + break; 17150 + case rfbTightFilterGradient: 17151 + filterFn = FilterGradientBPP; 17152 + bitsPixel = InitFilterGradientBPP(rw, rh); 17153 + break; 17154 + default: 17155 + fprintf(stderr, "Tight encoding: unknown filter code received.\n"); 17156 + return False; 17157 + } 17158 + } else { 17159 + filterFn = FilterCopyBPP; 17160 + bitsPixel = InitFilterCopyBPP(rw, rh); 17161 + } 17162 + if (bitsPixel == 0) { 17163 + fprintf(stderr, "Tight encoding: error receiving palette.\n"); 17164 + return False; 17165 + } 17166 + 17167 + /* Determine if the data should be decompressed or just copied. */ 17168 + rowSize = (rw * bitsPixel + 7) / 8; 17169 + bufferSize = -1; 17170 + if (rh * rowSize < TIGHT_MIN_TO_COMPRESS) 17171 + bufferSize = rh * rowSize; 17172 + else if (readUncompressed) { 17173 + bufferSize = (int)ReadCompactLen(); 17174 + } 17175 + if (bufferSize != -1) { 17176 + uncompressedData = (char *)realloc(uncompressedData, bufferSize); 17177 + if (!uncompressedData) { 17178 + fprintf(stderr, "Memory allocation error\n"); 17179 + return False; 17180 + } 17181 + if (!ReadFromRFBServer(uncompressedData, bufferSize)) 17182 + return False; 17183 + filterFn(rx, ry, rh); 17184 + if (appData.useBGR233) CopyDataToImage(buffer, rx, ry, rw, rh); 17185 + if (!appData.doubleBuffer) CopyImageToScreen(rx, ry, rw, rh); 17186 + 17187 + return True; 17188 + } 17189 + 17190 + /* Read the length (1..3 bytes) of compressed data following. */ 17191 + compressedLen = (int)ReadCompactLen(); 17192 + if (compressedLen <= 0) { 17193 + fprintf(stderr, "Incorrect data received from the server.\n"); 17194 + return False; 17195 + } 17196 + 17197 + /* Now let's initialize compression stream if needed. */ 17198 + stream_id = comp_ctl & 0x03; 17199 + zs = &zlibStream[stream_id]; 17200 + if (!zlibStreamActive[stream_id]) { 17201 + zs->zalloc = Z_NULL; 17202 + zs->zfree = Z_NULL; 17203 + zs->opaque = Z_NULL; 17204 + err = inflateInit(zs); 17205 + if (err != Z_OK) { 17206 + if (zs->msg != NULL) 17207 + fprintf(stderr, "InflateInit error: %s.\n", zs->msg); 17208 + return False; 17209 + } 17210 + zlibStreamActive[stream_id] = True; 17211 + } 17212 + 17213 + /* Read, decode and draw actual pixel data in a loop. */ 17214 + 17215 + compressedData = (char *)realloc(compressedData, compressedLen); 17216 + if (!compressedData) { 17217 + fprintf(stderr, "Memory allocation error\n"); 17218 + return False; 17219 + } 17220 + uncompressedData = (char *)realloc(uncompressedData, rh * rowSize); 17221 + if (!uncompressedData) { 17222 + fprintf(stderr, "Memory allocation error\n"); 17223 + return False; 17224 + } 17225 + 17226 + if (!ReadFromRFBServer(compressedData, compressedLen)) 17227 + return False; 17228 + zs->next_in = (Bytef *)compressedData; 17229 + zs->avail_in = compressedLen; 17230 + zs->next_out = (Bytef *)uncompressedData; 17231 + zs->avail_out = rh * rowSize; 17232 + 17233 + err = inflate(zs, Z_SYNC_FLUSH); 17234 + if (err != Z_OK && err != Z_STREAM_END) { 17235 + if (zs->msg != NULL) { 17236 + fprintf(stderr, "Inflate error: %s.\n", zs->msg); 17237 + } else { 17238 + fprintf(stderr, "Inflate error: %d.\n", err); 17239 + } 17240 + return False; 17241 + } 17242 + 17243 + filterFn(rx, ry, rh); 17244 + if (appData.useBGR233) CopyDataToImage(buffer, rx, ry, rw, rh); 17245 + if (!appData.doubleBuffer) CopyImageToScreen(rx, ry, rw, rh); 17246 + 17247 + return True; 17248 +} 17249 + 17250 +/*---------------------------------------------------------------------------- 17251 + * 17252 + * Filter stuff. 17253 + * 17254 + */ 17255 + 17256 +/* 17257 + The following variables are defined in rfbproto.c: 17258 + static Bool cutZeros; 17259 + static int rectWidth, rectColors; 17260 + static CARD8 tightPalette[256*4]; 17261 + static CARD8 tightPrevRow[2048*3*sizeof(CARD16)]; 17262 +*/ 17263 + 17264 +static int 17265 +InitFilterCopyBPP (int rw, int rh) 17266 +{ 17267 + rectWidth = rw; 17268 + 17269 +#if BPP == 32 17270 + if (myFormat.depth == 24 && myFormat.redMax == 0xFF && 17271 + myFormat.greenMax == 0xFF && myFormat.blueMax == 0xFF) { 17272 + cutZeros = True; 17273 + return 24; 17274 + } else { 17275 + cutZeros = False; 17276 + } 17277 +#endif 17278 + 17279 + return BPP; 17280 +} 17281 + 17282 +static void 17283 +FilterCopyBPP (int srcx, int srcy, int numRows) 17284 +{ 17285 + CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line 17286 + + srcx * image->bits_per_pixel/8]; 17287 + int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); 17288 + int y; 17289 +#if BPP == 32 17290 + int x; 17291 +#endif 17292 + 17293 + if (appData.useBGR233) { 17294 + dst = (CARDBPP *)buffer; 17295 + dstw = rectWidth; 17296 + } 17297 + 17298 +#if BPP == 32 17299 + if (cutZeros) { 17300 + for (y = 0; y < numRows; y++) { 17301 + for (x = 0; x < rectWidth; x++) { 17302 + dst[y*dstw+x] = 17303 + RGB24_TO_PIXEL32(uncompressedData[(y*rectWidth+x)*3], 17304 + uncompressedData[(y*rectWidth+x)*3+1], 17305 + uncompressedData[(y*rectWidth+x)*3+2]); 17306 + } 17307 + } 17308 + return; 17309 + } 17310 +#endif 17311 + 17312 + for (y = 0; y < numRows; y++) 17313 + memcpy (&dst[y*dstw], &uncompressedData[y*rectWidth], rectWidth * (BPP / 8)); 17314 +} 17315 + 17316 +static int 17317 +InitFilterGradientBPP (int rw, int rh) 17318 +{ 17319 + int bits; 17320 + 17321 + bits = InitFilterCopyBPP(rw, rh); 17322 + if (cutZeros) 17323 + memset(tightPrevRow, 0, rw * 3); 17324 + else 17325 + memset(tightPrevRow, 0, rw * 3 * sizeof(CARD16)); 17326 + 17327 + return bits; 17328 +} 17329 + 17330 +#if BPP == 32 17331 + 17332 +static void 17333 +FilterGradient24 (int srcx, int srcy, int numRows) 17334 +{ 17335 + CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line 17336 + + srcx * image->bits_per_pixel/8]; 17337 + int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); 17338 + int x, y, c; 17339 + CARD8 thisRow[2048*3]; 17340 + CARD8 pix[3]; 17341 + int est[3]; 17342 + 17343 + if (appData.useBGR233) { 17344 + dst = (CARDBPP *)buffer; 17345 + dstw = rectWidth; 17346 + } 17347 + 17348 + for (y = 0; y < numRows; y++) { 17349 + 17350 + /* First pixel in a row */ 17351 + for (c = 0; c < 3; c++) { 17352 + pix[c] = tightPrevRow[c] + uncompressedData[y*rectWidth*3+c]; 17353 + thisRow[c] = pix[c]; 17354 + } 17355 + dst[y*dstw] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); 17356 + 17357 + /* Remaining pixels of a row */ 17358 + for (x = 1; x < rectWidth; x++) { 17359 + for (c = 0; c < 3; c++) { 17360 + est[c] = (int)tightPrevRow[x*3+c] + (int)pix[c] - 17361 + (int)tightPrevRow[(x-1)*3+c]; 17362 + if (est[c] > 0xFF) { 17363 + est[c] = 0xFF; 17364 + } else if (est[c] < 0x00) { 17365 + est[c] = 0x00; 17366 + } 17367 + pix[c] = (CARD8)est[c] + buffer[(y*rectWidth+x)*3+c]; 17368 + thisRow[x*3+c] = pix[c]; 17369 + } 17370 + dst[y*dstw+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); 17371 + } 17372 + 17373 + memcpy(tightPrevRow, thisRow, rectWidth * 3); 17374 + } 17375 +} 17376 + 17377 +#endif 17378 + 17379 +static void 17380 +FilterGradientBPP (int srcx, int srcy, int numRows) 17381 +{ 17382 + int x, y, c; 17383 + CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line 17384 + + srcx * image->bits_per_pixel/8]; 17385 + int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); 17386 + CARDBPP *src = (CARDBPP *)uncompressedData; 17387 + CARD16 *thatRow = (CARD16 *)tightPrevRow; 17388 + CARD16 thisRow[2048*3]; 17389 + CARD16 pix[3]; 17390 + CARD16 max[3]; 17391 + int shift[3]; 17392 + int est[3]; 17393 + 17394 + if (appData.useBGR233) { 17395 + dst = (CARDBPP *)buffer; 17396 + dstw = rectWidth; 17397 + } 17398 + 17399 +#if BPP == 32 17400 + if (cutZeros) { 17401 + FilterGradient24(srcx, srcy, numRows); 17402 + return; 17403 + } 17404 +#endif 17405 + 17406 + max[0] = myFormat.redMax; 17407 + max[1] = myFormat.greenMax; 17408 + max[2] = myFormat.blueMax; 17409 + 17410 + shift[0] = myFormat.redShift; 17411 + shift[1] = myFormat.greenShift; 17412 + shift[2] = myFormat.blueShift; 17413 + 17414 + for (y = 0; y < numRows; y++) { 17415 + 17416 + /* First pixel in a row */ 17417 + for (c = 0; c < 3; c++) { 17418 + pix[c] = (CARD16)((src[y*rectWidth] >> shift[c]) + thatRow[c] & max[c]); 17419 + thisRow[c] = pix[c]; 17420 + } 17421 + dst[y*dstw] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); 17422 + 17423 + /* Remaining pixels of a row */ 17424 + for (x = 1; x < rectWidth; x++) { 17425 + for (c = 0; c < 3; c++) { 17426 + est[c] = (int)thatRow[x*3+c] + (int)pix[c] - (int)thatRow[(x-1)*3+c]; 17427 + if (est[c] > (int)max[c]) { 17428 + est[c] = (int)max[c]; 17429 + } else if (est[c] < 0) { 17430 + est[c] = 0; 17431 + } 17432 + pix[c] = (CARD16)((src[y*rectWidth+x] >> shift[c]) + est[c] & max[c]); 17433 + thisRow[x*3+c] = pix[c]; 17434 + } 17435 + dst[y*dstw+x] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); 17436 + } 17437 + memcpy(thatRow, thisRow, rectWidth * 3 * sizeof(CARD16)); 17438 + } 17439 +} 17440 + 17441 +static int 17442 +InitFilterPaletteBPP (int rw, int rh) 17443 +{ 17444 + int i; 17445 + CARD8 numColors; 17446 + CARDBPP *palette = (CARDBPP *)tightPalette; 17447 + 17448 + rectWidth = rw; 17449 + 17450 + if (!ReadFromRFBServer((char*)&numColors, 1)) 17451 + return 0; 17452 + 17453 + rectColors = (int)numColors; 17454 + if (++rectColors < 2) 17455 + return 0; 17456 + 17457 +#if BPP == 32 17458 + if (myFormat.depth == 24 && myFormat.redMax == 0xFF && 17459 + myFormat.greenMax == 0xFF && myFormat.blueMax == 0xFF) { 17460 + if (!ReadFromRFBServer((char*)&tightPalette, rectColors * 3)) 17461 + return 0; 17462 + for (i = rectColors - 1; i >= 0; i--) { 17463 + palette[i] = RGB24_TO_PIXEL32(tightPalette[i*3], 17464 + tightPalette[i*3+1], 17465 + tightPalette[i*3+2]); 17466 + } 17467 + return (rectColors == 2) ? 1 : 8; 17468 + } 17469 +#endif 17470 + 17471 + if (!ReadFromRFBServer((char*)&tightPalette, rectColors * (BPP / 8))) 17472 + return 0; 17473 + 17474 + return (rectColors == 2) ? 1 : 8; 17475 +} 17476 + 17477 +static void 17478 +FilterPaletteBPP (int srcx, int srcy, int numRows) 17479 +{ 17480 + int x, y, b, w; 17481 + CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line 17482 + + srcx * image->bits_per_pixel/8]; 17483 + int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); 17484 + CARD8 *src = (CARD8 *)uncompressedData; 17485 + CARDBPP *palette = (CARDBPP *)tightPalette; 17486 + 17487 + if (appData.useBGR233) { 17488 + dst = (CARDBPP *)buffer; 17489 + dstw = rectWidth; 17490 + } 17491 + 17492 + if (rectColors == 2) { 17493 + w = (rectWidth + 7) / 8; 17494 + for (y = 0; y < numRows; y++) { 17495 + for (x = 0; x < rectWidth / 8; x++) { 17496 + for (b = 7; b >= 0; b--) 17497 + dst[y*dstw+x*8+7-b] = palette[src[y*w+x] >> b & 1]; 17498 + } 17499 + for (b = 7; b >= 8 - rectWidth % 8; b--) { 17500 + dst[y*dstw+x*8+7-b] = palette[src[y*w+x] >> b & 1]; 17501 + } 17502 + } 17503 + } else { 17504 + for (y = 0; y < numRows; y++) 17505 + for (x = 0; x < rectWidth; x++) 17506 + dst[y*dstw+x] = palette[(int)src[y*rectWidth+x]]; 17507 + } 17508 +} 17509 + 17510 +#if BPP != 8 17511 + 17512 +/*---------------------------------------------------------------------------- 17513 + * 17514 + * JPEG decompression. 17515 + * 17516 + */ 17517 + 17518 +/* 17519 + The following variables are defined in rfbproto.c: 17520 + static Bool jpegError; 17521 + static struct jpeg_source_mgr jpegSrcManager; 17522 + static JOCTET *jpegBufferPtr; 17523 + static size_t *jpegBufferLen; 17524 +*/ 17525 + 17526 +static Bool 17527 +DecompressJpegRectBPP(int x, int y, int w, int h) 17528 +{ 17529 + int compressedLen; 17530 + char *dstptr; 17531 + int ps, flags=0; 17532 + 17533 + compressedLen = (int)ReadCompactLen(); 17534 + if (compressedLen <= 0) { 17535 + fprintf(stderr, "Incorrect data received from the server.\n"); 17536 + return False; 17537 + } 17538 + 17539 + compressedData = (char *)realloc(compressedData, compressedLen); 17540 + if (compressedData == NULL) { 17541 + fprintf(stderr, "Memory allocation error.\n"); 17542 + return False; 17543 + } 17544 + 17545 + if (!ReadFromRFBServer(compressedData, compressedLen)) { 17546 + return False; 17547 + } 17548 + 17549 + if(!tjhnd) { 17550 + if((tjhnd=tjInitDecompress())==NULL) { 17551 + fprintf(stderr, "TurboJPEG error: %s\n", tjGetErrorStr()); 17552 + return False; 17553 + } 17554 + } 17555 + 17556 + ps=image->bits_per_pixel/8; 17557 + if(myFormat.bigEndian && ps==4) flags|=TJ_ALPHAFIRST; 17558 + if(myFormat.redShift==16 && myFormat.blueShift==0) 17559 + flags|=TJ_BGR; 17560 + if(myFormat.bigEndian) flags^=TJ_BGR; 17561 + 17562 + dstptr=&image->data[image->bytes_per_line*y+x*ps]; 17563 + if(tjDecompress(tjhnd, (unsigned char *)compressedData, (unsigned long)compressedLen, 17564 + (unsigned char *)dstptr, w, image->bytes_per_line, h, ps, flags)==-1) { 17565 + fprintf(stderr, "TurboJPEG error: %s\n", tjGetErrorStr()); 17566 + return False; 17567 + } 17568 + 17569 + if (!appData.doubleBuffer) 17570 + CopyImageToScreen(x, y, w, h); 17571 + 17572 + return True; 17573 +} 17574 + 17575 +#endif 17576 + 17577 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/turbovnc/turbojpeg.h vnc_unixsrc/vncviewer/turbovnc/turbojpeg.h 17578 --- vnc_unixsrc.orig/vncviewer/turbovnc/turbojpeg.h 1969-12-31 19:00:00.000000000 -0500 17579 +++ vnc_unixsrc/vncviewer/turbovnc/turbojpeg.h 2008-04-03 04:28:56.000000000 -0400 17580 @@ -0,0 +1,229 @@ 17581 +/* Copyright (C)2004 Landmark Graphics 17582 + * Copyright (C)2005, 2006 Sun Microsystems, Inc. 17583 + * 17584 + * This library is free software and may be redistributed and/or modified under 17585 + * the terms of the wxWindows Library License, Version 3.1 or (at your option) 17586 + * any later version. The full license is in the LICENSE.txt file included 17587 + * with this distribution. 17588 + * 17589 + * This library is distributed in the hope that it will be useful, 17590 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17591 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17592 + * wxWindows Library License for more details. 17593 + */ 17594 + 17595 +#if (defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)) && defined(_WIN32) && defined(DLLDEFINE) 17596 +#define DLLEXPORT __declspec(dllexport) 17597 +#else 17598 +#define DLLEXPORT 17599 +#endif 17600 + 17601 +#define DLLCALL 17602 + 17603 +/* Subsampling */ 17604 +#define NUMSUBOPT 4 17605 + 17606 +enum {TJ_444=0, TJ_422, TJ_411, TJ_GRAYSCALE}; 17607 + 17608 +/* Flags */ 17609 +#define TJ_BGR 1 17610 +#define TJ_BOTTOMUP 2 17611 +#define TJ_FORCEMMX 8 /* Force IPP to use MMX code even if SSE available */ 17612 +#define TJ_FORCESSE 16 /* Force IPP to use SSE1 code even if SSE2 available */ 17613 +#define TJ_FORCESSE2 32 /* Force IPP to use SSE2 code (useful if auto-detect is not working properly) */ 17614 +#define TJ_ALPHAFIRST 64 /* BGR buffer is ABGR and RGB buffer is ARGB */ 17615 +#define TJ_FORCESSE3 128 /* Force IPP to use SSE3 code (useful if auto-detect is not working properly) */ 17616 + 17617 +typedef void* tjhandle; 17618 + 17619 +#define TJPAD(p) (((p)+3)&(~3)) 17620 +#ifndef max 17621 + #define max(a,b) ((a)>(b)?(a):(b)) 17622 +#endif 17623 + 17624 +#ifdef __cplusplus 17625 +extern "C" { 17626 +#endif 17627 + 17628 +/* API follows */ 17629 + 17630 + 17631 +/* 17632 + tjhandle tjInitCompress(void) 17633 + 17634 + Creates a new JPEG compressor instance, allocates memory for the structures, 17635 + and returns a handle to the instance. Most applications will only 17636 + need to call this once at the beginning of the program or once for each 17637 + concurrent thread. Don't try to create a new instance every time you 17638 + compress an image, because this will cause performance to suffer. 17639 + 17640 + RETURNS: NULL on error 17641 +*/ 17642 +DLLEXPORT tjhandle DLLCALL tjInitCompress(void); 17643 + 17644 + 17645 +/* 17646 + int tjCompress(tjhandle j, 17647 + unsigned char *srcbuf, int width, int pitch, int height, int pixelsize, 17648 + unsigned char *dstbuf, unsigned long *size, 17649 + int jpegsubsamp, int jpegqual, int flags) 17650 + 17651 + [INPUT] j = instance handle previously returned from a call to 17652 + tjInitCompress() 17653 + [INPUT] srcbuf = pointer to user-allocated image buffer containing pixels in 17654 + RGB(A) or BGR(A) form 17655 + [INPUT] width = width (in pixels) of the source image 17656 + [INPUT] pitch = bytes per line of the source image (width*pixelsize if the 17657 + bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap 17658 + is padded to the nearest 32-bit boundary, such as is the case for Windows 17659 + bitmaps. You can also be clever and use this parameter to skip lines, etc., 17660 + as long as the pitch is greater than 0.) 17661 + [INPUT] height = height (in pixels) of the source image 17662 + [INPUT] pixelsize = size (in bytes) of each pixel in the source image 17663 + RGBA and BGRA: 4, RGB and BGR: 3 17664 + [INPUT] dstbuf = pointer to user-allocated image buffer which will receive 17665 + the JPEG image. Use the macro TJBUFSIZE(width, height) to determine 17666 + the appropriate size for this buffer based on the image width and height. 17667 + [OUTPUT] size = pointer to unsigned long which receives the size (in bytes) 17668 + of the compressed image 17669 + [INPUT] jpegsubsamp = Specifies either 4:1:1, 4:2:2, or 4:4:4 subsampling. 17670 + When the image is converted from the RGB to YCbCr colorspace as part of the 17671 + JPEG compression process, every other Cb and Cr (chrominance) pixel can be 17672 + discarded to produce a smaller image with little perceptible loss of 17673 + image clarity (the human eye is more sensitive to small changes in 17674 + brightness than small changes in color.) 17675 + 17676 + TJ_411: 4:1:1 subsampling. Discards every other Cb, Cr pixel in both 17677 + horizontal and vertical directions. 17678 + TJ_422: 4:2:2 subsampling. Discards every other Cb, Cr pixel only in 17679 + the horizontal direction. 17680 + TJ_444: no subsampling. 17681 + TJ_GRAYSCALE: Generate grayscale JPEG image 17682 + 17683 + [INPUT] jpegqual = JPEG quality (an integer between 0 and 100 inclusive.) 17684 + [INPUT] flags = the bitwise OR of one or more of the following 17685 + 17686 + TJ_BGR: The components of each pixel in the source image are stored in 17687 + B,G,R order, not R,G,B 17688 + TJ_BOTTOMUP: The source image is stored in bottom-up (Windows) order, 17689 + not top-down 17690 + TJ_FORCEMMX: Valid only for the Intel Performance Primitives implementation 17691 + of this codec-- force IPP to use MMX code (bypass CPU auto-detection) 17692 + TJ_FORCESSE: Valid only for the Intel Performance Primitives implementation 17693 + of this codec-- force IPP to use SSE code (bypass CPU auto-detection) 17694 + TJ_FORCESSE2: Valid only for the Intel Performance Primitives implementation 17695 + of this codec-- force IPP to use SSE2 code (bypass CPU auto-detection) 17696 + TJ_FORCESSE3: Valid only for the Intel Performance Primitives implementation 17697 + of this codec-- force IPP to use SSE3 code (bypass CPU auto-detection) 17698 + 17699 + RETURNS: 0 on success, -1 on error 17700 +*/ 17701 +DLLEXPORT int DLLCALL tjCompress(tjhandle j, 17702 + unsigned char *srcbuf, int width, int pitch, int height, int pixelsize, 17703 + unsigned char *dstbuf, unsigned long *size, 17704 + int jpegsubsamp, int jpegqual, int flags); 17705 + 17706 +DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height); 17707 + 17708 +/* 17709 + tjhandle tjInitDecompress(void) 17710 + 17711 + Creates a new JPEG decompressor instance, allocates memory for the 17712 + structures, and returns a handle to the instance. Most applications will 17713 + only need to call this once at the beginning of the program or once for each 17714 + concurrent thread. Don't try to create a new instance every time you 17715 + decompress an image, because this will cause performance to suffer. 17716 + 17717 + RETURNS: NULL on error 17718 +*/ 17719 +DLLEXPORT tjhandle DLLCALL tjInitDecompress(void); 17720 + 17721 + 17722 +/* 17723 + int tjDecompressHeader(tjhandle j, 17724 + unsigned char *srcbuf, unsigned long size, 17725 + int *width, int *height) 17726 + 17727 + [INPUT] j = instance handle previously returned from a call to 17728 + tjInitDecompress() 17729 + [INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image 17730 + to decompress 17731 + [INPUT] size = size of the JPEG image buffer (in bytes) 17732 + [OUTPUT] width = width (in pixels) of the JPEG image 17733 + [OUTPUT] height = height (in pixels) of the JPEG image 17734 + 17735 + RETURNS: 0 on success, -1 on error 17736 +*/ 17737 +DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle j, 17738 + unsigned char *srcbuf, unsigned long size, 17739 + int *width, int *height); 17740 + 17741 + 17742 +/* 17743 + int tjDecompress(tjhandle j, 17744 + unsigned char *srcbuf, unsigned long size, 17745 + unsigned char *dstbuf, int width, int pitch, int height, int pixelsize, 17746 + int flags) 17747 + 17748 + [INPUT] j = instance handle previously returned from a call to 17749 + tjInitDecompress() 17750 + [INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image 17751 + to decompress 17752 + [INPUT] size = size of the JPEG image buffer (in bytes) 17753 + [INPUT] dstbuf = pointer to user-allocated image buffer which will receive 17754 + the bitmap image. This buffer should normally be pitch*height 17755 + bytes in size, although this pointer may also be used to decompress into 17756 + a specific region of a larger buffer. 17757 + [INPUT] width = width (in pixels) of the destination image 17758 + [INPUT] pitch = bytes per line of the destination image (width*pixelsize if the 17759 + bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap 17760 + is padded to the nearest 32-bit boundary, such as is the case for Windows 17761 + bitmaps. You can also be clever and use this parameter to skip lines, etc., 17762 + as long as the pitch is greater than 0.) 17763 + [INPUT] height = height (in pixels) of the destination image 17764 + [INPUT] pixelsize = size (in bytes) of each pixel in the destination image 17765 + RGBA/RGBx and BGRA/BGRx: 4, RGB and BGR: 3 17766 + [INPUT] flags = the bitwise OR of one or more of the following 17767 + 17768 + TJ_BGR: The components of each pixel in the destination image should be 17769 + written in B,G,R order, not R,G,B 17770 + TJ_BOTTOMUP: The destination image should be stored in bottom-up 17771 + (Windows) order, not top-down 17772 + TJ_FORCEMMX: Valid only for the Intel Performance Primitives implementation 17773 + of this codec-- force IPP to use MMX code (bypass CPU auto-detection) 17774 + TJ_FORCESSE: Valid only for the Intel Performance Primitives implementation 17775 + of this codec-- force IPP to use SSE code (bypass CPU auto-detection) 17776 + TJ_FORCESSE2: Valid only for the Intel Performance Primitives implementation 17777 + of this codec-- force IPP to use SSE2 code (bypass CPU auto-detection) 17778 + 17779 + RETURNS: 0 on success, -1 on error 17780 +*/ 17781 +DLLEXPORT int DLLCALL tjDecompress(tjhandle j, 17782 + unsigned char *srcbuf, unsigned long size, 17783 + unsigned char *dstbuf, int width, int pitch, int height, int pixelsize, 17784 + int flags); 17785 + 17786 + 17787 +/* 17788 + int tjDestroy(tjhandle h) 17789 + 17790 + Frees structures associated with a compression or decompression instance 17791 + 17792 + [INPUT] h = instance handle (returned from a previous call to 17793 + tjInitCompress() or tjInitDecompress() 17794 + 17795 + RETURNS: 0 on success, -1 on error 17796 +*/ 17797 +DLLEXPORT int DLLCALL tjDestroy(tjhandle h); 17798 + 17799 + 17800 +/* 17801 + char *tjGetErrorStr(void) 17802 + 17803 + Returns a descriptive error message explaining why the last command failed 17804 +*/ 17805 +DLLEXPORT char* DLLCALL tjGetErrorStr(void); 17806 + 17807 +#ifdef __cplusplus 17808 +} 17809 +#endif 17810 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vncviewer/vncviewer._man 17811 --- vnc_unixsrc.orig/vncviewer/vncviewer._man 1969-12-31 19:00:00.000000000 -0500 17812 +++ vnc_unixsrc/vncviewer/vncviewer._man 2010-04-11 23:30:24.000000000 -0400 17813 @@ -0,0 +1,829 @@ 17814 +'\" t 17815 +.\" ** The above line should force tbl to be a preprocessor ** 17816 +.\" Man page for X vncviewer 17817 +.\" 17818 +.\" Copyright (C) 1998 Marcus.Brinkmann (a] ruhr-uni-bochum.de 17819 +.\" Copyright (C) 2000,2001 Red Hat, Inc. 17820 +.\" Copyright (C) 2001-2003 Constantin Kaplinsky <const (a] ce.cctpu.edu.ru> 17821 +.\" Copyright (C) 2006-2010 Karl J. Runge <runge (a] karlrunge.com> 17822 +.\" 17823 +.\" You may distribute under the terms of the GNU General Public 17824 +.\" License as specified in the file LICENCE.TXT that comes with the 17825 +.\" TightVNC distribution. 17826 +.\" 17827 +.TH ssvncviewer 1 "April 2010" "" "SSVNC" 17828 +.SH NAME 17829 +ssvncviewer \- an X viewer client for VNC 17830 +.SH SYNOPSIS 17831 +.B ssvncviewer 17832 +.RI [\| options \|] 17833 +.RI [\| host \|][\| :display \|] 17834 +.br 17835 +.B ssvncviewer 17836 +.RI [\| options \|] 17837 +.RI [\| host \|][\| ::port \|] 17838 +.br 17839 +.B ssvncviewer 17840 +.RI [\| options \|] 17841 +.RI exec=[\| cmd+args... \|] 17842 +.br 17843 +.B ssvncviewer 17844 +.RI [\| options \|] 17845 +.RI fd=n 17846 +.br 17847 +.B ssvncviewer 17848 +.RI [\| options \|] 17849 +.RI /path/to/unix/socket 17850 +.br 17851 +.B ssvncviewer 17852 +.RI [\| options \|] 17853 +.IR \-listen 17854 +.RI [\| display \|] 17855 +.br 17856 +.B ssvncviewer 17857 +.IR \-help 17858 +.br 17859 +.SH DESCRIPTION 17860 +.B ssvncviewer 17861 +is an Xt\-based client application for the VNC (Virtual Network 17862 +Computing) system. It can connect to any VNC\-compatible server such 17863 +as \fBXvnc\fR, WinVNC, or \fBx11vnc\fR, allowing you to control desktop environment 17864 +of a different machine. 17865 + 17866 +ssvncviewer is an enhanced version of the tightvnc unix viewer that can 17867 +take advantage of features in the \fBx11vnc\fR and UltraVNC VNC servers. 17868 +See below for the description of these features. 17869 + 17870 +You can use F8 to display a pop\-up utility menu. Press F8 twice to 17871 +pass single F8 to the remote side. 17872 +.SH OPTIONS 17873 +.TP 17874 +\fB\-help\fR 17875 +Prints a short usage notice to stderr. 17876 +.TP 17877 +\fB\-listen\fR 17878 +Make the viewer listen on port 5500+\fIdisplay\fR for reverse 17879 +connections from a server. WinVNC supports reverse connections using 17880 +the "Add New Client" menu option, or the \-connect command line 17881 +option. \fBXvnc\fR requires the use of the helper program 17882 +\fBvncconnect\fR. 17883 +.TP 17884 +\fB\-via\fR \fIgateway\fR 17885 +Automatically create encrypted TCP tunnel to the \fIgateway\fR machine 17886 +before connection, connect to the \fIhost\fR through that tunnel 17887 +(TightVNC\-specific). By default, this option invokes SSH local port 17888 +forwarding, assuming that SSH client binary can be accessed as 17889 +/usr/bin/ssh. Note that when using the \fB\-via\fR option, the host 17890 +machine name should be specified as known to the gateway machine, e.g. 17891 +"localhost" denotes the \fIgateway\fR, not the machine where vncviewer 17892 +was launched. See the ENVIRONMENT section below for the information on 17893 +configuring the \fB\-via\fR option. 17894 +.TP 17895 +\fB\-shared\fR 17896 +When connecting, specify that a shared connection is requested. In 17897 +TightVNC, this is the default mode, allowing you to share the desktop 17898 +with other clients already using it. 17899 +.TP 17900 +\fB\-noshared\fR 17901 +When connecting, specify that the session may not be shared. This 17902 +would either disconnect other connected clients or refuse your 17903 +connection, depending on the server configuration. 17904 +.TP 17905 +\fB\-viewonly\fR 17906 +Disable transfer of mouse and keyboard events from the client to the 17907 +server. 17908 +.TP 17909 +\fB\-fullscreen\fR 17910 +Start in full\-screen mode. Please be aware that operating in 17911 +full\-screen mode may confuse X window managers. Typically, such 17912 +conflicts cause incorrect handling of input focus or make the viewer 17913 +window disappear mysteriously. See the grabKeyboard setting in the 17914 +RESOURCES section below for a method to solve input focus problem. 17915 +.TP 17916 +\fB\-noraiseonbeep\fR 17917 +By default, the viewer shows and raises its window on remote beep 17918 +(bell) event. This option disables such behaviour 17919 +(TightVNC\-specific). 17920 +.TP 17921 +\fB\-user\fR \fIusername\fR 17922 +User name for Unix login authentication. Default is to use current 17923 +Unix user name. If this option was given, the viewer will prefer Unix 17924 +login authentication over the standard VNC authentication. 17925 +.TP 17926 +\fB\-passwd\fR \fIpasswd\-file\fR 17927 +File from which to get the password (as generated by the 17928 +\fBvncpasswd\fR(1) program). This option affects only the standard VNC 17929 +authentication. 17930 +.TP 17931 +\fB\-encodings\fR \fIencoding\-list\fR 17932 +TightVNC supports several different compression methods to encode 17933 +screen updates; this option specifies a set of them to use in order of 17934 +preference. Encodings are specified separated with spaces, and must 17935 +thus be enclosed in quotes if more than one is specified. Commas may be used to avoid spaces. 17936 +Available encodings, in default order for a remote connection, are 17937 +"copyrect tight hextile zlib corre rre raw". For a local connection 17938 +(to the same machine), the default order to try is "raw copyrect tight 17939 +hextile zlib corre rre". Raw encoding is always assumed as a last option 17940 +if no other encoding can be used for some reason. For more information 17941 +on encodings, see the section ENCODINGS below. 17942 +.TP 17943 +\fB\-bgr233\fR 17944 +Always use the BGR233 format to encode pixel data. This reduces 17945 +network traffic, but colors may be represented inaccurately. The 17946 +bgr233 format is an 8\-bit "true color" format, with 2 bits blue, 3 17947 +bits green, and 3 bits red. 17948 +.TP 17949 +\fB\-owncmap\fR 17950 +Try to use a PseudoColor visual and a private colormap. This allows 17951 +the VNC server to control the colormap. 17952 +.TP 17953 +\fB\-truecolour\fR, \fB\-truecolor\fR 17954 +Try to use a TrueColor visual. 17955 +.TP 17956 +\fB\-depth\fR \fIdepth\fR 17957 +On an X server which supports multiple TrueColor visuals of different 17958 +depths, attempt to use the specified one (in bits per pixel); if 17959 +successful, this depth will be requested from the VNC server. 17960 +.TP 17961 +\fB\-compresslevel \fIlevel\fR 17962 +Use specified compression \fIlevel\fR (0..9) for "tight" and "zlib" 17963 +encodings (TightVNC\-specific). Level 1 uses minimum of CPU time and 17964 +achieves weak compression ratios, while level 9 offers best 17965 +compression but is slow in terms of CPU time consumption on the server 17966 +side. Use high levels with very slow network connections, and low 17967 +levels when working over high\-speed LANs. It's not recommended to use 17968 +compression level 0, reasonable choices start from the level 1. 17969 +.TP 17970 +\fB\-quality \fIlevel\fR 17971 +Use the specified JPEG quality \fIlevel\fR (0..9) for the "tight" 17972 +encoding (TightVNC\-specific). Quality level 0 denotes bad image 17973 +quality but very impressive compression ratios, while level 9 offers 17974 +very good image quality at lower compression ratios. Note that the 17975 +"tight" encoder uses JPEG to encode only those screen areas that look 17976 +suitable for lossy compression, so quality level 0 does not always 17977 +mean unacceptable image quality. 17978 +.TP 17979 +\fB\-nojpeg\fR 17980 +Disable lossy JPEG compression in Tight encoding (TightVNC\-specific). 17981 +Disabling JPEG compression is not a good idea in typical cases, as 17982 +that makes the Tight encoder less efficient. You might want to use 17983 +this option if it's absolutely necessary to achieve perfect image 17984 +quality (see also the \fB\-quality\fR option). 17985 +.TP 17986 +\fB\-nocursorshape\fR 17987 +Disable cursor shape updates, protocol extensions used to handle 17988 +remote cursor movements locally on the client side 17989 +(TightVNC\-specific). Using cursor shape updates decreases delays with 17990 +remote cursor movements, and can improve bandwidth usage dramatically. 17991 +.TP 17992 +\fB\-x11cursor\fR 17993 +Use a real X11 cursor with X-style cursor shape updates, instead of 17994 +drawing the remote cursor on the framebuffer. This option also 17995 +disables the dot cursor, and disables cursor position updates in 17996 +non-fullscreen mode. 17997 +.TP 17998 +\fB\-autopass\fR 17999 +Read a plain-text password from stdin. This option affects only the 18000 +standard VNC authentication. 18001 + 18002 +.SH Enhanced TightVNC Viewer (SSVNC) OPTIONS 18003 +.TP 18004 +Enhanced TightVNC Viewer (SSVNC) web page is located at: 18005 +.TP 18006 +http://www.karlrunge.com/x11vnc/ssvnc.html 18007 +.TP 18008 +Note: ZRLE and ZYWRLE encodings are now supported. 18009 +.TP 18010 +Note: F9 is shortcut to Toggle FullScreen mode. 18011 +.TP 18012 +Note: In -listen mode set the env var. SSVNC_MULTIPLE_LISTEN=1 18013 +to allow more than one incoming VNC server at a time. 18014 +This is the same as -multilisten described below. Set 18015 +SSVNC_MULTIPLE_LISTEN=MAX:n to allow no more than "n" 18016 +simultaneous reverse connections. 18017 + 18018 +If the host:port is specified as "exec=command args..." 18019 +then instead of making a TCP/IP socket connection to the 18020 +remote VNC server, "command args..." is executed and the 18021 +viewer is attached to its stdio. This enables tunnelling 18022 +established via an external command, e.g. an stunnel(8) 18023 +that does not involve a listening socket. 18024 +This mode does not work for -listen reverse connections. 18025 + 18026 +If the host:port is specified as "fd=n" then it is assumed 18027 +n is an already opened file descriptor to the socket. (i.e 18028 +the parent did fork+exec) 18029 + 18030 +If the host:port contains a '/' it is interpreted as a 18031 +unix-domain socket (AF_LOCAL insead of AF_INET) 18032 +.TP 18033 +\fB\-multilisten\fR 18034 +As in -listen (reverse connection listening) except 18035 +allow more than one incoming VNC server to be connected 18036 +at a time. The default for -listen of only one at a 18037 +time tries to play it safe by not allowing anyone on 18038 +the network to put (many) desktops on your screen over 18039 +a long window of time. Use -multilisten for no limit. 18040 +.TP 18041 +\fB\-acceptpopup\fR 18042 +In \fB\-listen\fR (reverse connection listening) mode when 18043 +a reverse VNC connection comes in show a popup asking 18044 +whether to Accept or Reject the connection. The IP 18045 +address of the connecting host is shown. Same as 18046 +setting the env. var. SSVNC_ACCEPT_POPUP=1. 18047 +.TP 18048 +\fB\-acceptpopupsc\fR 18049 +As in \fB\-acceptpopup\fR except assume UltraVNC Single 18050 +Click (SC) server. Retrieve User and ComputerName 18051 +info from UltraVNC Server and display in the Popup. 18052 +.TP 18053 +\fB\-use64\fR 18054 +In \fB\-bgr233\fR mode, use 64 colors instead of 256. 18055 +.TP 18056 +\fB\-bgr222\fR 18057 +Same as \fB\-use64\fR. 18058 +.TP 18059 +\fB\-use8\fR 18060 +In \fB\-bgr233\fR mode, use 8 colors instead of 256. 18061 +.TP 18062 +\fB\-bgr111\fR 18063 +Same as \fB\-use8\fR. 18064 +.TP 18065 +\fB\-16bpp\fR 18066 +If the vnc viewer X display is depth 24 at 32bpp 18067 +request a 16bpp format from the VNC server to cut 18068 +network traffic by up to 2X, then tranlate the 18069 +pixels to 32bpp locally. 18070 +.TP 18071 +\fB\-bgr565\fR 18072 +Same as \fB\-16bpp\fR. 18073 +.TP 18074 +\fB\-grey\fR 18075 +Use a grey scale for the 16- and 8\fB\-bpp\fR modes. 18076 +.TP 18077 +\fB\-alpha\fR 18078 +Use alphablending transparency for local cursors 18079 +requires: x11vnc server, both client and server 18080 +must be 32bpp and same endianness. 18081 +.TP 18082 +\fB\-scale\fR \fIstr\fR 18083 +Scale the desktop locally. The string "str" can 18084 +a floating point ratio, e.g. "0.9", or a fraction, 18085 +e.g. "3/4", or WxH, e.g. 1280x1024. Use "fit" 18086 +to fit in the current screen size. Use "auto" to 18087 +fit in the window size. "str" can also be set by 18088 +the env. var. SSVNC_SCALE. 18089 + 18090 +If you observe mouse trail painting errors, enable 18091 +X11 Cursor mode (either via Popup or \fB\-x11cursor\fR.) 18092 + 18093 +Note that scaling is done in software and so can be 18094 +slow and requires more memory. Some speedup Tips: 18095 + 18096 +ZRLE is faster than Tight in this mode. When 18097 +scaling is first detected, the encoding will 18098 +be automatically switched to ZRLE. Use the 18099 +Popup menu if you want to go back to Tight. 18100 +Set SSVNC_PRESERVE_ENCODING=1 to disable this. 18101 + 18102 +Use a solid background on the remote side. 18103 +(e.g. manually or via x11vnc \fB\-solid\fR ...) 18104 + 18105 +If the remote server is x11vnc, try client 18106 +side caching: x11vnc \fB\-ncache\fR 10 ... 18107 +.TP 18108 +\fB\-ycrop\fR n 18109 +Only show the top n rows of the framebuffer. For 18110 +use with x11vnc \fB\-ncache\fR client caching option 18111 +to help "hide" the pixel cache region. 18112 +Use a negative value (e.g. \fB\-1\fR) for autodetection. 18113 +Autodetection will always take place if the remote 18114 +fb height is more than 2 times the width. 18115 +.TP 18116 +\fB\-sbwidth\fR n 18117 +Scrollbar width for x11vnc \fB\-ncache\fR mode (\fB\-ycrop\fR), 18118 +default is very narrow: 2 pixels, it is narrow to 18119 +avoid distraction in \fB\-ycrop\fR mode. 18120 +.TP 18121 +\fB\-nobell\fR 18122 +Disable bell. 18123 +.TP 18124 +\fB\-rawlocal\fR 18125 +Prefer raw encoding for localhost, default is 18126 +no, i.e. assumes you have a SSH tunnel instead. 18127 +.TP 18128 +\fB\-notty\fR 18129 +Try to avoid using the terminal for interactive 18130 +responses: use windows for messages and prompting 18131 +instead. Messages will also be printed to terminal. 18132 +.TP 18133 +\fB\-sendclipboard\fR 18134 +Send the X CLIPBOARD selection (i.e. Ctrl+C, 18135 +Ctrl+V) instead of the X PRIMARY selection (mouse 18136 +select and middle button paste.) 18137 +.TP 18138 +\fB\-sendalways\fR 18139 +Whenever the mouse enters the VNC viewer main 18140 +window, send the selection to the VNC server even if 18141 +it has not changed. This is like the Xt resource 18142 +translation SelectionToVNC(always) 18143 +.TP 18144 +\fB\-recvtext\fR 18145 +str When cut text is received from the VNC server, 18146 +ssvncviewer will set both the X PRIMARY and the 18147 +X CLIPBOARD local selections. To control which 18148 +is set, specify 'str' as 'primary', 'clipboard', 18149 +or 'both' (the default.) 18150 +.TP 18151 +\fB\-graball\fR 18152 +Grab the entire X server when in fullscreen mode, 18153 +needed by some old window managers like fvwm2. 18154 +.TP 18155 +\fB\-popupfix\fR 18156 +Warp the popup back to the pointer position, 18157 +needed by some old window managers like fvwm2. 18158 +.TP 18159 +\fB\-grabkbd\fR 18160 +Grab the X keyboard when in fullscreen mode, 18161 +needed by some window managers. Same as \fB\-grabkeyboard\fR. 18162 +\fB\-grabkbd\fR is the default, use \fB\-nograbkbd\fR to disable. 18163 +.TP 18164 +\fB\-bs\fR, \fB\-nobs\fR 18165 +Whether or not to use X server Backingstore for the 18166 +main viewer window. The default is to not, mainly 18167 +because most Linux, etc, systems X servers disable 18168 +*all* Backingstore by default. To re\fB\-enable\fR it put 18169 + 18170 +Option "Backingstore" 18171 + 18172 +in the Device section of /etc/X11/xorg.conf. 18173 +In \fB\-bs\fR mode with no X server backingstore, whenever an 18174 +area of the screen is re\fB\-exposed\fR it must go out to the 18175 +VNC server to retrieve the pixels. This is too slow. 18176 + 18177 +In \fB\-nobs\fR mode, memory is allocated by the viewer to 18178 +provide its own backing of the main viewer window. This 18179 +actually makes some activities faster (changes in large 18180 +regions) but can appear to "flash" too much. 18181 +.TP 18182 +\fB\-noshm\fR 18183 +Disable use of MIT shared memory extension (not recommended) 18184 +.TP 18185 +\fB\-termchat\fR 18186 +Do the UltraVNC chat in the terminal vncviewer is in 18187 +instead of in an independent window. 18188 +.TP 18189 +\fB\-unixpw\fR \fIstr\fR 18190 +Useful for logging into x11vnc in \fB\-unixpw\fR mode. "str" is a 18191 +string that allows many ways to enter the Unix Username 18192 +and Unix Password. These characters: username, newline, 18193 +password, newline are sent to the VNC server after any VNC 18194 +authentication has taken place. Under x11vnc they are 18195 +used for the \fB\-unixpw\fR login. Other VNC servers could do 18196 +something similar. 18197 + 18198 +You can also indicate "str" via the environment 18199 +variable SSVNC_UNIXPW. 18200 + 18201 +Note that the Escape key is actually sent first to tell 18202 +x11vnc to not echo the Unix Username back to the VNC 18203 +viewer. Set SSVNC_UNIXPW_NOESC=1 to override this. 18204 + 18205 +If str is ".", then you are prompted at the command line 18206 +for the username and password in the normal way. If str is 18207 +"-" the stdin is read via getpass(3) for username@password. 18208 +Otherwise if str is a file, it is opened and the first line 18209 +read is taken as the Unix username and the 2nd as the 18210 +password. If str prefixed by "rm:" the file is removed 18211 +after reading. Otherwise, if str has a "@" character, 18212 +it is taken as username@password. Otherwise, the program 18213 +exits with an error. Got all that? 18214 +.TP 18215 +\fB-repeater\fR \fIstr\fR 18216 +This is for use with UltraVNC repeater proxy described 18217 +here: http://www.uvnc.com/addons/repeater.html. The "str" 18218 +is the ID string to be sent to the repeater. E.g. ID:1234 18219 +It can also be the hostname and port or display of the VNC 18220 +server, e.g. 12.34.56.78:0 or snoopy.com:1. Note that when 18221 +using -repeater, the host:dpy on the cmdline is the repeater 18222 +server, NOT the VNC server. The repeater will connect you. 18223 + 18224 +Example: vncviewer ... -repeater ID:3333 repeat.host:5900 18225 + 18226 +Example: vncviewer ... -repeater vhost:0 repeat.host:5900 18227 + 18228 +Use, e.g., '-repeater SCIII=ID:3210' if the repeater is a 18229 +Single Click III (SSL) repeater (repeater_SSL.exe) and you 18230 +are passing the SSL part of the connection through stunnel, socat, etc. 18231 +This way the magic UltraVNC string 'testB' needed to work with the 18232 +repeater is sent to it. 18233 +.TP 18234 +\fB-rfbversion\fR \fIstr\fR 18235 +Set the advertised RFB version. E.g.: -rfbversion 3.6 For some 18236 +servers, e.g. UltraVNC this needs to be done. 18237 +.TP 18238 +\fB-ultradsm\fR 18239 +UltraVNC has symmetric private encryption DSM plugins. See 18240 +http://www.uvnc.com/features/encryption.html. It is assumed 18241 +you are using a unix program (e.g. our ultravnc_dsm_helper) to 18242 +encrypt and decrypt the UltraVNC DSM stream. IN ADDITION TO 18243 +THAT supply -ultradsm to tell THIS viewer to modify the RFB 18244 +data sent so as to work with the UltraVNC Server. For some 18245 +reason, each RFB msg type must be sent twice under DSM. 18246 +.TP 18247 +\fB\-mslogon\fR \fIuser\fR 18248 +Use Windows MS Logon to an UltraVNC server. Supply the 18249 +username or "1" to be prompted. The default is to 18250 +autodetect the UltraVNC MS Logon server and prompt for 18251 +the username and password. 18252 + 18253 +IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman 18254 +exchange is very weak and can be brute forced to recover 18255 +your username and password in a few seconds of CPU 18256 +time. To be safe, be sure to use an additional encrypted 18257 +tunnel (e.g. SSL or SSH) for the entire VNC session. 18258 +.TP 18259 +\fB\-chatonly\fR 18260 +Try to be a client that only does UltraVNC text chat. This 18261 +mode is used by x11vnc to present a chat window on the physical 18262 +X11 console (i.e. to chat with the person at the display). 18263 +.TP 18264 +\fB-env\fR \fIVAR=VALUE\fR 18265 +To save writing a shell script to set environment 18266 +variables, specify as many as you need on the command line. For example, 18267 +-env SSVNC_MULTIPLE_LISTEN=MAX:5 -env EDITOR=vi 18268 +.TP 18269 +\fB\-noipv6\fR 18270 +Disable all IPv6 sockets. Same as VNCVIEWER_NO_IPV6=1. 18271 +.TP 18272 +\fB\-noipv4\fR 18273 +Disable all IPv4 sockets. Same as VNCVIEWER_NO_IPV4=1. 18274 +.TP 18275 +\fB\-printres\fR 18276 +Print out the Ssvnc X resources (appdefaults) and 18277 +then exit. You can save them to a file and customize them (e.g. the 18278 +keybindings and Popup menu) Then point to the file via 18279 +XENVIRONMENT or XAPPLRESDIR. 18280 +.TP 18281 +\fB\-pipeline\fR 18282 +Like TurboVNC, request the next framebuffer update as soon 18283 +as possible instead of waiting until the end of the current 18284 +framebuffer update coming in. Helps 'pipeline' the updates. 18285 +This is currently the default, use \fB-nopipeline\fR to disable. 18286 +.TP 18287 +\fB\-appshare\fR 18288 +Enable features for use with x11vnc's \fB\-appshare\fR mode where 18289 +instead of sharing the full desktop only the application's 18290 +windows are shared. Viewer multilisten mode is used to 18291 +create the multiple windows: \fB\-multilisten\fR is implied. 18292 +See 'x11vnc \fB\-appshare\fR \fB\-help\fR' more information on the mode. 18293 +Features enabled in the viewer under \fB\-appshare\fR are: 18294 +Minimum extra text in the title, auto \fB\-ycrop\fR is disabled, 18295 +x11vnc \fB\-remote_prefix\fR X11VNC_APPSHARE_CMD: message channel, 18296 +x11vnc initial window position hints. See also Escape Keys 18297 +below for additional key and mouse bindings. 18298 +.TP 18299 +\fB\-escape \fR\fIstr\fR 18300 +This sets the 'Escape Keys' modifier sequence and enables 18301 +escape keys mode. When the modifier keys escape sequence 18302 +is held down, the next keystroke is interpreted locally 18303 +to perform a special action instead of being sent to the 18304 +remote VNC server. 18305 + 18306 +Use '\fB\-escape\fR default' for the default modifier sequence. 18307 +(Unix: Alt_L,Super_L and MacOSX: Control_L,Meta_L) 18308 + 18309 +Here are the 'Escape Keys: Help+Set' instructions from the Popup: 18310 + 18311 +Escape Keys: Enter a comma separated list of modifier keys to be the 'escape 18312 +sequence'. When these keys are held down, the next keystroke is 18313 +interpreted locally to invoke a special action instead of being sent to 18314 +the remote VNC server. In other words, a set of 'Hot Keys'. 18315 + 18316 +Here is the list of local key mappings to special actions: 18317 + 18318 +r: refresh desktop b: toggle bell c: toggle full-color 18319 + 18320 +f: file transfer x: x11cursor z: toggle Tight/ZRLE 18321 + 18322 +l: full screen g: graball e: escape keys dialog 18323 + 18324 +s: scale dialog +: scale up (=) -: scale down (_) 18325 + 18326 +t: text chat a: alphablend cursor 18327 + 18328 +V: toggle viewonly Q: quit viewer 123456: UltraVNC scale 1/n 18329 + 18330 +Arrow keys: pan the viewport about 10% for each keypress. 18331 + 18332 +PageUp/PageDown: pan the viewport by a screenful vertically. 18333 + 18334 +Home/End: pan the viewport by a screenful horizontally. 18335 + 18336 +KeyPad Arrows: pan the viewport by 1 pixel for each keypress. 18337 + 18338 +Dragging the Mouse with Button1 pressed also pans the viewport. 18339 + 18340 +Clicking Mouse Button3 brings up the Popup Menu. 18341 + 18342 +The above mappings are \fBalways\fR active in ViewOnly mode, unless you set 18343 +the Escape Keys value to 'never'. 18344 + 18345 +x11vnc -appshare hot-keys: x11vnc has a simple application sharing mode 18346 +that enables the viewer-side to move, resize, or raise the remote toplevel 18347 +windows. To enable it, hold down Shift + the Escape Keys and press these: 18348 + 18349 +Arrow keys: move the remote window around in its desktop. 18350 + 18351 +PageUp/PageDn/Home/End: resize the remote window. 18352 + 18353 ++/-: raise or lower the remote window. 18354 + 18355 +M or Button1 move win to local position; D or Button3: delete remote win. 18356 + 18357 +If the Escape Keys value below is set to 'default' then a default list of 18358 +of modifier keys is used. For Unix it is: Alt_L,Super_L and for MacOSX it 18359 +is Control_L,Meta_L. Note: the Super_L key usually has a Windows(TM) Flag 18360 +on it. Also note the _L and _R mean the key is on the LEFT or RIGHT side 18361 +of the keyboard. 18362 + 18363 +On Unix the default is Alt and Windows keys on Left side of keyboard. 18364 +On MacOSX the default is Control and Command keys on Left side of keyboard. 18365 + 18366 +Example: Press and hold the Alt and Windows keys on the LEFT side of the 18367 +keyboard and then press 'c' to toggle the full-color state. Or press 't' 18368 +to toggle the ultravnc Text Chat window, etc. 18369 + 18370 +To use something besides the default, supply a comma separated list (or a 18371 +single one) from: Shift_L Shift_R Control_L Control_R Alt_L Alt_R Meta_L 18372 +Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch. 18373 +.TP 18374 +\fB New Popup actions:\fR 18375 + 18376 + ViewOnly: ~ -viewonly 18377 + Disable Bell: ~ -nobell 18378 + Cursor Shape: ~ -nocursorshape 18379 + X11 Cursor: ~ -x11cursor 18380 + Cursor Alphablend: ~ -alpha 18381 + Toggle Tight/Hextile: ~ -encodings hextile... 18382 + Toggle Tight/ZRLE: ~ -encodings zrle... 18383 + Toggle ZRLE/ZYWRLE: ~ -encodings zywrle... 18384 + Quality Level ~ -quality (both Tight and ZYWRLE) 18385 + Compress Level ~ -compresslevel 18386 + Disable JPEG: ~ -nojpeg (Tight) 18387 + Pipeline Updates ~ -pipeline 18388 + 18389 + Full Color as many colors as local screen allows. 18390 + Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only. 18391 + 16 bit color (BGR565) ~ -16bpp / -bgr565 18392 + 8 bit color (BGR233) ~ -bgr233 18393 + 256 colors ~ -bgr233 default # of colors. 18394 + 64 colors ~ -bgr222 / -use64 18395 + 8 colors ~ -bgr111 / -use8 18396 + Scale Viewer ~ -scale 18397 + Escape Keys: Toggle ~ -escape 18398 + Escape Keys: Help+Set ~ -escape 18399 + Set Y Crop (y-max) ~ -ycrop 18400 + Set Scrollbar Width ~ -sbwidth 18401 + XGrabServer ~ -graball 18402 + 18403 + UltraVNC Extensions: 18404 + 18405 + Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. 18406 + Text Chat Ultravnc ext. Do Text Chat. 18407 + File Transfer Ultravnc ext. File xfer via Java helper. 18408 + Single Window Ultravnc ext. Grab and view a single window. 18409 + (select then click on the window you want). 18410 + Disable Remote Input Ultravnc ext. Try to prevent input and 18411 + viewing of monitor at physical display. 18412 + 18413 + Note: the Ultravnc extensions only apply to servers that support 18414 + them. x11vnc/libvncserver supports some of them. 18415 + 18416 + Send Clipboard not Primary ~ -sendclipboard 18417 + Send Selection Every time ~ -sendalways 18418 + 18419 +.SH ENCODINGS 18420 +The server supplies information in whatever format is desired by the 18421 +client, in order to make the client as easy as possible to implement. 18422 +If the client represents itself as able to use multiple formats, the 18423 +server will choose one. 18424 + 18425 +.I Pixel format 18426 +refers to the representation of an individual pixel. The most common 18427 +formats are 24 and 16 bit "true\-color" values, and 8\-bit "color map" 18428 +representations, where an arbitrary map converts the color number to 18429 +RGB values. 18430 + 18431 +.I Encoding 18432 +refers to how a rectangle of pixels are sent (all pixel information in 18433 +VNC is sent as rectangles). All rectangles come with a header giving 18434 +the location and size of the rectangle and an encoding type used by 18435 +the data which follows. These types are listed below. 18436 +.TP 18437 +.B Raw 18438 +The raw encoding simply sends width*height pixel values. All clients 18439 +are required to support this encoding type. Raw is also the fastest 18440 +when the server and viewer are on the same machine, as the connection 18441 +speed is essentially infinite and raw encoding minimizes processing 18442 +time. 18443 +.TP 18444 +.B CopyRect 18445 +The Copy Rectangle encoding is efficient when something is being 18446 +moved; the only data sent is the location of a rectangle from which 18447 +data should be copied to the current location. Copyrect could also be 18448 +used to efficiently transmit a repeated pattern. 18449 +.TP 18450 +.B RRE 18451 +The Rise\-and\-Run\-length\-Encoding is basically a 2D version of 18452 +run\-length encoding (RLE). In this encoding, a sequence of identical 18453 +pixels are compressed to a single value and repeat count. In VNC, this 18454 +is implemented with a background color, and then specifications of an 18455 +arbitrary number of subrectangles and color for each. This is an 18456 +efficient encoding for large blocks of constant color. 18457 +.TP 18458 +.B CoRRE 18459 +This is a minor variation on RRE, using a maximum of 255x255 pixel 18460 +rectangles. This allows for single\-byte values to be used, reducing 18461 +packet size. This is in general more efficient, because the savings 18462 +from sending 1\-byte values generally outweighs the losses from the 18463 +(relatively rare) cases where very large regions are painted the same 18464 +color. 18465 +.TP 18466 +.B Hextile 18467 +Here, rectangles are split up in to 16x16 tiles, which are sent in a 18468 +predetermined order. The data within the tiles is sent either raw or 18469 +as a variant on RRE. Hextile encoding is usually the best choice for 18470 +using in high\-speed network environments (e.g. Ethernet local\-area 18471 +networks). 18472 +.TP 18473 +.B Zlib 18474 +Zlib is a very simple encoding that uses zlib library to compress raw 18475 +pixel data. This encoding achieves good compression, but consumes a 18476 +lot of CPU time. Support for this encoding is provided for 18477 +compatibility with VNC servers that might not understand Tight 18478 +encoding which is more efficient than Zlib in nearly all real\-life 18479 +situations. 18480 +.TP 18481 +.B Tight 18482 +Like Zlib encoding, Tight encoding uses zlib library to compress the 18483 +pixel data, but it pre\-processes data to maximize compression ratios, 18484 +and to minimize CPU usage on compression. Also, JPEG compression may 18485 +be used to encode color\-rich screen areas (see the description of 18486 +\-quality and \-nojpeg options above). Tight encoding is usually the 18487 +best choice for low\-bandwidth network environments (e.g. slow modem 18488 +connections). 18489 +.TP 18490 +.B ZRLE 18491 +The SSVNC viewer has ported the RealVNC (www.realvnc.com) ZRLE encoding 18492 +to the unix tightvnc viewer. 18493 +.TP 18494 +.B ZYWRLE 18495 +The SSVNC viewer has ported the Hitachi lossy wavelet based ZRLE 18496 +encoding from http://mobile.hitachi-system.co.jp/publications/ZYWRLE/ 18497 +to the unix tightvnc viewer. 18498 +.SH RESOURCES 18499 +X resources that \fBvncviewer\fR knows about, aside from the 18500 +normal Xt resources, are as follows: 18501 +.TP 18502 +.B shareDesktop 18503 +Equivalent of \fB\-shared\fR/\fB\-noshared\fR options. Default true. 18504 +.TP 18505 +.B viewOnly 18506 +Equivalent of \fB\-viewonly\fR option. Default false. 18507 +.TP 18508 +.B fullScreen 18509 +Equivalent of \fB\-fullscreen\fR option. Default false. 18510 +.TP 18511 +.B grabKeyboard 18512 +Grab keyboard in full-screen mode. This can help to solve problems 18513 +with losing keyboard focus. Default false. 18514 +.TP 18515 +.B raiseOnBeep 18516 +Equivalent of \fB\-noraiseonbeep\fR option, when set to false. Default 18517 +true. 18518 +.TP 18519 +.B passwordFile 18520 +Equivalent of \fB\-passwd\fR option. 18521 +.TP 18522 +.B userLogin 18523 +Equivalent of \fB\-user\fR option. 18524 +.TP 18525 +.B passwordDialog 18526 +Whether to use a dialog box to get the password (true) or get it from 18527 +the tty (false). Irrelevant if \fBpasswordFile\fR is set. Default 18528 +false. 18529 +.TP 18530 +.B encodings 18531 +Equivalent of \fB\-encodings\fR option. 18532 +.TP 18533 +.B compressLevel 18534 +Equivalent of \fB\-compresslevel\fR option (TightVNC\-specific). 18535 +.TP 18536 +.B qualityLevel 18537 +Equivalent of \fB\-quality\fR option (TightVNC\-specific). 18538 +.TP 18539 +.B enableJPEG 18540 +Equivalent of \fB\-nojpeg\fR option, when set to false. Default true. 18541 +.TP 18542 +.B useRemoteCursor 18543 +Equivalent of \fB\-nocursorshape\fR option, when set to false 18544 +(TightVNC\-specific). Default true. 18545 +.TP 18546 +.B useBGR233 18547 +Equivalent of \fB\-bgr233\fR option. Default false. 18548 +.TP 18549 +.B nColours 18550 +When using BGR233, try to allocate this many "exact" colors from the 18551 +BGR233 color cube. When using a shared colormap, setting this resource 18552 +lower leaves more colors for other X clients. Irrelevant when using 18553 +truecolor. Default is 256 (i.e. all of them). 18554 +.TP 18555 +.B useSharedColours 18556 +If the number of "exact" BGR233 colors successfully allocated is less 18557 +than 256 then the rest are filled in using the "nearest" colors 18558 +available. This resource says whether to only use the "exact" BGR233 18559 +colors for this purpose, or whether to use other clients' "shared" 18560 +colors as well. Default true (i.e. use other clients' colors). 18561 +.TP 18562 +.B forceOwnCmap 18563 +Equivalent of \fB\-owncmap\fR option. Default false. 18564 +.TP 18565 +.B forceTrueColour 18566 +Equivalent of \fB\-truecolour\fR option. Default false. 18567 +.TP 18568 +.B requestedDepth 18569 +Equivalent of \fB\-depth\fR option. 18570 +.TP 18571 +.B useSharedMemory 18572 +Use MIT shared memory extension if on the same machine as the X 18573 +server. Default true. 18574 +.TP 18575 +.B wmDecorationWidth, wmDecorationHeight 18576 +The total width and height taken up by window manager decorations. 18577 +This is used to calculate the maximum size of the VNC viewer window. 18578 +Default is width 4, height 24. 18579 +.TP 18580 +.B bumpScrollTime, bumpScrollPixels 18581 +When in full screen mode and the VNC desktop is bigger than the X 18582 +display, scrolling happens whenever the mouse hits the edge of the 18583 +screen. The maximum speed of scrolling is bumpScrollPixels pixels 18584 +every bumpScrollTime milliseconds. The actual speed of scrolling will 18585 +be slower than this, of course, depending on how fast your machine is. 18586 +Default 20 pixels every 25 milliseconds. 18587 +.TP 18588 +.B popupButtonCount 18589 +The number of buttons in the popup window. See the README file for 18590 +more information on how to customize the buttons. 18591 +.TP 18592 +.B debug 18593 +For debugging. Default false. 18594 +.TP 18595 +.B rawDelay, copyRectDelay 18596 +For debugging, see the README file for details. Default 0 (off). 18597 +.SH ENVIRONMENT 18598 +When started with the \fB\-via\fR option, vncviewer reads the 18599 +\fBVNC_VIA_CMD\fR environment variable, expands patterns beginning 18600 +with the "%" character, and executes result as a command assuming that 18601 +it would create TCP tunnel that should be used for VNC connection. If 18602 +not set, this environment variable defaults to "/usr/bin/ssh -f -L 18603 +%L:%H:%R %G sleep 20". 18604 + 18605 +The following patterns are recognized in the \fBVNC_VIA_CMD\fR (note 18606 +that all the patterns %G, %H, %L and %R must be present in the command 18607 +template): 18608 +.TP 18609 +.B %% 18610 +A literal "%"; 18611 +.TP 18612 +.B %G 18613 +gateway host name; 18614 +.TP 18615 +.B %H 18616 +remote VNC host name, as known to the gateway; 18617 +.TP 18618 +.B %L 18619 +local TCP port number; 18620 +.TP 18621 +.B %R 18622 +remote TCP port number. 18623 +.SH SEE ALSO 18624 +\fBvncserver\fR(1), \fBx11vnc\fR(1), \fBssvnc\fR(1), \fBXvnc\fR(1), \fBvncpasswd\fR(1), 18625 +\fBvncconnect\fR(1), \fBssh\fR(1), http://www.karlrunge.com/x11vnc, http://www.karlrunge.com/x11vnc/ssvnc.html 18626 +.SH AUTHORS 18627 +Original VNC was developed in AT&T Laboratories Cambridge. TightVNC 18628 +additions was implemented by Constantin Kaplinsky. Many other people 18629 +participated in development, testing and support. Karl J. Runge 18630 +added all of the SSVNC related features and improvements. 18631 + 18632 +\fBMan page authors:\fR 18633 +.br 18634 +Marcus Brinkmann <Marcus.Brinkmann (a] ruhr-uni-bochum.de>, 18635 +.br 18636 +Terran Melconian <terran (a] consistent.org>, 18637 +.br 18638 +Tim Waugh <twaugh (a] redhat.com>, 18639 +.br 18640 +Constantin Kaplinsky <const (a] ce.cctpu.edu.ru> 18641 +.br 18642 +Karl J. Runge <runge (a] karlrunge.com> 18643 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncviewer/vncviewer.c 18644 --- vnc_unixsrc.orig/vncviewer/vncviewer.c 2004-01-13 09:22:05.000000000 -0500 18645 +++ vnc_unixsrc/vncviewer/vncviewer.c 2010-04-18 12:43:47.000000000 -0400 18646 @@ -22,6 +22,8 @@ 18647 */ 18648 18649 #include "vncviewer.h" 18650 +#include <ctype.h> 18651 +#include <X11/Xaw/Toggle.h> 18652 18653 char *programName; 18654 XtAppContext appContext; 18655 @@ -29,11 +31,274 @@ 18656 18657 Widget toplevel; 18658 18659 +extern void raiseme(int force); 18660 +extern void CreateChat(void); 18661 + 18662 +void set_sbwidth(int sbw) { 18663 + char *q, *p, t[5]; 18664 + int i, k, N = 4; 18665 + int db = 0; 18666 + 18667 + if (sbw < 1) { 18668 + sbw = 2; 18669 + } else if (sbw > 100) { 18670 + sbw = 100; 18671 + } 18672 + if (db) fprintf(stderr, "sbw: %d\n", sbw); 18673 + 18674 + sprintf(t, "%4d", sbw); 18675 + k = 0; 18676 + while (fallback_resources[k] != NULL) { 18677 + q = strstr(fallback_resources[k], "horizontal.height: "); 18678 + if (!q) { 18679 + q = strstr(fallback_resources[k], "vertical.width: "); 18680 + } 18681 + if (q) { 18682 + p = strdup(fallback_resources[k]); 18683 + q = strstr(p, ": "); 18684 + if (q) { 18685 + q++; 18686 + q++; 18687 + for (i=0; i < N; i++) { 18688 + *(q+i) = t[i]; 18689 + } 18690 + fallback_resources[k] = p; 18691 + if (db) fprintf(stderr, "res: %s\n\n", p); 18692 + } 18693 + } 18694 + k++; 18695 + } 18696 +} 18697 + 18698 +void min_title(void) { 18699 + char *q; 18700 + int k; 18701 + 18702 + k = 0; 18703 + while (fallback_resources[k] != NULL) { 18704 + q = strstr(fallback_resources[k], "Ssvnc.title: "); 18705 + if (q) { 18706 + fallback_resources[k] = strdup("Ssvnc.title: %s"); 18707 + } 18708 + k++; 18709 + } 18710 +} 18711 + 18712 +#include <sys/types.h> 18713 +#include <sys/stat.h> 18714 +#include <unistd.h> 18715 + 18716 +void unixpw(char *instr, int vencrypt_plain) { 18717 + char *str, *q, *infile = NULL; 18718 + FILE *in; 18719 + int i, rmfile = 0; 18720 + struct stat sb; 18721 + int N = 99; 18722 + char username[100], passwd[100]; 18723 + static int did = 0; 18724 + 18725 + if (did) { 18726 + return; 18727 + } 18728 + did = 1; 18729 + 18730 + for (i=0; i<100; i++) { 18731 + username[i] = '\0'; 18732 + passwd[i] = '\0'; 18733 + } 18734 + 18735 + if (instr == NULL) { 18736 + return; 18737 + } else if (!strcmp(instr, "")) { 18738 + return; 18739 + } 18740 + 18741 + str = strdup(instr); 18742 + 18743 + if (strstr(str, "rm:") == str) { 18744 + rmfile = 1; 18745 + infile = str + strlen("rm:"); 18746 + } else if (stat(str, &sb) == 0) { 18747 + infile = str; 18748 + } 18749 + if (!strcmp(str, ".")) { 18750 + char *p; 18751 + if (!use_tty()) { 18752 + char *u; 18753 + fprintf(stderr, "\nEnter Unix Username and Password in the popups.\n"); 18754 + u = DoUserDialog(); 18755 + if (strlen(u) >= 100) { 18756 + exit(1); 18757 + } 18758 + sprintf(username, u); 18759 + p = DoPasswordDialog(); 18760 + } else { 18761 + raiseme(1); 18762 + fprintf(stderr, "\nUnix Username: "); 18763 + if (fgets(username, N, stdin) == NULL) { 18764 + exit(1); 18765 + } 18766 + p = getpass("Unix Password: "); 18767 + } 18768 + if (! p) { 18769 + exit(1); 18770 + } 18771 + strncpy(passwd, p, N); 18772 + fprintf(stderr, "\n"); 18773 + 18774 + } else if (!strcmp(str, "-")) { 18775 + char *p, *q; 18776 + if (!use_tty()) { 18777 + fprintf(stderr, "\nEnter unixuser@unixpasswd in the popup.\n"); 18778 + p = DoPasswordDialog(); 18779 + } else { 18780 + raiseme(1); 18781 + p = getpass("unixuser@unixpasswd: "); 18782 + } 18783 + if (! p) { 18784 + exit(1); 18785 + } 18786 + q = strchr(p, '@'); 18787 + if (! q) { 18788 + exit(1); 18789 + } 18790 + *q = '\0'; 18791 + strncpy(username, p, N); 18792 + strncpy(passwd, q+1, N); 18793 + 18794 + } else if (infile) { 18795 + in = fopen(infile, "r"); 18796 + if (in == NULL) { 18797 + fprintf(stderr, "failed to open -unixpw file.\n"); 18798 + exit(1); 18799 + } 18800 + if (fgets(username, N, in) == NULL) { 18801 + exit(1); 18802 + } 18803 + if (fgets(passwd, N, in) == NULL) { 18804 + exit(1); 18805 + } 18806 + fclose(in); 18807 + fprintf(stderr, "read username@passwd from file: %s\n", infile); 18808 + if (rmfile) { 18809 + fprintf(stderr, "deleting username@passwd file: %s\n", infile); 18810 + unlink(infile); 18811 + } 18812 + } else if (strchr(str, '@')) { 18813 + char *q = strchr(str, '@'); 18814 + *q = '\0'; 18815 + strncpy(username, str, N); 18816 + strncpy(passwd, q+1, N); 18817 + } else { 18818 + exit(1); 18819 + } 18820 + 18821 + free(str); 18822 + 18823 + if (vencrypt_plain) { 18824 + CARD32 ulen, plen; 18825 + char *q; 18826 + 18827 + q = strrchr(username, '\n'); 18828 + if (q) *q = '\0'; 18829 + q = strrchr(passwd, '\n'); 18830 + if (q) *q = '\0'; 18831 + 18832 + ulen = Swap32IfLE((CARD32)strlen(username)); 18833 + plen = Swap32IfLE((CARD32)strlen(passwd)); 18834 + 18835 + if (!WriteExact(rfbsock, (char *)&ulen, 4) || 18836 + !WriteExact(rfbsock, (char *)&plen, 4)) { 18837 + return; 18838 + } 18839 + 18840 + if (!WriteExact(rfbsock, username, strlen(username)) || 18841 + !WriteExact(rfbsock, passwd, strlen(passwd))) { 18842 + return; 18843 + } 18844 + return; 18845 + } 18846 + 18847 + 18848 + if (! getenv("SSVNC_UNIXPW_NOESC")) { 18849 + SendKeyEvent(XK_Escape, 1); 18850 + SendKeyEvent(XK_Escape, 0); 18851 + } 18852 + 18853 + q = username; 18854 + while (*q != '\0' && *q != '\n') { 18855 + char c = *q; 18856 + if (c >= 0x20 && c <= 0x07e) { 18857 + KeySym ks = (KeySym) c; 18858 + SendKeyEvent(ks, 1); 18859 + SendKeyEvent(ks, 0); 18860 + } 18861 + q++; 18862 + } 18863 + 18864 + SendKeyEvent(XK_Return, 1); 18865 + SendKeyEvent(XK_Return, 0); 18866 + 18867 + q = passwd; 18868 + while (*q != '\0' && *q != '\n') { 18869 + char c = *q; 18870 + if (c >= 0x20 && c <= 0x07e) { 18871 + KeySym ks = (KeySym) c; 18872 + SendKeyEvent(ks, 1); 18873 + SendKeyEvent(ks, 0); 18874 + } 18875 + q++; 18876 + } 18877 + 18878 + SendKeyEvent(XK_Return, 1); 18879 + SendKeyEvent(XK_Return, 0); 18880 +} 18881 + 18882 +static void chat_window_only(void) { 18883 + if (appData.chatOnly) { 18884 + static double last_time = 0.0; 18885 + if (dnow() > last_time + 1.5) { 18886 + XSync(dpy, False); 18887 + XUnmapWindow(dpy, XtWindow(toplevel)); 18888 + } 18889 + } 18890 +} 18891 + 18892 +int saw_appshare = 0; 18893 + 18894 int 18895 main(int argc, char **argv) 18896 { 18897 - int i; 18898 - programName = argv[0]; 18899 + int i, save_sbw, saw_listen = 0; 18900 + char *pw_loc = NULL; 18901 + programName = argv[0]; 18902 + 18903 + if (strrchr(programName, '/') != NULL) { 18904 + programName = strrchr(programName, '/') + 1; 18905 + } 18906 + 18907 + for (i = 1; i < argc; i++) { 18908 + if (!strcmp(argv[i], "-env")) { 18909 + if (i+1 < argc) { 18910 + char *estr = argv[i+1]; 18911 + if (strchr(estr, '=')) { 18912 + putenv(estr); 18913 + } 18914 + } 18915 + } 18916 + if (!strcmp(argv[i], "-noipv4")) { 18917 + putenv("VNCVIEWER_NO_IPV4=1"); 18918 + } 18919 + if (!strcmp(argv[i], "-noipv6")) { 18920 + putenv("VNCVIEWER_NO_IPV6=1"); 18921 + } 18922 + } 18923 + if (getenv("VNCVIEWER_NO_IPV4")) { 18924 + appData.noipv4 = True; 18925 + } 18926 + if (getenv("VNCVIEWER_NO_IPV6")) { 18927 + appData.noipv6 = True; 18928 + } 18929 18930 /* The -listen option is used to make us a daemon process which listens for 18931 incoming connections from servers, rather than actively connecting to a 18932 @@ -45,89 +310,1744 @@ 18933 listenForIncomingConnections() returns, setting the listenSpecified 18934 flag. */ 18935 18936 - for (i = 1; i < argc; i++) { 18937 - if (strcmp(argv[i], "-listen") == 0) { 18938 - listenForIncomingConnections(&argc, argv, i); 18939 - break; 18940 - } 18941 - if (strcmp(argv[i], "-tunnel") == 0 || strcmp(argv[i], "-via") == 0) { 18942 - if (!createTunnel(&argc, argv, i)) 18943 - exit(1); 18944 - break; 18945 - } 18946 - } 18947 + for (i = 1; i < argc; i++) { 18948 + if (!strcmp(argv[i], "-appshare")) { 18949 + putenv("SSVNC_MULTIPLE_LISTEN=1"); 18950 + fprintf(stderr, "Enabling -multilisten mode for 'x11vnc -appshare' usage.\n\n"); 18951 + saw_appshare = 1; 18952 + } 18953 + if (!strcmp(argv[i], "-multilisten")) { 18954 + putenv("SSVNC_MULTIPLE_LISTEN=1"); 18955 + saw_listen = 2; 18956 + } 18957 + if (!strcmp(argv[i], "-listen")) { 18958 + saw_listen = 1; 18959 + } 18960 + if (!strcmp(argv[i], "-acceptpopup")) { 18961 + putenv("SSVNC_ACCEPT_POPUP=1"); 18962 + } 18963 + if (!strcmp(argv[i], "-acceptpopupsc")) { 18964 + putenv("SSVNC_ACCEPT_POPUP_SC=1"); 18965 + } 18966 + if (strstr(argv[i], " pw=") != NULL) { 18967 + pw_loc = strstr(argv[i], " pw=") + 1; 18968 + } 18969 + } 18970 + 18971 + for (i = 1; i < argc; i++) { 18972 + if (!strcmp(argv[i], "-appshare") && !saw_listen) { 18973 + listenForIncomingConnections(&argc, argv, i); 18974 + break; 18975 + } 18976 + if (!strcmp(argv[i], "-multilisten")) { 18977 + listenForIncomingConnections(&argc, argv, i); 18978 + break; 18979 + } 18980 + if (!strcmp(argv[i], "-listen")) { 18981 + listenForIncomingConnections(&argc, argv, i); 18982 + break; 18983 + } 18984 + if (!strcmp(argv[i], "-tunnel") || !strcmp(argv[i], "-via")) { 18985 + if (!createTunnel(&argc, argv, i)) { 18986 + exit(1); 18987 + } 18988 + break; 18989 + } 18990 + if (!strcmp(argv[i], "-printres") || !strcmp(argv[i], "-res")) { 18991 + int j = 0; 18992 + fprintf(stdout, "\n! Ssvnc fallback X resources:\n\n"); 18993 + while (1) { 18994 + char *p = fallback_resources[j++]; 18995 + int k = 0; 18996 + if (p == NULL) break; 18997 + while (*p != '\0') { 18998 + fprintf(stdout, "%c", *p); 18999 + if (k > 0 && *p == 'n' && *(p-1) == '\\') { 19000 + fprintf(stdout, "\\\n"); 19001 + } 19002 + p++; k++; 19003 + } 19004 + fprintf(stdout, "\n\n"); 19005 + } 19006 + exit(0); 19007 + } 19008 + } 19009 + 19010 + 19011 + if (argc > 1 && strstr(argv[1], "-h") == argv[1]) { 19012 + usage(); 19013 + return 0; 19014 + } 19015 19016 /* Call the main Xt initialisation function. It parses command-line options, 19017 generating appropriate resource specs, and makes a connection to the X 19018 display. */ 19019 19020 - toplevel = XtVaAppInitialize(&appContext, "Vncviewer", 19021 - cmdLineOptions, numCmdLineOptions, 19022 - &argc, argv, fallback_resources, 19023 - XtNborderWidth, 0, NULL); 19024 + if (saw_appshare || getenv("VNCVIEWER_MIN_TITLE")) { 19025 + min_title(); 19026 + } 19027 + appData.sbWidth = 0; 19028 + if (getenv("VNCVIEWER_SBWIDTH")) { 19029 + int sbw = atoi(getenv("VNCVIEWER_SBWIDTH")); 19030 + if (sbw > 0) { 19031 + appData.sbWidth = sbw; 19032 + } 19033 + } 19034 + if (appData.sbWidth == 0) { 19035 + int i, sbw = 0; 19036 + for (i = 1; i < argc - 1; i++) { 19037 + if (!strcmp(argv[i], "-sbwidth")) { 19038 + sbw = atoi(argv[i+1]); 19039 + } 19040 + } 19041 + if (sbw > 0) { 19042 + appData.sbWidth = sbw; 19043 + } 19044 + } 19045 + save_sbw = appData.sbWidth; 19046 + if (save_sbw > 0) { 19047 + set_sbwidth(save_sbw); 19048 + } else { 19049 + set_sbwidth(6); 19050 + } 19051 + 19052 + toplevel = XtVaAppInitialize(&appContext, "Ssvnc", cmdLineOptions, 19053 + numCmdLineOptions, &argc, argv, fallback_resources, 19054 + XtNborderWidth, 0, NULL); 19055 19056 - dpy = XtDisplay(toplevel); 19057 + dpy = XtDisplay(toplevel); 19058 19059 /* Interpret resource specs and process any remaining command-line arguments 19060 (i.e. the VNC server name). If the server name isn't specified on the 19061 command line, getArgsAndResources() will pop up a dialog box and wait 19062 for one to be entered. */ 19063 19064 - GetArgsAndResources(argc, argv); 19065 + GetArgsAndResources(argc, argv); 19066 + 19067 + if (saw_appshare) { 19068 + appData.appShare = True; 19069 + } 19070 + 19071 + if (save_sbw) { 19072 + appData.sbWidth = save_sbw; 19073 + } 19074 + 19075 + if (appData.chatOnly) { 19076 + appData.encodingsString = "raw hextile"; 19077 + } 19078 + 19079 + if (pw_loc != NULL) { 19080 + char *q = pw_loc; 19081 + while (*q != '\0' && !isspace(*q)) { 19082 + *q = ' '; 19083 + q++; 19084 + } 19085 + } 19086 19087 /* Unless we accepted an incoming connection, make a TCP connection to the 19088 given VNC server */ 19089 19090 - if (!listenSpecified) { 19091 - if (!ConnectToRFBServer(vncServerHost, vncServerPort)) exit(1); 19092 - } 19093 + if (appData.repeaterUltra == NULL) { 19094 + if (getenv("SSVNC_REPEATER") != NULL) { 19095 + appData.repeaterUltra = strdup(getenv("SSVNC_REPEATER")); 19096 + } 19097 + } 19098 + 19099 + if (!listenSpecified) { 19100 + if (!ConnectToRFBServer(vncServerHost, vncServerPort)) { 19101 + exit(1); 19102 + } 19103 + if (appData.repeaterUltra != NULL) { 19104 + char tmp[256]; 19105 + if (strstr(appData.repeaterUltra, "SCIII=") == appData.repeaterUltra) { 19106 + appData.repeaterUltra = strdup(appData.repeaterUltra + strlen("SCIII=")); 19107 + fprintf(stderr, "sending 'testB' to ultravnc SC III SSL repeater...\n"); 19108 + WriteExact(rfbsock, "testB" , 5); 19109 + } 19110 + if (ReadFromRFBServer(tmp, 12)) { 19111 + tmp[12] = '\0'; 19112 + fprintf(stderr, "repeater 1st proto line: '%s'\n", tmp); 19113 + if (strstr(tmp, "RFB 000.000") == tmp) { 19114 + int i; 19115 + for (i=0; i<256; i++) { 19116 + tmp[i] = '\0'; 19117 + } 19118 + for (i=0; i<250; i++) { 19119 + if (i >= (int) strlen(appData.repeaterUltra)) { 19120 + break; 19121 + } 19122 + tmp[i] = appData.repeaterUltra[i]; 19123 + } 19124 + fprintf(stderr, "sending '%s' to repeater...\n", tmp); 19125 + WriteExact(rfbsock, tmp, 250); 19126 + } 19127 + } else { 19128 + fprintf(stderr, "repeater NO proto line!\n"); 19129 + } 19130 + } 19131 + } 19132 19133 /* Initialise the VNC connection, including reading the password */ 19134 19135 - if (!InitialiseRFBConnection()) exit(1); 19136 + if (!InitialiseRFBConnection()) { 19137 + Cleanup(); 19138 + exit(1); 19139 + } 19140 + if (appData.unixPW != NULL) { 19141 + unixpw(appData.unixPW, 0); 19142 + } else if (getenv("SSVNC_UNIXPW")) { 19143 + unixpw(getenv("SSVNC_UNIXPW"), 0); 19144 + } 19145 19146 /* Create the "popup" widget - this won't actually appear on the screen until 19147 some user-defined event causes the "ShowPopup" action to be invoked */ 19148 19149 - CreatePopup(); 19150 + CreatePopup(); 19151 + CreateScaleN(); 19152 + CreateTurboVNC(); 19153 + CreateQuality(); 19154 + CreateCompress(); 19155 + CreateChat(); 19156 19157 /* Find the best pixel format and X visual/colormap to use */ 19158 19159 - SetVisualAndCmap(); 19160 + SetVisualAndCmap(); 19161 19162 /* Create the "desktop" widget, and perform initialisation which needs doing 19163 before the widgets are realized */ 19164 19165 - ToplevelInitBeforeRealization(); 19166 + ToplevelInitBeforeRealization(); 19167 19168 - DesktopInitBeforeRealization(); 19169 + DesktopInitBeforeRealization(); 19170 19171 /* "Realize" all the widgets, i.e. actually create and map their X windows */ 19172 19173 - XtRealizeWidget(toplevel); 19174 + XtRealizeWidget(toplevel); 19175 19176 /* Perform initialisation that needs doing after realization, now that the X 19177 windows exist */ 19178 19179 - InitialiseSelection(); 19180 + InitialiseSelection(); 19181 19182 - ToplevelInitAfterRealization(); 19183 + ToplevelInitAfterRealization(); 19184 19185 - DesktopInitAfterRealization(); 19186 + DesktopInitAfterRealization(); 19187 19188 /* Tell the VNC server which pixel format and encodings we want to use */ 19189 19190 - SetFormatAndEncodings(); 19191 + SetFormatAndEncodings(); 19192 + 19193 + if (appData.chatOnly) { 19194 + chat_window_only(); 19195 + ToggleTextChat(0, NULL, NULL, NULL); 19196 + } 19197 19198 /* Now enter the main loop, processing VNC messages. X events will 19199 automatically be processed whenever the VNC connection is idle. */ 19200 19201 - while (1) { 19202 - if (!HandleRFBServerMessage()) 19203 - break; 19204 - } 19205 + while (1) { 19206 + if (!HandleRFBServerMessage()) { 19207 + break; 19208 + } 19209 + if (appData.chatOnly) { 19210 + chat_window_only(); 19211 + } 19212 + } 19213 + 19214 + Cleanup(); 19215 + 19216 + return 0; 19217 +} 19218 + 19219 +/* 19220 + * Toggle8bpp 19221 + */ 19222 + 19223 +static int last_ncolors = 0; 19224 +static int save_useBGR233 = 0; 19225 +static Bool save_useBGR565 = False; 19226 + 19227 +static Widget b8 = NULL; 19228 +static Widget b16 = NULL; 19229 +static Widget bfull = NULL; 19230 + 19231 +int do_format_change = 0; 19232 +int do_cursor_change = 0; 19233 +double do_fb_update = 0.0; 19234 +static void schedule_format_change(void) { 19235 + do_format_change = 1; 19236 + do_cursor_change = 0; 19237 +} 19238 +extern double dnow(void); 19239 +static void schedule_fb_update(void) { 19240 + do_fb_update = dnow(); 19241 +} 19242 +static void init_format_change(void) { 19243 + appDataNew.useBGR233 = appData.useBGR233; 19244 + appDataNew.useBGR565 = appData.useBGR565; 19245 + appDataNew.useGreyScale = appData.useGreyScale; 19246 + appDataNew.enableJPEG = appData.enableJPEG; 19247 + appDataNew.encodingsString = appData.encodingsString; 19248 + appDataNew.useRemoteCursor = appData.useRemoteCursor; 19249 + appDataNew.useX11Cursor = appData.useX11Cursor; 19250 + appDataNew.useRawLocal = appData.useRawLocal; 19251 + appDataNew.qualityLevel = appData.qualityLevel; 19252 + appDataNew.compressLevel = appData.compressLevel; 19253 +} 19254 +void cutover_format_change(void) { 19255 + appData.useBGR233 = appDataNew.useBGR233; 19256 + appData.useBGR565 = appDataNew.useBGR565; 19257 + appData.useGreyScale = appDataNew.useGreyScale; 19258 + appData.enableJPEG = appDataNew.enableJPEG; 19259 + appData.encodingsString = appDataNew.encodingsString; 19260 + appData.useRemoteCursor = appDataNew.useRemoteCursor; 19261 + appData.useX11Cursor = appDataNew.useX11Cursor; 19262 + appData.useRawLocal = appDataNew.useRawLocal; 19263 + appData.qualityLevel = appDataNew.qualityLevel; 19264 + appData.compressLevel = appDataNew.compressLevel; 19265 +} 19266 + 19267 +void 19268 +Toggle8bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19269 +{ 19270 + fprintf(stderr, "Toggle8bpp: %d\n", appData.useBGR233); 19271 + b8 = w; 19272 + init_format_change(); 19273 + if (appData.useBGR233) { 19274 + last_ncolors = appData.useBGR233; 19275 + appDataNew.useBGR233 = 0; 19276 + appDataNew.useBGR565 = save_useBGR565; 19277 + fprintf(stderr, "8bpp: off\n"); 19278 + } else { 19279 + if (!last_ncolors) last_ncolors = 256; 19280 + appDataNew.useBGR233 = last_ncolors; 19281 + save_useBGR565 = appData.useBGR565; 19282 + appDataNew.useBGR565 = False; 19283 + fprintf(stderr, "8bpp: on (%d colors)\n", appDataNew.useBGR233); 19284 + } 19285 + schedule_format_change(); 19286 + if (w || ev || params || num_params) {} 19287 +} 19288 + 19289 + 19290 +void 19291 +Toggle16bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19292 +{ 19293 + fprintf(stderr, "Toggle16bpp: %d\n", appData.useBGR565); 19294 + b16 = w; 19295 + init_format_change(); 19296 + if (appData.useBGR565) { 19297 + appDataNew.useBGR565 = False; 19298 + appDataNew.useBGR233 = save_useBGR233; 19299 + fprintf(stderr, "16bpp: off\n"); 19300 + } else { 19301 + appDataNew.useBGR565 = True; 19302 + save_useBGR233 = appData.useBGR233; 19303 + appDataNew.useBGR233 = 0; 19304 + fprintf(stderr, "16bpp: on\n"); 19305 + } 19306 + schedule_format_change(); 19307 + if (w || ev || params || num_params) {} 19308 +} 19309 + 19310 +void 19311 +ToggleFullColor(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19312 +{ 19313 + fprintf(stderr, "ToggleFullColor\n"); 19314 + bfull = w; 19315 + init_format_change(); 19316 + if (appData.useBGR565 || appData.useBGR233) { 19317 + save_useBGR565 = appData.useBGR565; 19318 + appDataNew.useBGR565 = False; 19319 + save_useBGR233 = appData.useBGR233; 19320 + appDataNew.useBGR233 = 0; 19321 + fprintf(stderr, "FullColor: on\n"); 19322 + } else { 19323 + if (save_useBGR565) { 19324 + appDataNew.useBGR565 = True; 19325 + appDataNew.useBGR233 = 0; 19326 + fprintf(stderr, "FullColor off -> 16bpp.\n"); 19327 + } else { 19328 + appDataNew.useBGR565 = False; 19329 + if (!save_useBGR233) save_useBGR233 = 256; 19330 + appDataNew.useBGR233 = save_useBGR233; 19331 + fprintf(stderr, "FullColor off -> 8bpp.\n"); 19332 + } 19333 + } 19334 + schedule_format_change(); 19335 + if (w || ev || params || num_params) {} 19336 +} 19337 + 19338 +void 19339 +ToggleXGrab(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19340 +{ 19341 + if (appData.grabAll) { 19342 + appData.grabAll = False; 19343 + } else { 19344 + appData.grabAll = True; 19345 + } 19346 + fprintf(stderr, "ToggleXGrab, current=%d\n", appData.grabAll); 19347 + /* always ungrab to be sure, fullscreen will handle the rest */ 19348 + XUngrabServer(dpy); 19349 + if (w || ev || params || num_params) {} 19350 +} 19351 + 19352 +void 19353 +ToggleEscapeActive(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19354 +{ 19355 + if (appData.escapeActive) { 19356 + appData.escapeActive = False; 19357 + } else { 19358 + appData.escapeActive = True; 19359 + } 19360 + if (w || ev || params || num_params) {} 19361 +} 19362 + 19363 +/* 19364 + * ToggleNColors 19365 + */ 19366 + 19367 +static Widget w256 = NULL; 19368 +static Widget w64 = NULL; 19369 +static Widget w8 = NULL; 19370 + 19371 +void 19372 +Toggle256Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19373 +{ 19374 + w256 = w; 19375 + if (appData.useBGR233 != 256) { 19376 + fprintf(stderr, "256 colors: on\n"); 19377 + init_format_change(); 19378 + last_ncolors = appDataNew.useBGR233 = 256; 19379 + save_useBGR565 = appData.useBGR565; 19380 + appDataNew.useBGR565 = False; 19381 + schedule_format_change(); 19382 + } 19383 + if (w || ev || params || num_params) {} 19384 +} 19385 + 19386 +void 19387 +Toggle64Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19388 +{ 19389 + w64 = w; 19390 + if (appData.useBGR233 != 64) { 19391 + fprintf(stderr, "64 colors: on\n"); 19392 + init_format_change(); 19393 + last_ncolors = appDataNew.useBGR233 = 64; 19394 + save_useBGR565 = appData.useBGR565; 19395 + appDataNew.useBGR565 = False; 19396 + schedule_format_change(); 19397 + } 19398 + if (w || ev || params || num_params) {} 19399 +} 19400 + 19401 +void 19402 +Toggle8Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19403 +{ 19404 + w8 = w; 19405 + if (appData.useBGR233 != 8) { 19406 + fprintf(stderr, "8 colors: on\n"); 19407 + init_format_change(); 19408 + last_ncolors = appDataNew.useBGR233 = 8; 19409 + save_useBGR565 = appData.useBGR565; 19410 + appDataNew.useBGR565 = False; 19411 + schedule_format_change(); 19412 + } 19413 + if (w || ev || params || num_params) {} 19414 +} 19415 + 19416 +void 19417 +ToggleGreyScale(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19418 +{ 19419 + fprintf(stderr, "ToggleGreyScale\n"); 19420 + init_format_change(); 19421 + if (appData.useGreyScale) { 19422 + appDataNew.useGreyScale = False; 19423 + fprintf(stderr, "greyscale: off\n"); 19424 + } else { 19425 + appDataNew.useGreyScale = True; 19426 + fprintf(stderr, "greyscale: on\n"); 19427 + } 19428 + schedule_format_change(); 19429 + if (w || ev || params || num_params) {} 19430 +} 19431 + 19432 +/* 19433 + * ToggleJPEG 19434 + */ 19435 + 19436 +void 19437 +ToggleJPEG(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19438 +{ 19439 + init_format_change(); 19440 + if (appData.enableJPEG) { 19441 + appDataNew.enableJPEG = False; 19442 + fprintf(stderr, "JPEG: off\n"); 19443 + } else { 19444 + appDataNew.enableJPEG = True; 19445 + fprintf(stderr, "JPEG: on\n"); 19446 + } 19447 + schedule_format_change(); 19448 + if (w || ev || params || num_params) {} 19449 +} 19450 + 19451 +/* 19452 + * ToggleTightZRLE 19453 + */ 19454 + 19455 +static Bool usingZRLE = False; 19456 +static Bool usingZYWRLE = False; 19457 +static Bool usingHextile = False; 19458 +extern int skip_maybe_sync; 19459 + 19460 +void 19461 +ToggleTightZRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19462 +{ 19463 + char prefTight[] = "copyrect tight zrle zywrle zlib hextile corre rre raw"; 19464 + char prefZRLE[] = "copyrect zrle zywrle tight zlib hextile corre rre raw"; 19465 + init_format_change(); 19466 + usingHextile = False; 19467 + if (! appData.encodingsString) { 19468 + appDataNew.encodingsString = strdup(prefZRLE); 19469 + usingZRLE = True; 19470 + fprintf(stderr, "prefer: ZRLE\n"); 19471 + } else { 19472 + char *t, *z; 19473 + static int first = 1; 19474 + t = strstr(appData.encodingsString, "tight"); 19475 + z = strstr(appData.encodingsString, "zrle"); 19476 + if (first && usingZRLE) { 19477 + appDataNew.encodingsString = strdup(prefTight); 19478 + usingZRLE = False; 19479 + usingZYWRLE = False; 19480 + } else if (! t) { 19481 + appDataNew.encodingsString = strdup(prefZRLE); 19482 + usingZRLE = True; 19483 + fprintf(stderr, "prefer: ZRLE\n"); 19484 + } else if (! z) { 19485 + appDataNew.encodingsString = strdup(prefTight); 19486 + usingZRLE = False; 19487 + usingZYWRLE = False; 19488 + skip_maybe_sync = 0; 19489 + fprintf(stderr, "prefer: Tight\n"); 19490 + } else { 19491 + if (t < z) { 19492 + appDataNew.encodingsString = strdup(prefZRLE); 19493 + usingZRLE = True; 19494 + fprintf(stderr, "prefer: ZRLE\n"); 19495 + } else { 19496 + appDataNew.encodingsString = strdup(prefTight); 19497 + usingZRLE = False; 19498 + usingZYWRLE = False; 19499 + skip_maybe_sync = 0; 19500 + fprintf(stderr, "prefer: Tight\n"); 19501 + } 19502 + } 19503 + first = 0; 19504 + } 19505 + schedule_format_change(); 19506 + if (w || ev || params || num_params) {} 19507 +} 19508 + 19509 +void 19510 +ToggleZRLEZYWRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19511 +{ 19512 + char prefZYWRLE[] = "copyrect zywrle zrle tight zlib hextile corre rre raw"; 19513 + char prefZRLE[] = "copyrect zrle zywrle tight zlib hextile corre rre raw"; 19514 + init_format_change(); 19515 + usingZRLE = True; 19516 + usingHextile = False; 19517 + if (! appData.encodingsString) { 19518 + appDataNew.encodingsString = strdup(prefZYWRLE); 19519 + usingZYWRLE = True; 19520 + fprintf(stderr, "prefer: ZYWRLE\n"); 19521 + } else { 19522 + char *z, *w; 19523 + w = strstr(appData.encodingsString, "zywrle"); 19524 + z = strstr(appData.encodingsString, "zrle"); 19525 + if (usingZYWRLE) { 19526 + appDataNew.encodingsString = strdup(prefZRLE); 19527 + fprintf(stderr, "prefer: ZRLE\n"); 19528 + usingZYWRLE = False; 19529 + skip_maybe_sync = 0; 19530 + } else { 19531 + appDataNew.encodingsString = strdup(prefZYWRLE); 19532 + fprintf(stderr, "prefer: ZYWRLE\n"); 19533 + usingZYWRLE = True; 19534 + } 19535 + } 19536 + schedule_format_change(); 19537 + if (w || ev || params || num_params) {} 19538 +} 19539 + 19540 +void 19541 +ToggleTightHextile(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19542 +{ 19543 + char prefTight[] = "copyrect tight zrle zywrle zlib hextile corre rre raw"; 19544 + char prefHextile[] = "copyrect hextile tight zrle zywrle zlib corre rre raw"; 19545 + init_format_change(); 19546 + usingZRLE = False; 19547 + usingZYWRLE = False; 19548 + if (! appData.encodingsString) { 19549 + appDataNew.encodingsString = strdup(prefHextile); 19550 + usingHextile = True; 19551 + fprintf(stderr, "prefer: Hextile\n"); 19552 + } else { 19553 + char *t, *z; 19554 + static int first = 1; 19555 + t = strstr(appData.encodingsString, "tight"); 19556 + z = strstr(appData.encodingsString, "hextile"); 19557 + if (first && usingHextile) { 19558 + appDataNew.encodingsString = strdup(prefTight); 19559 + usingHextile = False; 19560 + } else if (! t) { 19561 + appDataNew.encodingsString = strdup(prefHextile); 19562 + usingHextile = True; 19563 + fprintf(stderr, "prefer: Hextile\n"); 19564 + } else if (! z) { 19565 + appDataNew.encodingsString = strdup(prefTight); 19566 + usingHextile = False; 19567 + skip_maybe_sync = 0; 19568 + fprintf(stderr, "prefer: Tight\n"); 19569 + } else { 19570 + if (t < z) { 19571 + appDataNew.encodingsString = strdup(prefHextile); 19572 + usingHextile = True; 19573 + fprintf(stderr, "prefer: Hextile\n"); 19574 + } else { 19575 + appDataNew.encodingsString = strdup(prefTight); 19576 + usingHextile = False; 19577 + skip_maybe_sync = 0; 19578 + fprintf(stderr, "prefer: Tight\n"); 19579 + } 19580 + } 19581 + first = 0; 19582 + } 19583 + schedule_format_change(); 19584 + if (w || ev || params || num_params) {} 19585 +} 19586 + 19587 +void scale_check_zrle(void) { 19588 + static int didit = 0; 19589 + if (didit) { 19590 + return; 19591 + } 19592 + didit = 1; 19593 + if (getenv("SSVNC_PRESERVE_ENCODING")) { 19594 + return; 19595 + } 19596 + if (!usingZRLE && !usingHextile) { 19597 + Widget w = 0; 19598 + fprintf(stderr, "\nSwitching to faster ZRLE encoding in client-side scaling mode.\n"); 19599 + fprintf(stderr, "Switch back to Tight via the Popup menu if you prefer it.\n\n"); 19600 + ToggleTightZRLE(w, NULL, NULL, NULL); 19601 + } 19602 +} 19603 + 19604 +/* 19605 + * ToggleViewOnly 19606 + */ 19607 + 19608 +void 19609 +ToggleViewOnly(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19610 +{ 19611 + if (appData.viewOnly) { 19612 + appData.viewOnly = False; 19613 + fprintf(stderr, "viewonly: off\n"); 19614 + } else { 19615 + appData.viewOnly = True; 19616 + fprintf(stderr, "viewonly: on\n"); 19617 + } 19618 + Xcursors(1); 19619 + if (w || ev || params || num_params) {} 19620 +} 19621 + 19622 +void 19623 +ToggleCursorShape(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19624 +{ 19625 + init_format_change(); 19626 + if (appData.useRemoteCursor) { 19627 + appDataNew.useRemoteCursor = False; 19628 + fprintf(stderr, "useRemoteCursor: off\n"); 19629 + } else { 19630 + appDataNew.useRemoteCursor = True; 19631 + fprintf(stderr, "useRemoteCursor: on\n"); 19632 + } 19633 + schedule_format_change(); 19634 + if (!appDataNew.useRemoteCursor) { 19635 + do_cursor_change = 1; 19636 + } else { 19637 + do_cursor_change = -1; 19638 + } 19639 + if (w || ev || params || num_params) {} 19640 +} 19641 + 19642 +void 19643 +ToggleCursorAlpha(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19644 +{ 19645 + if (appData.useCursorAlpha) { 19646 + appData.useCursorAlpha = False; 19647 + fprintf(stderr, "useCursorAlpha: off\n"); 19648 + } else { 19649 + appData.useCursorAlpha = True; 19650 + fprintf(stderr, "useCursorAlpha: on\n"); 19651 + } 19652 + if (w || ev || params || num_params) {} 19653 +} 19654 + 19655 +void 19656 +ToggleX11Cursor(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19657 +{ 19658 + init_format_change(); 19659 + if (appData.useX11Cursor) { 19660 + appDataNew.useX11Cursor = False; 19661 + fprintf(stderr, "useX11Cursor: off\n"); 19662 + } else { 19663 + appDataNew.useX11Cursor = True; 19664 + fprintf(stderr, "useX11Cursor: on\n"); 19665 + } 19666 + schedule_format_change(); 19667 + do_cursor_change = 1; 19668 + if (w || ev || params || num_params) {} 19669 +} 19670 + 19671 +void 19672 +ToggleBell(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19673 +{ 19674 + if (appData.useBell) { 19675 + appData.useBell = False; 19676 + fprintf(stderr, "useBell: off\n"); 19677 + } else { 19678 + appData.useBell = True; 19679 + fprintf(stderr, "useBell: on\n"); 19680 + } 19681 + if (w || ev || params || num_params) {} 19682 +} 19683 + 19684 +void 19685 +ToggleRawLocal(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19686 +{ 19687 + init_format_change(); 19688 + if (appData.useRawLocal) { 19689 + appDataNew.useRawLocal = False; 19690 + fprintf(stderr, "useRawLocal: off\n"); 19691 + } else { 19692 + appDataNew.useRawLocal = True; 19693 + fprintf(stderr, "useRawLocal: on\n"); 19694 + } 19695 + schedule_format_change(); 19696 + if (w || ev || params || num_params) {} 19697 +} 19698 + 19699 +void 19700 +ToggleServerInput(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19701 +{ 19702 + if (appData.serverInput) { 19703 + appData.serverInput= False; 19704 + fprintf(stderr, "serverInput: off\n"); 19705 + SendServerInput(True); 19706 + } else { 19707 + appData.serverInput = True; 19708 + fprintf(stderr, "serverInput: on\n"); 19709 + SendServerInput(False); 19710 + } 19711 + if (w || ev || params || num_params) {} 19712 +} 19713 + 19714 +void 19715 +TogglePipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19716 +{ 19717 + if (appData.pipelineUpdates) { 19718 + appData.pipelineUpdates= False; 19719 + fprintf(stderr, "pipeline-update: off\n"); 19720 + } else { 19721 + appData.pipelineUpdates = True; 19722 + fprintf(stderr, "pipeline-update: on\n"); 19723 + } 19724 + /* XXX request one to be sure? */ 19725 + if (w || ev || params || num_params) {} 19726 +} 19727 + 19728 +void 19729 +ToggleSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19730 +{ 19731 + if (appData.sendClipboard) { 19732 + appData.sendClipboard= False; 19733 + fprintf(stderr, "Send CLIPBOARD Selection: off (send PRIMARY instead)\n"); 19734 + } else { 19735 + appData.sendClipboard = True; 19736 + fprintf(stderr, "Send CLIPBOARD Selection: on (do not send PRIMARY)\n"); 19737 + } 19738 + if (w || ev || params || num_params) {} 19739 +} 19740 + 19741 +void 19742 +ToggleSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19743 +{ 19744 + if (appData.sendAlways) { 19745 + appData.sendAlways= False; 19746 + fprintf(stderr, "Send Selection Always: off\n"); 19747 + } else { 19748 + appData.sendAlways = True; 19749 + fprintf(stderr, "Send Selection Always: on\n"); 19750 + } 19751 + if (w || ev || params || num_params) {} 19752 +} 19753 + 19754 + 19755 +Bool _sw1_ = False; /* XXX this is a weird bug... */ 19756 +Bool _sw2_ = False; 19757 +Bool _sw3_ = False; 19758 +Bool selectingSingleWindow = False; 19759 + 19760 +extern Cursor bogoCursor; 19761 + 19762 +void 19763 +ToggleSingleWindow(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19764 +{ 19765 + if (appData.singleWindow) { 19766 + appData.singleWindow= False; 19767 + fprintf(stderr, "singleWindow: off\n"); 19768 + SendSingleWindow(-1, -1); 19769 + } else { 19770 + appData.singleWindow = True; 19771 + selectingSingleWindow = True; 19772 + fprintf(stderr, "singleWindow: on\n"); 19773 + if (bogoCursor != None) { 19774 + XDefineCursor(dpy, desktopWin, bogoCursor); 19775 + } 19776 + } 19777 + if (w || ev || params || num_params) {} 19778 +} 19779 + 19780 +void raiseme(int force); 19781 +void AppendChatInput(char *); 19782 + 19783 +extern void ShowChat(Widget w, XEvent *event, String *params, Cardinal *num_params); 19784 +extern void ShowFile(Widget w, XEvent *event, String *params, Cardinal *num_params); 19785 +extern Bool SendTextChatFinished(void); 19786 + 19787 + 19788 +void printChat(char *str, Bool raise) { 19789 + if (appData.termChat) { 19790 + if (raise) { 19791 + raiseme(0); 19792 + } 19793 + fprintf(stderr, str); 19794 + } else { 19795 + if (raise) { 19796 + ShowChat(0, 0, 0, 0); 19797 + } 19798 + AppendChatInput(str); 19799 + } 19800 +} 19801 + 19802 +void 19803 +ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19804 +{ 19805 + if (appData.chatActive) { 19806 + printChat("\n*SentClose*\n\n", False); 19807 + SendTextChatClose(); 19808 + SendTextChatFinished(); 19809 + HideChat(0, NULL, NULL, NULL); 19810 + appData.chatActive= False; 19811 + } else { 19812 + ShowChat(0, 0, 0, 0); 19813 + SendTextChatOpen(); 19814 + if (appData.termChat) { 19815 + printChat("\n*SentOpen*\n\nSend: ", True); 19816 + } else { 19817 + printChat("\n*SentOpen*\n", True); 19818 + } 19819 + appData.chatActive = True; 19820 + } 19821 + if (w || ev || params || num_params) {} 19822 +} 19823 + 19824 +extern int filexfer_sock; 19825 +extern pid_t java_helper; 19826 +#define KILLJAVA 19827 +#ifdef KILLJAVA 19828 +#include <signal.h> 19829 +#endif 19830 + 19831 +void 19832 +ToggleFileXfer(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19833 +{ 19834 + static double last_start = 0.0; 19835 + if (appData.fileActive) { 19836 +#if 0 19837 + HideFile(w, ev, params, num_params); 19838 + appData.fileActive = False; 19839 +#endif 19840 +#ifndef KILLJAVA 19841 + if (filexfer_sock >= 0) { 19842 + close(filexfer_sock); 19843 + } 19844 +#else 19845 + if (java_helper != 0) { 19846 + int i; 19847 + if (dnow() < last_start + 6.0) { 19848 + fprintf(stderr, "skipping early kill of java helper (less than 5 secs)\n"); 19849 + } else { 19850 + for (i=1; i<=5; i++) { 19851 + pid_t p = java_helper + i; 19852 + fprintf(stderr, "trying to kill java helper: %d\n", p); 19853 + if (kill(p, SIGTERM) == 0) { 19854 + java_helper = 0; 19855 + break; 19856 + } 19857 + } 19858 + } 19859 + } 19860 +#endif 19861 + } else { 19862 + ShowFile(w, ev, params, num_params); 19863 + appData.fileActive = True; 19864 + last_start = dnow(); 19865 + } 19866 + if (w || ev || params || num_params) {} 19867 +} 19868 + 19869 +static int fooHandler(Display *dpy, XErrorEvent *error) { 19870 + if (dpy || error) {} 19871 + return 0; 19872 +} 19873 + 19874 +void raiseme(int force) { 19875 + if ((force || appData.termChat) && getenv("WINDOWID")) { 19876 + unsigned long w; 19877 + if (sscanf(getenv("WINDOWID"), "%lu", &w) == 1) { 19878 + ; 19879 + } else if (sscanf(getenv("WINDOWID"), "0x%lx", &w) == 1) { 19880 + ; 19881 + } else { 19882 + w = 0; 19883 + } 19884 + if (w != 0) { 19885 + XErrorHandler old = XSetErrorHandler(fooHandler); 19886 + XMapRaised(dpy, (Window) w); 19887 + XSync(dpy, False); 19888 + XSetErrorHandler(old); 19889 + } 19890 + } 19891 +} 19892 + 19893 +void set_server_scale(int n) { 19894 + if (n >= 1 && n < 100) { 19895 + int w = si.framebufferWidth; 19896 + int h = si.framebufferHeight; 19897 + appData.serverScale = n; 19898 + SendServerScale(n); 19899 + if (0) SendFramebufferUpdateRequest(0, 0, w, h, False); 19900 + schedule_fb_update(); 19901 + } 19902 +} 19903 + 19904 +void 19905 +DoServerScale(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19906 +{ 19907 + char str[100], *s, *q; 19908 + int n; 19909 + if (1) { 19910 + s = DoScaleNDialog(); 19911 + } else { 19912 + raiseme(1); 19913 + fprintf(stderr, "\n\n\a\nEnter integer n for 1/n server scaling: "); 19914 + str[0] = '\0'; 19915 + fgets(str, 100, stdin); 19916 + s = str; 19917 + q = strstr(str, "\n"); 19918 + if (q) *q = '\0'; 19919 + } 19920 + if (s[0] != '\0') { 19921 + n = atoi(s); 19922 + set_server_scale(n); 19923 + } 19924 + if (w || ev || params || num_params) {} 19925 +} 19926 + 19927 +void set_server_quality(int n) { 19928 + fprintf(stderr, "set_quality: %d\n", n); 19929 + if (n >= 0 && n <= 9) { 19930 + int w = si.framebufferWidth; 19931 + int h = si.framebufferHeight; 19932 + init_format_change(); 19933 + appDataNew.qualityLevel = n; 19934 + SendFramebufferUpdateRequest(0, 0, w, h, False); 19935 + schedule_format_change(); 19936 + } 19937 +} 19938 + 19939 +void 19940 +DoServerQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19941 +{ 19942 + char str[100], *s, *q; 19943 + int n; 19944 + if (1) { 19945 + s = DoQualityDialog(); 19946 + } else { 19947 + raiseme(1); 19948 + fprintf(stderr, "\n\n\a\nEnter integer 1 <= n <= 9 for quality setting: "); 19949 + str[0] = '\0'; 19950 + fgets(str, 100, stdin); 19951 + s = str; 19952 + q = strstr(str, "\n"); 19953 + if (q) *q = '\0'; 19954 + } 19955 + if (s[0] != '\0') { 19956 + n = atoi(s); 19957 + set_server_quality(n); 19958 + } 19959 + if (w || ev || params || num_params) {} 19960 +} 19961 + 19962 +void set_server_compress(int n) { 19963 + fprintf(stderr, "set_compress: %d\n", n); 19964 + if (n >= 0 && n <= 9) { 19965 + int w = si.framebufferWidth; 19966 + int h = si.framebufferHeight; 19967 + init_format_change(); 19968 + appDataNew.compressLevel = n; 19969 + SendFramebufferUpdateRequest(0, 0, w, h, False); 19970 + schedule_format_change(); 19971 + } 19972 +} 19973 + 19974 +void 19975 +DoServerCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params) 19976 +{ 19977 + char str[100], *s, *q; 19978 + int n; 19979 + if (1) { 19980 + s = DoCompressDialog(); 19981 + } else { 19982 + raiseme(1); 19983 + fprintf(stderr, "\n\n\a\nEnter integer 1 <= n <= 9 for compress level setting: "); 19984 + str[0] = '\0'; 19985 + fgets(str, 100, stdin); 19986 + s = str; 19987 + q = strstr(str, "\n"); 19988 + if (q) *q = '\0'; 19989 + } 19990 + if (s[0] != '\0') { 19991 + n = atoi(s); 19992 + set_server_compress(n); 19993 + } 19994 + if (w || ev || params || num_params) {} 19995 +} 19996 + 19997 +extern void rescale_image(void); 19998 +extern void get_scale_values(double *fx, double *fy); 19999 + 20000 +void 20001 +SetScale(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20002 +{ 20003 + char *s; 20004 + s = DoScaleDialog(); 20005 + if (s[0] != '\0') { 20006 +#if 0 20007 + int w = si.framebufferWidth; 20008 + int h = si.framebufferHeight; 20009 +#endif 20010 + double fx, fy; 20011 + int fs = 0; 20012 + if (appData.scale != NULL && !strcmp(s, appData.scale)) { 20013 + return; 20014 + } 20015 + 20016 + if (!strcasecmp(s, "none")) { 20017 + appData.scale = NULL; 20018 + } else if (!strcmp(s, "1.0")) { 20019 + appData.scale = NULL; 20020 + } else if (!strcmp(s, "1")) { 20021 + appData.scale = NULL; 20022 + } else { 20023 + appData.scale = strdup(s); 20024 + } 20025 + if (appData.scale != NULL) { 20026 + get_scale_values(&fx, &fy); 20027 + if (fx <= 0.0 || fy <= 0.0) { 20028 + appData.scale = NULL; 20029 + return; 20030 + } 20031 + } 20032 + 20033 + if (appData.fullScreen) { 20034 + fs = 1; 20035 + FullScreenOff(); 20036 + } 20037 + rescale_image(); 20038 + if (fs) { 20039 + FullScreenOn(); 20040 + } 20041 + } 20042 + if (w || ev || params || num_params) {} 20043 +} 20044 + 20045 +void 20046 +SetEscapeKeys(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20047 +{ 20048 + char *s; 20049 + s = DoEscapeKeysDialog(); 20050 + fprintf(stderr, "set escape keys: '%s'\n", s); 20051 + if (s[0] != '\0') { 20052 + appData.escapeKeys = strdup(s); 20053 + } 20054 + if (w || ev || params || num_params) {} 20055 +} 20056 + 20057 +void set_ycrop(int n) { 20058 + if (n >= 1) { 20059 + int w = si.framebufferWidth; 20060 + int h = si.framebufferHeight; 20061 + appData.yCrop = n; 20062 + ReDoDesktop(); 20063 + SendFramebufferUpdateRequest(0, 0, w, h, False); 20064 + schedule_fb_update(); 20065 + } 20066 +} 20067 20068 - Cleanup(); 20069 +void 20070 +SetYCrop(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20071 +{ 20072 + char str[100], *q, *s; 20073 + int n; 20074 + if (1) { 20075 + s = DoYCropDialog(); 20076 + } else { 20077 + raiseme(1); 20078 + fprintf(stderr, "\n\n\a\nEnter pixel size n -ycrop maximum y-height: "); 20079 + str[0] = '\0'; 20080 + fgets(str, 100, stdin); 20081 + s = str; 20082 + q = strstr(str, "\n"); 20083 + if (q) *q = '\0'; 20084 + } 20085 + if (s[0] != '\0') { 20086 + n = atoi(s); 20087 + set_ycrop(n); 20088 + } 20089 + if (w || ev || params || num_params) {} 20090 +} 20091 + 20092 +void set_scbar(int n) { 20093 + if (n >= 1) { 20094 + int w = si.framebufferWidth; 20095 + int h = si.framebufferHeight; 20096 +fprintf(stderr, "set_scbat: %d\n", n); 20097 + appData.sbWidth = n; 20098 + ReDoDesktop(); 20099 + SendFramebufferUpdateRequest(0, 0, w, h, False); 20100 + schedule_fb_update(); 20101 + } 20102 +} 20103 + 20104 +void 20105 +SetScbar(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20106 +{ 20107 + char str[100], *q, *s; 20108 + int n; 20109 + if (1) { 20110 + s = DoScbarDialog(); 20111 + } else { 20112 + raiseme(1); 20113 + fprintf(stderr, "\n\n\a\nEnter pixel size n scrollbar width: "); 20114 + str[0] = '\0'; 20115 + fgets(str, 100, stdin); 20116 + s = str; 20117 + q = strstr(str, "\n"); 20118 + if (q) *q = '\0'; 20119 + } 20120 + if (s[0] != '\0') { 20121 + n = atoi(s); 20122 + set_scbar(n); 20123 + } 20124 + if (w || ev || params || num_params) {} 20125 +} 20126 + 20127 +void 20128 +SetScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20129 +{ 20130 + if (*num_params != 0) { 20131 + int n = atoi(params[0]); 20132 + set_server_scale(n); 20133 + } 20134 + if (w || ev || params || num_params) {} 20135 +} 20136 + 20137 +void UpdateQual(void) { 20138 + SetFormatAndEncodings(); 20139 + UpdateSubsampButtons(); 20140 + UpdateQualSlider(); 20141 +} 20142 + 20143 +extern double latency; 20144 + 20145 +static void LosslessRefresh(void) { 20146 + String encodings = appData.encodingsString; 20147 + int compressLevel = appData.compressLevel; 20148 + int qual = appData.qualityLevel; 20149 + Bool enableJPEG = appData.enableJPEG; 20150 + appData.qualityLevel = -1; 20151 + appData.enableJPEG = False; 20152 + appData.encodingsString = "tight copyrect"; 20153 + appData.compressLevel = 1; 20154 + SetFormatAndEncodings(); 20155 + SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False); 20156 + if (latency > 0.0) { 20157 + if (0) usleep((int) latency * 1000); 20158 + } 20159 + appData.qualityLevel = qual; 20160 + appData.enableJPEG = enableJPEG; 20161 + appData.encodingsString = encodings; 20162 + appData.compressLevel = compressLevel; 20163 + SetFormatAndEncodings(); 20164 +} 20165 + 20166 +static void QualHigh(void) { 20167 + appData.encodingsString = "tight copyrect"; 20168 + if(appData.useBGR233 || appDataNew.useBGR565) { 20169 + fprintf(stderr, "WARNING: Cannot enable JPEG because BGR233/BGR565 is enabled.\n"); 20170 + } else { 20171 + appData.enableJPEG = True; 20172 + } 20173 + appData.subsampLevel = TVNC_1X; 20174 + appData.qualityLevel = 95; 20175 + UpdateQual(); 20176 +} 20177 + 20178 +static void QualMed(void) { 20179 + appData.encodingsString = "tight copyrect"; 20180 + if(appData.useBGR233 || appDataNew.useBGR565) { 20181 + fprintf(stderr, "WARNING: Cannot enable JPEG because BGR233/BGR565 is enabled.\n"); 20182 + } else { 20183 + appData.enableJPEG = True; 20184 + } 20185 + appData.subsampLevel = TVNC_2X; 20186 + appData.qualityLevel = 80; 20187 + UpdateQual(); 20188 +} 20189 + 20190 +static void QualLow(void) { 20191 + appData.encodingsString = "tight copyrect"; 20192 + if(appData.useBGR233 || appDataNew.useBGR565) { 20193 + fprintf(stderr, "WARNING: Cannot enable JPEG because BGR233/BGR565 is enabled.\n"); 20194 + } else { 20195 + appData.enableJPEG = True; 20196 + } 20197 + appData.subsampLevel = TVNC_4X; 20198 + appData.qualityLevel = 30; 20199 + UpdateQual(); 20200 +} 20201 + 20202 +static void QualLossless(void) { 20203 + appData.encodingsString = "tight copyrect"; 20204 + appData.enableJPEG = False; 20205 + appData.compressLevel = 0; 20206 + UpdateQual(); 20207 +} 20208 20209 - return 0; 20210 +static void QualLosslessWAN(void) { 20211 + appData.encodingsString = "tight copyrect"; 20212 + appData.enableJPEG = False; 20213 + appData.compressLevel = 1; 20214 + UpdateQual(); 20215 +} 20216 + 20217 +void 20218 +SetTurboVNC(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20219 +{ 20220 + if (*num_params != 0) { 20221 + int n = atoi(params[0]); 20222 + if (0) fprintf(stderr, "SetTurboVNC: %d\n", n); 20223 + if (n == 1) { 20224 + QualHigh(); 20225 + } else if (n == 2) { 20226 + QualMed(); 20227 + } else if (n == 3) { 20228 + QualLow(); 20229 + } else if (n == 4) { 20230 + QualLossless(); 20231 + } else if (n == 5) { 20232 + QualLosslessWAN(); 20233 + } else if (n == 6) { 20234 + appData.subsampLevel = TVNC_1X; 20235 + UpdateQual(); 20236 + } else if (n == 7) { 20237 + appData.subsampLevel = TVNC_2X; 20238 + UpdateQual(); 20239 + } else if (n == 8) { 20240 + appData.subsampLevel = TVNC_4X; 20241 + UpdateQual(); 20242 + } else if (n == 9) { 20243 + appData.subsampLevel = TVNC_GRAY; 20244 + UpdateQual(); 20245 + } else if (n == 10) { 20246 + LosslessRefresh(); 20247 + } 20248 + } 20249 + if (w || ev || params || num_params) {} 20250 +} 20251 + 20252 +void 20253 +SetQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20254 +{ 20255 + if (*num_params != 0) { 20256 + int n = atoi(params[0]); 20257 + set_server_quality(n); 20258 + } 20259 + if (w || ev || params || num_params) {} 20260 +} 20261 + 20262 +void 20263 +SetCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20264 +{ 20265 + if (*num_params != 0) { 20266 + int n = atoi(params[0]); 20267 + set_server_compress(n); 20268 + } 20269 + if (w || ev || params || num_params) {} 20270 +} 20271 + 20272 +void 20273 +GotChatText(char *str, int len) 20274 +{ 20275 + static char *b = NULL; 20276 + static int blen = -1; 20277 + int i, k; 20278 + if (appData.termChat) { 20279 + printChat("\nChat: ", True); 20280 + } else { 20281 + printChat("Chat: ", True); 20282 + } 20283 + 20284 + if (len < 0) len = 0; 20285 + 20286 + if (blen < len+1) { 20287 + if (b) free(b); 20288 + blen = 2 * (len + 10); 20289 + b = (char *) malloc(blen); 20290 + } 20291 + 20292 + k = 0; 20293 + for (i=0; i < len; i++) { 20294 + if (str[i] != '\r') { 20295 + b[k++] = str[i]; 20296 + } 20297 + } 20298 + b[k] = '\0'; 20299 + b[len] = '\0'; 20300 + printChat(b, True); 20301 + 20302 + if (appData.termChat) { 20303 + if (strstr(str, "\n")) { 20304 + printChat("Send: ", True); 20305 + } else { 20306 + printChat("\nSend: ", True); 20307 + } 20308 + } 20309 +} 20310 + 20311 +void 20312 +SetViewOnlyState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20313 +{ 20314 + if (appData.viewOnly) { 20315 + XtVaSetValues(w, XtNstate, True, NULL); 20316 + } else { 20317 + XtVaSetValues(w, XtNstate, False, NULL); 20318 + } 20319 + if (w || ev || params || num_params) {} 20320 +} 20321 + 20322 +void 20323 +SetNOJPEGState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20324 +{ 20325 + if (appData.enableJPEG) { 20326 + XtVaSetValues(w, XtNstate, False, NULL); 20327 + } else { 20328 + XtVaSetValues(w, XtNstate, True, NULL); 20329 + } 20330 + if (w || ev || params || num_params) {} 20331 +} 20332 + 20333 +void 20334 +SetQualityState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20335 +{ 20336 + if (*num_params != 0) { 20337 + int n = atoi(params[0]); 20338 + if (appData.qualityLevel == n) { 20339 + XtVaSetValues(w, XtNstate, True, NULL); 20340 + } else { 20341 + XtVaSetValues(w, XtNstate, False, NULL); 20342 + } 20343 + } 20344 + if (w || ev || params || num_params) {} 20345 +} 20346 + 20347 +void 20348 +SetCompressState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20349 +{ 20350 + if (*num_params != 0) { 20351 + int n = atoi(params[0]); 20352 + if (appData.compressLevel == n) { 20353 + XtVaSetValues(w, XtNstate, True, NULL); 20354 + } else { 20355 + XtVaSetValues(w, XtNstate, False, NULL); 20356 + } 20357 + } 20358 + if (w || ev || params || num_params) {} 20359 +} 20360 + 20361 +void 20362 +SetScaleNState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20363 +{ 20364 + if (*num_params != 0) { 20365 + int n = atoi(params[0]); 20366 + if (appData.serverScale == n || (appData.serverScale >= 6 && n >= 6)) { 20367 + XtVaSetValues(w, XtNstate, True, NULL); 20368 + } else { 20369 + XtVaSetValues(w, XtNstate, False, NULL); 20370 + } 20371 + } 20372 + if (w || ev || params || num_params) {} 20373 +} 20374 + 20375 +void 20376 +Set8bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20377 +{ 20378 + if (appData.useBGR233) { 20379 + XtVaSetValues(w, XtNstate, True, NULL); 20380 + if (b16 != NULL) { 20381 + XtVaSetValues(b16, XtNstate, False, NULL); 20382 + } 20383 + if (bfull != NULL) { 20384 + XtVaSetValues(bfull, XtNstate, False, NULL); 20385 + } 20386 + } else { 20387 + XtVaSetValues(w, XtNstate, False, NULL); 20388 + } 20389 + if (w || ev || params || num_params) {} 20390 +} 20391 + 20392 +void 20393 +Set16bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20394 +{ 20395 + if (appData.useBGR565) { 20396 + XtVaSetValues(w, XtNstate, True, NULL); 20397 + if (b8 != NULL) { 20398 + XtVaSetValues(b8, XtNstate, False, NULL); 20399 + } 20400 + if (bfull != NULL) { 20401 + XtVaSetValues(bfull, XtNstate, False, NULL); 20402 + } 20403 + } else { 20404 + XtVaSetValues(w, XtNstate, False, NULL); 20405 + } 20406 + if (w || ev || params || num_params) {} 20407 +} 20408 + 20409 +void 20410 +SetFullColorState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20411 +{ 20412 + if (appData.useBGR565 || appData.useBGR233) { 20413 + XtVaSetValues(w, XtNstate, False, NULL); 20414 + } else { 20415 + XtVaSetValues(w, XtNstate, True, NULL); 20416 + if (b8 != NULL) { 20417 + XtVaSetValues(b8, XtNstate, False, NULL); 20418 + } 20419 + if (b16 != NULL) { 20420 + XtVaSetValues(b16, XtNstate, False, NULL); 20421 + } 20422 + } 20423 + if (w || ev || params || num_params) {} 20424 +} 20425 + 20426 +void 20427 +SetXGrabState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20428 +{ 20429 + if (appData.grabAll) { 20430 + XtVaSetValues(w, XtNstate, True, NULL); 20431 + } else { 20432 + XtVaSetValues(w, XtNstate, False, NULL); 20433 + } 20434 + if (w || ev || params || num_params) {} 20435 +} 20436 + 20437 +void 20438 +SetEscapeKeysState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20439 +{ 20440 + if (appData.escapeActive) { 20441 + XtVaSetValues(w, XtNstate, True, NULL); 20442 + } else { 20443 + XtVaSetValues(w, XtNstate, False, NULL); 20444 + } 20445 + if (w || ev || params || num_params) {} 20446 +} 20447 + 20448 +void 20449 +Set256ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20450 +{ 20451 + if (appData.useBGR233 == 256) { 20452 + XtVaSetValues(w, XtNstate, True, NULL); 20453 + if (w64 != NULL) { 20454 + XtVaSetValues(w64 , XtNstate, False, NULL); 20455 + } 20456 + if (w8 != NULL) { 20457 + XtVaSetValues(w8 , XtNstate, False, NULL); 20458 + } 20459 + } else { 20460 + XtVaSetValues(w, XtNstate, False, NULL); 20461 + } 20462 + if (w || ev || params || num_params) {} 20463 +} 20464 + 20465 +void 20466 +Set64ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20467 +{ 20468 + if (appData.useBGR233 == 64) { 20469 + XtVaSetValues(w, XtNstate, True, NULL); 20470 + if (w256 != NULL) { 20471 + XtVaSetValues(w256, XtNstate, False, NULL); 20472 + } 20473 + if (w8 != NULL) { 20474 + XtVaSetValues(w8 , XtNstate, False, NULL); 20475 + } 20476 + } else { 20477 + XtVaSetValues(w, XtNstate, False, NULL); 20478 + } 20479 + if (w || ev || params || num_params) {} 20480 +} 20481 + 20482 +void 20483 +Set8ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20484 +{ 20485 + if (appData.useBGR233 == 8) { 20486 + XtVaSetValues(w, XtNstate, True, NULL); 20487 + if (w256 != NULL) { 20488 + XtVaSetValues(w256, XtNstate, False, NULL); 20489 + } 20490 + if (w64 != NULL) { 20491 + XtVaSetValues(w64 , XtNstate, False, NULL); 20492 + } 20493 + } else { 20494 + XtVaSetValues(w, XtNstate, False, NULL); 20495 + } 20496 + if (w || ev || params || num_params) {} 20497 +} 20498 + 20499 +void 20500 +SetGreyScaleState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20501 +{ 20502 + if (appData.useGreyScale) { 20503 + XtVaSetValues(w, XtNstate, True, NULL); 20504 + } else { 20505 + XtVaSetValues(w, XtNstate, False, NULL); 20506 + } 20507 + if (w || ev || params || num_params) {} 20508 +} 20509 + 20510 +static void init_state(void) { 20511 + static int first = 1; 20512 + if (first && appData.encodingsString) { 20513 + char *t, *z, *y, *h; 20514 + char *str = appData.encodingsString; 20515 + int len = strlen(str); 20516 + 20517 + t = strstr(str, "tight"); 20518 + z = strstr(str, "zrle"); 20519 + y = strstr(str, "zywrle"); 20520 + h = strstr(str, "hextile"); 20521 + 20522 + if (!t) t = str + len; 20523 + if (!z) z = str + len; 20524 + if (!y) y = str + len; 20525 + if (!h) h = str + len; 20526 + 20527 + usingZRLE = False; 20528 + usingZYWRLE = False; 20529 + usingHextile = False; 20530 + 20531 + if (t < z && t < y && t < h) { 20532 + ; 20533 + } else if (z < t && z < y && z < h) { 20534 + usingZRLE = True; 20535 + } else if (y < t && y < z && y < h) { 20536 + usingZYWRLE = True; 20537 + usingZRLE = True; 20538 + } else if (h < t && h < z && h < y) { 20539 + usingHextile = True; 20540 + } 20541 + } 20542 + first = 0; 20543 + 20544 +} 20545 + 20546 +void 20547 +SetZRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20548 +{ 20549 + init_state(); 20550 + if (usingZRLE) { 20551 + XtVaSetValues(w, XtNstate, True, NULL); 20552 + } else { 20553 + XtVaSetValues(w, XtNstate, False, NULL); 20554 + } 20555 + if (w || ev || params || num_params) {} 20556 +} 20557 + 20558 +void 20559 +SetHextileState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20560 +{ 20561 + init_state(); 20562 + if (usingHextile) { 20563 + XtVaSetValues(w, XtNstate, True, NULL); 20564 + } else { 20565 + XtVaSetValues(w, XtNstate, False, NULL); 20566 + } 20567 + if (w || ev || params || num_params) {} 20568 +} 20569 + 20570 +void 20571 +SetZYWRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20572 +{ 20573 + init_state(); 20574 + if (usingZYWRLE) { 20575 + XtVaSetValues(w, XtNstate, True, NULL); 20576 + } else { 20577 + XtVaSetValues(w, XtNstate, False, NULL); 20578 + } 20579 + if (w || ev || params || num_params) {} 20580 +} 20581 + 20582 +void 20583 +SetCursorShapeState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20584 +{ 20585 + if (appData.useRemoteCursor) { 20586 + XtVaSetValues(w, XtNstate, True, NULL); 20587 + } else { 20588 + XtVaSetValues(w, XtNstate, False, NULL); 20589 + } 20590 + if (w || ev || params || num_params) {} 20591 +} 20592 + 20593 +void 20594 +SetCursorAlphaState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20595 +{ 20596 + if (appData.useCursorAlpha) { 20597 + XtVaSetValues(w, XtNstate, True, NULL); 20598 + } else { 20599 + XtVaSetValues(w, XtNstate, False, NULL); 20600 + } 20601 + if (w || ev || params || num_params) {} 20602 +} 20603 + 20604 +void 20605 +SetX11CursorState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20606 +{ 20607 + if (appData.useX11Cursor) { 20608 + XtVaSetValues(w, XtNstate, True, NULL); 20609 + } else { 20610 + XtVaSetValues(w, XtNstate, False, NULL); 20611 + } 20612 + if (w || ev || params || num_params) {} 20613 +} 20614 + 20615 +void 20616 +SetBellState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20617 +{ 20618 + if (appData.useBell) { 20619 + XtVaSetValues(w, XtNstate, False, NULL); 20620 + } else { 20621 + XtVaSetValues(w, XtNstate, True, NULL); 20622 + } 20623 + if (w || ev || params || num_params) {} 20624 +} 20625 + 20626 +void 20627 +SetRawLocalState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20628 +{ 20629 + if (appData.useRawLocal) { 20630 + XtVaSetValues(w, XtNstate, True, NULL); 20631 + } else { 20632 + XtVaSetValues(w, XtNstate, False, NULL); 20633 + } 20634 + if (w || ev || params || num_params) {} 20635 +} 20636 + 20637 +void 20638 +SetServerInputState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20639 +{ 20640 + if (!appData.serverInput) { 20641 + XtVaSetValues(w, XtNstate, True, NULL); 20642 + } else { 20643 + XtVaSetValues(w, XtNstate, False, NULL); 20644 + } 20645 + if (w || ev || params || num_params) {} 20646 +} 20647 + 20648 +void 20649 +SetPipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20650 +{ 20651 + if (!appData.pipelineUpdates) { 20652 + XtVaSetValues(w, XtNstate, False, NULL); 20653 + } else { 20654 + XtVaSetValues(w, XtNstate, True, NULL); 20655 + } 20656 + if (w || ev || params || num_params) {} 20657 +} 20658 + 20659 +void 20660 +SetSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20661 +{ 20662 + if (!appData.sendClipboard) { 20663 + XtVaSetValues(w, XtNstate, False, NULL); 20664 + } else { 20665 + XtVaSetValues(w, XtNstate, True, NULL); 20666 + } 20667 + if (w || ev || params || num_params) {} 20668 +} 20669 + 20670 +void 20671 +SetSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20672 +{ 20673 + if (!appData.sendAlways) { 20674 + XtVaSetValues(w, XtNstate, False, NULL); 20675 + } else { 20676 + XtVaSetValues(w, XtNstate, True, NULL); 20677 + } 20678 + if (w || ev || params || num_params) {} 20679 +} 20680 + 20681 +void 20682 +SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20683 +{ 20684 + if (appData.singleWindow) { 20685 + XtVaSetValues(w, XtNstate, True, NULL); 20686 + } else { 20687 + XtVaSetValues(w, XtNstate, False, NULL); 20688 + } 20689 + if (w || ev || params || num_params) {} 20690 +} 20691 + 20692 +void 20693 +SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20694 +{ 20695 + if (appData.chatActive) { 20696 + XtVaSetValues(w, XtNstate, True, NULL); 20697 + } else { 20698 + XtVaSetValues(w, XtNstate, False, NULL); 20699 + } 20700 + if (w || ev || params || num_params) {} 20701 +} 20702 + 20703 +void 20704 +SetFileXferState(Widget w, XEvent *ev, String *params, Cardinal *num_params) 20705 +{ 20706 + if (appData.fileActive) { 20707 + XtVaSetValues(w, XtNstate, True, NULL); 20708 + } else { 20709 + XtVaSetValues(w, XtNstate, False, NULL); 20710 + } 20711 + if (w || ev || params || num_params) {} 20712 } 20713 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncviewer/vncviewer.h 20714 --- vnc_unixsrc.orig/vncviewer/vncviewer.h 2004-03-11 13:14:40.000000000 -0500 20715 +++ vnc_unixsrc/vncviewer/vncviewer.h 2010-04-17 22:29:42.000000000 -0400 20716 @@ -28,6 +28,7 @@ 20717 #include <string.h> 20718 #include <sys/time.h> 20719 #include <sys/types.h> 20720 +#include <sys/stat.h> 20721 #include <unistd.h> 20722 #include <pwd.h> 20723 #include <X11/IntrinsicP.h> 20724 @@ -51,7 +52,13 @@ 20725 (((l) & 0x0000ff00) << 8) | \ 20726 (((l) & 0x000000ff) << 24)) : (l)) 20727 20728 -#define MAX_ENCODINGS 20 20729 +#define Swap32IfBE(l) \ 20730 + (*(char *)&endianTest ? (l) : ((((l) & 0xff000000) >> 24) | \ 20731 + (((l) & 0x00ff0000) >> 8) | \ 20732 + (((l) & 0x0000ff00) << 8) | \ 20733 + (((l) & 0x000000ff) << 24)) ) 20734 + 20735 +#define MAX_ENCODINGS 24 20736 20737 #define FLASH_PORT_OFFSET 5400 20738 #define LISTEN_PORT_OFFSET 5500 20739 @@ -64,60 +71,133 @@ 20740 #define DEFAULT_VIA_CMD \ 20741 (DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20") 20742 20743 +#define TVNC_SAMPOPT 4 20744 +enum {TVNC_1X=0, TVNC_4X, TVNC_2X, TVNC_GRAY}; 20745 20746 -/* argsresources.c */ 20747 - 20748 -typedef struct { 20749 - Bool shareDesktop; 20750 - Bool viewOnly; 20751 - Bool fullScreen; 20752 - Bool grabKeyboard; 20753 - Bool raiseOnBeep; 20754 - 20755 - String encodingsString; 20756 - 20757 - Bool useBGR233; 20758 - int nColours; 20759 - Bool useSharedColours; 20760 - Bool forceOwnCmap; 20761 - Bool forceTrueColour; 20762 - int requestedDepth; 20763 - 20764 - Bool useShm; 20765 - 20766 - int wmDecorationWidth; 20767 - int wmDecorationHeight; 20768 - 20769 - char *userLogin; 20770 - 20771 - char *passwordFile; 20772 - Bool passwordDialog; 20773 - 20774 - int rawDelay; 20775 - int copyRectDelay; 20776 +#if 0 20777 +static const char *subsampLevel2str[TVNC_SAMPOPT] = { 20778 + "1X", "4X", "2X", "Gray" 20779 +}; 20780 +#endif 20781 +#ifdef TURBOVNC 20782 +#define rfbTightNoZlib 0x0A 20783 +#define rfbTurboVncVendor "TRBO" 20784 +#define rfbJpegQualityLevel1 0xFFFFFE01 20785 +#define rfbJpegQualityLevel100 0xFFFFFE64 20786 +#define rfbJpegSubsamp1X 0xFFFFFD00 20787 +#define rfbJpegSubsamp4X 0xFFFFFD01 20788 +#define rfbJpegSubsamp2X 0xFFFFFD02 20789 +#define rfbJpegSubsampGray 0xFFFFFD03 20790 +#endif 20791 + 20792 +/* for debugging width, height, etc */ 20793 +#if 0 20794 +#define XtVaSetValues printf("%s:%d\n", __FILE__, __LINE__); XtVaSetValues 20795 +#endif 20796 20797 - Bool debug; 20798 20799 - int popupButtonCount; 20800 +/* argsresources.c */ 20801 20802 - int bumpScrollTime; 20803 - int bumpScrollPixels; 20804 +typedef struct { 20805 + Bool shareDesktop; 20806 + Bool viewOnly; 20807 + Bool fullScreen; 20808 + Bool grabKeyboard; 20809 + Bool raiseOnBeep; 20810 + 20811 + String encodingsString; 20812 + 20813 + int useBGR233; 20814 + int nColours; 20815 + Bool useSharedColours; 20816 + Bool forceOwnCmap; 20817 + Bool forceTrueColour; 20818 + int requestedDepth; 20819 + Bool useBGR565; 20820 + Bool useGreyScale; 20821 + 20822 + Bool grabAll; 20823 + Bool useXserverBackingStore; 20824 + Bool overrideRedir; 20825 + Bool popupFix; 20826 + 20827 + Bool useShm; 20828 + Bool termChat; 20829 + 20830 + int wmDecorationWidth; 20831 + int wmDecorationHeight; 20832 + 20833 + char *userLogin; 20834 + char *unixPW; 20835 + char *msLogon; 20836 + char *repeaterUltra; 20837 + Bool ultraDSM; 20838 + Bool acceptPopup; 20839 + char *rfbVersion; 20840 + 20841 + char *passwordFile; 20842 + Bool passwordDialog; 20843 + Bool notty; 20844 + 20845 + int rawDelay; 20846 + int copyRectDelay; 20847 + 20848 + int yCrop; 20849 + int sbWidth; 20850 + Bool useCursorAlpha; 20851 + Bool useRawLocal; 20852 + 20853 + Bool debug; 20854 + 20855 + int popupButtonCount; 20856 + int popupButtonBreak; 20857 + 20858 + int bumpScrollTime; 20859 + int bumpScrollPixels; 20860 + 20861 + int compressLevel; 20862 + int qualityLevel; 20863 + Bool enableJPEG; 20864 + Bool useRemoteCursor; 20865 + Bool useX11Cursor; 20866 + Bool useBell; 20867 + Bool autoPass; 20868 + 20869 + Bool serverInput; 20870 + Bool singleWindow; 20871 + int serverScale; 20872 + Bool chatActive; 20873 + Bool chatOnly; 20874 + Bool fileActive; 20875 + 20876 + char *scale; 20877 + char *escapeKeys; 20878 + Bool appShare; 20879 + Bool escapeActive; 20880 + Bool pipelineUpdates; 20881 + 20882 + Bool sendClipboard; 20883 + Bool sendAlways; 20884 + char *recvText; 20885 + 20886 + /* only for turbovnc mode */ 20887 + String subsampString; 20888 + int subsampLevel; 20889 + Bool doubleBuffer; 20890 20891 - int compressLevel; 20892 - int qualityLevel; 20893 - Bool enableJPEG; 20894 - Bool useRemoteCursor; 20895 - Bool useX11Cursor; 20896 - Bool autoPass; 20897 + Bool noipv4; 20898 + Bool noipv6; 20899 20900 } AppData; 20901 20902 extern AppData appData; 20903 +extern AppData appDataNew; 20904 20905 extern char *fallback_resources[]; 20906 extern char vncServerHost[]; 20907 extern int vncServerPort; 20908 extern Bool listenSpecified; 20909 +extern pid_t listenParent; 20910 extern int listenPort, flashPort; 20911 20912 extern XrmOptionDescRec cmdLineOptions[]; 20913 @@ -130,10 +210,11 @@ 20914 /* colour.c */ 20915 20916 extern unsigned long BGR233ToPixel[]; 20917 +extern unsigned long BGR565ToPixel[]; 20918 20919 extern Colormap cmap; 20920 extern Visual *vis; 20921 -extern unsigned int visdepth, visbpp; 20922 +extern unsigned int visdepth, visbpp, isLSB; 20923 20924 extern void SetVisualAndCmap(); 20925 20926 @@ -155,15 +236,60 @@ 20927 extern GC srcGC, dstGC; 20928 extern Dimension dpyWidth, dpyHeight; 20929 20930 +extern int appshare_0_hint; 20931 +extern int appshare_x_hint; 20932 +extern int appshare_y_hint; 20933 + 20934 extern void DesktopInitBeforeRealization(); 20935 extern void DesktopInitAfterRealization(); 20936 +extern void Xcursors(int set); 20937 extern void SendRFBEvent(Widget w, XEvent *event, String *params, 20938 Cardinal *num_params); 20939 extern void CopyDataToScreen(char *buf, int x, int y, int width, int height); 20940 +extern void FillScreen(int x, int y, int width, int height, unsigned long fill); 20941 extern void SynchroniseScreen(); 20942 20943 +extern void ReDoDesktop(); 20944 +extern void DesktopCursorOff(); 20945 +extern void put_image(int x1, int y1, int x2, int y2, int width, int height, int solid); 20946 +extern void copy_rect(int x, int y, int width, int height, int src_x, int src_y); 20947 + 20948 +extern void releaseAllPressedModifiers(void); 20949 +extern void fs_grab(int check); 20950 +extern void fs_ungrab(int check); 20951 + 20952 /* dialogs.c */ 20953 20954 +extern int use_tty(void); 20955 + 20956 +extern void ScaleDialogDone(Widget w, XEvent *event, String *params, 20957 + Cardinal *num_params); 20958 +extern char *DoScaleDialog(); 20959 + 20960 +extern void EscapeDialogDone(Widget w, XEvent *event, String *params, 20961 + Cardinal *num_params); 20962 +extern char *DoEscapeKeysDialog(); 20963 + 20964 +extern void YCropDialogDone(Widget w, XEvent *event, String *params, 20965 + Cardinal *num_params); 20966 +extern char *DoYCropDialog(); 20967 + 20968 +extern void ScbarDialogDone(Widget w, XEvent *event, String *params, 20969 + Cardinal *num_params); 20970 +extern char *DoScbarDialog(); 20971 + 20972 +extern void ScaleNDialogDone(Widget w, XEvent *event, String *params, 20973 + Cardinal *num_params); 20974 +extern char *DoScaleNDialog(); 20975 + 20976 +extern void QualityDialogDone(Widget w, XEvent *event, String *params, 20977 + Cardinal *num_params); 20978 +extern char *DoQualityDialog(); 20979 + 20980 +extern void CompressDialogDone(Widget w, XEvent *event, String *params, 20981 + Cardinal *num_params); 20982 +extern char *DoCompressDialog(); 20983 + 20984 extern void ServerDialogDone(Widget w, XEvent *event, String *params, 20985 Cardinal *num_params); 20986 extern char *DoServerDialog(); 20987 @@ -171,6 +297,10 @@ 20988 Cardinal *num_params); 20989 extern char *DoPasswordDialog(); 20990 20991 +extern void UserDialogDone(Widget w, XEvent *event, String *params, 20992 + Cardinal *num_params); 20993 +extern char *DoUserDialog(); 20994 + 20995 /* fullscreen.c */ 20996 20997 extern void ToggleFullScreen(Widget w, XEvent *event, String *params, 20998 @@ -181,6 +311,13 @@ 20999 extern void FullScreenOn(); 21000 extern void FullScreenOff(); 21001 21002 +extern int net_wm_supported(void); 21003 + 21004 +extern void JumpLeft(Widget w, XEvent *event, String *params, Cardinal *num_params); 21005 +extern void JumpRight(Widget w, XEvent *event, String *params, Cardinal *num_params); 21006 +extern void JumpUp(Widget w, XEvent *event, String *params, Cardinal *num_params); 21007 +extern void JumpDown(Widget w, XEvent *event, String *params, Cardinal *num_params); 21008 + 21009 /* listen.c */ 21010 21011 extern void listenForIncomingConnections(); 21012 @@ -196,6 +333,8 @@ 21013 Cardinal *num_params); 21014 extern void Quit(Widget w, XEvent *event, String *params, 21015 Cardinal *num_params); 21016 +extern void HideChat(Widget w, XEvent *event, String *params, 21017 + Cardinal *num_params); 21018 extern void Cleanup(); 21019 21020 /* popup.c */ 21021 @@ -207,6 +346,29 @@ 21022 Cardinal *num_params); 21023 extern void CreatePopup(); 21024 21025 +extern void HideScaleN(Widget w, XEvent *event, String *params, 21026 + Cardinal *num_params); 21027 +extern void CreateScaleN(); 21028 + 21029 +extern void HideTurboVNC(Widget w, XEvent *event, String *params, 21030 + Cardinal *num_params); 21031 +extern void CreateTurboVNC(); 21032 +extern void UpdateSubsampButtons(); 21033 +extern void UpdateQualSlider(); 21034 +extern void UpdateQual(); 21035 + 21036 +extern void HideQuality(Widget w, XEvent *event, String *params, 21037 + Cardinal *num_params); 21038 +extern void CreateQuality(); 21039 + 21040 +extern void HideCompress(Widget w, XEvent *event, String *params, 21041 + Cardinal *num_params); 21042 +extern void CreateCompress(); 21043 + 21044 +extern void Noop(Widget w, XEvent *event, String *params, 21045 + Cardinal *num_params); 21046 + 21047 +extern int CreateMsg(char *msg, int wait); 21048 /* rfbproto.c */ 21049 21050 extern int rfbsock; 21051 @@ -229,8 +391,19 @@ 21052 extern Bool SendClientCutText(char *str, int len); 21053 extern Bool HandleRFBServerMessage(); 21054 21055 +extern Bool SendServerInput(Bool enabled); 21056 +extern Bool SendSingleWindow(int x, int y); 21057 +extern Bool SendServerScale(int n); 21058 + 21059 +extern Bool SendTextChat(char *str); 21060 +extern Bool SendTextChatOpen(void); 21061 +extern Bool SendTextChatClose(void); 21062 +extern Bool SendTextChatFinish(void); 21063 + 21064 extern void PrintPixelFormat(rfbPixelFormat *format); 21065 21066 +extern double dnow(void); 21067 + 21068 /* selection.c */ 21069 21070 extern void InitialiseSelection(); 21071 @@ -241,8 +414,10 @@ 21072 21073 /* shm.c */ 21074 21075 -extern XImage *CreateShmImage(); 21076 +extern XImage *CreateShmImage(int do_ycrop); 21077 extern void ShmCleanup(); 21078 +extern void ShmDetach(); 21079 +extern Bool UsingShm(); 21080 21081 /* sockets.c */ 21082 21083 @@ -252,11 +427,19 @@ 21084 extern Bool WriteExact(int sock, char *buf, int n); 21085 extern int FindFreeTcpPort(void); 21086 extern int ListenAtTcpPort(int port); 21087 -extern int ConnectToTcpAddr(unsigned int host, int port); 21088 +extern int ListenAtTcpPort6(int port); 21089 +extern int dotted_ip(char *host, int partial); 21090 +extern int ConnectToTcpAddr(const char *hostname, int port); 21091 +extern int ConnectToUnixSocket(char *file); 21092 extern int AcceptTcpConnection(int listenSock); 21093 +extern int AcceptTcpConnection6(int listenSock); 21094 extern Bool SetNonBlocking(int sock); 21095 +extern Bool SetNoDelay(int sock); 21096 +extern Bool SocketPair(int fd[2]); 21097 21098 extern int StringToIPAddr(const char *str, unsigned int *addr); 21099 +extern char *get_peer_ip(int sock); 21100 +extern char *ip2host(char *ip); 21101 extern Bool SameMachine(int sock); 21102 21103 /* tunnel.c */ 21104 @@ -271,3 +454,82 @@ 21105 extern XtAppContext appContext; 21106 extern Display* dpy; 21107 extern Widget toplevel; 21108 + 21109 +extern void GotChatText(char *str, int len); 21110 +extern void unixpw(char *instr, int vencrypt_plain); 21111 + 21112 +extern void Toggle8bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21113 +extern void Toggle16bpp(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21114 +extern void ToggleFullColor(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21115 +extern void Toggle256Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21116 +extern void Toggle64Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21117 +extern void Toggle8Colors(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21118 +extern void ToggleGreyScale(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21119 +extern void ToggleTightZRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21120 +extern void ToggleTightHextile(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21121 +extern void ToggleZRLEZYWRLE(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21122 +extern void ToggleViewOnly(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21123 +extern void ToggleJPEG(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21124 +extern void ToggleCursorShape(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21125 +extern void ToggleCursorAlpha(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21126 +extern void ToggleX11Cursor(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21127 +extern void ToggleBell(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21128 +extern void ToggleRawLocal(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21129 +extern void ToggleServerInput(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21130 +extern void TogglePipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21131 +extern void ToggleSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21132 +extern void ToggleSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21133 +extern void ToggleSingleWindow(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21134 +extern void ToggleXGrab(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21135 +extern void ToggleEscapeActive(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21136 +extern void SetEscapeKeys(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21137 +extern void DoServerScale(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21138 +extern void DoServerQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21139 +extern void DoServerCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21140 +extern void SetScale(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21141 +extern void SetYCrop(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21142 +extern void SetScbar(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21143 +extern void ShowScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21144 +extern void ShowTurboVNC(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21145 +extern void ShowQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21146 +extern void ShowCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21147 +extern void SetScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21148 +extern void SetTurboVNC(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21149 +extern void SetQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21150 +extern void SetCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21151 +extern void ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21152 +extern void ToggleFileXfer(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21153 +extern void ToggleTermTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21154 + 21155 +extern void scale_check_zrle(void); 21156 + 21157 +extern void SetViewOnlyState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21158 +extern void SetNOJPEGState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21159 +extern void SetScaleNState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21160 +extern void SetQualityState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21161 +extern void SetCompressState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21162 +extern void Set8bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21163 +extern void Set16bppState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21164 +extern void SetFullColorState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21165 +extern void Set256ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21166 +extern void Set64ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21167 +extern void Set8ColorsState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21168 +extern void SetGreyScaleState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21169 +extern void SetZRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21170 +extern void SetHextileState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21171 +extern void SetZYWRLEState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21172 +extern void SetCursorShapeState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21173 +extern void SetCursorAlphaState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21174 +extern void SetX11CursorState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21175 +extern void SetBellState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21176 +extern void SetRawLocalState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21177 +extern void SetServerInputState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21178 +extern void SetPipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21179 +extern void SetSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21180 +extern void SetSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21181 +extern void SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21182 +extern void SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21183 +extern void SetTermTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21184 +extern void SetFileXferState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21185 +extern void SetXGrabState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21186 +extern void SetEscapeKeysState(Widget w, XEvent *ev, String *params, Cardinal *num_params); 21187 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vncviewer/vncviewer.man 21188 --- vnc_unixsrc.orig/vncviewer/vncviewer.man 2004-03-11 13:14:40.000000000 -0500 21189 +++ vnc_unixsrc/vncviewer/vncviewer.man 2010-04-11 23:30:24.000000000 -0400 21190 @@ -5,38 +5,55 @@ 21191 .\" Copyright (C) 1998 Marcus.Brinkmann (a] ruhr-uni-bochum.de 21192 .\" Copyright (C) 2000,2001 Red Hat, Inc. 21193 .\" Copyright (C) 2001-2003 Constantin Kaplinsky <const (a] ce.cctpu.edu.ru> 21194 +.\" Copyright (C) 2006-2010 Karl J. Runge <runge (a] karlrunge.com> 21195 .\" 21196 .\" You may distribute under the terms of the GNU General Public 21197 .\" License as specified in the file LICENCE.TXT that comes with the 21198 .\" TightVNC distribution. 21199 .\" 21200 -.TH vncviewer 1 "January 2003" "" "TightVNC" 21201 +.TH ssvncviewer 1 "April 2010" "" "SSVNC" 21202 .SH NAME 21203 -vncviewer \- an X viewer client for VNC 21204 +ssvncviewer \- an X viewer client for VNC 21205 .SH SYNOPSIS 21206 -.B vncviewer 21207 +.B ssvncviewer 21208 .RI [\| options \|] 21209 .RI [\| host \|][\| :display \|] 21210 .br 21211 -.B vncviewer 21212 +.B ssvncviewer 21213 .RI [\| options \|] 21214 .RI [\| host \|][\| ::port \|] 21215 .br 21216 -.B vncviewer 21217 +.B ssvncviewer 21218 +.RI [\| options \|] 21219 +.RI exec=[\| cmd+args... \|] 21220 +.br 21221 +.B ssvncviewer 21222 +.RI [\| options \|] 21223 +.RI fd=n 21224 +.br 21225 +.B ssvncviewer 21226 +.RI [\| options \|] 21227 +.RI /path/to/unix/socket 21228 +.br 21229 +.B ssvncviewer 21230 .RI [\| options \|] 21231 .IR \-listen 21232 .RI [\| display \|] 21233 .br 21234 -.B vncviewer 21235 +.B ssvncviewer 21236 .IR \-help 21237 .br 21238 .SH DESCRIPTION 21239 -.B vncviewer 21240 +.B ssvncviewer 21241 is an Xt\-based client application for the VNC (Virtual Network 21242 Computing) system. It can connect to any VNC\-compatible server such 21243 -as \fBXvnc\fR or WinVNC, allowing you to control desktop environment 21244 +as \fBXvnc\fR, WinVNC, or \fBx11vnc\fR, allowing you to control desktop environment 21245 of a different machine. 21246 21247 +ssvncviewer is an enhanced version of the tightvnc unix viewer that can 21248 +take advantage of features in the \fBx11vnc\fR and UltraVNC VNC servers. 21249 +See below for the description of these features. 21250 + 21251 You can use F8 to display a pop\-up utility menu. Press F8 twice to 21252 pass single F8 to the remote side. 21253 .SH OPTIONS 21254 @@ -102,13 +119,13 @@ 21255 TightVNC supports several different compression methods to encode 21256 screen updates; this option specifies a set of them to use in order of 21257 preference. Encodings are specified separated with spaces, and must 21258 -thus be enclosed in quotes if more than one is specified. Available 21259 -encodings, in default order for a remote connection, are "copyrect 21260 -tight hextile zlib corre rre raw". For a local connection (to the same 21261 -machine), the default order to try is "raw copyrect tight hextile zlib 21262 -corre rre". Raw encoding is always assumed as a last option if no 21263 -other encoding can be used for some reason. For more information on 21264 -encodings, see the section ENCODINGS below. 21265 +thus be enclosed in quotes if more than one is specified. Commas may be used to avoid spaces. 21266 +Available encodings, in default order for a remote connection, are 21267 +"copyrect tight hextile zlib corre rre raw". For a local connection 21268 +(to the same machine), the default order to try is "raw copyrect tight 21269 +hextile zlib corre rre". Raw encoding is always assumed as a last option 21270 +if no other encoding can be used for some reason. For more information 21271 +on encodings, see the section ENCODINGS below. 21272 .TP 21273 \fB\-bgr233\fR 21274 Always use the BGR233 format to encode pixel data. This reduces 21275 @@ -168,6 +185,424 @@ 21276 \fB\-autopass\fR 21277 Read a plain-text password from stdin. This option affects only the 21278 standard VNC authentication. 21279 + 21280 +.SH Enhanced TightVNC Viewer (SSVNC) OPTIONS 21281 +.TP 21282 +Enhanced TightVNC Viewer (SSVNC) web page is located at: 21283 +.TP 21284 +http://www.karlrunge.com/x11vnc/ssvnc.html 21285 +.TP 21286 +Note: ZRLE and ZYWRLE encodings are now supported. 21287 +.TP 21288 +Note: F9 is shortcut to Toggle FullScreen mode. 21289 +.TP 21290 +Note: In -listen mode set the env var. SSVNC_MULTIPLE_LISTEN=1 21291 +to allow more than one incoming VNC server at a time. 21292 +This is the same as -multilisten described below. Set 21293 +SSVNC_MULTIPLE_LISTEN=MAX:n to allow no more than "n" 21294 +simultaneous reverse connections. 21295 + 21296 +If the host:port is specified as "exec=command args..." 21297 +then instead of making a TCP/IP socket connection to the 21298 +remote VNC server, "command args..." is executed and the 21299 +viewer is attached to its stdio. This enables tunnelling 21300 +established via an external command, e.g. an stunnel(8) 21301 +that does not involve a listening socket. 21302 +This mode does not work for -listen reverse connections. 21303 + 21304 +If the host:port is specified as "fd=n" then it is assumed 21305 +n is an already opened file descriptor to the socket. (i.e 21306 +the parent did fork+exec) 21307 + 21308 +If the host:port contains a '/' it is interpreted as a 21309 +unix-domain socket (AF_LOCAL insead of AF_INET) 21310 +.TP 21311 +\fB\-multilisten\fR 21312 +As in -listen (reverse connection listening) except 21313 +allow more than one incoming VNC server to be connected 21314 +at a time. The default for -listen of only one at a 21315 +time tries to play it safe by not allowing anyone on 21316 +the network to put (many) desktops on your screen over 21317 +a long window of time. Use -multilisten for no limit. 21318 +.TP 21319 +\fB\-acceptpopup\fR 21320 +In \fB\-listen\fR (reverse connection listening) mode when 21321 +a reverse VNC connection comes in show a popup asking 21322 +whether to Accept or Reject the connection. The IP 21323 +address of the connecting host is shown. Same as 21324 +setting the env. var. SSVNC_ACCEPT_POPUP=1. 21325 +.TP 21326 +\fB\-acceptpopupsc\fR 21327 +As in \fB\-acceptpopup\fR except assume UltraVNC Single 21328 +Click (SC) server. Retrieve User and ComputerName 21329 +info from UltraVNC Server and display in the Popup. 21330 +.TP 21331 +\fB\-use64\fR 21332 +In \fB\-bgr233\fR mode, use 64 colors instead of 256. 21333 +.TP 21334 +\fB\-bgr222\fR 21335 +Same as \fB\-use64\fR. 21336 +.TP 21337 +\fB\-use8\fR 21338 +In \fB\-bgr233\fR mode, use 8 colors instead of 256. 21339 +.TP 21340 +\fB\-bgr111\fR 21341 +Same as \fB\-use8\fR. 21342 +.TP 21343 +\fB\-16bpp\fR 21344 +If the vnc viewer X display is depth 24 at 32bpp 21345 +request a 16bpp format from the VNC server to cut 21346 +network traffic by up to 2X, then tranlate the 21347 +pixels to 32bpp locally. 21348 +.TP 21349 +\fB\-bgr565\fR 21350 +Same as \fB\-16bpp\fR. 21351 +.TP 21352 +\fB\-grey\fR 21353 +Use a grey scale for the 16- and 8\fB\-bpp\fR modes. 21354 +.TP 21355 +\fB\-alpha\fR 21356 +Use alphablending transparency for local cursors 21357 +requires: x11vnc server, both client and server 21358 +must be 32bpp and same endianness. 21359 +.TP 21360 +\fB\-scale\fR \fIstr\fR 21361 +Scale the desktop locally. The string "str" can 21362 +a floating point ratio, e.g. "0.9", or a fraction, 21363 +e.g. "3/4", or WxH, e.g. 1280x1024. Use "fit" 21364 +to fit in the current screen size. Use "auto" to 21365 +fit in the window size. "str" can also be set by 21366 +the env. var. SSVNC_SCALE. 21367 + 21368 +If you observe mouse trail painting errors, enable 21369 +X11 Cursor mode (either via Popup or \fB\-x11cursor\fR.) 21370 + 21371 +Note that scaling is done in software and so can be 21372 +slow and requires more memory. Some speedup Tips: 21373 + 21374 +ZRLE is faster than Tight in this mode. When 21375 +scaling is first detected, the encoding will 21376 +be automatically switched to ZRLE. Use the 21377 +Popup menu if you want to go back to Tight. 21378 +Set SSVNC_PRESERVE_ENCODING=1 to disable this. 21379 + 21380 +Use a solid background on the remote side. 21381 +(e.g. manually or via x11vnc \fB\-solid\fR ...) 21382 + 21383 +If the remote server is x11vnc, try client 21384 +side caching: x11vnc \fB\-ncache\fR 10 ... 21385 +.TP 21386 +\fB\-ycrop\fR n 21387 +Only show the top n rows of the framebuffer. For 21388 +use with x11vnc \fB\-ncache\fR client caching option 21389 +to help "hide" the pixel cache region. 21390 +Use a negative value (e.g. \fB\-1\fR) for autodetection. 21391 +Autodetection will always take place if the remote 21392 +fb height is more than 2 times the width. 21393 +.TP 21394 +\fB\-sbwidth\fR n 21395 +Scrollbar width for x11vnc \fB\-ncache\fR mode (\fB\-ycrop\fR), 21396 +default is very narrow: 2 pixels, it is narrow to 21397 +avoid distraction in \fB\-ycrop\fR mode. 21398 +.TP 21399 +\fB\-nobell\fR 21400 +Disable bell. 21401 +.TP 21402 +\fB\-rawlocal\fR 21403 +Prefer raw encoding for localhost, default is 21404 +no, i.e. assumes you have a SSH tunnel instead. 21405 +.TP 21406 +\fB\-notty\fR 21407 +Try to avoid using the terminal for interactive 21408 +responses: use windows for messages and prompting 21409 +instead. Messages will also be printed to terminal. 21410 +.TP 21411 +\fB\-sendclipboard\fR 21412 +Send the X CLIPBOARD selection (i.e. Ctrl+C, 21413 +Ctrl+V) instead of the X PRIMARY selection (mouse 21414 +select and middle button paste.) 21415 +.TP 21416 +\fB\-sendalways\fR 21417 +Whenever the mouse enters the VNC viewer main 21418 +window, send the selection to the VNC server even if 21419 +it has not changed. This is like the Xt resource 21420 +translation SelectionToVNC(always) 21421 +.TP 21422 +\fB\-recvtext\fR 21423 +str When cut text is received from the VNC server, 21424 +ssvncviewer will set both the X PRIMARY and the 21425 +X CLIPBOARD local selections. To control which 21426 +is set, specify 'str' as 'primary', 'clipboard', 21427 +or 'both' (the default.) 21428 +.TP 21429 +\fB\-graball\fR 21430 +Grab the entire X server when in fullscreen mode, 21431 +needed by some old window managers like fvwm2. 21432 +.TP 21433 +\fB\-popupfix\fR 21434 +Warp the popup back to the pointer position, 21435 +needed by some old window managers like fvwm2. 21436 +.TP 21437 +\fB\-grabkbd\fR 21438 +Grab the X keyboard when in fullscreen mode, 21439 +needed by some window managers. Same as \fB\-grabkeyboard\fR. 21440 +\fB\-grabkbd\fR is the default, use \fB\-nograbkbd\fR to disable. 21441 +.TP 21442 +\fB\-bs\fR, \fB\-nobs\fR 21443 +Whether or not to use X server Backingstore for the 21444 +main viewer window. The default is to not, mainly 21445 +because most Linux, etc, systems X servers disable 21446 +*all* Backingstore by default. To re\fB\-enable\fR it put 21447 + 21448 +Option "Backingstore" 21449 + 21450 +in the Device section of /etc/X11/xorg.conf. 21451 +In \fB\-bs\fR mode with no X server backingstore, whenever an 21452 +area of the screen is re\fB\-exposed\fR it must go out to the 21453 +VNC server to retrieve the pixels. This is too slow. 21454 + 21455 +In \fB\-nobs\fR mode, memory is allocated by the viewer to 21456 +provide its own backing of the main viewer window. This 21457 +actually makes some activities faster (changes in large 21458 +regions) but can appear to "flash" too much. 21459 +.TP 21460 +\fB\-noshm\fR 21461 +Disable use of MIT shared memory extension (not recommended) 21462 +.TP 21463 +\fB\-termchat\fR 21464 +Do the UltraVNC chat in the terminal vncviewer is in 21465 +instead of in an independent window. 21466 +.TP 21467 +\fB\-unixpw\fR \fIstr\fR 21468 +Useful for logging into x11vnc in \fB\-unixpw\fR mode. "str" is a 21469 +string that allows many ways to enter the Unix Username 21470 +and Unix Password. These characters: username, newline, 21471 +password, newline are sent to the VNC server after any VNC 21472 +authentication has taken place. Under x11vnc they are 21473 +used for the \fB\-unixpw\fR login. Other VNC servers could do 21474 +something similar. 21475 + 21476 +You can also indicate "str" via the environment 21477 +variable SSVNC_UNIXPW. 21478 + 21479 +Note that the Escape key is actually sent first to tell 21480 +x11vnc to not echo the Unix Username back to the VNC 21481 +viewer. Set SSVNC_UNIXPW_NOESC=1 to override this. 21482 + 21483 +If str is ".", then you are prompted at the command line 21484 +for the username and password in the normal way. If str is 21485 +"-" the stdin is read via getpass(3) for username@password. 21486 +Otherwise if str is a file, it is opened and the first line 21487 +read is taken as the Unix username and the 2nd as the 21488 +password. If str prefixed by "rm:" the file is removed 21489 +after reading. Otherwise, if str has a "@" character, 21490 +it is taken as username@password. Otherwise, the program 21491 +exits with an error. Got all that? 21492 +.TP 21493 +\fB-repeater\fR \fIstr\fR 21494 +This is for use with UltraVNC repeater proxy described 21495 +here: http://www.uvnc.com/addons/repeater.html. The "str" 21496 +is the ID string to be sent to the repeater. E.g. ID:1234 21497 +It can also be the hostname and port or display of the VNC 21498 +server, e.g. 12.34.56.78:0 or snoopy.com:1. Note that when 21499 +using -repeater, the host:dpy on the cmdline is the repeater 21500 +server, NOT the VNC server. The repeater will connect you. 21501 + 21502 +Example: vncviewer ... -repeater ID:3333 repeat.host:5900 21503 + 21504 +Example: vncviewer ... -repeater vhost:0 repeat.host:5900 21505 + 21506 +Use, e.g., '-repeater SCIII=ID:3210' if the repeater is a 21507 +Single Click III (SSL) repeater (repeater_SSL.exe) and you 21508 +are passing the SSL part of the connection through stunnel, socat, etc. 21509 +This way the magic UltraVNC string 'testB' needed to work with the 21510 +repeater is sent to it. 21511 +.TP 21512 +\fB-rfbversion\fR \fIstr\fR 21513 +Set the advertised RFB version. E.g.: -rfbversion 3.6 For some 21514 +servers, e.g. UltraVNC this needs to be done. 21515 +.TP 21516 +\fB-ultradsm\fR 21517 +UltraVNC has symmetric private encryption DSM plugins. See 21518 +http://www.uvnc.com/features/encryption.html. It is assumed 21519 +you are using a unix program (e.g. our ultravnc_dsm_helper) to 21520 +encrypt and decrypt the UltraVNC DSM stream. IN ADDITION TO 21521 +THAT supply -ultradsm to tell THIS viewer to modify the RFB 21522 +data sent so as to work with the UltraVNC Server. For some 21523 +reason, each RFB msg type must be sent twice under DSM. 21524 +.TP 21525 +\fB\-mslogon\fR \fIuser\fR 21526 +Use Windows MS Logon to an UltraVNC server. Supply the 21527 +username or "1" to be prompted. The default is to 21528 +autodetect the UltraVNC MS Logon server and prompt for 21529 +the username and password. 21530 + 21531 +IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman 21532 +exchange is very weak and can be brute forced to recover 21533 +your username and password in a few seconds of CPU 21534 +time. To be safe, be sure to use an additional encrypted 21535 +tunnel (e.g. SSL or SSH) for the entire VNC session. 21536 +.TP 21537 +\fB\-chatonly\fR 21538 +Try to be a client that only does UltraVNC text chat. This 21539 +mode is used by x11vnc to present a chat window on the physical 21540 +X11 console (i.e. to chat with the person at the display). 21541 +.TP 21542 +\fB-env\fR \fIVAR=VALUE\fR 21543 +To save writing a shell script to set environment 21544 +variables, specify as many as you need on the command line. For example, 21545 +-env SSVNC_MULTIPLE_LISTEN=MAX:5 -env EDITOR=vi 21546 +.TP 21547 +\fB\-noipv6\fR 21548 +Disable all IPv6 sockets. Same as VNCVIEWER_NO_IPV6=1. 21549 +.TP 21550 +\fB\-noipv4\fR 21551 +Disable all IPv4 sockets. Same as VNCVIEWER_NO_IPV4=1. 21552 +.TP 21553 +\fB\-printres\fR 21554 +Print out the Ssvnc X resources (appdefaults) and 21555 +then exit. You can save them to a file and customize them (e.g. the 21556 +keybindings and Popup menu) Then point to the file via 21557 +XENVIRONMENT or XAPPLRESDIR. 21558 +.TP 21559 +\fB\-pipeline\fR 21560 +Like TurboVNC, request the next framebuffer update as soon 21561 +as possible instead of waiting until the end of the current 21562 +framebuffer update coming in. Helps 'pipeline' the updates. 21563 +This is currently the default, use \fB-nopipeline\fR to disable. 21564 +.TP 21565 +\fB\-appshare\fR 21566 +Enable features for use with x11vnc's \fB\-appshare\fR mode where 21567 +instead of sharing the full desktop only the application's 21568 +windows are shared. Viewer multilisten mode is used to 21569 +create the multiple windows: \fB\-multilisten\fR is implied. 21570 +See 'x11vnc \fB\-appshare\fR \fB\-help\fR' more information on the mode. 21571 +Features enabled in the viewer under \fB\-appshare\fR are: 21572 +Minimum extra text in the title, auto \fB\-ycrop\fR is disabled, 21573 +x11vnc \fB\-remote_prefix\fR X11VNC_APPSHARE_CMD: message channel, 21574 +x11vnc initial window position hints. See also Escape Keys 21575 +below for additional key and mouse bindings. 21576 +.TP 21577 +\fB\-escape \fR\fIstr\fR 21578 +This sets the 'Escape Keys' modifier sequence and enables 21579 +escape keys mode. When the modifier keys escape sequence 21580 +is held down, the next keystroke is interpreted locally 21581 +to perform a special action instead of being sent to the 21582 +remote VNC server. 21583 + 21584 +Use '\fB\-escape\fR default' for the default modifier sequence. 21585 +(Unix: Alt_L,Super_L and MacOSX: Control_L,Meta_L) 21586 + 21587 +Here are the 'Escape Keys: Help+Set' instructions from the Popup: 21588 + 21589 +Escape Keys: Enter a comma separated list of modifier keys to be the 'escape 21590 +sequence'. When these keys are held down, the next keystroke is 21591 +interpreted locally to invoke a special action instead of being sent to 21592 +the remote VNC server. In other words, a set of 'Hot Keys'. 21593 + 21594 +Here is the list of local key mappings to special actions: 21595 + 21596 +r: refresh desktop b: toggle bell c: toggle full-color 21597 + 21598 +f: file transfer x: x11cursor z: toggle Tight/ZRLE 21599 + 21600 +l: full screen g: graball e: escape keys dialog 21601 + 21602 +s: scale dialog +: scale up (=) -: scale down (_) 21603 + 21604 +t: text chat a: alphablend cursor 21605 + 21606 +V: toggle viewonly Q: quit viewer 123456: UltraVNC scale 1/n 21607 + 21608 +Arrow keys: pan the viewport about 10% for each keypress. 21609 + 21610 +PageUp/PageDown: pan the viewport by a screenful vertically. 21611 + 21612 +Home/End: pan the viewport by a screenful horizontally. 21613 + 21614 +KeyPad Arrows: pan the viewport by 1 pixel for each keypress. 21615 + 21616 +Dragging the Mouse with Button1 pressed also pans the viewport. 21617 + 21618 +Clicking Mouse Button3 brings up the Popup Menu. 21619 + 21620 +The above mappings are \fBalways\fR active in ViewOnly mode, unless you set 21621 +the Escape Keys value to 'never'. 21622 + 21623 +x11vnc -appshare hot-keys: x11vnc has a simple application sharing mode 21624 +that enables the viewer-side to move, resize, or raise the remote toplevel 21625 +windows. To enable it, hold down Shift + the Escape Keys and press these: 21626 + 21627 +Arrow keys: move the remote window around in its desktop. 21628 + 21629 +PageUp/PageDn/Home/End: resize the remote window. 21630 + 21631 ++/-: raise or lower the remote window. 21632 + 21633 +M or Button1 move win to local position; D or Button3: delete remote win. 21634 + 21635 +If the Escape Keys value below is set to 'default' then a default list of 21636 +of modifier keys is used. For Unix it is: Alt_L,Super_L and for MacOSX it 21637 +is Control_L,Meta_L. Note: the Super_L key usually has a Windows(TM) Flag 21638 +on it. Also note the _L and _R mean the key is on the LEFT or RIGHT side 21639 +of the keyboard. 21640 + 21641 +On Unix the default is Alt and Windows keys on Left side of keyboard. 21642 +On MacOSX the default is Control and Command keys on Left side of keyboard. 21643 + 21644 +Example: Press and hold the Alt and Windows keys on the LEFT side of the 21645 +keyboard and then press 'c' to toggle the full-color state. Or press 't' 21646 +to toggle the ultravnc Text Chat window, etc. 21647 + 21648 +To use something besides the default, supply a comma separated list (or a 21649 +single one) from: Shift_L Shift_R Control_L Control_R Alt_L Alt_R Meta_L 21650 +Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch. 21651 +.TP 21652 +\fB New Popup actions:\fR 21653 + 21654 + ViewOnly: ~ -viewonly 21655 + Disable Bell: ~ -nobell 21656 + Cursor Shape: ~ -nocursorshape 21657 + X11 Cursor: ~ -x11cursor 21658 + Cursor Alphablend: ~ -alpha 21659 + Toggle Tight/Hextile: ~ -encodings hextile... 21660 + Toggle Tight/ZRLE: ~ -encodings zrle... 21661 + Toggle ZRLE/ZYWRLE: ~ -encodings zywrle... 21662 + Quality Level ~ -quality (both Tight and ZYWRLE) 21663 + Compress Level ~ -compresslevel 21664 + Disable JPEG: ~ -nojpeg (Tight) 21665 + Pipeline Updates ~ -pipeline 21666 + 21667 + Full Color as many colors as local screen allows. 21668 + Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only. 21669 + 16 bit color (BGR565) ~ -16bpp / -bgr565 21670 + 8 bit color (BGR233) ~ -bgr233 21671 + 256 colors ~ -bgr233 default # of colors. 21672 + 64 colors ~ -bgr222 / -use64 21673 + 8 colors ~ -bgr111 / -use8 21674 + Scale Viewer ~ -scale 21675 + Escape Keys: Toggle ~ -escape 21676 + Escape Keys: Help+Set ~ -escape 21677 + Set Y Crop (y-max) ~ -ycrop 21678 + Set Scrollbar Width ~ -sbwidth 21679 + XGrabServer ~ -graball 21680 + 21681 + UltraVNC Extensions: 21682 + 21683 + Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. 21684 + Text Chat Ultravnc ext. Do Text Chat. 21685 + File Transfer Ultravnc ext. File xfer via Java helper. 21686 + Single Window Ultravnc ext. Grab and view a single window. 21687 + (select then click on the window you want). 21688 + Disable Remote Input Ultravnc ext. Try to prevent input and 21689 + viewing of monitor at physical display. 21690 + 21691 + Note: the Ultravnc extensions only apply to servers that support 21692 + them. x11vnc/libvncserver supports some of them. 21693 + 21694 + Send Clipboard not Primary ~ -sendclipboard 21695 + Send Selection Every time ~ -sendalways 21696 + 21697 .SH ENCODINGS 21698 The server supplies information in whatever format is desired by the 21699 client, in order to make the client as easy as possible to implement. 21700 @@ -238,6 +673,15 @@ 21701 \-quality and \-nojpeg options above). Tight encoding is usually the 21702 best choice for low\-bandwidth network environments (e.g. slow modem 21703 connections). 21704 +.TP 21705 +.B ZRLE 21706 +The SSVNC viewer has ported the RealVNC (www.realvnc.com) ZRLE encoding 21707 +to the unix tightvnc viewer. 21708 +.TP 21709 +.B ZYWRLE 21710 +The SSVNC viewer has ported the Hitachi lossy wavelet based ZRLE 21711 +encoding from http://mobile.hitachi-system.co.jp/publications/ZYWRLE/ 21712 +to the unix tightvnc viewer. 21713 .SH RESOURCES 21714 X resources that \fBvncviewer\fR knows about, aside from the 21715 normal Xt resources, are as follows: 21716 @@ -364,12 +808,13 @@ 21717 .B %R 21718 remote TCP port number. 21719 .SH SEE ALSO 21720 -\fBvncserver\fR(1), \fBXvnc\fR(1), \fBvncpasswd\fR(1), 21721 -\fBvncconnect\fR(1), \fBssh\fR(1) 21722 +\fBvncserver\fR(1), \fBx11vnc\fR(1), \fBssvnc\fR(1), \fBXvnc\fR(1), \fBvncpasswd\fR(1), 21723 +\fBvncconnect\fR(1), \fBssh\fR(1), http://www.karlrunge.com/x11vnc, http://www.karlrunge.com/x11vnc/ssvnc.html 21724 .SH AUTHORS 21725 Original VNC was developed in AT&T Laboratories Cambridge. TightVNC 21726 additions was implemented by Constantin Kaplinsky. Many other people 21727 -participated in development, testing and support. 21728 +participated in development, testing and support. Karl J. Runge 21729 +added all of the SSVNC related features and improvements. 21730 21731 \fBMan page authors:\fR 21732 .br 21733 @@ -380,3 +825,5 @@ 21734 Tim Waugh <twaugh (a] redhat.com>, 21735 .br 21736 Constantin Kaplinsky <const (a] ce.cctpu.edu.ru> 21737 +.br 21738 +Karl J. Runge <runge (a] karlrunge.com> 21739 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrle.c vnc_unixsrc/vncviewer/zrle.c 21740 --- vnc_unixsrc.orig/vncviewer/zrle.c 2007-02-04 18:59:50.000000000 -0500 21741 +++ vnc_unixsrc/vncviewer/zrle.c 2010-02-25 23:24:28.000000000 -0500 21742 @@ -0,0 +1,620 @@ 21743 +/* 21744 + * Copyright (C) 2005 Johannes E. Schindelin. All Rights Reserved. 21745 + * 21746 + * This is free software; you can redistribute it and/or modify 21747 + * it under the terms of the GNU General Public License as published by 21748 + * the Free Software Foundation; either version 2 of the License, or 21749 + * (at your option) any later version. 21750 + * 21751 + * This software is distributed in the hope that it will be useful, 21752 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21753 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21754 + * GNU General Public License for more details. 21755 + * 21756 + * You should have received a copy of the GNU General Public License 21757 + * along with this software; if not, write to the Free Software 21758 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 21759 + * USA. 21760 + */ 21761 + 21762 +/* 21763 + * zrle.c - handle zrle encoding. 21764 + * 21765 + * This file shouldn't be compiled directly. It is included multiple times by 21766 + * rfbproto.c, each time with a different definition of the macro BPP. For 21767 + * each value of BPP, this file defines a function which handles an zrle 21768 + * encoded rectangle with BPP bits per pixel. 21769 + */ 21770 + 21771 +#ifndef REALBPP 21772 +#define REALBPP BPP 21773 +#endif 21774 + 21775 +#if !defined(UNCOMP) || UNCOMP==0 21776 +#define HandleZRLE CONCAT2E(HandleZRLE,REALBPP) 21777 +#define HandleZRLETile CONCAT2E(HandleZRLETile,REALBPP) 21778 +#elif UNCOMP>0 21779 +#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Down) 21780 +#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Down) 21781 +#else 21782 +#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Up) 21783 +#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Up) 21784 +#endif 21785 +#undef CARDBPP 21786 +#undef CARDREALBPP 21787 +#define CARDBPP CONCAT2E(CARD, BPP) 21788 +#define CARDREALBPP CONCAT2E(CARD,REALBPP) 21789 + 21790 +#define FillRectangle(x, y, w, h, color) \ 21791 + { \ 21792 + XGCValues _gcv; \ 21793 + _gcv.foreground = color; \ 21794 + if (!appData.useXserverBackingStore) { \ 21795 + FillScreen(x, y, w, h, _gcv.foreground); \ 21796 + } else { \ 21797 + XChangeGC(dpy, gc, GCForeground, &_gcv); \ 21798 + XFillRectangle(dpy, desktopWin, gc, x, y, w, h); \ 21799 + } \ 21800 + } 21801 + 21802 +#if defined(__sparc) || defined(__sparc__) || defined(__ppc__) || defined(__POWERPC__) || defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) 21803 +#define IS_BIG_ENDIAN 1 21804 +#else 21805 +#define IS_BIG_ENDIAN 0 21806 +#endif 21807 + 21808 +#if DO_ZYWRLE 21809 + 21810 +#define ENDIAN_LITTLE 0 21811 +#define ENDIAN_BIG 1 21812 +#define ENDIAN_NO 2 21813 +#if IS_BIG_ENDIAN 21814 +#define ZYWRLE_ENDIAN ENDIAN_BIG 21815 +#else 21816 +#define ZYWRLE_ENDIAN ENDIAN_LITTLE 21817 +#endif 21818 +#undef END_FIX 21819 +#if ZYWRLE_ENDIAN == ENDIAN_LITTLE 21820 +# define END_FIX LE 21821 +#elif ZYWRLE_ENDIAN == ENDIAN_BIG 21822 +# define END_FIX BE 21823 +#else 21824 +# define END_FIX NE 21825 +#endif 21826 +#define __RFB_CONCAT3E(a,b,c) CONCAT3E(a,b,c) 21827 +#define __RFB_CONCAT2E(a,b) CONCAT2E(a,b) 21828 +#undef CPIXEL 21829 +#if REALBPP != BPP 21830 +#if UNCOMP == 0 21831 +#define CPIXEL REALBPP 21832 +#elif UNCOMP>0 21833 +#define CPIXEL CONCAT2E(REALBPP,Down) 21834 +#else 21835 +#define CPIXEL CONCAT2E(REALBPP,Up) 21836 +#endif 21837 +#endif 21838 +#define PIXEL_T CARDBPP 21839 +#if BPP!=8 21840 +#define ZYWRLE_DECODE 1 21841 +#include "zywrletemplate.c" 21842 +#endif 21843 +#undef CPIXEL 21844 + 21845 +#endif /* DO_ZYWRLE */ 21846 + 21847 +static int HandleZRLETile( 21848 + unsigned char* buffer,size_t buffer_length, 21849 + int x,int y,int w,int h); 21850 + 21851 +static Bool 21852 +HandleZRLE (int rx, int ry, int rw, int rh) 21853 +{ 21854 + rfbZRLEHeader header; 21855 + int remaining; 21856 + int inflateResult; 21857 + int toRead; 21858 + int min_buffer_size = rw * rh * (REALBPP / 8) * 2; 21859 + 21860 + /* First make sure we have a large enough raw buffer to hold the 21861 + * decompressed data. In practice, with a fixed REALBPP, fixed frame 21862 + * buffer size and the first update containing the entire frame 21863 + * buffer, this buffer allocation should only happen once, on the 21864 + * first update. 21865 + */ 21866 + if ( raw_buffer_size < min_buffer_size) { 21867 + 21868 + if ( raw_buffer != NULL ) { 21869 + 21870 + free( raw_buffer ); 21871 + 21872 + } 21873 + 21874 + raw_buffer_size = min_buffer_size; 21875 + raw_buffer = (char*) malloc( raw_buffer_size ); 21876 + 21877 + } 21878 + 21879 + if (!ReadFromRFBServer((char *)&header, sz_rfbZRLEHeader)) 21880 + return False; 21881 + 21882 + remaining = Swap32IfLE(header.length); 21883 + 21884 + /* Need to initialize the decompressor state. */ 21885 + decompStream.next_in = ( Bytef * )buffer; 21886 + decompStream.avail_in = 0; 21887 + decompStream.next_out = ( Bytef * )raw_buffer; 21888 + decompStream.avail_out = raw_buffer_size; 21889 + decompStream.data_type = Z_BINARY; 21890 + 21891 + /* Initialize the decompression stream structures on the first invocation. */ 21892 + if ( decompStreamInited == False ) { 21893 + 21894 + inflateResult = inflateInit( &decompStream ); 21895 + 21896 + if ( inflateResult != Z_OK ) { 21897 + fprintf(stderr, 21898 + "inflateInit returned error: %d, msg: %s\n", 21899 + inflateResult, 21900 + decompStream.msg); 21901 + return False; 21902 + } 21903 + 21904 + decompStreamInited = True; 21905 + 21906 + } 21907 + 21908 + inflateResult = Z_OK; 21909 + 21910 + /* Process buffer full of data until no more to process, or 21911 + * some type of inflater error, or Z_STREAM_END. 21912 + */ 21913 + while (( remaining > 0 ) && 21914 + ( inflateResult == Z_OK )) { 21915 + 21916 + if ( remaining > BUFFER_SIZE ) { 21917 + toRead = BUFFER_SIZE; 21918 + } 21919 + else { 21920 + toRead = remaining; 21921 + } 21922 + 21923 + /* Fill the buffer, obtaining data from the server. */ 21924 + if (!ReadFromRFBServer(buffer,toRead)) 21925 + return False; 21926 + 21927 + decompStream.next_in = ( Bytef * )buffer; 21928 + decompStream.avail_in = toRead; 21929 + 21930 + /* Need to uncompress buffer full. */ 21931 + inflateResult = inflate( &decompStream, Z_SYNC_FLUSH ); 21932 + 21933 + /* We never supply a dictionary for compression. */ 21934 + if ( inflateResult == Z_NEED_DICT ) { 21935 + fprintf(stderr, "zlib inflate needs a dictionary!\n"); 21936 + return False; 21937 + } 21938 + if ( inflateResult < 0 ) { 21939 + fprintf(stderr, 21940 + "zlib inflate returned error: %d, msg: %s\n", 21941 + inflateResult, 21942 + decompStream.msg); 21943 + return False; 21944 + } 21945 + 21946 + /* Result buffer allocated to be at least large enough. We should 21947 + * never run out of space! 21948 + */ 21949 + if (( decompStream.avail_in > 0 ) && 21950 + ( decompStream.avail_out <= 0 )) { 21951 + fprintf(stderr, "zlib inflate ran out of space!\n"); 21952 + return False; 21953 + } 21954 + 21955 + remaining -= toRead; 21956 + 21957 + } /* while ( remaining > 0 ) */ 21958 + 21959 + if ( inflateResult == Z_OK ) { 21960 + void* buf=raw_buffer; 21961 + int i,j; 21962 + 21963 + remaining = raw_buffer_size-decompStream.avail_out; 21964 + 21965 + for(j=0; j<rh; j+=rfbZRLETileHeight) 21966 + for(i=0; i<rw; i+=rfbZRLETileWidth) { 21967 + int subWidth=(i+rfbZRLETileWidth>rw)?rw-i:rfbZRLETileWidth; 21968 + int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight; 21969 + int result=HandleZRLETile(buf,remaining,rx+i,ry+j,subWidth,subHeight); 21970 + 21971 + if(result<0) { 21972 + fprintf(stderr, "ZRLE decoding failed (%d)\n",result); 21973 +return True; 21974 + return False; 21975 + } 21976 + 21977 + buf+=result; 21978 + remaining-=result; 21979 + } 21980 + } 21981 + else { 21982 + 21983 + fprintf(stderr, 21984 + "zlib inflate returned error: %d, msg: %s\n", 21985 + inflateResult, 21986 + decompStream.msg); 21987 + return False; 21988 + 21989 + } 21990 + 21991 + return True; 21992 +} 21993 + 21994 +#if REALBPP!=BPP && defined(UNCOMP) && UNCOMP!=0 21995 +# if BPP == 32 && IS_BIG_ENDIAN 21996 +# define UncompressCPixel(p) ( (*p << myFormat.redShift) | (*(p+1) << myFormat.greenShift) | (*(p+2) << myFormat.blueShift) ) 21997 +# else 21998 +# if UNCOMP>0 21999 +# define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)>>UNCOMP) 22000 +# else 22001 +# define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)<<(-(UNCOMP))) 22002 +# endif 22003 +# endif 22004 +#else 22005 +# define UncompressCPixel(pointer) (*(CARDBPP*)pointer) 22006 +#endif 22007 + 22008 +extern XImage *image; 22009 +extern XImage *image_scale; 22010 +extern int skip_maybe_sync; 22011 + 22012 +static int HandleZRLETile( 22013 + unsigned char* buffer,size_t buffer_length, 22014 + int x,int y,int w,int h) { 22015 + unsigned char* buffer_copy = buffer; 22016 + unsigned char* buffer_end = buffer+buffer_length; 22017 + unsigned char type; 22018 + 22019 + if(buffer_length<1) 22020 + return -2; 22021 + 22022 + if (frameBufferLen < w * h * BPP/8) { 22023 + if(frameBuffer) { 22024 + free(frameBuffer); 22025 + } 22026 + frameBufferLen = w * h * BPP/8 * 2; 22027 + frameBuffer = (unsigned char *) malloc(frameBufferLen); 22028 + } 22029 + 22030 +zywrle_top: 22031 + type = *buffer; 22032 + buffer++; 22033 + switch(type) { 22034 + case 0: /* raw */ 22035 + { 22036 +#if DO_ZYWRLE && BPP != 8 22037 + if (zywrle_level > 0 && !(zywrle_level & 0x80) ) { 22038 + zywrle_level |= 0x80; 22039 + goto zywrle_top; 22040 + } else 22041 +#endif 22042 + { 22043 +#if REALBPP!=BPP 22044 + int m0 = 0, i,j; 22045 + 22046 + 22047 + if(1+w*h*REALBPP/8>buffer_length) { 22048 + fprintf(stderr, "expected %d bytes, got only %d (%dx%d)\n",1+w*h*REALBPP/8,buffer_length,w,h); 22049 + return -3; 22050 + } 22051 + 22052 + for(j=y*si.framebufferWidth; j<(y+h)*si.framebufferWidth; j+=si.framebufferWidth) { 22053 + for(i=x; i<x+w; i++,buffer+=REALBPP/8) { 22054 +# if 0 22055 + ((CARDBPP*)frameBuffer)[j+i] = UncompressCPixel(buffer); 22056 + /* alt */ 22057 + CARDBPP color = UncompressCPixel(buffer); 22058 + CopyDataToScreen((char *)&color, i, j/si.framebufferWidth, 1, 1); 22059 +# else 22060 + ((CARDBPP*)frameBuffer)[m0++] = UncompressCPixel(buffer); 22061 +# endif 22062 + } 22063 + } 22064 + CopyDataToScreen((char *)frameBuffer, x, y, w, h); 22065 +if (0) fprintf(stderr, "cha1: %dx%d+%d+%d\n", w, h, x, y); 22066 + 22067 +#else 22068 +# if 0 22069 + CopyRectangle(buffer, x, y, w, h); 22070 +# else 22071 + CopyDataToScreen((char *)buffer, x, y, w, h); 22072 +# endif 22073 + buffer+=w*h*REALBPP/8; 22074 +#endif 22075 + } 22076 + break; 22077 + } 22078 + case 1: /* solid */ 22079 + { 22080 + CARDBPP color = UncompressCPixel(buffer); 22081 + 22082 + if(1+REALBPP/8>buffer_length) 22083 + return -4; 22084 + 22085 + if ((BPP == 8 && appData.useBGR233) || (BPP == 16 && appData.useBGR565)) { 22086 + int m0; 22087 + for (m0=0; m0 < w*h; m0++) { 22088 + ((CARDBPP*)frameBuffer)[m0] = color; 22089 + } 22090 + CopyDataToScreen((char *)frameBuffer, x, y, w, h); 22091 + } else { 22092 + FillRectangle(x, y, w, h, color); 22093 + } 22094 +if (0) fprintf(stderr, "cha2: %dx%d+%d+%d\n", w, h, x, y); 22095 + 22096 + buffer+=REALBPP/8; 22097 + 22098 + break; 22099 + } 22100 + case 2 ... 127: /* packed Palette */ 22101 + { 22102 + CARDBPP palette[16]; 22103 + int m0, i,j,shift, 22104 + bpp=(type>4?(type>16?8:4):(type>2?2:1)), 22105 + mask=(1<<bpp)-1, 22106 + divider=(8/bpp); 22107 + 22108 + if(1+type*REALBPP/8+((w+divider-1)/divider)*h>buffer_length) 22109 + return -5; 22110 + 22111 + /* read palette */ 22112 + for(i=0; i<type; i++,buffer+=REALBPP/8) 22113 + palette[i] = UncompressCPixel(buffer); 22114 + 22115 + m0 = 0; 22116 + /* read palettized pixels */ 22117 + for(j=y*si.framebufferWidth; j<(y+h)*si.framebufferWidth; j+=si.framebufferWidth) { 22118 + for(i=x,shift=8-bpp; i<x+w; i++) { 22119 +# if 0 22120 + ((CARDBPP*)frameBuffer)[j+i] = palette[((*buffer)>>shift)&mask]; 22121 + /* alt */ 22122 + CARDBPP color = palette[((*buffer)>>shift)&mask]; 22123 + CopyDataToScreen((char *)&color, i, j/si.framebufferWidth, 1, 1); 22124 +# else 22125 + ((CARDBPP*)frameBuffer)[m0++] = palette[((*buffer)>>shift)&mask]; 22126 +# endif 22127 + shift-=bpp; 22128 + if(shift<0) { 22129 + shift=8-bpp; 22130 + buffer++; 22131 + } 22132 + } 22133 + if(shift<8-bpp) 22134 + buffer++; 22135 + } 22136 + CopyDataToScreen((char *)frameBuffer, x, y, w, h); 22137 +if (0) fprintf(stderr, "cha3: %dx%d+%d+%d\n", w, h, x, y); 22138 + 22139 + break; 22140 + } 22141 + /* case 17 ... 127: not used, but valid */ 22142 + case 128: /* plain RLE */ 22143 + { 22144 + int m0=0, i=0,j=0; 22145 + while(j<h) { 22146 + int color,length; 22147 + /* read color */ 22148 + if(buffer+REALBPP/8+1>buffer_end) 22149 + return -7; 22150 + color = UncompressCPixel(buffer); 22151 + buffer+=REALBPP/8; 22152 + /* read run length */ 22153 + length=1; 22154 + while(*buffer==0xff) { 22155 + if(buffer+1>=buffer_end) 22156 + return -8; 22157 + length+=*buffer; 22158 + buffer++; 22159 + } 22160 + length+=*buffer; 22161 + buffer++; 22162 + while(j<h && length>0) { 22163 +# if 0 22164 + ((CARDBPP*)frameBuffer)[(y+j)*si.framebufferWidth+x+i] = color; 22165 + /* alt */ 22166 + CopyDataToScreen((char *)&color, x+i, y+j, 1, 1); 22167 +# else 22168 + ((CARDBPP*)frameBuffer)[m0++] = color; 22169 +# endif 22170 + length--; 22171 + i++; 22172 + if(i>=w) { 22173 + i=0; 22174 + j++; 22175 + } 22176 + } 22177 + if(length>0) 22178 + fprintf(stderr, "Warning: possible ZRLE corruption\n"); 22179 + } 22180 + CopyDataToScreen((char *)frameBuffer, x, y, w, h); 22181 +if (0) fprintf(stderr, "cha4: %dx%d+%d+%d\n", w, h, x, y); 22182 + 22183 + break; 22184 + } 22185 + case 129: /* unused */ 22186 + { 22187 + return -8; 22188 + } 22189 + case 130 ... 255: /* palette RLE */ 22190 + { 22191 + CARDBPP palette[128]; 22192 + int m0 = 0, i,j; 22193 + 22194 + if(2+(type-128)*REALBPP/8>buffer_length) 22195 + return -9; 22196 + 22197 + /* read palette */ 22198 + for(i=0; i<type-128; i++,buffer+=REALBPP/8) 22199 + palette[i] = UncompressCPixel(buffer); 22200 + /* read palettized pixels */ 22201 + i=j=0; 22202 + while(j<h) { 22203 + int color,length; 22204 + /* read color */ 22205 + if(buffer>=buffer_end) 22206 + return -10; 22207 + color = palette[(*buffer)&0x7f]; 22208 + length=1; 22209 + if(*buffer&0x80) { 22210 + if(buffer+1>=buffer_end) 22211 + return -11; 22212 + buffer++; 22213 + /* read run length */ 22214 + while(*buffer==0xff) { 22215 + if(buffer+1>=buffer_end) 22216 + return -8; 22217 + length+=*buffer; 22218 + buffer++; 22219 + } 22220 + length+=*buffer; 22221 + } 22222 + buffer++; 22223 + while(j<h && length>0) { 22224 +# if 0 22225 + ((CARDBPP*)frameBuffer)[(y+j)*si.framebufferWidth+x+i] = color; 22226 + /* alt */ 22227 + CopyDataToScreen((char *)&color, x+i, y+j, 1, 1); 22228 +# else 22229 + ((CARDBPP*)frameBuffer)[m0++] = color; 22230 +# endif 22231 + length--; 22232 + i++; 22233 + if(i>=w) { 22234 + i=0; 22235 + j++; 22236 + } 22237 + } 22238 + if(length>0) 22239 + fprintf(stderr, "Warning: possible ZRLE corruption\n"); 22240 + } 22241 + CopyDataToScreen((char *)frameBuffer, x, y, w, h); 22242 +if (0) fprintf(stderr, "cha5: %dx%d+%d+%d\n", w, h, x, y); 22243 + 22244 + break; 22245 + } 22246 + } 22247 + 22248 +#if DO_ZYWRLE && BPP != 8 22249 + if (zywrle_level & 0x80) { 22250 + int th, tx; 22251 + int widthInBytes = w * BPP / 8; 22252 + int scrWidthInBytes; 22253 + char *scr, *buf; 22254 + static CARDBPP *ptmp = NULL; 22255 + static int ptmp_len = 0; 22256 + XImage *im = image_scale ? image_scale : image; 22257 + 22258 + if (w * h > ptmp_len) { 22259 + ptmp_len = w * h; 22260 + if (ptmp_len < rfbZRLETileWidth*rfbZRLETileHeight) { 22261 + ptmp_len = rfbZRLETileWidth*rfbZRLETileHeight; 22262 + } 22263 + if (ptmp) { 22264 + free(ptmp); 22265 + } 22266 + ptmp = (CARDBPP *) malloc(ptmp_len * sizeof(CARDBPP)); 22267 + } 22268 + 22269 + zywrle_level &= 0x7F; 22270 + /* Reverse copy: screen to buf/ptmp: */ 22271 + /* make this CopyDataFromScreen() or something. */ 22272 + if (!appData.useBGR565) { 22273 + scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8; 22274 + if (scrWidthInBytes != im->bytes_per_line) scrWidthInBytes = im->bytes_per_line; 22275 + scr = im->data + y * scrWidthInBytes + x * myFormat.bitsPerPixel / 8; 22276 + buf = (char *) ptmp; 22277 + 22278 + for (th = 0; th < h; th++) { 22279 + memcpy(buf, scr, widthInBytes); 22280 + buf += widthInBytes; 22281 + scr += scrWidthInBytes; 22282 + } 22283 + } else { 22284 + scrWidthInBytes = si.framebufferWidth * 4; 22285 + if (scrWidthInBytes != im->bytes_per_line) scrWidthInBytes = im->bytes_per_line; 22286 + scr = im->data + y * scrWidthInBytes + x * 4; 22287 + buf = (char *) ptmp; 22288 + 22289 + for (th = 0; th < h; th++) { 22290 + for (tx = 0; tx < w; tx++) { 22291 + unsigned long pix = *((unsigned int *)scr + tx); 22292 + unsigned int r1 = (pix & 0xff0000) >> 16; 22293 + unsigned int g1 = (pix & 0x00ff00) >> 8; 22294 + unsigned int b1 = (pix & 0x0000ff) >> 0; 22295 + int r2, g2, b2, idx; 22296 + int rok = 0, gok = 0, bok = 0, is0, sh = 10; 22297 + r2 = (31 * r1)/255; 22298 + g2 = (63 * g1)/255; 22299 + b2 = (31 * b1)/255; 22300 + for (is0 = 0; is0 < sh; is0++) { 22301 + int is, i, t; 22302 + for (i = 0; i < 2; i++) { 22303 + if (i == 0) { 22304 + is = -is0; 22305 + } else { 22306 + is = +is0; 22307 + } 22308 + if (!rok) { 22309 + t = r2 + is; 22310 + if (r1 == (255 * t)/31) { 22311 + r2 = t; rok = 1; 22312 + } 22313 + } 22314 + if (!gok) { 22315 + t = g2 + is; 22316 + if (g1 == (255 * t)/63) { 22317 + g2 = t; gok = 1; 22318 + } 22319 + } 22320 + if (!bok) { 22321 + t = b2 + is; 22322 + if (b1 == (255 * t)/31) { 22323 + b2 = t; bok = 1; 22324 + } 22325 + } 22326 + } 22327 + if (rok && gok && bok) { 22328 + break; 22329 + } 22330 + } 22331 + idx = (r2 << 11) | (g2 << 5) | (b2 << 0); 22332 + *((CARDBPP *)buf + tx) = (CARDBPP) idx; 22333 + } 22334 + buf += widthInBytes; 22335 + scr += scrWidthInBytes; 22336 + } 22337 + } 22338 + ZYWRLE_SYNTHESIZE((PIXEL_T *)ptmp, (PIXEL_T *)ptmp, w, h, w, zywrle_level, zywrleBuf ); 22339 + skip_maybe_sync = 1; 22340 + 22341 + if (appData.yCrop > 0) { 22342 + skip_maybe_sync = 0; 22343 + } 22344 + CopyDataToScreen((char *)ptmp, x, y, w, h); 22345 + 22346 + } 22347 +#endif 22348 + 22349 + return buffer-buffer_copy; 22350 +} 22351 + 22352 +#undef CARDBPP 22353 +#undef CARDREALBPP 22354 +#undef HandleZRLE 22355 +#undef HandleZRLETile 22356 +#undef UncompressCPixel 22357 +#undef REALBPP 22358 + 22359 +#undef UNCOMP 22360 + 22361 +#undef FillRectangle 22362 +#undef IS_BIG_ENDIAN 22363 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrleencodetemplate.c vnc_unixsrc/vncviewer/zrleencodetemplate.c 22364 --- vnc_unixsrc.orig/vncviewer/zrleencodetemplate.c 1969-12-31 19:00:00.000000000 -0500 22365 +++ vnc_unixsrc/vncviewer/zrleencodetemplate.c 2007-02-04 23:18:09.000000000 -0500 22366 @@ -0,0 +1,317 @@ 22367 +/* 22368 + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. 22369 + * Copyright (C) 2003 Sun Microsystems, Inc. 22370 + * 22371 + * This is free software; you can redistribute it and/or modify 22372 + * it under the terms of the GNU General Public License as published by 22373 + * the Free Software Foundation; either version 2 of the License, or 22374 + * (at your option) any later version. 22375 + * 22376 + * This software is distributed in the hope that it will be useful, 22377 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 22378 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22379 + * GNU General Public License for more details. 22380 + * 22381 + * You should have received a copy of the GNU General Public License 22382 + * along with this software; if not, write to the Free Software 22383 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 22384 + * USA. 22385 + */ 22386 + 22387 +/* 22388 + * Before including this file, you must define a number of CPP macros. 22389 + * 22390 + * BPP should be 8, 16 or 32 depending on the bits per pixel. 22391 + * GET_IMAGE_INTO_BUF should be some code which gets a rectangle of pixel data 22392 + * into the given buffer. EXTRA_ARGS can be defined to pass any other 22393 + * arguments needed by GET_IMAGE_INTO_BUF. 22394 + * 22395 + * Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel 22396 + * bigger than the largest tile of pixel data, since the ZRLE encoding 22397 + * algorithm writes to the position one past the end of the pixel data. 22398 + */ 22399 + 22400 +#include "zrleoutstream.h" 22401 +#include "zrlepalettehelper.h" 22402 +#include <assert.h> 22403 + 22404 +/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same 22405 + but also expands its arguments if they are macros */ 22406 + 22407 +#ifndef __RFB_CONCAT2E 22408 +#define __RFB_CONCAT2(a,b) a##b 22409 +#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b) 22410 +#endif 22411 + 22412 +#ifndef __RFB_CONCAT3E 22413 +#define __RFB_CONCAT3(a,b,c) a##b##c 22414 +#define __RFB_CONCAT3E(a,b,c) __RFB_CONCAT3(a,b,c) 22415 +#endif 22416 + 22417 +#undef END_FIX 22418 +#if ZYWRLE_ENDIAN == ENDIAN_LITTLE 22419 +# define END_FIX LE 22420 +#elif ZYWRLE_ENDIAN == ENDIAN_BIG 22421 +# define END_FIX BE 22422 +#else 22423 +# define END_FIX NE 22424 +#endif 22425 + 22426 +#ifdef CPIXEL 22427 +#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP) 22428 +#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL) 22429 +#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,CPIXEL,END_FIX) 22430 +#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,CPIXEL,END_FIX) 22431 +#define BPPOUT 24 22432 +#elif BPP==15 22433 +#define PIXEL_T __RFB_CONCAT2E(zrle_U,16) 22434 +#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,16) 22435 +#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX) 22436 +#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX) 22437 +#define BPPOUT 16 22438 +#else 22439 +#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP) 22440 +#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP) 22441 +#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX) 22442 +#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX) 22443 +#define BPPOUT BPP 22444 +#endif 22445 + 22446 +#ifndef ZRLE_ONCE 22447 +#define ZRLE_ONCE 22448 + 22449 +static const int bitsPerPackedPixel[] = { 22450 + 0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 22451 +}; 22452 + 22453 +int zywrle_level; 22454 +int zywrleBuf[rfbZRLETileWidth*rfbZRLETileHeight]; 22455 + 22456 +static zrlePaletteHelper paletteHelper; 22457 + 22458 +#endif /* ZRLE_ONCE */ 22459 + 22460 +void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os); 22461 + 22462 +#if BPP!=8 22463 +#define ZYWRLE_ENCODE 22464 +#include "zywrletemplate.c" 22465 +#endif 22466 + 22467 +static void ZRLE_ENCODE (int x, int y, int w, int h, 22468 + zrleOutStream* os, void* buf 22469 + EXTRA_ARGS 22470 + ) 22471 +{ 22472 + int ty; 22473 + for (ty = y; ty < y+h; ty += rfbZRLETileHeight) { 22474 + int tx, th = rfbZRLETileHeight; 22475 + if (th > y+h-ty) th = y+h-ty; 22476 + for (tx = x; tx < x+w; tx += rfbZRLETileWidth) { 22477 + int tw = rfbZRLETileWidth; 22478 + if (tw > x+w-tx) tw = x+w-tx; 22479 + 22480 + GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf); 22481 + 22482 + ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, os); 22483 + } 22484 + } 22485 + zrleOutStreamFlush(os); 22486 +} 22487 + 22488 + 22489 +void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os) 22490 +{ 22491 + /* First find the palette and the number of runs */ 22492 + 22493 + zrlePaletteHelper *ph; 22494 + 22495 + int runs = 0; 22496 + int singlePixels = 0; 22497 + 22498 + rfbBool useRle; 22499 + rfbBool usePalette; 22500 + 22501 + int estimatedBytes; 22502 + int plainRleBytes; 22503 + int i; 22504 + 22505 + PIXEL_T* ptr = data; 22506 + PIXEL_T* end = ptr + h * w; 22507 + *end = ~*(end-1); /* one past the end is different so the while loop ends */ 22508 + 22509 + ph = &paletteHelper; 22510 + zrlePaletteHelperInit(ph); 22511 + 22512 + while (ptr < end) { 22513 + PIXEL_T pix = *ptr; 22514 + if (*++ptr != pix) { 22515 + singlePixels++; 22516 + } else { 22517 + while (*++ptr == pix) ; 22518 + runs++; 22519 + } 22520 + zrlePaletteHelperInsert(ph, pix); 22521 + } 22522 + 22523 + /* Solid tile is a special case */ 22524 + 22525 + if (ph->size == 1) { 22526 + zrleOutStreamWriteU8(os, 1); 22527 + zrleOutStreamWRITE_PIXEL(os, ph->palette[0]); 22528 + return; 22529 + } 22530 + 22531 + /* Try to work out whether to use RLE and/or a palette. We do this by 22532 + estimating the number of bytes which will be generated and picking the 22533 + method which results in the fewest bytes. Of course this may not result 22534 + in the fewest bytes after compression... */ 22535 + 22536 + useRle = FALSE; 22537 + usePalette = FALSE; 22538 + 22539 + estimatedBytes = w * h * (BPPOUT/8); /* start assuming raw */ 22540 + 22541 +#if BPP!=8 22542 + if( (zywrle_level>0)&& !(zywrle_level & 0x80) ){ 22543 + estimatedBytes >>= zywrle_level; 22544 + } 22545 +#endif 22546 + 22547 + plainRleBytes = ((BPPOUT/8)+1) * (runs + singlePixels); 22548 + 22549 + if (plainRleBytes < estimatedBytes) { 22550 + useRle = TRUE; 22551 + estimatedBytes = plainRleBytes; 22552 + } 22553 + 22554 + if (ph->size < 128) { 22555 + int paletteRleBytes = (BPPOUT/8) * ph->size + 2 * runs + singlePixels; 22556 + 22557 + if (paletteRleBytes < estimatedBytes) { 22558 + useRle = TRUE; 22559 + usePalette = TRUE; 22560 + estimatedBytes = paletteRleBytes; 22561 + } 22562 + 22563 + if (ph->size < 17) { 22564 + int packedBytes = ((BPPOUT/8) * ph->size + 22565 + w * h * bitsPerPackedPixel[ph->size-1] / 8); 22566 + 22567 + if (packedBytes < estimatedBytes) { 22568 + useRle = FALSE; 22569 + usePalette = TRUE; 22570 + estimatedBytes = packedBytes; 22571 + } 22572 + } 22573 + } 22574 + 22575 + if (!usePalette) ph->size = 0; 22576 + 22577 + zrleOutStreamWriteU8(os, (useRle ? 128 : 0) | ph->size); 22578 + 22579 + for (i = 0; i < ph->size; i++) { 22580 + zrleOutStreamWRITE_PIXEL(os, ph->palette[i]); 22581 + } 22582 + 22583 + if (useRle) { 22584 + 22585 + PIXEL_T* ptr = data; 22586 + PIXEL_T* end = ptr + w * h; 22587 + PIXEL_T* runStart; 22588 + PIXEL_T pix; 22589 + while (ptr < end) { 22590 + int len; 22591 + runStart = ptr; 22592 + pix = *ptr++; 22593 + while (*ptr == pix && ptr < end) 22594 + ptr++; 22595 + len = ptr - runStart; 22596 + if (len <= 2 && usePalette) { 22597 + int index = zrlePaletteHelperLookup(ph, pix); 22598 + if (len == 2) 22599 + zrleOutStreamWriteU8(os, index); 22600 + zrleOutStreamWriteU8(os, index); 22601 + continue; 22602 + } 22603 + if (usePalette) { 22604 + int index = zrlePaletteHelperLookup(ph, pix); 22605 + zrleOutStreamWriteU8(os, index | 128); 22606 + } else { 22607 + zrleOutStreamWRITE_PIXEL(os, pix); 22608 + } 22609 + len -= 1; 22610 + while (len >= 255) { 22611 + zrleOutStreamWriteU8(os, 255); 22612 + len -= 255; 22613 + } 22614 + zrleOutStreamWriteU8(os, len); 22615 + } 22616 + 22617 + } else { 22618 + 22619 + /* no RLE */ 22620 + 22621 + if (usePalette) { 22622 + int bppp; 22623 + PIXEL_T* ptr = data; 22624 + 22625 + /* packed pixels */ 22626 + 22627 + assert (ph->size < 17); 22628 + 22629 + bppp = bitsPerPackedPixel[ph->size-1]; 22630 + 22631 + for (i = 0; i < h; i++) { 22632 + zrle_U8 nbits = 0; 22633 + zrle_U8 byte = 0; 22634 + 22635 + PIXEL_T* eol = ptr + w; 22636 + 22637 + while (ptr < eol) { 22638 + PIXEL_T pix = *ptr++; 22639 + zrle_U8 index = zrlePaletteHelperLookup(ph, pix); 22640 + byte = (byte << bppp) | index; 22641 + nbits += bppp; 22642 + if (nbits >= 8) { 22643 + zrleOutStreamWriteU8(os, byte); 22644 + nbits = 0; 22645 + } 22646 + } 22647 + if (nbits > 0) { 22648 + byte <<= 8 - nbits; 22649 + zrleOutStreamWriteU8(os, byte); 22650 + } 22651 + } 22652 + } else { 22653 + 22654 + /* raw */ 22655 + 22656 +#if BPP!=8 22657 + if( (zywrle_level>0)&& !(zywrle_level & 0x80) ){ 22658 + ZYWRLE_ANALYZE( data, data, w, h, w, zywrle_level, zywrleBuf ); 22659 + zywrle_level |= 0x80; 22660 + ZRLE_ENCODE_TILE( data, w, h, os ); 22661 + zywrle_level &= 0x7F; 22662 + }else 22663 +#endif 22664 + { 22665 +#ifdef CPIXEL 22666 + PIXEL_T *ptr; 22667 + for (ptr = data; ptr < data+w*h; ptr++) { 22668 + zrleOutStreamWRITE_PIXEL(os, *ptr); 22669 + } 22670 +#else 22671 + zrleOutStreamWriteBytes(os, (zrle_U8 *)data, w*h*(BPP/8)); 22672 +#endif 22673 + } 22674 + } 22675 + } 22676 +} 22677 + 22678 +#undef PIXEL_T 22679 +#undef zrleOutStreamWRITE_PIXEL 22680 +#undef ZRLE_ENCODE 22681 +#undef ZRLE_ENCODE_TILE 22682 +#undef ZYWRLE_ENCODE_TILE 22683 +#undef BPPOUT 22684 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrleoutstream.c vnc_unixsrc/vncviewer/zrleoutstream.c 22685 --- vnc_unixsrc.orig/vncviewer/zrleoutstream.c 1969-12-31 19:00:00.000000000 -0500 22686 +++ vnc_unixsrc/vncviewer/zrleoutstream.c 2005-05-15 10:57:54.000000000 -0400 22687 @@ -0,0 +1,275 @@ 22688 +/* 22689 + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. 22690 + * Copyright (C) 2003 Sun Microsystems, Inc. 22691 + * 22692 + * This is free software; you can redistribute it and/or modify 22693 + * it under the terms of the GNU General Public License as published by 22694 + * the Free Software Foundation; either version 2 of the License, or 22695 + * (at your option) any later version. 22696 + * 22697 + * This software is distributed in the hope that it will be useful, 22698 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 22699 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22700 + * GNU General Public License for more details. 22701 + * 22702 + * You should have received a copy of the GNU General Public License 22703 + * along with this software; if not, write to the Free Software 22704 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 22705 + * USA. 22706 + */ 22707 + 22708 +#include "zrleoutstream.h" 22709 +#include <stdlib.h> 22710 + 22711 +#define ZRLE_IN_BUFFER_SIZE 16384 22712 +#define ZRLE_OUT_BUFFER_SIZE 1024 22713 +#undef ZRLE_DEBUG 22714 + 22715 +static rfbBool zrleBufferAlloc(zrleBuffer *buffer, int size) 22716 +{ 22717 + buffer->ptr = buffer->start = malloc(size); 22718 + if (buffer->start == NULL) { 22719 + buffer->end = NULL; 22720 + return FALSE; 22721 + } 22722 + 22723 + buffer->end = buffer->start + size; 22724 + 22725 + return TRUE; 22726 +} 22727 + 22728 +static void zrleBufferFree(zrleBuffer *buffer) 22729 +{ 22730 + if (buffer->start) 22731 + free(buffer->start); 22732 + buffer->start = buffer->ptr = buffer->end = NULL; 22733 +} 22734 + 22735 +static rfbBool zrleBufferGrow(zrleBuffer *buffer, int size) 22736 +{ 22737 + int offset; 22738 + 22739 + size += buffer->end - buffer->start; 22740 + offset = ZRLE_BUFFER_LENGTH (buffer); 22741 + 22742 + buffer->start = realloc(buffer->start, size); 22743 + if (!buffer->start) { 22744 + return FALSE; 22745 + } 22746 + 22747 + buffer->end = buffer->start + size; 22748 + buffer->ptr = buffer->start + offset; 22749 + 22750 + return TRUE; 22751 +} 22752 + 22753 +zrleOutStream *zrleOutStreamNew(void) 22754 +{ 22755 + zrleOutStream *os; 22756 + 22757 + os = malloc(sizeof(zrleOutStream)); 22758 + if (os == NULL) 22759 + return NULL; 22760 + 22761 + if (!zrleBufferAlloc(&os->in, ZRLE_IN_BUFFER_SIZE)) { 22762 + free(os); 22763 + return NULL; 22764 + } 22765 + 22766 + if (!zrleBufferAlloc(&os->out, ZRLE_OUT_BUFFER_SIZE)) { 22767 + zrleBufferFree(&os->in); 22768 + free(os); 22769 + return NULL; 22770 + } 22771 + 22772 + os->zs.zalloc = Z_NULL; 22773 + os->zs.zfree = Z_NULL; 22774 + os->zs.opaque = Z_NULL; 22775 + if (deflateInit(&os->zs, Z_DEFAULT_COMPRESSION) != Z_OK) { 22776 + zrleBufferFree(&os->in); 22777 + free(os); 22778 + return NULL; 22779 + } 22780 + 22781 + return os; 22782 +} 22783 + 22784 +void zrleOutStreamFree (zrleOutStream *os) 22785 +{ 22786 + deflateEnd(&os->zs); 22787 + zrleBufferFree(&os->in); 22788 + zrleBufferFree(&os->out); 22789 + free(os); 22790 +} 22791 + 22792 +rfbBool zrleOutStreamFlush(zrleOutStream *os) 22793 +{ 22794 + os->zs.next_in = os->in.start; 22795 + os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in); 22796 + 22797 +#ifdef ZRLE_DEBUG 22798 + rfbLog("zrleOutStreamFlush: avail_in %d\n", os->zs.avail_in); 22799 +#endif 22800 + 22801 + while (os->zs.avail_in != 0) { 22802 + do { 22803 + int ret; 22804 + 22805 + if (os->out.ptr >= os->out.end && 22806 + !zrleBufferGrow(&os->out, os->out.end - os->out.start)) { 22807 + rfbLog("zrleOutStreamFlush: failed to grow output buffer\n"); 22808 + return FALSE; 22809 + } 22810 + 22811 + os->zs.next_out = os->out.ptr; 22812 + os->zs.avail_out = os->out.end - os->out.ptr; 22813 + 22814 +#ifdef ZRLE_DEBUG 22815 + rfbLog("zrleOutStreamFlush: calling deflate, avail_in %d, avail_out %d\n", 22816 + os->zs.avail_in, os->zs.avail_out); 22817 +#endif 22818 + 22819 + if ((ret = deflate(&os->zs, Z_SYNC_FLUSH)) != Z_OK) { 22820 + rfbLog("zrleOutStreamFlush: deflate failed with error code %d\n", ret); 22821 + return FALSE; 22822 + } 22823 + 22824 +#ifdef ZRLE_DEBUG 22825 + rfbLog("zrleOutStreamFlush: after deflate: %d bytes\n", 22826 + os->zs.next_out - os->out.ptr); 22827 +#endif 22828 + 22829 + os->out.ptr = os->zs.next_out; 22830 + } while (os->zs.avail_out == 0); 22831 + } 22832 + 22833 + os->in.ptr = os->in.start; 22834 + 22835 + return TRUE; 22836 +} 22837 + 22838 +static int zrleOutStreamOverrun(zrleOutStream *os, 22839 + int size) 22840 +{ 22841 +#ifdef ZRLE_DEBUG 22842 + rfbLog("zrleOutStreamOverrun\n"); 22843 +#endif 22844 + 22845 + while (os->in.end - os->in.ptr < size && os->in.ptr > os->in.start) { 22846 + os->zs.next_in = os->in.start; 22847 + os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in); 22848 + 22849 + do { 22850 + int ret; 22851 + 22852 + if (os->out.ptr >= os->out.end && 22853 + !zrleBufferGrow(&os->out, os->out.end - os->out.start)) { 22854 + rfbLog("zrleOutStreamOverrun: failed to grow output buffer\n"); 22855 + return FALSE; 22856 + } 22857 + 22858 + os->zs.next_out = os->out.ptr; 22859 + os->zs.avail_out = os->out.end - os->out.ptr; 22860 + 22861 +#ifdef ZRLE_DEBUG 22862 + rfbLog("zrleOutStreamOverrun: calling deflate, avail_in %d, avail_out %d\n", 22863 + os->zs.avail_in, os->zs.avail_out); 22864 +#endif 22865 + 22866 + if ((ret = deflate(&os->zs, 0)) != Z_OK) { 22867 + rfbLog("zrleOutStreamOverrun: deflate failed with error code %d\n", ret); 22868 + return 0; 22869 + } 22870 + 22871 +#ifdef ZRLE_DEBUG 22872 + rfbLog("zrleOutStreamOverrun: after deflate: %d bytes\n", 22873 + os->zs.next_out - os->out.ptr); 22874 +#endif 22875 + 22876 + os->out.ptr = os->zs.next_out; 22877 + } while (os->zs.avail_out == 0); 22878 + 22879 + /* output buffer not full */ 22880 + 22881 + if (os->zs.avail_in == 0) { 22882 + os->in.ptr = os->in.start; 22883 + } else { 22884 + /* but didn't consume all the data? try shifting what's left to the 22885 + * start of the buffer. 22886 + */ 22887 + rfbLog("zrleOutStreamOverrun: out buf not full, but in data not consumed\n"); 22888 + memmove(os->in.start, os->zs.next_in, os->in.ptr - os->zs.next_in); 22889 + os->in.ptr -= os->zs.next_in - os->in.start; 22890 + } 22891 + } 22892 + 22893 + if (size > os->in.end - os->in.ptr) 22894 + size = os->in.end - os->in.ptr; 22895 + 22896 + return size; 22897 +} 22898 + 22899 +static int zrleOutStreamCheck(zrleOutStream *os, int size) 22900 +{ 22901 + if (os->in.ptr + size > os->in.end) { 22902 + return zrleOutStreamOverrun(os, size); 22903 + } 22904 + return size; 22905 +} 22906 + 22907 +void zrleOutStreamWriteBytes(zrleOutStream *os, 22908 + const zrle_U8 *data, 22909 + int length) 22910 +{ 22911 + const zrle_U8* dataEnd = data + length; 22912 + while (data < dataEnd) { 22913 + int n = zrleOutStreamCheck(os, dataEnd - data); 22914 + memcpy(os->in.ptr, data, n); 22915 + os->in.ptr += n; 22916 + data += n; 22917 + } 22918 +} 22919 + 22920 +void zrleOutStreamWriteU8(zrleOutStream *os, zrle_U8 u) 22921 +{ 22922 + zrleOutStreamCheck(os, 1); 22923 + *os->in.ptr++ = u; 22924 +} 22925 + 22926 +void zrleOutStreamWriteOpaque8(zrleOutStream *os, zrle_U8 u) 22927 +{ 22928 + zrleOutStreamCheck(os, 1); 22929 + *os->in.ptr++ = u; 22930 +} 22931 + 22932 +void zrleOutStreamWriteOpaque16 (zrleOutStream *os, zrle_U16 u) 22933 +{ 22934 + zrleOutStreamCheck(os, 2); 22935 + *os->in.ptr++ = ((zrle_U8*)&u)[0]; 22936 + *os->in.ptr++ = ((zrle_U8*)&u)[1]; 22937 +} 22938 + 22939 +void zrleOutStreamWriteOpaque32 (zrleOutStream *os, zrle_U32 u) 22940 +{ 22941 + zrleOutStreamCheck(os, 4); 22942 + *os->in.ptr++ = ((zrle_U8*)&u)[0]; 22943 + *os->in.ptr++ = ((zrle_U8*)&u)[1]; 22944 + *os->in.ptr++ = ((zrle_U8*)&u)[2]; 22945 + *os->in.ptr++ = ((zrle_U8*)&u)[3]; 22946 +} 22947 + 22948 +void zrleOutStreamWriteOpaque24A(zrleOutStream *os, zrle_U32 u) 22949 +{ 22950 + zrleOutStreamCheck(os, 3); 22951 + *os->in.ptr++ = ((zrle_U8*)&u)[0]; 22952 + *os->in.ptr++ = ((zrle_U8*)&u)[1]; 22953 + *os->in.ptr++ = ((zrle_U8*)&u)[2]; 22954 +} 22955 + 22956 +void zrleOutStreamWriteOpaque24B(zrleOutStream *os, zrle_U32 u) 22957 +{ 22958 + zrleOutStreamCheck(os, 3); 22959 + *os->in.ptr++ = ((zrle_U8*)&u)[1]; 22960 + *os->in.ptr++ = ((zrle_U8*)&u)[2]; 22961 + *os->in.ptr++ = ((zrle_U8*)&u)[3]; 22962 +} 22963 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrleoutstream.h vnc_unixsrc/vncviewer/zrleoutstream.h 22964 --- vnc_unixsrc.orig/vncviewer/zrleoutstream.h 1969-12-31 19:00:00.000000000 -0500 22965 +++ vnc_unixsrc/vncviewer/zrleoutstream.h 2004-05-25 06:05:15.000000000 -0400 22966 @@ -0,0 +1,62 @@ 22967 +/* 22968 + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. 22969 + * Copyright (C) 2003 Sun Microsystems, Inc. 22970 + * 22971 + * This is free software; you can redistribute it and/or modify 22972 + * it under the terms of the GNU General Public License as published by 22973 + * the Free Software Foundation; either version 2 of the License, or 22974 + * (at your option) any later version. 22975 + * 22976 + * This software is distributed in the hope that it will be useful, 22977 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 22978 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22979 + * GNU General Public License for more details. 22980 + * 22981 + * You should have received a copy of the GNU General Public License 22982 + * along with this software; if not, write to the Free Software 22983 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 22984 + * USA. 22985 + */ 22986 + 22987 +#ifndef __ZRLE_OUT_STREAM_H__ 22988 +#define __ZRLE_OUT_STREAM_H__ 22989 + 22990 +#include <zlib.h> 22991 +#include "zrletypes.h" 22992 +#include "rfb/rfb.h" 22993 + 22994 +typedef struct { 22995 + zrle_U8 *start; 22996 + zrle_U8 *ptr; 22997 + zrle_U8 *end; 22998 +} zrleBuffer; 22999 + 23000 +typedef struct { 23001 + zrleBuffer in; 23002 + zrleBuffer out; 23003 + 23004 + z_stream zs; 23005 +} zrleOutStream; 23006 + 23007 +#define ZRLE_BUFFER_LENGTH(b) ((b)->ptr - (b)->start) 23008 + 23009 +zrleOutStream *zrleOutStreamNew (void); 23010 +void zrleOutStreamFree (zrleOutStream *os); 23011 +rfbBool zrleOutStreamFlush (zrleOutStream *os); 23012 +void zrleOutStreamWriteBytes (zrleOutStream *os, 23013 + const zrle_U8 *data, 23014 + int length); 23015 +void zrleOutStreamWriteU8 (zrleOutStream *os, 23016 + zrle_U8 u); 23017 +void zrleOutStreamWriteOpaque8 (zrleOutStream *os, 23018 + zrle_U8 u); 23019 +void zrleOutStreamWriteOpaque16 (zrleOutStream *os, 23020 + zrle_U16 u); 23021 +void zrleOutStreamWriteOpaque32 (zrleOutStream *os, 23022 + zrle_U32 u); 23023 +void zrleOutStreamWriteOpaque24A(zrleOutStream *os, 23024 + zrle_U32 u); 23025 +void zrleOutStreamWriteOpaque24B(zrleOutStream *os, 23026 + zrle_U32 u); 23027 + 23028 +#endif /* __ZRLE_OUT_STREAM_H__ */ 23029 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrlepalettehelper.c vnc_unixsrc/vncviewer/zrlepalettehelper.c 23030 --- vnc_unixsrc.orig/vncviewer/zrlepalettehelper.c 1969-12-31 19:00:00.000000000 -0500 23031 +++ vnc_unixsrc/vncviewer/zrlepalettehelper.c 2004-05-25 06:05:15.000000000 -0400 23032 @@ -0,0 +1,62 @@ 23033 +/* 23034 + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. 23035 + * Copyright (C) 2003 Sun Microsystems, Inc. 23036 + * 23037 + * This is free software; you can redistribute it and/or modify 23038 + * it under the terms of the GNU General Public License as published by 23039 + * the Free Software Foundation; either version 2 of the License, or 23040 + * (at your option) any later version. 23041 + * 23042 + * This software is distributed in the hope that it will be useful, 23043 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 23044 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23045 + * GNU General Public License for more details. 23046 + * 23047 + * You should have received a copy of the GNU General Public License 23048 + * along with this software; if not, write to the Free Software 23049 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 23050 + * USA. 23051 + */ 23052 + 23053 +#include "zrlepalettehelper.h" 23054 +#include <assert.h> 23055 +#include <string.h> 23056 + 23057 +#define ZRLE_HASH(pix) (((pix) ^ ((pix) >> 17)) & 4095) 23058 + 23059 +void zrlePaletteHelperInit(zrlePaletteHelper *helper) 23060 +{ 23061 + memset(helper->palette, 0, sizeof(helper->palette)); 23062 + memset(helper->index, 255, sizeof(helper->index)); 23063 + memset(helper->key, 0, sizeof(helper->key)); 23064 + helper->size = 0; 23065 +} 23066 + 23067 +void zrlePaletteHelperInsert(zrlePaletteHelper *helper, zrle_U32 pix) 23068 +{ 23069 + if (helper->size < ZRLE_PALETTE_MAX_SIZE) { 23070 + int i = ZRLE_HASH(pix); 23071 + 23072 + while (helper->index[i] != 255 && helper->key[i] != pix) 23073 + i++; 23074 + if (helper->index[i] != 255) return; 23075 + 23076 + helper->index[i] = helper->size; 23077 + helper->key[i] = pix; 23078 + helper->palette[helper->size] = pix; 23079 + } 23080 + helper->size++; 23081 +} 23082 + 23083 +int zrlePaletteHelperLookup(zrlePaletteHelper *helper, zrle_U32 pix) 23084 +{ 23085 + int i = ZRLE_HASH(pix); 23086 + 23087 + assert(helper->size <= ZRLE_PALETTE_MAX_SIZE); 23088 + 23089 + while (helper->index[i] != 255 && helper->key[i] != pix) 23090 + i++; 23091 + if (helper->index[i] != 255) return helper->index[i]; 23092 + 23093 + return -1; 23094 +} 23095 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrlepalettehelper.h vnc_unixsrc/vncviewer/zrlepalettehelper.h 23096 --- vnc_unixsrc.orig/vncviewer/zrlepalettehelper.h 1969-12-31 19:00:00.000000000 -0500 23097 +++ vnc_unixsrc/vncviewer/zrlepalettehelper.h 2004-05-25 06:05:15.000000000 -0400 23098 @@ -0,0 +1,46 @@ 23099 +/* 23100 + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. 23101 + * Copyright (C) 2003 Sun Microsystems, Inc. 23102 + * 23103 + * This is free software; you can redistribute it and/or modify 23104 + * it under the terms of the GNU General Public License as published by 23105 + * the Free Software Foundation; either version 2 of the License, or 23106 + * (at your option) any later version. 23107 + * 23108 + * This software is distributed in the hope that it will be useful, 23109 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 23110 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23111 + * GNU General Public License for more details. 23112 + * 23113 + * You should have received a copy of the GNU General Public License 23114 + * along with this software; if not, write to the Free Software 23115 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 23116 + * USA. 23117 + */ 23118 + 23119 +/* 23120 + * The PaletteHelper class helps us build up the palette from pixel data by 23121 + * storing a reverse index using a simple hash-table 23122 + */ 23123 + 23124 +#ifndef __ZRLE_PALETTE_HELPER_H__ 23125 +#define __ZRLE_PALETTE_HELPER_H__ 23126 + 23127 +#include "zrletypes.h" 23128 + 23129 +#define ZRLE_PALETTE_MAX_SIZE 127 23130 + 23131 +typedef struct { 23132 + zrle_U32 palette[ZRLE_PALETTE_MAX_SIZE]; 23133 + zrle_U8 index[ZRLE_PALETTE_MAX_SIZE + 4096]; 23134 + zrle_U32 key[ZRLE_PALETTE_MAX_SIZE + 4096]; 23135 + int size; 23136 +} zrlePaletteHelper; 23137 + 23138 +void zrlePaletteHelperInit (zrlePaletteHelper *helper); 23139 +void zrlePaletteHelperInsert(zrlePaletteHelper *helper, 23140 + zrle_U32 pix); 23141 +int zrlePaletteHelperLookup(zrlePaletteHelper *helper, 23142 + zrle_U32 pix); 23143 + 23144 +#endif /* __ZRLE_PALETTE_HELPER_H__ */ 23145 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zrletypes.h vnc_unixsrc/vncviewer/zrletypes.h 23146 --- vnc_unixsrc.orig/vncviewer/zrletypes.h 1969-12-31 19:00:00.000000000 -0500 23147 +++ vnc_unixsrc/vncviewer/zrletypes.h 2004-05-25 06:05:15.000000000 -0400 23148 @@ -0,0 +1,30 @@ 23149 +/* 23150 + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. 23151 + * 23152 + * This is free software; you can redistribute it and/or modify 23153 + * it under the terms of the GNU General Public License as published by 23154 + * the Free Software Foundation; either version 2 of the License, or 23155 + * (at your option) any later version. 23156 + * 23157 + * This software is distributed in the hope that it will be useful, 23158 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 23159 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23160 + * GNU General Public License for more details. 23161 + * 23162 + * You should have received a copy of the GNU General Public License 23163 + * along with this software; if not, write to the Free Software 23164 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 23165 + * USA. 23166 + */ 23167 + 23168 +#ifndef __ZRLE_TYPES_H__ 23169 +#define __ZRLE_TYPES_H__ 23170 + 23171 +typedef unsigned char zrle_U8; 23172 +typedef unsigned short zrle_U16; 23173 +typedef unsigned int zrle_U32; 23174 +typedef signed char zrle_S8; 23175 +typedef signed short zrle_S16; 23176 +typedef signed int zrle_S32; 23177 + 23178 +#endif /* __ZRLE_TYPES_H__ */ 23179 diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zywrletemplate.c vnc_unixsrc/vncviewer/zywrletemplate.c 23180 --- vnc_unixsrc.orig/vncviewer/zywrletemplate.c 1969-12-31 19:00:00.000000000 -0500 23181 +++ vnc_unixsrc/vncviewer/zywrletemplate.c 2008-02-15 23:33:13.000000000 -0500 23182 @@ -0,0 +1,824 @@ 23183 + 23184 +/******************************************************************** 23185 + * * 23186 + * THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE. * 23187 + * * 23188 + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 23189 + * GOVERNED BY A FOLLOWING BSD-STYLE SOURCE LICENSE. * 23190 + * PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 23191 + * * 23192 + * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006 * 23193 + * BY Hitachi Systems & Services, Ltd. * 23194 + * (Noriaki Yamazaki, Research & Developement Center) * * 23195 + * * 23196 + ******************************************************************** 23197 +Redistribution and use in source and binary forms, with or without 23198 +modification, are permitted provided that the following conditions 23199 +are met: 23200 + 23201 +- Redistributions of source code must retain the above copyright 23202 +notice, this list of conditions and the following disclaimer. 23203 + 23204 +- Redistributions in binary form must reproduce the above copyright 23205 +notice, this list of conditions and the following disclaimer in the 23206 +documentation and/or other materials provided with the distribution. 23207 + 23208 +- Neither the name of the Hitachi Systems & Services, Ltd. nor 23209 +the names of its contributors may be used to endorse or promote 23210 +products derived from this software without specific prior written 23211 +permission. 23212 + 23213 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23214 +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23215 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23216 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION 23217 +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23218 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23219 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23220 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23221 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23222 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23223 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23224 + ********************************************************************/ 23225 + 23226 +/* Change Log: 23227 + V0.02 : 2008/02/04 : Fix mis encode/decode when width != scanline 23228 + (Thanks Johannes Schindelin, author of LibVNC 23229 + Server/Client) 23230 + V0.01 : 2007/02/06 : Initial release 23231 +*/ 23232 + 23233 +/* #define ZYWRLE_ENCODE */ 23234 +/* #define ZYWRLE_DECODE */ 23235 +#define ZYWRLE_QUANTIZE 23236 + 23237 +/* 23238 +[References] 23239 + PLHarr: 23240 + 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. 23241 + EZW: 23242 + Shapiro, JM: Embedded Image Coding Using Zerotrees of Wavelet Coefficients, IEEE Trans. Signal. Process., Vol.41, pp.3445-3462 (1993). 23243 +*/ 23244 + 23245 + 23246 +/* Template Macro stuffs. */ 23247 +#undef ZYWRLE_ANALYZE 23248 +#undef ZYWRLE_SYNTHESIZE 23249 +#define ZYWRLE_ANALYZE __RFB_CONCAT3E(zywrleAnalyze,BPP,END_FIX) 23250 +#define ZYWRLE_SYNTHESIZE __RFB_CONCAT3E(zywrleSynthesize,BPP,END_FIX) 23251 + 23252 +#define ZYWRLE_RGBYUV __RFB_CONCAT3E(zywrleRGBYUV,BPP,END_FIX) 23253 +#define ZYWRLE_YUVRGB __RFB_CONCAT3E(zywrleYUVRGB,BPP,END_FIX) 23254 +#define ZYWRLE_YMASK __RFB_CONCAT2E(ZYWRLE_YMASK,BPP) 23255 +#define ZYWRLE_UVMASK __RFB_CONCAT2E(ZYWRLE_UVMASK,BPP) 23256 +#define ZYWRLE_LOAD_PIXEL __RFB_CONCAT2E(ZYWRLE_LOAD_PIXEL,BPP) 23257 +#define ZYWRLE_SAVE_PIXEL __RFB_CONCAT2E(ZYWRLE_SAVE_PIXEL,BPP) 23258 + 23259 +/* Packing/Unpacking pixel stuffs. 23260 + Endian conversion stuffs. */ 23261 +#undef S_0 23262 +#undef S_1 23263 +#undef L_0 23264 +#undef L_1 23265 +#undef L_2 23266 +#if ZYWRLE_ENDIAN == ENDIAN_BIG 23267 +# define S_0 1 23268 +# define S_1 0 23269 +# define L_0 3 23270 +# define L_1 2 23271 +# define L_2 1 23272 +#else 23273 +# define S_0 0 23274 +# define S_1 1 23275 +# define L_0 0 23276 +# define L_1 1 23277 +# define L_2 2 23278 +#endif 23279 + 23280 +/* Load/Save pixel stuffs. */ 23281 +#define ZYWRLE_YMASK15 0xFFFFFFF8 23282 +#define ZYWRLE_UVMASK15 0xFFFFFFF8 23283 +#define ZYWRLE_LOAD_PIXEL15(pSrc,R,G,B) { \ 23284 + R = (((unsigned char*)pSrc)[S_1]<< 1)& 0xF8; \ 23285 + G = ((((unsigned char*)pSrc)[S_1]<< 6)|(((unsigned char*)pSrc)[S_0]>> 2))& 0xF8; \ 23286 + B = (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8; \ 23287 +} 23288 +#define ZYWRLE_SAVE_PIXEL15(pDst,R,G,B) { \ 23289 + R &= 0xF8; \ 23290 + G &= 0xF8; \ 23291 + B &= 0xF8; \ 23292 + ((unsigned char*)pDst)[S_1] = (unsigned char)( (R>>1)|(G>>6) ); \ 23293 + ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<2))& 0xFF); \ 23294 +} 23295 +#define ZYWRLE_YMASK16 0xFFFFFFFC 23296 +#define ZYWRLE_UVMASK16 0xFFFFFFF8 23297 +#define ZYWRLE_LOAD_PIXEL16(pSrc,R,G,B) { \ 23298 + R = ((unsigned char*)pSrc)[S_1] & 0xF8; \ 23299 + G = ((((unsigned char*)pSrc)[S_1]<< 5)|(((unsigned char*)pSrc)[S_0]>> 3))& 0xFC; \ 23300 + B = (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8; \ 23301 +} 23302 +#define ZYWRLE_SAVE_PIXEL16(pDst,R,G,B) { \ 23303 + R &= 0xF8; \ 23304 + G &= 0xFC; \ 23305 + B &= 0xF8; \ 23306 + ((unsigned char*)pDst)[S_1] = (unsigned char)( R |(G>>5) ); \ 23307 + ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<3))& 0xFF); \ 23308 +} 23309 +#define ZYWRLE_YMASK32 0xFFFFFFFF 23310 +#define ZYWRLE_UVMASK32 0xFFFFFFFF 23311 +#define ZYWRLE_LOAD_PIXEL32(pSrc,R,G,B) { \ 23312 + R = ((unsigned char*)pSrc)[L_2]; \ 23313 + G = ((unsigned char*)pSrc)[L_1]; \ 23314 + B = ((unsigned char*)pSrc)[L_0]; \ 23315 +} 23316 +#define ZYWRLE_SAVE_PIXEL32(pDst,R,G,B) { \ 23317 + ((unsigned char*)pDst)[L_2] = (unsigned char)R; \ 23318 + ((unsigned char*)pDst)[L_1] = (unsigned char)G; \ 23319 + ((unsigned char*)pDst)[L_0] = (unsigned char)B; \ 23320 +} 23321 + 23322 +#ifndef ZYWRLE_ONCE 23323 +#define ZYWRLE_ONCE 23324 + 23325 +#ifdef WIN32 23326 +#define InlineX __inline 23327 +#else 23328 +#define InlineX inline 23329 +#endif 23330 + 23331 +#ifdef ZYWRLE_ENCODE 23332 +/* Tables for Coefficients filtering. */ 23333 +# ifndef ZYWRLE_QUANTIZE 23334 +/* Type A:lower bit omitting of EZW style. */ 23335 +const static unsigned int zywrleParam[3][3]={ 23336 + {0x0000F000,0x00000000,0x00000000}, 23337 + {0x0000C000,0x00F0F0F0,0x00000000}, 23338 + {0x0000C000,0x00C0C0C0,0x00F0F0F0}, 23339 +/* {0x0000FF00,0x00000000,0x00000000}, 23340 + {0x0000FF00,0x00FFFFFF,0x00000000}, 23341 + {0x0000FF00,0x00FFFFFF,0x00FFFFFF}, */ 23342 +}; 23343 +# else 23344 +/* Type B:Non liner quantization filter. */ 23345 +static const signed char zywrleConv[4][256]={ 23346 +{ /* bi=5, bo=5 r=0.0:PSNR=24.849 */ 23347 + 0, 0, 0, 0, 0, 0, 0, 0, 23348 + 0, 0, 0, 0, 0, 0, 0, 0, 23349 + 0, 0, 0, 0, 0, 0, 0, 0, 23350 + 0, 0, 0, 0, 0, 0, 0, 0, 23351 + 0, 0, 0, 0, 0, 0, 0, 0, 23352 + 0, 0, 0, 0, 0, 0, 0, 0, 23353 + 0, 0, 0, 0, 0, 0, 0, 0, 23354 + 0, 0, 0, 0, 0, 0, 0, 0, 23355 + 0, 0, 0, 0, 0, 0, 0, 0, 23356 + 0, 0, 0, 0, 0, 0, 0, 0, 23357 + 0, 0, 0, 0, 0, 0, 0, 0, 23358 + 0, 0, 0, 0, 0, 0, 0, 0, 23359 + 0, 0, 0, 0, 0, 0, 0, 0, 23360 + 0, 0, 0, 0, 0, 0, 0, 0, 23361 + 0, 0, 0, 0, 0, 0, 0, 0, 23362 + 0, 0, 0, 0, 0, 0, 0, 0, 23363 + 0, 0, 0, 0, 0, 0, 0, 0, 23364 + 0, 0, 0, 0, 0, 0, 0, 0, 23365 + 0, 0, 0, 0, 0, 0, 0, 0, 23366 + 0, 0, 0, 0, 0, 0, 0, 0, 23367 + 0, 0, 0, 0, 0, 0, 0, 0, 23368 + 0, 0, 0, 0, 0, 0, 0, 0, 23369 + 0, 0, 0, 0, 0, 0, 0, 0, 23370 + 0, 0, 0, 0, 0, 0, 0, 0, 23371 + 0, 0, 0, 0, 0, 0, 0, 0, 23372 + 0, 0, 0, 0, 0, 0, 0, 0, 23373 + 0, 0, 0, 0, 0, 0, 0, 0, 23374 + 0, 0, 0, 0, 0, 0, 0, 0, 23375 + 0, 0, 0, 0, 0, 0, 0, 0, 23376 + 0, 0, 0, 0, 0, 0, 0, 0, 23377 + 0, 0, 0, 0, 0, 0, 0, 0, 23378 + 0, 0, 0, 0, 0, 0, 0, 0, 23379 +}, 23380 +{ /* bi=5, bo=5 r=2.0:PSNR=74.031 */ 23381 + 0, 0, 0, 0, 0, 0, 0, 0, 23382 + 0, 0, 0, 0, 0, 0, 0, 0, 23383 + 0, 0, 0, 0, 0, 0, 0, 32, 23384 + 32, 32, 32, 32, 32, 32, 32, 32, 23385 + 32, 32, 32, 32, 32, 32, 32, 32, 23386 + 48, 48, 48, 48, 48, 48, 48, 48, 23387 + 48, 48, 48, 56, 56, 56, 56, 56, 23388 + 56, 56, 56, 56, 64, 64, 64, 64, 23389 + 64, 64, 64, 64, 72, 72, 72, 72, 23390 + 72, 72, 72, 72, 80, 80, 80, 80, 23391 + 80, 80, 88, 88, 88, 88, 88, 88, 23392 + 88, 88, 88, 88, 88, 88, 96, 96, 23393 + 96, 96, 96, 104, 104, 104, 104, 104, 23394 + 104, 104, 104, 104, 104, 112, 112, 112, 23395 + 112, 112, 112, 112, 112, 112, 120, 120, 23396 + 120, 120, 120, 120, 120, 120, 120, 120, 23397 + 0, -120, -120, -120, -120, -120, -120, -120, 23398 + -120, -120, -120, -112, -112, -112, -112, -112, 23399 + -112, -112, -112, -112, -104, -104, -104, -104, 23400 + -104, -104, -104, -104, -104, -104, -96, -96, 23401 + -96, -96, -96, -88, -88, -88, -88, -88, 23402 + -88, -88, -88, -88, -88, -88, -88, -80, 23403 + -80, -80, -80, -80, -80, -72, -72, -72, 23404 + -72, -72, -72, -72, -72, -64, -64, -64, 23405 + -64, -64, -64, -64, -64, -56, -56, -56, 23406 + -56, -56, -56, -56, -56, -56, -48, -48, 23407 + -48, -48, -48, -48, -48, -48, -48, -48, 23408 + -48, -32, -32, -32, -32, -32, -32, -32, 23409 + -32, -32, -32, -32, -32, -32, -32, -32, 23410 + -32, -32, 0, 0, 0, 0, 0, 0, 23411 + 0, 0, 0, 0, 0, 0, 0, 0, 23412 + 0, 0, 0, 0, 0, 0, 0, 0, 23413 +}, 23414 +{ /* bi=5, bo=4 r=2.0:PSNR=64.441 */ 23415 + 0, 0, 0, 0, 0, 0, 0, 0, 23416 + 0, 0, 0, 0, 0, 0, 0, 0, 23417 + 0, 0, 0, 0, 0, 0, 0, 0, 23418 + 0, 0, 0, 0, 0, 0, 0, 0, 23419 + 48, 48, 48, 48, 48, 48, 48, 48, 23420 + 48, 48, 48, 48, 48, 48, 48, 48, 23421 + 48, 48, 48, 48, 48, 48, 48, 48, 23422 + 64, 64, 64, 64, 64, 64, 64, 64, 23423 + 64, 64, 64, 64, 64, 64, 64, 64, 23424 + 80, 80, 80, 80, 80, 80, 80, 80, 23425 + 80, 80, 80, 80, 80, 88, 88, 88, 23426 + 88, 88, 88, 88, 88, 88, 88, 88, 23427 + 104, 104, 104, 104, 104, 104, 104, 104, 23428 + 104, 104, 104, 112, 112, 112, 112, 112, 23429 + 112, 112, 112, 112, 120, 120, 120, 120, 23430 + 120, 120, 120, 120, 120, 120, 120, 120, 23431 + 0, -120, -120, -120, -120, -120, -120, -120, 23432 + -120, -120, -120, -120, -120, -112, -112, -112, 23433 + -112, -112, -112, -112, -112, -112, -104, -104, 23434 + -104, -104, -104, -104, -104, -104, -104, -104, 23435 + -104, -88, -88, -88, -88, -88, -88, -88, 23436 + -88, -88, -88, -88, -80, -80, -80, -80, 23437 + -80, -80, -80, -80, -80, -80, -80, -80, 23438 + -80, -64, -64, -64, -64, -64, -64, -64, 23439 + -64, -64, -64, -64, -64, -64, -64, -64, 23440 + -64, -48, -48, -48, -48, -48, -48, -48, 23441 + -48, -48, -48, -48, -48, -48, -48, -48, 23442 + -48, -48, -48, -48, -48, -48, -48, -48, 23443 + -48, 0, 0, 0, 0, 0, 0, 0, 23444 + 0, 0, 0, 0, 0, 0, 0, 0, 23445 + 0, 0, 0, 0, 0, 0, 0, 0, 23446 + 0, 0, 0, 0, 0, 0, 0, 0, 23447 +}, 23448 +{ /* bi=5, bo=2 r=2.0:PSNR=43.175 */ 23449 + 0, 0, 0, 0, 0, 0, 0, 0, 23450 + 0, 0, 0, 0, 0, 0, 0, 0, 23451 + 0, 0, 0, 0, 0, 0, 0, 0, 23452 + 0, 0, 0, 0, 0, 0, 0, 0, 23453 + 0, 0, 0, 0, 0, 0, 0, 0, 23454 + 0, 0, 0, 0, 0, 0, 0, 0, 23455 + 0, 0, 0, 0, 0, 0, 0, 0, 23456 + 0, 0, 0, 0, 0, 0, 0, 0, 23457 + 88, 88, 88, 88, 88, 88, 88, 88, 23458 + 88, 88, 88, 88, 88, 88, 88, 88, 23459 + 88, 88, 88, 88, 88, 88, 88, 88, 23460 + 88, 88, 88, 88, 88, 88, 88, 88, 23461 + 88, 88, 88, 88, 88, 88, 88, 88, 23462 + 88, 88, 88, 88, 88, 88, 88, 88, 23463 + 88, 88, 88, 88, 88, 88, 88, 88, 23464 + 88, 88, 88, 88, 88, 88, 88, 88, 23465 + 0, -88, -88, -88, -88, -88, -88, -88, 23466 + -88, -88, -88, -88, -88, -88, -88, -88, 23467 + -88, -88, -88, -88, -88, -88, -88, -88, 23468 + -88, -88, -88, -88, -88, -88, -88, -88, 23469 + -88, -88, -88, -88, -88, -88, -88, -88, 23470 + -88, -88, -88, -88, -88, -88, -88, -88, 23471 + -88, -88, -88, -88, -88, -88, -88, -88, 23472 + -88, -88, -88, -88, -88, -88, -88, -88, 23473 + -88, 0, 0, 0, 0, 0, 0, 0, 23474 + 0, 0, 0, 0, 0, 0, 0, 0, 23475 + 0, 0, 0, 0, 0, 0, 0, 0, 23476 + 0, 0, 0, 0, 0, 0, 0, 0, 23477 + 0, 0, 0, 0, 0, 0, 0, 0, 23478 + 0, 0, 0, 0, 0, 0, 0, 0, 23479 + 0, 0, 0, 0, 0, 0, 0, 0, 23480 + 0, 0, 0, 0, 0, 0, 0, 0, 23481 +} 23482 +}; 23483 +const static signed char* zywrleParam[3][3][3]={ 23484 + {{zywrleConv[0],zywrleConv[2],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}}, 23485 + {{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}}, 23486 + {{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[2],zywrleConv[2],zywrleConv[2]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]}}, 23487 +}; 23488 +# endif 23489 +#endif 23490 + 23491 +static InlineX void Harr(signed char* pX0, signed char* pX1) 23492 +{ 23493 + /* Piecewise-Linear Harr(PLHarr) */ 23494 + int X0 = (int)*pX0, X1 = (int)*pX1; 23495 + int orgX0 = X0, orgX1 = X1; 23496 + if ((X0 ^ X1) & 0x80) { 23497 + /* differ sign */ 23498 + X1 += X0; 23499 + if (((X1^orgX1)&0x80)==0) { 23500 + /* |X1| > |X0| */ 23501 + X0 -= X1; /* H = -B */ 23502 + } 23503 + } else { 23504 + /* same sign */ 23505 + X0 -= X1; 23506 + if (((X0 ^ orgX0) & 0x80) == 0) { 23507 + /* |X0| > |X1| */ 23508 + X1 += X0; /* L = A */ 23509 + } 23510 + } 23511 + *pX0 = (signed char)X1; 23512 + *pX1 = (signed char)X0; 23513 +} 23514 +/* 23515 + 1D-Wavelet transform. 23516 + 23517 + In coefficients array, the famous 'pyramid' decomposition is well used. 23518 + 23519 + 1D Model: 23520 + |L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0 23521 + |L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1 23522 + 23523 + But this method needs line buffer because H/L is different position from X0/X1. 23524 + So, I used 'interleave' decomposition instead of it. 23525 + 23526 + 1D Model: 23527 + |L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0 23528 + |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1 23529 + 23530 + In this method, H/L and X0/X1 is always same position. 23531 + This lead us to more speed and less memory. 23532 + Of cause, the result of both method is quite same 23533 + because it's only difference that coefficient position. 23534 +*/ 23535 +static InlineX void WaveletLevel(int* data, int size, int l, int SkipPixel) 23536 +{ 23537 + int s, ofs; 23538 + signed char* pX0; 23539 + signed char* end; 23540 + 23541 + pX0 = (signed char*)data; 23542 + s = (8<<l)*SkipPixel; 23543 + end = pX0+(size>>(l+1))*s; 23544 + s -= 2; 23545 + ofs = (4<<l)*SkipPixel; 23546 + while (pX0 < end) { 23547 + Harr(pX0, pX0+ofs); 23548 + pX0++; 23549 + Harr(pX0, pX0+ofs); 23550 + pX0++; 23551 + Harr(pX0, pX0+ofs); 23552 + pX0 += s; 23553 + } 23554 +} 23555 +#define InvWaveletLevel(d,s,l,pix) WaveletLevel(d,s,l,pix) 23556 + 23557 +#ifdef ZYWRLE_ENCODE 23558 +# ifndef ZYWRLE_QUANTIZE 23559 +/* Type A:lower bit omitting of EZW style. */ 23560 +static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l) 23561 +{ 23562 + int r, s; 23563 + int x, y; 23564 + int* pH; 23565 + const unsigned int* pM; 23566 + 23567 + pM = &(zywrleParam[level-1][l]); 23568 + s = 2<<l; 23569 + for (r = 1; r < 4; r++) { 23570 + pH = pBuf; 23571 + if (r & 0x01) 23572 + pH += s>>1; 23573 + if (r & 0x02) 23574 + pH += (s>>1)*width; 23575 + for (y = 0; y < height / s; y++) { 23576 + for (x = 0; x < width / s; x++) { 23577 + /* 23578 + these are same following code. 23579 + pH[x] = pH[x] / (~pM[x]+1) * (~pM[x]+1); 23580 + ( round pH[x] with pM[x] bit ) 23581 + '&' operator isn't 'round' but is 'floor'. 23582 + So, we must offset when pH[x] is negative. 23583 + */ 23584 + if (((signed char*)pH)[0] & 0x80) 23585 + ((signed char*)pH)[0] += ~((signed char*)pM)[0]; 23586 + if (((signed char*)pH)[1] & 0x80) 23587 + ((signed char*)pH)[1] += ~((signed char*)pM)[1]; 23588 + if (((signed char*)pH)[2] & 0x80) 23589 + ((signed char*)pH)[2] += ~((signed char*)pM)[2]; 23590 + *pH &= *pM; 23591 + pH += s; 23592 + } 23593 + pH += (s-1)*width; 23594 + } 23595 + } 23596 +} 23597 +# else 23598 +/* 23599 + Type B:Non liner quantization filter. 23600 + 23601 + Coefficients have Gaussian curve and smaller value which is 23602 + large part of coefficients isn't more important than larger value. 23603 + So, I use filter of Non liner quantize/dequantize table. 23604 + In general, Non liner quantize formula is explained as following. 23605 + 23606 + y=f(x) = sign(x)*round( ((abs(x)/(2^7))^ r )* 2^(bo-1) )*2^(8-bo) 23607 + x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi) 23608 + ( r:power coefficient bi:effective MSB in input bo:effective MSB in output ) 23609 + 23610 + r < 1.0 : Smaller value is more important than larger value. 23611 + r > 1.0 : Larger value is more important than smaller value. 23612 + r = 1.0 : Liner quantization which is same with EZW style. 23613 + 23614 + r = 0.75 is famous non liner quantization used in MP3 audio codec. 23615 + In contrast to audio data, larger value is important in wavelet coefficients. 23616 + So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ). 23617 + 23618 + As compared with EZW style liner quantization, this filter tended to be 23619 + more sharp edge and be more compression rate but be more blocking noise and be less quality. 23620 + Especially, the surface of graphic objects has distinguishable noise in middle quality mode. 23621 + 23622 + We need only quantized-dequantized(filtered) value rather than quantized value itself 23623 + because all values are packed or palette-lized in later ZRLE section. 23624 + This lead us not to need to modify client decoder when we change 23625 + the filtering procedure in future. 23626 + Client only decodes coefficients given by encoder. 23627 +*/ 23628 +static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l) 23629 +{ 23630 + int r, s; 23631 + int x, y; 23632 + int* pH; 23633 + const signed char** pM; 23634 + 23635 + pM = zywrleParam[level-1][l]; 23636 + s = 2<<l; 23637 + for (r = 1; r < 4; r++) { 23638 + pH = pBuf; 23639 + if (r & 0x01) 23640 + pH += s>>1; 23641 + if (r & 0x02) 23642 + pH += (s>>1)*width; 23643 + for (y = 0; y < height / s; y++) { 23644 + for (x = 0; x < width / s; x++) { 23645 + ((signed char*)pH)[0] = pM[0][((unsigned char*)pH)[0]]; 23646 + ((signed char*)pH)[1] = pM[1][((unsigned char*)pH)[1]]; 23647 + ((signed char*)pH)[2] = pM[2][((unsigned char*)pH)[2]]; 23648 + pH += s; 23649 + } 23650 + pH += (s-1)*width; 23651 + } 23652 + } 23653 +} 23654 +# endif 23655 + 23656 +static InlineX void Wavelet(int* pBuf, int width, int height, int level) 23657 +{ 23658 + int l, s; 23659 + int* pTop; 23660 + int* pEnd; 23661 + 23662 + for (l = 0; l < level; l++) { 23663 + pTop = pBuf; 23664 + pEnd = pBuf+height*width; 23665 + s = width<<l; 23666 + while (pTop < pEnd) { 23667 + WaveletLevel(pTop, width, l, 1); 23668 + pTop += s; 23669 + } 23670 + pTop = pBuf; 23671 + pEnd = pBuf+width; 23672 + s = 1<<l; 23673 + while (pTop < pEnd) { 23674 + WaveletLevel(pTop, height,l, width); 23675 + pTop += s; 23676 + } 23677 + FilterWaveletSquare(pBuf, width, height, level, l); 23678 + } 23679 +} 23680 +#endif 23681 +#ifdef ZYWRLE_DECODE 23682 +static InlineX void InvWavelet(int* pBuf, int width, int height, int level) 23683 +{ 23684 + int l, s; 23685 + int* pTop; 23686 + int* pEnd; 23687 + 23688 + for (l = level - 1; l >= 0; l--) { 23689 + pTop = pBuf; 23690 + pEnd = pBuf+width; 23691 + s = 1<<l; 23692 + while (pTop < pEnd) { 23693 + InvWaveletLevel(pTop, height,l, width); 23694 + pTop += s; 23695 + } 23696 + pTop = pBuf; 23697 + pEnd = pBuf+height*width; 23698 + s = width<<l; 23699 + while (pTop < pEnd) { 23700 + InvWaveletLevel(pTop, width, l, 1); 23701 + pTop += s; 23702 + } 23703 + } 23704 +} 23705 +#endif 23706 + 23707 +/* Load/Save coefficients stuffs. 23708 + Coefficients manages as 24 bits little-endian pixel. */ 23709 +#define ZYWRLE_LOAD_COEFF(pSrc,R,G,B) { \ 23710 + R = ((signed char*)pSrc)[2]; \ 23711 + G = ((signed char*)pSrc)[1]; \ 23712 + B = ((signed char*)pSrc)[0]; \ 23713 +} 23714 +#define ZYWRLE_SAVE_COEFF(pDst,R,G,B) { \ 23715 + ((signed char*)pDst)[2] = (signed char)R; \ 23716 + ((signed char*)pDst)[1] = (signed char)G; \ 23717 + ((signed char*)pDst)[0] = (signed char)B; \ 23718 +} 23719 + 23720 +/* 23721 + RGB <=> YUV conversion stuffs. 23722 + YUV coversion is explained as following formula in strict meaning: 23723 + Y = 0.299R + 0.587G + 0.114B ( 0<=Y<=255) 23724 + U = -0.169R - 0.331G + 0.500B (-128<=U<=127) 23725 + V = 0.500R - 0.419G - 0.081B (-128<=V<=127) 23726 + 23727 + I use simple conversion RCT(reversible color transform) which is described 23728 + in JPEG-2000 specification. 23729 + Y = (R + 2G + B)/4 ( 0<=Y<=255) 23730 + U = B-G (-256<=U<=255) 23731 + V = R-G (-256<=V<=255) 23732 +*/ 23733 +#define ROUND(x) (((x)<0)?0:(((x)>255)?255:(x))) 23734 + /* RCT is N-bit RGB to N-bit Y and N+1-bit UV. 23735 + For make Same N-bit, UV is lossy. 23736 + More exact PLHarr, we reduce to odd range(-127<=x<=127). */ 23737 +#define ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ymask,uvmask) { \ 23738 + Y = (R+(G<<1)+B)>>2; \ 23739 + U = B-G; \ 23740 + V = R-G; \ 23741 + Y -= 128; \ 23742 + U >>= 1; \ 23743 + V >>= 1; \ 23744 + Y &= ymask; \ 23745 + U &= uvmask; \ 23746 + V &= uvmask; \ 23747 + if (Y == -128) \ 23748 + Y += (0xFFFFFFFF-ymask+1); \ 23749 + if (U == -128) \ 23750 + U += (0xFFFFFFFF-uvmask+1); \ 23751 + if (V == -128) \ 23752 + V += (0xFFFFFFFF-uvmask+1); \ 23753 +} 23754 +#define ZYWRLE_YUVRGB1(R,G,B,Y,U,V) { \ 23755 + Y += 128; \ 23756 + U <<= 1; \ 23757 + V <<= 1; \ 23758 + G = Y-((U+V)>>2); \ 23759 + B = U+G; \ 23760 + R = V+G; \ 23761 + G = ROUND(G); \ 23762 + B = ROUND(B); \ 23763 + R = ROUND(R); \ 23764 +} 23765 + 23766 +/* 23767 + coefficient packing/unpacking stuffs. 23768 + Wavelet transform makes 4 sub coefficient image from 1 original image. 23769 + 23770 + model with pyramid decomposition: 23771 + +------+------+ 23772 + | | | 23773 + | L | Hx | 23774 + | | | 23775 + +------+------+ 23776 + | | | 23777 + | H | Hxy | 23778 + | | | 23779 + +------+------+ 23780 + 23781 + So, we must transfer each sub images individually in strict meaning. 23782 + But at least ZRLE meaning, following one decompositon image is same as 23783 + avobe individual sub image. I use this format. 23784 + (Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L) 23785 + for simplified procedure for any wavelet level.) 23786 + 23787 + +------+------+ 23788 + | L | 23789 + +------+------+ 23790 + | Hx | 23791 + +------+------+ 23792 + | Hy | 23793 + +------+------+ 23794 + | Hxy | 23795 + +------+------+ 23796 +*/ 23797 +#define INC_PTR(data) \ 23798 + data++; \ 23799 + if( data-pData >= (w+uw) ){ \ 23800 + data += scanline-(w+uw); \ 23801 + pData = data; \ 23802 + } 23803 + 23804 +#define ZYWRLE_TRANSFER_COEFF(pBuf,data,r,w,h,scanline,level,TRANS) \ 23805 + pH = pBuf; \ 23806 + s = 2<<level; \ 23807 + if (r & 0x01) \ 23808 + pH += s>>1; \ 23809 + if (r & 0x02) \ 23810 + pH += (s>>1)*w; \ 23811 + pEnd = pH+h*w; \ 23812 + while (pH < pEnd) { \ 23813 + pLine = pH+w; \ 23814 + while (pH < pLine) { \ 23815 + TRANS \ 23816 + INC_PTR(data) \ 23817 + pH += s; \ 23818 + } \ 23819 + pH += (s-1)*w; \ 23820 + } 23821 + 23822 +#define ZYWRLE_PACK_COEFF(pBuf,data,r,width,height,scanline,level) \ 23823 + ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_COEFF(pH,R,G,B);ZYWRLE_SAVE_PIXEL(data,R,G,B);) 23824 + 23825 +#define ZYWRLE_UNPACK_COEFF(pBuf,data,r,width,height,scanline,level) \ 23826 + ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_PIXEL(data,R,G,B);ZYWRLE_SAVE_COEFF(pH,R,G,B);) 23827 + 23828 +#define ZYWRLE_SAVE_UNALIGN(data,TRANS) \ 23829 + pTop = pBuf+w*h; \ 23830 + pEnd = pBuf + (w+uw)*(h+uh); \ 23831 + while (pTop < pEnd) { \ 23832 + TRANS \ 23833 + INC_PTR(data) \ 23834 + pTop++; \ 23835 + } 23836 + 23837 +#define ZYWRLE_LOAD_UNALIGN(data,TRANS) \ 23838 + pTop = pBuf+w*h; \ 23839 + if (uw) { \ 23840 + pData= data + w; \ 23841 + pEnd = (int*)(pData+ h*scanline); \ 23842 + while (pData < (PIXEL_T*)pEnd) { \ 23843 + pLine = (int*)(pData + uw); \ 23844 + while (pData < (PIXEL_T*)pLine) { \ 23845 + TRANS \ 23846 + pData++; \ 23847 + pTop++; \ 23848 + } \ 23849 + pData += scanline-uw; \ 23850 + } \ 23851 + } \ 23852 + if (uh) { \ 23853 + pData= data + h*scanline; \ 23854 + pEnd = (int*)(pData+ uh*scanline); \ 23855 + while (pData < (PIXEL_T*)pEnd) { \ 23856 + pLine = (int*)(pData + w); \ 23857 + while (pData < (PIXEL_T*)pLine) { \ 23858 + TRANS \ 23859 + pData++; \ 23860 + pTop++; \ 23861 + } \ 23862 + pData += scanline-w; \ 23863 + } \ 23864 + } \ 23865 + if (uw && uh) { \ 23866 + pData= data + w+ h*scanline; \ 23867 + pEnd = (int*)(pData+ uh*scanline); \ 23868 + while (pData < (PIXEL_T*)pEnd) { \ 23869 + pLine = (int*)(pData + uw); \ 23870 + while (pData < (PIXEL_T*)pLine) { \ 23871 + TRANS \ 23872 + pData++; \ 23873 + pTop++; \ 23874 + } \ 23875 + pData += scanline-uw; \ 23876 + } \ 23877 + } 23878 + 23879 +static InlineX void zywrleCalcSize(int* pW, int* pH, int level) 23880 +{ 23881 + *pW &= ~((1<<level)-1); 23882 + *pH &= ~((1<<level)-1); 23883 +} 23884 + 23885 +#endif /* ZYWRLE_ONCE */ 23886 + 23887 +#ifndef CPIXEL 23888 +#ifdef ZYWRLE_ENCODE 23889 +static InlineX void ZYWRLE_RGBYUV(int* pBuf, PIXEL_T* data, int width, int height, int scanline) 23890 +{ 23891 + int R, G, B; 23892 + int Y, U, V; 23893 + int* pLine; 23894 + int* pEnd; 23895 + pEnd = pBuf+height*width; 23896 + while (pBuf < pEnd) { 23897 + pLine = pBuf+width; 23898 + while (pBuf < pLine) { 23899 + ZYWRLE_LOAD_PIXEL(data,R,G,B); 23900 + ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ZYWRLE_YMASK,ZYWRLE_UVMASK); 23901 + ZYWRLE_SAVE_COEFF(pBuf,V,Y,U); 23902 + pBuf++; 23903 + data++; 23904 + } 23905 + data += scanline-width; 23906 + } 23907 +} 23908 +#endif 23909 +#ifdef ZYWRLE_DECODE 23910 +static InlineX void ZYWRLE_YUVRGB(int* pBuf, PIXEL_T* data, int width, int height, int scanline) { 23911 + int R, G, B; 23912 + int Y, U, V; 23913 + int* pLine; 23914 + int* pEnd; 23915 + pEnd = pBuf+height*width; 23916 + while (pBuf < pEnd) { 23917 + pLine = pBuf+width; 23918 + while (pBuf < pLine) { 23919 + ZYWRLE_LOAD_COEFF(pBuf,V,Y,U); 23920 + ZYWRLE_YUVRGB1(R,G,B,Y,U,V); 23921 + ZYWRLE_SAVE_PIXEL(data,R,G,B); 23922 + pBuf++; 23923 + data++; 23924 + } 23925 + data += scanline-width; 23926 + } 23927 +} 23928 +#endif 23929 + 23930 +#ifdef ZYWRLE_ENCODE 23931 +PIXEL_T* ZYWRLE_ANALYZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf) { 23932 + int l; 23933 + int uw = w; 23934 + int uh = h; 23935 + int* pTop; 23936 + int* pEnd; 23937 + int* pLine; 23938 + PIXEL_T* pData; 23939 + int R, G, B; 23940 + int s; 23941 + int* pH; 23942 + 23943 + zywrleCalcSize(&w, &h, level); 23944 + if (w == 0 || h == 0) 23945 + return NULL; 23946 + uw -= w; 23947 + uh -= h; 23948 + 23949 + pData = dst; 23950 + ZYWRLE_LOAD_UNALIGN(src,*(PIXEL_T*)pTop=*pData;) 23951 + ZYWRLE_RGBYUV(pBuf, src, w, h, scanline); 23952 + Wavelet(pBuf, w, h, level); 23953 + for (l = 0; l < level; l++) { 23954 + ZYWRLE_PACK_COEFF(pBuf, dst, 3, w, h, scanline, l); 23955 + ZYWRLE_PACK_COEFF(pBuf, dst, 2, w, h, scanline, l); 23956 + ZYWRLE_PACK_COEFF(pBuf, dst, 1, w, h, scanline, l); 23957 + if (l == level - 1) { 23958 + ZYWRLE_PACK_COEFF(pBuf, dst, 0, w, h, scanline, l); 23959 + } 23960 + } 23961 + ZYWRLE_SAVE_UNALIGN(dst,*dst=*(PIXEL_T*)pTop;) 23962 + return dst; 23963 +} 23964 +#endif 23965 +#ifdef ZYWRLE_DECODE 23966 +PIXEL_T* ZYWRLE_SYNTHESIZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf) 23967 +{ 23968 + int l; 23969 + int uw = w; 23970 + int uh = h; 23971 + int* pTop; 23972 + int* pEnd; 23973 + int* pLine; 23974 + PIXEL_T* pData; 23975 + int R, G, B; 23976 + int s; 23977 + int* pH; 23978 + 23979 + zywrleCalcSize(&w, &h, level); 23980 + if (w == 0 || h == 0) 23981 + return NULL; 23982 + uw -= w; 23983 + uh -= h; 23984 + 23985 + pData = src; 23986 + for (l = 0; l < level; l++) { 23987 + ZYWRLE_UNPACK_COEFF(pBuf, src, 3, w, h, scanline, l); 23988 + ZYWRLE_UNPACK_COEFF(pBuf, src, 2, w, h, scanline, l); 23989 + ZYWRLE_UNPACK_COEFF(pBuf, src, 1, w, h, scanline, l); 23990 + if (l == level - 1) { 23991 + ZYWRLE_UNPACK_COEFF(pBuf, src, 0, w, h, scanline, l); 23992 + } 23993 + } 23994 + ZYWRLE_SAVE_UNALIGN(src,*(PIXEL_T*)pTop=*src;) 23995 + InvWavelet(pBuf, w, h, level); 23996 + ZYWRLE_YUVRGB(pBuf, dst, w, h, scanline); 23997 + ZYWRLE_LOAD_UNALIGN(dst,*pData=*(PIXEL_T*)pTop;) 23998 + return src; 23999 +} 24000 +#endif 24001 +#endif /* CPIXEL */ 24002 + 24003 +#undef ZYWRLE_RGBYUV 24004 +#undef ZYWRLE_YUVRGB 24005 +#undef ZYWRLE_LOAD_PIXEL 24006 +#undef ZYWRLE_SAVE_PIXEL 24007 diff -Naur -X ./exclude vnc_unixsrc.orig/include/rfbproto.h vnc_unixsrc/include/rfbproto.h 24008 --- vnc_unixsrc.orig/include/rfbproto.h 2004-05-27 03:02:02.000000000 -0400 24009 +++ vnc_unixsrc/include/rfbproto.h 2010-02-25 21:54:58.000000000 -0500 24010 @@ -205,7 +205,22 @@ 24011 #define rfbSecTypeInvalid 0 24012 #define rfbSecTypeNone 1 24013 #define rfbSecTypeVncAuth 2 24014 +#define rfbSecTypeRA2 5 24015 +#define rfbSecTypeRA2ne 6 24016 #define rfbSecTypeTight 16 24017 +#define rfbSecTypeUltra 17 24018 + 24019 +/* try to support VeNCrypt and TLS */ 24020 +#define rfbSecTypeAnonTls 18 24021 +#define rfbSecTypeVencrypt 19 24022 + 24023 +#define rfbVencryptPlain 256 24024 +#define rfbVencryptTlsNone 257 24025 +#define rfbVencryptTlsVnc 258 24026 +#define rfbVencryptTlsPlain 259 24027 +#define rfbVencryptX509None 260 24028 +#define rfbVencryptX509Vnc 261 24029 +#define rfbVencryptX509Plain 262 24030 24031 24032 /*----------------------------------------------------------------------------- 24033 @@ -381,6 +396,11 @@ 24034 #define rfbBell 2 24035 #define rfbServerCutText 3 24036 24037 +#define rfbResizeFrameBuffer 4 /* Modif sf@2002 */ 24038 + 24039 +/* http://sourceforge.net/projects/vncsessmgr */ 24040 +#define rfbRestartConnection 82 24041 + 24042 #define rfbFileListData 130 24043 #define rfbFileDownloadData 131 24044 #define rfbFileUploadCancel 132 24045 @@ -403,6 +423,18 @@ 24046 #define rfbPointerEvent 5 24047 #define rfbClientCutText 6 24048 24049 +/* ultra */ 24050 + 24051 +#define rfbFileTransfer 7 24052 +#define rfbSetScale 8 24053 +#define rfbSetServerInput 9 24054 +#define rfbSetSW 10 24055 +#define rfbTextChat 11 24056 +#define rfbKeyFrameRequest 12 24057 +#define rfbPalmVNCSetScaleFactor 0xF 24058 + 24059 + 24060 + 24061 #define rfbFileListRequest 130 24062 #define rfbFileDownloadRequest 131 24063 #define rfbFileUploadRequest 132 24064 @@ -435,6 +467,13 @@ 24065 #define rfbEncodingTight 7 24066 #define rfbEncodingZlibHex 8 24067 24068 +#define rfbEncodingZRLE 16 24069 +/* 24070 +nyama/2006/08/02:new YUV-Wavlet lossy codec based on ZRLE (ZYWRLE) 24071 + */ 24072 +#define rfbEncodingZYWRLE 17 24073 + 24074 + 24075 /* signatures for basic encoding types */ 24076 #define sig_rfbEncodingRaw "RAW_____" 24077 #define sig_rfbEncodingCopyRect "COPYRECT" 24078 @@ -955,6 +994,51 @@ 24079 #define sz_rfbFileDownloadFailedMsg 4 24080 24081 /*----------------------------------------------------------------------------- 24082 + * RestartConnection - the server has restarted the client connection. 24083 + */ 24084 + 24085 +typedef struct _rfbRestartConnectionMsg { 24086 + CARD8 type; /* always rfbRestartConnection */ 24087 + CARD8 pad1; 24088 + CARD16 pad2; 24089 + CARD32 length; 24090 + /* followed by char text[length] */ 24091 +} rfbRestartConnectionMsg; 24092 + 24093 +#define sz_rfbRestartConnectionMsg 8 24094 + 24095 + 24096 +typedef struct _rfbTextChatMsg { 24097 + CARD8 type; /* always rfbTextChat */ 24098 + CARD8 pad1; /* Could be used later as an additionnal param */ 24099 + CARD16 pad2; /* Could be used later as text offset, for instance */ 24100 + CARD32 length; /* Specific values for Open, close, finished (-1, -2, -3) */ 24101 + /* followed by char text[length] */ 24102 +} rfbTextChatMsg; 24103 + 24104 +#define sz_rfbTextChatMsg 8 24105 + 24106 +#define rfbTextMaxSize 4096 24107 +#define rfbTextChatOpen 0xFFFFFFFF 24108 +#define rfbTextChatClose 0xFFFFFFFE 24109 +#define rfbTextChatFinished 0xFFFFFFFD 24110 + 24111 +/*----------------------------------------------------------------------------- 24112 + * Modif sf@2002 24113 + * ResizeFrameBuffer - The Client must change the size of its framebuffer 24114 + */ 24115 + 24116 +typedef struct _rfbResizeFrameBufferMsg { 24117 + CARD8 type; /* always rfbResizeFrameBuffer */ 24118 + CARD8 pad1; 24119 + CARD16 framebufferWidth; /* FrameBuffer width */ 24120 + CARD16 framebufferHeight; /* FrameBuffer height */ 24121 +} rfbResizeFrameBufferMsg; 24122 + 24123 +#define sz_rfbResizeFrameBufferMsg 6 24124 + 24125 + 24126 +/*----------------------------------------------------------------------------- 24127 * Union of all server->client messages. 24128 */ 24129 24130 @@ -968,6 +1052,8 @@ 24131 rfbFileDownloadDataMsg fdd; 24132 rfbFileUploadCancelMsg fuc; 24133 rfbFileDownloadFailedMsg fdf; 24134 + rfbRestartConnectionMsg rc; 24135 + rfbTextChatMsg tc; 24136 } rfbServerToClientMsg; 24137 24138 24139 @@ -1221,6 +1307,41 @@ 24140 24141 #define sz_rfbFileCreateDirRequestMsg 4 24142 24143 +/* ultra */ 24144 +typedef struct _rfbSetScaleMsg { 24145 + CARD8 type; /* always rfbSetScale */ 24146 + CARD8 scale; /* Scale value 1<sv<n */ 24147 + CARD16 pad; 24148 +} rfbSetScaleMsg; 24149 + 24150 +#define sz_rfbSetScaleMsg 4 24151 + 24152 +typedef struct { 24153 + CARD8 type; /* always rfbSetScaleFactor */ 24154 + 24155 + CARD8 scale; /* Scale factor (positive non-zero integer) */ 24156 + CARD16 pad2; 24157 +} rfbPalmVNCSetScaleFactorMsg; 24158 + 24159 +#define sz_rfbPalmVNCSetScaleFactorMsg (4) 24160 + 24161 +typedef struct _rfbSetServerInputMsg { 24162 + CARD8 type; /* always rfbSetServerInputMsg */ 24163 + CARD8 status; /* on or off */ 24164 + CARD16 pad; 24165 +} rfbSetServerInputMsg; 24166 + 24167 +#define sz_rfbSetServerInputMsg 4 24168 + 24169 +typedef struct _rfbSetSWMsg { 24170 + CARD8 type; /* always rfbSetSW */ 24171 + CARD8 status; 24172 + CARD16 x; 24173 + CARD16 y; 24174 +} rfbSetSWMsg; 24175 + 24176 +#define sz_rfbSetSWMsg 6 24177 + 24178 /*----------------------------------------------------------------------------- 24179 * Union of all client->server messages. 24180 */ 24181 @@ -1241,4 +1362,9 @@ 24182 rfbFileDownloadCancelMsg fdc; 24183 rfbFileUploadFailedMsg fuf; 24184 rfbFileCreateDirRequestMsg fcdr; 24185 + rfbSetScaleMsg ssc; 24186 + rfbPalmVNCSetScaleFactorMsg pssf; 24187 + rfbSetServerInputMsg sim; 24188 + rfbSetSWMsg sw; 24189 + rfbTextChatMsg tc; 24190 } rfbClientToServerMsg; 24191 diff -Naur -X ./exclude vnc_unixsrc.orig/include/vncauth.h vnc_unixsrc/include/vncauth.h 24192 --- vnc_unixsrc.orig/include/vncauth.h 2000-06-11 08:00:53.000000000 -0400 24193 +++ vnc_unixsrc/include/vncauth.h 2009-03-21 00:37:23.000000000 -0400 24194 @@ -23,8 +23,11 @@ 24195 24196 #define MAXPWLEN 8 24197 #define CHALLENGESIZE 16 24198 +#define CHALLENGESIZE_MSLOGON 64 24199 24200 extern int vncEncryptAndStorePasswd(char *passwd, char *fname); 24201 extern char *vncDecryptPasswdFromFile(char *fname); 24202 extern void vncRandomBytes(unsigned char *bytes); 24203 extern void vncEncryptBytes(unsigned char *bytes, char *passwd); 24204 + 24205 +extern void vncEncryptPasswd_MSLOGON(unsigned char *encryptedPasswd, char *passwd); 24206 diff -Naur -X ./exclude vnc_unixsrc.orig/libvncauth/d3des.c vnc_unixsrc/libvncauth/d3des.c 24207 --- vnc_unixsrc.orig/libvncauth/d3des.c 2000-06-11 08:00:53.000000000 -0400 24208 +++ vnc_unixsrc/libvncauth/d3des.c 2010-02-25 21:49:02.000000000 -0500 24209 @@ -34,12 +34,15 @@ 24210 static void cookey(unsigned long *); 24211 24212 static unsigned long KnL[32] = { 0L }; 24213 +/* no londer used: */ 24214 +#if 0 24215 static unsigned long KnR[32] = { 0L }; 24216 static unsigned long Kn3[32] = { 0L }; 24217 static unsigned char Df_Key[24] = { 24218 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 24219 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, 24220 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; 24221 +#endif 24222 24223 static unsigned short bytebit[8] = { 24224 01, 02, 04, 010, 020, 040, 0100, 0200 }; 24225 diff -Naur -X ./exclude vnc_unixsrc.orig/libvncauth/vncauth.c vnc_unixsrc/libvncauth/vncauth.c 24226 --- vnc_unixsrc.orig/libvncauth/vncauth.c 2003-03-01 11:48:06.000000000 -0500 24227 +++ vnc_unixsrc/libvncauth/vncauth.c 2010-02-25 21:47:25.000000000 -0500 24228 @@ -27,9 +27,11 @@ 24229 #include <sys/types.h> 24230 #include <sys/stat.h> 24231 #include <unistd.h> 24232 +#include <time.h> 24233 #include <vncauth.h> 24234 #include <d3des.h> 24235 24236 +#include <fcntl.h> 24237 24238 /* 24239 * Make sure we call srandom() only once. 24240 @@ -45,6 +47,8 @@ 24241 24242 static unsigned char s_fixedkey[8] = {23,82,107,6,35,78,88,7}; 24243 24244 +int vncEncryptAndStorePasswd2(char *passwd, char *passwdViewOnly, char *fname); 24245 +int vncDecryptPasswdFromFile2(char *fname, char *passwdFullControl, char *passwdViewOnly); 24246 24247 /* 24248 * Encrypt a password and store it in a file. Returns 0 if successful, 24249 @@ -73,7 +77,7 @@ 24250 vncEncryptAndStorePasswd2(char *passwd, char *passwdViewOnly, char *fname) 24251 { 24252 FILE *fp; 24253 - int i, bytesToWrite, bytesWrote; 24254 + int bytesToWrite, bytesWrote; 24255 unsigned char encryptedPasswd[16] = { 24256 0,0,0,0,0,0,0,0, 24257 0,0,0,0,0,0,0,0 24258 @@ -195,6 +199,44 @@ 24259 return (i < 16) ? 1 : 2; 24260 } 24261 24262 +unsigned int urandom(void) { 24263 + unsigned int val = 0; 24264 + struct stat sb; 24265 + int fd = -1; 24266 + if (fd < 0 && stat("/dev/urandom", &sb) == 0) { 24267 + fd = open("/dev/urandom", O_RDONLY); 24268 + } 24269 + if (fd < 0 && stat("/dev/random", &sb) == 0) { 24270 + fd = open("/dev/random", O_RDONLY); 24271 + } 24272 + if (fd < 0 && stat("/proc/loadavg", &sb) == 0) { 24273 + fd = open("/proc/loadavg", O_RDONLY); 24274 + } 24275 + if (fd < 0 && stat("/bin/bash", &sb) == 0) { 24276 + fd = open("/bin/bash", O_RDONLY); 24277 + lseek(fd, (off_t) (unsigned int) getpid(), SEEK_SET); 24278 + } 24279 + if (fd >= 0) { 24280 + int i; 24281 + for (i=0; i < 3; i++) { 24282 + char buf[2]; 24283 + if (read(fd, buf, 1) > 0) { 24284 + unsigned char uc = (unsigned char) buf[0]; 24285 + if (i==0) { 24286 + val += uc; 24287 + } else if (i==1) { 24288 + val += uc * 256; 24289 + } else if (i==2) { 24290 + val += uc * 256 * 256; 24291 + } 24292 + } 24293 + } 24294 + close(fd); 24295 + } else { 24296 + val = (unsigned int) getpid(); 24297 + } 24298 + return val; 24299 +} 24300 24301 /* 24302 * Generate CHALLENGESIZE random bytes for use in challenge-response 24303 @@ -207,11 +249,13 @@ 24304 int i; 24305 unsigned int seed; 24306 24307 - if (!s_srandom_called) { 24308 - seed = (unsigned int)time(0) ^ (unsigned int)getpid(); 24309 - srandom(seed); 24310 - s_srandom_called = 1; 24311 - } 24312 + if (!s_srandom_called) { 24313 + seed = (unsigned int)time(0) ^ (unsigned int)getpid(); 24314 + seed += urandom(); 24315 + 24316 + srandom(seed); 24317 + s_srandom_called = 1; 24318 + } 24319 24320 for (i = 0; i < CHALLENGESIZE; i++) { 24321 bytes[i] = (unsigned char)(random() & 255); 24322 @@ -245,3 +289,48 @@ 24323 des(bytes+i, bytes+i); 24324 } 24325 } 24326 + 24327 +void UvncEncryptPasswd_MSLOGON(unsigned char *encryptedPasswd, char *passwd) { 24328 + unsigned int i; 24329 + for (i=0; i < 32; i++) { 24330 + if (i < strlen(passwd)) { 24331 + encryptedPasswd[i] = passwd[i]; 24332 + } else { 24333 + encryptedPasswd[i] = '\0'; 24334 + } 24335 + } 24336 + deskey(s_fixedkey, EN0); 24337 + des(encryptedPasswd, encryptedPasswd); 24338 +} 24339 + 24340 +void UvncEncryptBytes2(unsigned char *where, int length, unsigned char *key) { 24341 + int i, j; 24342 + deskey(key, EN0); 24343 + for (i=0; i < 8; i++) { 24344 + where[i] ^= key[i]; 24345 + } 24346 + des(where, where); 24347 + for (i=8; i < length; i += 8) { 24348 + for (j=0; j < 8; j++) { 24349 + where[i+j] ^= where[i+j-8]; 24350 + } 24351 + des(where+i, where+i); 24352 + } 24353 +} 24354 + 24355 +void UvncDecryptBytes2(unsigned char *where, int length, unsigned char *key) { 24356 + int i, j; 24357 + deskey(key, DE1); 24358 + for (i = length - 8; i > 0; i -= 8) { 24359 + des(where + i, where + i); 24360 + for (j=0; j < 8; j++) { 24361 + where[i+j] ^= where[i+j-8]; 24362 + } 24363 + } 24364 + /* i=0 */ 24365 + des(where, where); 24366 + for (i=0; i < 8; i++) { 24367 + where[i] ^= key[i]; 24368 + } 24369 +} 24370 + 24371