set most of trunk svn property eol-style:native
[reactos.git] / reactos / base / applications / tsclient / rdesktop / uiports / qtwin.cpp
index 7ccc220..ae72a91 100644 (file)
-/* -*- c-basic-offset: 8 -*-\r
-   rdesktop: A Remote Desktop Protocol client.\r
-   User interface services - QT Window System\r
-   Copyright (C) Jay Sorg 2004-2006\r
-\r
-   This program is free software; you can redistribute it and/or modify\r
-   it under the terms of the GNU General Public License as published by\r
-   the Free Software Foundation; either version 2 of the License, or\r
-   (at your option) any later version.\r
-\r
-   This program is distributed in the hope that it will be useful,\r
-   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-   GNU General Public License for more details.\r
-\r
-   You should have received a copy of the GNU General Public License\r
-   along with this program; if not, write to the Free Software\r
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
-*/\r
-\r
-#include "rdesktop.h"\r
-\r
-#include <qapplication.h>\r
-#include <qmainwindow.h>\r
-#include <qwidget.h>\r
-#include <qpainter.h>\r
-#include <qpixmap.h>\r
-#include <qbrush.h>\r
-#include <qimage.h>\r
-#include <qbitmap.h>\r
-#include <qcursor.h>\r
-#include <qsocketnotifier.h>\r
-#include <qscrollview.h>\r
-#include <qfile.h>\r
-\r
-#include "qtwin.h"\r
-\r
-#include <unistd.h> // gethostname\r
-#include <pwd.h> // getpwuid\r
-#include <stdarg.h> // va_list va_start va_end\r
-\r
-#include <errno.h>\r
-#include <fcntl.h>\r
-\r
-/* rdesktop globals */\r
-extern int g_tcp_port_rdp;\r
-int g_use_rdp5 = 1;\r
-char g_hostname[16];\r
-char g_username[64];\r
-int g_height = 600;\r
-int g_width = 800;\r
-int g_server_depth = 8;\r
-int g_encryption = 1;\r
-int g_desktop_save = 1;\r
-int g_polygon_ellipse_orders = 0;\r
-int g_bitmap_cache = 1;\r
-int g_bitmap_cache_persist_enable = False;\r
-int g_bitmap_cache_precache = True;\r
-int g_bitmap_compression = 1;\r
-int g_rdp5_performanceflags = 0;\r
-int g_console_session = 0;\r
-int g_keylayout = 0x409; /* Defaults to US keyboard layout */\r
-int g_keyboard_type = 0x4; /* Defaults to US keyboard layout */\r
-int g_keyboard_subtype = 0x0; /* Defaults to US keyboard layout */\r
-int g_keyboard_functionkeys = 0xc; /* Defaults to US keyboard layout */\r
-\r
-/* hack globals */\r
-static int g_argc = 0;\r
-static char ** g_argv = 0;\r
-static int g_UpAndRunning = 0;\r
-static int g_sock = 0;\r
-static int g_deactivated = 0;\r
-static uint32 g_ext_disc_reason = 0;\r
-static char g_servername[128];\r
-static char g_title[128] = "";\r
-static int g_flags = RDP_LOGON_NORMAL;\r
-\r
-#ifdef WITH_RDPSND\r
-extern int g_dsp_busy;\r
-extern int g_dsp_fd;\r
-static int g_rdpsnd = 0;\r
-static QSocketNotifier * g_SoundNotifier = 0;\r
-#endif\r
-\r
-/* qt globals */\r
-static QSocketNotifier * g_SocketNotifier = 0;\r
-static QApplication * g_App = 0;\r
-static QMyMainWindow * g_MW = 0;\r
-static QMyScrollView * g_SV = 0;\r
-static QPixmap * g_BS = 0;\r
-static QPixmap * g_DS = 0;\r
-static QPainter * g_P1 = 0;\r
-static QPainter * g_P2 = 0;\r
-static QColor g_Color1;\r
-static QColor g_Color2;\r
-\r
-struct QColorMap\r
-{\r
-  uint32 RGBColors[256];\r
-  int NumColors;\r
-};\r
-static struct QColorMap * g_CM = 0;\r
-static QRegion * g_ClipRect;\r
-\r
-static Qt::RasterOp g_OpCodes[16] = {\r
-    Qt::ClearROP,        // BLACKNESS     0\r
-    Qt::NorROP,          // NOTSRCERASE   DSon\r
-    Qt::NotAndROP,       //               DSna\r
-    Qt::NotCopyROP,      // NOTSRCCOPY    Sn\r
-    Qt::AndNotROP,       // SRCERASE      SDna\r
-    Qt::NotROP,          // DSTINVERT     Dn\r
-    Qt::XorROP,          // SRCINVERT     DSx\r
-    Qt::NandROP,         //               DSan\r
-    Qt::AndROP,          // SRCAND        DSa\r
-    Qt::NotXorROP,       //               DSxn\r
-    Qt::NopROP,          //               D\r
-    Qt::NotOrROP,        // MERGEPAINT    DSno\r
-    Qt::CopyROP,         // SRCCOPY       S\r
-    Qt::OrNotROP,        //               SDno\r
-    Qt::OrROP,           // SRCPAINT      DSo\r
-    Qt::SetROP};         // WHITENESS     1\r
-\r
-/* Session Directory redirection */\r
-BOOL g_redirect = False;\r
-char g_redirect_server[64];\r
-char g_redirect_domain[16];\r
-char g_redirect_password[64];\r
-char g_redirect_username[64];\r
-char g_redirect_cookie[128];\r
-uint32 g_redirect_flags = 0;\r
-\r
-//*****************************************************************************\r
-uint32 Color15to32(uint32 InColor)\r
-{\r
-  uint32 r, g, b;\r
-\r
-  r = (InColor & 0x7c00) >> 10;\r
-  r = (r * 0xff) / 0x1f;\r
-  g = (InColor & 0x03e0) >> 5;\r
-  g = (g * 0xff) / 0x1f;\r
-  b = (InColor & 0x001f);\r
-  b = (b * 0xff) / 0x1f;\r
-  return (r << 16) | (g << 8) | b;\r
-}\r
-\r
-//*****************************************************************************\r
-uint32 Color16to32(uint32 InColor)\r
-{\r
-  uint32 r, g, b;\r
-\r
-  r = (InColor & 0xf800) >> 11;\r
-  r = (r * 0xff) / 0x1f;\r
-  g = (InColor & 0x07e0) >> 5;\r
-  g = (g * 0xff) / 0x3f;\r
-  b = (InColor & 0x001f);\r
-  b = (b * 0xff) / 0x1f;\r
-  return (r << 16) | (g << 8) | b;\r
-}\r
-\r
-//*****************************************************************************\r
-uint32 Color24to32(uint32 InColor)\r
-{\r
-  return ((InColor & 0x00ff0000) >> 16) |\r
-         ((InColor & 0x000000ff) << 16) |\r
-          (InColor & 0x0000ff00);\r
-}\r
-\r
-//*****************************************************************************\r
-void SetColorx(QColor * Color, uint32 InColor)\r
-{\r
-  switch (g_server_depth)\r
-  {\r
-    case 8:\r
-      if (g_CM == NULL || InColor > 255)\r
-      {\r
-        Color->setRgb(0);\r
-        return;\r
-      }\r
-      Color->setRgb(g_CM->RGBColors[InColor]);\r
-      break;\r
-    case 15:\r
-      Color->setRgb(Color15to32(InColor));\r
-      break;\r
-    case 16:\r
-      Color->setRgb(Color16to32(InColor));\r
-      break;\r
-    case 24:\r
-      Color->setRgb(Color24to32(InColor));\r
-      break;\r
-    default:\r
-      Color->setRgb(0);\r
-  }\r
-}\r
-\r
-//*****************************************************************************\r
-void SetOpCode(int opcode)\r
-{\r
-  if (opcode >= 0 && opcode < 16)\r
-  {\r
-    Qt::RasterOp op = g_OpCodes[opcode];\r
-    if (op != Qt::CopyROP)\r
-    {\r
-      g_P1->setRasterOp(op);\r
-      g_P2->setRasterOp(op);\r
-    }\r
-  }\r
-}\r
-\r
-//*****************************************************************************\r
-void ResetOpCode(int opcode)\r
-{\r
-  if (opcode >= 0 && opcode < 16)\r
-  {\r
-    Qt::RasterOp op = g_OpCodes[opcode];\r
-    if (op != Qt::CopyROP)\r
-    {\r
-      g_P1->setRasterOp(Qt::CopyROP);\r
-      g_P2->setRasterOp(Qt::CopyROP);\r
-    }\r
-  }\r
-}\r
-\r
-/*****************************************************************************/\r
-QMyMainWindow::QMyMainWindow(): QWidget()\r
-{\r
-}\r
-\r
-/*****************************************************************************/\r
-QMyMainWindow::~QMyMainWindow()\r
-{\r
-}\r
-\r
-//*****************************************************************************\r
-void QMyMainWindow::mouseMoveEvent(QMouseEvent * e)\r
-{\r
-  if (!g_UpAndRunning)\r
-  {\r
-    return;\r
-  }\r
-  rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, e->x(), e->y());\r
-}\r
-\r
-//*****************************************************************************\r
-void QMyMainWindow::mousePressEvent(QMouseEvent * e)\r
-{\r
-  if (!g_UpAndRunning)\r
-  {\r
-    return;\r
-  }\r
-  if (e->button() == LeftButton)\r
-  {\r
-    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1,\r
-                   e->x(), e->y());\r
-  }\r
-  else if (e->button() == RightButton)\r
-  {\r
-    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON2,\r
-                   e->x(), e->y());\r
-  }\r
-  else if (e->button() == MidButton)\r
-  {\r
-    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON3,\r
-                   e->x(), e->y());\r
-  }\r
-}\r
-\r
-//*****************************************************************************\r
-void QMyMainWindow::mouseReleaseEvent(QMouseEvent * e)\r
-{\r
-  if (!g_UpAndRunning)\r
-  {\r
-    return;\r
-  }\r
-  if (e->button() == LeftButton)\r
-  {\r
-    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, e->x(), e->y());\r
-  }\r
-  else if (e->button() == RightButton)\r
-  {\r
-    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2, e->x(), e->y());\r
-  }\r
-  else if (e->button() == MidButton)\r
-  {\r
-    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3, e->x(), e->y());\r
-  }\r
-}\r
-\r
-//*****************************************************************************\r
-void QMyMainWindow::wheelEvent(QWheelEvent * e)\r
-{\r
-  if (!g_UpAndRunning)\r
-  {\r
-    return;\r
-  }\r
-  if (e->delta() > 0)\r
-  {\r
-    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON4, e->x(), e->y());\r
-  }\r
-  else if (e->delta() < 0)\r
-  {\r
-    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON5, e->x(), e->y());\r
-  }\r
-}\r
-\r
-//*****************************************************************************\r
-int GetScanCode(QKeyEvent* e)\r
-{\r
-  int Key = e->key();\r
-  int ScanCode = 0;\r
-  Qt::ButtonState bs = e->state();\r
-  if (!(bs & Qt::ShiftButton)) // shift is not down\r
-  {\r
-    if (Key == 42) // *\r
-      return 0x37;\r
-    if (Key == 43) // +\r
-      return 0x4e;\r
-  }\r
-  switch (Key)\r
-  {\r
-    case 4100: ScanCode = 0x1c; break; // enter\r
-    case 4101: ScanCode = 0x1c; break;\r
-    case 4117: ScanCode = 0xd0; break; // down arrow\r
-    case 4115: ScanCode = 0xc8; break; // up arrow\r
-    case 4114: ScanCode = 0xcb; break; // left arrow\r
-    case 4116: ScanCode = 0xcd; break; // right arrow\r
-    case 4112: ScanCode = 0xc7; break; // home\r
-    case 4113: ScanCode = 0xcf; break; // end\r
-    case 4102: ScanCode = 0xd2; break; // insert\r
-    case 4103: ScanCode = 0xd3; break; // delete\r
-    case 4118: ScanCode = 0xc9; break; // page up\r
-    case 4119: ScanCode = 0xd1; break; // page down\r
-    case 4143: ScanCode = 0x00; break; // num lock\r
-    case 47:   ScanCode = 0x35; break; // /\r
-    case 42:   ScanCode = 0x37; break; // *\r
-    case 45:   ScanCode = 0x0c; break; // -\r
-    case 95:   ScanCode = 0x0c; break; // _\r
-    case 43:   ScanCode = 0x0d; break; // +\r
-    case 46:   ScanCode = 0x34; break; // .\r
-    case 48:   ScanCode = 0x0b; break; // 0\r
-    case 41:   ScanCode = 0x0b; break; // )\r
-    case 49:   ScanCode = 0x02; break; // 1\r
-    case 33:   ScanCode = 0x02; break; // !\r
-    case 50:   ScanCode = 0x03; break; // 2\r
-    case 64:   ScanCode = 0x03; break; // @\r
-    case 51:   ScanCode = 0x04; break; // 3\r
-    case 35:   ScanCode = 0x04; break; // #\r
-    case 52:   ScanCode = 0x05; break; // 4\r
-    case 36:   ScanCode = 0x05; break; // $\r
-    case 53:   ScanCode = 0x06; break; // 5\r
-    case 37:   ScanCode = 0x06; break; // %\r
-    case 54:   ScanCode = 0x07; break; // 6\r
-    case 94:   ScanCode = 0x07; break; // ^\r
-    case 55:   ScanCode = 0x08; break; // 7\r
-    case 38:   ScanCode = 0x08; break; // &\r
-    case 56:   ScanCode = 0x09; break; // 8\r
-    case 57:   ScanCode = 0x0a; break; // 9\r
-    case 40:   ScanCode = 0x0a; break; // (\r
-    case 61:   ScanCode = 0x0d; break; // =\r
-    case 65:   ScanCode = 0x1e; break; // a\r
-    case 66:   ScanCode = 0x30; break; // b\r
-    case 67:   ScanCode = 0x2e; break; // c\r
-    case 68:   ScanCode = 0x20; break; // d\r
-    case 69:   ScanCode = 0x12; break; // e\r
-    case 70:   ScanCode = 0x21; break; // f\r
-    case 71:   ScanCode = 0x22; break; // g\r
-    case 72:   ScanCode = 0x23; break; // h\r
-    case 73:   ScanCode = 0x17; break; // i\r
-    case 74:   ScanCode = 0x24; break; // j\r
-    case 75:   ScanCode = 0x25; break; // k\r
-    case 76:   ScanCode = 0x26; break; // l\r
-    case 77:   ScanCode = 0x32; break; // m\r
-    case 78:   ScanCode = 0x31; break; // n\r
-    case 79:   ScanCode = 0x18; break; // o\r
-    case 80:   ScanCode = 0x19; break; // p\r
-    case 81:   ScanCode = 0x10; break; // q\r
-    case 82:   ScanCode = 0x13; break; // r\r
-    case 83:   ScanCode = 0x1f; break; // s\r
-    case 84:   ScanCode = 0x14; break; // t\r
-    case 85:   ScanCode = 0x16; break; // u\r
-    case 86:   ScanCode = 0x2f; break; // v\r
-    case 87:   ScanCode = 0x11; break; // w\r
-    case 88:   ScanCode = 0x2d; break; // x\r
-    case 89:   ScanCode = 0x15; break; // y\r
-    case 90:   ScanCode = 0x2c; break; // z\r
-    case 32:   ScanCode = 0x39; break; // space\r
-    case 44:   ScanCode = 0x33; break; // ,\r
-    case 60:   ScanCode = 0x33; break; // <\r
-    case 62:   ScanCode = 0x34; break; // >\r
-    case 63:   ScanCode = 0x35; break; // ?\r
-    case 92:   ScanCode = 0x2b; break; // backslash\r
-    case 124:  ScanCode = 0x2b; break; // bar\r
-    case 4097: ScanCode = 0x0f; break; // tab\r
-    case 4132: ScanCode = 0x3a; break; // caps lock\r
-    case 4096: ScanCode = 0x01; break; // esc\r
-    case 59:   ScanCode = 0x27; break; // ;\r
-    case 58:   ScanCode = 0x27; break; // :\r
-    case 39:   ScanCode = 0x28; break; // '\r
-    case 34:   ScanCode = 0x28; break; // "\r
-    case 91:   ScanCode = 0x1a; break; // [\r
-    case 123:  ScanCode = 0x1a; break; // {\r
-    case 93:   ScanCode = 0x1b; break; // ]\r
-    case 125:  ScanCode = 0x1b; break; // }\r
-    case 4144: ScanCode = 0x3b; break; // f1\r
-    case 4145: ScanCode = 0x3c; break; // f2\r
-    case 4146: ScanCode = 0x3d; break; // f3\r
-    case 4147: ScanCode = 0x3e; break; // f4\r
-    case 4148: ScanCode = 0x3f; break; // f5\r
-    case 4149: ScanCode = 0x40; break; // f6\r
-    case 4150: ScanCode = 0x41; break; // f7\r
-    case 4151: ScanCode = 0x42; break; // f8\r
-    case 4152: ScanCode = 0x43; break; // f9\r
-    case 4153: ScanCode = 0x44; break; // f10\r
-    case 4154: ScanCode = 0x57; break; // f11\r
-    case 4155: ScanCode = 0x58; break; // f12\r
-    case 4128: ScanCode = 0x2a; break; // shift\r
-    case 4131: ScanCode = 0x38; break; // alt\r
-    case 4129: ScanCode = 0x1d; break; // ctrl\r
-    case 96:   ScanCode = 0x29; break; // `\r
-    case 126:  ScanCode = 0x29; break; // ~\r
-    case 4099: ScanCode = 0x0e; break; // backspace\r
-  }\r
-//  if (ScanCode == 0)\r
-//    printf("key %d scancode %d\n", Key, ScanCode);\r
-  return ScanCode;\r
-}\r
-\r
-//*****************************************************************************\r
-void QMyMainWindow::keyPressEvent(QKeyEvent* e)\r
-{\r
-  if (!g_UpAndRunning)\r
-    return;\r
-  int ScanCode = GetScanCode(e);\r
-  if (ScanCode != 0)\r
-  {\r
-    rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS, ScanCode, 0);\r
-    e->accept();\r
-  }\r
-}\r
-\r
-//*****************************************************************************\r
-void QMyMainWindow::keyReleaseEvent(QKeyEvent* e)\r
-{\r
-  if (!g_UpAndRunning)\r
-  {\r
-    return;\r
-  }\r
-  int ScanCode = GetScanCode(e);\r
-  if (ScanCode != 0)\r
-  {\r
-    rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, ScanCode, 0);\r
-    e->accept();\r
-  }\r
-}\r
-\r
-//*****************************************************************************\r
-void QMyMainWindow::paintEvent(QPaintEvent * pe)\r
-{\r
-  QRect Rect;\r
-\r
-  Rect = pe->rect();\r
-  bitBlt(this, Rect.left(), Rect.top(), g_BS, Rect.left(), Rect.top(),\r
-         Rect.width(), Rect.height());\r
-}\r
-\r
-//*****************************************************************************\r
-void QMyMainWindow::closeEvent(QCloseEvent * e)\r
-{\r
-  e->accept();\r
-}\r
-\r
-//*****************************************************************************\r
-bool QMyMainWindow::event(QEvent * e)\r
-{\r
-  return QWidget::event(e);\r
-}\r
-\r
-//*****************************************************************************\r
-void QMyMainWindow::dataReceived()\r
-{\r
-  if (!rdp_loop(&g_deactivated, &g_ext_disc_reason))\r
-  {\r
-    g_SV->close();\r
-  }\r
-#ifdef WITH_RDPSND\r
-  if (g_dsp_busy)\r
-  {\r
-    if (g_SoundNotifier == 0)\r
-    {\r
-      g_SoundNotifier = new QSocketNotifier(g_dsp_fd, QSocketNotifier::Write,\r
-                                            g_MW);\r
-      g_MW->connect(g_SoundNotifier, SIGNAL(activated(int)), g_MW,\r
-                    SLOT(soundSend()));\r
-    }\r
-    else\r
-    {\r
-      if (!g_SoundNotifier->isEnabled())\r
-      {\r
-        g_SoundNotifier->setEnabled(true);\r
-      }\r
-    }\r
-  }\r
-#endif\r
-}\r
-\r
-/******************************************************************************/\r
-void QMyMainWindow::soundSend()\r
-{\r
-#ifdef WITH_RDPSND\r
-  g_SoundNotifier->setEnabled(false);\r
-  wave_out_play();\r
-  if (g_dsp_busy)\r
-  {\r
-    g_SoundNotifier->setEnabled(true);\r
-  }\r
-#endif\r
-}\r
-\r
-//*****************************************************************************\r
-void QMyScrollView::keyPressEvent(QKeyEvent * e)\r
-{\r
-  g_MW->keyPressEvent(e);\r
-}\r
-\r
-//*****************************************************************************\r
-void QMyScrollView::keyReleaseEvent(QKeyEvent * e)\r
-{\r
-  g_MW->keyReleaseEvent(e);\r
-}\r
-\r
-\r
-//*****************************************************************************\r
-void ui_begin_update(void)\r
-{\r
-  g_P1->begin(g_MW);\r
-  g_P2->begin(g_BS);\r
-}\r
-\r
-//*****************************************************************************\r
-void ui_end_update(void)\r
-{\r
-  g_P1->end();\r
-  g_P2->end();\r
-}\r
-\r
-/*****************************************************************************/\r
-int ui_init(void)\r
-{\r
-  g_App = new QApplication(g_argc, g_argv);\r
-  return 1;\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_deinit(void)\r
-{\r
-  delete g_App;\r
-}\r
-\r
-/*****************************************************************************/\r
-int ui_create_window(void)\r
-{\r
-  int w, h;\r
-  QPainter * painter;\r
-  QWidget * desktop;\r
-\r
-  g_MW = new QMyMainWindow();\r
-  g_SV = new QMyScrollView();\r
-  g_SV->addChild(g_MW);\r
-  g_BS = new QPixmap(g_width, g_height);\r
-  painter = new QPainter(g_BS);\r
-  painter->fillRect(0, 0, g_width, g_height, QBrush(QColor("white")));\r
-  painter->fillRect(0, 0, g_width, g_height, QBrush(QBrush::CrossPattern));\r
-  delete painter;\r
-  g_DS = new QPixmap(480, 480);\r
-  g_P1 = new QPainter();\r
-  g_P2 = new QPainter();\r
-  g_ClipRect = new QRegion(0, 0, g_width, g_height);\r
-  desktop = QApplication::desktop();\r
-  w = desktop->width();              // returns screen width\r
-  h = desktop->height();             // returns screen height\r
-  g_MW->resize(g_width, g_height);\r
-  if (w < g_width || h < g_height)\r
-  {\r
-    g_SV->resize(w, h);\r
-  }\r
-  else\r
-  {\r
-    g_SV->resize(g_width + 4, g_height + 4);\r
-  }\r
-  g_SV->setMaximumWidth(g_width + 4);\r
-  g_SV->setMaximumHeight(g_height + 4);\r
-  g_App->setMainWidget(g_SV);\r
-  g_SV->show();\r
-  g_MW->setMouseTracking(true);\r
-  if (g_title[0] != 0)\r
-  {\r
-    g_SV->setCaption(g_title);\r
-  }\r
-\r
-/*  XGrayKey(0, 64, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);\r
-  XGrayKey(0, 113, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);\r
-  XGrayKey(0, 37, AnyModifie, SV-winId(), 0, GrabModeAsync, GrabModeAsync);\r
-  XGrayKey(0, 109, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);\r
-  XGrayKey(0, 115, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);\r
-  XGrayKey(0, 116, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);\r
-  XGrayKey(0, 117, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);\r
-  XGrayKey(0, 62, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);\r
-  XGrayKey(0, 50, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);*/\r
-\r
-  return 1;\r
-}\r
-\r
-//*****************************************************************************\r
-void ui_main_loop(void)\r
-{\r
-#ifdef WITH_RDPSND\r
-  // init sound\r
-  if (g_rdpsnd)\r
-  {\r
-    rdpsnd_init();\r
-  }\r
-#endif\r
-  // connect\r
-  if (!rdp_connect(g_servername, g_flags, "", "", "", ""))\r
-  {\r
-    return;\r
-  }\r
-  // start notifier\r
-  g_SocketNotifier = new QSocketNotifier(g_sock, QSocketNotifier::Read, g_MW);\r
-  g_MW->connect(g_SocketNotifier, SIGNAL(activated(int)),\r
-                g_MW, SLOT(dataReceived()));\r
-  g_UpAndRunning = 1;\r
-  // app main loop\r
-  g_App->exec();\r
-}\r
-\r
-//*****************************************************************************\r
-void ui_destroy_window(void)\r
-{\r
-  delete g_MW;\r
-  delete g_SV;\r
-  delete g_BS;\r
-  delete g_DS;\r
-  delete g_P1;\r
-  delete g_P2;\r
-  delete g_ClipRect;\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_bell(void)\r
-{\r
-}\r
-\r
-/*****************************************************************************/\r
-int ui_select(int in_val)\r
-{\r
-  if (g_sock == 0)\r
-  {\r
-    g_sock = in_val;\r
-  }\r
-  return 1;\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_destroy_cursor(void * cursor)\r
-{\r
-  QCursor * Cursor;\r
-  Cursor = (QCursor*)cursor;\r
-  if (Cursor != NULL)\r
-  {\r
-    delete Cursor;\r
-  }\r
-}\r
-\r
-/*****************************************************************************/\r
-void* ui_create_glyph(int width, int height, uint8 * data)\r
-{\r
-  QBitmap * Bitmap;\r
-  Bitmap = new QBitmap(width, height, data);\r
-  Bitmap->setMask(*Bitmap);\r
-  return (HGLYPH)Bitmap;\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_destroy_glyph(void * glyph)\r
-{\r
-  QBitmap* Bitmap;\r
-  Bitmap = (QBitmap*)glyph;\r
-  delete Bitmap;\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_destroy_bitmap(void * bmp)\r
-{\r
-  QPixmap * Pixmap;\r
-  Pixmap = (QPixmap*)bmp;\r
-  delete Pixmap;\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_reset_clip(void)\r
-{\r
-  g_P1->setClipRect(0, 0, g_width, g_height);\r
-  g_P2->setClipRect(0, 0, g_width, g_height);\r
-  delete g_ClipRect;\r
-  g_ClipRect = new QRegion(0, 0, g_width, g_height);\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_set_clip(int x, int y, int cx, int cy)\r
-{\r
-  g_P1->setClipRect(x, y, cx, cy);\r
-  g_P2->setClipRect(x, y, cx, cy);\r
-  delete g_ClipRect;\r
-  g_ClipRect = new QRegion(x, y, cx, cy);\r
-}\r
-\r
-/*****************************************************************************/\r
-void * ui_create_colourmap(COLOURMAP * colours)\r
-{\r
-  QColorMap* LCM;\r
-  int i, r, g, b;\r
-  LCM = (QColorMap*)malloc(sizeof(QColorMap));\r
-  memset(LCM, 0, sizeof(QColorMap));\r
-  i = 0;\r
-  while (i < colours->ncolours && i < 256)\r
-  {\r
-    r = colours->colours[i].red;\r
-    g = colours->colours[i].green;\r
-    b = colours->colours[i].blue;\r
-    LCM->RGBColors[i] = (r << 16) | (g << 8) | b;\r
-    i++;\r
-  }\r
-  LCM->NumColors = colours->ncolours;\r
-  return LCM;\r
-}\r
-\r
-//*****************************************************************************\r
-// todo, does this leak at end of program\r
-void ui_destroy_colourmap(HCOLOURMAP map)\r
-{\r
-  QColorMap * LCM;\r
-  LCM = (QColorMap*)map;\r
-  if (LCM == NULL)\r
-    return;\r
-  free(LCM);\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_set_colourmap(void * map)\r
-{\r
-  // destoy old colormap\r
-  ui_destroy_colourmap(g_CM);\r
-  g_CM = (QColorMap*)map;\r
-}\r
-\r
-/*****************************************************************************/\r
-HBITMAP ui_create_bitmap(int width, int height, uint8 * data)\r
-{\r
-  QImage * Image = NULL;\r
-  QPixmap * Pixmap;\r
-  uint32 * d = NULL;\r
-  uint16 * s;\r
-  int i;\r
-\r
-  switch (g_server_depth)\r
-  {\r
-    case 8:\r
-      Image = new QImage(data, width, height, 8, (QRgb*)&g_CM->RGBColors,\r
-                         g_CM->NumColors, QImage::IgnoreEndian);\r
-      break;\r
-    case 15:\r
-      d = (uint32*)malloc(width * height * 4);\r
-      s = (uint16*)data;\r
-      for (i = 0; i < width * height; i++)\r
-      {\r
-        d[i] = Color15to32(s[i]);\r
-      }\r
-      Image = new QImage((uint8*)d, width, height, 32, NULL,\r
-                         0, QImage::IgnoreEndian);\r
-      break;\r
-    case 16:\r
-      d = (uint32*)malloc(width * height * 4);\r
-      s = (uint16*)data;\r
-      for (i = 0; i < width * height; i++)\r
-      {\r
-        d[i] = Color16to32(s[i]);\r
-      }\r
-      Image = new QImage((uint8*)d, width, height, 32, NULL,\r
-                         0, QImage::IgnoreEndian);\r
-      break;\r
-    case 24:\r
-      d = (uint32*)malloc(width * height * 4);\r
-      memset(d, 0, width * height * 4);\r
-      for (i = 0; i < width * height; i++)\r
-      {\r
-        memcpy(d + i, data + i * 3, 3);\r
-      }\r
-      Image = new QImage((uint8*)d, width, height, 32, NULL,\r
-                         0, QImage::IgnoreEndian);\r
-      break;\r
-  }\r
-  if (Image == NULL)\r
-  {\r
-    return NULL;\r
-  }\r
-  Pixmap = new QPixmap();\r
-  Pixmap->convertFromImage(*Image);\r
-  delete Image;\r
-  if (d != NULL)\r
-  {\r
-    free(d);\r
-  }\r
-  return (HBITMAP)Pixmap;\r
-}\r
-\r
-//******************************************************************************\r
-// adjust coordinates for cliping rect\r
-int WarpCoords(int * x, int * y, int * cx, int * cy, int * srcx, int * srcy)\r
-{\r
-  int dx, dy;\r
-  QRect InRect(*x, *y, *cx, *cy);\r
-  QRect OutRect;\r
-  QRect CRect = g_ClipRect->boundingRect();\r
-  OutRect = InRect.intersect(CRect);\r
-  if (OutRect.isEmpty())\r
-  {\r
-    return False;\r
-  }\r
-  dx = OutRect.x() - InRect.x();\r
-  dy = OutRect.y() - InRect.y();\r
-  *x = OutRect.x();\r
-  *y = OutRect.y();\r
-  *cx = OutRect.width();\r
-  *cy = OutRect.height();\r
-  *srcx = *srcx + dx;\r
-  *srcy = *srcy + dy;\r
-  return True;\r
-}\r
-\r
-//******************************************************************************\r
-// needed because bitBlt don't seem to care about clipping rects\r
-// also has 2 dsts and src can be null\r
-void bitBltClip(QPaintDevice * dst1, QPaintDevice * dst2, int dx, int dy,\r
-                QPaintDevice * src, int sx, int sy, int sw, int sh,\r
-                Qt::RasterOp rop, bool im)\r
-{\r
-  if (WarpCoords(&dx, &dy, &sw, &sh, &sx, &sy))\r
-  {\r
-    if (dst1 != NULL)\r
-    {\r
-      if (src == NULL)\r
-      {\r
-        bitBlt(dst1, dx, dy, dst1, sx, sy, sw, sh, rop, im);\r
-      }\r
-      else\r
-      {\r
-        bitBlt(dst1, dx, dy, src, sx, sy, sw, sh, rop, im);\r
-      }\r
-    }\r
-    if (dst2 != NULL)\r
-    {\r
-      if (src == NULL)\r
-      {\r
-        bitBlt(dst2, dx, dy, dst2, sx, sy, sw, sh, rop, im);\r
-      }\r
-      else\r
-      {\r
-        bitBlt(dst2, dx, dy, src, sx, sy, sw, sh, rop, im);\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-#define DO_GLYPH(ttext,idx) \\r
-{ \\r
-  glyph = cache_get_font (font, ttext[idx]); \\r
-  if (!(flags & TEXT2_IMPLICIT_X)) \\r
-  { \\r
-    xyoffset = ttext[++idx]; \\r
-    if ((xyoffset & 0x80)) \\r
-    { \\r
-      if (flags & TEXT2_VERTICAL) \\r
-        y += ttext[idx+1] | (ttext[idx+2] << 8); \\r
-      else \\r
-        x += ttext[idx+1] | (ttext[idx+2] << 8); \\r
-      idx += 2; \\r
-    } \\r
-    else \\r
-    { \\r
-      if (flags & TEXT2_VERTICAL) \\r
-        y += xyoffset; \\r
-      else \\r
-        x += xyoffset; \\r
-    } \\r
-  } \\r
-  if (glyph != NULL) \\r
-  { \\r
-    g_P2->drawPixmap(x + glyph->offset, y + glyph->baseline, \\r
-                     *((QBitmap*)glyph->pixmap)); \\r
-    if (flags & TEXT2_IMPLICIT_X) \\r
-      x += glyph->width; \\r
-  } \\r
-}\r
-\r
-//*****************************************************************************\r
-void ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode,\r
-                  int x, int y, int clipx, int clipy,\r
-                  int clipcx, int clipcy, int boxx,\r
-                  int boxy, int boxcx, int boxcy, BRUSH * brush,\r
-                  int bgcolour, int fgcolour, uint8 * text, uint8 length)\r
-{\r
-  FONTGLYPH * glyph;\r
-  int i, j, xyoffset;\r
-  DATABLOB * entry;\r
-\r
-  SetColorx(&g_Color1, fgcolour);\r
-  SetColorx(&g_Color2, bgcolour);\r
-  g_P2->setBackgroundColor(g_Color2);\r
-  g_P2->setPen(g_Color1);\r
-  if (boxcx > 1)\r
-  {\r
-    g_P2->fillRect(boxx, boxy, boxcx, boxcy, QBrush(g_Color2));\r
-  }\r
-  else if (mixmode == MIX_OPAQUE)\r
-  {\r
-    g_P2->fillRect(clipx, clipy, clipcx, clipcy, QBrush(g_Color2));\r
-  }\r
-\r
-  /* Paint text, character by character */\r
-  for (i = 0; i < length;)\r
-  {\r
-    switch (text[i])\r
-    {\r
-      case 0xff:\r
-        if (i + 2 < length)\r
-        {\r
-          cache_put_text(text[i + 1], text, text[i + 2]);\r
-        }\r
-        else\r
-        {\r
-          error("this shouldn't be happening\n");\r
-          exit(1);\r
-        }\r
-        /* this will move pointer from start to first character after FF\r
-           command */\r
-        length -= i + 3;\r
-        text = &(text[i + 3]);\r
-        i = 0;\r
-        break;\r
-\r
-      case 0xfe:\r
-        entry = cache_get_text(text[i + 1]);\r
-        if (entry != NULL)\r
-        {\r
-          if ((((uint8 *) (entry->data))[1] == 0) &&\r
-                             (!(flags & TEXT2_IMPLICIT_X)))\r
-          {\r
-            if (flags & TEXT2_VERTICAL)\r
-            {\r
-              y += text[i + 2];\r
-            }\r
-            else\r
-            {\r
-              x += text[i + 2];\r
-            }\r
-          }\r
-          for (j = 0; j < entry->size; j++)\r
-          {\r
-            DO_GLYPH(((uint8 *) (entry->data)), j);\r
-          }\r
-        }\r
-        if (i + 2 < length)\r
-        {\r
-          i += 3;\r
-        }\r
-        else\r
-        {\r
-          i += 2;\r
-        }\r
-        length -= i;\r
-        /* this will move pointer from start to first character after FE\r
-           command */\r
-        text = &(text[i]);\r
-        i = 0;\r
-        break;\r
-\r
-      default:\r
-        DO_GLYPH(text, i);\r
-        i++;\r
-        break;\r
-    }\r
-  }\r
-  if (boxcx > 1)\r
-  {\r
-    bitBltClip(g_MW, NULL, boxx, boxy, g_BS, boxx, boxy, boxcx, boxcy,\r
-               Qt::CopyROP, true);\r
-  }\r
-  else\r
-  {\r
-    bitBltClip(g_MW, NULL, clipx, clipy, g_BS, clipx, clipy, clipcx,\r
-               clipcy, Qt::CopyROP, true);\r
-  }\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_line(uint8 opcode, int startx, int starty, int endx, int endy,\r
-             PEN * pen)\r
-{\r
-  SetColorx(&g_Color1, pen->colour);\r
-  SetOpCode(opcode);\r
-  g_P1->setPen(g_Color1);\r
-  g_P1->moveTo(startx, starty);\r
-  g_P1->lineTo(endx, endy);\r
-  g_P2->setPen(g_Color1);\r
-  g_P2->moveTo(startx, starty);\r
-  g_P2->lineTo(endx, endy);\r
-  ResetOpCode(opcode);\r
-}\r
-\r
-/*****************************************************************************/\r
-// not used\r
-void ui_triblt(uint8 opcode, int x, int y, int cx, int cy,\r
-               HBITMAP src, int srcx, int srcy,\r
-               BRUSH* brush, int bgcolour, int fgcolour)\r
-{\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_memblt(uint8 opcode, int x, int y, int cx, int cy,\r
-               HBITMAP src, int srcx, int srcy)\r
-{\r
-  QPixmap* Pixmap;\r
-  Pixmap = (QPixmap*)src;\r
-  if (Pixmap != NULL)\r
-  {\r
-    SetOpCode(opcode);\r
-    g_P1->drawPixmap(x, y, *Pixmap, srcx, srcy, cx, cy);\r
-    g_P2->drawPixmap(x, y, *Pixmap, srcx, srcy, cx, cy);\r
-    ResetOpCode(opcode);\r
-  }\r
-}\r
-\r
-//******************************************************************************\r
-void CommonDeskSave(QPixmap* Pixmap1, QPixmap* Pixmap2, int Offset, int x,\r
-                    int y, int cx, int cy, int dir)\r
-{\r
-  int lx;\r
-  int ly;\r
-  int x1;\r
-  int y1;\r
-  int width;\r
-  int lcx;\r
-  int right;\r
-  int bottom;\r
-  lx = Offset % 480;\r
-  ly = Offset / 480;\r
-  y1 = y;\r
-  right = x + cx;\r
-  bottom = y + cy;\r
-  while (y1 < bottom)\r
-  {\r
-    x1 = x;\r
-    lcx = cx;\r
-    while (x1 < right)\r
-    {\r
-      width = 480 - lx;\r
-      if (width > lcx)\r
-        width = lcx;\r
-      if (dir == 0)\r
-        bitBlt(Pixmap1, lx, ly, Pixmap2, x1, y1, width, 1, Qt::CopyROP, true);\r
-      else\r
-        bitBlt(Pixmap2, x1, y1, Pixmap1, lx, ly, width, 1, Qt::CopyROP, true);\r
-      lx = lx + width;\r
-      if (lx >= 480)\r
-      {\r
-        lx = 0;\r
-        ly++;\r
-        if (ly >= 480)\r
-          ly = 0;\r
-      }\r
-      lcx = lcx - width;\r
-      x1 = x1 + width;\r
-    }\r
-    y1++;\r
-  }\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)\r
-{\r
-  QPixmap * Pixmap;\r
-\r
-  Pixmap = new QPixmap(cx, cy);\r
-  CommonDeskSave(g_DS, Pixmap, offset, 0, 0, cx, cy, 1);\r
-  bitBltClip(g_MW, g_BS, x, y, Pixmap, 0, 0, cx, cy, Qt::CopyROP, true);\r
-  delete Pixmap;\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)\r
-{\r
-  CommonDeskSave(g_DS, g_BS, offset, x, y, cx, cy, 0);\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_rect(int x, int y, int cx, int cy, int colour)\r
-{\r
-  SetColorx(&g_Color1, colour);\r
-  g_P1->fillRect(x, y, cx, cy, QBrush(g_Color1));\r
-  g_P2->fillRect(x, y, cx, cy, QBrush(g_Color1));\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_screenblt(uint8 opcode, int x, int y, int cx, int cy,\r
-                  int srcx, int srcy)\r
-{\r
-  SetOpCode(opcode);\r
-  bitBltClip(g_MW, g_BS, x, y, NULL, srcx, srcy, cx, cy, Qt::CopyROP, true);\r
-  ResetOpCode(opcode);\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_patblt(uint8 opcode, int x, int y, int cx, int cy,\r
-               BRUSH* brush, int bgcolour, int fgcolour)\r
-{\r
-  QBitmap* Bitmap;\r
-  QBrush* Brush;\r
-  uint8 ipattern[8], i;\r
-  SetOpCode(opcode);\r
-  switch (brush->style)\r
-  {\r
-    case 0:\r
-      SetColorx(&g_Color1, fgcolour);\r
-      g_P2->fillRect(x, y, cx, cy, QBrush(g_Color1));\r
-      break;\r
-    case 3:\r
-      SetColorx(&g_Color1, fgcolour);\r
-      SetColorx(&g_Color2, bgcolour);\r
-      for (i = 0; i != 8; i++)\r
-      {\r
-        ipattern[7 - i] = ~brush->pattern[i];\r
-      }\r
-      Bitmap = new QBitmap(8, 8, ipattern);\r
-      Brush = new QBrush(g_Color1, *Bitmap);\r
-      g_P2->setBackgroundMode(Qt::OpaqueMode);\r
-      g_P2->setBrushOrigin(brush->xorigin, brush->yorigin);\r
-      g_P2->setBackgroundColor(g_Color2);\r
-      g_P2->fillRect(x, y, cx, cy, *Brush);\r
-      delete Brush;\r
-      delete Bitmap;\r
-      g_P2->setBackgroundMode(Qt::TransparentMode);\r
-      g_P2->setBrushOrigin(0, 0);\r
-      break;\r
-  }\r
-  ResetOpCode(opcode);\r
-  bitBltClip(g_MW, NULL, x, y, g_BS, x, y, cx, cy, Qt::CopyROP, true);\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_destblt(uint8 opcode, int x, int y, int cx, int cy)\r
-{\r
-  SetOpCode(opcode);\r
-  g_P1->fillRect(x, y, cx, cy, QBrush(QColor("black")));\r
-  g_P2->fillRect(x, y, cx, cy, QBrush(QColor("black")));\r
-  ResetOpCode(opcode);\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_move_pointer(int x, int y)\r
-{\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_set_null_cursor(void)\r
-{\r
-  g_MW->setCursor(10); // Qt::BlankCursor\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_paint_bitmap(int x, int y, int cx, int cy,\r
-                     int width, int height, uint8* data)\r
-{\r
-  QImage * Image = NULL;\r
-  QPixmap * Pixmap;\r
-  uint32 * d = NULL;\r
-  uint16 * s;\r
-  int i;\r
-\r
-  switch (g_server_depth)\r
-  {\r
-    case 8:\r
-      Image = new QImage(data, width, height, 8, (QRgb*)&g_CM->RGBColors,\r
-                         g_CM->NumColors, QImage::IgnoreEndian);\r
-      break;\r
-    case 15:\r
-      d = (uint32*)malloc(width * height * 4);\r
-      s = (uint16*)data;\r
-      for (i = 0; i < width * height; i++)\r
-      {\r
-        d[i] = Color15to32(s[i]);\r
-      }\r
-      Image = new QImage((uint8*)d, width, height, 32, NULL,\r
-                         0, QImage::IgnoreEndian);\r
-      break;\r
-    case 16:\r
-      d = (uint32*)malloc(width * height * 4);\r
-      s = (uint16*)data;\r
-      for (i = 0; i < width * height; i++)\r
-      {\r
-        d[i] = Color16to32(s[i]);\r
-      }\r
-      Image = new QImage((uint8*)d, width, height, 32, NULL,\r
-                         0, QImage::IgnoreEndian);\r
-      break;\r
-    case 24:\r
-      d = (uint32*)malloc(width * height * 4);\r
-      memset(d, 0, width * height * 4);\r
-      for (i = 0; i < width * height; i++)\r
-      {\r
-        memcpy(d + i, data + i * 3, 3);\r
-      }\r
-      Image = new QImage((uint8*)d, width, height, 32, NULL,\r
-                         0, QImage::IgnoreEndian);\r
-      break;\r
-  }\r
-  if (Image == NULL)\r
-  {\r
-    return;\r
-  }\r
-  Pixmap = new QPixmap();\r
-  Pixmap->convertFromImage(*Image);\r
-  g_P1->drawPixmap(x, y, *Pixmap, 0, 0, cx, cy);\r
-  g_P2->drawPixmap(x, y, *Pixmap, 0, 0, cx, cy);\r
-  delete Image;\r
-  delete Pixmap;\r
-  if (d != NULL)\r
-  {\r
-    free(d);\r
-  }\r
-}\r
-\r
-//******************************************************************************\r
-int Is24On(uint8* Data, int X, int Y)\r
-{\r
-  uint8 R, G, B;\r
-  int Start;\r
-  Start = Y * 32 * 3 + X * 3;\r
-  R = Data[Start];\r
-  G = Data[Start + 1];\r
-  B = Data[Start + 2];\r
-  return !((R == 0) && (G == 0) && (B == 0));\r
-}\r
-\r
-//******************************************************************************\r
-int Is1On(uint8* Data, int X, int Y)\r
-{\r
-  int Start;\r
-  int Shift;\r
-  Start = (Y * 32) / 8 + X / 8;\r
-  Shift = X % 8;\r
-  return (Data[Start] & (0x80 >> Shift)) == 0;\r
-}\r
-\r
-//******************************************************************************\r
-void Set1(uint8* Data, int X, int Y)\r
-{\r
-  int Start;\r
-  int Shift;\r
-  Start = (Y * 32) / 8 + X / 8;\r
-  Shift = X % 8;\r
-  Data[Start] = Data[Start] | (0x80 >> Shift);\r
-}\r
-\r
-//******************************************************************************\r
-void FlipOver(uint8* Data)\r
-{\r
-  uint8 AData[128];\r
-  int Index;\r
-  memcpy(AData, Data, 128);\r
-  for (Index = 0; Index <= 31; Index++)\r
-  {\r
-    Data[127 - (Index * 4 + 3)] = AData[Index * 4];\r
-    Data[127 - (Index * 4 + 2)] = AData[Index * 4 + 1];\r
-    Data[127 - (Index * 4 + 1)] = AData[Index * 4 + 2];\r
-    Data[127 - Index * 4] = AData[Index * 4 + 3];\r
-  }\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_set_cursor(HCURSOR cursor)\r
-{\r
-  QCursor* Cursor;\r
-  Cursor = (QCursor*)cursor;\r
-  if (Cursor != NULL)\r
-    g_MW->setCursor(*Cursor);\r
-}\r
-\r
-/*****************************************************************************/\r
-HCURSOR ui_create_cursor(unsigned int x, unsigned int y,\r
-                         int width, int height,\r
-                         uint8* andmask, uint8* xormask)\r
-{\r
-  uint8 AData[128];\r
-  uint8 AMask[128];\r
-  QBitmap* DataBitmap;\r
-  QBitmap* MaskBitmap;\r
-  QCursor* Cursor;\r
-  int I1, I2, BOn, MOn;\r
-\r
-  if (width != 32 || height != 32)\r
-  {\r
-    return 0;\r
-  }\r
-  memset(AData, 0, 128);\r
-  memset(AMask, 0, 128);\r
-  for (I1 = 0; I1 <= 31; I1++)\r
-  {\r
-    for (I2 = 0; I2 <= 31; I2++)\r
-    {\r
-      MOn = Is24On(xormask, I1, I2);\r
-      BOn = Is1On(andmask, I1, I2);\r
-      if (BOn ^ MOn) // xor\r
-      {\r
-        Set1(AData, I1, I2);\r
-        if (!MOn)\r
-        {\r
-          Set1(AMask, I1, I2);\r
-        }\r
-      }\r
-      if (MOn)\r
-      {\r
-        Set1(AMask, I1, I2);\r
-      }\r
-    }\r
-  }\r
-  FlipOver(AData);\r
-  FlipOver(AMask);\r
-  DataBitmap = new QBitmap(32, 32, AData);\r
-  MaskBitmap = new QBitmap(32, 32, AMask);\r
-  Cursor = new QCursor(*DataBitmap, *MaskBitmap, x, y);\r
-  delete DataBitmap;\r
-  delete MaskBitmap;\r
-  return Cursor;\r
-}\r
-\r
-/*****************************************************************************/\r
-uint16 ui_get_numlock_state(uint32 state)\r
-{\r
-  return 0;\r
-}\r
-\r
-/*****************************************************************************/\r
-uint32 read_keyboard_state(void)\r
-{\r
-  return 0;\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_resize_window(void)\r
-{\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints,\r
-                BRUSH * brush, int bgcolour, int fgcolour)\r
-{\r
-}\r
-\r
-/*****************************************************************************/\r
-/* todo, use qt function for this (QPainter::drawPolyline) */\r
-void ui_polyline(uint8 opcode, POINT * points, int npoints, PEN * pen)\r
-{\r
-  int i, x, y, dx, dy;\r
-\r
-  if (npoints > 0)\r
-  {\r
-    x = points[0].x;\r
-    y = points[0].y;\r
-    for (i = 1; i < npoints; i++)\r
-    {\r
-      dx = points[i].x;\r
-      dy = points[i].y;\r
-      ui_line(opcode, x, y, x + dx, y + dy, pen);\r
-      x = x + dx;\r
-      y = y + dy;\r
-    }\r
-  }\r
-}\r
-\r
-/*****************************************************************************/\r
-void ui_ellipse(uint8 opcode, uint8 fillmode,\r
-                int x, int y, int cx, int cy,\r
-                BRUSH * brush, int bgcolour, int fgcolour)\r
-{\r
-}\r
-\r
-/*****************************************************************************/\r
-void generate_random(uint8 * random)\r
-{\r
-  QFile File("/dev/random");\r
-  File.open(IO_ReadOnly);\r
-  if (File.readBlock((char*)random, 32) == 32)\r
-  {\r
-    return;\r
-  }\r
-  warning("no /dev/random\n");\r
-  memcpy(random, "12345678901234567890123456789012", 32);\r
-}\r
-\r
-/*****************************************************************************/\r
-void save_licence(uint8 * data, int length)\r
-{\r
-  char * home, * path, * tmppath;\r
-  int fd;\r
-\r
-  home = getenv("HOME");\r
-  if (home == NULL)\r
-  {\r
-    return;\r
-  }\r
-  path = (char *) xmalloc(strlen(home) + strlen(g_hostname) +\r
-                          sizeof("/.rdesktop/licence."));\r
-  sprintf(path, "%s/.rdesktop", home);\r
-  if ((mkdir(path, 0700) == -1) && errno != EEXIST)\r
-  {\r
-    perror(path);\r
-    return;\r
-  }\r
-  /* write licence to licence.hostname.new, then atomically rename to\r
-     licence.hostname */\r
-  sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);\r
-  tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));\r
-  strcpy(tmppath, path);\r
-  strcat(tmppath, ".new");\r
-  fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);\r
-  if (fd == -1)\r
-  {\r
-    perror(tmppath);\r
-    return;\r
-  }\r
-  if (write(fd, data, length) != length)\r
-  {\r
-    perror(tmppath);\r
-    unlink(tmppath);\r
-  }\r
-  else if (rename(tmppath, path) == -1)\r
-  {\r
-    perror(path);\r
-    unlink(tmppath);\r
-  }\r
-  close(fd);\r
-  xfree(tmppath);\r
-  xfree(path);\r
-}\r
-\r
-/*****************************************************************************/\r
-int load_licence(uint8 ** data)\r
-{\r
-  char * home, * path;\r
-  struct stat st;\r
-  int fd, length;\r
-\r
-  home = getenv("HOME");\r
-  if (home == NULL)\r
-  {\r
-    return -1;\r
-  }\r
-  path = (char *) xmalloc(strlen(home) + strlen(g_hostname) +\r
-                          sizeof("/.rdesktop/licence."));\r
-  sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);\r
-  fd = open(path, O_RDONLY);\r
-  if (fd == -1)\r
-  {\r
-    return -1;\r
-  }\r
-  if (fstat(fd, &st))\r
-  {\r
-    return -1;\r
-  }\r
-  *data = (uint8 *) xmalloc(st.st_size);\r
-  length = read(fd, *data, st.st_size);\r
-  close(fd);\r
-  xfree(path);\r
-  return length;\r
-}\r
-\r
-/*****************************************************************************/\r
-void* xrealloc(void * in_val, int size)\r
-{\r
-  return realloc(in_val, size);\r
-}\r
-\r
-/*****************************************************************************/\r
-void* xmalloc(int size)\r
-{\r
-  return malloc(size);\r
-}\r
-\r
-/*****************************************************************************/\r
-void xfree(void * in_val)\r
-{\r
-  if (in_val != NULL)\r
-  {\r
-    free(in_val);\r
-  }\r
-}\r
-\r
-/*****************************************************************************/\r
-char * xstrdup(const char * s)\r
-{\r
-  char * mem = strdup(s);\r
-  if (mem == NULL)\r
-  {\r
-    perror("strdup");\r
-    exit(1);\r
-  }\r
-  return mem;\r
-}\r
-\r
-/*****************************************************************************/\r
-void warning(char * format, ...)\r
-{\r
-  va_list ap;\r
-\r
-  fprintf(stderr, "WARNING: ");\r
-  va_start(ap, format);\r
-  vfprintf(stderr, format, ap);\r
-  va_end(ap);\r
-}\r
-\r
-/*****************************************************************************/\r
-void unimpl(char * format, ...)\r
-{\r
-  va_list ap;\r
-\r
-  fprintf(stderr, "NOT IMPLEMENTED: ");\r
-  va_start(ap, format);\r
-  vfprintf(stderr, format, ap);\r
-  va_end(ap);\r
-}\r
-\r
-/*****************************************************************************/\r
-void error(char * format, ...)\r
-{\r
-  va_list ap;\r
-\r
-  fprintf(stderr, "ERROR: ");\r
-  va_start(ap, format);\r
-  vfprintf(stderr, format, ap);\r
-  va_end(ap);\r
-}\r
-\r
-/*****************************************************************************/\r
-void out_params(void)\r
-{\r
-  fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");\r
-  fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");\r
-  fprintf(stderr, "QT uiport by Jay Sorg\n");\r
-  fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");\r
-  fprintf(stderr, "Usage: qtrdesktop [options] server\n");\r
-  fprintf(stderr, "   -g WxH: desktop geometry\n");\r
-  fprintf(stderr, "   -4: use RDP version 4\n");\r
-  fprintf(stderr, "   -5: use RDP version 5 (default)\n");\r
-  fprintf(stderr, "   -t 3389: tcp port)\n");\r
-  fprintf(stderr, "   -a 8|16|24: connection colour depth\n");\r
-  fprintf(stderr, "   -T title: window title\n");\r
-  fprintf(stderr, "   -P: use persistent bitmap caching\n");\r
-  fprintf(stderr, "   -0: attach to console\n");\r
-  fprintf(stderr, "   -z: enable rdp compression\n");\r
-  fprintf(stderr, "   -r sound: enable sound\n");\r
-  fprintf(stderr, "\n");\r
-}\r
-\r
-/*****************************************************************************/\r
-/* produce a hex dump */\r
-void hexdump(uint8 * p, uint32 len)\r
-{\r
-  uint8 * line = p;\r
-  int i, thisline;\r
-  uint32 offset = 0;\r
-\r
-  while (offset < len)\r
-  {\r
-    printf("%04x ", offset);\r
-    thisline = len - offset;\r
-    if (thisline > 16)\r
-    {\r
-      thisline = 16;\r
-    }\r
-    for (i = 0; i < thisline; i++)\r
-    {\r
-      printf("%02x ", line[i]);\r
-    }\r
-    for (; i < 16; i++)\r
-    {\r
-      printf("   ");\r
-    }\r
-    for (i = 0; i < thisline; i++)\r
-    {\r
-      printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');\r
-    }\r
-    printf("\n");\r
-    offset += thisline;\r
-    line += thisline;\r
-  }\r
-}\r
-\r
-/*****************************************************************************/\r
-int rd_pstcache_mkdir(void)\r
-{\r
-  char * home;\r
-  char bmpcache_dir[256];\r
-\r
-  home = getenv("HOME");\r
-  if (home == NULL)\r
-  {\r
-    return False;\r
-  }\r
-  sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");\r
-  if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)\r
-  {\r
-    perror(bmpcache_dir);\r
-    return False;\r
-  }\r
-  sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");\r
-  if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)\r
-  {\r
-    perror(bmpcache_dir);\r
-    return False;\r
-  }\r
-  return True;\r
-}\r
-\r
-/*****************************************************************************/\r
-int rd_open_file(char * filename)\r
-{\r
-  char * home;\r
-  char fn[256];\r
-  int fd;\r
-\r
-  home = getenv("HOME");\r
-  if (home == NULL)\r
-  {\r
-    return -1;\r
-  }\r
-  sprintf(fn, "%s/.rdesktop/%s", home, filename);\r
-  fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);\r
-  if (fd == -1)\r
-  {\r
-    perror(fn);\r
-  }\r
-  return fd;\r
-}\r
-\r
-/*****************************************************************************/\r
-void rd_close_file(int fd)\r
-{\r
-  close(fd);\r
-}\r
-\r
-/*****************************************************************************/\r
-int rd_read_file(int fd, void * ptr, int len)\r
-{\r
-  return read(fd, ptr, len);\r
-}\r
-\r
-/*****************************************************************************/\r
-int rd_write_file(int fd, void * ptr, int len)\r
-{\r
-  return write(fd, ptr, len);\r
-}\r
-\r
-/*****************************************************************************/\r
-int rd_lseek_file(int fd, int offset)\r
-{\r
-  return lseek(fd, offset, SEEK_SET);\r
-}\r
-\r
-/*****************************************************************************/\r
-int rd_lock_file(int fd, int start, int len)\r
-{\r
-  struct flock lock;\r
-\r
-  lock.l_type = F_WRLCK;\r
-  lock.l_whence = SEEK_SET;\r
-  lock.l_start = start;\r
-  lock.l_len = len;\r
-  if (fcntl(fd, F_SETLK, &lock) == -1)\r
-  {\r
-    return False;\r
-  }\r
-  return True;\r
-}\r
-\r
-/*****************************************************************************/\r
-void get_username_and_hostname(void)\r
-{\r
-  char fullhostname[64];\r
-  char * p;\r
-  struct passwd * pw;\r
-\r
-  STRNCPY(g_username, "unknown", sizeof(g_username));\r
-  STRNCPY(g_hostname, "unknown", sizeof(g_hostname));\r
-  pw = getpwuid(getuid());\r
-  if (pw != NULL && pw->pw_name != NULL)\r
-  {\r
-    STRNCPY(g_username, pw->pw_name, sizeof(g_username));\r
-  }\r
-  if (gethostname(fullhostname, sizeof(fullhostname)) != -1)\r
-  {\r
-    p = strchr(fullhostname, '.');\r
-    if (p != NULL)\r
-    {\r
-      *p = 0;\r
-    }\r
-    STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));\r
-  }\r
-}\r
-\r
-/*****************************************************************************/\r
-int parse_parameters(int in_argc, char ** in_argv)\r
-{\r
-  int i;\r
-  char * p;\r
-\r
-  if (in_argc <= 1)\r
-  {\r
-    out_params();\r
-    return 0;\r
-  }\r
-  g_argc = in_argc;\r
-  g_argv = in_argv;\r
-  for (i = 1; i < in_argc; i++)\r
-  {\r
-    strcpy(g_servername, in_argv[i]);\r
-    if (strcmp(in_argv[i], "-g") == 0)\r
-    {\r
-      g_width = strtol(in_argv[i + 1], &p, 10);\r
-      if (g_width <= 0)\r
-      {\r
-        error("invalid geometry\n");\r
-        return 0;\r
-      }\r
-      if (*p == 'x')\r
-      {\r
-        g_height = strtol(p + 1, NULL, 10);\r
-      }\r
-      if (g_height <= 0)\r
-      {\r
-        error("invalid geometry\n");\r
-        return 0;\r
-      }\r
-      g_width = (g_width + 3) & ~3;\r
-    }\r
-    else if (strcmp(in_argv[i], "-T") == 0)\r
-    {\r
-      strcpy(g_title, in_argv[i + 1]);\r
-    }\r
-    else if (strcmp(in_argv[i], "-4") == 0)\r
-    {\r
-      g_use_rdp5 = 0;\r
-    }\r
-    else if (strcmp(in_argv[i], "-5") == 0)\r
-    {\r
-      g_use_rdp5 = 1;\r
-    }\r
-    else if (strcmp(in_argv[i], "-a") == 0)\r
-    {\r
-      g_server_depth = strtol(in_argv[i + 1], &p, 10);\r
-      if (g_server_depth != 8 && g_server_depth != 15 &&\r
-          g_server_depth != 16 && g_server_depth != 24)\r
-      {\r
-        error("invalid bpp\n");\r
-        return 0;\r
-      }\r
-    }\r
-    else if (strcmp(in_argv[i], "-t") == 0)\r
-    {\r
-      g_tcp_port_rdp = strtol(in_argv[i + 1], &p, 10);\r
-    }\r
-    else if (strcmp(in_argv[i], "-P") == 0)\r
-    {\r
-      g_bitmap_cache_persist_enable = 1;\r
-    }\r
-    else if (strcmp(in_argv[i], "-0") == 0)\r
-    {\r
-      g_console_session = 1;\r
-    }\r
-    else if (strcmp(in_argv[i], "-z") == 0)\r
-    {\r
-      g_flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);\r
-    }\r
-    else if (strcmp(in_argv[i], "-r") == 0)\r
-    {\r
-      if (strcmp(in_argv[i + 1], "sound") == 0)\r
-      {\r
-#ifdef WITH_RDPSND\r
-        g_rdpsnd = 1;\r
-#endif\r
-      }\r
-    }\r
-  }\r
-  return 1;\r
-}\r
-\r
-/*****************************************************************************/\r
-int main(int in_argc, char** in_argv)\r
-{\r
-  get_username_and_hostname();\r
-  if (!parse_parameters(in_argc, in_argv))\r
-  {\r
-    return 0;\r
-  }\r
-  if (!ui_init())\r
-  {\r
-    return 1;\r
-  }\r
-  if (!ui_create_window())\r
-  {\r
-    return 1;\r
-  }\r
-  ui_main_loop();\r
-  ui_destroy_window();\r
-  ui_deinit();\r
-  return 0;\r
-}\r
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   User interface services - QT Window System
+   Copyright (C) Jay Sorg 2004-2006
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "rdesktop.h"
+
+#include <qapplication.h>
+#include <qmainwindow.h>
+#include <qwidget.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qbrush.h>
+#include <qimage.h>
+#include <qbitmap.h>
+#include <qcursor.h>
+#include <qsocketnotifier.h>
+#include <qscrollview.h>
+#include <qfile.h>
+
+#include "qtwin.h"
+
+#include <unistd.h> // gethostname
+#include <pwd.h> // getpwuid
+#include <stdarg.h> // va_list va_start va_end
+
+#include <errno.h>
+#include <fcntl.h>
+
+/* rdesktop globals */
+extern int g_tcp_port_rdp;
+int g_use_rdp5 = 1;
+char g_hostname[16];
+char g_username[64];
+int g_height = 600;
+int g_width = 800;
+int g_server_depth = 8;
+int g_encryption = 1;
+int g_desktop_save = 1;
+int g_polygon_ellipse_orders = 0;
+int g_bitmap_cache = 1;
+int g_bitmap_cache_persist_enable = False;
+int g_bitmap_cache_precache = True;
+int g_bitmap_compression = 1;
+int g_rdp5_performanceflags = 0;
+int g_console_session = 0;
+int g_keylayout = 0x409; /* Defaults to US keyboard layout */
+int g_keyboard_type = 0x4; /* Defaults to US keyboard layout */
+int g_keyboard_subtype = 0x0; /* Defaults to US keyboard layout */
+int g_keyboard_functionkeys = 0xc; /* Defaults to US keyboard layout */
+
+/* hack globals */
+static int g_argc = 0;
+static char ** g_argv = 0;
+static int g_UpAndRunning = 0;
+static int g_sock = 0;
+static int g_deactivated = 0;
+static uint32 g_ext_disc_reason = 0;
+static char g_servername[128];
+static char g_title[128] = "";
+static int g_flags = RDP_LOGON_NORMAL;
+
+#ifdef WITH_RDPSND
+extern int g_dsp_busy;
+extern int g_dsp_fd;
+static int g_rdpsnd = 0;
+static QSocketNotifier * g_SoundNotifier = 0;
+#endif
+
+/* qt globals */
+static QSocketNotifier * g_SocketNotifier = 0;
+static QApplication * g_App = 0;
+static QMyMainWindow * g_MW = 0;
+static QMyScrollView * g_SV = 0;
+static QPixmap * g_BS = 0;
+static QPixmap * g_DS = 0;
+static QPainter * g_P1 = 0;
+static QPainter * g_P2 = 0;
+static QColor g_Color1;
+static QColor g_Color2;
+
+struct QColorMap
+{
+  uint32 RGBColors[256];
+  int NumColors;
+};
+static struct QColorMap * g_CM = 0;
+static QRegion * g_ClipRect;
+
+static Qt::RasterOp g_OpCodes[16] = {
+    Qt::ClearROP,        // BLACKNESS     0
+    Qt::NorROP,          // NOTSRCERASE   DSon
+    Qt::NotAndROP,       //               DSna
+    Qt::NotCopyROP,      // NOTSRCCOPY    Sn
+    Qt::AndNotROP,       // SRCERASE      SDna
+    Qt::NotROP,          // DSTINVERT     Dn
+    Qt::XorROP,          // SRCINVERT     DSx
+    Qt::NandROP,         //               DSan
+    Qt::AndROP,          // SRCAND        DSa
+    Qt::NotXorROP,       //               DSxn
+    Qt::NopROP,          //               D
+    Qt::NotOrROP,        // MERGEPAINT    DSno
+    Qt::CopyROP,         // SRCCOPY       S
+    Qt::OrNotROP,        //               SDno
+    Qt::OrROP,           // SRCPAINT      DSo
+    Qt::SetROP};         // WHITENESS     1
+
+/* Session Directory redirection */
+BOOL g_redirect = False;
+char g_redirect_server[64];
+char g_redirect_domain[16];
+char g_redirect_password[64];
+char g_redirect_username[64];
+char g_redirect_cookie[128];
+uint32 g_redirect_flags = 0;
+
+//*****************************************************************************
+uint32 Color15to32(uint32 InColor)
+{
+  uint32 r, g, b;
+
+  r = (InColor & 0x7c00) >> 10;
+  r = (r * 0xff) / 0x1f;
+  g = (InColor & 0x03e0) >> 5;
+  g = (g * 0xff) / 0x1f;
+  b = (InColor & 0x001f);
+  b = (b * 0xff) / 0x1f;
+  return (r << 16) | (g << 8) | b;
+}
+
+//*****************************************************************************
+uint32 Color16to32(uint32 InColor)
+{
+  uint32 r, g, b;
+
+  r = (InColor & 0xf800) >> 11;
+  r = (r * 0xff) / 0x1f;
+  g = (InColor & 0x07e0) >> 5;
+  g = (g * 0xff) / 0x3f;
+  b = (InColor & 0x001f);
+  b = (b * 0xff) / 0x1f;
+  return (r << 16) | (g << 8) | b;
+}
+
+//*****************************************************************************
+uint32 Color24to32(uint32 InColor)
+{
+  return ((InColor & 0x00ff0000) >> 16) |
+         ((InColor & 0x000000ff) << 16) |
+          (InColor & 0x0000ff00);
+}
+
+//*****************************************************************************
+void SetColorx(QColor * Color, uint32 InColor)
+{
+  switch (g_server_depth)
+  {
+    case 8:
+      if (g_CM == NULL || InColor > 255)
+      {
+        Color->setRgb(0);
+        return;
+      }
+      Color->setRgb(g_CM->RGBColors[InColor]);
+      break;
+    case 15:
+      Color->setRgb(Color15to32(InColor));
+      break;
+    case 16:
+      Color->setRgb(Color16to32(InColor));
+      break;
+    case 24:
+      Color->setRgb(Color24to32(InColor));
+      break;
+    default:
+      Color->setRgb(0);
+  }
+}
+
+//*****************************************************************************
+void SetOpCode(int opcode)
+{
+  if (opcode >= 0 && opcode < 16)
+  {
+    Qt::RasterOp op = g_OpCodes[opcode];
+    if (op != Qt::CopyROP)
+    {
+      g_P1->setRasterOp(op);
+      g_P2->setRasterOp(op);
+    }
+  }
+}
+
+//*****************************************************************************
+void ResetOpCode(int opcode)
+{
+  if (opcode >= 0 && opcode < 16)
+  {
+    Qt::RasterOp op = g_OpCodes[opcode];
+    if (op != Qt::CopyROP)
+    {
+      g_P1->setRasterOp(Qt::CopyROP);
+      g_P2->setRasterOp(Qt::CopyROP);
+    }
+  }
+}
+
+/*****************************************************************************/
+QMyMainWindow::QMyMainWindow(): QWidget()
+{
+}
+
+/*****************************************************************************/
+QMyMainWindow::~QMyMainWindow()
+{
+}
+
+//*****************************************************************************
+void QMyMainWindow::mouseMoveEvent(QMouseEvent * e)
+{
+  if (!g_UpAndRunning)
+  {
+    return;
+  }
+  rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, e->x(), e->y());
+}
+
+//*****************************************************************************
+void QMyMainWindow::mousePressEvent(QMouseEvent * e)
+{
+  if (!g_UpAndRunning)
+  {
+    return;
+  }
+  if (e->button() == LeftButton)
+  {
+    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON1,
+                   e->x(), e->y());
+  }
+  else if (e->button() == RightButton)
+  {
+    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON2,
+                   e->x(), e->y());
+  }
+  else if (e->button() == MidButton)
+  {
+    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_DOWN | MOUSE_FLAG_BUTTON3,
+                   e->x(), e->y());
+  }
+}
+
+//*****************************************************************************
+void QMyMainWindow::mouseReleaseEvent(QMouseEvent * e)
+{
+  if (!g_UpAndRunning)
+  {
+    return;
+  }
+  if (e->button() == LeftButton)
+  {
+    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, e->x(), e->y());
+  }
+  else if (e->button() == RightButton)
+  {
+    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2, e->x(), e->y());
+  }
+  else if (e->button() == MidButton)
+  {
+    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3, e->x(), e->y());
+  }
+}
+
+//*****************************************************************************
+void QMyMainWindow::wheelEvent(QWheelEvent * e)
+{
+  if (!g_UpAndRunning)
+  {
+    return;
+  }
+  if (e->delta() > 0)
+  {
+    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON4, e->x(), e->y());
+  }
+  else if (e->delta() < 0)
+  {
+    rdp_send_input(0, RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON5, e->x(), e->y());
+  }
+}
+
+//*****************************************************************************
+int GetScanCode(QKeyEvent* e)
+{
+  int Key = e->key();
+  int ScanCode = 0;
+  Qt::ButtonState bs = e->state();
+  if (!(bs & Qt::ShiftButton)) // shift is not down
+  {
+    if (Key == 42) // *
+      return 0x37;
+    if (Key == 43) // +
+      return 0x4e;
+  }
+  switch (Key)
+  {
+    case 4100: ScanCode = 0x1c; break; // enter
+    case 4101: ScanCode = 0x1c; break;
+    case 4117: ScanCode = 0xd0; break; // down arrow
+    case 4115: ScanCode = 0xc8; break; // up arrow
+    case 4114: ScanCode = 0xcb; break; // left arrow
+    case 4116: ScanCode = 0xcd; break; // right arrow
+    case 4112: ScanCode = 0xc7; break; // home
+    case 4113: ScanCode = 0xcf; break; // end
+    case 4102: ScanCode = 0xd2; break; // insert
+    case 4103: ScanCode = 0xd3; break; // delete
+    case 4118: ScanCode = 0xc9; break; // page up
+    case 4119: ScanCode = 0xd1; break; // page down
+    case 4143: ScanCode = 0x00; break; // num lock
+    case 47:   ScanCode = 0x35; break; // /
+    case 42:   ScanCode = 0x37; break; // *
+    case 45:   ScanCode = 0x0c; break; // -
+    case 95:   ScanCode = 0x0c; break; // _
+    case 43:   ScanCode = 0x0d; break; // +
+    case 46:   ScanCode = 0x34; break; // .
+    case 48:   ScanCode = 0x0b; break; // 0
+    case 41:   ScanCode = 0x0b; break; // )
+    case 49:   ScanCode = 0x02; break; // 1
+    case 33:   ScanCode = 0x02; break; // !
+    case 50:   ScanCode = 0x03; break; // 2
+    case 64:   ScanCode = 0x03; break; // @
+    case 51:   ScanCode = 0x04; break; // 3
+    case 35:   ScanCode = 0x04; break; // #
+    case 52:   ScanCode = 0x05; break; // 4
+    case 36:   ScanCode = 0x05; break; // $
+    case 53:   ScanCode = 0x06; break; // 5
+    case 37:   ScanCode = 0x06; break; // %
+    case 54:   ScanCode = 0x07; break; // 6
+    case 94:   ScanCode = 0x07; break; // ^
+    case 55:   ScanCode = 0x08; break; // 7
+    case 38:   ScanCode = 0x08; break; // &
+    case 56:   ScanCode = 0x09; break; // 8
+    case 57:   ScanCode = 0x0a; break; // 9
+    case 40:   ScanCode = 0x0a; break; // (
+    case 61:   ScanCode = 0x0d; break; // =
+    case 65:   ScanCode = 0x1e; break; // a
+    case 66:   ScanCode = 0x30; break; // b
+    case 67:   ScanCode = 0x2e; break; // c
+    case 68:   ScanCode = 0x20; break; // d
+    case 69:   ScanCode = 0x12; break; // e
+    case 70:   ScanCode = 0x21; break; // f
+    case 71:   ScanCode = 0x22; break; // g
+    case 72:   ScanCode = 0x23; break; // h
+    case 73:   ScanCode = 0x17; break; // i
+    case 74:   ScanCode = 0x24; break; // j
+    case 75:   ScanCode = 0x25; break; // k
+    case 76:   ScanCode = 0x26; break; // l
+    case 77:   ScanCode = 0x32; break; // m
+    case 78:   ScanCode = 0x31; break; // n
+    case 79:   ScanCode = 0x18; break; // o
+    case 80:   ScanCode = 0x19; break; // p
+    case 81:   ScanCode = 0x10; break; // q
+    case 82:   ScanCode = 0x13; break; // r
+    case 83:   ScanCode = 0x1f; break; // s
+    case 84:   ScanCode = 0x14; break; // t
+    case 85:   ScanCode = 0x16; break; // u
+    case 86:   ScanCode = 0x2f; break; // v
+    case 87:   ScanCode = 0x11; break; // w
+    case 88:   ScanCode = 0x2d; break; // x
+    case 89:   ScanCode = 0x15; break; // y
+    case 90:   ScanCode = 0x2c; break; // z
+    case 32:   ScanCode = 0x39; break; // space
+    case 44:   ScanCode = 0x33; break; // ,
+    case 60:   ScanCode = 0x33; break; // <
+    case 62:   ScanCode = 0x34; break; // >
+    case 63:   ScanCode = 0x35; break; // ?
+    case 92:   ScanCode = 0x2b; break; // backslash
+    case 124:  ScanCode = 0x2b; break; // bar
+    case 4097: ScanCode = 0x0f; break; // tab
+    case 4132: ScanCode = 0x3a; break; // caps lock
+    case 4096: ScanCode = 0x01; break; // esc
+    case 59:   ScanCode = 0x27; break; // ;
+    case 58:   ScanCode = 0x27; break; // :
+    case 39:   ScanCode = 0x28; break; // '
+    case 34:   ScanCode = 0x28; break; // "
+    case 91:   ScanCode = 0x1a; break; // [
+    case 123:  ScanCode = 0x1a; break; // {
+    case 93:   ScanCode = 0x1b; break; // ]
+    case 125:  ScanCode = 0x1b; break; // }
+    case 4144: ScanCode = 0x3b; break; // f1
+    case 4145: ScanCode = 0x3c; break; // f2
+    case 4146: ScanCode = 0x3d; break; // f3
+    case 4147: ScanCode = 0x3e; break; // f4
+    case 4148: ScanCode = 0x3f; break; // f5
+    case 4149: ScanCode = 0x40; break; // f6
+    case 4150: ScanCode = 0x41; break; // f7
+    case 4151: ScanCode = 0x42; break; // f8
+    case 4152: ScanCode = 0x43; break; // f9
+    case 4153: ScanCode = 0x44; break; // f10
+    case 4154: ScanCode = 0x57; break; // f11
+    case 4155: ScanCode = 0x58; break; // f12
+    case 4128: ScanCode = 0x2a; break; // shift
+    case 4131: ScanCode = 0x38; break; // alt
+    case 4129: ScanCode = 0x1d; break; // ctrl
+    case 96:   ScanCode = 0x29; break; // `
+    case 126:  ScanCode = 0x29; break; // ~
+    case 4099: ScanCode = 0x0e; break; // backspace
+  }
+//  if (ScanCode == 0)
+//    printf("key %d scancode %d\n", Key, ScanCode);
+  return ScanCode;
+}
+
+//*****************************************************************************
+void QMyMainWindow::keyPressEvent(QKeyEvent* e)
+{
+  if (!g_UpAndRunning)
+    return;
+  int ScanCode = GetScanCode(e);
+  if (ScanCode != 0)
+  {
+    rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYPRESS, ScanCode, 0);
+    e->accept();
+  }
+}
+
+//*****************************************************************************
+void QMyMainWindow::keyReleaseEvent(QKeyEvent* e)
+{
+  if (!g_UpAndRunning)
+  {
+    return;
+  }
+  int ScanCode = GetScanCode(e);
+  if (ScanCode != 0)
+  {
+    rdp_send_input(0, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, ScanCode, 0);
+    e->accept();
+  }
+}
+
+//*****************************************************************************
+void QMyMainWindow::paintEvent(QPaintEvent * pe)
+{
+  QRect Rect;
+
+  Rect = pe->rect();
+  bitBlt(this, Rect.left(), Rect.top(), g_BS, Rect.left(), Rect.top(),
+         Rect.width(), Rect.height());
+}
+
+//*****************************************************************************
+void QMyMainWindow::closeEvent(QCloseEvent * e)
+{
+  e->accept();
+}
+
+//*****************************************************************************
+bool QMyMainWindow::event(QEvent * e)
+{
+  return QWidget::event(e);
+}
+
+//*****************************************************************************
+void QMyMainWindow::dataReceived()
+{
+  if (!rdp_loop(&g_deactivated, &g_ext_disc_reason))
+  {
+    g_SV->close();
+  }
+#ifdef WITH_RDPSND
+  if (g_dsp_busy)
+  {
+    if (g_SoundNotifier == 0)
+    {
+      g_SoundNotifier = new QSocketNotifier(g_dsp_fd, QSocketNotifier::Write,
+                                            g_MW);
+      g_MW->connect(g_SoundNotifier, SIGNAL(activated(int)), g_MW,
+                    SLOT(soundSend()));
+    }
+    else
+    {
+      if (!g_SoundNotifier->isEnabled())
+      {
+        g_SoundNotifier->setEnabled(true);
+      }
+    }
+  }
+#endif
+}
+
+/******************************************************************************/
+void QMyMainWindow::soundSend()
+{
+#ifdef WITH_RDPSND
+  g_SoundNotifier->setEnabled(false);
+  wave_out_play();
+  if (g_dsp_busy)
+  {
+    g_SoundNotifier->setEnabled(true);
+  }
+#endif
+}
+
+//*****************************************************************************
+void QMyScrollView::keyPressEvent(QKeyEvent * e)
+{
+  g_MW->keyPressEvent(e);
+}
+
+//*****************************************************************************
+void QMyScrollView::keyReleaseEvent(QKeyEvent * e)
+{
+  g_MW->keyReleaseEvent(e);
+}
+
+
+//*****************************************************************************
+void ui_begin_update(void)
+{
+  g_P1->begin(g_MW);
+  g_P2->begin(g_BS);
+}
+
+//*****************************************************************************
+void ui_end_update(void)
+{
+  g_P1->end();
+  g_P2->end();
+}
+
+/*****************************************************************************/
+int ui_init(void)
+{
+  g_App = new QApplication(g_argc, g_argv);
+  return 1;
+}
+
+/*****************************************************************************/
+void ui_deinit(void)
+{
+  delete g_App;
+}
+
+/*****************************************************************************/
+int ui_create_window(void)
+{
+  int w, h;
+  QPainter * painter;
+  QWidget * desktop;
+
+  g_MW = new QMyMainWindow();
+  g_SV = new QMyScrollView();
+  g_SV->addChild(g_MW);
+  g_BS = new QPixmap(g_width, g_height);
+  painter = new QPainter(g_BS);
+  painter->fillRect(0, 0, g_width, g_height, QBrush(QColor("white")));
+  painter->fillRect(0, 0, g_width, g_height, QBrush(QBrush::CrossPattern));
+  delete painter;
+  g_DS = new QPixmap(480, 480);
+  g_P1 = new QPainter();
+  g_P2 = new QPainter();
+  g_ClipRect = new QRegion(0, 0, g_width, g_height);
+  desktop = QApplication::desktop();
+  w = desktop->width();              // returns screen width
+  h = desktop->height();             // returns screen height
+  g_MW->resize(g_width, g_height);
+  if (w < g_width || h < g_height)
+  {
+    g_SV->resize(w, h);
+  }
+  else
+  {
+    g_SV->resize(g_width + 4, g_height + 4);
+  }
+  g_SV->setMaximumWidth(g_width + 4);
+  g_SV->setMaximumHeight(g_height + 4);
+  g_App->setMainWidget(g_SV);
+  g_SV->show();
+  g_MW->setMouseTracking(true);
+  if (g_title[0] != 0)
+  {
+    g_SV->setCaption(g_title);
+  }
+
+/*  XGrayKey(0, 64, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
+  XGrayKey(0, 113, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
+  XGrayKey(0, 37, AnyModifie, SV-winId(), 0, GrabModeAsync, GrabModeAsync);
+  XGrayKey(0, 109, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
+  XGrayKey(0, 115, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
+  XGrayKey(0, 116, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
+  XGrayKey(0, 117, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
+  XGrayKey(0, 62, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);
+  XGrayKey(0, 50, AnyModifie, SV->winId(), 0, GrabModeAsync, GrabModeAsync);*/
+
+  return 1;
+}
+
+//*****************************************************************************
+void ui_main_loop(void)
+{
+#ifdef WITH_RDPSND
+  // init sound
+  if (g_rdpsnd)
+  {
+    rdpsnd_init();
+  }
+#endif
+  // connect
+  if (!rdp_connect(g_servername, g_flags, "", "", "", ""))
+  {
+    return;
+  }
+  // start notifier
+  g_SocketNotifier = new QSocketNotifier(g_sock, QSocketNotifier::Read, g_MW);
+  g_MW->connect(g_SocketNotifier, SIGNAL(activated(int)),
+                g_MW, SLOT(dataReceived()));
+  g_UpAndRunning = 1;
+  // app main loop
+  g_App->exec();
+}
+
+//*****************************************************************************
+void ui_destroy_window(void)
+{
+  delete g_MW;
+  delete g_SV;
+  delete g_BS;
+  delete g_DS;
+  delete g_P1;
+  delete g_P2;
+  delete g_ClipRect;
+}
+
+/*****************************************************************************/
+void ui_bell(void)
+{
+}
+
+/*****************************************************************************/
+int ui_select(int in_val)
+{
+  if (g_sock == 0)
+  {
+    g_sock = in_val;
+  }
+  return 1;
+}
+
+/*****************************************************************************/
+void ui_destroy_cursor(void * cursor)
+{
+  QCursor * Cursor;
+  Cursor = (QCursor*)cursor;
+  if (Cursor != NULL)
+  {
+    delete Cursor;
+  }
+}
+
+/*****************************************************************************/
+void* ui_create_glyph(int width, int height, uint8 * data)
+{
+  QBitmap * Bitmap;
+  Bitmap = new QBitmap(width, height, data);
+  Bitmap->setMask(*Bitmap);
+  return (HGLYPH)Bitmap;
+}
+
+/*****************************************************************************/
+void ui_destroy_glyph(void * glyph)
+{
+  QBitmap* Bitmap;
+  Bitmap = (QBitmap*)glyph;
+  delete Bitmap;
+}
+
+/*****************************************************************************/
+void ui_destroy_bitmap(void * bmp)
+{
+  QPixmap * Pixmap;
+  Pixmap = (QPixmap*)bmp;
+  delete Pixmap;
+}
+
+/*****************************************************************************/
+void ui_reset_clip(void)
+{
+  g_P1->setClipRect(0, 0, g_width, g_height);
+  g_P2->setClipRect(0, 0, g_width, g_height);
+  delete g_ClipRect;
+  g_ClipRect = new QRegion(0, 0, g_width, g_height);
+}
+
+/*****************************************************************************/
+void ui_set_clip(int x, int y, int cx, int cy)
+{
+  g_P1->setClipRect(x, y, cx, cy);
+  g_P2->setClipRect(x, y, cx, cy);
+  delete g_ClipRect;
+  g_ClipRect = new QRegion(x, y, cx, cy);
+}
+
+/*****************************************************************************/
+void * ui_create_colourmap(COLOURMAP * colours)
+{
+  QColorMap* LCM;
+  int i, r, g, b;
+  LCM = (QColorMap*)malloc(sizeof(QColorMap));
+  memset(LCM, 0, sizeof(QColorMap));
+  i = 0;
+  while (i < colours->ncolours && i < 256)
+  {
+    r = colours->colours[i].red;
+    g = colours->colours[i].green;
+    b = colours->colours[i].blue;
+    LCM->RGBColors[i] = (r << 16) | (g << 8) | b;
+    i++;
+  }
+  LCM->NumColors = colours->ncolours;
+  return LCM;
+}
+
+//*****************************************************************************
+// todo, does this leak at end of program
+void ui_destroy_colourmap(HCOLOURMAP map)
+{
+  QColorMap * LCM;
+  LCM = (QColorMap*)map;
+  if (LCM == NULL)
+    return;
+  free(LCM);
+}
+
+/*****************************************************************************/
+void ui_set_colourmap(void * map)
+{
+  // destoy old colormap
+  ui_destroy_colourmap(g_CM);
+  g_CM = (QColorMap*)map;
+}
+
+/*****************************************************************************/
+HBITMAP ui_create_bitmap(int width, int height, uint8 * data)
+{
+  QImage * Image = NULL;
+  QPixmap * Pixmap;
+  uint32 * d = NULL;
+  uint16 * s;
+  int i;
+
+  switch (g_server_depth)
+  {
+    case 8:
+      Image = new QImage(data, width, height, 8, (QRgb*)&g_CM->RGBColors,
+                         g_CM->NumColors, QImage::IgnoreEndian);
+      break;
+    case 15:
+      d = (uint32*)malloc(width * height * 4);
+      s = (uint16*)data;
+      for (i = 0; i < width * height; i++)
+      {
+        d[i] = Color15to32(s[i]);
+      }
+      Image = new QImage((uint8*)d, width, height, 32, NULL,
+                         0, QImage::IgnoreEndian);
+      break;
+    case 16:
+      d = (uint32*)malloc(width * height * 4);
+      s = (uint16*)data;
+      for (i = 0; i < width * height; i++)
+      {
+        d[i] = Color16to32(s[i]);
+      }
+      Image = new QImage((uint8*)d, width, height, 32, NULL,
+                         0, QImage::IgnoreEndian);
+      break;
+    case 24:
+      d = (uint32*)malloc(width * height * 4);
+      memset(d, 0, width * height * 4);
+      for (i = 0; i < width * height; i++)
+      {
+        memcpy(d + i, data + i * 3, 3);
+      }
+      Image = new QImage((uint8*)d, width, height, 32, NULL,
+                         0, QImage::IgnoreEndian);
+      break;
+  }
+  if (Image == NULL)
+  {
+    return NULL;
+  }
+  Pixmap = new QPixmap();
+  Pixmap->convertFromImage(*Image);
+  delete Image;
+  if (d != NULL)
+  {
+    free(d);
+  }
+  return (HBITMAP)Pixmap;
+}
+
+//******************************************************************************
+// adjust coordinates for cliping rect
+int WarpCoords(int * x, int * y, int * cx, int * cy, int * srcx, int * srcy)
+{
+  int dx, dy;
+  QRect InRect(*x, *y, *cx, *cy);
+  QRect OutRect;
+  QRect CRect = g_ClipRect->boundingRect();
+  OutRect = InRect.intersect(CRect);
+  if (OutRect.isEmpty())
+  {
+    return False;
+  }
+  dx = OutRect.x() - InRect.x();
+  dy = OutRect.y() - InRect.y();
+  *x = OutRect.x();
+  *y = OutRect.y();
+  *cx = OutRect.width();
+  *cy = OutRect.height();
+  *srcx = *srcx + dx;
+  *srcy = *srcy + dy;
+  return True;
+}
+
+//******************************************************************************
+// needed because bitBlt don't seem to care about clipping rects
+// also has 2 dsts and src can be null
+void bitBltClip(QPaintDevice * dst1, QPaintDevice * dst2, int dx, int dy,
+                QPaintDevice * src, int sx, int sy, int sw, int sh,
+                Qt::RasterOp rop, bool im)
+{
+  if (WarpCoords(&dx, &dy, &sw, &sh, &sx, &sy))
+  {
+    if (dst1 != NULL)
+    {
+      if (src == NULL)
+      {
+        bitBlt(dst1, dx, dy, dst1, sx, sy, sw, sh, rop, im);
+      }
+      else
+      {
+        bitBlt(dst1, dx, dy, src, sx, sy, sw, sh, rop, im);
+      }
+    }
+    if (dst2 != NULL)
+    {
+      if (src == NULL)
+      {
+        bitBlt(dst2, dx, dy, dst2, sx, sy, sw, sh, rop, im);
+      }
+      else
+      {
+        bitBlt(dst2, dx, dy, src, sx, sy, sw, sh, rop, im);
+      }
+    }
+  }
+}
+
+#define DO_GLYPH(ttext,idx) \
+{ \
+  glyph = cache_get_font (font, ttext[idx]); \
+  if (!(flags & TEXT2_IMPLICIT_X)) \
+  { \
+    xyoffset = ttext[++idx]; \
+    if ((xyoffset & 0x80)) \
+    { \
+      if (flags & TEXT2_VERTICAL) \
+        y += ttext[idx+1] | (ttext[idx+2] << 8); \
+      else \
+        x += ttext[idx+1] | (ttext[idx+2] << 8); \
+      idx += 2; \
+    } \
+    else \
+    { \
+      if (flags & TEXT2_VERTICAL) \
+        y += xyoffset; \
+      else \
+        x += xyoffset; \
+    } \
+  } \
+  if (glyph != NULL) \
+  { \
+    g_P2->drawPixmap(x + glyph->offset, y + glyph->baseline, \
+                     *((QBitmap*)glyph->pixmap)); \
+    if (flags & TEXT2_IMPLICIT_X) \
+      x += glyph->width; \
+  } \
+}
+
+//*****************************************************************************
+void 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)
+{
+  FONTGLYPH * glyph;
+  int i, j, xyoffset;
+  DATABLOB * entry;
+
+  SetColorx(&g_Color1, fgcolour);
+  SetColorx(&g_Color2, bgcolour);
+  g_P2->setBackgroundColor(g_Color2);
+  g_P2->setPen(g_Color1);
+  if (boxcx > 1)
+  {
+    g_P2->fillRect(boxx, boxy, boxcx, boxcy, QBrush(g_Color2));
+  }
+  else if (mixmode == MIX_OPAQUE)
+  {
+    g_P2->fillRect(clipx, clipy, clipcx, clipcy, QBrush(g_Color2));
+  }
+
+  /* Paint text, character by character */
+  for (i = 0; i < length;)
+  {
+    switch (text[i])
+    {
+      case 0xff:
+        if (i + 2 < length)
+        {
+          cache_put_text(text[i + 1], text, text[i + 2]);
+        }
+        else
+        {
+          error("this shouldn't be happening\n");
+          exit(1);
+        }
+        /* this will move pointer from start to first character after FF
+           command */
+        length -= i + 3;
+        text = &(text[i + 3]);
+        i = 0;
+        break;
+
+      case 0xfe:
+        entry = cache_get_text(text[i + 1]);
+        if (entry != NULL)
+        {
+          if ((((uint8 *) (entry->data))[1] == 0) &&
+                             (!(flags & TEXT2_IMPLICIT_X)))
+          {
+            if (flags & TEXT2_VERTICAL)
+            {
+              y += text[i + 2];
+            }
+            else
+            {
+              x += text[i + 2];
+            }
+          }
+          for (j = 0; j < entry->size; j++)
+          {
+            DO_GLYPH(((uint8 *) (entry->data)), j);
+          }
+        }
+        if (i + 2 < length)
+        {
+          i += 3;
+        }
+        else
+        {
+          i += 2;
+        }
+        length -= i;
+        /* this will move pointer from start to first character after FE
+           command */
+        text = &(text[i]);
+        i = 0;
+        break;
+
+      default:
+        DO_GLYPH(text, i);
+        i++;
+        break;
+    }
+  }
+  if (boxcx > 1)
+  {
+    bitBltClip(g_MW, NULL, boxx, boxy, g_BS, boxx, boxy, boxcx, boxcy,
+               Qt::CopyROP, true);
+  }
+  else
+  {
+    bitBltClip(g_MW, NULL, clipx, clipy, g_BS, clipx, clipy, clipcx,
+               clipcy, Qt::CopyROP, true);
+  }
+}
+
+/*****************************************************************************/
+void ui_line(uint8 opcode, int startx, int starty, int endx, int endy,
+             PEN * pen)
+{
+  SetColorx(&g_Color1, pen->colour);
+  SetOpCode(opcode);
+  g_P1->setPen(g_Color1);
+  g_P1->moveTo(startx, starty);
+  g_P1->lineTo(endx, endy);
+  g_P2->setPen(g_Color1);
+  g_P2->moveTo(startx, starty);
+  g_P2->lineTo(endx, endy);
+  ResetOpCode(opcode);
+}
+
+/*****************************************************************************/
+// not used
+void ui_triblt(uint8 opcode, int x, int y, int cx, int cy,
+               HBITMAP src, int srcx, int srcy,
+               BRUSH* brush, int bgcolour, int fgcolour)
+{
+}
+
+/*****************************************************************************/
+void ui_memblt(uint8 opcode, int x, int y, int cx, int cy,
+               HBITMAP src, int srcx, int srcy)
+{
+  QPixmap* Pixmap;
+  Pixmap = (QPixmap*)src;
+  if (Pixmap != NULL)
+  {
+    SetOpCode(opcode);
+    g_P1->drawPixmap(x, y, *Pixmap, srcx, srcy, cx, cy);
+    g_P2->drawPixmap(x, y, *Pixmap, srcx, srcy, cx, cy);
+    ResetOpCode(opcode);
+  }
+}
+
+//******************************************************************************
+void CommonDeskSave(QPixmap* Pixmap1, QPixmap* Pixmap2, int Offset, int x,
+                    int y, int cx, int cy, int dir)
+{
+  int lx;
+  int ly;
+  int x1;
+  int y1;
+  int width;
+  int lcx;
+  int right;
+  int bottom;
+  lx = Offset % 480;
+  ly = Offset / 480;
+  y1 = y;
+  right = x + cx;
+  bottom = y + cy;
+  while (y1 < bottom)
+  {
+    x1 = x;
+    lcx = cx;
+    while (x1 < right)
+    {
+      width = 480 - lx;
+      if (width > lcx)
+        width = lcx;
+      if (dir == 0)
+        bitBlt(Pixmap1, lx, ly, Pixmap2, x1, y1, width, 1, Qt::CopyROP, true);
+      else
+        bitBlt(Pixmap2, x1, y1, Pixmap1, lx, ly, width, 1, Qt::CopyROP, true);
+      lx = lx + width;
+      if (lx >= 480)
+      {
+        lx = 0;
+        ly++;
+        if (ly >= 480)
+          ly = 0;
+      }
+      lcx = lcx - width;
+      x1 = x1 + width;
+    }
+    y1++;
+  }
+}
+
+/*****************************************************************************/
+void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy)
+{
+  QPixmap * Pixmap;
+
+  Pixmap = new QPixmap(cx, cy);
+  CommonDeskSave(g_DS, Pixmap, offset, 0, 0, cx, cy, 1);
+  bitBltClip(g_MW, g_BS, x, y, Pixmap, 0, 0, cx, cy, Qt::CopyROP, true);
+  delete Pixmap;
+}
+
+/*****************************************************************************/
+void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy)
+{
+  CommonDeskSave(g_DS, g_BS, offset, x, y, cx, cy, 0);
+}
+
+/*****************************************************************************/
+void ui_rect(int x, int y, int cx, int cy, int colour)
+{
+  SetColorx(&g_Color1, colour);
+  g_P1->fillRect(x, y, cx, cy, QBrush(g_Color1));
+  g_P2->fillRect(x, y, cx, cy, QBrush(g_Color1));
+}
+
+/*****************************************************************************/
+void ui_screenblt(uint8 opcode, int x, int y, int cx, int cy,
+                  int srcx, int srcy)
+{
+  SetOpCode(opcode);
+  bitBltClip(g_MW, g_BS, x, y, NULL, srcx, srcy, cx, cy, Qt::CopyROP, true);
+  ResetOpCode(opcode);
+}
+
+/*****************************************************************************/
+void ui_patblt(uint8 opcode, int x, int y, int cx, int cy,
+               BRUSH* brush, int bgcolour, int fgcolour)
+{
+  QBitmap* Bitmap;
+  QBrush* Brush;
+  uint8 ipattern[8], i;
+  SetOpCode(opcode);
+  switch (brush->style)
+  {
+    case 0:
+      SetColorx(&g_Color1, fgcolour);
+      g_P2->fillRect(x, y, cx, cy, QBrush(g_Color1));
+      break;
+    case 3:
+      SetColorx(&g_Color1, fgcolour);
+      SetColorx(&g_Color2, bgcolour);
+      for (i = 0; i != 8; i++)
+      {
+        ipattern[7 - i] = ~brush->pattern[i];
+      }
+      Bitmap = new QBitmap(8, 8, ipattern);
+      Brush = new QBrush(g_Color1, *Bitmap);
+      g_P2->setBackgroundMode(Qt::OpaqueMode);
+      g_P2->setBrushOrigin(brush->xorigin, brush->yorigin);
+      g_P2->setBackgroundColor(g_Color2);
+      g_P2->fillRect(x, y, cx, cy, *Brush);
+      delete Brush;
+      delete Bitmap;
+      g_P2->setBackgroundMode(Qt::TransparentMode);
+      g_P2->setBrushOrigin(0, 0);
+      break;
+  }
+  ResetOpCode(opcode);
+  bitBltClip(g_MW, NULL, x, y, g_BS, x, y, cx, cy, Qt::CopyROP, true);
+}
+
+/*****************************************************************************/
+void ui_destblt(uint8 opcode, int x, int y, int cx, int cy)
+{
+  SetOpCode(opcode);
+  g_P1->fillRect(x, y, cx, cy, QBrush(QColor("black")));
+  g_P2->fillRect(x, y, cx, cy, QBrush(QColor("black")));
+  ResetOpCode(opcode);
+}
+
+/*****************************************************************************/
+void ui_move_pointer(int x, int y)
+{
+}
+
+/*****************************************************************************/
+void ui_set_null_cursor(void)
+{
+  g_MW->setCursor(10); // Qt::BlankCursor
+}
+
+/*****************************************************************************/
+void ui_paint_bitmap(int x, int y, int cx, int cy,
+                     int width, int height, uint8* data)
+{
+  QImage * Image = NULL;
+  QPixmap * Pixmap;
+  uint32 * d = NULL;
+  uint16 * s;
+  int i;
+
+  switch (g_server_depth)
+  {
+    case 8:
+      Image = new QImage(data, width, height, 8, (QRgb*)&g_CM->RGBColors,
+                         g_CM->NumColors, QImage::IgnoreEndian);
+      break;
+    case 15:
+      d = (uint32*)malloc(width * height * 4);
+      s = (uint16*)data;
+      for (i = 0; i < width * height; i++)
+      {
+        d[i] = Color15to32(s[i]);
+      }
+      Image = new QImage((uint8*)d, width, height, 32, NULL,
+                         0, QImage::IgnoreEndian);
+      break;
+    case 16:
+      d = (uint32*)malloc(width * height * 4);
+      s = (uint16*)data;
+      for (i = 0; i < width * height; i++)
+      {
+        d[i] = Color16to32(s[i]);
+      }
+      Image = new QImage((uint8*)d, width, height, 32, NULL,
+                         0, QImage::IgnoreEndian);
+      break;
+    case 24:
+      d = (uint32*)malloc(width * height * 4);
+      memset(d, 0, width * height * 4);
+      for (i = 0; i < width * height; i++)
+      {
+        memcpy(d + i, data + i * 3, 3);
+      }
+      Image = new QImage((uint8*)d, width, height, 32, NULL,
+                         0, QImage::IgnoreEndian);
+      break;
+  }
+  if (Image == NULL)
+  {
+    return;
+  }
+  Pixmap = new QPixmap();
+  Pixmap->convertFromImage(*Image);
+  g_P1->drawPixmap(x, y, *Pixmap, 0, 0, cx, cy);
+  g_P2->drawPixmap(x, y, *Pixmap, 0, 0, cx, cy);
+  delete Image;
+  delete Pixmap;
+  if (d != NULL)
+  {
+    free(d);
+  }
+}
+
+//******************************************************************************
+int Is24On(uint8* Data, int X, int Y)
+{
+  uint8 R, G, B;
+  int Start;
+  Start = Y * 32 * 3 + X * 3;
+  R = Data[Start];
+  G = Data[Start + 1];
+  B = Data[Start + 2];
+  return !((R == 0) && (G == 0) && (B == 0));
+}
+
+//******************************************************************************
+int Is1On(uint8* Data, int X, int Y)
+{
+  int Start;
+  int Shift;
+  Start = (Y * 32) / 8 + X / 8;
+  Shift = X % 8;
+  return (Data[Start] & (0x80 >> Shift)) == 0;
+}
+
+//******************************************************************************
+void Set1(uint8* Data, int X, int Y)
+{
+  int Start;
+  int Shift;
+  Start = (Y * 32) / 8 + X / 8;
+  Shift = X % 8;
+  Data[Start] = Data[Start] | (0x80 >> Shift);
+}
+
+//******************************************************************************
+void FlipOver(uint8* Data)
+{
+  uint8 AData[128];
+  int Index;
+  memcpy(AData, Data, 128);
+  for (Index = 0; Index <= 31; Index++)
+  {
+    Data[127 - (Index * 4 + 3)] = AData[Index * 4];
+    Data[127 - (Index * 4 + 2)] = AData[Index * 4 + 1];
+    Data[127 - (Index * 4 + 1)] = AData[Index * 4 + 2];
+    Data[127 - Index * 4] = AData[Index * 4 + 3];
+  }
+}
+
+/*****************************************************************************/
+void ui_set_cursor(HCURSOR cursor)
+{
+  QCursor* Cursor;
+  Cursor = (QCursor*)cursor;
+  if (Cursor != NULL)
+    g_MW->setCursor(*Cursor);
+}
+
+/*****************************************************************************/
+HCURSOR ui_create_cursor(unsigned int x, unsigned int y,
+                         int width, int height,
+                         uint8* andmask, uint8* xormask)
+{
+  uint8 AData[128];
+  uint8 AMask[128];
+  QBitmap* DataBitmap;
+  QBitmap* MaskBitmap;
+  QCursor* Cursor;
+  int I1, I2, BOn, MOn;
+
+  if (width != 32 || height != 32)
+  {
+    return 0;
+  }
+  memset(AData, 0, 128);
+  memset(AMask, 0, 128);
+  for (I1 = 0; I1 <= 31; I1++)
+  {
+    for (I2 = 0; I2 <= 31; I2++)
+    {
+      MOn = Is24On(xormask, I1, I2);
+      BOn = Is1On(andmask, I1, I2);
+      if (BOn ^ MOn) // xor
+      {
+        Set1(AData, I1, I2);
+        if (!MOn)
+        {
+          Set1(AMask, I1, I2);
+        }
+      }
+      if (MOn)
+      {
+        Set1(AMask, I1, I2);
+      }
+    }
+  }
+  FlipOver(AData);
+  FlipOver(AMask);
+  DataBitmap = new QBitmap(32, 32, AData);
+  MaskBitmap = new QBitmap(32, 32, AMask);
+  Cursor = new QCursor(*DataBitmap, *MaskBitmap, x, y);
+  delete DataBitmap;
+  delete MaskBitmap;
+  return Cursor;
+}
+
+/*****************************************************************************/
+uint16 ui_get_numlock_state(uint32 state)
+{
+  return 0;
+}
+
+/*****************************************************************************/
+uint32 read_keyboard_state(void)
+{
+  return 0;
+}
+
+/*****************************************************************************/
+void ui_resize_window(void)
+{
+}
+
+/*****************************************************************************/
+void ui_polygon(uint8 opcode, uint8 fillmode, POINT * point, int npoints,
+                BRUSH * brush, int bgcolour, int fgcolour)
+{
+}
+
+/*****************************************************************************/
+/* todo, use qt function for this (QPainter::drawPolyline) */
+void ui_polyline(uint8 opcode, POINT * points, int npoints, PEN * pen)
+{
+  int i, x, y, dx, dy;
+
+  if (npoints > 0)
+  {
+    x = points[0].x;
+    y = points[0].y;
+    for (i = 1; i < npoints; i++)
+    {
+      dx = points[i].x;
+      dy = points[i].y;
+      ui_line(opcode, x, y, x + dx, y + dy, pen);
+      x = x + dx;
+      y = y + dy;
+    }
+  }
+}
+
+/*****************************************************************************/
+void ui_ellipse(uint8 opcode, uint8 fillmode,
+                int x, int y, int cx, int cy,
+                BRUSH * brush, int bgcolour, int fgcolour)
+{
+}
+
+/*****************************************************************************/
+void generate_random(uint8 * random)
+{
+  QFile File("/dev/random");
+  File.open(IO_ReadOnly);
+  if (File.readBlock((char*)random, 32) == 32)
+  {
+    return;
+  }
+  warning("no /dev/random\n");
+  memcpy(random, "12345678901234567890123456789012", 32);
+}
+
+/*****************************************************************************/
+void save_licence(uint8 * data, int length)
+{
+  char * home, * path, * tmppath;
+  int fd;
+
+  home = getenv("HOME");
+  if (home == NULL)
+  {
+    return;
+  }
+  path = (char *) xmalloc(strlen(home) + strlen(g_hostname) +
+                          sizeof("/.rdesktop/licence."));
+  sprintf(path, "%s/.rdesktop", home);
+  if ((mkdir(path, 0700) == -1) && errno != EEXIST)
+  {
+    perror(path);
+    return;
+  }
+  /* write licence to licence.hostname.new, then atomically rename to
+     licence.hostname */
+  sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
+  tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
+  strcpy(tmppath, path);
+  strcat(tmppath, ".new");
+  fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+  if (fd == -1)
+  {
+    perror(tmppath);
+    return;
+  }
+  if (write(fd, data, length) != length)
+  {
+    perror(tmppath);
+    unlink(tmppath);
+  }
+  else if (rename(tmppath, path) == -1)
+  {
+    perror(path);
+    unlink(tmppath);
+  }
+  close(fd);
+  xfree(tmppath);
+  xfree(path);
+}
+
+/*****************************************************************************/
+int load_licence(uint8 ** data)
+{
+  char * home, * path;
+  struct stat st;
+  int fd, length;
+
+  home = getenv("HOME");
+  if (home == NULL)
+  {
+    return -1;
+  }
+  path = (char *) xmalloc(strlen(home) + strlen(g_hostname) +
+                          sizeof("/.rdesktop/licence."));
+  sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
+  fd = open(path, O_RDONLY);
+  if (fd == -1)
+  {
+    return -1;
+  }
+  if (fstat(fd, &st))
+  {
+    return -1;
+  }
+  *data = (uint8 *) xmalloc(st.st_size);
+  length = read(fd, *data, st.st_size);
+  close(fd);
+  xfree(path);
+  return length;
+}
+
+/*****************************************************************************/
+void* xrealloc(void * in_val, int size)
+{
+  return realloc(in_val, size);
+}
+
+/*****************************************************************************/
+void* xmalloc(int size)
+{
+  return malloc(size);
+}
+
+/*****************************************************************************/
+void xfree(void * in_val)
+{
+  if (in_val != NULL)
+  {
+    free(in_val);
+  }
+}
+
+/*****************************************************************************/
+char * xstrdup(const char * s)
+{
+  char * mem = strdup(s);
+  if (mem == NULL)
+  {
+    perror("strdup");
+    exit(1);
+  }
+  return mem;
+}
+
+/*****************************************************************************/
+void warning(char * format, ...)
+{
+  va_list ap;
+
+  fprintf(stderr, "WARNING: ");
+  va_start(ap, format);
+  vfprintf(stderr, format, ap);
+  va_end(ap);
+}
+
+/*****************************************************************************/
+void unimpl(char * format, ...)
+{
+  va_list ap;
+
+  fprintf(stderr, "NOT IMPLEMENTED: ");
+  va_start(ap, format);
+  vfprintf(stderr, format, ap);
+  va_end(ap);
+}
+
+/*****************************************************************************/
+void error(char * format, ...)
+{
+  va_list ap;
+
+  fprintf(stderr, "ERROR: ");
+  va_start(ap, format);
+  vfprintf(stderr, format, ap);
+  va_end(ap);
+}
+
+/*****************************************************************************/
+void out_params(void)
+{
+  fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
+  fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
+  fprintf(stderr, "QT uiport by Jay Sorg\n");
+  fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
+  fprintf(stderr, "Usage: qtrdesktop [options] server\n");
+  fprintf(stderr, "   -g WxH: desktop geometry\n");
+  fprintf(stderr, "   -4: use RDP version 4\n");
+  fprintf(stderr, "   -5: use RDP version 5 (default)\n");
+  fprintf(stderr, "   -t 3389: tcp port)\n");
+  fprintf(stderr, "   -a 8|16|24: connection colour depth\n");
+  fprintf(stderr, "   -T title: window title\n");
+  fprintf(stderr, "   -P: use persistent bitmap caching\n");
+  fprintf(stderr, "   -0: attach to console\n");
+  fprintf(stderr, "   -z: enable rdp compression\n");
+  fprintf(stderr, "   -r sound: enable sound\n");
+  fprintf(stderr, "\n");
+}
+
+/*****************************************************************************/
+/* produce a hex dump */
+void hexdump(uint8 * p, uint32 len)
+{
+  uint8 * line = p;
+  int i, thisline;
+  uint32 offset = 0;
+
+  while (offset < len)
+  {
+    printf("%04x ", offset);
+    thisline = len - offset;
+    if (thisline > 16)
+    {
+      thisline = 16;
+    }
+    for (i = 0; i < thisline; i++)
+    {
+      printf("%02x ", line[i]);
+    }
+    for (; i < 16; i++)
+    {
+      printf("   ");
+    }
+    for (i = 0; i < thisline; i++)
+    {
+      printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
+    }
+    printf("\n");
+    offset += thisline;
+    line += thisline;
+  }
+}
+
+/*****************************************************************************/
+int rd_pstcache_mkdir(void)
+{
+  char * home;
+  char bmpcache_dir[256];
+
+  home = getenv("HOME");
+  if (home == NULL)
+  {
+    return False;
+  }
+  sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
+  if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
+  {
+    perror(bmpcache_dir);
+    return False;
+  }
+  sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
+  if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
+  {
+    perror(bmpcache_dir);
+    return False;
+  }
+  return True;
+}
+
+/*****************************************************************************/
+int rd_open_file(char * filename)
+{
+  char * home;
+  char fn[256];
+  int fd;
+
+  home = getenv("HOME");
+  if (home == NULL)
+  {
+    return -1;
+  }
+  sprintf(fn, "%s/.rdesktop/%s", home, filename);
+  fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+  if (fd == -1)
+  {
+    perror(fn);
+  }
+  return fd;
+}
+
+/*****************************************************************************/
+void rd_close_file(int fd)
+{
+  close(fd);
+}
+
+/*****************************************************************************/
+int rd_read_file(int fd, void * ptr, int len)
+{
+  return read(fd, ptr, len);
+}
+
+/*****************************************************************************/
+int rd_write_file(int fd, void * ptr, int len)
+{
+  return write(fd, ptr, len);
+}
+
+/*****************************************************************************/
+int rd_lseek_file(int fd, int offset)
+{
+  return lseek(fd, offset, SEEK_SET);
+}
+
+/*****************************************************************************/
+int rd_lock_file(int fd, int start, int len)
+{
+  struct flock lock;
+
+  lock.l_type = F_WRLCK;
+  lock.l_whence = SEEK_SET;
+  lock.l_start = start;
+  lock.l_len = len;
+  if (fcntl(fd, F_SETLK, &lock) == -1)
+  {
+    return False;
+  }
+  return True;
+}
+
+/*****************************************************************************/
+void get_username_and_hostname(void)
+{
+  char fullhostname[64];
+  char * p;
+  struct passwd * pw;
+
+  STRNCPY(g_username, "unknown", sizeof(g_username));
+  STRNCPY(g_hostname, "unknown", sizeof(g_hostname));
+  pw = getpwuid(getuid());
+  if (pw != NULL && pw->pw_name != NULL)
+  {
+    STRNCPY(g_username, pw->pw_name, sizeof(g_username));
+  }
+  if (gethostname(fullhostname, sizeof(fullhostname)) != -1)
+  {
+    p = strchr(fullhostname, '.');
+    if (p != NULL)
+    {
+      *p = 0;
+    }
+    STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
+  }
+}
+
+/*****************************************************************************/
+int parse_parameters(int in_argc, char ** in_argv)
+{
+  int i;
+  char * p;
+
+  if (in_argc <= 1)
+  {
+    out_params();
+    return 0;
+  }
+  g_argc = in_argc;
+  g_argv = in_argv;
+  for (i = 1; i < in_argc; i++)
+  {
+    strcpy(g_servername, in_argv[i]);
+    if (strcmp(in_argv[i], "-g") == 0)
+    {
+      g_width = strtol(in_argv[i + 1], &p, 10);
+      if (g_width <= 0)
+      {
+        error("invalid geometry\n");
+        return 0;
+      }
+      if (*p == 'x')
+      {
+        g_height = strtol(p + 1, NULL, 10);
+      }
+      if (g_height <= 0)
+      {
+        error("invalid geometry\n");
+        return 0;
+      }
+      g_width = (g_width + 3) & ~3;
+    }
+    else if (strcmp(in_argv[i], "-T") == 0)
+    {
+      strcpy(g_title, in_argv[i + 1]);
+    }
+    else if (strcmp(in_argv[i], "-4") == 0)
+    {
+      g_use_rdp5 = 0;
+    }
+    else if (strcmp(in_argv[i], "-5") == 0)
+    {
+      g_use_rdp5 = 1;
+    }
+    else if (strcmp(in_argv[i], "-a") == 0)
+    {
+      g_server_depth = strtol(in_argv[i + 1], &p, 10);
+      if (g_server_depth != 8 && g_server_depth != 15 &&
+          g_server_depth != 16 && g_server_depth != 24)
+      {
+        error("invalid bpp\n");
+        return 0;
+      }
+    }
+    else if (strcmp(in_argv[i], "-t") == 0)
+    {
+      g_tcp_port_rdp = strtol(in_argv[i + 1], &p, 10);
+    }
+    else if (strcmp(in_argv[i], "-P") == 0)
+    {
+      g_bitmap_cache_persist_enable = 1;
+    }
+    else if (strcmp(in_argv[i], "-0") == 0)
+    {
+      g_console_session = 1;
+    }
+    else if (strcmp(in_argv[i], "-z") == 0)
+    {
+      g_flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);
+    }
+    else if (strcmp(in_argv[i], "-r") == 0)
+    {
+      if (strcmp(in_argv[i + 1], "sound") == 0)
+      {
+#ifdef WITH_RDPSND
+        g_rdpsnd = 1;
+#endif
+      }
+    }
+  }
+  return 1;
+}
+
+/*****************************************************************************/
+int main(int in_argc, char** in_argv)
+{
+  get_username_and_hostname();
+  if (!parse_parameters(in_argc, in_argv))
+  {
+    return 0;
+  }
+  if (!ui_init())
+  {
+    return 1;
+  }
+  if (!ui_create_window())
+  {
+    return 1;
+  }
+  ui_main_loop();
+  ui_destroy_window();
+  ui_deinit();
+  return 0;
+}