• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff -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+
665diff -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 }
2417diff -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
2768diff -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
2833diff -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*
2855diff -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@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-
3780diff -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 }
7132diff -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 }
7740diff -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+
8773diff -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+}
8787diff -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
8963diff -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 }
9515diff -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;
9966diff -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+}
10871diff -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+}
10895diff -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-
15008diff -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
15074diff -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 }
15494diff -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 }
15667diff -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
15682diff -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.
16872diff -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
16901diff -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
16922diff -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);
16960diff -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+
17577diff -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
17810diff -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@ruhr-uni-bochum.de
17819+.\" Copyright (C) 2000,2001 Red Hat, Inc.
17820+.\" Copyright (C) 2001-2003 Constantin Kaplinsky <const@ce.cctpu.edu.ru>
17821+.\" Copyright (C) 2006-2010 Karl J. Runge <runge@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@ruhr-uni-bochum.de>,
18635+.br
18636+Terran Melconian <terran@consistent.org>,
18637+.br
18638+Tim Waugh <twaugh@redhat.com>,
18639+.br
18640+Constantin Kaplinsky <const@ce.cctpu.edu.ru>
18641+.br
18642+Karl J. Runge <runge@karlrunge.com>
18643diff -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 }
20713diff -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);
21187diff -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@ruhr-uni-bochum.de
21192 .\" Copyright (C) 2000,2001 Red Hat, Inc.
21193 .\" Copyright (C) 2001-2003 Constantin Kaplinsky <const@ce.cctpu.edu.ru>
21194+.\" Copyright (C) 2006-2010 Karl J. Runge <runge@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@redhat.com>,
21735 .br
21736 Constantin Kaplinsky <const@ce.cctpu.edu.ru>
21737+.br
21738+Karl J. Runge <runge@karlrunge.com>
21739diff -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
22363diff -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
22684diff -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+}
22963diff -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__ */
23029diff -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+}
23095diff -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__ */
23145diff -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__ */
23179diff -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
24007diff -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;
24191diff -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);
24206diff -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 };
24225diff -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