-/* -*- 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;
+}