Home | History | Annotate | Download | only in patches
      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", &current) != 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/&/&amp;/g;
   8783 +	$_ =~ s/</&lt;/g;
   8784 +	$_ =~ s/>/&gt;/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