Martin Ettl <ettl DOT martin AT gmx DOT de>: Fix various resource and memory leaks
[reactos.git] / reactos / base / applications / tsclient / rdesktop / uiports / qtwin.cpp
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
5
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.
10
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.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "rdesktop.h"
22
23 #include <qapplication.h>
24 #include <qmainwindow.h>
25 #include <qwidget.h>
26 #include <qpainter.h>
27 #include <qpixmap.h>
28 #include <qbrush.h>
29 #include <qimage.h>
30 #include <qbitmap.h>
31 #include <qcursor.h>
32 #include <qsocketnotifier.h>
33 #include <qscrollview.h>
34 #include <qfile.h>
35
36 #include "qtwin.h"
37
38 #include <unistd.h> // gethostname
39 #include <pwd.h> // getpwuid
40 #include <stdarg.h> // va_list va_start va_end
41
42 #include <errno.h>
43 #include <fcntl.h>
44
45 /* rdesktop globals */
46 extern int g_tcp_port_rdp;
47 int g_use_rdp5 = 1;
48 char g_hostname[16];
49 char g_username[64];
50 int g_height = 600;
51 int g_width = 800;
52 int g_server_depth = 8;
53 int g_encryption = 1;
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 */
66
67 /* hack globals */
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;
77
78 #ifdef WITH_RDPSND
79 extern int g_dsp_busy;
80 extern int g_dsp_fd;
81 static int g_rdpsnd = 0;
82 static QSocketNotifier * g_SoundNotifier = 0;
83 #endif
84
85 /* qt globals */
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;
96
97 struct QColorMap
98 {
99 uint32 RGBColors[256];
100 int NumColors;
101 };
102 static struct QColorMap * g_CM = 0;
103 static QRegion * g_ClipRect;
104
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
113 Qt::NandROP, // DSan
114 Qt::AndROP, // SRCAND DSa
115 Qt::NotXorROP, // DSxn
116 Qt::NopROP, // D
117 Qt::NotOrROP, // MERGEPAINT DSno
118 Qt::CopyROP, // SRCCOPY S
119 Qt::OrNotROP, // SDno
120 Qt::OrROP, // SRCPAINT DSo
121 Qt::SetROP}; // WHITENESS 1
122
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;
131
132 //*****************************************************************************
133 uint32 Color15to32(uint32 InColor)
134 {
135 uint32 r, g, b;
136
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;
144 }
145
146 //*****************************************************************************
147 uint32 Color16to32(uint32 InColor)
148 {
149 uint32 r, g, b;
150
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;
158 }
159
160 //*****************************************************************************
161 uint32 Color24to32(uint32 InColor)
162 {
163 return ((InColor & 0x00ff0000) >> 16) |
164 ((InColor & 0x000000ff) << 16) |
165 (InColor & 0x0000ff00);
166 }
167
168 //*****************************************************************************
169 void SetColorx(QColor * Color, uint32 InColor)
170 {
171 switch (g_server_depth)
172 {
173 case 8:
174 if (g_CM == NULL || InColor > 255)
175 {
176 Color->setRgb(0);
177 return;
178 }
179 Color->setRgb(g_CM->RGBColors[InColor]);
180 break;
181 case 15:
182 Color->setRgb(Color15to32(InColor));
183 break;
184 case 16:
185 Color->setRgb(Color16to32(InColor));
186 break;
187 case 24:
188 Color->setRgb(Color24to32(InColor));
189 break;
190 default:
191 Color->setRgb(0);
192 }
193 }
194
195 //*****************************************************************************
196 void SetOpCode(int opcode)
197 {
198 if (opcode >= 0 && opcode < 16)
199 {
200 Qt::RasterOp op = g_OpCodes[opcode];
201 if (op != Qt::CopyROP)
202 {
203 g_P1->setRasterOp(op);
204 g_P2->setRasterOp(op);
205 }
206 }
207 }
208
209 //*****************************************************************************
210 void ResetOpCode(int opcode)
211 {
212 if (opcode >= 0 && opcode < 16)
213 {
214 Qt::RasterOp op = g_OpCodes[opcode];
215 if (op != Qt::CopyROP)
216 {
217 g_P1->setRasterOp(Qt::CopyROP);
218 g_P2->setRasterOp(Qt::CopyROP);
219 }
220 }
221 }
222
223 /*****************************************************************************/
224 QMyMainWindow::QMyMainWindow(): QWidget()
225 {
226 }
227
228 /*****************************************************************************/
229 QMyMainWindow::~QMyMainWindow()
230 {
231 }
232
233 //*****************************************************************************
234 void QMyMainWindow::mouseMoveEvent(QMouseEvent * e)
235 {
236 if (!g_UpAndRunning)
237 {
238 return;
239 }
240 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, e->x(), e->y());
241 }
242
243 //*****************************************************************************
244 void QMyMainWindow::mousePressEvent(QMouseEvent * e)
245 {
246 if (!g_UpAndRunning)
247 {
248 return;
249 }
250 if (e->button() == LeftButton)
251 {
252 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1,
253 e->x(), e->y());
254 }
255 else if (e->button() == RightButton)
256 {
257 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON2,
258 e->x(), e->y());
259 }
260 else if (e->button() == MidButton)
261 {
262 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON3,
263 e->x(), e->y());
264 }
265 }
266
267 //*****************************************************************************
268 void QMyMainWindow::mouseReleaseEvent(QMouseEvent * e)
269 {
270 if (!g_UpAndRunning)
271 {
272 return;
273 }
274 if (e->button() == LeftButton)
275 {
276 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, e->x(), e->y());
277 }
278 else if (e->button() == RightButton)
279 {
280 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2, e->x(), e->y());
281 }
282 else if (e->button() == MidButton)
283 {
284 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3, e->x(), e->y());
285 }
286 }
287
288 //*****************************************************************************
289 void QMyMainWindow::wheelEvent(QWheelEvent * e)
290 {
291 if (!g_UpAndRunning)
292 {
293 return;
294 }
295 if (e->delta() > 0)
296 {
297 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON4, e->x(), e->y());
298 }
299 else if (e->delta() < 0)
300 {
301 rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON5, e->x(), e->y());
302 }
303 }
304
305 //*****************************************************************************
306 int GetScanCode(QKeyEvent* e)
307 {
308 int Key = e->key();
309 int ScanCode = 0;
310 Qt::ButtonState bs = e->state();
311 if (!(bs & Qt::ShiftButton)) // shift is not down
312 {
313 if (Key == 42) // *
314 return 0x37;
315 if (Key == 43) // +
316 return 0x4e;
317 }
318 switch (Key)
319 {
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
421 }
422 // if (ScanCode == 0)
423 // printf("key %d scancode %d\n", Key, ScanCode);
424 return ScanCode;
425 }
426
427 //*****************************************************************************
428 void QMyMainWindow::keyPressEvent(QKeyEvent* e)
429 {
430 if (!g_UpAndRunning)
431 return;
432 int ScanCode = GetScanCode(e);
433 if (ScanCode != 0)
434 {
435 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS, ScanCode, 0);
436 e->accept();
437 }
438 }
439
440 //*****************************************************************************
441 void QMyMainWindow::keyReleaseEvent(QKeyEvent* e)
442 {
443 if (!g_UpAndRunning)
444 {
445 return;
446 }
447 int ScanCode = GetScanCode(e);
448 if (ScanCode != 0)
449 {
450 rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, ScanCode, 0);
451 e->accept();
452 }
453 }
454
455 //*****************************************************************************
456 void QMyMainWindow::paintEvent(QPaintEvent * pe)
457 {
458 QRect Rect;
459
460 Rect = pe->rect();
461 bitBlt(this, Rect.left(), Rect.top(), g_BS, Rect.left(), Rect.top(),
462 Rect.width(), Rect.height());
463 }
464
465 //*****************************************************************************
466 void QMyMainWindow::closeEvent(QCloseEvent * e)
467 {
468 e->accept();
469 }
470
471 //*****************************************************************************
472 bool QMyMainWindow::event(QEvent * e)
473 {
474 return QWidget::event(e);
475 }
476
477 //*****************************************************************************
478 void QMyMainWindow::dataReceived()
479 {
480 if (!rdp_loop(&g_deactivated, &g_ext_disc_reason))
481 {
482 g_SV->close();
483 }
484 #ifdef WITH_RDPSND
485 if (g_dsp_busy)
486 {
487 if (g_SoundNotifier == 0)
488 {
489 g_SoundNotifier = new QSocketNotifier(g_dsp_fd, QSocketNotifier::Write,
490 g_MW);
491 g_MW->connect(g_SoundNotifier, SIGNAL(activated(int)), g_MW,
492 SLOT(soundSend()));
493 }
494 else
495 {
496 if (!g_SoundNotifier->isEnabled())
497 {
498 g_SoundNotifier->setEnabled(true);
499 }
500 }
501 }
502 #endif
503 }
504
505 /******************************************************************************/
506 void QMyMainWindow::soundSend()
507 {
508 #ifdef WITH_RDPSND
509 g_SoundNotifier->setEnabled(false);
510 wave_out_play();
511 if (g_dsp_busy)
512 {
513 g_SoundNotifier->setEnabled(true);
514 }
515 #endif
516 }
517
518 //*****************************************************************************
519 void QMyScrollView::keyPressEvent(QKeyEvent * e)
520 {
521 g_MW->keyPressEvent(e);
522 }
523
524 //*****************************************************************************
525 void QMyScrollView::keyReleaseEvent(QKeyEvent * e)
526 {
527 g_MW->keyReleaseEvent(e);
528 }
529
530
531 //*****************************************************************************
532 void ui_begin_update(void)
533 {
534 g_P1->begin(g_MW);
535 g_P2->begin(g_BS);
536 }
537
538 //*****************************************************************************
539 void ui_end_update(void)
540 {
541 g_P1->end();
542 g_P2->end();
543 }
544
545 /*****************************************************************************/
546 int ui_init(void)
547 {
548 g_App = new QApplication(g_argc, g_argv);
549 return 1;
550 }
551
552 /*****************************************************************************/
553 void ui_deinit(void)
554 {
555 delete g_App;
556 }
557
558 /*****************************************************************************/
559 int ui_create_window(void)
560 {
561 int w, h;
562 QPainter * painter;
563 QWidget * desktop;
564
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));
572 delete painter;
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)
582 {
583 g_SV->resize(w, h);
584 }
585 else
586 {
587 g_SV->resize(g_width + 4, g_height + 4);
588 }
589 g_SV->setMaximumWidth(g_width + 4);
590 g_SV->setMaximumHeight(g_height + 4);
591 g_App->setMainWidget(g_SV);
592 g_SV->show();
593 g_MW->setMouseTracking(true);
594 if (g_title[0] != 0)
595 {
596 g_SV->setCaption(g_title);
597 }
598
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);*/
608
609 return 1;
610 }
611
612 //*****************************************************************************
613 void ui_main_loop(void)
614 {
615 #ifdef WITH_RDPSND
616 // init sound
617 if (g_rdpsnd)
618 {
619 rdpsnd_init();
620 }
621 #endif
622 // connect
623 if (!rdp_connect(g_servername, g_flags, "", "", "", ""))
624 {
625 return;
626 }
627 // start notifier
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()));
631 g_UpAndRunning = 1;
632 // app main loop
633 g_App->exec();
634 }
635
636 //*****************************************************************************
637 void ui_destroy_window(void)
638 {
639 delete g_MW;
640 delete g_SV;
641 delete g_BS;
642 delete g_DS;
643 delete g_P1;
644 delete g_P2;
645 delete g_ClipRect;
646 }
647
648 /*****************************************************************************/
649 void ui_bell(void)
650 {
651 }
652
653 /*****************************************************************************/
654 int ui_select(int in_val)
655 {
656 if (g_sock == 0)
657 {
658 g_sock = in_val;
659 }
660 return 1;
661 }
662
663 /*****************************************************************************/
664 void ui_destroy_cursor(void * cursor)
665 {
666 QCursor * Cursor;
667 Cursor = (QCursor*)cursor;
668 if (Cursor != NULL)
669 {
670 delete Cursor;
671 }
672 }
673
674 /*****************************************************************************/
675 void* ui_create_glyph(int width, int height, uint8 * data)
676 {
677 QBitmap * Bitmap;
678 Bitmap = new QBitmap(width, height, data);
679 Bitmap->setMask(*Bitmap);
680 return (HGLYPH)Bitmap;
681 }
682
683 /*****************************************************************************/
684 void ui_destroy_glyph(void * glyph)
685 {
686 QBitmap* Bitmap;
687 Bitmap = (QBitmap*)glyph;
688 delete Bitmap;
689 }
690
691 /*****************************************************************************/
692 void ui_destroy_bitmap(void * bmp)
693 {
694 QPixmap * Pixmap;
695 Pixmap = (QPixmap*)bmp;
696 delete Pixmap;
697 }
698
699 /*****************************************************************************/
700 void ui_reset_clip(void)
701 {
702 g_P1->setClipRect(0, 0, g_width, g_height);
703 g_P2->setClipRect(0, 0, g_width, g_height);
704 delete g_ClipRect;
705 g_ClipRect = new QRegion(0, 0, g_width, g_height);
706 }
707
708 /*****************************************************************************/
709 void ui_set_clip(int x, int y, int cx, int cy)
710 {
711 g_P1->setClipRect(x, y, cx, cy);
712 g_P2->setClipRect(x, y, cx, cy);
713 delete g_ClipRect;
714 g_ClipRect = new QRegion(x, y, cx, cy);
715 }
716
717 /*****************************************************************************/
718 void * ui_create_colourmap(COLOURMAP * colours)
719 {
720 QColorMap* LCM;
721 int i, r, g, b;
722 LCM = (QColorMap*)malloc(sizeof(QColorMap));
723 memset(LCM, 0, sizeof(QColorMap));
724 i = 0;
725 while (i < colours->ncolours && i < 256)
726 {
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;
731 i++;
732 }
733 LCM->NumColors = colours->ncolours;
734 return LCM;
735 }
736
737 //*****************************************************************************
738 // todo, does this leak at end of program
739 void ui_destroy_colourmap(HCOLOURMAP map)
740 {
741 QColorMap * LCM;
742 LCM = (QColorMap*)map;
743 if (LCM == NULL)
744 return;
745 free(LCM);
746 }
747
748 /*****************************************************************************/
749 void ui_set_colourmap(void * map)
750 {
751 // destoy old colormap
752 ui_destroy_colourmap(g_CM);
753 g_CM = (QColorMap*)map;
754 }
755
756 /*****************************************************************************/
757 HBITMAP ui_create_bitmap(int width, int height, uint8 * data)
758 {
759 QImage * Image = NULL;
760 QPixmap * Pixmap;
761 uint32 * d = NULL;
762 uint16 * s;
763 int i;
764
765 switch (g_server_depth)
766 {
767 case 8:
768 Image = new QImage(data, width, height, 8, (QRgb*)&g_CM->RGBColors,
769 g_CM->NumColors, QImage::IgnoreEndian);
770 break;
771 case 15:
772 d = (uint32*)malloc(width * height * 4);
773 s = (uint16*)data;
774 for (i = 0; i < width * height; i++)
775 {
776 d[i] = Color15to32(s[i]);
777 }
778 Image = new QImage((uint8*)d, width, height, 32, NULL,
779 0, QImage::IgnoreEndian);
780 break;
781 case 16:
782 d = (uint32*)malloc(width * height * 4);
783 s = (uint16*)data;
784 for (i = 0; i < width * height; i++)
785 {
786 d[i] = Color16to32(s[i]);
787 }
788 Image = new QImage((uint8*)d, width, height, 32, NULL,
789 0, QImage::IgnoreEndian);
790 break;
791 case 24:
792 d = (uint32*)malloc(width * height * 4);
793 memset(d, 0, width * height * 4);
794 for (i = 0; i < width * height; i++)
795 {
796 memcpy(d + i, data + i * 3, 3);
797 }
798 Image = new QImage((uint8*)d, width, height, 32, NULL,
799 0, QImage::IgnoreEndian);
800 break;
801 }
802 if (Image == NULL)
803 {
804 return NULL;
805 }
806 Pixmap = new QPixmap();
807 Pixmap->convertFromImage(*Image);
808 delete Image;
809 if (d != NULL)
810 {
811 free(d);
812 }
813 return (HBITMAP)Pixmap;
814 }
815
816 //******************************************************************************
817 // adjust coordinates for cliping rect
818 int WarpCoords(int * x, int * y, int * cx, int * cy, int * srcx, int * srcy)
819 {
820 int dx, dy;
821 QRect InRect(*x, *y, *cx, *cy);
822 QRect OutRect;
823 QRect CRect = g_ClipRect->boundingRect();
824 OutRect = InRect.intersect(CRect);
825 if (OutRect.isEmpty())
826 {
827 return False;
828 }
829 dx = OutRect.x() - InRect.x();
830 dy = OutRect.y() - InRect.y();
831 *x = OutRect.x();
832 *y = OutRect.y();
833 *cx = OutRect.width();
834 *cy = OutRect.height();
835 *srcx = *srcx + dx;
836 *srcy = *srcy + dy;
837 return True;
838 }
839
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)
846 {
847 if (WarpCoords(&dx, &dy, &sw, &sh, &sx, &sy))
848 {
849 if (dst1 != NULL)
850 {
851 if (src == NULL)
852 {
853 bitBlt(dst1, dx, dy, dst1, sx, sy, sw, sh, rop, im);
854 }
855 else
856 {
857 bitBlt(dst1, dx, dy, src, sx, sy, sw, sh, rop, im);
858 }
859 }
860 if (dst2 != NULL)
861 {
862 if (src == NULL)
863 {
864 bitBlt(dst2, dx, dy, dst2, sx, sy, sw, sh, rop, im);
865 }
866 else
867 {
868 bitBlt(dst2, dx, dy, src, sx, sy, sw, sh, rop, im);
869 }
870 }
871 }
872 }
873
874 #define DO_GLYPH(ttext,idx) \
875 { \
876 glyph = cache_get_font (font, ttext[idx]); \
877 if (!(flags & TEXT2_IMPLICIT_X)) \
878 { \
879 xyoffset = ttext[++idx]; \
880 if ((xyoffset & 0x80)) \
881 { \
882 if (flags & TEXT2_VERTICAL) \
883 y += ttext[idx+1] | (ttext[idx+2] << 8); \
884 else \
885 x += ttext[idx+1] | (ttext[idx+2] << 8); \
886 idx += 2; \
887 } \
888 else \
889 { \
890 if (flags & TEXT2_VERTICAL) \
891 y += xyoffset; \
892 else \
893 x += xyoffset; \
894 } \
895 } \
896 if (glyph != NULL) \
897 { \
898 g_P2->drawPixmap(x + glyph->offset, y + glyph->baseline, \
899 *((QBitmap*)glyph->pixmap)); \
900 if (flags & TEXT2_IMPLICIT_X) \
901 x += glyph->width; \
902 } \
903 }
904
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)
911 {
912 FONTGLYPH * glyph;
913 int i, j, xyoffset;
914 DATABLOB * entry;
915
916 SetColorx(&g_Color1, fgcolour);
917 SetColorx(&g_Color2, bgcolour);
918 g_P2->setBackgroundColor(g_Color2);
919 g_P2->setPen(g_Color1);
920 if (boxcx > 1)
921 {
922 g_P2->fillRect(boxx, boxy, boxcx, boxcy, QBrush(g_Color2));
923 }
924 else if (mixmode == MIX_OPAQUE)
925 {
926 g_P2->fillRect(clipx, clipy, clipcx, clipcy, QBrush(g_Color2));
927 }
928
929 /* Paint text, character by character */
930 for (i = 0; i < length;)
931 {
932 switch (text[i])
933 {
934 case 0xff:
935 if (i + 2 < length)
936 {
937 cache_put_text(text[i + 1], text, text[i + 2]);
938 }
939 else
940 {
941 error("this shouldn't be happening\n");
942 exit(1);
943 }
944 /* this will move pointer from start to first character after FF
945 command */
946 length -= i + 3;
947 text = &(text[i + 3]);
948 i = 0;
949 break;
950
951 case 0xfe:
952 entry = cache_get_text(text[i + 1]);
953 if (entry != NULL)
954 {
955 if ((((uint8 *) (entry->data))[1] == 0) &&
956 (!(flags & TEXT2_IMPLICIT_X)))
957 {
958 if (flags & TEXT2_VERTICAL)
959 {
960 y += text[i + 2];
961 }
962 else
963 {
964 x += text[i + 2];
965 }
966 }
967 for (j = 0; j < entry->size; j++)
968 {
969 DO_GLYPH(((uint8 *) (entry->data)), j);
970 }
971 }
972 if (i + 2 < length)
973 {
974 i += 3;
975 }
976 else
977 {
978 i += 2;
979 }
980 length -= i;
981 /* this will move pointer from start to first character after FE
982 command */
983 text = &(text[i]);
984 i = 0;
985 break;
986
987 default:
988 DO_GLYPH(text, i);
989 i++;
990 break;
991 }
992 }
993 if (boxcx > 1)
994 {
995 bitBltClip(g_MW, NULL, boxx, boxy, g_BS, boxx, boxy, boxcx, boxcy,
996 Qt::CopyROP, true);
997 }
998 else
999 {
1000 bitBltClip(g_MW, NULL, clipx, clipy, g_BS, clipx, clipy, clipcx,
1001 clipcy, Qt::CopyROP, true);
1002 }
1003 }
1004
1005 /*****************************************************************************/
1006 void ui_line(uint8 opcode, int startx, int starty, int endx, int endy,
1007 PEN * pen)
1008 {
1009 SetColorx(&g_Color1, pen->colour);
1010 SetOpCode(opcode);
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);
1018 }
1019
1020 /*****************************************************************************/
1021 // not used
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)
1025 {
1026 }
1027
1028 /*****************************************************************************/
1029 void ui_memblt(uint8 opcode, int x, int y, int cx, int cy,
1030 HBITMAP src, int srcx, int srcy)
1031 {
1032 QPixmap* Pixmap;
1033 Pixmap = (QPixmap*)src;
1034 if (Pixmap != NULL)
1035 {
1036 SetOpCode(opcode);
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);
1040 }
1041 }
1042
1043 //******************************************************************************
1044 void CommonDeskSave(QPixmap* Pixmap1, QPixmap* Pixmap2, int Offset, int x,
1045 int y, int cx, int cy, int dir)
1046 {
1047 int lx;
1048 int ly;
1049 int x1;
1050 int y1;
1051 int width;
1052 int lcx;
1053 int right;
1054 int bottom;
1055 lx = Offset % 480;
1056 ly = Offset / 480;
1057 y1 = y;
1058 right = x + cx;
1059 bottom = y + cy;
1060 while (y1 < bottom)
1061 {
1062 x1 = x;
1063 lcx = cx;
1064 while (x1 < right)
1065 {
1066 width = 480 - lx;
1067 if (width > lcx)
1068 width = lcx;
1069 if (dir == 0)
1070 bitBlt(Pixmap1, lx, ly, Pixmap2, x1, y1, width, 1, Qt::CopyROP, true);
1071 else
1072 bitBlt(Pixmap2, x1, y1, Pixmap1, lx, ly, width, 1, Qt::CopyROP, true);
1073 lx = lx + width;
1074 if (lx >= 480)
1075 {
1076 lx = 0;
1077 ly++;
1078 if (ly >= 480)
1079 ly = 0;
1080 }
1081 lcx = lcx - width;
1082 x1 = x1 + width;
1083 }
1084 y1++;
1085 }
1086 }
1087
1088 /*****************************************************************************/
1089 void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
1090 {
1091 QPixmap * Pixmap;
1092
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);
1096 delete Pixmap;
1097 }
1098
1099 /*****************************************************************************/
1100 void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
1101 {
1102 CommonDeskSave(g_DS, g_BS, offset, x, y, cx, cy, 0);
1103 }
1104
1105 /*****************************************************************************/
1106 void ui_rect(int x, int y, int cx, int cy, int colour)
1107 {
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));
1111 }
1112
1113 /*****************************************************************************/
1114 void ui_screenblt(uint8 opcode, int x, int y, int cx, int cy,
1115 int srcx, int srcy)
1116 {
1117 SetOpCode(opcode);
1118 bitBltClip(g_MW, g_BS, x, y, NULL, srcx, srcy, cx, cy, Qt::CopyROP, true);
1119 ResetOpCode(opcode);
1120 }
1121
1122 /*****************************************************************************/
1123 void ui_patblt(uint8 opcode, int x, int y, int cx, int cy,
1124 BRUSH* brush, int bgcolour, int fgcolour)
1125 {
1126 QBitmap* Bitmap;
1127 QBrush* Brush;
1128 uint8 ipattern[8], i;
1129 SetOpCode(opcode);
1130 switch (brush->style)
1131 {
1132 case 0:
1133 SetColorx(&g_Color1, fgcolour);
1134 g_P2->fillRect(x, y, cx, cy, QBrush(g_Color1));
1135 break;
1136 case 3:
1137 SetColorx(&g_Color1, fgcolour);
1138 SetColorx(&g_Color2, bgcolour);
1139 for (i = 0; i != 8; i++)
1140 {
1141 ipattern[7 - i] = ~brush->pattern[i];
1142 }
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);
1149 delete Brush;
1150 delete Bitmap;
1151 g_P2->setBackgroundMode(Qt::TransparentMode);
1152 g_P2->setBrushOrigin(0, 0);
1153 break;
1154 }
1155 ResetOpCode(opcode);
1156 bitBltClip(g_MW, NULL, x, y, g_BS, x, y, cx, cy, Qt::CopyROP, true);
1157 }
1158
1159 /*****************************************************************************/
1160 void ui_destblt(uint8 opcode, int x, int y, int cx, int cy)
1161 {
1162 SetOpCode(opcode);
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);
1166 }
1167
1168 /*****************************************************************************/
1169 void ui_move_pointer(int x, int y)
1170 {
1171 }
1172
1173 /*****************************************************************************/
1174 void ui_set_null_cursor(void)
1175 {
1176 g_MW->setCursor(10); // Qt::BlankCursor
1177 }
1178
1179 /*****************************************************************************/
1180 void ui_paint_bitmap(int x, int y, int cx, int cy,
1181 int width, int height, uint8* data)
1182 {
1183 QImage * Image = NULL;
1184 QPixmap * Pixmap;
1185 uint32 * d = NULL;
1186 uint16 * s;
1187 int i;
1188
1189 switch (g_server_depth)
1190 {
1191 case 8:
1192 Image = new QImage(data, width, height, 8, (QRgb*)&g_CM->RGBColors,
1193 g_CM->NumColors, QImage::IgnoreEndian);
1194 break;
1195 case 15:
1196 d = (uint32*)malloc(width * height * 4);
1197 s = (uint16*)data;
1198 for (i = 0; i < width * height; i++)
1199 {
1200 d[i] = Color15to32(s[i]);
1201 }
1202 Image = new QImage((uint8*)d, width, height, 32, NULL,
1203 0, QImage::IgnoreEndian);
1204 break;
1205 case 16:
1206 d = (uint32*)malloc(width * height * 4);
1207 s = (uint16*)data;
1208 for (i = 0; i < width * height; i++)
1209 {
1210 d[i] = Color16to32(s[i]);
1211 }
1212 Image = new QImage((uint8*)d, width, height, 32, NULL,
1213 0, QImage::IgnoreEndian);
1214 break;
1215 case 24:
1216 d = (uint32*)malloc(width * height * 4);
1217 memset(d, 0, width * height * 4);
1218 for (i = 0; i < width * height; i++)
1219 {
1220 memcpy(d + i, data + i * 3, 3);
1221 }
1222 Image = new QImage((uint8*)d, width, height, 32, NULL,
1223 0, QImage::IgnoreEndian);
1224 break;
1225 }
1226 if (Image == NULL)
1227 {
1228 return;
1229 }
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);
1234 delete Image;
1235 delete Pixmap;
1236 if (d != NULL)
1237 {
1238 free(d);
1239 }
1240 }
1241
1242 //******************************************************************************
1243 int Is24On(uint8* Data, int X, int Y)
1244 {
1245 uint8 R, G, B;
1246 int Start;
1247 Start = Y * 32 * 3 + X * 3;
1248 R = Data[Start];
1249 G = Data[Start + 1];
1250 B = Data[Start + 2];
1251 return !((R == 0) && (G == 0) && (B == 0));
1252 }
1253
1254 //******************************************************************************
1255 int Is1On(uint8* Data, int X, int Y)
1256 {
1257 int Start;
1258 int Shift;
1259 Start = (Y * 32) / 8 + X / 8;
1260 Shift = X % 8;
1261 return (Data[Start] & (0x80 >> Shift)) == 0;
1262 }
1263
1264 //******************************************************************************
1265 void Set1(uint8* Data, int X, int Y)
1266 {
1267 int Start;
1268 int Shift;
1269 Start = (Y * 32) / 8 + X / 8;
1270 Shift = X % 8;
1271 Data[Start] = Data[Start] | (0x80 >> Shift);
1272 }
1273
1274 //******************************************************************************
1275 void FlipOver(uint8* Data)
1276 {
1277 uint8 AData[128];
1278 int Index;
1279 memcpy(AData, Data, 128);
1280 for (Index = 0; Index <= 31; Index++)
1281 {
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];
1286 }
1287 }
1288
1289 /*****************************************************************************/
1290 void ui_set_cursor(HCURSOR cursor)
1291 {
1292 QCursor* Cursor;
1293 Cursor = (QCursor*)cursor;
1294 if (Cursor != NULL)
1295 g_MW->setCursor(*Cursor);
1296 }
1297
1298 /*****************************************************************************/
1299 HCURSOR ui_create_cursor(unsigned int x, unsigned int y,
1300 int width, int height,
1301 uint8* andmask, uint8* xormask)
1302 {
1303 uint8 AData[128];
1304 uint8 AMask[128];
1305 QBitmap* DataBitmap;
1306 QBitmap* MaskBitmap;
1307 QCursor* Cursor;
1308 int I1, I2, BOn, MOn;
1309
1310 if (width != 32 || height != 32)
1311 {
1312 return 0;
1313 }
1314 memset(AData, 0, 128);
1315 memset(AMask, 0, 128);
1316 for (I1 = 0; I1 <= 31; I1++)
1317 {
1318 for (I2 = 0; I2 <= 31; I2++)
1319 {
1320 MOn = Is24On(xormask, I1, I2);
1321 BOn = Is1On(andmask, I1, I2);
1322 if (BOn ^ MOn) // xor
1323 {
1324 Set1(AData, I1, I2);
1325 if (!MOn)
1326 {
1327 Set1(AMask, I1, I2);
1328 }
1329 }
1330 if (MOn)
1331 {
1332 Set1(AMask, I1, I2);
1333 }
1334 }
1335 }
1336 FlipOver(AData);
1337 FlipOver(AMask);
1338 DataBitmap = new QBitmap(32, 32, AData);
1339 MaskBitmap = new QBitmap(32, 32, AMask);
1340 Cursor = new QCursor(*DataBitmap, *MaskBitmap, x, y);
1341 delete DataBitmap;
1342 delete MaskBitmap;
1343 return Cursor;
1344 }
1345
1346 /*****************************************************************************/
1347 uint16 ui_get_numlock_state(uint32 state)
1348 {
1349 return 0;
1350 }
1351
1352 /*****************************************************************************/
1353 uint32 read_keyboard_state(void)
1354 {
1355 return 0;
1356 }
1357
1358 /*****************************************************************************/
1359 void ui_resize_window(void)
1360 {
1361 }
1362
1363 /*****************************************************************************/
1364 void ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints,
1365 BRUSH * brush, int bgcolour, int fgcolour)
1366 {
1367 }
1368
1369 /*****************************************************************************/
1370 /* todo, use qt function for this (QPainter::drawPolyline) */
1371 void ui_polyline(uint8 opcode, POINT * points, int npoints, PEN * pen)
1372 {
1373 int i, x, y, dx, dy;
1374
1375 if (npoints > 0)
1376 {
1377 x = points[0].x;
1378 y = points[0].y;
1379 for (i = 1; i < npoints; i++)
1380 {
1381 dx = points[i].x;
1382 dy = points[i].y;
1383 ui_line(opcode, x, y, x + dx, y + dy, pen);
1384 x = x + dx;
1385 y = y + dy;
1386 }
1387 }
1388 }
1389
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)
1394 {
1395 }
1396
1397 /*****************************************************************************/
1398 void generate_random(uint8 * random)
1399 {
1400 QFile File("/dev/random");
1401 File.open(IO_ReadOnly);
1402 if (File.readBlock((char*)random, 32) == 32)
1403 {
1404 return;
1405 }
1406 warning("no /dev/random\n");
1407 memcpy(random, "12345678901234567890123456789012", 32);
1408 }
1409
1410 /*****************************************************************************/
1411 void save_licence(uint8 * data, int length)
1412 {
1413 char * home, * path, * tmppath;
1414 int fd;
1415
1416 home = getenv("HOME");
1417 if (home == NULL)
1418 {
1419 return;
1420 }
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)
1425 {
1426 perror(path);
1427 return;
1428 }
1429 /* write licence to licence.hostname.new, then atomically rename to
1430 licence.hostname */
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);
1436 if (fd == -1)
1437 {
1438 perror(tmppath);
1439 return;
1440 }
1441 if (write(fd, data, length) != length)
1442 {
1443 perror(tmppath);
1444 unlink(tmppath);
1445 }
1446 else if (rename(tmppath, path) == -1)
1447 {
1448 perror(path);
1449 unlink(tmppath);
1450 }
1451 close(fd);
1452 xfree(tmppath);
1453 xfree(path);
1454 }
1455
1456 /*****************************************************************************/
1457 int load_licence(uint8 ** data)
1458 {
1459 char * home, * path;
1460 struct stat st;
1461 int fd, length;
1462
1463 home = getenv("HOME");
1464 if (home == NULL)
1465 {
1466 return -1;
1467 }
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);
1472 if (fd == -1)
1473 {
1474 return -1;
1475 }
1476 if (fstat(fd, &st))
1477 {
1478 close(fd);
1479 xfree(path);
1480 return -1;
1481 }
1482 *data = (uint8 *) xmalloc(st.st_size);
1483 length = read(fd, *data, st.st_size);
1484 close(fd);
1485 xfree(path);
1486 return length;
1487 }
1488
1489 /*****************************************************************************/
1490 void* xrealloc(void * in_val, int size)
1491 {
1492 return realloc(in_val, size);
1493 }
1494
1495 /*****************************************************************************/
1496 void* xmalloc(int size)
1497 {
1498 return malloc(size);
1499 }
1500
1501 /*****************************************************************************/
1502 void xfree(void * in_val)
1503 {
1504 if (in_val != NULL)
1505 {
1506 free(in_val);
1507 }
1508 }
1509
1510 /*****************************************************************************/
1511 char * xstrdup(const char * s)
1512 {
1513 char * mem = strdup(s);
1514 if (mem == NULL)
1515 {
1516 perror("strdup");
1517 exit(1);
1518 }
1519 return mem;
1520 }
1521
1522 /*****************************************************************************/
1523 void warning(char * format, ...)
1524 {
1525 va_list ap;
1526
1527 fprintf(stderr, "WARNING: ");
1528 va_start(ap, format);
1529 vfprintf(stderr, format, ap);
1530 va_end(ap);
1531 }
1532
1533 /*****************************************************************************/
1534 void unimpl(char * format, ...)
1535 {
1536 va_list ap;
1537
1538 fprintf(stderr, "NOT IMPLEMENTED: ");
1539 va_start(ap, format);
1540 vfprintf(stderr, format, ap);
1541 va_end(ap);
1542 }
1543
1544 /*****************************************************************************/
1545 void error(char * format, ...)
1546 {
1547 va_list ap;
1548
1549 fprintf(stderr, "ERROR: ");
1550 va_start(ap, format);
1551 vfprintf(stderr, format, ap);
1552 va_end(ap);
1553 }
1554
1555 /*****************************************************************************/
1556 void out_params(void)
1557 {
1558 fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
1559 fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
1560 fprintf(stderr, "QT uiport by Jay Sorg\n");
1561 fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
1562 fprintf(stderr, "Usage: qtrdesktop [options] server\n");
1563 fprintf(stderr, " -g WxH: desktop geometry\n");
1564 fprintf(stderr, " -4: use RDP version 4\n");
1565 fprintf(stderr, " -5: use RDP version 5 (default)\n");
1566 fprintf(stderr, " -t 3389: tcp port)\n");
1567 fprintf(stderr, " -a 8|16|24: connection colour depth\n");
1568 fprintf(stderr, " -T title: window title\n");
1569 fprintf(stderr, " -P: use persistent bitmap caching\n");
1570 fprintf(stderr, " -0: attach to console\n");
1571 fprintf(stderr, " -z: enable rdp compression\n");
1572 fprintf(stderr, " -r sound: enable sound\n");
1573 fprintf(stderr, "\n");
1574 }
1575
1576 /*****************************************************************************/
1577 /* produce a hex dump */
1578 void hexdump(uint8 * p, uint32 len)
1579 {
1580 uint8 * line = p;
1581 int i, thisline;
1582 uint32 offset = 0;
1583
1584 while (offset < len)
1585 {
1586 printf("%04x ", offset);
1587 thisline = len - offset;
1588 if (thisline > 16)
1589 {
1590 thisline = 16;
1591 }
1592 for (i = 0; i < thisline; i++)
1593 {
1594 printf("%02x ", line[i]);
1595 }
1596 for (; i < 16; i++)
1597 {
1598 printf(" ");
1599 }
1600 for (i = 0; i < thisline; i++)
1601 {
1602 printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
1603 }
1604 printf("\n");
1605 offset += thisline;
1606 line += thisline;
1607 }
1608 }
1609
1610 /*****************************************************************************/
1611 int rd_pstcache_mkdir(void)
1612 {
1613 char * home;
1614 char bmpcache_dir[256];
1615
1616 home = getenv("HOME");
1617 if (home == NULL)
1618 {
1619 return False;
1620 }
1621 sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
1622 if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1623 {
1624 perror(bmpcache_dir);
1625 return False;
1626 }
1627 sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
1628 if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1629 {
1630 perror(bmpcache_dir);
1631 return False;
1632 }
1633 return True;
1634 }
1635
1636 /*****************************************************************************/
1637 int rd_open_file(char * filename)
1638 {
1639 char * home;
1640 char fn[256];
1641 int fd;
1642
1643 home = getenv("HOME");
1644 if (home == NULL)
1645 {
1646 return -1;
1647 }
1648 sprintf(fn, "%s/.rdesktop/%s", home, filename);
1649 fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1650 if (fd == -1)
1651 {
1652 perror(fn);
1653 }
1654 return fd;
1655 }
1656
1657 /*****************************************************************************/
1658 void rd_close_file(int fd)
1659 {
1660 close(fd);
1661 }
1662
1663 /*****************************************************************************/
1664 int rd_read_file(int fd, void * ptr, int len)
1665 {
1666 return read(fd, ptr, len);
1667 }
1668
1669 /*****************************************************************************/
1670 int rd_write_file(int fd, void * ptr, int len)
1671 {
1672 return write(fd, ptr, len);
1673 }
1674
1675 /*****************************************************************************/
1676 int rd_lseek_file(int fd, int offset)
1677 {
1678 return lseek(fd, offset, SEEK_SET);
1679 }
1680
1681 /*****************************************************************************/
1682 int rd_lock_file(int fd, int start, int len)
1683 {
1684 struct flock lock;
1685
1686 lock.l_type = F_WRLCK;
1687 lock.l_whence = SEEK_SET;
1688 lock.l_start = start;
1689 lock.l_len = len;
1690 if (fcntl(fd, F_SETLK, &lock) == -1)
1691 {
1692 return False;
1693 }
1694 return True;
1695 }
1696
1697 /*****************************************************************************/
1698 void get_username_and_hostname(void)
1699 {
1700 char fullhostname[64];
1701 char * p;
1702 struct passwd * pw;
1703
1704 STRNCPY(g_username, "unknown", sizeof(g_username));
1705 STRNCPY(g_hostname, "unknown", sizeof(g_hostname));
1706 pw = getpwuid(getuid());
1707 if (pw != NULL && pw->pw_name != NULL)
1708 {
1709 STRNCPY(g_username, pw->pw_name, sizeof(g_username));
1710 }
1711 if (gethostname(fullhostname, sizeof(fullhostname)) != -1)
1712 {
1713 p = strchr(fullhostname, '.');
1714 if (p != NULL)
1715 {
1716 *p = 0;
1717 }
1718 STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
1719 }
1720 }
1721
1722 /*****************************************************************************/
1723 int parse_parameters(int in_argc, char ** in_argv)
1724 {
1725 int i;
1726 char * p;
1727
1728 if (in_argc <= 1)
1729 {
1730 out_params();
1731 return 0;
1732 }
1733 g_argc = in_argc;
1734 g_argv = in_argv;
1735 for (i = 1; i < in_argc; i++)
1736 {
1737 strcpy(g_servername, in_argv[i]);
1738 if (strcmp(in_argv[i], "-g") == 0)
1739 {
1740 g_width = strtol(in_argv[i + 1], &p, 10);
1741 if (g_width <= 0)
1742 {
1743 error("invalid geometry\n");
1744 return 0;
1745 }
1746 if (*p == 'x')
1747 {
1748 g_height = strtol(p + 1, NULL, 10);
1749 }
1750 if (g_height <= 0)
1751 {
1752 error("invalid geometry\n");
1753 return 0;
1754 }
1755 g_width = (g_width + 3) & ~3;
1756 }
1757 else if (strcmp(in_argv[i], "-T") == 0)
1758 {
1759 strcpy(g_title, in_argv[i + 1]);
1760 }
1761 else if (strcmp(in_argv[i], "-4") == 0)
1762 {
1763 g_use_rdp5 = 0;
1764 }
1765 else if (strcmp(in_argv[i], "-5") == 0)
1766 {
1767 g_use_rdp5 = 1;
1768 }
1769 else if (strcmp(in_argv[i], "-a") == 0)
1770 {
1771 g_server_depth = strtol(in_argv[i + 1], &p, 10);
1772 if (g_server_depth != 8 && g_server_depth != 15 &&
1773 g_server_depth != 16 && g_server_depth != 24)
1774 {
1775 error("invalid bpp\n");
1776 return 0;
1777 }
1778 }
1779 else if (strcmp(in_argv[i], "-t") == 0)
1780 {
1781 g_tcp_port_rdp = strtol(in_argv[i + 1], &p, 10);
1782 }
1783 else if (strcmp(in_argv[i], "-P") == 0)
1784 {
1785 g_bitmap_cache_persist_enable = 1;
1786 }
1787 else if (strcmp(in_argv[i], "-0") == 0)
1788 {
1789 g_console_session = 1;
1790 }
1791 else if (strcmp(in_argv[i], "-z") == 0)
1792 {
1793 g_flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);
1794 }
1795 else if (strcmp(in_argv[i], "-r") == 0)
1796 {
1797 if (strcmp(in_argv[i + 1], "sound") == 0)
1798 {
1799 #ifdef WITH_RDPSND
1800 g_rdpsnd = 1;
1801 #endif
1802 }
1803 }
1804 }
1805 return 1;
1806 }
1807
1808 /*****************************************************************************/
1809 int main(int in_argc, char** in_argv)
1810 {
1811 get_username_and_hostname();
1812 if (!parse_parameters(in_argc, in_argv))
1813 {
1814 return 0;
1815 }
1816 if (!ui_init())
1817 {
1818 return 1;
1819 }
1820 if (!ui_create_window())
1821 {
1822 return 1;
1823 }
1824 ui_main_loop();
1825 ui_destroy_window();
1826 ui_deinit();
1827 return 0;
1828 }