summaryrefslogtreecommitdiffstats
path: root/xorg/X11R7.6/rdp/rdpup.c
diff options
context:
space:
mode:
authorJay Sorg <jay.sorg@gmail.com>2012-03-06 11:49:15 -0800
committerJay Sorg <jay.sorg@gmail.com>2012-03-06 11:49:15 -0800
commit5b40f518c187e172658e91c42eef713312485a79 (patch)
tree99be90312087a2140e7fc593d7a9ac0cdd1ace65 /xorg/X11R7.6/rdp/rdpup.c
parent823238cb75d1ca4c00c32a42b4d7915597c4fecd (diff)
downloadxrdp-proprietary-5b40f518c187e172658e91c42eef713312485a79.tar.gz
xrdp-proprietary-5b40f518c187e172658e91c42eef713312485a79.zip
xorg: add rdp X1 source
Diffstat (limited to 'xorg/X11R7.6/rdp/rdpup.c')
-rw-r--r--xorg/X11R7.6/rdp/rdpup.c1078
1 files changed, 1078 insertions, 0 deletions
diff --git a/xorg/X11R7.6/rdp/rdpup.c b/xorg/X11R7.6/rdp/rdpup.c
new file mode 100644
index 00000000..9124f88e
--- /dev/null
+++ b/xorg/X11R7.6/rdp/rdpup.c
@@ -0,0 +1,1078 @@
+/*
+Copyright 2005-2012 Jay Sorg
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include "rdp.h"
+
+#if 1
+#define DEBUG_OUT_UP(arg)
+#else
+#define DEBUG_OUT_UP(arg) ErrorF arg
+#endif
+
+static int g_listen_sck = 0;
+static int g_sck = 0;
+static int g_sck_closed = 0;
+static int g_connected = 0;
+
+static int g_dis_listen_sck = 0;
+static int g_dis_sck = 0;
+static int g_dis_sck_closed = 0;
+static int g_dis_connected = 0;
+
+static int g_begin = 0;
+static struct stream* g_out_s = 0;
+static struct stream* g_in_s = 0;
+static int g_button_mask = 0;
+static int g_cursor_x = 0;
+static int g_cursor_y = 0;
+static OsTimerPtr g_timer = 0;
+static int g_scheduled = 0;
+static int g_count = 0;
+extern ScreenPtr g_pScreen; /* from rdpmain.c */
+extern int g_Bpp; /* from rdpmain.c */
+extern int g_Bpp_mask; /* from rdpmain.c */
+extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */
+
+/*
+0 GXclear, 0
+1 GXnor, DPon
+2 GXandInverted, DPna
+3 GXcopyInverted, Pn
+4 GXandReverse, PDna
+5 GXinvert, Dn
+6 GXxor, DPx
+7 GXnand, DPan
+8 GXand, DPa
+9 GXequiv, DPxn
+a GXnoop, D
+b GXorInverted, DPno
+c GXcopy, P
+d GXorReverse, PDno
+e GXor, DPo
+f GXset 1
+*/
+
+static int g_rdp_opcodes[16] =
+{
+ 0x00, /* GXclear 0x0 0 */
+ 0x88, /* GXand 0x1 src AND dst */
+ 0x44, /* GXandReverse 0x2 src AND NOT dst */
+ 0xcc, /* GXcopy 0x3 src */
+ 0x22, /* GXandInverted 0x4 NOT src AND dst */
+ 0xaa, /* GXnoop 0x5 dst */
+ 0x66, /* GXxor 0x6 src XOR dst */
+ 0xee, /* GXor 0x7 src OR dst */
+ 0x11, /* GXnor 0x8 NOT src AND NOT dst */
+ 0x99, /* GXequiv 0x9 NOT src XOR dst */
+ 0x55, /* GXinvert 0xa NOT dst */
+ 0xdd, /* GXorReverse 0xb src OR NOT dst */
+ 0x33, /* GXcopyInverted 0xc NOT src */
+ 0xbb, /* GXorInverted 0xd NOT src OR dst */
+ 0x77, /* GXnand 0xe NOT src OR NOT dst */
+ 0xff /* GXset 0xf 1 */
+};
+
+/*****************************************************************************/
+/* returns error */
+static int
+rdpup_send(char* data, int len)
+{
+ int sent;
+
+ DEBUG_OUT_UP(("rdpup_send - sending %d bytes\n", len));
+ if (g_sck_closed)
+ {
+ return 1;
+ }
+ while (len > 0)
+ {
+ sent = g_tcp_send(g_sck, data, len, 0);
+ if (sent == -1)
+ {
+ if (g_tcp_last_error_would_block(g_sck))
+ {
+ g_sleep(1);
+ }
+ else
+ {
+ RemoveEnabledDevice(g_sck);
+ g_connected = 0;
+ g_tcp_close(g_sck);
+ g_sck = 0;
+ g_sck_closed = 1;
+ return 1;
+ }
+ }
+ else if (sent == 0)
+ {
+ RemoveEnabledDevice(g_sck);
+ g_connected = 0;
+ g_tcp_close(g_sck);
+ g_sck = 0;
+ g_sck_closed = 1;
+ return 1;
+ }
+ else
+ {
+ data += sent;
+ len -= sent;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+static int
+rdpup_send_msg(struct stream* s)
+{
+ int len;
+ int rv;
+
+ rv = 1;
+ if (s != 0)
+ {
+ len = s->end - s->data;
+ if (len > s->size)
+ {
+ rdpLog("overrun error len %d count %d\n", len, g_count);
+ }
+ s_pop_layer(s, iso_hdr);
+ out_uint16_le(s, 1);
+ out_uint16_le(s, g_count);
+ out_uint32_le(s, len - 8);
+ rv = rdpup_send(s->data, len);
+ }
+ if (rv != 0)
+ {
+ rdpLog("error in rdpup_send_msg\n");
+ }
+ return rv;
+}
+
+/******************************************************************************/
+static CARD32
+rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg)
+{
+ if (g_connected && g_begin)
+ {
+ DEBUG_OUT_UP(("end %d\n", g_count));
+ out_uint16_le(g_out_s, 2);
+ g_count++;
+ s_mark_end(g_out_s);
+ rdpup_send_msg(g_out_s);
+ }
+ g_count = 0;
+ g_begin = 0;
+ g_scheduled = 0;
+ return 0;
+}
+
+/******************************************************************************/
+static void
+rdpScheduleDeferredUpdate(void)
+{
+ if (!g_scheduled)
+ {
+ g_scheduled = 1;
+ g_timer = TimerSet(g_timer, 0, 40, rdpDeferredUpdateCallback, 0);
+ }
+}
+
+/******************************************************************************/
+/* returns error */
+static int
+rdpup_recv(char* data, int len)
+{
+ int rcvd;
+
+ if (g_sck_closed)
+ {
+ return 1;
+ }
+ while (len > 0)
+ {
+ rcvd = g_tcp_recv(g_sck, data, len, 0);
+ if (rcvd == -1)
+ {
+ if (g_tcp_last_error_would_block(g_sck))
+ {
+ g_sleep(1);
+ }
+ else
+ {
+ RemoveEnabledDevice(g_sck);
+ g_connected = 0;
+ g_tcp_close(g_sck);
+ g_sck = 0;
+ g_sck_closed = 1;
+ return 1;
+ }
+ }
+ else if (rcvd == 0)
+ {
+ RemoveEnabledDevice(g_sck);
+ g_connected = 0;
+ g_tcp_close(g_sck);
+ g_sck = 0;
+ g_sck_closed = 1;
+ return 1;
+ }
+ else
+ {
+ data += rcvd;
+ len -= rcvd;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+static int
+rdpup_recv_msg(struct stream* s)
+{
+ int len;
+ int rv;
+
+ rv = 1;
+ if (s != 0)
+ {
+ init_stream(s, 4);
+ rv = rdpup_recv(s->data, 4);
+ if (rv == 0)
+ {
+ in_uint32_le(s, len);
+ if (len > 3)
+ {
+ init_stream(s, len);
+ rv = rdpup_recv(s->data, len - 4);
+ }
+ }
+ }
+ if (rv != 0)
+ {
+ rdpLog("error in rdpup_recv_msg\n");
+ }
+ return rv;
+}
+
+/******************************************************************************/
+/*
+ this from miScreenInit
+ pScreen->mmWidth = (xsize * 254 + dpix * 5) / (dpix * 10);
+ pScreen->mmHeight = (ysize * 254 + dpiy * 5) / (dpiy * 10);
+*/
+static int
+process_screen_size_msg(int width, int height, int bpp)
+{
+ RRScreenSizePtr pSize;
+ int mmwidth;
+ int mmheight;
+ int error;
+
+ ErrorF("process_screen_size_msg: set width %d height %d bpp %d\n",
+ width, height, bpp);
+ g_rdpScreen.rdp_width = width;
+ g_rdpScreen.rdp_height = height;
+ g_rdpScreen.rdp_bpp = bpp;
+ if (bpp < 15)
+ {
+ g_rdpScreen.rdp_Bpp = 1;
+ g_rdpScreen.rdp_Bpp_mask = 0xff;
+ }
+ else if (bpp == 15)
+ {
+ g_rdpScreen.rdp_Bpp = 2;
+ g_rdpScreen.rdp_Bpp_mask = 0x7fff;
+ }
+ else if (bpp == 16)
+ {
+ g_rdpScreen.rdp_Bpp = 2;
+ g_rdpScreen.rdp_Bpp_mask = 0xffff;
+ }
+ else if (bpp > 16)
+ {
+ g_rdpScreen.rdp_Bpp = 4;
+ g_rdpScreen.rdp_Bpp_mask = 0xffffff;
+ }
+ mmwidth = PixelToMM(width);
+ mmheight = PixelToMM(height);
+ pSize = RRRegisterSize(g_pScreen, width, height, mmwidth, mmheight);
+ RRSetCurrentConfig(g_pScreen, RR_Rotate_0, 0, pSize);
+ if ((g_rdpScreen.width != width) || (g_rdpScreen.height != height))
+ {
+ error = RRSetScreenConfig(g_pScreen, RR_Rotate_0, 0, pSize);
+ if (error == BadImplementation)
+ {
+ ErrorF("process_screen_size_msg: RRSetScreenConfig returned "
+ "BadImplementation\n");
+ }
+ }
+}
+
+/******************************************************************************/
+static int
+l_bound_by(int val, int low, int high)
+{
+ if (val > high)
+ {
+ val = high;
+ }
+ if (val < low)
+ {
+ val = low;
+ }
+ return val;
+}
+
+/******************************************************************************/
+static int
+rdpup_process_msg(struct stream* s)
+{
+ int msg_type;
+ int msg;
+ int param1;
+ int param2;
+ int param3;
+ int param4;
+
+ in_uint16_le(s, msg_type);
+ if (msg_type == 103)
+ {
+ in_uint32_le(s, msg);
+ in_uint32_le(s, param1);
+ in_uint32_le(s, param2);
+ in_uint32_le(s, param3);
+ in_uint32_le(s, param4);
+ DEBUG_OUT_UP(("rdpup_process_msg - msg %d param1 %d param2 %d param3 %d \
+param4 %d\n", msg, param1, param2, param3, param4));
+ switch (msg)
+ {
+ case 15: /* key down */
+ case 16: /* key up */
+ KbdAddEvent(msg == 15, param1, param2, param3, param4);
+ break;
+ case 17: /* from RDP_INPUT_SYNCHRONIZE */
+ KbdSync(param1);
+ break;
+ case 100:
+ /* without the minus 2, strange things happen when dragging
+ past the width or height */
+ g_cursor_x = l_bound_by(param1, 0, g_rdpScreen.width - 2);
+ g_cursor_y = l_bound_by(param2, 0, g_rdpScreen.height - 2);
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 101:
+ g_button_mask = g_button_mask & (~1);
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 102:
+ g_button_mask = g_button_mask | 1;
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 103:
+ g_button_mask = g_button_mask & (~4);
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 104:
+ g_button_mask = g_button_mask | 4;
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 105:
+ g_button_mask = g_button_mask & (~2);
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 106:
+ g_button_mask = g_button_mask | 2;
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 107:
+ g_button_mask = g_button_mask & (~8);
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 108:
+ g_button_mask = g_button_mask | 8;
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 109:
+ g_button_mask = g_button_mask & (~16);
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 110:
+ g_button_mask = g_button_mask | 16;
+ PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y);
+ break;
+ case 200:
+ rdpup_begin_update();
+ rdpup_send_area((param1 >> 16) & 0xffff, param1 & 0xffff,
+ (param2 >> 16) & 0xffff, param2 & 0xffff);
+ rdpup_end_update();
+ break;
+ case 300:
+ process_screen_size_msg(param1, param2, param3);
+ break;
+ }
+ }
+ else
+ {
+ rdpLog("unknown message type in rdpup_process_msg\n");
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_init(void)
+{
+ char text[256];
+ int i;
+
+ i = atoi(display);
+ if (i < 1)
+ {
+ return 0;
+ }
+ g_sprintf(text, "62%2.2d", i);
+ if (g_in_s == 0)
+ {
+ make_stream(g_in_s);
+ init_stream(g_in_s, 8192);
+ }
+ if (g_out_s == 0)
+ {
+ make_stream(g_out_s);
+ init_stream(g_out_s, 8192 * g_Bpp + 100);
+ }
+ if (g_listen_sck == 0)
+ {
+ g_listen_sck = g_tcp_socket();
+ if (g_tcp_bind(g_listen_sck, text) != 0)
+ {
+ return 0;
+ }
+ g_tcp_listen(g_listen_sck);
+ AddEnabledDevice(g_listen_sck);
+ }
+ g_dis_listen_sck = g_tcp_local_socket_dgram();
+ if (g_dis_listen_sck != 0)
+ {
+ g_sprintf(text, "/tmp/.xrdp/xrdp_disconnect_display_%s", display);
+ if (g_tcp_local_bind(g_dis_listen_sck, text) == 0)
+ {
+ AddEnabledDevice(g_dis_listen_sck);
+ }
+ else
+ {
+ rdpLog("g_tcp_local_bind failed [%s]\n", text);
+ }
+ }
+ return 1;
+}
+
+/******************************************************************************/
+int
+rdpup_check(void)
+{
+ int sel;
+ int new_sck;
+ char buf[8];
+
+ sel = g_tcp_select(g_listen_sck, g_sck, g_dis_listen_sck);
+ if (sel & 1)
+ {
+ new_sck = g_tcp_accept(g_listen_sck);
+ if (new_sck == -1)
+ {
+ }
+ else
+ {
+ if (g_sck != 0)
+ {
+ /* should maybe ask is user wants to allow here with timeout */
+ rdpLog("replacing connection, already got a connection\n");
+ RemoveEnabledDevice(g_sck);
+ g_connected = 0;
+ g_tcp_close(g_sck);
+ g_sck = 0;
+ g_sck_closed = 1;
+ }
+ rdpLog("got a connection\n");
+ g_sck = new_sck;
+ g_tcp_set_non_blocking(g_sck);
+ g_tcp_set_no_delay(g_sck);
+ g_connected = 1;
+ g_sck_closed = 0;
+ g_begin = 0;
+ AddEnabledDevice(g_sck);
+ }
+ }
+ if (sel & 2)
+ {
+ if (rdpup_recv_msg(g_in_s) == 0)
+ {
+ rdpup_process_msg(g_in_s);
+ }
+ }
+ if (sel & 4)
+ {
+ if (g_tcp_recv(g_dis_listen_sck, buf, 4, 0) > 0)
+ {
+ if (g_sck != 0)
+ {
+ rdpLog("disconnecting session via user request\n");
+ RemoveEnabledDevice(g_sck);
+ g_connected = 0;
+ g_tcp_close(g_sck);
+ g_sck = 0;
+ g_sck_closed = 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_begin_update(void)
+{
+ if (g_connected)
+ {
+ if (g_begin)
+ {
+ return 0;
+ }
+ init_stream(g_out_s, 0);
+ s_push_layer(g_out_s, iso_hdr, 8);
+ out_uint16_le(g_out_s, 1);
+ DEBUG_OUT_UP(("begin %d\n", g_count));
+ g_begin = 1;
+ g_count = 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_end_update(void)
+{
+ if (g_connected && g_begin)
+ {
+ rdpScheduleDeferredUpdate();
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_pre_check(int in_size)
+{
+ if (!g_begin)
+ {
+ rdpup_begin_update();
+ }
+ if ((g_out_s->p - g_out_s->data) > (g_out_s->size - (in_size + 20)))
+ {
+ s_mark_end(g_out_s);
+ rdpup_send_msg(g_out_s);
+ g_count = 0;
+ init_stream(g_out_s, 0);
+ s_push_layer(g_out_s, iso_hdr, 8);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_fill_rect(short x, short y, int cx, int cy)
+{
+ if (g_connected)
+ {
+ DEBUG_OUT_UP((" rdpup_fill_rect\n"));
+ rdpup_pre_check(10);
+ out_uint16_le(g_out_s, 3);
+ g_count++;
+ out_uint16_le(g_out_s, x);
+ out_uint16_le(g_out_s, y);
+ out_uint16_le(g_out_s, cx);
+ out_uint16_le(g_out_s, cy);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_screen_blt(short x, short y, int cx, int cy, short srcx, short srcy)
+{
+ if (g_connected)
+ {
+ DEBUG_OUT_UP((" rdpup_screen_blt\n"));
+ rdpup_pre_check(14);
+ out_uint16_le(g_out_s, 4);
+ g_count++;
+ out_uint16_le(g_out_s, x);
+ out_uint16_le(g_out_s, y);
+ out_uint16_le(g_out_s, cx);
+ out_uint16_le(g_out_s, cy);
+ out_uint16_le(g_out_s, srcx);
+ out_uint16_le(g_out_s, srcy);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_set_clip(short x, short y, int cx, int cy)
+{
+ if (g_connected)
+ {
+ DEBUG_OUT_UP((" rdpup_set_clip\n"));
+ rdpup_pre_check(10);
+ out_uint16_le(g_out_s, 10);
+ g_count++;
+ out_uint16_le(g_out_s, x);
+ out_uint16_le(g_out_s, y);
+ out_uint16_le(g_out_s, cx);
+ out_uint16_le(g_out_s, cy);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_reset_clip(void)
+{
+ if (g_connected)
+ {
+ DEBUG_OUT_UP((" rdpup_reset_clip\n"));
+ rdpup_pre_check(2);
+ out_uint16_le(g_out_s, 11);
+ g_count++;
+ }
+ return 0;
+}
+
+#define COLOR8(r, g, b) \
+ ((((r) >> 5) << 0) | (((g) >> 5) << 3) | (((b) >> 6) << 6))
+#define COLOR15(r, g, b) \
+ ((((r) >> 3) << 10) | (((g) >> 3) << 5) | (((b) >> 3) << 0))
+#define COLOR16(r, g, b) \
+ ((((r) >> 3) << 11) | (((g) >> 2) << 5) | (((b) >> 3) << 0))
+#define COLOR24(r, g, b) \
+ ((((r) >> 0) << 0) | (((g) >> 0) << 8) | (((b) >> 0) << 16))
+#define SPLITCOLOR32(r, g, b, c) \
+{ \
+ r = ((c) >> 16) & 0xff; \
+ g = ((c) >> 8) & 0xff; \
+ b = (c) & 0xff; \
+}
+
+int
+convert_pixel(int in_pixel)
+{
+ int red;
+ int green;
+ int blue;
+ int rv;
+
+ rv = 0;
+ if (g_rdpScreen.depth == 24)
+ {
+ if (g_rdpScreen.rdp_bpp == 24)
+ {
+ rv = in_pixel;
+ SPLITCOLOR32(red, green, blue, rv);
+ rv = COLOR24(red, green, blue);
+ }
+ else if (g_rdpScreen.rdp_bpp == 16)
+ {
+ rv = in_pixel;
+ SPLITCOLOR32(red, green, blue, rv);
+ rv = COLOR16(red, green, blue);
+ }
+ else if (g_rdpScreen.rdp_bpp == 15)
+ {
+ rv = in_pixel;
+ SPLITCOLOR32(red, green, blue, rv);
+ rv = COLOR15(red, green, blue);
+ }
+ else if (g_rdpScreen.rdp_bpp == 8)
+ {
+ rv = in_pixel;
+ SPLITCOLOR32(red, green, blue, rv);
+ rv = COLOR8(red, green, blue);
+ }
+ }
+ else if (g_rdpScreen.depth == g_rdpScreen.rdp_bpp)
+ {
+ return in_pixel;
+ }
+ return rv;
+}
+
+int
+convert_pixels(void* src, void* dst, int num_pixels)
+{
+ unsigned int pixel;
+ unsigned int red;
+ unsigned int green;
+ unsigned int blue;
+ unsigned int* src32;
+ unsigned int* dst32;
+ unsigned short* dst16;
+ unsigned char* dst8;
+ int index;
+
+ if (g_rdpScreen.depth == g_rdpScreen.rdp_bpp)
+ {
+ memcpy(dst, src, num_pixels * g_Bpp);
+ return 0;
+ }
+ if (g_rdpScreen.depth == 24)
+ {
+ src32 = (unsigned int*)src;
+ if (g_rdpScreen.rdp_bpp == 24)
+ {
+ dst32 = (unsigned int*)dst;
+ for (index = 0; index < num_pixels; index++)
+ {
+ pixel = *src32;
+ *dst32 = pixel;
+ dst32++;
+ src32++;
+ }
+ }
+ else if (g_rdpScreen.rdp_bpp == 16)
+ {
+ dst16 = (unsigned short*)dst;
+ for (index = 0; index < num_pixels; index++)
+ {
+ pixel = *src32;
+ SPLITCOLOR32(red, green, blue, pixel);
+ pixel = COLOR16(red, green, blue);
+ *dst16 = pixel;
+ dst16++;
+ src32++;
+ }
+ }
+ else if (g_rdpScreen.rdp_bpp == 15)
+ {
+ dst16 = (unsigned short*)dst;
+ for (index = 0; index < num_pixels; index++)
+ {
+ pixel = *src32;
+ SPLITCOLOR32(red, green, blue, pixel);
+ pixel = COLOR15(red, green, blue);
+ *dst16 = pixel;
+ dst16++;
+ src32++;
+ }
+ }
+ else if (g_rdpScreen.rdp_bpp == 8)
+ {
+ dst8 = (unsigned char*)dst;
+ for (index = 0; index < num_pixels; index++)
+ {
+ pixel = *src32;
+ SPLITCOLOR32(red, green, blue, pixel);
+ pixel = COLOR8(red, green, blue);
+ *dst8 = pixel;
+ dst8++;
+ src32++;
+ }
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_set_fgcolor(int fgcolor)
+{
+ if (g_connected)
+ {
+ DEBUG_OUT_UP((" rdpup_set_fgcolor\n"));
+ rdpup_pre_check(6);
+ out_uint16_le(g_out_s, 12);
+ g_count++;
+ fgcolor = fgcolor & g_Bpp_mask;
+ fgcolor = convert_pixel(fgcolor) & g_rdpScreen.rdp_Bpp_mask;
+ out_uint32_le(g_out_s, fgcolor);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_set_bgcolor(int bgcolor)
+{
+ if (g_connected)
+ {
+ DEBUG_OUT_UP((" rdpup_set_bgcolor\n"));
+ rdpup_pre_check(6);
+ out_uint16_le(g_out_s, 13);
+ g_count++;
+ bgcolor = bgcolor & g_Bpp_mask;
+ bgcolor = convert_pixel(bgcolor) & g_rdpScreen.rdp_Bpp_mask;
+ out_uint32_le(g_out_s, bgcolor);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_set_opcode(int opcode)
+{
+ if (g_connected)
+ {
+ DEBUG_OUT_UP((" rdpup_set_opcode\n"));
+ rdpup_pre_check(4);
+ out_uint16_le(g_out_s, 14);
+ g_count++;
+ out_uint16_le(g_out_s, g_rdp_opcodes[opcode & 0xf]);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_set_pen(int style, int width)
+{
+ if (g_connected)
+ {
+ DEBUG_OUT_UP((" rdpup_set_pen\n"));
+ rdpup_pre_check(6);
+ out_uint16_le(g_out_s, 17);
+ g_count++;
+ out_uint16_le(g_out_s, style);
+ out_uint16_le(g_out_s, width);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_draw_line(short x1, short y1, short x2, short y2)
+{
+ if (g_connected)
+ {
+ DEBUG_OUT_UP((" rdpup_draw_line\n"));
+ rdpup_pre_check(10);
+ out_uint16_le(g_out_s, 18);
+ g_count++;
+ out_uint16_le(g_out_s, x1);
+ out_uint16_le(g_out_s, y1);
+ out_uint16_le(g_out_s, x2);
+ out_uint16_le(g_out_s, y2);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+int
+rdpup_set_cursor(short x, short y, char* cur_data, char* cur_mask)
+{
+ if (g_connected)
+ {
+ DEBUG_OUT_UP((" rdpup_set_cursor\n"));
+ rdpup_pre_check(6 + 32 * (32 * 3) + 32 * (32 / 8));
+ out_uint16_le(g_out_s, 19);
+ g_count++;
+ x = MAX(0, x);
+ x = MIN(31, x);
+ y = MAX(0, y);
+ y = MIN(31, y);
+ out_uint16_le(g_out_s, x);
+ out_uint16_le(g_out_s, y);
+ out_uint8a(g_out_s, cur_data, 32 * (32 * 3));
+ out_uint8a(g_out_s, cur_mask, 32 * (32 / 8));
+ }
+ return 0;
+}
+
+/******************************************************************************/
+static int
+get_single_color(int x, int y, int w, int h)
+{
+ int rv;
+ int i;
+ int j;
+ int p;
+ unsigned char* i8;
+ unsigned short* i16;
+ unsigned int* i32;
+
+ rv = -1;
+ if (g_Bpp == 1)
+ {
+ for (i = 0; i < h; i++)
+ {
+ i8 = (unsigned char*)(g_rdpScreen.pfbMemory +
+ ((y + i) * g_rdpScreen.paddedWidthInBytes) + (x * g_Bpp));
+ if (i == 0)
+ {
+ p = *i8;
+ }
+ for (j = 0; j < w; j++)
+ {
+ if (i8[j] != p)
+ {
+ return -1;
+ }
+ }
+ }
+ rv = p;
+ }
+ else if (g_Bpp == 2)
+ {
+ for (i = 0; i < h; i++)
+ {
+ i16 = (unsigned short*)(g_rdpScreen.pfbMemory +
+ ((y + i) * g_rdpScreen.paddedWidthInBytes) + (x * g_Bpp));
+ if (i == 0)
+ {
+ p = *i16;
+ }
+ for (j = 0; j < w; j++)
+ {
+ if (i16[j] != p)
+ {
+ return -1;
+ }
+ }
+ }
+ rv = p;
+ }
+ else if (g_Bpp == 4)
+ {
+ for (i = 0; i < h; i++)
+ {
+ i32 = (unsigned int*)(g_rdpScreen.pfbMemory +
+ ((y + i) * g_rdpScreen.paddedWidthInBytes) + (x * g_Bpp));
+ if (i == 0)
+ {
+ p = *i32;
+ }
+ for (j = 0; j < w; j++)
+ {
+ if (i32[j] != p)
+ {
+ return -1;
+ }
+ }
+ }
+ rv = p;
+ }
+ return rv;
+}
+
+/******************************************************************************/
+/* split the bitmap up into 64 x 64 pixel areas */
+void
+rdpup_send_area(int x, int y, int w, int h)
+{
+ char* s;
+ int i;
+ int single_color;
+ int lx;
+ int ly;
+ int lh;
+ int lw;
+
+ if (x >= g_rdpScreen.width)
+ {
+ return;
+ }
+ if (y >= g_rdpScreen.height)
+ {
+ return;
+ }
+ if (x < 0)
+ {
+ w += x;
+ x = 0;
+ }
+ if (y < 0)
+ {
+ h += y;
+ y = 0;
+ }
+ if (w <= 0)
+ {
+ return;
+ }
+ if (h <= 0)
+ {
+ return;
+ }
+ if (x + w > g_rdpScreen.width)
+ {
+ w = g_rdpScreen.width - x;
+ }
+ if (y + h > g_rdpScreen.height)
+ {
+ h = g_rdpScreen.height - y;
+ }
+ DEBUG_OUT_UP(("%d\n", w * h));
+ if (g_connected && g_begin)
+ {
+ DEBUG_OUT_UP((" rdpup_send_area\n"));
+ ly = y;
+ while (ly < y + h)
+ {
+ lx = x;
+ while (lx < x + w)
+ {
+ lw = MIN(64, (x + w) - lx);
+ lh = MIN(64, (y + h) - ly);
+ single_color = get_single_color(lx, ly, lw, lh);
+ if (single_color != -1)
+ {
+ DEBUG_OUT_UP(("%d sending single color\n", g_count));
+ rdpup_set_fgcolor(single_color);
+ rdpup_fill_rect(lx, ly, lw, lh);
+ }
+ else
+ {
+ rdpup_pre_check(lw * lh * g_rdpScreen.rdp_Bpp + 42);
+ out_uint16_le(g_out_s, 5);
+ g_count++;
+ out_uint16_le(g_out_s, lx);
+ out_uint16_le(g_out_s, ly);
+ out_uint16_le(g_out_s, lw);
+ out_uint16_le(g_out_s, lh);
+ out_uint32_le(g_out_s, lw * lh * g_rdpScreen.rdp_Bpp);
+ for (i = 0; i < lh; i++)
+ {
+ s = (g_rdpScreen.pfbMemory +
+ ((ly + i) * g_rdpScreen.paddedWidthInBytes) + (lx * g_Bpp));
+ convert_pixels(s, g_out_s->p, lw);
+ g_out_s->p += lw * g_rdpScreen.rdp_Bpp;
+ }
+ out_uint16_le(g_out_s, lw);
+ out_uint16_le(g_out_s, lh);
+ out_uint16_le(g_out_s, 0);
+ out_uint16_le(g_out_s, 0);
+ }
+ lx += 64;
+ }
+ ly += 64;
+ }
+ }
+}