1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 User interface services - QT Window System
4 Copyright (C) Jay Sorg 2004-2006
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include <qapplication.h>
24 #include <qmainwindow.h>
32 #include <qsocketnotifier.h>
33 #include <qscrollview.h>
38 #include <unistd.h> // gethostname
39 #include <pwd.h> // getpwuid
40 #include <stdarg.h> // va_list va_start va_end
45 /* rdesktop globals */
46 extern int g_tcp_port_rdp
;
52 int g_server_depth
= 8;
54 int g_desktop_save
= 1;
55 int g_polygon_ellipse_orders
= 0;
56 int g_bitmap_cache
= 1;
57 int g_bitmap_cache_persist_enable
= False
;
58 int g_bitmap_cache_precache
= True
;
59 int g_bitmap_compression
= 1;
60 int g_rdp5_performanceflags
= 0;
61 int g_console_session
= 0;
62 int g_keylayout
= 0x409; /* Defaults to US keyboard layout */
63 int g_keyboard_type
= 0x4; /* Defaults to US keyboard layout */
64 int g_keyboard_subtype
= 0x0; /* Defaults to US keyboard layout */
65 int g_keyboard_functionkeys
= 0xc; /* Defaults to US keyboard layout */
68 static int g_argc
= 0;
69 static char ** g_argv
= 0;
70 static int g_UpAndRunning
= 0;
71 static int g_sock
= 0;
72 static int g_deactivated
= 0;
73 static uint32 g_ext_disc_reason
= 0;
74 static char g_servername
[128];
75 static char g_title
[128] = "";
76 static int g_flags
= RDP_LOGON_NORMAL
;
79 extern int g_dsp_busy
;
81 static int g_rdpsnd
= 0;
82 static QSocketNotifier
* g_SoundNotifier
= 0;
86 static QSocketNotifier
* g_SocketNotifier
= 0;
87 static QApplication
* g_App
= 0;
88 static QMyMainWindow
* g_MW
= 0;
89 static QMyScrollView
* g_SV
= 0;
90 static QPixmap
* g_BS
= 0;
91 static QPixmap
* g_DS
= 0;
92 static QPainter
* g_P1
= 0;
93 static QPainter
* g_P2
= 0;
94 static QColor g_Color1
;
95 static QColor g_Color2
;
99 uint32 RGBColors
[256];
102 static struct QColorMap
* g_CM
= 0;
103 static QRegion
* g_ClipRect
;
105 static Qt::RasterOp g_OpCodes
[16] = {
106 Qt::ClearROP
, // BLACKNESS 0
107 Qt::NorROP
, // NOTSRCERASE DSon
108 Qt::NotAndROP
, // DSna
109 Qt::NotCopyROP
, // NOTSRCCOPY Sn
110 Qt::AndNotROP
, // SRCERASE SDna
111 Qt::NotROP
, // DSTINVERT Dn
112 Qt::XorROP
, // SRCINVERT DSx
114 Qt::AndROP
, // SRCAND DSa
115 Qt::NotXorROP
, // DSxn
117 Qt::NotOrROP
, // MERGEPAINT DSno
118 Qt::CopyROP
, // SRCCOPY S
119 Qt::OrNotROP
, // SDno
120 Qt::OrROP
, // SRCPAINT DSo
121 Qt::SetROP
}; // WHITENESS 1
123 /* Session Directory redirection */
124 BOOL g_redirect
= False
;
125 char g_redirect_server
[64];
126 char g_redirect_domain
[16];
127 char g_redirect_password
[64];
128 char g_redirect_username
[64];
129 char g_redirect_cookie
[128];
130 uint32 g_redirect_flags
= 0;
132 //*****************************************************************************
133 uint32
Color15to32(uint32 InColor
)
137 r
= (InColor
& 0x7c00) >> 10;
138 r
= (r
* 0xff) / 0x1f;
139 g
= (InColor
& 0x03e0) >> 5;
140 g
= (g
* 0xff) / 0x1f;
141 b
= (InColor
& 0x001f);
142 b
= (b
* 0xff) / 0x1f;
143 return (r
<< 16) | (g
<< 8) | b
;
146 //*****************************************************************************
147 uint32
Color16to32(uint32 InColor
)
151 r
= (InColor
& 0xf800) >> 11;
152 r
= (r
* 0xff) / 0x1f;
153 g
= (InColor
& 0x07e0) >> 5;
154 g
= (g
* 0xff) / 0x3f;
155 b
= (InColor
& 0x001f);
156 b
= (b
* 0xff) / 0x1f;
157 return (r
<< 16) | (g
<< 8) | b
;
160 //*****************************************************************************
161 uint32
Color24to32(uint32 InColor
)
163 return ((InColor
& 0x00ff0000) >> 16) |
164 ((InColor
& 0x000000ff) << 16) |
165 (InColor
& 0x0000ff00);
168 //*****************************************************************************
169 void SetColorx(QColor
* Color
, uint32 InColor
)
171 switch (g_server_depth
)
174 if (g_CM
== NULL
|| InColor
> 255)
179 Color
->setRgb(g_CM
->RGBColors
[InColor
]);
182 Color
->setRgb(Color15to32(InColor
));
185 Color
->setRgb(Color16to32(InColor
));
188 Color
->setRgb(Color24to32(InColor
));
195 //*****************************************************************************
196 void SetOpCode(int opcode
)
198 if (opcode
>= 0 && opcode
< 16)
200 Qt::RasterOp op
= g_OpCodes
[opcode
];
201 if (op
!= Qt::CopyROP
)
203 g_P1
->setRasterOp(op
);
204 g_P2
->setRasterOp(op
);
209 //*****************************************************************************
210 void ResetOpCode(int opcode
)
212 if (opcode
>= 0 && opcode
< 16)
214 Qt::RasterOp op
= g_OpCodes
[opcode
];
215 if (op
!= Qt::CopyROP
)
217 g_P1
->setRasterOp(Qt::CopyROP
);
218 g_P2
->setRasterOp(Qt::CopyROP
);
223 /*****************************************************************************/
224 QMyMainWindow::QMyMainWindow(): QWidget()
228 /*****************************************************************************/
229 QMyMainWindow::~QMyMainWindow()
233 //*****************************************************************************
234 void QMyMainWindow::mouseMoveEvent(QMouseEvent
* e
)
240 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_MOVE
, e
->x(), e
->y());
243 //*****************************************************************************
244 void QMyMainWindow::mousePressEvent(QMouseEvent
* e
)
250 if (e
->button() == LeftButton
)
252 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_DOWN
| MOUSE_FLAG_BUTTON1
,
255 else if (e
->button() == RightButton
)
257 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_DOWN
| MOUSE_FLAG_BUTTON2
,
260 else if (e
->button() == MidButton
)
262 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_DOWN
| MOUSE_FLAG_BUTTON3
,
267 //*****************************************************************************
268 void QMyMainWindow::mouseReleaseEvent(QMouseEvent
* e
)
274 if (e
->button() == LeftButton
)
276 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_BUTTON1
, e
->x(), e
->y());
278 else if (e
->button() == RightButton
)
280 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_BUTTON2
, e
->x(), e
->y());
282 else if (e
->button() == MidButton
)
284 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_BUTTON3
, e
->x(), e
->y());
288 //*****************************************************************************
289 void QMyMainWindow::wheelEvent(QWheelEvent
* e
)
297 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_BUTTON4
, e
->x(), e
->y());
299 else if (e
->delta() < 0)
301 rdp_send_input(0, RDP_INPUT_MOUSE
, MOUSE_FLAG_BUTTON5
, e
->x(), e
->y());
305 //*****************************************************************************
306 int GetScanCode(QKeyEvent
* e
)
310 Qt::ButtonState bs
= e
->state();
311 if (!(bs
& Qt::ShiftButton
)) // shift is not down
320 case 4100: ScanCode
= 0x1c; break; // enter
321 case 4101: ScanCode
= 0x1c; break;
322 case 4117: ScanCode
= 0xd0; break; // down arrow
323 case 4115: ScanCode
= 0xc8; break; // up arrow
324 case 4114: ScanCode
= 0xcb; break; // left arrow
325 case 4116: ScanCode
= 0xcd; break; // right arrow
326 case 4112: ScanCode
= 0xc7; break; // home
327 case 4113: ScanCode
= 0xcf; break; // end
328 case 4102: ScanCode
= 0xd2; break; // insert
329 case 4103: ScanCode
= 0xd3; break; // delete
330 case 4118: ScanCode
= 0xc9; break; // page up
331 case 4119: ScanCode
= 0xd1; break; // page down
332 case 4143: ScanCode
= 0x00; break; // num lock
333 case 47: ScanCode
= 0x35; break; // /
334 case 42: ScanCode
= 0x37; break; // *
335 case 45: ScanCode
= 0x0c; break; // -
336 case 95: ScanCode
= 0x0c; break; // _
337 case 43: ScanCode
= 0x0d; break; // +
338 case 46: ScanCode
= 0x34; break; // .
339 case 48: ScanCode
= 0x0b; break; // 0
340 case 41: ScanCode
= 0x0b; break; // )
341 case 49: ScanCode
= 0x02; break; // 1
342 case 33: ScanCode
= 0x02; break; // !
343 case 50: ScanCode
= 0x03; break; // 2
344 case 64: ScanCode
= 0x03; break; // @
345 case 51: ScanCode
= 0x04; break; // 3
346 case 35: ScanCode
= 0x04; break; // #
347 case 52: ScanCode
= 0x05; break; // 4
348 case 36: ScanCode
= 0x05; break; // $
349 case 53: ScanCode
= 0x06; break; // 5
350 case 37: ScanCode
= 0x06; break; // %
351 case 54: ScanCode
= 0x07; break; // 6
352 case 94: ScanCode
= 0x07; break; // ^
353 case 55: ScanCode
= 0x08; break; // 7
354 case 38: ScanCode
= 0x08; break; // &
355 case 56: ScanCode
= 0x09; break; // 8
356 case 57: ScanCode
= 0x0a; break; // 9
357 case 40: ScanCode
= 0x0a; break; // (
358 case 61: ScanCode
= 0x0d; break; // =
359 case 65: ScanCode
= 0x1e; break; // a
360 case 66: ScanCode
= 0x30; break; // b
361 case 67: ScanCode
= 0x2e; break; // c
362 case 68: ScanCode
= 0x20; break; // d
363 case 69: ScanCode
= 0x12; break; // e
364 case 70: ScanCode
= 0x21; break; // f
365 case 71: ScanCode
= 0x22; break; // g
366 case 72: ScanCode
= 0x23; break; // h
367 case 73: ScanCode
= 0x17; break; // i
368 case 74: ScanCode
= 0x24; break; // j
369 case 75: ScanCode
= 0x25; break; // k
370 case 76: ScanCode
= 0x26; break; // l
371 case 77: ScanCode
= 0x32; break; // m
372 case 78: ScanCode
= 0x31; break; // n
373 case 79: ScanCode
= 0x18; break; // o
374 case 80: ScanCode
= 0x19; break; // p
375 case 81: ScanCode
= 0x10; break; // q
376 case 82: ScanCode
= 0x13; break; // r
377 case 83: ScanCode
= 0x1f; break; // s
378 case 84: ScanCode
= 0x14; break; // t
379 case 85: ScanCode
= 0x16; break; // u
380 case 86: ScanCode
= 0x2f; break; // v
381 case 87: ScanCode
= 0x11; break; // w
382 case 88: ScanCode
= 0x2d; break; // x
383 case 89: ScanCode
= 0x15; break; // y
384 case 90: ScanCode
= 0x2c; break; // z
385 case 32: ScanCode
= 0x39; break; // space
386 case 44: ScanCode
= 0x33; break; // ,
387 case 60: ScanCode
= 0x33; break; // <
388 case 62: ScanCode
= 0x34; break; // >
389 case 63: ScanCode
= 0x35; break; // ?
390 case 92: ScanCode
= 0x2b; break; // backslash
391 case 124: ScanCode
= 0x2b; break; // bar
392 case 4097: ScanCode
= 0x0f; break; // tab
393 case 4132: ScanCode
= 0x3a; break; // caps lock
394 case 4096: ScanCode
= 0x01; break; // esc
395 case 59: ScanCode
= 0x27; break; // ;
396 case 58: ScanCode
= 0x27; break; // :
397 case 39: ScanCode
= 0x28; break; // '
398 case 34: ScanCode
= 0x28; break; // "
399 case 91: ScanCode
= 0x1a; break; // [
400 case 123: ScanCode
= 0x1a; break; // {
401 case 93: ScanCode
= 0x1b; break; // ]
402 case 125: ScanCode
= 0x1b; break; // }
403 case 4144: ScanCode
= 0x3b; break; // f1
404 case 4145: ScanCode
= 0x3c; break; // f2
405 case 4146: ScanCode
= 0x3d; break; // f3
406 case 4147: ScanCode
= 0x3e; break; // f4
407 case 4148: ScanCode
= 0x3f; break; // f5
408 case 4149: ScanCode
= 0x40; break; // f6
409 case 4150: ScanCode
= 0x41; break; // f7
410 case 4151: ScanCode
= 0x42; break; // f8
411 case 4152: ScanCode
= 0x43; break; // f9
412 case 4153: ScanCode
= 0x44; break; // f10
413 case 4154: ScanCode
= 0x57; break; // f11
414 case 4155: ScanCode
= 0x58; break; // f12
415 case 4128: ScanCode
= 0x2a; break; // shift
416 case 4131: ScanCode
= 0x38; break; // alt
417 case 4129: ScanCode
= 0x1d; break; // ctrl
418 case 96: ScanCode
= 0x29; break; // `
419 case 126: ScanCode
= 0x29; break; // ~
420 case 4099: ScanCode
= 0x0e; break; // backspace
422 // if (ScanCode == 0)
423 // printf("key %d scancode %d\n", Key, ScanCode);
427 //*****************************************************************************
428 void QMyMainWindow::keyPressEvent(QKeyEvent
* e
)
432 int ScanCode
= GetScanCode(e
);
435 rdp_send_input(0, RDP_INPUT_SCANCODE
, RDP_KEYPRESS
, ScanCode
, 0);
440 //*****************************************************************************
441 void QMyMainWindow::keyReleaseEvent(QKeyEvent
* e
)
447 int ScanCode
= GetScanCode(e
);
450 rdp_send_input(0, RDP_INPUT_SCANCODE
, RDP_KEYRELEASE
, ScanCode
, 0);
455 //*****************************************************************************
456 void QMyMainWindow::paintEvent(QPaintEvent
* pe
)
461 bitBlt(this, Rect
.left(), Rect
.top(), g_BS
, Rect
.left(), Rect
.top(),
462 Rect
.width(), Rect
.height());
465 //*****************************************************************************
466 void QMyMainWindow::closeEvent(QCloseEvent
* e
)
471 //*****************************************************************************
472 bool QMyMainWindow::event(QEvent
* e
)
474 return QWidget::event(e
);
477 //*****************************************************************************
478 void QMyMainWindow::dataReceived()
480 if (!rdp_loop(&g_deactivated
, &g_ext_disc_reason
))
487 if (g_SoundNotifier
== 0)
489 g_SoundNotifier
= new QSocketNotifier(g_dsp_fd
, QSocketNotifier::Write
,
491 g_MW
->connect(g_SoundNotifier
, SIGNAL(activated(int)), g_MW
,
496 if (!g_SoundNotifier
->isEnabled())
498 g_SoundNotifier
->setEnabled(true);
505 /******************************************************************************/
506 void QMyMainWindow::soundSend()
509 g_SoundNotifier
->setEnabled(false);
513 g_SoundNotifier
->setEnabled(true);
518 //*****************************************************************************
519 void QMyScrollView::keyPressEvent(QKeyEvent
* e
)
521 g_MW
->keyPressEvent(e
);
524 //*****************************************************************************
525 void QMyScrollView::keyReleaseEvent(QKeyEvent
* e
)
527 g_MW
->keyReleaseEvent(e
);
531 //*****************************************************************************
532 void ui_begin_update(void)
538 //*****************************************************************************
539 void ui_end_update(void)
545 /*****************************************************************************/
548 g_App
= new QApplication(g_argc
, g_argv
);
552 /*****************************************************************************/
558 /*****************************************************************************/
559 int ui_create_window(void)
565 g_MW
= new QMyMainWindow();
566 g_SV
= new QMyScrollView();
567 g_SV
->addChild(g_MW
);
568 g_BS
= new QPixmap(g_width
, g_height
);
569 painter
= new QPainter(g_BS
);
570 painter
->fillRect(0, 0, g_width
, g_height
, QBrush(QColor("white")));
571 painter
->fillRect(0, 0, g_width
, g_height
, QBrush(QBrush::CrossPattern
));
573 g_DS
= new QPixmap(480, 480);
574 g_P1
= new QPainter();
575 g_P2
= new QPainter();
576 g_ClipRect
= new QRegion(0, 0, g_width
, g_height
);
577 desktop
= QApplication::desktop();
578 w
= desktop
->width(); // returns screen width
579 h
= desktop
->height(); // returns screen height
580 g_MW
->resize(g_width
, g_height
);
581 if (w
< g_width
|| h
< g_height
)
587 g_SV
->resize(g_width
+ 4, g_height
+ 4);
589 g_SV
->setMaximumWidth(g_width
+ 4);
590 g_SV
->setMaximumHeight(g_height
+ 4);
591 g_App
->setMainWidget(g_SV
);
593 g_MW
->setMouseTracking(true);
596 g_SV
->setCaption(g_title
);
599 /* XGrayKey(0, 64, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
600 XGrayKey(0, 113, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
601 XGrayKey(0, 37, AnyModifie, SV-winId(), 0, GrabModeAsync, GrabModeAsync);
602 XGrayKey(0, 109, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
603 XGrayKey(0, 115, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
604 XGrayKey(0, 116, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
605 XGrayKey(0, 117, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
606 XGrayKey(0, 62, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
607 XGrayKey(0, 50, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);*/
612 //*****************************************************************************
613 void ui_main_loop(void)
623 if (!rdp_connect(g_servername
, g_flags
, "", "", "", ""))
628 g_SocketNotifier
= new QSocketNotifier(g_sock
, QSocketNotifier::Read
, g_MW
);
629 g_MW
->connect(g_SocketNotifier
, SIGNAL(activated(int)),
630 g_MW
, SLOT(dataReceived()));
636 //*****************************************************************************
637 void ui_destroy_window(void)
648 /*****************************************************************************/
653 /*****************************************************************************/
654 int ui_select(int in_val
)
663 /*****************************************************************************/
664 void ui_destroy_cursor(void * cursor
)
667 Cursor
= (QCursor
*)cursor
;
674 /*****************************************************************************/
675 void* ui_create_glyph(int width
, int height
, uint8
* data
)
678 Bitmap
= new QBitmap(width
, height
, data
);
679 Bitmap
->setMask(*Bitmap
);
680 return (HGLYPH
)Bitmap
;
683 /*****************************************************************************/
684 void ui_destroy_glyph(void * glyph
)
687 Bitmap
= (QBitmap
*)glyph
;
691 /*****************************************************************************/
692 void ui_destroy_bitmap(void * bmp
)
695 Pixmap
= (QPixmap
*)bmp
;
699 /*****************************************************************************/
700 void ui_reset_clip(void)
702 g_P1
->setClipRect(0, 0, g_width
, g_height
);
703 g_P2
->setClipRect(0, 0, g_width
, g_height
);
705 g_ClipRect
= new QRegion(0, 0, g_width
, g_height
);
708 /*****************************************************************************/
709 void ui_set_clip(int x
, int y
, int cx
, int cy
)
711 g_P1
->setClipRect(x
, y
, cx
, cy
);
712 g_P2
->setClipRect(x
, y
, cx
, cy
);
714 g_ClipRect
= new QRegion(x
, y
, cx
, cy
);
717 /*****************************************************************************/
718 void * ui_create_colourmap(COLOURMAP
* colours
)
722 LCM
= (QColorMap
*)malloc(sizeof(QColorMap
));
723 memset(LCM
, 0, sizeof(QColorMap
));
725 while (i
< colours
->ncolours
&& i
< 256)
727 r
= colours
->colours
[i
].red
;
728 g
= colours
->colours
[i
].green
;
729 b
= colours
->colours
[i
].blue
;
730 LCM
->RGBColors
[i
] = (r
<< 16) | (g
<< 8) | b
;
733 LCM
->NumColors
= colours
->ncolours
;
737 //*****************************************************************************
738 // todo, does this leak at end of program
739 void ui_destroy_colourmap(HCOLOURMAP map
)
742 LCM
= (QColorMap
*)map
;
748 /*****************************************************************************/
749 void ui_set_colourmap(void * map
)
751 // destoy old colormap
752 ui_destroy_colourmap(g_CM
);
753 g_CM
= (QColorMap
*)map
;
756 /*****************************************************************************/
757 HBITMAP
ui_create_bitmap(int width
, int height
, uint8
* data
)
759 QImage
* Image
= NULL
;
765 switch (g_server_depth
)
768 Image
= new QImage(data
, width
, height
, 8, (QRgb
*)&g_CM
->RGBColors
,
769 g_CM
->NumColors
, QImage::IgnoreEndian
);
772 d
= (uint32
*)malloc(width
* height
* 4);
774 for (i
= 0; i
< width
* height
; i
++)
776 d
[i
] = Color15to32(s
[i
]);
778 Image
= new QImage((uint8
*)d
, width
, height
, 32, NULL
,
779 0, QImage::IgnoreEndian
);
782 d
= (uint32
*)malloc(width
* height
* 4);
784 for (i
= 0; i
< width
* height
; i
++)
786 d
[i
] = Color16to32(s
[i
]);
788 Image
= new QImage((uint8
*)d
, width
, height
, 32, NULL
,
789 0, QImage::IgnoreEndian
);
792 d
= (uint32
*)malloc(width
* height
* 4);
793 memset(d
, 0, width
* height
* 4);
794 for (i
= 0; i
< width
* height
; i
++)
796 memcpy(d
+ i
, data
+ i
* 3, 3);
798 Image
= new QImage((uint8
*)d
, width
, height
, 32, NULL
,
799 0, QImage::IgnoreEndian
);
806 Pixmap
= new QPixmap();
807 Pixmap
->convertFromImage(*Image
);
813 return (HBITMAP
)Pixmap
;
816 //******************************************************************************
817 // adjust coordinates for cliping rect
818 int WarpCoords(int * x
, int * y
, int * cx
, int * cy
, int * srcx
, int * srcy
)
821 QRect
InRect(*x
, *y
, *cx
, *cy
);
823 QRect CRect
= g_ClipRect
->boundingRect();
824 OutRect
= InRect
.intersect(CRect
);
825 if (OutRect
.isEmpty())
829 dx
= OutRect
.x() - InRect
.x();
830 dy
= OutRect
.y() - InRect
.y();
833 *cx
= OutRect
.width();
834 *cy
= OutRect
.height();
840 //******************************************************************************
841 // needed because bitBlt don't seem to care about clipping rects
842 // also has 2 dsts and src can be null
843 void bitBltClip(QPaintDevice
* dst1
, QPaintDevice
* dst2
, int dx
, int dy
,
844 QPaintDevice
* src
, int sx
, int sy
, int sw
, int sh
,
845 Qt::RasterOp rop
, bool im
)
847 if (WarpCoords(&dx
, &dy
, &sw
, &sh
, &sx
, &sy
))
853 bitBlt(dst1
, dx
, dy
, dst1
, sx
, sy
, sw
, sh
, rop
, im
);
857 bitBlt(dst1
, dx
, dy
, src
, sx
, sy
, sw
, sh
, rop
, im
);
864 bitBlt(dst2
, dx
, dy
, dst2
, sx
, sy
, sw
, sh
, rop
, im
);
868 bitBlt(dst2
, dx
, dy
, src
, sx
, sy
, sw
, sh
, rop
, im
);
874 #define DO_GLYPH(ttext,idx) \
876 glyph = cache_get_font (font, ttext[idx]); \
877 if (!(flags & TEXT2_IMPLICIT_X)) \
879 xyoffset = ttext[++idx]; \
880 if ((xyoffset & 0x80)) \
882 if (flags & TEXT2_VERTICAL) \
883 y += ttext[idx+1] | (ttext[idx+2] << 8); \
885 x += ttext[idx+1] | (ttext[idx+2] << 8); \
890 if (flags & TEXT2_VERTICAL) \
898 g_P2->drawPixmap(x + glyph->offset, y + glyph->baseline, \
899 *((QBitmap*)glyph->pixmap)); \
900 if (flags & TEXT2_IMPLICIT_X) \
905 //*****************************************************************************
906 void ui_draw_text(uint8 font
, uint8 flags
, uint8 opcode
, int mixmode
,
907 int x
, int y
, int clipx
, int clipy
,
908 int clipcx
, int clipcy
, int boxx
,
909 int boxy
, int boxcx
, int boxcy
, BRUSH
* brush
,
910 int bgcolour
, int fgcolour
, uint8
* text
, uint8 length
)
916 SetColorx(&g_Color1
, fgcolour
);
917 SetColorx(&g_Color2
, bgcolour
);
918 g_P2
->setBackgroundColor(g_Color2
);
919 g_P2
->setPen(g_Color1
);
922 g_P2
->fillRect(boxx
, boxy
, boxcx
, boxcy
, QBrush(g_Color2
));
924 else if (mixmode
== MIX_OPAQUE
)
926 g_P2
->fillRect(clipx
, clipy
, clipcx
, clipcy
, QBrush(g_Color2
));
929 /* Paint text, character by character */
930 for (i
= 0; i
< length
;)
937 cache_put_text(text
[i
+ 1], text
, text
[i
+ 2]);
941 error("this shouldn't be happening\n");
944 /* this will move pointer from start to first character after FF
947 text
= &(text
[i
+ 3]);
952 entry
= cache_get_text(text
[i
+ 1]);
955 if ((((uint8
*) (entry
->data
))[1] == 0) &&
956 (!(flags
& TEXT2_IMPLICIT_X
)))
958 if (flags
& TEXT2_VERTICAL
)
967 for (j
= 0; j
< entry
->size
; j
++)
969 DO_GLYPH(((uint8
*) (entry
->data
)), j
);
981 /* this will move pointer from start to first character after FE
995 bitBltClip(g_MW
, NULL
, boxx
, boxy
, g_BS
, boxx
, boxy
, boxcx
, boxcy
,
1000 bitBltClip(g_MW
, NULL
, clipx
, clipy
, g_BS
, clipx
, clipy
, clipcx
,
1001 clipcy
, Qt::CopyROP
, true);
1005 /*****************************************************************************/
1006 void ui_line(uint8 opcode
, int startx
, int starty
, int endx
, int endy
,
1009 SetColorx(&g_Color1
, pen
->colour
);
1011 g_P1
->setPen(g_Color1
);
1012 g_P1
->moveTo(startx
, starty
);
1013 g_P1
->lineTo(endx
, endy
);
1014 g_P2
->setPen(g_Color1
);
1015 g_P2
->moveTo(startx
, starty
);
1016 g_P2
->lineTo(endx
, endy
);
1017 ResetOpCode(opcode
);
1020 /*****************************************************************************/
1022 void ui_triblt(uint8 opcode
, int x
, int y
, int cx
, int cy
,
1023 HBITMAP src
, int srcx
, int srcy
,
1024 BRUSH
* brush
, int bgcolour
, int fgcolour
)
1028 /*****************************************************************************/
1029 void ui_memblt(uint8 opcode
, int x
, int y
, int cx
, int cy
,
1030 HBITMAP src
, int srcx
, int srcy
)
1033 Pixmap
= (QPixmap
*)src
;
1037 g_P1
->drawPixmap(x
, y
, *Pixmap
, srcx
, srcy
, cx
, cy
);
1038 g_P2
->drawPixmap(x
, y
, *Pixmap
, srcx
, srcy
, cx
, cy
);
1039 ResetOpCode(opcode
);
1043 //******************************************************************************
1044 void CommonDeskSave(QPixmap
* Pixmap1
, QPixmap
* Pixmap2
, int Offset
, int x
,
1045 int y
, int cx
, int cy
, int dir
)
1070 bitBlt(Pixmap1
, lx
, ly
, Pixmap2
, x1
, y1
, width
, 1, Qt::CopyROP
, true);
1072 bitBlt(Pixmap2
, x1
, y1
, Pixmap1
, lx
, ly
, width
, 1, Qt::CopyROP
, true);
1088 /*****************************************************************************/
1089 void ui_desktop_restore(uint32 offset
, int x
, int y
, int cx
, int cy
)
1093 Pixmap
= new QPixmap(cx
, cy
);
1094 CommonDeskSave(g_DS
, Pixmap
, offset
, 0, 0, cx
, cy
, 1);
1095 bitBltClip(g_MW
, g_BS
, x
, y
, Pixmap
, 0, 0, cx
, cy
, Qt::CopyROP
, true);
1099 /*****************************************************************************/
1100 void ui_desktop_save(uint32 offset
, int x
, int y
, int cx
, int cy
)
1102 CommonDeskSave(g_DS
, g_BS
, offset
, x
, y
, cx
, cy
, 0);
1105 /*****************************************************************************/
1106 void ui_rect(int x
, int y
, int cx
, int cy
, int colour
)
1108 SetColorx(&g_Color1
, colour
);
1109 g_P1
->fillRect(x
, y
, cx
, cy
, QBrush(g_Color1
));
1110 g_P2
->fillRect(x
, y
, cx
, cy
, QBrush(g_Color1
));
1113 /*****************************************************************************/
1114 void ui_screenblt(uint8 opcode
, int x
, int y
, int cx
, int cy
,
1118 bitBltClip(g_MW
, g_BS
, x
, y
, NULL
, srcx
, srcy
, cx
, cy
, Qt::CopyROP
, true);
1119 ResetOpCode(opcode
);
1122 /*****************************************************************************/
1123 void ui_patblt(uint8 opcode
, int x
, int y
, int cx
, int cy
,
1124 BRUSH
* brush
, int bgcolour
, int fgcolour
)
1128 uint8 ipattern
[8], i
;
1130 switch (brush
->style
)
1133 SetColorx(&g_Color1
, fgcolour
);
1134 g_P2
->fillRect(x
, y
, cx
, cy
, QBrush(g_Color1
));
1137 SetColorx(&g_Color1
, fgcolour
);
1138 SetColorx(&g_Color2
, bgcolour
);
1139 for (i
= 0; i
!= 8; i
++)
1141 ipattern
[7 - i
] = ~brush
->pattern
[i
];
1143 Bitmap
= new QBitmap(8, 8, ipattern
);
1144 Brush
= new QBrush(g_Color1
, *Bitmap
);
1145 g_P2
->setBackgroundMode(Qt::OpaqueMode
);
1146 g_P2
->setBrushOrigin(brush
->xorigin
, brush
->yorigin
);
1147 g_P2
->setBackgroundColor(g_Color2
);
1148 g_P2
->fillRect(x
, y
, cx
, cy
, *Brush
);
1151 g_P2
->setBackgroundMode(Qt::TransparentMode
);
1152 g_P2
->setBrushOrigin(0, 0);
1155 ResetOpCode(opcode
);
1156 bitBltClip(g_MW
, NULL
, x
, y
, g_BS
, x
, y
, cx
, cy
, Qt::CopyROP
, true);
1159 /*****************************************************************************/
1160 void ui_destblt(uint8 opcode
, int x
, int y
, int cx
, int cy
)
1163 g_P1
->fillRect(x
, y
, cx
, cy
, QBrush(QColor("black")));
1164 g_P2
->fillRect(x
, y
, cx
, cy
, QBrush(QColor("black")));
1165 ResetOpCode(opcode
);
1168 /*****************************************************************************/
1169 void ui_move_pointer(int x
, int y
)
1173 /*****************************************************************************/
1174 void ui_set_null_cursor(void)
1176 g_MW
->setCursor(10); // Qt::BlankCursor
1179 /*****************************************************************************/
1180 void ui_paint_bitmap(int x
, int y
, int cx
, int cy
,
1181 int width
, int height
, uint8
* data
)
1183 QImage
* Image
= NULL
;
1189 switch (g_server_depth
)
1192 Image
= new QImage(data
, width
, height
, 8, (QRgb
*)&g_CM
->RGBColors
,
1193 g_CM
->NumColors
, QImage::IgnoreEndian
);
1196 d
= (uint32
*)malloc(width
* height
* 4);
1198 for (i
= 0; i
< width
* height
; i
++)
1200 d
[i
] = Color15to32(s
[i
]);
1202 Image
= new QImage((uint8
*)d
, width
, height
, 32, NULL
,
1203 0, QImage::IgnoreEndian
);
1206 d
= (uint32
*)malloc(width
* height
* 4);
1208 for (i
= 0; i
< width
* height
; i
++)
1210 d
[i
] = Color16to32(s
[i
]);
1212 Image
= new QImage((uint8
*)d
, width
, height
, 32, NULL
,
1213 0, QImage::IgnoreEndian
);
1216 d
= (uint32
*)malloc(width
* height
* 4);
1217 memset(d
, 0, width
* height
* 4);
1218 for (i
= 0; i
< width
* height
; i
++)
1220 memcpy(d
+ i
, data
+ i
* 3, 3);
1222 Image
= new QImage((uint8
*)d
, width
, height
, 32, NULL
,
1223 0, QImage::IgnoreEndian
);
1230 Pixmap
= new QPixmap();
1231 Pixmap
->convertFromImage(*Image
);
1232 g_P1
->drawPixmap(x
, y
, *Pixmap
, 0, 0, cx
, cy
);
1233 g_P2
->drawPixmap(x
, y
, *Pixmap
, 0, 0, cx
, cy
);
1242 //******************************************************************************
1243 int Is24On(uint8
* Data
, int X
, int Y
)
1247 Start
= Y
* 32 * 3 + X
* 3;
1249 G
= Data
[Start
+ 1];
1250 B
= Data
[Start
+ 2];
1251 return !((R
== 0) && (G
== 0) && (B
== 0));
1254 //******************************************************************************
1255 int Is1On(uint8
* Data
, int X
, int Y
)
1259 Start
= (Y
* 32) / 8 + X
/ 8;
1261 return (Data
[Start
] & (0x80 >> Shift
)) == 0;
1264 //******************************************************************************
1265 void Set1(uint8
* Data
, int X
, int Y
)
1269 Start
= (Y
* 32) / 8 + X
/ 8;
1271 Data
[Start
] = Data
[Start
] | (0x80 >> Shift
);
1274 //******************************************************************************
1275 void FlipOver(uint8
* Data
)
1279 memcpy(AData
, Data
, 128);
1280 for (Index
= 0; Index
<= 31; Index
++)
1282 Data
[127 - (Index
* 4 + 3)] = AData
[Index
* 4];
1283 Data
[127 - (Index
* 4 + 2)] = AData
[Index
* 4 + 1];
1284 Data
[127 - (Index
* 4 + 1)] = AData
[Index
* 4 + 2];
1285 Data
[127 - Index
* 4] = AData
[Index
* 4 + 3];
1289 /*****************************************************************************/
1290 void ui_set_cursor(HCURSOR cursor
)
1293 Cursor
= (QCursor
*)cursor
;
1295 g_MW
->setCursor(*Cursor
);
1298 /*****************************************************************************/
1299 HCURSOR
ui_create_cursor(unsigned int x
, unsigned int y
,
1300 int width
, int height
,
1301 uint8
* andmask
, uint8
* xormask
)
1305 QBitmap
* DataBitmap
;
1306 QBitmap
* MaskBitmap
;
1308 int I1
, I2
, BOn
, MOn
;
1310 if (width
!= 32 || height
!= 32)
1314 memset(AData
, 0, 128);
1315 memset(AMask
, 0, 128);
1316 for (I1
= 0; I1
<= 31; I1
++)
1318 for (I2
= 0; I2
<= 31; I2
++)
1320 MOn
= Is24On(xormask
, I1
, I2
);
1321 BOn
= Is1On(andmask
, I1
, I2
);
1322 if (BOn
^ MOn
) // xor
1324 Set1(AData
, I1
, I2
);
1327 Set1(AMask
, I1
, I2
);
1332 Set1(AMask
, I1
, I2
);
1338 DataBitmap
= new QBitmap(32, 32, AData
);
1339 MaskBitmap
= new QBitmap(32, 32, AMask
);
1340 Cursor
= new QCursor(*DataBitmap
, *MaskBitmap
, x
, y
);
1346 /*****************************************************************************/
1347 uint16
ui_get_numlock_state(uint32 state
)
1352 /*****************************************************************************/
1353 uint32
read_keyboard_state(void)
1358 /*****************************************************************************/
1359 void ui_resize_window(void)
1363 /*****************************************************************************/
1364 void ui_polygon(uint8 opcode
, uint8 fillmode
, POINT
* point
, int npoints
,
1365 BRUSH
* brush
, int bgcolour
, int fgcolour
)
1369 /*****************************************************************************/
1370 /* todo, use qt function for this (QPainter::drawPolyline) */
1371 void ui_polyline(uint8 opcode
, POINT
* points
, int npoints
, PEN
* pen
)
1373 int i
, x
, y
, dx
, dy
;
1379 for (i
= 1; i
< npoints
; i
++)
1383 ui_line(opcode
, x
, y
, x
+ dx
, y
+ dy
, pen
);
1390 /*****************************************************************************/
1391 void ui_ellipse(uint8 opcode
, uint8 fillmode
,
1392 int x
, int y
, int cx
, int cy
,
1393 BRUSH
* brush
, int bgcolour
, int fgcolour
)
1397 /*****************************************************************************/
1398 void generate_random(uint8
* random
)
1400 QFile
File("/dev/random");
1401 File
.open(IO_ReadOnly
);
1402 if (File
.readBlock((char*)random
, 32) == 32)
1406 warning("no /dev/random\n");
1407 memcpy(random
, "12345678901234567890123456789012", 32);
1410 /*****************************************************************************/
1411 void save_licence(uint8
* data
, int length
)
1413 char * home
, * path
, * tmppath
;
1416 home
= getenv("HOME");
1421 path
= (char *) xmalloc(strlen(home
) + strlen(g_hostname
) +
1422 sizeof("/.rdesktop/licence."));
1423 sprintf(path
, "%s/.rdesktop", home
);
1424 if ((mkdir(path
, 0700) == -1) && errno
!= EEXIST
)
1429 /* write licence to licence.hostname.new, then atomically rename to
1431 sprintf(path
, "%s/.rdesktop/licence.%s", home
, g_hostname
);
1432 tmppath
= (char *) xmalloc(strlen(path
) + sizeof(".new"));
1433 strcpy(tmppath
, path
);
1434 strcat(tmppath
, ".new");
1435 fd
= open(tmppath
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0600);
1441 if (write(fd
, data
, length
) != length
)
1446 else if (rename(tmppath
, path
) == -1)
1456 /*****************************************************************************/
1457 int load_licence(uint8
** data
)
1459 char * home
, * path
;
1463 home
= getenv("HOME");
1468 path
= (char *) xmalloc(strlen(home
) + strlen(g_hostname
) +
1469 sizeof("/.rdesktop/licence."));
1470 sprintf(path
, "%s/.rdesktop/licence.%s", home
, g_hostname
);
1471 fd
= open(path
, O_RDONLY
);
1480 *data
= (uint8
*) xmalloc(st
.st_size
);
1481 length
= read(fd
, *data
, st
.st_size
);
1487 /*****************************************************************************/
1488 void* xrealloc(void * in_val
, int size
)
1490 return realloc(in_val
, size
);
1493 /*****************************************************************************/
1494 void* xmalloc(int size
)
1496 return malloc(size
);
1499 /*****************************************************************************/
1500 void xfree(void * in_val
)
1508 /*****************************************************************************/
1509 char * xstrdup(const char * s
)
1511 char * mem
= strdup(s
);
1520 /*****************************************************************************/
1521 void warning(char * format
, ...)
1525 fprintf(stderr
, "WARNING: ");
1526 va_start(ap
, format
);
1527 vfprintf(stderr
, format
, ap
);
1531 /*****************************************************************************/
1532 void unimpl(char * format
, ...)
1536 fprintf(stderr
, "NOT IMPLEMENTED: ");
1537 va_start(ap
, format
);
1538 vfprintf(stderr
, format
, ap
);
1542 /*****************************************************************************/
1543 void error(char * format
, ...)
1547 fprintf(stderr
, "ERROR: ");
1548 va_start(ap
, format
);
1549 vfprintf(stderr
, format
, ap
);
1553 /*****************************************************************************/
1554 void out_params(void)
1556 fprintf(stderr
, "rdesktop: A Remote Desktop Protocol client.\n");
1557 fprintf(stderr
, "Version " VERSION
". Copyright (C) 1999-2005 Matt Chapman.\n");
1558 fprintf(stderr
, "QT uiport by Jay Sorg\n");
1559 fprintf(stderr
, "See http://www.rdesktop.org/ for more information.\n\n");
1560 fprintf(stderr
, "Usage: qtrdesktop [options] server\n");
1561 fprintf(stderr
, " -g WxH: desktop geometry\n");
1562 fprintf(stderr
, " -4: use RDP version 4\n");
1563 fprintf(stderr
, " -5: use RDP version 5 (default)\n");
1564 fprintf(stderr
, " -t 3389: tcp port)\n");
1565 fprintf(stderr
, " -a 8|16|24: connection colour depth\n");
1566 fprintf(stderr
, " -T title: window title\n");
1567 fprintf(stderr
, " -P: use persistent bitmap caching\n");
1568 fprintf(stderr
, " -0: attach to console\n");
1569 fprintf(stderr
, " -z: enable rdp compression\n");
1570 fprintf(stderr
, " -r sound: enable sound\n");
1571 fprintf(stderr
, "\n");
1574 /*****************************************************************************/
1575 /* produce a hex dump */
1576 void hexdump(uint8
* p
, uint32 len
)
1582 while (offset
< len
)
1584 printf("%04x ", offset
);
1585 thisline
= len
- offset
;
1590 for (i
= 0; i
< thisline
; i
++)
1592 printf("%02x ", line
[i
]);
1598 for (i
= 0; i
< thisline
; i
++)
1600 printf("%c", (line
[i
] >= 0x20 && line
[i
] < 0x7f) ? line
[i
] : '.');
1608 /*****************************************************************************/
1609 int rd_pstcache_mkdir(void)
1612 char bmpcache_dir
[256];
1614 home
= getenv("HOME");
1619 sprintf(bmpcache_dir
, "%s/%s", home
, ".rdesktop");
1620 if ((mkdir(bmpcache_dir
, S_IRWXU
) == -1) && errno
!= EEXIST
)
1622 perror(bmpcache_dir
);
1625 sprintf(bmpcache_dir
, "%s/%s", home
, ".rdesktop/cache");
1626 if ((mkdir(bmpcache_dir
, S_IRWXU
) == -1) && errno
!= EEXIST
)
1628 perror(bmpcache_dir
);
1634 /*****************************************************************************/
1635 int rd_open_file(char * filename
)
1641 home
= getenv("HOME");
1646 sprintf(fn
, "%s/.rdesktop/%s", home
, filename
);
1647 fd
= open(fn
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
1655 /*****************************************************************************/
1656 void rd_close_file(int fd
)
1661 /*****************************************************************************/
1662 int rd_read_file(int fd
, void * ptr
, int len
)
1664 return read(fd
, ptr
, len
);
1667 /*****************************************************************************/
1668 int rd_write_file(int fd
, void * ptr
, int len
)
1670 return write(fd
, ptr
, len
);
1673 /*****************************************************************************/
1674 int rd_lseek_file(int fd
, int offset
)
1676 return lseek(fd
, offset
, SEEK_SET
);
1679 /*****************************************************************************/
1680 int rd_lock_file(int fd
, int start
, int len
)
1684 lock
.l_type
= F_WRLCK
;
1685 lock
.l_whence
= SEEK_SET
;
1686 lock
.l_start
= start
;
1688 if (fcntl(fd
, F_SETLK
, &lock
) == -1)
1695 /*****************************************************************************/
1696 void get_username_and_hostname(void)
1698 char fullhostname
[64];
1702 STRNCPY(g_username
, "unknown", sizeof(g_username
));
1703 STRNCPY(g_hostname
, "unknown", sizeof(g_hostname
));
1704 pw
= getpwuid(getuid());
1705 if (pw
!= NULL
&& pw
->pw_name
!= NULL
)
1707 STRNCPY(g_username
, pw
->pw_name
, sizeof(g_username
));
1709 if (gethostname(fullhostname
, sizeof(fullhostname
)) != -1)
1711 p
= strchr(fullhostname
, '.');
1716 STRNCPY(g_hostname
, fullhostname
, sizeof(g_hostname
));
1720 /*****************************************************************************/
1721 int parse_parameters(int in_argc
, char ** in_argv
)
1733 for (i
= 1; i
< in_argc
; i
++)
1735 strcpy(g_servername
, in_argv
[i
]);
1736 if (strcmp(in_argv
[i
], "-g") == 0)
1738 g_width
= strtol(in_argv
[i
+ 1], &p
, 10);
1741 error("invalid geometry\n");
1746 g_height
= strtol(p
+ 1, NULL
, 10);
1750 error("invalid geometry\n");
1753 g_width
= (g_width
+ 3) & ~3;
1755 else if (strcmp(in_argv
[i
], "-T") == 0)
1757 strcpy(g_title
, in_argv
[i
+ 1]);
1759 else if (strcmp(in_argv
[i
], "-4") == 0)
1763 else if (strcmp(in_argv
[i
], "-5") == 0)
1767 else if (strcmp(in_argv
[i
], "-a") == 0)
1769 g_server_depth
= strtol(in_argv
[i
+ 1], &p
, 10);
1770 if (g_server_depth
!= 8 && g_server_depth
!= 15 &&
1771 g_server_depth
!= 16 && g_server_depth
!= 24)
1773 error("invalid bpp\n");
1777 else if (strcmp(in_argv
[i
], "-t") == 0)
1779 g_tcp_port_rdp
= strtol(in_argv
[i
+ 1], &p
, 10);
1781 else if (strcmp(in_argv
[i
], "-P") == 0)
1783 g_bitmap_cache_persist_enable
= 1;
1785 else if (strcmp(in_argv
[i
], "-0") == 0)
1787 g_console_session
= 1;
1789 else if (strcmp(in_argv
[i
], "-z") == 0)
1791 g_flags
|= (RDP_LOGON_COMPRESSION
| RDP_LOGON_COMPRESSION2
);
1793 else if (strcmp(in_argv
[i
], "-r") == 0)
1795 if (strcmp(in_argv
[i
+ 1], "sound") == 0)
1806 /*****************************************************************************/
1807 int main(int in_argc
, char** in_argv
)
1809 get_username_and_hostname();
1810 if (!parse_parameters(in_argc
, in_argv
))
1818 if (!ui_create_window())
1823 ui_destroy_window();