There! Hello rdesktop, please lie down on that table, don't worry, this won't hurt...
[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
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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 return -1;
1479 }
1480 *data = (uint8 *) xmalloc(st.st_size);
1481 length = read(fd, *data, st.st_size);
1482 close(fd);
1483 xfree(path);
1484 return length;
1485 }
1486
1487 /*****************************************************************************/
1488 void* xrealloc(void * in_val, int size)
1489 {
1490 return realloc(in_val, size);
1491 }
1492
1493 /*****************************************************************************/
1494 void* xmalloc(int size)
1495 {
1496 return malloc(size);
1497 }
1498
1499 /*****************************************************************************/
1500 void xfree(void * in_val)
1501 {
1502 if (in_val != NULL)
1503 {
1504 free(in_val);
1505 }
1506 }
1507
1508 /*****************************************************************************/
1509 char * xstrdup(const char * s)
1510 {
1511 char * mem = strdup(s);
1512 if (mem == NULL)
1513 {
1514 perror("strdup");
1515 exit(1);
1516 }
1517 return mem;
1518 }
1519
1520 /*****************************************************************************/
1521 void warning(char * format, ...)
1522 {
1523 va_list ap;
1524
1525 fprintf(stderr, "WARNING: ");
1526 va_start(ap, format);
1527 vfprintf(stderr, format, ap);
1528 va_end(ap);
1529 }
1530
1531 /*****************************************************************************/
1532 void unimpl(char * format, ...)
1533 {
1534 va_list ap;
1535
1536 fprintf(stderr, "NOT IMPLEMENTED: ");
1537 va_start(ap, format);
1538 vfprintf(stderr, format, ap);
1539 va_end(ap);
1540 }
1541
1542 /*****************************************************************************/
1543 void error(char * format, ...)
1544 {
1545 va_list ap;
1546
1547 fprintf(stderr, "ERROR: ");
1548 va_start(ap, format);
1549 vfprintf(stderr, format, ap);
1550 va_end(ap);
1551 }
1552
1553 /*****************************************************************************/
1554 void out_params(void)
1555 {
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");
1572 }
1573
1574 /*****************************************************************************/
1575 /* produce a hex dump */
1576 void hexdump(uint8 * p, uint32 len)
1577 {
1578 uint8 * line = p;
1579 int i, thisline;
1580 uint32 offset = 0;
1581
1582 while (offset < len)
1583 {
1584 printf("%04x ", offset);
1585 thisline = len - offset;
1586 if (thisline > 16)
1587 {
1588 thisline = 16;
1589 }
1590 for (i = 0; i < thisline; i++)
1591 {
1592 printf("%02x ", line[i]);
1593 }
1594 for (; i < 16; i++)
1595 {
1596 printf(" ");
1597 }
1598 for (i = 0; i < thisline; i++)
1599 {
1600 printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
1601 }
1602 printf("\n");
1603 offset += thisline;
1604 line += thisline;
1605 }
1606 }
1607
1608 /*****************************************************************************/
1609 int rd_pstcache_mkdir(void)
1610 {
1611 char * home;
1612 char bmpcache_dir[256];
1613
1614 home = getenv("HOME");
1615 if (home == NULL)
1616 {
1617 return False;
1618 }
1619 sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
1620 if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1621 {
1622 perror(bmpcache_dir);
1623 return False;
1624 }
1625 sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
1626 if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1627 {
1628 perror(bmpcache_dir);
1629 return False;
1630 }
1631 return True;
1632 }
1633
1634 /*****************************************************************************/
1635 int rd_open_file(char * filename)
1636 {
1637 char * home;
1638 char fn[256];
1639 int fd;
1640
1641 home = getenv("HOME");
1642 if (home == NULL)
1643 {
1644 return -1;
1645 }
1646 sprintf(fn, "%s/.rdesktop/%s", home, filename);
1647 fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1648 if (fd == -1)
1649 {
1650 perror(fn);
1651 }
1652 return fd;
1653 }
1654
1655 /*****************************************************************************/
1656 void rd_close_file(int fd)
1657 {
1658 close(fd);
1659 }
1660
1661 /*****************************************************************************/
1662 int rd_read_file(int fd, void * ptr, int len)
1663 {
1664 return read(fd, ptr, len);
1665 }
1666
1667 /*****************************************************************************/
1668 int rd_write_file(int fd, void * ptr, int len)
1669 {
1670 return write(fd, ptr, len);
1671 }
1672
1673 /*****************************************************************************/
1674 int rd_lseek_file(int fd, int offset)
1675 {
1676 return lseek(fd, offset, SEEK_SET);
1677 }
1678
1679 /*****************************************************************************/
1680 int rd_lock_file(int fd, int start, int len)
1681 {
1682 struct flock lock;
1683
1684 lock.l_type = F_WRLCK;
1685 lock.l_whence = SEEK_SET;
1686 lock.l_start = start;
1687 lock.l_len = len;
1688 if (fcntl(fd, F_SETLK, &lock) == -1)
1689 {
1690 return False;
1691 }
1692 return True;
1693 }
1694
1695 /*****************************************************************************/
1696 void get_username_and_hostname(void)
1697 {
1698 char fullhostname[64];
1699 char * p;
1700 struct passwd * pw;
1701
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)
1706 {
1707 STRNCPY(g_username, pw->pw_name, sizeof(g_username));
1708 }
1709 if (gethostname(fullhostname, sizeof(fullhostname)) != -1)
1710 {
1711 p = strchr(fullhostname, '.');
1712 if (p != NULL)
1713 {
1714 *p = 0;
1715 }
1716 STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
1717 }
1718 }
1719
1720 /*****************************************************************************/
1721 int parse_parameters(int in_argc, char ** in_argv)
1722 {
1723 int i;
1724 char * p;
1725
1726 if (in_argc <= 1)
1727 {
1728 out_params();
1729 return 0;
1730 }
1731 g_argc = in_argc;
1732 g_argv = in_argv;
1733 for (i = 1; i < in_argc; i++)
1734 {
1735 strcpy(g_servername, in_argv[i]);
1736 if (strcmp(in_argv[i], "-g") == 0)
1737 {
1738 g_width = strtol(in_argv[i + 1], &p, 10);
1739 if (g_width <= 0)
1740 {
1741 error("invalid geometry\n");
1742 return 0;
1743 }
1744 if (*p == 'x')
1745 {
1746 g_height = strtol(p + 1, NULL, 10);
1747 }
1748 if (g_height <= 0)
1749 {
1750 error("invalid geometry\n");
1751 return 0;
1752 }
1753 g_width = (g_width + 3) & ~3;
1754 }
1755 else if (strcmp(in_argv[i], "-T") == 0)
1756 {
1757 strcpy(g_title, in_argv[i + 1]);
1758 }
1759 else if (strcmp(in_argv[i], "-4") == 0)
1760 {
1761 g_use_rdp5 = 0;
1762 }
1763 else if (strcmp(in_argv[i], "-5") == 0)
1764 {
1765 g_use_rdp5 = 1;
1766 }
1767 else if (strcmp(in_argv[i], "-a") == 0)
1768 {
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)
1772 {
1773 error("invalid bpp\n");
1774 return 0;
1775 }
1776 }
1777 else if (strcmp(in_argv[i], "-t") == 0)
1778 {
1779 g_tcp_port_rdp = strtol(in_argv[i + 1], &p, 10);
1780 }
1781 else if (strcmp(in_argv[i], "-P") == 0)
1782 {
1783 g_bitmap_cache_persist_enable = 1;
1784 }
1785 else if (strcmp(in_argv[i], "-0") == 0)
1786 {
1787 g_console_session = 1;
1788 }
1789 else if (strcmp(in_argv[i], "-z") == 0)
1790 {
1791 g_flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);
1792 }
1793 else if (strcmp(in_argv[i], "-r") == 0)
1794 {
1795 if (strcmp(in_argv[i + 1], "sound") == 0)
1796 {
1797 #ifdef WITH_RDPSND
1798 g_rdpsnd = 1;
1799 #endif
1800 }
1801 }
1802 }
1803 return 1;
1804 }
1805
1806 /*****************************************************************************/
1807 int main(int in_argc, char** in_argv)
1808 {
1809 get_username_and_hostname();
1810 if (!parse_parameters(in_argc, in_argv))
1811 {
1812 return 0;
1813 }
1814 if (!ui_init())
1815 {
1816 return 1;
1817 }
1818 if (!ui_create_window())
1819 {
1820 return 1;
1821 }
1822 ui_main_loop();
1823 ui_destroy_window();
1824 ui_deinit();
1825 return 0;
1826 }