1 /* -*- c-basic-offset: 8 -*-
2    rdesktop: A Remote Desktop Protocol client.
3    User interface services - QT Emb System
4    Copyright (C) Jay Sorg 2004-2005
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 //#define SHARP
22 
23 #ifdef SHARP
24 #include <qpe/qpeapplication.h>
25 #else
26 #include <qapplication.h>
27 #endif
28 #include <qcursor.h>
29 #include <qmainwindow.h>
30 #include <qwidget.h>
31 #include <qpainter.h>
32 #include <qimage.h>
33 #include <qsocketnotifier.h>
34 #include <qscrollview.h>
35 #include <qmessagebox.h>
36 #include <qpushbutton.h>
37 #include <qlineedit.h>
38 #include <qcombobox.h>
39 #include <qlabel.h>
40 #include <qfile.h>
41 #include <qcheckbox.h>
42 #include <qpopupmenu.h>
43 
44 #include <stdlib.h>
45 #include <stdarg.h> // va_list va_start va_end
46 #include <unistd.h> // gethostname
47 #include <pwd.h> // getpwuid
48 
49 #include "../rdesktop.h"
50 #include "qtewin.h"
51 
52 #define QT_OPTI
53 
54 extern int g_tcp_port_rdp;
55 int g_encryption = 1;
56 int g_bitmap_cache = 1;
57 int g_bitmap_cache_persist_enable = 0;
58 int g_bitmap_cache_precache = 1;
59 int g_use_rdp5 = 1;
60 int g_desktop_save = 1;
61 int g_bitmap_compression = 1;
62 int g_polygon_ellipse_orders = 0;
63 int g_rdp5_performanceflags =
64   RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
65 int g_console_session = 0;
66 int g_keylayout = 0x409; /* Defaults to US keyboard layout */
67 int g_keyboard_type = 0x4; /* Defaults to US keyboard layout */
68 int g_keyboard_subtype = 0x0; /* Defaults to US keyboard layout */
69 int g_keyboard_functionkeys = 0xc; /* Defaults to US keyboard layout */
70 int g_width = 640;
71 int g_height = 480;
72 int g_server_bpp = 8;
73 char g_hostname[16] = "";
74 char g_username[100] = "";
75 
76 #ifdef WITH_RDPSND
77 extern int g_dsp_busy;
78 extern int g_dsp_fd;
79 int g_rdpsnd = 0;
80 static QSocketNotifier * g_SoundNotifier = 0;
81 #endif
82 
83 /* types */
84 struct QColorMap
85 {
86   uint32 RGBColors[256];
87   uint32 NumColors;
88 };
89 
90 struct bitmap
91 {
92   int w;
93   int h;
94   uint8 * data;
95 };
96 
97 static int g_client_width = 640;
98 static int g_client_height = 480;
99 static uint32 g_flags = RDP_LOGON_NORMAL;
100 static char g_server[64] = "";
101 static char g_domain[16] = "";
102 static char g_password[16] = "";
103 static char g_shell[128] = "";
104 static char g_directory[32] = "";
105 static int g_fullscreen = 0;
106 static int g_global_sock = 0;
107 static int g_deactivated = 0;
108 static uint32 g_ext_disc_reason = 0;
109 
110 static QSocketNotifier * g_SocketNotifier = 0;
111 #ifdef SHARP
112 static QPEApplication * g_App = 0;
113 #else
114 static QApplication * g_App = 0;
115 #endif
116 static QMyMainWindow * g_MW = 0;
117 static QMyScrollView * g_SV = 0;
118 static struct QColorMap * g_CM = 0;
119 static uint8 * g_BS = 0; /* the screen data */
120 static int g_clipx = 0;
121 static int g_clipy = 0;
122 static int g_clipcx = 0;
123 static int g_clipcy = 0;
124 
125 /* Session Directory redirection */
126 BOOL g_redirect = False;
127 char g_redirect_server[64];
128 char g_redirect_domain[16];
129 char g_redirect_password[64];
130 char g_redirect_username[64];
131 char g_redirect_cookie[128];
132 uint32 g_redirect_flags = 0;
133 
134 #define BPP ((g_server_bpp + 7) / 8)
135 #define GETPIXEL8(d, x, y, w) (*(((uint8*)d) + ((y) * (w) + (x))))
136 #define GETPIXEL16(d, x, y, w) (*(((uint16*)d) + ((y) * (w) + (x))))
137 #define GETPIXEL32(d, x, y, w) (*(((uint32*)d) + ((y) * (w) + (x))))
138 #define SETPIXEL8(d, x, y, w, v) *(((uint8*)d) + ((y) * (w) + (x))) = v
139 #define SETPIXEL16(d, x, y, w, v) *(((uint16*)d) + ((y) * (w) + (x))) = v
140 #define SETPIXEL32(d, x, y, w, v) *(((uint32*)d) + ((y) * (w) + (x))) = v
141 
142 /******************************************************************************/
CleanString(QString * Item)143 void CleanString(QString * Item)
144 {
145   int i;
146 
147   i = Item->length() - 1;
148   while (i >= 0)
149   {
150     if (Item->at(i) == 10 || Item->at(i) == 13)
151     {
152       Item->remove(i, 1);
153     }
154     i--;
155   }
156 }
157 
158 /******************************************************************************/
QMyDialog(QWidget * parent)159 QMyDialog::QMyDialog(QWidget * parent) : QDialog(parent, "Settings", true)
160 {
161   int i, j;
162   char * home;
163   char Text[256];
164   QString Line;
165   QString ItemName;
166   QString ItemValue;
167 
168   // resize dialog
169   resize(230, 270);
170   // main list box
171   ListBox = new QListBox(this);
172   ListBox->move(10, 10);
173   ListBox->resize(200, 100);
174   connect(ListBox, SIGNAL(selectionChanged()), this, SLOT(ListBoxChanged()));
175   connect(ListBox, SIGNAL(selected(int)), this, SLOT(ListBoxSelected(int)));
176   // server
177   Label1 = new QLabel(this);
178   Label1->setText("Server Desc");
179   Label1->move(10, 120);
180   Label1->resize(100, 20);
181   ServerNameEdit = new QLineEdit(this);
182   ServerNameEdit->move(75, 120);
183   ServerNameEdit->resize(100, 20);
184   // username
185   Label2 = new QLabel(this);
186   Label2->setText("User Name");
187   Label2->move(10, 150);
188   Label2->resize(100, 20);
189   UserNameEdit = new QLineEdit(this);
190   UserNameEdit->move(75, 150);
191   UserNameEdit->resize(100, 20);
192   // ip
193   Label3 = new QLabel(this);
194   Label3->setText("Server IP");
195   Label3->move(10, 180);
196   Label3->resize(100, 20);
197   IPEdit = new QLineEdit(this);
198   IPEdit->move(75, 180);
199   IPEdit->resize(100, 20);
200   // width and height
201   WidthHeightBox = new QComboBox(this);
202   WidthHeightBox->move(10, 210);
203   WidthHeightBox->resize(100, 20);
204   WidthHeightBox->insertItem("240x320");
205   WidthHeightBox->insertItem("640x480");
206   WidthHeightBox->insertItem("800x600");
207   connect(WidthHeightBox, SIGNAL(activated(int)), this, SLOT(ComboChanged(int)));
208   WidthHeightBox->setCurrentItem(1);
209   WidthEdit = new QLineEdit(this);
210   WidthEdit->move(110, 210);
211   WidthEdit->resize(30, 20);
212   WidthEdit->setText("800");
213   HeightEdit = new QLineEdit(this);
214   HeightEdit->move(140, 210);
215   HeightEdit->resize(30, 20);
216   HeightEdit->setText("600");
217   // add to list button
218   AddButton = new QPushButton(this);
219   AddButton->move(180, 120);
220   AddButton->resize(50, 20);
221   AddButton->setText("Add");
222   connect(AddButton, SIGNAL(clicked()), this, SLOT(AddClicked()));
223   // change list item button
224   EditButton = new QPushButton(this);
225   EditButton->move(180, 140);
226   EditButton->resize(50, 20);
227   EditButton->setText("Edit");
228   connect(EditButton, SIGNAL(clicked()), this, SLOT(EditClicked()));
229   // save to file button
230   SaveButton = new QPushButton(this);
231   SaveButton->move(180, 160);
232   SaveButton->resize(50, 20);
233   SaveButton->setText("Save");
234   connect(SaveButton, SIGNAL(clicked()), this, SLOT(SaveClicked()));
235   // remove an item button
236   RemoveButton = new QPushButton(this);
237   RemoveButton->move(180, 180);
238   RemoveButton->resize(50, 20);
239   RemoveButton->setText("Remove");
240   connect(RemoveButton, SIGNAL(clicked()), this, SLOT(RemoveClicked()));
241   // full screen check box
242   FullScreenCheckBox = new QCheckBox(this, "Full Screen");
243   FullScreenCheckBox->setText("Full Screen");
244   FullScreenCheckBox->move(10, 230);
245   // ok button
246   OKButton = new QPushButton(this);
247   OKButton->setText("OK");
248   OKButton->move(100, 240);
249   OKButton->resize(50, 20);
250   connect(OKButton, SIGNAL(clicked()), this, SLOT(OKClicked()));
251   // cancel button
252   CancelButton = new QPushButton(this);
253   CancelButton->setText("Cancel");
254   CancelButton->move(160, 240);
255   CancelButton->resize(50, 20);
256   connect(CancelButton, SIGNAL(clicked()), this, SLOT(CancelClicked()));
257 
258   for (i = 0; i < 10; i++)
259   {
260     ConnectionList[i] = new QMyConnectionItem;
261     ConnectionList[i]->ServerName = "";
262     ConnectionList[i]->UserName = "";
263     ConnectionList[i]->ServerIP = "";
264     ConnectionList[i]->Width = 0;
265     ConnectionList[i]->Height = 0;
266     ConnectionList[i]->FullScreen = 0;
267   }
268   home = getenv("HOME");
269   if (home != NULL)
270   {
271     sprintf(Text, "%s/rdesktop.ini", home);
272     QFile * File = new QFile(Text);
273     if (File->open(IO_ReadOnly))
274     {
275       i = -1;
276       while (!File->atEnd())
277       {
278         File->readLine(Line, 255);
279         j = Line.find("=");
280         if (j > 0)
281         {
282           ItemName = Line.mid(0, j);
283           CleanString(&ItemName);
284           ItemValue = Line.mid(j + 1);
285           CleanString(&ItemValue);
286           if (ItemName == "Server")
287           {
288             i++;
289             ConnectionList[i]->ServerName = ItemValue;
290             ListBox->insertItem(ItemValue);
291           }
292           else if (ItemName == "UserName")
293             ConnectionList[i]->UserName = ItemValue;
294           else if (ItemName == "Width")
295             ConnectionList[i]->Width = ItemValue.toInt();
296           else if (ItemName == "Height")
297             ConnectionList[i]->Height = ItemValue.toInt();
298           else if (ItemName == "IP")
299             ConnectionList[i]->ServerIP = ItemValue;
300           else if (ItemName == "FullScreen")
301             ConnectionList[i]->FullScreen = (ItemValue != "0");
302         }
303       }
304     }
305     delete File;
306   }
307 }
308 
309 /******************************************************************************/
~QMyDialog()310 QMyDialog::~QMyDialog()
311 {
312   QMyConnectionItem * Item;
313   int i;
314 
315   for (i = 0; i < 10; i++)
316   {
317     Item = ConnectionList[i];
318     delete Item;
319   }
320 }
321 
322 /******************************************************************************/
ComboChanged(int index)323 void QMyDialog::ComboChanged(int index)
324 {
325   if (index == 0)
326   {
327     WidthEdit->setText("240");
328     HeightEdit->setText("320");
329   }
330   if (index == 1)
331   {
332     WidthEdit->setText("640");
333     HeightEdit->setText("480");
334   }
335   else if (index == 2)
336   {
337     WidthEdit->setText("800");
338     HeightEdit->setText("600");
339   }
340 }
341 
342 /******************************************************************************/
OKClicked()343 void QMyDialog::OKClicked()
344 {
345   ServerName = ServerNameEdit->text();
346   UserName = UserNameEdit->text();
347   Width = WidthEdit->text().toInt();
348   Height = HeightEdit->text().toInt();
349   ServerIP = IPEdit->text();
350   FullScreen = FullScreenCheckBox->isChecked();
351   done(1);
352 }
353 
354 /******************************************************************************/
CancelClicked()355 void QMyDialog::CancelClicked()
356 {
357   done(0);
358 }
359 
360 /******************************************************************************/
AddClicked()361 void QMyDialog::AddClicked()
362 {
363   int i;
364   QMyConnectionItem * Item;
365 
366   i = ListBox->count();
367   if (i < 10)
368   {
369     ListBox->insertItem(ServerNameEdit->text());
370     Item = ConnectionList[i];
371     Item->ServerName = ServerNameEdit->text();
372     Item->UserName = UserNameEdit->text();
373     Item->Width = WidthEdit->text().toInt();
374     Item->Height = HeightEdit->text().toInt();
375     Item->ServerIP = IPEdit->text();
376     Item->FullScreen = FullScreenCheckBox->isChecked();
377   }
378 }
379 
380 /******************************************************************************/
EditClicked()381 void QMyDialog::EditClicked()
382 {
383   int i;
384   QMyConnectionItem * Item;
385 
386   i = ListBox->currentItem();
387   if (i >= 0)
388   {
389     Item = ConnectionList[i];
390     Item->ServerName = ServerNameEdit->text();
391     Item->UserName = UserNameEdit->text();
392     Item->Width = WidthEdit->text().toInt();
393     Item->Height = HeightEdit->text().toInt();
394     Item->ServerIP = IPEdit->text();
395     Item->FullScreen = FullScreenCheckBox->isChecked();
396     ListBox->changeItem(ServerNameEdit->text(), i);
397   }
398 }
399 
400 /******************************************************************************/
WriteString(QFile * File,QString * Line)401 void WriteString(QFile* File, QString* Line)
402 {
403   File->writeBlock((const char*)(*Line), Line->length());
404 }
405 
406 /******************************************************************************/
SaveClicked()407 void QMyDialog::SaveClicked()
408 {
409   int i, j;
410   QMyConnectionItem * Item;
411   QString Line;
412   char * home;
413   char Text[256];
414   QFile* File;
415 
416   home = getenv("HOME");
417   if (home != NULL)
418   {
419     sprintf(Text, "%s/rdesktop.ini", home);
420     File = new QFile(Text);
421     if (File->open(IO_Truncate | IO_ReadWrite))
422     {
423       i = ListBox->count();
424       for (j = 0; j < i; j++)
425       {
426         Item = ConnectionList[j];
427         Line = "Server=";
428         Line += Item->ServerName;
429         Line += (char)10;
430         WriteString(File, &Line);
431         Line = "UserName=";
432         Line += Item->UserName;
433         Line += (char)10;
434         WriteString(File, &Line);
435         Line = "Width=";
436         sprintf(Text, "%d", Item->Width);
437         Line += Text;
438         Line += (char)10;
439         WriteString(File, &Line);
440         Line = "Height=";
441         sprintf(Text, "%d", Item->Height);
442         Line += Text;
443         Line += (char)10;
444         WriteString(File, &Line);
445         Line = "IP=";
446         Line += Item->ServerIP;
447         Line += (char)10;
448         WriteString(File, &Line);
449         Line = "FullScreen=";
450         if (Item->FullScreen)
451           Line += "1";
452         else
453           Line += "0";
454         Line += (char)10;
455         WriteString(File, &Line);
456       }
457     }
458     File->flush();
459     File->close();
460     delete File;
461   }
462 }
463 
464 /******************************************************************************/
RemoveClicked()465 void QMyDialog::RemoveClicked()
466 {
467   int i, j, c;
468   QMyConnectionItem * Item1;
469   QMyConnectionItem * Item2;
470 
471   i = ListBox->currentItem();
472   if (i >= 0)
473   {
474     c = ListBox->count();
475     for (j = i; j < c - 1; j++)
476     {
477       Item1 = ConnectionList[i];
478       Item2 = ConnectionList[i + 1];
479       Item1->ServerName = Item2->ServerName;
480       Item1->UserName = Item2->UserName;
481       Item1->Width = Item2->Width;
482       Item1->Height = Item2->Height;
483       Item1->ServerIP = Item2->ServerIP;
484       Item1->FullScreen = Item2->FullScreen;
485     }
486     ListBox->removeItem(i);
487   }
488 }
489 
490 /******************************************************************************/
ListBoxChanged()491 void QMyDialog::ListBoxChanged()
492 {
493   int i;
494   QMyConnectionItem * Item;
495   char Text[100];
496 
497   i = ListBox->currentItem();
498   if (i >= 0 && i < 10)
499   {
500     Item = ConnectionList[i];
501     ServerNameEdit->setText(Item->ServerName);
502     UserNameEdit->setText(Item->UserName);
503     sprintf(Text, "%d", Item->Width);
504     WidthEdit->setText(Text);
505     sprintf(Text, "%d", Item->Height);
506     HeightEdit->setText(Text);
507     IPEdit->setText(Item->ServerIP);
508     FullScreenCheckBox->setChecked(Item->FullScreen != 0);
509   }
510 }
511 
512 /******************************************************************************/
ListBoxSelected(int)513 void QMyDialog::ListBoxSelected(int /*index*/)
514 {
515 }
516 
517 /******************************************************************************/
GetScanCode(QKeyEvent * e,int * ScanCode,int * code)518 void GetScanCode(QKeyEvent * e, int * ScanCode, int * code)
519 {
520   int key;
521   int mod;
522   int ascii;
523 
524   key = e->key();
525   mod = e->state();
526   ascii = e->ascii();
527 
528   *ScanCode = 0;
529   *code = mod; // 8 shift, 16 control, 32 alt
530 
531   switch (key)
532   {
533     case 4096: // esc
534     case 4097: // tab
535     case 4099: // backspace
536     case 4100: // enter
537     case 4101: // enter
538     case 4103: // delete
539       ascii = 0;
540   }
541 
542   if (ascii == 0)
543   {
544     switch (key)
545     {
546       case 4096: *ScanCode = 0x01; break; // esc
547       case 4097: *ScanCode = 0x0f; break; // tab
548       case 4099: *ScanCode = 0x0e; break; // backspace
549       case 4100: *ScanCode = 0x1c; break; // enter
550       case 4101: *ScanCode = 0x1c; break; // enter
551       case 4112: *ScanCode = 0xc7; break; // home
552       case 4113: *ScanCode = 0xcf; break; // end
553       case 4102: *ScanCode = 0xd2; break; // insert
554       case 4103: *ScanCode = 0xd3; break; // delete
555       case 4118: *ScanCode = 0xc9; break; // page up
556       case 4119: *ScanCode = 0xd1; break; // page down
557       case 4117: *ScanCode = 0xd0; break; // down arrow
558       case 4115: *ScanCode = 0xc8; break; // up arrow
559       case 4114: *ScanCode = 0xcb; break; // left arrow
560       case 4116: *ScanCode = 0xcd; break; // right arrow
561       case 4128: *ScanCode = 0x2a; break; // shift
562       case 4131: *ScanCode = 0x38; break; // alt
563       case 4129: *ScanCode = 0x1d; break; // ctrl
564     }
565     if (*ScanCode != 0)
566       return;
567   }
568 
569   switch (ascii)
570   {
571     // first row
572     case 'q':  *ScanCode = 0x10; break;
573     case 'Q':  *ScanCode = 0x10; *code |= 8; break;
574     case '1':  *ScanCode = 0x02; break;
575     case 'w':  *ScanCode = 0x11; break;
576     case 'W':  *ScanCode = 0x11; *code |= 8; break;
577     case '2':  *ScanCode = 0x03; break;
578     case 'e':  *ScanCode = 0x12; break;
579     case 'E':  *ScanCode = 0x12; *code |= 8; break;
580     case '3':  *ScanCode = 0x04; break;
581     case 'r':  *ScanCode = 0x13; break;
582     case 'R':  *ScanCode = 0x13; *code |= 8; break;
583     case '4':  *ScanCode = 0x05; break;
584     case 't':  *ScanCode = 0x14; break;
585     case 'T':  *ScanCode = 0x14; *code |= 8; break;
586     case '5':  *ScanCode = 0x06; break;
587     case 'y':  *ScanCode = 0x15; break;
588     case 'Y':  *ScanCode = 0x15; *code |= 8; break;
589     case '6':  *ScanCode = 0x07; break;
590     case 'u':  *ScanCode = 0x16; break;
591     case 'U':  *ScanCode = 0x16; *code |= 8; break;
592     case '7':  *ScanCode = 0x08; break;
593     case 'i':  *ScanCode = 0x17; break;
594     case 'I':  *ScanCode = 0x17; *code |= 8; break;
595     case '8':  *ScanCode = 0x09; break;
596     case 'o':  *ScanCode = 0x18; break;
597     case 'O':  *ScanCode = 0x18; *code |= 8; break;
598     case '9':  *ScanCode = 0x0a; break;
599     case 'p':  *ScanCode = 0x19; break;
600     case 'P':  *ScanCode = 0x19; *code |= 8; break;
601     case '0':  *ScanCode = 0x0b; break;
602     // second row
603     case 'a':  *ScanCode = 0x1e; break;
604     case 'A':  *ScanCode = 0x1e; *code |= 8; break;
605     case '!':  *ScanCode = 0x02; *code |= 8; break;
606     case 's':  *ScanCode = 0x1f; break;
607     case 'S':  *ScanCode = 0x1f; *code |= 8; break;
608     case '@':  *ScanCode = 0x03; *code |= 8; break;
609     case 'd':  *ScanCode = 0x20; break;
610     case 'D':  *ScanCode = 0x20; *code |= 8; break;
611     case '#':  *ScanCode = 0x04; *code |= 8; break;
612     case 'f':  *ScanCode = 0x21; break;
613     case 'F':  *ScanCode = 0x21; *code |= 8; break;
614     case '$':  *ScanCode = 0x05; *code |= 8; break;
615     case 'g':  *ScanCode = 0x22; break;
616     case 'G':  *ScanCode = 0x22; *code |= 8; break;
617     case '%':  *ScanCode = 0x06; *code |= 8; break;
618     case 'h':  *ScanCode = 0x23; break;
619     case 'H':  *ScanCode = 0x23; *code |= 8; break;
620     case '_':  *ScanCode = 0x0c; *code |= 8; break;
621     case 'j':  *ScanCode = 0x24; break;
622     case 'J':  *ScanCode = 0x24; *code |= 8; break;
623     case '&':  *ScanCode = 0x08; *code |= 8; break;
624     case 'k':  *ScanCode = 0x25; break;
625     case 'K':  *ScanCode = 0x25; *code |= 8; break;
626     case '*':  *ScanCode = 0x09; *code |= 8; break;
627     case 'l':  *ScanCode = 0x26; break;
628     case 'L':  *ScanCode = 0x26; *code |= 8; break;
629     case '(':  *ScanCode = 0x0a; *code |= 8; break;
630 //    case 8:    *ScanCode = 0x0e; break; // backspace
631     // third row
632     case 'z':  *ScanCode = 0x2c; break;
633     case 'Z':  *ScanCode = 0x2c; *code |= 8; break;
634     case 'x':  *ScanCode = 0x2d; break;
635     case 'X':  *ScanCode = 0x2d; *code |= 8; break;
636     case 'c':  *ScanCode = 0x2e; break;
637     case 'C':  *ScanCode = 0x2e; *code |= 8; break;
638     case 'v':  *ScanCode = 0x2f; break;
639     case 'V':  *ScanCode = 0x2f; *code |= 8; break;
640     case 'b':  *ScanCode = 0x30; break;
641     case 'B':  *ScanCode = 0x30; *code |= 8; break;
642     case '-':  *ScanCode = 0x0c; break;
643     case 'n':  *ScanCode = 0x31; break;
644     case 'N':  *ScanCode = 0x31; *code |= 8; break;
645     case '+':  *ScanCode = 0x0d; *code |= 8; break;
646     case 'm':  *ScanCode = 0x32; break;
647     case 'M':  *ScanCode = 0x32; *code |= 8; break;
648     case '=':  *ScanCode = 0x0d; break;
649     case ',':  *ScanCode = 0x33; break;
650     case ';':  *ScanCode = 0x27; break;
651     case ')':  *ScanCode = 0x0b; *code |= 8; break;
652     // fourth row
653 //    case 9:    *ScanCode = 0x0f; break; // tab
654     case '/':  *ScanCode = 0x35; break;
655     case '?':  *ScanCode = 0x35; *code |= 8; break;
656     case ' ':  *ScanCode = 0x39; break;
657     case '\'': *ScanCode = 0x28; break;
658     case '"':  *ScanCode = 0x28; *code |= 8; break;
659     case '~':  *ScanCode = 0x29; *code |= 8; break;
660     case '.':  *ScanCode = 0x34; break;
661     case ':':  *ScanCode = 0x27; *code |= 8; break;
662     case '<':  *ScanCode = 0x33; *code |= 8; break;
663 //    case 13:   *ScanCode = 0x1c; break; // enter
664     case '>':  *ScanCode = 0x34; *code |= 8; break;
665     // others
666 //    case 27:   *ScanCode = 0x01; break; // esc
667     case '`':  *ScanCode = 0x29; break;
668     case '^':  *ScanCode = 0x07; *code |= 8; break;
669     case '[':  *ScanCode = 0x1a; break;
670     case '{':  *ScanCode = 0x1a; *code |= 8; break;
671     case ']':  *ScanCode = 0x1b; break;
672     case '}':  *ScanCode = 0x1b; *code |= 8; break;
673     case '\\': *ScanCode = 0x2b; break;
674     case '|':  *ScanCode = 0x2b; *code |= 8; break;
675     // ctrl keys
676     case 1:    *ScanCode = 0x1e; *code |= 16; break; // a
677     case 2:    *ScanCode = 0x30; *code |= 16; break; // b
678   }
679 
680   if (*ScanCode == 0 && key < 3000)
681     printf("unknown key %d mod %d ascii %d\n", key, mod, ascii);
682 
683 }
684 
685 /******************************************************************************/
QMyScrollView()686 QMyScrollView::QMyScrollView() : QScrollView()
687 {
688 }
689 
690 /******************************************************************************/
~QMyScrollView()691 QMyScrollView::~QMyScrollView()
692 {
693 }
694 
695 /******************************************************************************/
keyPressEvent(QKeyEvent * e)696 void QMyScrollView::keyPressEvent(QKeyEvent* e)
697 {
698   int ScanCode, code;
699   GetScanCode(e, &ScanCode, &code);
700   if (ScanCode != 0)
701   {
702     if (code & 8) // send shift
703       rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x2a, 0);
704     if (code & 16) // send control
705       rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0);
706     if (code & 32) // send alt
707       rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x38, 0);
708     rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS, ScanCode, 0);
709     e->accept();
710   }
711 }
712 
713 /******************************************************************************/
keyReleaseEvent(QKeyEvent * e)714 void QMyScrollView::keyReleaseEvent(QKeyEvent* e)
715 {
716   int ScanCode, code;
717   GetScanCode(e, &ScanCode, &code);
718   if (ScanCode != 0)
719   {
720     rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, ScanCode, 0);
721     if (code & 8) // send shift
722       rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x2a, 0);
723     if (code & 16) // send control
724       rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x1d, 0);
725     if (code & 32) // send alt
726       rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x38, 0);
727     e->accept();
728   }
729 }
730 
731 /******************************************************************************/
showEvent(QShowEvent * e)732 void QMyScrollView::showEvent(QShowEvent* e)
733 {
734   QScrollView::showEvent(e);
735 }
736 
737 /******************************************************************************/
show()738 void QMyScrollView::show()
739 {
740   QScrollView::show();
741 }
742 
743 /******************************************************************************/
polish()744 void QMyScrollView::polish()
745 {
746   QScrollView::polish();
747 }
748 
749 /******************************************************************************/
timerEvent(QTimerEvent * e)750 void QMyScrollView::timerEvent(QTimerEvent * e)
751 {
752   QMyDialog * d;
753   QWidget * Desktop;
754   int dw;
755   int dh;
756 
757   QScrollView::timerEvent(e);
758   killTimer(timer_id);
759   d = new QMyDialog(this);
760   if (d->exec() == 1) // ok clicked
761   {
762     g_width = d->Width;
763     g_height = d->Height;
764     g_client_width = g_width;
765     g_client_height = g_height;
766     g_fullscreen = d->FullScreen;
767     sprintf(g_server, "%s", (const char*)d->ServerIP);
768     sprintf(g_username, "%s", (const char*)d->UserName);
769 #ifdef WITH_RDPSND
770     // init sound
771     if (g_rdpsnd)
772     {
773       rdpsnd_init();
774     }
775 #endif
776     if (!rdp_connect(g_server, g_flags, g_domain, g_password, g_shell,
777                      g_directory))
778     {
779       delete d;
780       g_SV->close();
781       return;
782     }
783     g_BS = (uint8*)xmalloc(g_width * g_height * 4);
784     memset(g_BS, 0, g_width * g_height * 4);
785     g_clipx = 0;
786     g_clipy = 0;
787     g_clipcx = g_width;
788     g_clipcy = g_height;
789     g_CM = (QColorMap*)xmalloc(sizeof(struct QColorMap));
790     memset(g_CM, 0, sizeof(struct QColorMap));
791     g_CM->NumColors = 256;
792     g_MW = new QMyMainWindow();
793     g_MW->resize(g_client_width, g_client_height);
794     g_MW->show();
795     g_SV->addChild(g_MW);
796     g_MW->setMouseTracking(true);
797     g_MW->setCursor((int)10); /* Qt::BlankCursor */
798     g_SocketNotifier = new QSocketNotifier(g_global_sock,
799                                            QSocketNotifier::Read,
800                                            g_MW);
801     g_MW->connect(g_SocketNotifier, SIGNAL(activated(int)), g_MW,
802                   SLOT(dataReceived()));
803     if (g_fullscreen)
804     {
805       Desktop = g_App->desktop();
806       dw = Desktop->width();
807       dh = Desktop->height();
808       if (dw == g_client_width && dh == g_client_height)
809       {
810         g_MW->resize(g_client_width - 4, g_client_height - 4);
811       }
812       g_SV->showFullScreen();
813     }
814     delete d;
815   }
816   else // cancel clicked
817   {
818     delete d;
819     g_SV->close();
820   }
821 }
822 
823 /******************************************************************************/
QMyMainWindow()824 QMyMainWindow::QMyMainWindow() : QWidget(g_SV->viewport())
825 {
826   PopupMenu = new QPopupMenu(this);
827   PopupMenu->insertItem("Right click", 1, 0);
828   PopupMenu->insertItem("Toggle fullscreen", 2, 1);
829   PopupMenu->insertItem("Reset keyboard", 3, 2);
830   PopupMenu->insertItem("Double click", 4, 3);
831   connect(PopupMenu, SIGNAL(activated(int)), this, SLOT(MemuClicked(int)));
832 }
833 
834 /******************************************************************************/
~QMyMainWindow()835 QMyMainWindow::~QMyMainWindow()
836 {
837   delete PopupMenu;
838 }
839 
840 /******************************************************************************/
rd(double in)841 int rd(double in)
842 {
843   return (int)(in + 0.50);
844 }
845 
846 /******************************************************************************/
c2sx(int cx)847 int c2sx(int cx)
848 {
849   double sx;
850 
851   sx = (double)g_client_width / (double)g_width;
852   return rd(cx / sx);
853 }
854 
855 /******************************************************************************/
c2sy(int cy)856 int c2sy(int cy)
857 {
858   double sy;
859 
860   sy = (double)g_client_height / (double)g_height;
861   return rd(cy / sy);
862 }
863 
864 /******************************************************************************/
timerEvent(QTimerEvent * e)865 void QMyMainWindow::timerEvent(QTimerEvent * e)
866 {
867   QWidget::timerEvent(e);
868   if (e->timerId() == timer_id)
869   {
870     // send mouse up
871     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1,
872                    rd(c2sx(mx)), rd(c2sy(my)));
873     // if in fullscreen, take it out or the menu won't work
874     if (g_fullscreen)
875     {
876       g_fullscreen = 0;
877       g_SV->showNormal();
878       g_SV->showMaximized();
879     }
880     else
881       PopupMenu->popup(mapToGlobal(QPoint(mx, my)));
882   }
883   killTimer(timer_id);
884 }
885 
886 /******************************************************************************/
MemuClicked(int MenuID)887 void QMyMainWindow::MemuClicked(int MenuID)
888 {
889   QWidget * Desktop;
890   int dw;
891   int dh;
892 
893   if (MenuID == 1) // right click
894   {
895     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON2,
896                    rd(c2sx(mx)), rd(c2sy(my)));
897     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2,
898                    rd(c2sx(mx)), rd(c2sy(my)));
899   }
900   else if (MenuID == 2) // toggle full screen
901   {
902     g_fullscreen = ~g_fullscreen;
903     if (g_fullscreen)
904     {
905       Desktop = g_App->desktop();
906       dw = Desktop->width();
907       dh = Desktop->height();
908       if (dw == g_client_width && dh == g_client_height)
909         g_MW->resize(g_client_width - 4, g_client_height - 4);
910       g_SV->showFullScreen();
911     }
912     else
913     {
914       g_SV->showNormal();
915       g_SV->showMaximized();
916       g_MW->resize(g_client_width, g_client_height);
917     }
918   }
919   else if (MenuID == 3) // reset keyboard
920   {
921     rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x2a, 0); // shift
922     rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x1d, 0); // control
923     rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x38, 0); // alt
924   }
925   else if (MenuID == 4) // double click
926   {
927     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1,
928                    rd(c2sx(mx)), rd(c2sy(my)));
929     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1,
930                    rd(c2sx(mx)), rd(c2sy(my)));
931     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1,
932                    rd(c2sx(mx)), rd(c2sy(my)));
933     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1,
934                    rd(c2sx(mx)), rd(c2sy(my)));
935   }
936 }
937 
938 /******************************************************************************/
mouseMoveEvent(QMouseEvent * e)939 void QMyMainWindow::mouseMoveEvent(QMouseEvent* e)
940 {
941   int x, y;
942 
943   x = e->x();
944   y = e->y();
945   if (timer_id)
946   {
947     x = x - mx;
948     y = y - my;
949     if (x < -10 || x > 10 || y < -10 || y > 10)
950     {
951       killTimer(timer_id);
952       timer_id = 0;
953     }
954   }
955   rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, c2sx(e->x()),
956                  c2sy(e->y()));
957 }
958 
959 /******************************************************************************/
mousePressEvent(QMouseEvent * e)960 void QMyMainWindow::mousePressEvent(QMouseEvent* e)
961 {
962   timer_id = startTimer(1000);
963   mx = e->x();
964   my = e->y();
965   if (e->button() == LeftButton)
966     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1,
967                    c2sx(e->x()), c2sy(e->y()));
968   else if (e->button() == RightButton)
969     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON2,
970                    c2sx(e->x()), c2sy(e->y()));
971   else if (e->button() == MidButton)
972     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON3,
973                    c2sx(e->x()), c2sy(e->y()));
974 }
975 
976 /******************************************************************************/
mouseReleaseEvent(QMouseEvent * e)977 void QMyMainWindow::mouseReleaseEvent(QMouseEvent* e)
978 {
979   killTimer(timer_id);
980   timer_id = 0;
981   if (e->button() == LeftButton)
982     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, c2sx(e->x()),
983                    c2sy(e->y()));
984   else if (e->button() == RightButton)
985     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2, c2sx(e->x()),
986                    c2sy(e->y()));
987   else if (e->button() == MidButton)
988     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3, c2sx(e->x()),
989                    c2sy(e->y()));
990 }
991 
992 /******************************************************************************/
wheelEvent(QWheelEvent * e)993 void QMyMainWindow::wheelEvent(QWheelEvent* e)
994 {
995   if (e->delta() > 0)
996     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON4, c2sx(e->x()),
997                    c2sy(e->y()));
998   else if (e->delta() < 0)
999     rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON5, c2sx(e->x()),
1000                    c2sy(e->y()));
1001 }
1002 
1003 #define NOT(x) (~x)
1004 
1005 /******************************************************************************/
rop(int rop,int src,int dst)1006 int rop(int rop, int src, int dst)
1007 {
1008   switch (rop)
1009   {
1010     case 0x0: return 0;
1011     case 0x1: return NOT (src | dst);
1012     case 0x2: return NOT (src) & dst;
1013     case 0x3: return NOT (src);
1014     case 0x4: return src & NOT (dst);
1015     case 0x5: return NOT (dst);
1016     case 0x6: return src ^ dst;
1017     case 0x7: return NOT (src & dst);
1018     case 0x8: return src & dst;
1019     case 0x9: return NOT (src) ^ dst;
1020     case 0xa: return dst;
1021     case 0xb: return NOT (src) | dst;
1022     case 0xc: return src;
1023     case 0xd: return src | NOT (dst);
1024     case 0xe: return src | dst;
1025     case 0xf: return NOT (0);
1026   }
1027   return dst;
1028 }
1029 
1030 /*****************************************************************************/
get_pixel(int x,int y)1031 int get_pixel(int x, int y)
1032 {
1033   if (x >= 0 && x < g_width && y >= 0 && y < g_height)
1034   {
1035     if (g_server_bpp == 8)
1036       return GETPIXEL8(g_BS, x, y, g_width);
1037     else if (g_server_bpp == 16)
1038       return GETPIXEL16(g_BS, x, y, g_width);
1039     else if (g_server_bpp == 24)
1040       return GETPIXEL32(g_BS, x, y, g_width);
1041     else
1042       return 0;
1043   }
1044   else
1045     return 0;
1046 }
1047 
1048 /******************************************************************************/
set_pixel(int x,int y,int pixel,int op=0xc)1049 void set_pixel(int x, int y, int pixel, int op = 0xc)
1050 {
1051   int p;
1052 
1053   if (x >= g_clipx && x < (g_clipx + g_clipcx) &&
1054       y >= g_clipy && y < (g_clipy + g_clipcy))
1055   {
1056     if (x >= 0 && x < g_width && y >= 0 && y < g_height)
1057     {
1058       if (op == 0xc)
1059       {
1060         if (g_server_bpp == 8)
1061         {
1062           SETPIXEL8(g_BS, x, y, g_width, pixel);
1063         }
1064         else if (g_server_bpp == 16)
1065         {
1066           SETPIXEL16(g_BS, x, y, g_width, pixel);
1067         }
1068         else if (g_server_bpp == 24)
1069         {
1070           SETPIXEL32(g_BS, x, y, g_width, pixel);
1071         }
1072       }
1073       else
1074       {
1075         if (g_server_bpp == 8)
1076         {
1077           p = GETPIXEL8(g_BS, x, y, g_width);
1078           p = rop(op, pixel, p);
1079           SETPIXEL8(g_BS, x, y, g_width, p);
1080         }
1081         else if (g_server_bpp == 16)
1082         {
1083           p = GETPIXEL16(g_BS, x, y, g_width);
1084           p = rop(op, pixel, p);
1085           SETPIXEL16(g_BS, x, y, g_width, p);
1086         }
1087         else if (g_server_bpp == 24)
1088         {
1089           p = GETPIXEL32(g_BS, x, y, g_width);
1090           p = rop(op, pixel, p);
1091           SETPIXEL32(g_BS, x, y, g_width, p);
1092         }
1093       }
1094     }
1095   }
1096 }
1097 
1098 /******************************************************************************/
1099 // adjust coordinates for cliping rect
WarpCoords(int * x,int * y,int * cx,int * cy,int * srcx,int * srcy)1100 bool WarpCoords(int * x, int * y, int * cx, int * cy, int * srcx, int * srcy)
1101 {
1102   int dx, dy;
1103   QRect InRect(*x, *y, *cx, *cy);
1104   QRect OutRect;
1105   QRect CRect(g_clipx, g_clipy, g_clipcx, g_clipcy);
1106   OutRect = InRect.intersect(CRect);
1107   if (OutRect.isEmpty())
1108     return false;
1109   dx = OutRect.x() - InRect.x();
1110   dy = OutRect.y() - InRect.y();
1111   *x = OutRect.x();
1112   *y = OutRect.y();
1113   *cx = OutRect.width();
1114   *cy = OutRect.height();
1115   if (srcx != NULL)
1116     *srcx = *srcx + dx;
1117   if (srcy != NULL)
1118     *srcy = *srcy + dy;
1119   return true;
1120 }
1121 
1122 /******************************************************************************/
paintEvent(QPaintEvent * pe)1123 void QMyMainWindow::paintEvent(QPaintEvent * pe)
1124 {
1125   QImage * Image;
1126   QPainter * Painter;
1127   QRect Rect;
1128   int i, j, w, h, l, t, pixel, r, g, b;
1129   uint8 * data;
1130   double sx, sy;
1131 
1132   Image = 0;
1133   data = 0;
1134   if (!testWFlags(WRepaintNoErase))
1135     setWFlags(WRepaintNoErase);
1136   if (g_CM != NULL || g_server_bpp > 8)
1137   {
1138     sx = (double)g_client_width / (double)g_width;
1139     sy = (double)g_client_height / (double)g_height;
1140     Rect = pe->rect();
1141     l = rd(Rect.left() / sx);
1142     t = rd(Rect.top() / sy);
1143     w = rd(Rect.width() / sx);
1144     h = rd(Rect.height() / sy);
1145     if (w > 0 && h > 0)
1146     {
1147       if (g_server_bpp == 8 && g_CM->NumColors > 0)
1148       {
1149         w = (w + 3) & ~3;
1150         data = (uint8*)xmalloc(w * h);
1151         for (i = 0; i < h; i++)
1152           for (j = 0; j < w; j++)
1153             data[i * w + j] = GETPIXEL8(g_BS, l + j, t + i, g_width);
1154         Image = new QImage(data, w, h, 8,(QRgb*)g_CM->RGBColors,
1155                            g_CM->NumColors, QImage::IgnoreEndian);
1156       }
1157       else if (g_server_bpp == 16)
1158       {
1159         w = (w + 3) & ~3;
1160         data = (uint8*)xmalloc(w * h * 4);
1161         for (i = 0; i < h; i++)
1162           for (j = 0; j < w; j++)
1163           {
1164             pixel = GETPIXEL16(g_BS, l + j, t + i, g_width);
1165             r = ((pixel >> 8) & 0xf8) | ((pixel >> 13) & 0x7);
1166             g = ((pixel >> 3) & 0xfc) | ((pixel >> 9) & 0x3);
1167             b = ((pixel << 3) & 0xf8) | ((pixel >> 2) & 0x7);
1168             pixel = ((r << 16) | (g << 8) | b);
1169             SETPIXEL32(data, j, i, w, pixel);
1170           }
1171         Image = new QImage(data, w, h, 32, NULL,
1172                            0, QImage::IgnoreEndian);
1173       }
1174       else if (g_server_bpp == 24)
1175       {
1176         w = (w + 3) & ~3;
1177         data = (uint8*)xmalloc(w * h * 4);
1178         for (i = 0; i < h; i++)
1179           for (j = 0; j < w; j++)
1180           {
1181             pixel = GETPIXEL32(g_BS, l + j, t + i, g_width);
1182             r = (pixel >> 0) & 0xff;
1183             g = (pixel >> 8) & 0xff;
1184             b = (pixel >> 16) & 0xff;
1185             pixel = ((r << 16) | (g << 8) | b);
1186             SETPIXEL32(data, j, i, w, pixel);
1187           }
1188         Image = new QImage(data, w, h, 32, NULL,
1189                            0, QImage::IgnoreEndian);
1190       }
1191       if (Image != 0)
1192       {
1193         Painter = new QPainter(this);
1194         Painter->scale(sx, sy);
1195         Painter->drawImage(l, t, *Image, 0, 0, w, h);
1196         delete Painter;
1197         delete Image;
1198       }
1199       xfree(data);
1200     }
1201   }
1202 }
1203 
1204 /******************************************************************************/
closeEvent(QCloseEvent * e)1205 void QMyMainWindow::closeEvent(QCloseEvent * e)
1206 {
1207   e->accept();
1208 }
1209 
1210 /******************************************************************************/
dataReceived()1211 void QMyMainWindow::dataReceived()
1212 {
1213   if (!rdp_loop(&g_deactivated, &g_ext_disc_reason))
1214     g_SV->close();
1215 #ifdef WITH_RDPSND
1216   if (g_dsp_busy)
1217   {
1218     if (g_SoundNotifier == 0)
1219     {
1220       g_SoundNotifier = new QSocketNotifier(g_dsp_fd, QSocketNotifier::Write,
1221                                             g_MW);
1222       g_MW->connect(g_SoundNotifier, SIGNAL(activated(int)), g_MW,
1223                     SLOT(soundSend()));
1224     }
1225     else
1226     {
1227       if (!g_SoundNotifier->isEnabled())
1228         g_SoundNotifier->setEnabled(true);
1229     }
1230   }
1231 #endif
1232 }
1233 
1234 /******************************************************************************/
soundSend()1235 void QMyMainWindow::soundSend()
1236 {
1237 #ifdef WITH_RDPSND
1238   g_SoundNotifier->setEnabled(false);
1239   wave_out_play();
1240   if (g_dsp_busy)
1241   {
1242     g_SoundNotifier->setEnabled(true);
1243   }
1244 #endif
1245 }
1246 
1247 /******************************************************************************/
redraw(int x,int y,int cx,int cy)1248 void redraw(int x, int y, int cx, int cy)
1249 {
1250   double sx, sy;
1251 
1252   if (WarpCoords(&x, &y, &cx, &cy, NULL, NULL))
1253   {
1254     sx = (double)g_client_width / (double)g_width;
1255     sy = (double)g_client_height / (double)g_height;
1256     x = rd(x * sx);
1257     y = rd(y * sy);
1258     cx = rd(cx * sx);
1259     cy = rd(cy * sy);
1260     g_MW->update(x, y, cx, cy);
1261   }
1262 }
1263 
1264 /******************************************************************************/
1265 /* Returns 0 after user quit, 1 otherwise */
ui_select(int rdp_socket)1266 int ui_select(int rdp_socket)
1267 {
1268   if (g_global_sock == 0)
1269     g_global_sock = rdp_socket;
1270   return 1;
1271 }
1272 
1273 /******************************************************************************/
ui_move_pointer(int,int)1274 void ui_move_pointer(int /*x*/, int /*y*/)
1275 {
1276 }
1277 
1278 /******************************************************************************/
ui_set_null_cursor(void)1279 void ui_set_null_cursor(void)
1280 {
1281 }
1282 
1283 /******************************************************************************/
ui_create_bitmap(int width,int height,uint8 * data)1284 HBITMAP ui_create_bitmap(int width, int height, uint8 * data)
1285 {
1286   struct bitmap * the_bitmap;
1287   uint8 * bitmap_data;
1288   int i, j;
1289   int r, g, b, pixel;
1290 
1291   bitmap_data = (uint8*)xmalloc(width * height * 4);
1292   the_bitmap = (struct bitmap*)xmalloc(sizeof(struct bitmap));
1293   the_bitmap->w = width;
1294   the_bitmap->h = height;
1295   the_bitmap->data = bitmap_data;
1296   if (g_server_bpp == 8)
1297   {
1298     for (i = 0; i < height; i++)
1299       for (j = 0; j < width; j++)
1300         bitmap_data[i * width + j] = data[i * width + j];
1301   }
1302   else if (g_server_bpp == 16)
1303   {
1304     for (i = 0; i < height; i++)
1305       for (j = 0; j < width; j++)
1306         *(((uint16*)bitmap_data) + (i * width + j)) =
1307                      *(((uint16*)data) + (i * width + j));
1308   }
1309   else if (g_server_bpp == 24)
1310   {
1311     for (i = 0; i < height; i++)
1312       for (j = 0; j < width; j++)
1313       {
1314         r = data[(i * width + j) * 3 + 0];
1315         g = data[(i * width + j) * 3 + 1];
1316         b = data[(i * width + j) * 3 + 2];
1317         pixel = (r << 16) | (g << 8) | b;
1318         SETPIXEL32(bitmap_data, j, i, width, pixel);
1319       }
1320   }
1321   return the_bitmap;
1322 }
1323 
1324 /******************************************************************************/
ui_paint_bitmap(int x,int y,int cx,int cy,int width,int height,uint8 * data)1325 void ui_paint_bitmap(int x, int y, int cx, int cy, int width,
1326                      int height, uint8 * data)
1327 {
1328   int i, j;
1329   int r, g, b, pixel;
1330 
1331   if (g_server_bpp == 8)
1332   {
1333     for (i = 0; i < cy; i++)
1334       for (j = 0; j < cx; j++)
1335         if (i < height)
1336           if (j < width)
1337             set_pixel(x + j, y + i, data[i * width + j]);
1338   }
1339   else if (g_server_bpp == 16)
1340   {
1341     for (i = 0; i < cy; i++)
1342       for (j = 0; j < cx; j++)
1343         if (i < height)
1344           if (j < width)
1345             set_pixel(x + j, y + i, *(((uint16*)data) + (i * width + j)));
1346   }
1347   else if (g_server_bpp == 24)
1348   {
1349     for (i = 0; i < cy; i++)
1350       for (j = 0; j < cx; j++)
1351         if (i < height)
1352           if (j < width)
1353           {
1354             r = data[(i * width + j) * 3 + 0];
1355             g = data[(i * width + j) * 3 + 1];
1356             b = data[(i * width + j) * 3 + 2];
1357             pixel = (r << 16) | (g << 8) | b;
1358             set_pixel(x + j, y + i, pixel);
1359           }
1360   }
1361   redraw(x, y, cx, cy);
1362 }
1363 
1364 /******************************************************************************/
ui_destroy_bitmap(HBITMAP bmp)1365 void ui_destroy_bitmap(HBITMAP bmp)
1366 {
1367   struct bitmap* the_bitmap;
1368 
1369   the_bitmap = (struct bitmap*)bmp;
1370   if (the_bitmap != NULL)
1371   {
1372     if (the_bitmap->data != NULL)
1373       xfree(the_bitmap->data);
1374     xfree(the_bitmap);
1375   }
1376 }
1377 
1378 /******************************************************************************/
is_pixel_on(uint8 * data,int x,int y,int width,int bpp)1379 bool is_pixel_on(uint8 * data, int x, int y, int width, int bpp)
1380 {
1381   int start, shift;
1382 
1383   if (bpp == 1)
1384   {
1385     width = (width + 7) / 8;
1386     start = (y * width) + x / 8;
1387     shift = x % 8;
1388     return (data[start] & (0x80 >> shift)) != 0;
1389   }
1390   else if (bpp == 8)
1391     return data[y * width + x] != 0;
1392   else
1393     return false;
1394 }
1395 
1396 /******************************************************************************/
set_pixel_on(uint8 * data,int x,int y,int width,int bpp,uint8 pixel)1397 void set_pixel_on(uint8 * data, int x, int y, int width, int bpp, uint8 pixel)
1398 {
1399   if (bpp == 8)
1400     data[y * width + x] = pixel;
1401 }
1402 
1403 /******************************************************************************/
ui_create_glyph(int width,int height,uint8 * data)1404 HGLYPH ui_create_glyph(int width, int height, uint8 * data)
1405 {
1406   int i, j;
1407   uint8* glyph_data;
1408   struct bitmap* the_glyph;
1409 
1410   glyph_data = (uint8*)xmalloc(width * height);
1411   the_glyph = (struct bitmap*)xmalloc(sizeof(struct bitmap));
1412   the_glyph->w = width;
1413   the_glyph->h = height;
1414   the_glyph->data = glyph_data;
1415   memset(glyph_data, 0, width * height);
1416   for (i = 0; i < height; i++)
1417     for (j = 0; j < width; j++)
1418       if (is_pixel_on(data, j, i, width, 1))
1419         set_pixel_on(glyph_data, j, i, width, 8, 255);
1420   return the_glyph;
1421 }
1422 
1423 /******************************************************************************/
ui_destroy_glyph(HGLYPH glyph)1424 void ui_destroy_glyph(HGLYPH glyph)
1425 {
1426   struct bitmap* the_glyph;
1427 
1428   the_glyph = (struct bitmap*)glyph;
1429   if (the_glyph != NULL)
1430   {
1431     if (the_glyph->data != NULL)
1432       xfree(the_glyph->data);
1433     xfree(the_glyph);
1434   }
1435 }
1436 
1437 /******************************************************************************/
ui_create_cursor(uint32 x,uint32 y,int width,int height,uint8 * andmask,uint8 * xormask)1438 HCURSOR ui_create_cursor(uint32 x, uint32 y,
1439                          int width, int height,
1440                          uint8 * andmask, uint8 * xormask)
1441 {
1442   return (void*)1;
1443 }
1444 
1445 /******************************************************************************/
ui_set_cursor(HCURSOR)1446 void ui_set_cursor(HCURSOR /*cursor*/)
1447 {
1448 }
1449 
1450 /*****************************************************************************/
ui_get_numlock_state(uint32 state)1451 uint16 ui_get_numlock_state(uint32 state)
1452 {
1453   return 0;
1454 }
1455 
1456 /*****************************************************************************/
read_keyboard_state(void)1457 unsigned int read_keyboard_state(void)
1458 {
1459   return 0;
1460 }
1461 
1462 /*****************************************************************************/
ui_resize_window(void)1463 void ui_resize_window(void)
1464 {
1465 }
1466 
1467 /*****************************************************************************/
ui_polygon(uint8 opcode,uint8 fillmode,POINT * point,int npoints,BRUSH * brush,int bgcolour,int fgcolour)1468 void ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints,
1469                 BRUSH * brush, int bgcolour, int fgcolour)
1470 {
1471 }
1472 
1473 /*****************************************************************************/
1474 /* todo, use qt function for this (QPainter::drawPolyline) */
ui_polyline(uint8 opcode,POINT * points,int npoints,PEN * pen)1475 void ui_polyline(uint8 opcode, POINT * points, int npoints, PEN * pen)
1476 {
1477   int i, x, y, dx, dy;
1478 
1479   if (npoints > 0)
1480   {
1481     x = points[0].x;
1482     y = points[0].y;
1483     for (i = 1; i < npoints; i++)
1484     {
1485       dx = points[i].x;
1486       dy = points[i].y;
1487       ui_line(opcode, x, y, x + dx, y + dy, pen);
1488       x = x + dx;
1489       y = y + dy;
1490     }
1491   }
1492 }
1493 
1494 /*****************************************************************************/
ui_ellipse(uint8 opcode,uint8 fillmode,int x,int y,int cx,int cy,BRUSH * brush,int bgcolour,int fgcolour)1495 void ui_ellipse(uint8 opcode, uint8 fillmode,
1496                 int x, int y, int cx, int cy,
1497                 BRUSH * brush, int bgcolour, int fgcolour)
1498 {
1499 }
1500 
1501 /******************************************************************************/
ui_destroy_cursor(HCURSOR)1502 void ui_destroy_cursor(HCURSOR /*cursor*/)
1503 {
1504 }
1505 
1506 /******************************************************************************/
ui_create_colourmap(COLOURMAP * colours)1507 HCOLOURMAP ui_create_colourmap(COLOURMAP * colours)
1508 {
1509   int i;
1510   int x;
1511   uint8 r, g, b;
1512   i = 0;
1513   while (i < colours->ncolours && i < 256)
1514   {
1515     r = colours->colours[i].red;
1516     g = colours->colours[i].green;
1517     b = colours->colours[i].blue;
1518     x = (r << 16) | (g << 8) | b;
1519     g_CM->RGBColors[i] = x;
1520     i++;
1521   }
1522   g_CM->NumColors = colours->ncolours;
1523   return g_CM;
1524 }
1525 
1526 /******************************************************************************/
ui_set_colourmap(HCOLOURMAP map)1527 void ui_set_colourmap(HCOLOURMAP map)
1528 {
1529 }
1530 
1531 /******************************************************************************/
ui_destroy_colourmap(HCOLOURMAP map)1532 void ui_destroy_colourmap(HCOLOURMAP map)
1533 {
1534 }
1535 
1536 /******************************************************************************/
ui_begin_update(void)1537 void ui_begin_update(void)
1538 {
1539 }
1540 
1541 /******************************************************************************/
ui_end_update(void)1542 void ui_end_update(void)
1543 {
1544 }
1545 
1546 /******************************************************************************/
ui_set_clip(int x,int y,int cx,int cy)1547 void ui_set_clip(int x, int y, int cx, int cy)
1548 {
1549   g_clipx = x;
1550   g_clipy = y;
1551   g_clipcx = cx;
1552   g_clipcy = cy;
1553 }
1554 
1555 /******************************************************************************/
ui_reset_clip(void)1556 void ui_reset_clip(void)
1557 {
1558   g_clipx = 0;
1559   g_clipy = 0;
1560   g_clipcx = g_width;
1561   g_clipcy = g_height;
1562 }
1563 
1564 /******************************************************************************/
ui_bell(void)1565 void ui_bell(void)
1566 {
1567   g_App->beep();
1568 }
1569 
1570 /******************************************************************************/
ui_destblt(uint8 opcode,int x,int y,int cx,int cy)1571 void ui_destblt(uint8 opcode, int x, int y, int cx, int cy)
1572 {
1573   int i, j;
1574 
1575 
1576   if (opcode == 0x0) /* black */
1577   {
1578     for (i = 0; i < cy; i++)
1579       for (j = 0; j < cx; j++)
1580         set_pixel(x + j, y + i, 0, 0xc);
1581   }
1582   else if (opcode == 0xf) /* white */
1583   {
1584     for (i = 0; i < cy; i++)
1585       for (j = 0; j < cx; j++)
1586         set_pixel(x + j, y + i, 0xffffff, 0xc);
1587   }
1588   else
1589   {
1590     for (i = 0; i < cy; i++)
1591       for (j = 0; j < cx; j++)
1592         set_pixel(x + j, y + i, get_pixel(x + j, y + i), opcode);
1593   }
1594   redraw(x, y, cx, cy);
1595 }
1596 
1597 /******************************************************************************/
1598 // does not repaint
fill_rect(int x,int y,int cx,int cy,int colour,int opcode=0xc)1599 void fill_rect(int x, int y, int cx, int cy, int colour, int opcode = 0xc)
1600 {
1601   int i, j;
1602 
1603   if (x + cx > g_width)
1604     cx = g_width - x;
1605   if (y + cy > g_height)
1606     cy = g_height - y;
1607 #ifdef QT_OPTI
1608   if (opcode == 0xc) /* optimize */
1609   {
1610     if (WarpCoords(&x, &y, &cx, &cy, 0, 0))
1611     {
1612       if (g_server_bpp == 8)
1613       {
1614         for (i = 0; i < cy; i++)
1615           for (j = 0; j < cx; j++)
1616             SETPIXEL8(g_BS, x + j, y + i, g_width, colour);
1617       }
1618       else if (g_server_bpp == 16)
1619       {
1620         for (i = 0; i < cy; i++)
1621           for (j = 0; j < cx; j++)
1622             SETPIXEL16(g_BS, x + j, y + i, g_width, colour);
1623       }
1624       else if (g_server_bpp == 24)
1625       {
1626         for (i = 0; i < cy; i++)
1627           for (j = 0; j < cx; j++)
1628             SETPIXEL32(g_BS, x + j, y + i, g_width, colour);
1629       }
1630     }
1631   }
1632   else
1633 #endif
1634   {
1635     for (i = 0; i < cy; i++)
1636       for (j = 0; j < cx; j++)
1637         set_pixel(x + j, y + i, colour, opcode);
1638   }
1639 }
1640 
1641 /******************************************************************************/
ui_rect(int x,int y,int cx,int cy,int colour)1642 void ui_rect(int x, int y, int cx, int cy, int colour)
1643 {
1644   fill_rect(x, y, cx, cy, colour);
1645   redraw(x, y, cx, cy);
1646 }
1647 
1648 /******************************************************************************/
ui_patblt(uint8 opcode,int x,int y,int cx,int cy,BRUSH * brush,int bgcolour,int fgcolour)1649 void ui_patblt(uint8 opcode, int x, int y, int cx, int cy,
1650                BRUSH * brush, int bgcolour, int fgcolour)
1651 {
1652   int i, j;
1653   uint8 ipattern[8];
1654 
1655   switch (brush->style)
1656   {
1657     case 0:
1658       fill_rect(x, y, cx, cy, fgcolour, opcode);
1659       break;
1660     case 3:
1661       for (i = 0; i < 8; i++)
1662         ipattern[i] = ~brush->pattern[7 - i];
1663       for (i = 0; i < cy; i++)
1664         for (j = 0; j < cx; j++)
1665           if (is_pixel_on(ipattern, (x + j + brush->xorigin) % 8,
1666                             (y + i + brush->yorigin) % 8, 8, 1))
1667             set_pixel(x + j, y + i, fgcolour, opcode);
1668           else
1669             set_pixel(x + j, y + i, bgcolour, opcode);
1670       break;
1671   }
1672   redraw(x, y, cx, cy);
1673 }
1674 
1675 /******************************************************************************/
ui_screenblt(uint8 opcode,int x,int y,int cx,int cy,int srcx,int srcy)1676 void ui_screenblt(uint8 opcode, int x, int y, int cx, int cy,
1677                   int srcx, int srcy)
1678 {
1679   int i, j, pixel;
1680   uint8 * temp;
1681 
1682   temp = (uint8*)xmalloc(cx * cy * 4);
1683 #ifdef QT_OPTI
1684   if (opcode == 0xc)
1685   {
1686     if (WarpCoords(&x, &y, &cx, &cy, &srcx, &srcy))
1687     {
1688       if (g_server_bpp == 8)
1689       {
1690         for (i = 0; i < cy; i++)
1691           for (j = 0; j < cx; j++)
1692           {
1693             pixel = GETPIXEL8(g_BS, srcx + j, srcy + i, g_width);
1694             SETPIXEL8(temp, j, i, cx, pixel);
1695           }
1696         for (i = 0; i < cy; i++)
1697           for (j = 0; j < cx; j++)
1698           {
1699             pixel = GETPIXEL8(temp, j, i, cx);
1700             SETPIXEL8(g_BS, x + j, y + i, g_width, pixel);
1701           }
1702       }
1703       else if (g_server_bpp == 16)
1704       {
1705         for (i = 0; i < cy; i++)
1706           for (j = 0; j < cx; j++)
1707           {
1708             pixel = GETPIXEL16(g_BS, srcx + j, srcy + i, g_width);
1709             SETPIXEL16(temp, j, i, cx, pixel);
1710           }
1711         for (i = 0; i < cy; i++)
1712           for (j = 0; j < cx; j++)
1713           {
1714             pixel = GETPIXEL16(temp, j, i, cx);
1715             SETPIXEL16(g_BS, x + j, y + i, g_width, pixel);
1716           }
1717       }
1718       else if (g_server_bpp == 24)
1719       {
1720         for (i = 0; i < cy; i++)
1721           for (j = 0; j < cx; j++)
1722           {
1723             pixel = GETPIXEL32(g_BS, srcx + j, srcy + i, g_width);
1724             SETPIXEL32(temp, j, i, cx, pixel);
1725           }
1726         for (i = 0; i < cy; i++)
1727           for (j = 0; j < cx; j++)
1728           {
1729             pixel = GETPIXEL32(temp, j, i, cx);
1730             SETPIXEL32(g_BS, x + j, y + i, g_width, pixel);
1731           }
1732       }
1733     }
1734   }
1735   else
1736 #endif
1737   {
1738     if (g_server_bpp == 8)
1739     {
1740       for (i = 0; i < cy; i++)
1741         for (j = 0; j < cx; j++)
1742           temp[i * cx + j] = get_pixel(srcx + j, srcy + i);
1743       for (i = 0; i < cy; i++)
1744         for (j = 0; j < cx; j++)
1745           set_pixel(x + j, y + i, temp[i * cx + j], opcode);
1746     }
1747     else if (g_server_bpp == 16)
1748     {
1749       for (i = 0; i < cy; i++)
1750         for (j = 0; j < cx; j++)
1751         {
1752           pixel = get_pixel(srcx + j, srcy + i);
1753           SETPIXEL16(temp, j, i, cx, pixel);
1754         }
1755       for (i = 0; i < cy; i++)
1756         for (j = 0; j < cx; j++)
1757         {
1758           pixel = GETPIXEL16(temp, j, i, cx);
1759           set_pixel(x + j, y + i, pixel, opcode);
1760         }
1761     }
1762     else if (g_server_bpp == 24)
1763     {
1764       for (i = 0; i < cy; i++)
1765         for (j = 0; j < cx; j++)
1766           *(((uint32*)temp) + (i * cx + j)) = get_pixel(srcx + j, srcy + i);
1767       for (i = 0; i < cy; i++)
1768         for (j = 0; j < cx; j++)
1769           set_pixel(x + j, y + i, *(((uint32*)temp) + (i * cx + j)), opcode);
1770     }
1771   }
1772   xfree(temp);
1773   redraw(x, y, cx, cy);
1774 }
1775 
1776 /******************************************************************************/
ui_memblt(uint8 opcode,int x,int y,int cx,int cy,HBITMAP src,int srcx,int srcy)1777 void ui_memblt(uint8 opcode, int x, int y, int cx, int cy,
1778                HBITMAP src, int srcx, int srcy)
1779 {
1780   int i, j, p;
1781   struct bitmap * the_bitmap;
1782 
1783   the_bitmap = (struct bitmap*)src;
1784   if (the_bitmap == NULL)
1785     return;
1786 #ifdef QT_OPTI
1787   if (opcode == 0xc) /* optimize */
1788   {
1789     if (WarpCoords(&x, &y, &cx, &cy, &srcx, &srcy))
1790     {
1791       if (g_server_bpp == 8)
1792       {
1793         for (i = 0; i < cy; i++)
1794           for (j = 0; j < cx; j++)
1795           {
1796             p = GETPIXEL8(the_bitmap->data, srcx + j, srcy + i, the_bitmap->w);
1797             SETPIXEL8(g_BS, x + j, y + i, g_width, p);
1798           }
1799       }
1800       else if (g_server_bpp == 16)
1801       {
1802         for (i = 0; i < cy; i++)
1803           for (j = 0; j < cx; j++)
1804           {
1805             p = GETPIXEL16(the_bitmap->data, srcx + j, srcy + i, the_bitmap->w);
1806             SETPIXEL16(g_BS, x + j, y + i, g_width, p);
1807           }
1808       }
1809       else if (g_server_bpp == 24)
1810       {
1811         for (i = 0; i < cy; i++)
1812           for (j = 0; j < cx; j++)
1813           {
1814             p = GETPIXEL32(the_bitmap->data, srcx + j, srcy + i, the_bitmap->w);
1815             SETPIXEL32(g_BS, x + j, y + i, g_width, p);
1816           }
1817       }
1818     }
1819   }
1820   else
1821 #endif
1822   {
1823     if (g_server_bpp == 8)
1824     {
1825       for (i = 0; i < cy; i++)
1826         for (j = 0; j < cx; j++)
1827           if ((i + srcy) < the_bitmap->h && (j + srcx) < the_bitmap->w)
1828             set_pixel(x + j, y + i,
1829                       the_bitmap->data[(i + srcy) * the_bitmap->w + (j + srcx)],
1830                       opcode);
1831     }
1832     else if (g_server_bpp == 16)
1833     {
1834       for (i = 0; i < cy; i++)
1835         for (j = 0; j < cx; j++)
1836           if ((i + srcy) < the_bitmap->h && (j + srcx) < the_bitmap->w)
1837             set_pixel(x + j, y + i,
1838                       *(((uint16*)the_bitmap->data) + ((i + srcy) * the_bitmap->w + (j + srcx))),
1839                       opcode);
1840     }
1841     else if (g_server_bpp == 24)
1842     {
1843       for (i = 0; i < cy; i++)
1844         for (j = 0; j < cx; j++)
1845           if ((i + srcy) < the_bitmap->h && (j + srcx) < the_bitmap->w)
1846             set_pixel(x + j, y + i,
1847                       *(((uint32*)the_bitmap->data) + ((i + srcy) * the_bitmap->w + (j + srcx))),
1848                       opcode);
1849     }
1850   }
1851   redraw(x, y, cx, cy);
1852 }
1853 
1854 /******************************************************************************/
1855 // not used
ui_triblt(uint8 opcode,int x,int y,int cx,int cy,HBITMAP src,int srcx,int srcy,BRUSH * brush,int bgcolour,int fgcolour)1856 void ui_triblt(uint8 opcode, int x, int y, int cx, int cy,
1857                HBITMAP src, int srcx, int srcy, BRUSH * brush,
1858                int bgcolour, int fgcolour)
1859 {
1860 }
1861 
1862 /******************************************************************************/
1863 /* Bresenham's line drawing algorithm */
ui_line(uint8 opcode,int startx,int starty,int endx,int endy,PEN * pen)1864 void ui_line(uint8 opcode, int startx, int starty, int endx,
1865              int endy, PEN * pen)
1866 {
1867   int dx, dy, incx, incy, dpr, dpru, p, left, top, right, bottom;
1868 
1869   if (startx > endx)
1870   {
1871     dx = startx - endx;
1872     incx = -1;
1873     left = endx;
1874     right = startx;
1875   }
1876   else
1877   {
1878     dx = endx - startx;
1879     incx = 1;
1880     left = startx;
1881     right = endx;
1882   }
1883   if (starty > endy)
1884   {
1885     dy = starty - endy;
1886     incy = -1;
1887     top = endy;
1888     bottom = starty;
1889   }
1890   else
1891   {
1892     dy = endy - starty;
1893     incy = 1;
1894     top = starty;
1895     bottom = endy;
1896   }
1897   if (dx >= dy)
1898   {
1899     dpr = dy << 1;
1900     dpru = dpr - (dx << 1);
1901     p = dpr - dx;
1902     for (; dx >= 0; dx--)
1903     {
1904       set_pixel(startx, starty, pen->colour, opcode);
1905       if (p > 0)
1906       {
1907         startx += incx;
1908         starty += incy;
1909         p += dpru;
1910       }
1911       else
1912       {
1913         startx += incx;
1914         p += dpr;
1915       }
1916     }
1917   }
1918   else
1919   {
1920     dpr = dx << 1;
1921     dpru = dpr - (dy << 1);
1922     p = dpr - dy;
1923     for (; dy >= 0; dy--)
1924     {
1925       set_pixel(startx, starty, pen->colour, opcode);
1926       if (p > 0)
1927       {
1928         startx += incx;
1929         starty += incy;
1930         p += dpru;
1931       }
1932       else
1933       {
1934         starty += incy;
1935         p += dpr;
1936       }
1937     }
1938   }
1939   redraw(left, top, (right - left) + 1, (bottom - top) + 1);
1940 }
1941 
1942 /******************************************************************************/
draw_glyph(int x,int y,HGLYPH glyph,int fgcolour)1943 void draw_glyph (int x, int y, HGLYPH glyph, int fgcolour)
1944 {
1945   struct bitmap *the_glyph;
1946   int i, j;
1947 
1948   the_glyph = (struct bitmap*)glyph;
1949   if (the_glyph == NULL)
1950     return;
1951   for (i = 0; i < the_glyph->h; i++)
1952     for (j = 0; j < the_glyph->w; j++)
1953       if (is_pixel_on(the_glyph->data, j, i, the_glyph->w, 8))
1954         set_pixel(x + j, y + i, fgcolour);
1955 }
1956 
1957 #define DO_GLYPH(ttext,idx) \
1958 {\
1959   glyph = cache_get_font (font, ttext[idx]);\
1960   if (!(flags & TEXT2_IMPLICIT_X))\
1961     {\
1962       xyoffset = ttext[++idx];\
1963       if ((xyoffset & 0x80))\
1964 	{\
1965 	  if (flags & TEXT2_VERTICAL) \
1966 	    y += ttext[idx+1] | (ttext[idx+2] << 8);\
1967 	  else\
1968 	    x += ttext[idx+1] | (ttext[idx+2] << 8);\
1969 	  idx += 2;\
1970 	}\
1971       else\
1972 	{\
1973 	  if (flags & TEXT2_VERTICAL) \
1974 	    y += xyoffset;\
1975 	  else\
1976 	    x += xyoffset;\
1977 	}\
1978     }\
1979   if (glyph != NULL)\
1980     {\
1981       draw_glyph (x + glyph->offset, y + glyph->baseline, glyph->pixmap, fgcolour);\
1982       if (flags & TEXT2_IMPLICIT_X)\
1983 	x += glyph->width;\
1984     }\
1985 }
1986 
1987 /******************************************************************************/
1988 //*****************************************************************************
ui_draw_text(uint8 font,uint8 flags,uint8 opcode,int mixmode,int x,int y,int clipx,int clipy,int clipcx,int clipcy,int boxx,int boxy,int boxcx,int boxcy,BRUSH * brush,int bgcolour,int fgcolour,uint8 * text,uint8 length)1989 void ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode,
1990                   int x, int y, int clipx, int clipy,
1991                   int clipcx, int clipcy, int boxx,
1992                   int boxy, int boxcx, int boxcy, BRUSH * brush,
1993                   int bgcolour, int fgcolour, uint8 * text, uint8 length)
1994 {
1995   FONTGLYPH * glyph;
1996   int i, j, xyoffset;
1997   DATABLOB * entry;
1998 
1999   if (boxx + boxcx > g_width)
2000     boxcx = g_width - boxx;
2001   if (boxy + boxcy > g_height)
2002     boxcy = g_height - boxy;
2003 
2004   if (boxcx > 1)
2005     fill_rect(boxx, boxy, boxcx, boxcy, bgcolour);
2006   else if (mixmode == MIX_OPAQUE)
2007     fill_rect(clipx, clipy, clipcx, clipcy, bgcolour);
2008 
2009   /* Paint text, character by character */
2010   for (i = 0; i < length;)
2011   {
2012     switch (text[i])
2013     {
2014       case 0xff:
2015         if (i + 2 < length)
2016           cache_put_text(text[i + 1], text, text[i + 2]);
2017         else
2018         {
2019           error("this shouldn't be happening\n");
2020           exit(1);
2021         }
2022         /* this will move pointer from start to first character after FF command */
2023         length -= i + 3;
2024         text = &(text[i + 3]);
2025         i = 0;
2026         break;
2027 
2028       case 0xfe:
2029         entry = cache_get_text(text[i + 1]);
2030         if (entry != NULL)
2031         {
2032           if ((((uint8 *) (entry->data))[1] == 0) && (!(flags & TEXT2_IMPLICIT_X)))
2033           {
2034             if (flags & TEXT2_VERTICAL)
2035               y += text[i + 2];
2036             else
2037               x += text[i + 2];
2038           }
2039           for (j = 0; j < entry->size; j++)
2040             DO_GLYPH(((uint8 *) (entry->data)), j);
2041         }
2042         if (i + 2 < length)
2043           i += 3;
2044         else
2045           i += 2;
2046         length -= i;
2047         /* this will move pointer from start to first character after FE command */
2048         text = &(text[i]);
2049         i = 0;
2050         break;
2051 
2052       default:
2053         DO_GLYPH(text, i);
2054         i++;
2055         break;
2056     }
2057   }
2058   if (boxcx > 1)
2059     redraw(boxx, boxy, boxcx, boxcy);
2060   else
2061     redraw(clipx, clipy, clipcx, clipcy);
2062 }
2063 
2064 /******************************************************************************/
ui_desktop_save(uint32 offset,int x,int y,int cx,int cy)2065 void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
2066 {
2067   uint8 * data;
2068   int i, j, Bpp, pixel;
2069 
2070   Bpp = 4;
2071   switch (g_server_bpp)
2072   {
2073     case 8: Bpp = 1; break;
2074     case 15: Bpp = 2; break;
2075     case 16: Bpp = 2; break;
2076   }
2077   data = (uint8*)xmalloc(cx * cy * Bpp);
2078   if (g_server_bpp == 8)
2079   {
2080     for (i = 0; i < cy; i++)
2081       for (j = 0; j < cx; j++)
2082       {
2083         pixel = get_pixel(x + j, y + i);
2084         SETPIXEL8(data, j, i, cx, pixel);
2085       }
2086   }
2087   else if (g_server_bpp == 16)
2088   {
2089     for (i = 0; i < cy; i++)
2090       for (j = 0; j < cx; j++)
2091       {
2092         pixel = get_pixel(x + j, y + i);
2093         SETPIXEL16(data, j, i, cx, pixel);
2094       }
2095   }
2096   else if (g_server_bpp == 24)
2097   {
2098     for (i = 0; i < cy; i++)
2099       for (j = 0; j < cx; j++)
2100         *(((uint32*)data) + (i * cx + j)) = get_pixel(x + j, y + i);
2101   }
2102   offset *= Bpp;
2103   cache_put_desktop(offset, cx, cy, cx * Bpp, Bpp, data);
2104   xfree(data);
2105 }
2106 
2107 /******************************************************************************/
ui_desktop_restore(uint32 offset,int x,int y,int cx,int cy)2108 void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
2109 {
2110   uint8 * data;
2111   int i, j;
2112   int Bpp;
2113 
2114   Bpp = 4;
2115   switch (g_server_bpp)
2116   {
2117     case 8: Bpp = 1; break;
2118     case 15: Bpp = 2; break;
2119     case 16: Bpp = 2; break;
2120   }
2121   offset *= Bpp;
2122   data = cache_get_desktop(offset, cx, cy, Bpp);
2123   if (g_server_bpp == 8)
2124   {
2125     for (i = 0; i < cy; i++)
2126       for (j = 0; j < cx; j++)
2127         set_pixel(x + j, y + i, data[i * cx + j]);
2128   }
2129   else if (g_server_bpp == 16)
2130   {
2131     for (i = 0; i < cy; i++)
2132       for (j = 0; j < cx; j++)
2133         set_pixel(x + j, y + i, *(((uint16*)data) + (i * cx + j)));
2134   }
2135   else if (g_server_bpp == 24)
2136   {
2137     for (i = 0; i < cy; i++)
2138       for (j = 0; j < cx; j++)
2139         set_pixel(x + j, y + i, *(((uint32*)data) + (i * cx + j)));
2140   }
2141   redraw(x, y, cx, cy);
2142 }
2143 
2144 /*****************************************************************************/
xrealloc(void * in_val,int size)2145 void * xrealloc(void * in_val, int size)
2146 {
2147   if (size < 1)
2148   {
2149     size = 1;
2150   }
2151   return realloc(in_val, size);
2152 }
2153 
2154 /*****************************************************************************/
xmalloc(int size)2155 void * xmalloc(int size)
2156 {
2157   return malloc(size);
2158 }
2159 
2160 /*****************************************************************************/
xfree(void * in_val)2161 void xfree(void * in_val)
2162 {
2163   if (in_val != NULL)
2164   {
2165     free(in_val);
2166   }
2167 }
2168 
2169 /*****************************************************************************/
xstrdup(const char * s)2170 char * xstrdup(const char * s)
2171 {
2172   char * mem = strdup(s);
2173   if (mem == NULL)
2174   {
2175     perror("strdup");
2176     exit(1);
2177   }
2178   return mem;
2179 }
2180 
2181 /*****************************************************************************/
warning(char * format,...)2182 void warning(char * format, ...)
2183 {
2184   va_list ap;
2185 
2186   fprintf(stderr, "WARNING: ");
2187   va_start(ap, format);
2188   vfprintf(stderr, format, ap);
2189   va_end(ap);
2190 }
2191 
2192 /*****************************************************************************/
unimpl(char * format,...)2193 void unimpl(char * format, ...)
2194 {
2195   va_list ap;
2196 
2197   fprintf(stderr, "NOT IMPLEMENTED: ");
2198   va_start(ap, format);
2199   vfprintf(stderr, format, ap);
2200   va_end(ap);
2201 }
2202 
2203 /*****************************************************************************/
error(char * format,...)2204 void error(char * format, ...)
2205 {
2206   va_list ap;
2207 
2208   fprintf(stderr, "ERROR: ");
2209   va_start(ap, format);
2210   vfprintf(stderr, format, ap);
2211   va_end(ap);
2212 }
2213 
2214 /*****************************************************************************/
rd_pstcache_mkdir(void)2215 BOOL rd_pstcache_mkdir(void)
2216 {
2217   return 0;
2218 }
2219 
2220 /*****************************************************************************/
rd_open_file(char * filename)2221 int rd_open_file(char * filename)
2222 {
2223   return 0;
2224 }
2225 
2226 /*****************************************************************************/
rd_close_file(int fd)2227 void rd_close_file(int fd)
2228 {
2229   return;
2230 }
2231 
2232 /*****************************************************************************/
rd_read_file(int fd,void * ptr,int len)2233 int rd_read_file(int fd, void * ptr, int len)
2234 {
2235   return 0;
2236 }
2237 
2238 /*****************************************************************************/
rd_write_file(int fd,void * ptr,int len)2239 int rd_write_file(int fd, void * ptr, int len)
2240 {
2241   return 0;
2242 }
2243 
2244 /*****************************************************************************/
rd_lseek_file(int fd,int offset)2245 int rd_lseek_file(int fd, int offset)
2246 {
2247   return 0;
2248 }
2249 
2250 /*****************************************************************************/
rd_lock_file(int fd,int start,int len)2251 BOOL rd_lock_file(int fd, int start, int len)
2252 {
2253   return False;
2254 }
2255 
2256 /*****************************************************************************/
load_licence(uint8 ** data)2257 int load_licence(uint8 ** data)
2258 {
2259   return 0;
2260 }
2261 
2262 /*****************************************************************************/
save_licence(uint8 * data,int length)2263 void save_licence(uint8 * data, int length)
2264 {
2265 }
2266 
2267 /*****************************************************************************/
generate_random(uint8 * random)2268 void generate_random(uint8 * random)
2269 {
2270   QFile File("/dev/random");
2271   File.open(IO_ReadOnly);
2272   if (File.readBlock((char*)random, 32) == 32)
2273   {
2274     return;
2275   }
2276   warning("no /dev/random\n");
2277   memcpy(random, "12345678901234567890123456789012", 32);
2278 }
2279 
2280 /*****************************************************************************/
2281 /* produce a hex dump */
hexdump(uint8 * p,uint32 len)2282 void hexdump(uint8 * p, uint32 len)
2283 {
2284   uint8 * line = p;
2285   int i, thisline;
2286   uint32 offset = 0;
2287 
2288   while (offset < len)
2289   {
2290     printf("%04x ", offset);
2291     thisline = len - offset;
2292     if (thisline > 16)
2293     {
2294       thisline = 16;
2295     }
2296     for (i = 0; i < thisline; i++)
2297     {
2298       printf("%02x ", line[i]);
2299     }
2300     for (; i < 16; i++)
2301     {
2302       printf("   ");
2303     }
2304     for (i = 0; i < thisline; i++)
2305     {
2306       printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
2307     }
2308     printf("\n");
2309     offset += thisline;
2310     line += thisline;
2311   }
2312 }
2313 
2314 /*****************************************************************************/
get_username_and_hostname(void)2315 void get_username_and_hostname(void)
2316 {
2317   char fullhostname[64];
2318   char * p;
2319   struct passwd * pw;
2320 
2321   STRNCPY(g_username, "unknown", sizeof(g_username));
2322   STRNCPY(g_hostname, "unknown", sizeof(g_hostname));
2323   pw = getpwuid(getuid());
2324   if (pw != NULL && pw->pw_name != NULL)
2325   {
2326     STRNCPY(g_username, pw->pw_name, sizeof(g_username));
2327   }
2328   if (gethostname(fullhostname, sizeof(fullhostname)) != -1)
2329   {
2330     p = strchr(fullhostname, '.');
2331     if (p != NULL)
2332     {
2333       *p = 0;
2334     }
2335     STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
2336   }
2337 }
2338 
2339 /*****************************************************************************/
out_params(void)2340 void out_params(void)
2341 {
2342   fprintf(stderr, "qterdesktop: A Remote Desktop Protocol client.\n");
2343   fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2004 Matt Chapman.\n");
2344   fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
2345   fprintf(stderr, "Usage: qterdesktop [options] server\n");
2346   fprintf(stderr, "   -g: desktop geometry (WxH)\n");
2347   fprintf(stderr, "   -4: use RDP version 4\n");
2348   fprintf(stderr, "   -5: use RDP version 5 (default)\n");
2349   fprintf(stderr, "   -t: tcp port)\n");
2350   fprintf(stderr, "   -a: connection colour depth\n");
2351   fprintf(stderr, "   -u: user name\n");
2352   fprintf(stderr, "   -d: domain\n");
2353   fprintf(stderr, "   -s: shell\n");
2354   fprintf(stderr, "   -c: working directory\n");
2355   fprintf(stderr, "   -p: password (- to prompt)\n");
2356   fprintf(stderr, "   -n: client hostname\n");
2357   fprintf(stderr, "   -f: full screen\n");
2358   fprintf(stderr, "   -r sound: enable sound\n");
2359   fprintf(stderr, "\n");
2360 }
2361 
2362 /*****************************************************************************/
parse_parameters(int in_argc,char ** in_argv)2363 int parse_parameters(int in_argc, char ** in_argv)
2364 {
2365   int i;
2366   char * p;
2367 
2368   for (i = 1; i < in_argc; i++)
2369   {
2370     strcpy(g_server, in_argv[i]);
2371     if (strcmp(in_argv[i], "-h") == 0)
2372     {
2373       out_params();
2374       return 0;
2375     }
2376     else if (strcmp(in_argv[i], "-g") == 0)
2377     {
2378       g_width = strtol(in_argv[i + 1], &p, 10);
2379       if (*p == 'x')
2380       {
2381         g_height = strtol(p + 1, &p, 10);
2382       }
2383       if (*p == '-')
2384       {
2385         g_client_width = strtol(p + 1, &p, 10);
2386       }
2387       else
2388       {
2389         g_client_width = g_width;
2390         g_client_height = g_height;
2391       }
2392       if (*p == 'x')
2393       {
2394         g_client_height = strtol(p + 1, NULL, 10);
2395       }
2396       g_width = (g_width + 3) & ~3;
2397       g_height = (g_height + 3) & ~3;
2398       g_client_width = (g_client_width + 3) & ~3;
2399       g_client_height = (g_client_height + 3) & ~3;
2400       i++;
2401     }
2402     else if (strcmp(in_argv[i], "-4") == 0)
2403     {
2404       g_use_rdp5 = 0;
2405     }
2406     else if (strcmp(in_argv[i], "-5") == 0)
2407     {
2408       g_use_rdp5 = 1;
2409     }
2410     else if (strcmp(in_argv[i], "-a") == 0)
2411     {
2412       g_server_bpp = strtol(in_argv[i + 1], &p, 10);
2413       if (g_server_bpp != 8 &&
2414           g_server_bpp != 16 && g_server_bpp != 24)
2415       {
2416         error("invalid bpp\n");
2417         return 0;
2418       }
2419       i++;
2420     }
2421     else if (strcmp(in_argv[i], "-t") == 0)
2422     {
2423       g_tcp_port_rdp = strtol(in_argv[i + 1], &p, 10);
2424       i++;
2425     }
2426     else if (strcmp(in_argv[i], "-u") == 0)
2427     {
2428       STRNCPY(g_username, in_argv[i + 1], sizeof(g_username));
2429       i++;
2430     }
2431     else if (strcmp(in_argv[i], "-d") == 0)
2432     {
2433       STRNCPY(g_domain, in_argv[i + 1], sizeof(g_domain));
2434       i++;
2435     }
2436     else if (strcmp(in_argv[i], "-s") == 0)
2437     {
2438       STRNCPY(g_shell, in_argv[i + 1], sizeof(g_shell));
2439       i++;
2440     }
2441     else if (strcmp(in_argv[i], "-c") == 0)
2442     {
2443       STRNCPY(g_directory, in_argv[i + 1], sizeof(g_directory));
2444       i++;
2445     }
2446     else if (strcmp(in_argv[i], "-p") == 0)
2447     {
2448       STRNCPY(g_password, in_argv[i + 1], sizeof(g_password));
2449       g_flags |= RDP_LOGON_AUTO;
2450       i++;
2451     }
2452     else if (strcmp(in_argv[i], "-n") == 0)
2453     {
2454       STRNCPY(g_hostname, in_argv[i + 1], sizeof(g_hostname));
2455       i++;
2456     }
2457     else if (strcmp(in_argv[i], "-f") == 0)
2458     {
2459       g_fullscreen = 1;
2460     }
2461     else if (strcmp(in_argv[i], "-r") == 0)
2462     {
2463       if (strcmp(in_argv[i + 1], "sound") == 0)
2464       {
2465 #ifdef WITH_RDPSND
2466         g_rdpsnd = 1;
2467 #endif
2468       }
2469       i++;
2470     }
2471   }
2472   return 1;
2473 }
2474 
2475 /******************************************************************************/
param_connect(void)2476 int param_connect(void)
2477 {
2478   QWidget * Desktop;
2479   int dw, dh;
2480 
2481 #ifdef WITH_RDPSND
2482   // init sound
2483   if (g_rdpsnd)
2484   {
2485     rdpsnd_init();
2486   }
2487 #endif
2488   if (rdp_connect(g_server, g_flags, g_domain, g_password, g_shell,
2489                   g_directory))
2490   {
2491     g_BS = (uint8*)xmalloc(g_width * g_height * 4);
2492     memset(g_BS, 0, g_width * g_height * 4);
2493     g_clipx = 0;
2494     g_clipy = 0;
2495     g_clipcx = g_width;
2496     g_clipcy = g_height;
2497     g_CM = (QColorMap*)xmalloc(sizeof(struct QColorMap));
2498     memset(g_CM, 0, sizeof(struct QColorMap));
2499     g_CM->NumColors = 256;
2500     g_MW = new QMyMainWindow();
2501     g_MW->resize(g_client_width, g_client_height);
2502     g_MW->show();
2503     g_SV->addChild(g_MW);
2504     g_MW->setMouseTracking(true);
2505     g_SocketNotifier = new QSocketNotifier(g_global_sock,
2506                                            QSocketNotifier::Read,
2507                                            g_MW);
2508     g_MW->connect(g_SocketNotifier, SIGNAL(activated(int)), g_MW,
2509                   SLOT(dataReceived()));
2510     if (g_fullscreen)
2511     {
2512       Desktop = g_App->desktop();
2513       dw = Desktop->width();
2514       dh = Desktop->height();
2515       if (dw == g_client_width && dh == g_client_height)
2516       {
2517         g_MW->resize(g_client_width - 4, g_client_height - 4);
2518       }
2519       g_SV->showFullScreen();
2520     }
2521     g_MW->setCursor((int)10); /* Qt::BlankCursor */
2522     g_App->exec();
2523   }
2524   return 0;
2525 }
2526 
2527 /******************************************************************************/
main(int argc,char ** argv)2528 int main(int argc, char ** argv)
2529 {
2530 #ifdef SHARP
2531   g_App = new QPEApplication(argc, argv);
2532 #else
2533   g_App = new QApplication(argc, argv, QApplication::GuiServer);
2534   //g_App = new QApplication(argc, argv);
2535 #endif
2536   g_SV = new QMyScrollView();
2537   g_App->setMainWidget(g_SV);
2538   g_SV->showMaximized();
2539   if (argc > 1)
2540   {
2541     get_username_and_hostname();
2542     if (parse_parameters(argc, argv))
2543     {
2544       param_connect();
2545     }
2546   }
2547   else
2548   {
2549     g_SV->timer_id = g_SV->startTimer(1000); /* one sec delay, then dialog */
2550     g_App->exec();
2551   }
2552   delete g_SV;
2553   delete g_App;
2554   xfree(g_CM);
2555   xfree(g_BS);
2556   return 0;
2557 }
2558