summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Xserver/hw/rdp/Makefile47
-rw-r--r--Xserver/hw/rdp/gcops.h98
-rw-r--r--Xserver/hw/rdp/rdp.h400
-rw-r--r--Xserver/hw/rdp/rdpdraw.c2114
-rw-r--r--Xserver/hw/rdp/rdpinput.c999
-rw-r--r--Xserver/hw/rdp/rdpmain.c528
-rw-r--r--Xserver/hw/rdp/rdpmisc.c377
-rw-r--r--Xserver/hw/rdp/rdpup.c806
8 files changed, 5369 insertions, 0 deletions
diff --git a/Xserver/hw/rdp/Makefile b/Xserver/hw/rdp/Makefile
new file mode 100644
index 00000000..40ea1da2
--- /dev/null
+++ b/Xserver/hw/rdp/Makefile
@@ -0,0 +1,47 @@
+
+OBJS = rdpmain.o rdpdraw.o rdpinput.o rdpmisc.o rdpup.o miinitext.o
+
+CFLAGS = -O2 -fno-strength-reduce -ansi -pedantic
+CFLAGS += -I. -I../../../../exports/include/X11
+CFLAGS += -I../../../../include/fonts
+CFLAGS += -I../../../../exports/include/X11
+CFLAGS += -I../../cfb -I../../mfb -I../../mi
+CFLAGS += -I../../include -I../../os
+CFLAGS += -I../../../../../include
+CFLAGS += -I/usr/local/include
+CFLAGS += -I../../../.././ -I../../../../exports/include
+CFLAGS += -I../../../../include/extensions
+CFLAGS += -I../../render
+CFLAGS += -Dlinux -D__i386__
+CFLAGS += -D_POSIX_C_SOURCE=199309L
+CFLAGS += -D_POSIX_SOURCE -D_XOPEN_SOURCE=500L
+CFLAGS += -D_BSD_SOURCE -D_SVID_SOURCE -D_REENTRANT
+
+CFLAGS += -DSHAPE -DXKB -DBIGREQS -DGLXEXT -DGLX_USE_MESA -DMITMISC -DXTEST
+CFLAGS += -DPANORAMIX -DRANDR -DRENDER -DXCMISC -DXSYNC -DXRECORD
+
+CFLAGS += -D_GNU_SOURCE -DLBX -DXAPPGROUP -DXCSECURITY -DTOGCUP
+CFLAGS += -DXF86BIGFONT -DDPMSExtension -DSINGLEDEPTH -DXvExtension
+CFLAGS += -DXFree86Server -DXvMCExtension -DSMART_SCHEDULE -DXResExtension
+CFLAGS += -DX_BYTE_ORDER=X_LITTLE_ENDIAN -DXTRAP -DMITSHM -DDBE -DEVI
+CFLAGS += -DSCREENSAVER -DXV -DXVMC -DFONTCACHE
+
+#CFLAGS += -DXINPUT
+
+CFLAGS += -DGCCUSESGAS -DSTATIC_COLOR -DAVOID_GLYPHBLT -DPIXPRIV
+CFLAGS += -DNDEBUG -DFUNCPROTO=15 -DNARROWPROTO -DDDXOSINIT
+CFLAGS += -DSERVER_LOCK -DDDXOSFATALERROR -DDDXTIME -DPART_NET
+#CFLAGS += -DXVNCRELEASE=\"tight1.2.9\"
+
+all: rdp
+
+rdp: $(OBJS)
+ $(AR) rvu librdp.a $(OBJS)
+ ranlib librdp.a
+
+clean:
+ rm -f $(OBJS) librdp.a
+
+
+miinitext.o: ../../mi/miinitext.c
+ $(CC) $(CFLAGS) -c ../../mi/miinitext.c
diff --git a/Xserver/hw/rdp/gcops.h b/Xserver/hw/rdp/gcops.h
new file mode 100644
index 00000000..a6baeb82
--- /dev/null
+++ b/Xserver/hw/rdp/gcops.h
@@ -0,0 +1,98 @@
+/*
+Copyright 2005-2006 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.
+
+*/
+
+static void
+rdpValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr d);
+static void
+rdpChangeGC(GCPtr pGC, unsigned long mask);
+static void
+rdpCopyGC(GCPtr src, unsigned long mask, GCPtr dst);
+static void
+rdpDestroyGC(GCPtr pGC);
+static void
+rdpChangeClip(GCPtr pGC, int type, pointer pValue, int nrects);
+static void
+rdpDestroyClip(GCPtr pGC);
+static void
+rdpCopyClip(GCPtr dst, GCPtr src);
+static void
+rdpFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
+ DDXPointPtr pptInit, int * pwidthInit, int fSorted);
+static void
+rdpSetSpans(DrawablePtr pDrawable, GCPtr pGC, char * psrc,
+ DDXPointPtr ppt, int * pwidth, int nspans, int fSorted);
+static void
+rdpPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
+ int w, int h, int leftPad, int format, char * pBits);
+static RegionPtr
+rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h, int dstx, int dsty);
+static RegionPtr
+rdpCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width, int height,
+ int dstx, int dsty, unsigned long bitPlane);
+static void
+rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int npt, DDXPointPtr pptInit);
+static void
+rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int npt, DDXPointPtr pptInit);
+static void
+rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSegs);
+static void
+rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
+ xRectangle * pRects);
+static void
+rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs);
+static void
+rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
+ int shape, int mode, int count,
+ DDXPointPtr pPts);
+static void
+rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
+ xRectangle * prectInit);
+static void
+rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * parcs);
+static int
+rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, int count, char * chars);
+static int
+rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, int count, unsigned short * chars);
+static void
+rdpImageText8(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, int count, char * chars);
+static void
+rdpImageText16(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, int count,
+ unsigned short * chars);
+static void
+rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr * ppci, pointer pglyphBase);
+static void
+rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr * ppci,
+ pointer pglyphBase);
+static void
+rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
+ int w, int h, int x, int y);
diff --git a/Xserver/hw/rdp/rdp.h b/Xserver/hw/rdp/rdp.h
new file mode 100644
index 00000000..eae8907c
--- /dev/null
+++ b/Xserver/hw/rdp/rdp.h
@@ -0,0 +1,400 @@
+/*
+Copyright 2005-2006 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 <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include "X11/X.h"
+#define NEED_EVENTS
+#include "X11/Xproto.h"
+#include "X11/Xos.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#define PSZ 8
+#include "cfb.h"
+#include "mibstore.h"
+#include "colormapst.h"
+#include "gcstruct.h"
+#include "input.h"
+#include "mipointer.h"
+#include "dixstruct.h"
+#include "propertyst.h"
+#include <Xatom.h>
+#include <errno.h>
+#include <sys/param.h>
+#include "dix.h"
+#include <X11/keysym.h>
+#include "dixfontstr.h"
+#include "osdep.h"
+#include "fontstruct.h"
+#include <cursorstr.h>
+#include "picturestr.h"
+#include <netinet/tcp.h>
+
+/* Per-screen (framebuffer) structure. There is only one of these, since we
+ don't allow the X server to have multiple screens. */
+typedef struct
+{
+ int width;
+ int paddedWidthInBytes;
+ int height;
+ int depth;
+ int bitsPerPixel;
+ int sizeInBytes;
+ char* pfbMemory;
+ Pixel blackPixel;
+ Pixel whitePixel;
+ /* wrapped screen functions */
+ /* Random screen procedures */
+ CloseScreenProcPtr CloseScreen;
+ /* GC procedures */
+ CreateGCProcPtr CreateGC;
+ /* Window Procedures */
+ PaintWindowBackgroundProcPtr PaintWindowBackground;
+ PaintWindowBorderProcPtr PaintWindowBorder;
+ CopyWindowProcPtr CopyWindow;
+ ClearToBackgroundProcPtr ClearToBackground;
+ ScreenWakeupHandlerProcPtr WakeupHandler;
+ CompositeProcPtr Composite;
+ /* Backing store procedures */
+ RestoreAreasProcPtr RestoreAreas;
+
+ /*InstallColormapProcPtr InstallColormap;*/
+
+} rdpScreenInfo;
+
+typedef rdpScreenInfo* rdpScreenInfoPtr;
+
+typedef struct
+{
+ GCFuncs* funcs;
+ GCOps* ops;
+} rdpGCRec;
+
+typedef rdpGCRec* rdpGCPtr;
+
+/* rdpmisc.c */
+void
+rdpLog(char *format, ...);
+int
+rdpBitsPerPixel(int depth);
+void
+rdpClientStateChange(CallbackListPtr* cbl, pointer myData, pointer clt);
+int
+g_tcp_recv(int sck, void* ptr, int len, int flags);
+void
+g_tcp_close(int sck);
+int
+g_tcp_last_error_would_block(int sck);
+void
+g_sleep(int msecs);
+int
+g_tcp_send(int sck, void* ptr, int len, int flags);
+void*
+g_malloc(int size, int zero);
+void
+g_free(void* ptr);
+void
+g_sprintf(char* dest, char* format, ...);
+int
+g_tcp_socket(void);
+void
+g_memcpy(void* d_ptr, const void* s_ptr, int size);
+int
+g_tcp_set_no_delay(int sck);
+int
+g_tcp_set_non_blocking(int sck);
+int
+g_tcp_accept(int sck);
+int
+g_tcp_select(int sck1, int sck2);
+int
+g_tcp_bind(int sck, char* port);
+int
+g_tcp_listen(int sck);
+
+/* rdpdraw.c */
+Bool
+rdpCloseScreen(int i, ScreenPtr pScreen);
+Bool
+rdpCreateGC(GCPtr pGC);
+void
+rdpPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what);
+void
+rdpPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what);
+void
+rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion);
+void
+rdpClearToBackground(WindowPtr pWin, int x, int y, int w, int h,
+ Bool generateExposures);
+RegionPtr
+rdpRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed);
+void
+rdpInstallColormap(ColormapPtr pmap);
+void
+rdpUninstallColormap(ColormapPtr pmap);
+int
+rdpListInstalledColormaps(ScreenPtr pScreen, Colormap* pmaps);
+void
+rdpStoreColors(ColormapPtr pmap, int ndef, xColorItem* pdefs);
+Bool
+rdpSaveScreen(ScreenPtr pScreen, int on);
+Bool
+rdpRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+Bool
+rdpUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+void
+rdpCursorLimits(ScreenPtr pScreen, CursorPtr pCursor,
+ BoxPtr pHotBox, BoxPtr pTopLeftBox);
+void
+rdpConstrainCursor(ScreenPtr pScreen, BoxPtr pBox);
+Bool
+rdpSetCursorPosition(ScreenPtr pScreen, int x, int y, Bool generateEvent);
+Bool
+rdpDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor);
+void
+rdpRecolorCursor(ScreenPtr pScreen, CursorPtr pCursor,
+ Bool displayed);
+void
+rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
+ INT16 yDst, CARD16 width, CARD16 height);
+
+
+/* rdpkbdptr.c */
+int
+rdpKeybdProc(DeviceIntPtr pDevice, int onoff);
+int
+rdpMouseProc(DeviceIntPtr pDevice, int onoff);
+Bool
+rdpCursorOffScreen(ScreenPtr* ppScreen, int* x, int* y);
+void
+rdpCrossScreen(ScreenPtr pScreen, Bool entering);
+Bool
+rdpSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+Bool
+rdpSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+void
+rdpSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y);
+void
+rdpSpriteMoveCursor(ScreenPtr pScreen, int x, int y);
+void
+PtrAddEvent(int buttonMask, int x, int y);
+void
+KbdAddEvent(int down, int param1, int param2, int param3, int param4);
+
+/* rdpup.c */
+int
+rdpup_init(void);
+int
+rdpup_check(void);
+int
+rdpup_begin_update(void);
+int
+rdpup_end_update(void);
+int
+rdpup_fill_rect(short x, short y, int cx, int cy);
+int
+rdpup_screen_blt(short x, short y, int cx, int cy, short srcx, short srcy);
+int
+rdpup_set_clip(short x, short y, int cx, int cy);
+int
+rdpup_reset_clip(void);
+int
+rdpup_set_fgcolor(int fgcolor);
+int
+rdpup_set_bgcolor(int bgcolor);
+int
+rdpup_set_opcode(int opcode);
+int
+rdpup_paint_rect(short x, short y, int cx, int cy,
+ char* bmpdata, int width, int height,
+ short srcx, short srcy);
+int
+rdpup_set_pen(int style, int width);
+int
+rdpup_draw_line(short x1, short y1, short x2, short y2);
+void
+rdpup_send_area(int x, int y, int w, int h);
+
+#if defined(__sparc__) || defined(__PPC__)
+#define B_ENDIAN
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define L_ENDIAN
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#define B_ENDIAN
+#endif
+/* check if we need to align data */
+#if defined(__sparc__) || defined(__alpha__) || defined(__hppa__) || \
+ defined(__AIX__) || defined(__PPC__) || defined(__mips__) || \
+ defined(__ia64__)
+#define NEED_ALIGN
+#endif
+
+/* parser state */
+struct stream
+{
+ char* p;
+ char* end;
+ char* data;
+ int size;
+ /* offsets of various headers */
+ char* iso_hdr;
+ char* mcs_hdr;
+ char* sec_hdr;
+ char* rdp_hdr;
+ char* channel_hdr;
+ char* next_packet;
+};
+
+/******************************************************************************/
+#define s_push_layer(s, h, n) \
+{ \
+ (s)->h = (s)->p; \
+ (s)->p += (n); \
+}
+
+/******************************************************************************/
+#define s_pop_layer(s, h) \
+{ \
+ (s)->p = (s)->h; \
+}
+
+/******************************************************************************/
+#if defined(B_ENDIAN) || defined(NEED_ALIGN)
+#define out_uint16_le(s, v) \
+{ \
+ *((s)->p) = (unsigned char)((v) >> 0); \
+ (s)->p++; \
+ *((s)->p) = (unsigned char)((v) >> 8); \
+ (s)->p++; \
+}
+#else
+#define out_uint16_le(s, v) \
+{ \
+ *((unsigned short*)((s)->p)) = (unsigned short)(v); \
+ (s)->p += 2; \
+}
+#endif
+
+/******************************************************************************/
+#define init_stream(s, v) \
+{ \
+ if ((v) > (s)->size) \
+ { \
+ g_free((s)->data); \
+ (s)->data = (char*)g_malloc((v), 0); \
+ (s)->size = (v); \
+ } \
+ (s)->p = (s)->data; \
+ (s)->end = (s)->data; \
+ (s)->next_packet = 0; \
+}
+
+/******************************************************************************/
+#define out_uint8p(s, v, n) \
+{ \
+ g_memcpy((s)->p, (v), (n)); \
+ (s)->p += (n); \
+}
+
+/******************************************************************************/
+#define out_uint8a(s, v, n) \
+{ \
+ out_uint8p((s), (v), (n)); \
+}
+
+/******************************************************************************/
+#if defined(B_ENDIAN) || defined(NEED_ALIGN)
+#define out_uint32_le(s, v) \
+{ \
+ *((s)->p) = (unsigned char)((v) >> 0); \
+ (s)->p++; \
+ *((s)->p) = (unsigned char)((v) >> 8); \
+ (s)->p++; \
+ *((s)->p) = (unsigned char)((v) >> 16); \
+ (s)->p++; \
+ *((s)->p) = (unsigned char)((v) >> 24); \
+ (s)->p++; \
+}
+#else
+#define out_uint32_le(s, v) \
+{ \
+ *((unsigned int*)((s)->p)) = (v); \
+ (s)->p += 4; \
+}
+#endif
+
+/******************************************************************************/
+#if defined(B_ENDIAN) || defined(NEED_ALIGN)
+#define in_uint32_le(s, v) \
+{ \
+ (v) = (unsigned int) \
+ ( \
+ (*((unsigned char*)((s)->p + 0)) << 0) | \
+ (*((unsigned char*)((s)->p + 1)) << 8) | \
+ (*((unsigned char*)((s)->p + 2)) << 16) | \
+ (*((unsigned char*)((s)->p + 3)) << 24) \
+ ); \
+ (s)->p += 4; \
+}
+#else
+#define in_uint32_le(s, v) \
+{ \
+ (v) = *((unsigned int*)((s)->p)); \
+ (s)->p += 4; \
+}
+#endif
+
+/******************************************************************************/
+#if defined(B_ENDIAN) || defined(NEED_ALIGN)
+#define in_uint16_le(s, v) \
+{ \
+ (v) = (unsigned short) \
+ ( \
+ (*((unsigned char*)((s)->p + 0)) << 0) | \
+ (*((unsigned char*)((s)->p + 1)) << 8) \
+ ); \
+ (s)->p += 2; \
+}
+#else
+#define in_uint16_le(s, v) \
+{ \
+ (v) = *((unsigned short*)((s)->p)); \
+ (s)->p += 2; \
+}
+#endif
+
+/******************************************************************************/
+#define s_mark_end(s) \
+{ \
+ (s)->end = (s)->p; \
+}
+
+/******************************************************************************/
+#define make_stream(s) \
+{ \
+ (s) = (struct stream*)g_malloc(sizeof(struct stream), 1); \
+}
diff --git a/Xserver/hw/rdp/rdpdraw.c b/Xserver/hw/rdp/rdpdraw.c
new file mode 100644
index 00000000..0d0d6353
--- /dev/null
+++ b/Xserver/hw/rdp/rdpdraw.c
@@ -0,0 +1,2114 @@
+/*
+Copyright 2005-2006 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.
+
+Xserver drawing ops and funcs
+
+*/
+
+#include "rdp.h"
+#include "gcops.h"
+
+#define DEBUG_OUT_FUNCS(arg)
+#define DEBUG_OUT_OPS(arg)
+/*#define DEBUG_OUT_FUNCS(arg) ErrorF arg*/
+/*#define DEBUG_OUT_OPS(arg) ErrorF arg*/
+
+#if 0
+int atemp = 0;
+char atext[256];
+
+#define DEBUG_OUT_OPS(arg) \
+{ \
+ if (atemp == 0) \
+ { \
+ g_file_delete("/home/jj/atemp.log"); \
+ atemp = g_file_open("/home/jj/atemp.log"); \
+ g_set_file_rights("/home/jj/atemp.log", 1, 1); \
+ } \
+ g_sprintf(atext, arg ); \
+ g_file_write(atemp, atext, g_strlen(atext)); \
+}
+#endif
+
+#if 0
+int atemp = 0;
+char atext[256];
+#define DEBUG_OUT_OPS1(arg) \
+{ \
+ if (atemp == 0) \
+ { \
+ g_file_delete("/home/jj/atemp.log"); \
+ atemp = g_file_open("/home/jj/atemp.log"); \
+ g_set_file_rights("/home/jj/atemp.log", 1, 1); \
+ } \
+ g_sprintf arg ; \
+ g_file_write(atemp, atext, g_strlen(atext)); \
+}
+#endif
+
+extern rdpScreenInfo g_rdpScreen; /* from rdpmain.c */
+extern int g_rdpGCIndex; /* from rdpmain.c */
+extern int g_Bpp; /* from rdpmain.c */
+extern ScreenPtr g_pScreen; /* from rdpmain.c */
+
+ColormapPtr g_rdpInstalledColormap;
+
+static GCFuncs g_rdpGCFuncs =
+{
+ rdpValidateGC, rdpChangeGC, rdpCopyGC, rdpDestroyGC, rdpChangeClip,
+ rdpDestroyClip, rdpCopyClip
+};
+
+static GCOps g_rdpGCOps =
+{
+ rdpFillSpans, rdpSetSpans, rdpPutImage, rdpCopyArea, rdpCopyPlane,
+ rdpPolyPoint, rdpPolylines, rdpPolySegment, rdpPolyRectangle,
+ rdpPolyArc, rdpFillPolygon, rdpPolyFillRect, rdpPolyFillArc,
+ rdpPolyText8, rdpPolyText16, rdpImageText8, rdpImageText16,
+ rdpImageGlyphBlt, rdpPolyGlyphBlt, rdpPushPixels
+};
+
+/******************************************************************************/
+/* return 0, draw nothing */
+/* return 1, draw with no clip */
+/* return 2, draw using clip */
+static int
+rdp_get_clip(RegionPtr pRegion, DrawablePtr pDrawable, GCPtr pGC)
+{
+ WindowPtr pWindow;
+ RegionPtr temp;
+ BoxRec box;
+ int rv;
+
+ rv = 0;
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ pWindow = (WindowPtr)pDrawable;
+ if (pWindow->viewable)
+ {
+ if (pGC->subWindowMode == IncludeInferiors)
+ {
+ temp = &pWindow->borderClip;
+ }
+ else
+ {
+ temp = &pWindow->clipList;
+ }
+ if (miRegionNotEmpty(temp))
+ {
+ switch (pGC->clientClipType)
+ {
+ case CT_NONE:
+ rv = 2;
+ miRegionCopy(pRegion, temp);
+ break;
+ case CT_REGION:
+ rv = 2;
+ miRegionCopy(pRegion, pGC->clientClip);
+ miTranslateRegion(pRegion,
+ pDrawable->x + pGC->clipOrg.x,
+ pDrawable->y + pGC->clipOrg.y);
+ miIntersect(pRegion, pRegion, temp);
+ break;
+ default:
+ ErrorF("unimp clip type %d\n", pGC->clientClipType);
+ break;
+ }
+ if (rv == 2) /* check if the clip is the entire screen */
+ {
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = g_rdpScreen.width;
+ box.y2 = g_rdpScreen.height;
+ if (miRectIn(pRegion, &box) == rgnIN)
+ {
+ rv = 1;
+ }
+ }
+ }
+ }
+ }
+ return rv;
+}
+
+/******************************************************************************/
+static void
+GetTextBoundingBox(DrawablePtr pDrawable, FontPtr font, int x, int y,
+ int n, BoxPtr pbox)
+{
+ int maxAscent;
+ int maxDescent;
+ int maxCharWidth;
+
+ if (FONTASCENT(font) > FONTMAXBOUNDS(font, ascent))
+ {
+ maxAscent = FONTASCENT(font);
+ }
+ else
+ {
+ maxAscent = FONTMAXBOUNDS(font, ascent);
+ }
+ if (FONTDESCENT(font) > FONTMAXBOUNDS(font, descent))
+ {
+ maxDescent = FONTDESCENT(font);
+ }
+ else
+ {
+ maxDescent = FONTMAXBOUNDS(font, descent);
+ }
+ if (FONTMAXBOUNDS(font, rightSideBearing) >
+ FONTMAXBOUNDS(font, characterWidth))
+ {
+ maxCharWidth = FONTMAXBOUNDS(font, rightSideBearing);
+ }
+ else
+ {
+ maxCharWidth = FONTMAXBOUNDS(font, characterWidth);
+ }
+ pbox->x1 = pDrawable->x + x;
+ pbox->y1 = pDrawable->y + y - maxAscent;
+ pbox->x2 = pbox->x1 + maxCharWidth * n;
+ pbox->y2 = pbox->y1 + maxAscent + maxDescent;
+ if (FONTMINBOUNDS(font, leftSideBearing) < 0)
+ {
+ pbox->x1 += FONTMINBOUNDS(font, leftSideBearing);
+ }
+}
+
+/******************************************************************************/
+#define GC_FUNC_PROLOGUE(_pGC) \
+{ \
+ priv = (rdpGCPtr)(_pGC->devPrivates[g_rdpGCIndex].ptr); \
+ (_pGC)->funcs = priv->funcs; \
+ if (priv->ops != 0) \
+ { \
+ (_pGC)->ops = priv->ops; \
+ } \
+}
+
+/******************************************************************************/
+#define GC_FUNC_EPILOGUE(_pGC) \
+{ \
+ priv->funcs = (_pGC)->funcs; \
+ (_pGC)->funcs = &g_rdpGCFuncs; \
+ if (priv->ops != 0) \
+ { \
+ priv->ops = (_pGC)->ops; \
+ (_pGC)->ops = &g_rdpGCOps; \
+ } \
+}
+
+/******************************************************************************/
+static void
+rdpValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr d)
+{
+ rdpGCRec* priv;
+ int viewable;
+ RegionPtr pRegion;
+
+ DEBUG_OUT_FUNCS(("in rdpValidateGC\n"));
+ GC_FUNC_PROLOGUE(pGC);
+ pGC->funcs->ValidateGC(pGC, changes, d);
+ viewable = d->type == DRAWABLE_WINDOW && ((WindowPtr)d)->viewable;
+ if (viewable)
+ {
+ if (pGC->subWindowMode == IncludeInferiors)
+ {
+ pRegion = &(((WindowPtr)d)->borderClip);
+ }
+ else
+ {
+ pRegion = &(((WindowPtr)d)->clipList);
+ }
+ viewable = miRegionNotEmpty(pRegion);
+ }
+ priv->ops = 0;
+ if (viewable)
+ {
+ priv->ops = pGC->ops;
+ }
+ GC_FUNC_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpChangeGC(GCPtr pGC, unsigned long mask)
+{
+ rdpGCRec* priv;
+
+ DEBUG_OUT_FUNCS(("in rdpChangeGC\n"));
+ GC_FUNC_PROLOGUE(pGC);
+ pGC->funcs->ChangeGC(pGC, mask);
+ GC_FUNC_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpCopyGC(GCPtr src, unsigned long mask, GCPtr dst)
+{
+ rdpGCRec* priv;
+
+ DEBUG_OUT_FUNCS(("in rdpCopyGC\n"));
+ GC_FUNC_PROLOGUE(dst);
+ dst->funcs->CopyGC(src, mask, dst);
+ GC_FUNC_EPILOGUE(dst);
+}
+
+/******************************************************************************/
+static void
+rdpDestroyGC(GCPtr pGC)
+{
+ rdpGCRec* priv;
+
+ DEBUG_OUT_FUNCS(("in rdpDestroyGC\n"));
+ GC_FUNC_PROLOGUE(pGC);
+ pGC->funcs->DestroyGC(pGC);
+ GC_FUNC_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpChangeClip(GCPtr pGC, int type, pointer pValue, int nrects)
+{
+ rdpGCRec* priv;
+
+ DEBUG_OUT_FUNCS(("in rdpChangeClip\n"));
+ GC_FUNC_PROLOGUE(pGC);
+ pGC->funcs->ChangeClip(pGC, type, pValue, nrects);
+ GC_FUNC_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpDestroyClip(GCPtr pGC)
+{
+ rdpGCRec* priv;
+
+ DEBUG_OUT_FUNCS(("in rdpDestroyClip\n"));
+ GC_FUNC_PROLOGUE(pGC);
+ pGC->funcs->DestroyClip(pGC);
+ GC_FUNC_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpCopyClip(GCPtr dst, GCPtr src)
+{
+ rdpGCRec* priv;
+
+ DEBUG_OUT_FUNCS(("in rdpCopyClip\n"));
+ GC_FUNC_PROLOGUE(dst);
+ dst->funcs->CopyClip(dst, src);
+ GC_FUNC_EPILOGUE(dst);
+}
+
+/******************************************************************************/
+#define GC_OP_PROLOGUE(_pGC) \
+{ \
+ priv = (rdpGCPtr)pGC->devPrivates[g_rdpGCIndex].ptr; \
+ oldFuncs = _pGC->funcs; \
+ (_pGC)->funcs = priv->funcs; \
+ (_pGC)->ops = priv->ops; \
+}
+
+/******************************************************************************/
+#define GC_OP_EPILOGUE(_pGC) \
+{ \
+ priv->ops = (_pGC)->ops; \
+ (_pGC)->funcs = oldFuncs; \
+ (_pGC)->ops = &g_rdpGCOps; \
+}
+
+/******************************************************************************/
+static void
+rdpFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
+ DDXPointPtr pptInit, int* pwidthInit, int fSorted)
+{
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ int cd;
+ int j;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpFillSpans\n"));
+ GC_OP_PROLOGUE(pGC)
+ pGC->ops->FillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+ miRegionInit(&clip_reg, NullBox, 0);
+ cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
+ if (cd == 1)
+ {
+ rdpup_begin_update();
+ miRegionCopy(&clip_reg, &(((WindowPtr)pDrawable)->borderClip));
+ for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ else if (cd == 2)
+ {
+ rdpup_begin_update();
+ miIntersect(&clip_reg, &clip_reg,
+ &(((WindowPtr)pDrawable)->borderClip));
+ for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionUninit(&clip_reg);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpSetSpans(DrawablePtr pDrawable, GCPtr pGC, char* psrc,
+ DDXPointPtr ppt, int* pwidth, int nspans, int fSorted)
+{
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ int cd;
+ int j;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpSetSpans\n"));
+ GC_OP_PROLOGUE(pGC);
+ pGC->ops->SetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
+ miRegionInit(&clip_reg, NullBox, 0);
+ cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
+ if (cd == 1)
+ {
+ rdpup_begin_update();
+ miRegionCopy(&clip_reg, &(((WindowPtr)pDrawable)->borderClip));
+ for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ else if (cd == 2)
+ {
+ rdpup_begin_update();
+ miIntersect(&clip_reg, &clip_reg,
+ &((WindowPtr)pDrawable)->borderClip);
+ for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionUninit(&clip_reg);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
+ int w, int h, int leftPad, int format, char* pBits)
+{
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ int cd;
+ int j;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpPutImage\n"));
+ GC_OP_PROLOGUE(pGC);
+ pGC->ops->PutImage(pDrawable, pGC, depth, x, y, w, h, leftPad,
+ format, pBits);
+ miRegionInit(&clip_reg, NullBox, 0);
+ cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
+ if (cd == 1)
+ {
+ rdpup_begin_update();
+ rdpup_send_area(pDrawable->x + x, pDrawable->y + y, w, h);
+ rdpup_end_update();
+ }
+ else if (cd == 2)
+ {
+ rdpup_begin_update();
+ for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_set_clip(box.x1, box.y1, (box.x2 - box.x1), (box.y2 - box.y1));
+ rdpup_send_area(pDrawable->x + x, pDrawable->y + y, w, h);
+ }
+ rdpup_reset_clip();
+ rdpup_end_update();
+ }
+ miRegionUninit(&clip_reg);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static RegionPtr
+rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h, int dstx, int dsty)
+{
+ rdpGCPtr priv;
+ RegionPtr rv;
+ RegionRec clip_reg;
+ RegionRec box_reg;
+ int num_clips;
+ int cd;
+ int j;
+ int can_do_screen_blt;
+ int dx;
+ int dy;
+ BoxRec box;
+ BoxPtr pbox;
+ GCFuncs* oldFuncs;
+
+ DEBUG_OUT_OPS(("in rdpCopyArea\n"));
+ GC_OP_PROLOGUE(pGC);
+ rv = pGC->ops->CopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
+ miRegionInit(&clip_reg, NullBox, 0);
+ cd = rdp_get_clip(&clip_reg, pDst, pGC);
+ can_do_screen_blt = pSrc->type == DRAWABLE_WINDOW &&
+ ((WindowPtr)pSrc)->viewable &&
+ pGC->alu == GXcopy;
+ if (cd == 1)
+ {
+ rdpup_begin_update();
+ if (can_do_screen_blt)
+ {
+ rdpup_screen_blt(pDst->x + dstx, pDst->y + dsty, w, h,
+ pSrc->x + srcx, pSrc->y + srcy);
+ }
+ else
+ {
+ rdpup_send_area(pDst->x + dstx, pDst->y + dsty, w, h);
+ }
+ rdpup_end_update();
+ }
+ else if (cd == 2)
+ {
+ num_clips = REGION_NUM_RECTS(&clip_reg);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ if (can_do_screen_blt)
+ {
+ dx = dstx - srcx;
+ dy = dsty - srcy;
+ if (dy < 0 || (dy == 0 && dx < 0))
+ {
+ for (j = 0; j < num_clips; j++)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_screen_blt(pDst->x + dstx, pDst->y + dsty, w, h,
+ pSrc->x + srcx, pSrc->y + srcy);
+ }
+ }
+ else
+ {
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_screen_blt(pDst->x + dstx, pDst->y + dsty, w, h,
+ pSrc->x + srcx, pSrc->y + srcy);
+ }
+ }
+ rdpup_reset_clip();
+ }
+ else
+ {
+ box.x1 = pDst->x + dstx;
+ box.y1 = pDst->y + dsty;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+ miRegionInit(&box_reg, &box, 0);
+ miIntersect(&clip_reg, &clip_reg, &box_reg);
+ num_clips = REGION_NUM_RECTS(&clip_reg);
+ if (num_clips < 10)
+ {
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ }
+ else
+ {
+ pbox = miRegionExtents(&clip_reg);
+ rdpup_send_area(pbox->x1, pbox->y1, pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ }
+ miRegionUninit(&box_reg);
+ }
+ rdpup_end_update();
+ }
+ }
+ miRegionUninit(&clip_reg);
+ GC_OP_EPILOGUE(pGC);
+ return rv;
+}
+
+/******************************************************************************/
+static RegionPtr
+rdpCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width, int height,
+ int dstx, int dsty, unsigned long bitPlane)
+{
+ rdpGCPtr priv;
+ RegionPtr rv;
+ RegionRec reg;
+ int cd;
+ GCFuncs* oldFuncs;
+
+ DEBUG_OUT_OPS(("in rdpCopyPlane\n"));
+ GC_OP_PROLOGUE(pGC);
+ rv = pGC->ops->CopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
+ width, height, dstx, dsty, bitPlane);
+ miRegionInit(&reg, NullBox, 0);
+ cd = rdp_get_clip(&reg, pDstDrawable, pGC);
+ if (cd == 1)
+ {
+ }
+ else if (cd == 2)
+ {
+ }
+ miRegionUninit(&reg);
+ GC_OP_EPILOGUE(pGC);
+ return rv;
+}
+
+/******************************************************************************/
+static void
+rdpPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int npt, DDXPointPtr in_pts)
+{
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ int num_clips;
+ int cd;
+ int x;
+ int y;
+ int i;
+ int j;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+ BoxRec total_box;
+ DDXPointPtr pts;
+ DDXPointRec stack_pts[32];
+
+ DEBUG_OUT_OPS(("in rdpPolyPoint\n"));
+ GC_OP_PROLOGUE(pGC);
+ if (npt > 32)
+ {
+ pts = (DDXPointPtr)Xalloc(sizeof(DDXPointRec) * npt);
+ }
+ else
+ {
+ pts = stack_pts;
+ }
+ for (i = 0; i < npt; i++)
+ {
+ pts[i].x = pDrawable->x + in_pts[i].x;
+ pts[i].y = pDrawable->y + in_pts[i].y;
+ if (i == 0)
+ {
+ total_box.x1 = pts[0].x;
+ total_box.y1 = pts[0].y;
+ total_box.x2 = pts[0].x;
+ total_box.y2 = pts[0].y;
+ }
+ else
+ {
+ if (pts[i].x < total_box.x1)
+ {
+ total_box.x1 = pts[i].x;
+ }
+ if (pts[i].y < total_box.y1)
+ {
+ total_box.y1 = pts[i].y;
+ }
+ if (pts[i].x > total_box.x2)
+ {
+ total_box.x2 = pts[i].x;
+ }
+ if (pts[i].y > total_box.y2)
+ {
+ total_box.y2 = pts[i].y;
+ }
+ }
+ /* todo, use this total_box */
+ }
+ pGC->ops->PolyPoint(pDrawable, pGC, mode, npt, in_pts);
+ miRegionInit(&clip_reg, NullBox, 0);
+ cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
+ if (cd == 1)
+ {
+ if (npt > 0)
+ {
+ rdpup_begin_update();
+ rdpup_set_fgcolor(pGC->fgPixel);
+ for (i = 0; i < npt; i++)
+ {
+ x = pts[i].x;
+ y = pts[i].y;
+ rdpup_fill_rect(x, y, 1, 1);
+ }
+ rdpup_end_update();
+ }
+ }
+ else if (cd == 2)
+ {
+ num_clips = REGION_NUM_RECTS(&clip_reg);
+ if (npt > 0 && num_clips > 0)
+ {
+ rdpup_begin_update();
+ rdpup_set_fgcolor(pGC->fgPixel);
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ for (i = 0; i < npt; i++)
+ {
+ x = pts[i].x;
+ y = pts[i].y;
+ rdpup_fill_rect(x, y, 1, 1);
+ }
+ }
+ rdpup_reset_clip();
+ rdpup_end_update();
+ }
+ }
+ miRegionUninit(&clip_reg);
+ if (pts != stack_pts)
+ {
+ Xfree(pts);
+ }
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int npt, DDXPointPtr pptInit)
+{
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ int num_clips;
+ int cd;
+ int i;
+ int j;
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+ DDXPointPtr ppts;
+
+ DEBUG_OUT_OPS(("in rdpPolylines\n"));
+ GC_OP_PROLOGUE(pGC);
+ ppts = 0;
+ if (npt > 0)
+ {
+ ppts = (DDXPointPtr)Xalloc(sizeof(DDXPointRec) * npt);
+ for (i = 0; i < npt; i++)
+ {
+ ppts[i] = pptInit[i];
+ }
+ }
+ pGC->ops->Polylines(pDrawable, pGC, mode, npt, pptInit);
+ miRegionInit(&clip_reg, NullBox, 0);
+ cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
+ if (cd == 1)
+ {
+ if (ppts != 0)
+ {
+ rdpup_begin_update();
+ rdpup_set_fgcolor(pGC->fgPixel);
+ rdpup_set_opcode(pGC->alu);
+ rdpup_set_pen(0, pGC->lineWidth);
+ x1 = ppts[0].x + pDrawable->x;
+ y1 = ppts[0].y + pDrawable->y;
+ for (i = 1; i < npt; i++)
+ {
+ if (mode == CoordModeOrigin)
+ {
+ x2 = pDrawable->x + ppts[i].x;
+ y2 = pDrawable->y + ppts[i].y;
+ }
+ else
+ {
+ x2 = x1 + ppts[i].x;
+ y2 = y1 + ppts[i].y;
+ }
+ rdpup_draw_line(x1, y1, x2, y2);
+ x1 = x2;
+ y1 = y2;
+ }
+ rdpup_set_opcode(GXcopy);
+ rdpup_end_update();
+ }
+ }
+ else if (cd == 2)
+ {
+ num_clips = REGION_NUM_RECTS(&clip_reg);
+ if (ppts != 0 && num_clips > 0)
+ {
+ rdpup_begin_update();
+ rdpup_set_fgcolor(pGC->fgPixel);
+ rdpup_set_opcode(pGC->alu);
+ rdpup_set_pen(0, pGC->lineWidth);
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ x1 = ppts[0].x + pDrawable->x;
+ y1 = ppts[0].y + pDrawable->y;
+ for (i = 1; i < npt; i++)
+ {
+ if (mode == CoordModeOrigin)
+ {
+ x2 = pDrawable->x + ppts[i].x;
+ y2 = pDrawable->y + ppts[i].y;
+ }
+ else
+ {
+ x2 = x1 + ppts[i].x;
+ y2 = y1 + ppts[i].y;
+ }
+ rdpup_draw_line(x1, y1, x2, y2);
+ x1 = x2;
+ y1 = y2;
+ }
+ }
+ rdpup_reset_clip();
+ rdpup_set_opcode(GXcopy);
+ rdpup_end_update();
+ }
+ }
+ miRegionUninit(&clip_reg);
+ Xfree(ppts);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment* pSegs)
+{
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ int cd;
+ int i;
+ int j;
+ GCFuncs* oldFuncs;
+ xSegment* segs;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpPolySegment\n"));
+ GC_OP_PROLOGUE(pGC);
+ segs = 0;
+ if (nseg) /* get the rects */
+ {
+ segs = (xSegment*)Xalloc(nseg * sizeof(xSegment));
+ for (i = 0; i < nseg; i++)
+ {
+ segs[i].x1 = pSegs[i].x1 + pDrawable->x;
+ segs[i].y1 = pSegs[i].y1 + pDrawable->y;
+ segs[i].x2 = pSegs[i].x2 + pDrawable->x;
+ segs[i].y2 = pSegs[i].y2 + pDrawable->y;
+ }
+ }
+ pGC->ops->PolySegment(pDrawable, pGC, nseg, pSegs);
+ miRegionInit(&clip_reg, NullBox, 0);
+ cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
+ if (cd == 1) /* no clip */
+ {
+ if (segs != 0)
+ {
+ rdpup_begin_update();
+ rdpup_set_fgcolor(pGC->fgPixel);
+ rdpup_set_opcode(pGC->alu);
+ rdpup_set_pen(0, pGC->lineWidth);
+ for (i = 0; i < nseg; i++)
+ {
+ rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2);
+ }
+ rdpup_set_opcode(GXcopy);
+ rdpup_end_update();
+ }
+ }
+ else if (cd == 2) /* clip */
+ {
+ if (segs != 0)
+ {
+ rdpup_begin_update();
+ rdpup_set_fgcolor(pGC->fgPixel);
+ rdpup_set_opcode(pGC->alu);
+ rdpup_set_pen(0, pGC->lineWidth);
+ for (j = REGION_NUM_RECTS(&clip_reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ for (i = 0; i < nseg; i++)
+ {
+ rdpup_draw_line(segs[i].x1, segs[i].y1, segs[i].x2, segs[i].y2);
+ }
+ }
+ rdpup_reset_clip();
+ rdpup_set_opcode(GXcopy);
+ rdpup_end_update();
+ }
+ }
+ Xfree(segs);
+ miRegionUninit(&clip_reg);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+/* tested with pGC->lineWidth = 0, 1, 2, 4 and opcodes 3 and 6 */
+static void
+rdpPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
+ xRectangle* rects)
+{
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ RegionPtr fill_reg;
+ int num_clips;
+ int cd;
+ int lw;
+ int i;
+ int j;
+ int up;
+ int down;
+ GCFuncs* oldFuncs;
+ xRectangle* regRects;
+ xRectangle* r;
+ xRectangle* rect1;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpPolyRectangle\n"));
+ GC_OP_PROLOGUE(pGC);
+ /* make a copy of rects */
+ rect1 = (xRectangle*)Xalloc(sizeof(xRectangle) * nrects);
+ for (i = 0; i < nrects; i++)
+ {
+ rect1[i] = rects[i];
+ }
+ pGC->ops->PolyRectangle(pDrawable, pGC, nrects, rects);
+ miRegionInit(&clip_reg, NullBox, 0);
+ cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
+ regRects = 0;
+ if (cd != 0 && nrects > 0)
+ {
+ regRects = (xRectangle*)Xalloc(nrects * 4 * sizeof(xRectangle));
+ lw = pGC->lineWidth;
+ if (lw < 1)
+ {
+ lw = 1;
+ }
+ up = lw / 2;
+ down = 1 + (lw - 1) / 2;
+ for (i = 0; i < nrects; i++)
+ {
+ r = regRects + i * 4;
+ r->x = (rect1[i].x + pDrawable->x) - up;
+ r->y = (rect1[i].y + pDrawable->y) - up;
+ r->width = rect1[i].width + up + down;
+ r->height = lw;
+ r++;
+ r->x = (rect1[i].x + pDrawable->x) - up;
+ r->y = (rect1[i].y + pDrawable->y) + down;
+ r->width = lw;
+ r->height = MAX(rect1[i].height - (up + down), 0);
+ r++;
+ r->x = ((rect1[i].x + rect1[i].width) + pDrawable->x) - up;
+ r->y = (rect1[i].y + pDrawable->y) + down;
+ r->width = lw;
+ r->height = MAX(rect1[i].height - (up + down), 0);
+ r++;
+ r->x = (rect1[i].x + pDrawable->x) - up;
+ r->y = ((rect1[i].y + rect1[i].height) + pDrawable->y) - up;
+ r->width = rect1[i].width + up + down;
+ r->height = lw;
+ }
+ }
+ if (cd == 1)
+ {
+ if (regRects != 0)
+ {
+ rdpup_begin_update();
+ if (pGC->lineStyle == LineSolid)
+ {
+ rdpup_set_fgcolor(pGC->fgPixel);
+ rdpup_set_opcode(pGC->alu);
+ for (i = 0; i < nrects * 4; i++)
+ {
+ r = regRects + i;
+ rdpup_fill_rect(r->x, r->y, r->width, r->height);
+ }
+ rdpup_set_opcode(GXcopy);
+ }
+ else
+ {
+ for (i = 0; i < nrects * 4; i++)
+ {
+ r = regRects + i;
+ rdpup_send_area(r->x, r->y, r->width, r->height);
+ }
+ }
+ rdpup_end_update();
+ }
+ }
+ else if (cd == 2)
+ {
+ if (regRects != 0)
+ {
+ fill_reg = miRectsToRegion(nrects * 4, regRects, CT_NONE);
+ miIntersect(&clip_reg, &clip_reg, fill_reg);
+ num_clips = REGION_NUM_RECTS(&clip_reg);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ if (pGC->lineStyle == LineSolid)
+ {
+ rdpup_set_fgcolor(pGC->fgPixel);
+ rdpup_set_opcode(pGC->alu);
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_set_opcode(GXcopy);
+ }
+ else
+ {
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ }
+ rdpup_end_update();
+ }
+ miRegionDestroy(fill_reg);
+ }
+ }
+ miRegionUninit(&clip_reg);
+ Xfree(regRects);
+ Xfree(rect1);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs)
+{
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ RegionPtr tmpRegion;
+ int cd;
+ int lw;
+ int extra;
+ int i;
+ int num_clips;
+ GCFuncs* oldFuncs;
+ xRectangle* rects;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpPolyArc\n"));
+ GC_OP_PROLOGUE(pGC);
+ rects = 0;
+ if (narcs > 0)
+ {
+ rects = (xRectangle*)Xalloc(narcs * sizeof(xRectangle));
+ lw = pGC->lineWidth;
+ if (lw == 0)
+ {
+ lw = 1;
+ }
+ extra = lw / 2;
+ for (i = 0; i < narcs; i++)
+ {
+ rects[i].x = (parcs[i].x - extra) + pDrawable->x;
+ rects[i].y = (parcs[i].y - extra) + pDrawable->y;
+ rects[i].width = parcs[i].width + lw;
+ rects[i].height = parcs[i].height + lw;
+ }
+ }
+ pGC->ops->PolyArc(pDrawable, pGC, narcs, parcs);
+ miRegionInit(&clip_reg, NullBox, 0);
+ cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
+ if (cd == 1)
+ {
+ if (rects != 0)
+ {
+ tmpRegion = miRectsToRegion(narcs, rects, CT_NONE);
+ num_clips = REGION_NUM_RECTS(tmpRegion);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ for (i = num_clips - 1; i >= 0; i--)
+ {
+ box = REGION_RECTS(tmpRegion)[i];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionDestroy(tmpRegion);
+ }
+ }
+ else if (cd == 2)
+ {
+ if (rects != 0)
+ {
+ tmpRegion = miRectsToRegion(narcs, rects, CT_NONE);
+ miIntersect(tmpRegion, tmpRegion, &clip_reg);
+ num_clips = REGION_NUM_RECTS(tmpRegion);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ for (i = num_clips - 1; i >= 0; i--)
+ {
+ box = REGION_RECTS(tmpRegion)[i];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionDestroy(tmpRegion);
+ }
+ }
+ miRegionUninit(&clip_reg);
+ Xfree(rects);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
+ int shape, int mode, int count,
+ DDXPointPtr pPts)
+{
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ RegionRec box_reg;
+ int num_clips;
+ int cd;
+ int maxx;
+ int maxy;
+ int minx;
+ int miny;
+ int i;
+ int j;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpFillPolygon\n"));
+ GC_OP_PROLOGUE(pGC);
+ pGC->ops->FillPolygon(pDrawable, pGC, shape, mode, count, pPts);
+ miRegionInit(&clip_reg, NullBox, 0);
+ cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
+ if (cd != 0)
+ {
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = 0;
+ box.y2 = 0;
+ if (count > 0)
+ {
+ maxx = pPts[0].x;
+ maxy = pPts[0].y;
+ minx = maxx;
+ miny = maxy;
+ for (i = 1; i < count; i++)
+ {
+ if (pPts[i].x > maxx)
+ {
+ maxx = pPts[i].x;
+ }
+ if (pPts[i].x < minx)
+ {
+ minx = pPts[i].x;
+ }
+ if (pPts[i].y > maxy)
+ {
+ maxy = pPts[i].y;
+ }
+ if (pPts[i].y < miny)
+ {
+ miny = pPts[i].y;
+ }
+ box.x1 = pDrawable->x + minx;
+ box.y1 = pDrawable->y + miny;
+ box.x2 = pDrawable->x + maxx + 1;
+ box.y2 = pDrawable->y + maxy + 1;
+ }
+ }
+ }
+ if (cd == 1)
+ {
+ rdpup_begin_update();
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_end_update();
+ }
+ else if (cd == 2)
+ {
+ miRegionInit(&box_reg, &box, 0);
+ miIntersect(&clip_reg, &clip_reg, &box_reg);
+ num_clips = REGION_NUM_RECTS(&clip_reg);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionUninit(&box_reg);
+ }
+ miRegionUninit(&clip_reg);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrectFill,
+ xRectangle* prectInit)
+{
+ int i;
+ int j;
+ int cd;
+ int num_clips;
+ xRectangle* copy_of_rects;
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ RegionPtr fill_reg;
+ BoxRec box;
+ GCFuncs* oldFuncs;
+
+ DEBUG_OUT_OPS(("in rdpPolyFillRect\n"));
+ GC_OP_PROLOGUE(pGC);
+ /* make a copy of rects */
+ copy_of_rects = (xRectangle*)Xalloc(sizeof(xRectangle) * nrectFill);
+ for (i = 0; i < nrectFill; i++)
+ {
+ copy_of_rects[i] = prectInit[i];
+ }
+ fill_reg = miRectsToRegion(nrectFill, copy_of_rects, CT_NONE);
+ Xfree(copy_of_rects);
+ miTranslateRegion(fill_reg, pDrawable->x, pDrawable->y);
+ pGC->ops->PolyFillRect(pDrawable, pGC, nrectFill, prectInit);
+ miRegionInit(&clip_reg, NullBox, 0);
+ cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
+ if (cd == 1) /* no clip */
+ {
+ rdpup_begin_update();
+ if (pGC->fillStyle == 0 && /* solid fill */
+ (pGC->alu == GXclear ||
+ pGC->alu == GXset ||
+ pGC->alu == GXinvert ||
+ pGC->alu == GXnoop ||
+ pGC->alu == GXand ||
+ pGC->alu == GXcopy /*||
+ pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */
+ {
+ rdpup_set_fgcolor(pGC->fgPixel);
+ rdpup_set_opcode(pGC->alu);
+ for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(fill_reg)[j];
+ rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_set_opcode(GXcopy);
+ }
+ else /* non solid fill */
+ {
+ for (j = REGION_NUM_RECTS(fill_reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(fill_reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ }
+ rdpup_end_update();
+ }
+ else if (cd == 2) /* clip */
+ {
+ miIntersect(&clip_reg, &clip_reg, fill_reg);
+ num_clips = REGION_NUM_RECTS(&clip_reg);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ if (pGC->fillStyle == 0 && /* solid fill */
+ (pGC->alu == GXclear ||
+ pGC->alu == GXset ||
+ pGC->alu == GXinvert ||
+ pGC->alu == GXnoop ||
+ pGC->alu == GXand ||
+ pGC->alu == GXcopy /*||
+ pGC->alu == GXxor*/)) /* todo, why dosen't xor work? */
+ {
+ rdpup_set_fgcolor(pGC->fgPixel);
+ rdpup_set_opcode(pGC->alu);
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_set_opcode(GXcopy);
+ }
+ else /* non solid fill */
+ {
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ }
+ rdpup_end_update();
+ }
+ }
+ miRegionUninit(&clip_reg);
+ miRegionDestroy(fill_reg);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc* parcs)
+{
+ rdpGCPtr priv;
+ RegionRec reg;
+ int cd;
+ GCFuncs* oldFuncs;
+
+ DEBUG_OUT_OPS(("in rdpPolyFillArc\n"));
+ GC_OP_PROLOGUE(pGC);
+ pGC->ops->PolyFillArc(pDrawable, pGC, narcs, parcs);
+ miRegionInit(&reg, NullBox, 0);
+ cd = rdp_get_clip(&reg, pDrawable, pGC);
+ if (cd == 1)
+ {
+ }
+ else if (cd == 2)
+ {
+ }
+ miRegionUninit(&reg);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static int
+rdpPolyText8(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, int count, char* chars)
+{
+ rdpGCPtr priv;
+ RegionRec reg;
+ RegionRec reg1;
+ int num_clips;
+ int cd;
+ int j;
+ int rv;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpPolyText8\n"));
+ GC_OP_PROLOGUE(pGC);
+ if (count != 0)
+ {
+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box);
+ }
+ rv = pGC->ops->PolyText8(pDrawable, pGC, x, y, count, chars);
+ miRegionInit(&reg, NullBox, 0);
+ if (count == 0)
+ {
+ cd = 0;
+ }
+ else
+ {
+ cd = rdp_get_clip(&reg, pDrawable, pGC);
+ }
+ if (cd == 1)
+ {
+ rdpup_begin_update();
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_end_update();
+ }
+ else if (cd == 2)
+ {
+ miRegionInit(&reg1, &box, 0);
+ miIntersect(&reg, &reg, &reg1);
+ num_clips = REGION_NUM_RECTS(&reg);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionUninit(&reg1);
+ }
+ miRegionUninit(&reg);
+ GC_OP_EPILOGUE(pGC);
+ return rv;
+}
+
+/******************************************************************************/
+static int
+rdpPolyText16(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, int count, unsigned short* chars)
+{
+ rdpGCPtr priv;
+ RegionRec reg;
+ RegionRec reg1;
+ int num_clips;
+ int cd;
+ int j;
+ int rv;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpPolyText16\n"));
+ GC_OP_PROLOGUE(pGC);
+ if (count != 0)
+ {
+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box);
+ }
+ rv = pGC->ops->PolyText16(pDrawable, pGC, x, y, count, chars);
+ miRegionInit(&reg, NullBox, 0);
+ if (count == 0)
+ {
+ cd = 0;
+ }
+ else
+ {
+ cd = rdp_get_clip(&reg, pDrawable, pGC);
+ }
+ if (cd == 1)
+ {
+ rdpup_begin_update();
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_end_update();
+ }
+ else if (cd == 2)
+ {
+ miRegionInit(&reg1, &box, 0);
+ miIntersect(&reg, &reg, &reg1);
+ num_clips = REGION_NUM_RECTS(&reg);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionUninit(&reg1);
+ }
+ miRegionUninit(&reg);
+ GC_OP_EPILOGUE(pGC);
+ return rv;
+}
+
+/******************************************************************************/
+static void
+rdpImageText8(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, int count, char* chars)
+{
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ RegionRec box_reg;
+ int num_clips;
+ int cd;
+ int j;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpImageText8\n"));
+ GC_OP_PROLOGUE(pGC);
+ if (count != 0)
+ {
+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box);
+ }
+ pGC->ops->ImageText8(pDrawable, pGC, x, y, count, chars);
+ miRegionInit(&clip_reg, NullBox, 0);
+ if (count == 0)
+ {
+ cd = 0;
+ }
+ else
+ {
+ cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
+ }
+ if (cd == 1)
+ {
+ rdpup_begin_update();
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_end_update();
+ }
+ else if (cd == 2)
+ {
+ miRegionInit(&box_reg, &box, 0);
+ miIntersect(&clip_reg, &clip_reg, &box_reg);
+ num_clips = REGION_NUM_RECTS(&clip_reg);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionUninit(&box_reg);
+ }
+ miRegionUninit(&clip_reg);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpImageText16(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, int count,
+ unsigned short* chars)
+{
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ RegionRec box_reg;
+ int num_clips;
+ int cd;
+ int j;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpImageText16\n"));
+ GC_OP_PROLOGUE(pGC);
+ if (count != 0)
+ {
+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box);
+ }
+ pGC->ops->ImageText16(pDrawable, pGC, x, y, count, chars);
+ miRegionInit(&clip_reg, NullBox, 0);
+ if (count == 0)
+ {
+ cd = 0;
+ }
+ else
+ {
+ cd = rdp_get_clip(&clip_reg, pDrawable, pGC);
+ }
+ if (cd == 1)
+ {
+ rdpup_begin_update();
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_end_update();
+ }
+ else if (cd == 2)
+ {
+ miRegionInit(&box_reg, &box, 0);
+ miIntersect(&clip_reg, &clip_reg, &box_reg);
+ num_clips = REGION_NUM_RECTS(&clip_reg);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionUninit(&box_reg);
+ }
+ miRegionUninit(&clip_reg);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr* ppci, pointer pglyphBase)
+{
+ rdpGCPtr priv;
+ RegionRec reg;
+ RegionRec box_reg;
+ int num_clips;
+ int cd;
+ int j;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpImageGlyphBlt\n"));
+ GC_OP_PROLOGUE(pGC);
+ if (nglyph != 0)
+ {
+ GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box);
+ }
+ pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ miRegionInit(&reg, NullBox, 0);
+ if (nglyph == 0)
+ {
+ cd = 0;
+ }
+ else
+ {
+ cd = rdp_get_clip(&reg, pDrawable, pGC);
+ }
+ if (cd == 1)
+ {
+ rdpup_begin_update();
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_end_update();
+ }
+ else if (cd == 2)
+ {
+ miRegionInit(&box_reg, &box, 0);
+ miIntersect(&reg, &reg, &box_reg);
+ num_clips = REGION_NUM_RECTS(&reg);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionUninit(&box_reg);
+ }
+ miRegionUninit(&reg);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr* ppci,
+ pointer pglyphBase)
+{
+ rdpGCPtr priv;
+ RegionRec reg;
+ RegionRec box_reg;
+ int num_clips;
+ int cd;
+ int j;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpPolyGlyphBlt\n"));
+ GC_OP_PROLOGUE(pGC);
+ if (nglyph != 0)
+ {
+ GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box);
+ }
+ pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ miRegionInit(&reg, NullBox, 0);
+ if (nglyph == 0)
+ {
+ cd = 0;
+ }
+ else
+ {
+ cd = rdp_get_clip(&reg, pDrawable, pGC);
+ }
+ if (cd == 1)
+ {
+ rdpup_begin_update();
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_end_update();
+ }
+ else if (cd == 2)
+ {
+ miRegionInit(&box_reg, &box, 0);
+ miIntersect(&reg, &reg, &box_reg);
+ num_clips = REGION_NUM_RECTS(&reg);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionUninit(&box_reg);
+ }
+ miRegionUninit(&reg);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+static void
+rdpPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
+ int w, int h, int x, int y)
+{
+ rdpGCPtr priv;
+ RegionRec clip_reg;
+ RegionRec box_reg;
+ int num_clips;
+ int cd;
+ int j;
+ GCFuncs* oldFuncs;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpPushPixels\n"));
+ GC_OP_PROLOGUE(pGC);
+ pGC->ops->PushPixels(pGC, pBitMap, pDst, w, h, x, y);
+ miRegionInit(&clip_reg, NullBox, 0);
+ cd = rdp_get_clip(&clip_reg, pDst, pGC);
+ if (cd == 1)
+ {
+ rdpup_begin_update();
+ rdpup_send_area(x, y, w, h);
+ rdpup_end_update();
+ }
+ else if (cd == 2)
+ {
+ miRegionInit(&box_reg, &box, 0);
+ miIntersect(&clip_reg, &clip_reg, &box_reg);
+ num_clips = REGION_NUM_RECTS(&clip_reg);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&clip_reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionUninit(&box_reg);
+ }
+ miRegionUninit(&clip_reg);
+ GC_OP_EPILOGUE(pGC);
+}
+
+/******************************************************************************/
+Bool
+rdpCloseScreen(int i, ScreenPtr pScreen)
+{
+ DEBUG_OUT_OPS(("in rdpCloseScreen\n"));
+ pScreen->CloseScreen = g_rdpScreen.CloseScreen;
+ pScreen->CreateGC = g_rdpScreen.CreateGC;
+ pScreen->PaintWindowBackground = g_rdpScreen.PaintWindowBackground;
+ pScreen->PaintWindowBorder = g_rdpScreen.PaintWindowBorder;
+ pScreen->CopyWindow = g_rdpScreen.CopyWindow;
+ pScreen->ClearToBackground = g_rdpScreen.ClearToBackground;
+ pScreen->RestoreAreas = g_rdpScreen.RestoreAreas;
+ return 1;
+}
+
+/******************************************************************************/
+Bool
+rdpCreateGC(GCPtr pGC)
+{
+ rdpGCRec* priv;
+ Bool rv;
+
+ DEBUG_OUT_OPS(("in rdpCreateGC\n"));
+ rv = 0;
+ if (g_rdpGCIndex != -1)
+ {
+ priv = (rdpGCPtr)pGC->devPrivates[g_rdpGCIndex].ptr;
+ g_pScreen->CreateGC = g_rdpScreen.CreateGC;
+ rv = g_pScreen->CreateGC(pGC);
+ if (rv)
+ {
+ priv->funcs = pGC->funcs;
+ priv->ops = 0;
+ pGC->funcs = &g_rdpGCFuncs;
+ }
+ else
+ {
+ ErrorF("error in rdpCreateGC\n");
+ }
+ g_pScreen->CreateGC = rdpCreateGC;
+ }
+ else
+ {
+ ErrorF("error in rdpCreateGC\n");
+ }
+ return rv;
+}
+
+/******************************************************************************/
+void
+rdpPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ int j;
+ RegionRec reg;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpPaintWindowBackground\n"));
+ miRegionInit(&reg, NullBox, 0);
+ miRegionCopy(&reg, pRegion);
+ g_pScreen->PaintWindowBackground = g_rdpScreen.PaintWindowBackground;
+ g_pScreen->PaintWindowBackground(pWin, pRegion, what);
+ rdpup_begin_update();
+ if (what == PW_BACKGROUND && pWin->backgroundState == BackgroundPixel)
+ {
+ rdpup_set_fgcolor(pWin->background.pixel);
+ for (j = REGION_NUM_RECTS(&reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg)[j];
+ rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ }
+ else if (what == PW_BORDER && pWin->borderIsPixel)
+ {
+ rdpup_set_fgcolor(pWin->border.pixel);
+ for (j = REGION_NUM_RECTS(&reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg)[j];
+ rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ }
+ else
+ {
+ for (j = REGION_NUM_RECTS(&reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ }
+ rdpup_end_update();
+ miRegionUninit(&reg);
+ g_pScreen->PaintWindowBackground = rdpPaintWindowBackground;
+}
+
+/******************************************************************************/
+void
+rdpPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ int j;
+ RegionRec reg;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpPaintWindowBorder\n"));
+ miRegionInit(&reg, NullBox, 0);
+ miRegionCopy(&reg, pRegion);
+ g_pScreen->PaintWindowBackground = g_rdpScreen.PaintWindowBackground;
+ g_pScreen->PaintWindowBackground(pWin, pRegion, what);
+ rdpup_begin_update();
+ if (what == PW_BACKGROUND && pWin->backgroundState == BackgroundPixel)
+ {
+ rdpup_set_fgcolor(pWin->background.pixel);
+ for (j = REGION_NUM_RECTS(&reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg)[j];
+ rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ }
+ else if (what == PW_BORDER && pWin->borderIsPixel)
+ {
+ rdpup_set_fgcolor(pWin->border.pixel);
+ for (j = REGION_NUM_RECTS(&reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg)[j];
+ rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ }
+ else
+ {
+ for (j = REGION_NUM_RECTS(&reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ }
+ rdpup_end_update();
+ miRegionUninit(&reg);
+ g_pScreen->PaintWindowBackground = rdpPaintWindowBackground;
+}
+
+/******************************************************************************/
+void
+rdpCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion)
+{
+ RegionRec reg;
+ RegionRec clip;
+ int dx;
+ int dy;
+ int i;
+ int j;
+ int num_clip_rects;
+ int num_reg_rects;
+ BoxRec box1;
+ BoxRec box2;
+
+ DEBUG_OUT_OPS(("in rdpCopyWindow\n"));
+ miRegionInit(&reg, NullBox, 0);
+ miRegionCopy(&reg, pOldRegion);
+ g_pScreen->CopyWindow = g_rdpScreen.CopyWindow;
+ g_pScreen->CopyWindow(pWin, ptOldOrg, pOldRegion);
+ miRegionInit(&clip, NullBox, 0);
+ miRegionCopy(&clip, &pWin->borderClip);
+ dx = pWin->drawable.x - ptOldOrg.x;
+ dy = pWin->drawable.y - ptOldOrg.y;
+ rdpup_begin_update();
+ num_clip_rects = REGION_NUM_RECTS(&clip);
+ num_reg_rects = REGION_NUM_RECTS(&reg);
+ /* should maybe sort the rects instead of checking dy < 0 */
+ /* If we can depend on the rects going from top to bottom, left
+ to right we are ok */
+ if (dy < 0 || (dy == 0 && dx < 0))
+ {
+ for (j = 0; j < num_clip_rects; j++)
+ {
+ box1 = REGION_RECTS(&clip)[j];
+ rdpup_set_clip(box1.x1, box1.y1, box1.x2 - box1.x1, box1.y2 - box1.y1);
+ for (i = 0; i < num_reg_rects; i++)
+ {
+ box2 = REGION_RECTS(&reg)[i];
+ rdpup_screen_blt(box2.x1 + dx, box2.y1 + dy, box2.x2 - box2.x1,
+ box2.y2 - box2.y1, box2.x1, box2.y1);
+ }
+ }
+ }
+ else
+ {
+ for (j = num_clip_rects - 1; j >= 0; j--)
+ {
+ box1 = REGION_RECTS(&clip)[j];
+ rdpup_set_clip(box1.x1, box1.y1, box1.x2 - box1.x1, box1.y2 - box1.y1);
+ for (i = num_reg_rects - 1; i >= 0; i--)
+ {
+ box2 = REGION_RECTS(&reg)[i];
+ rdpup_screen_blt(box2.x1 + dx, box2.y1 + dy, box2.x2 - box2.x1,
+ box2.y2 - box2.y1, box2.x1, box2.y1);
+ }
+ }
+ }
+ rdpup_reset_clip();
+ rdpup_end_update();
+ miRegionUninit(&reg);
+ miRegionUninit(&clip);
+ g_pScreen->CopyWindow = rdpCopyWindow;
+}
+
+/******************************************************************************/
+void
+rdpClearToBackground(WindowPtr pWin, int x, int y, int w, int h,
+ Bool generateExposures)
+{
+ int j;
+ BoxRec box;
+ RegionRec reg;
+
+ DEBUG_OUT_OPS(("in rdpClearToBackground\n"));
+ g_pScreen->ClearToBackground = g_rdpScreen.ClearToBackground;
+ g_pScreen->ClearToBackground(pWin, x, y, w, h, generateExposures);
+ if (!generateExposures)
+ {
+ if (w > 0 && h > 0)
+ {
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+ }
+ else
+ {
+ box.x1 = pWin->drawable.x;
+ box.y1 = pWin->drawable.y;
+ box.x2 = box.x1 + pWin->drawable.width;
+ box.y2 = box.y1 + pWin->drawable.height;
+ }
+ miRegionInit(&reg, &box, 0);
+ miIntersect(&reg, &reg, &pWin->clipList);
+ rdpup_begin_update();
+ for (j = REGION_NUM_RECTS(&reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ miRegionUninit(&reg);
+ }
+ g_pScreen->ClearToBackground = rdpClearToBackground;
+}
+
+/******************************************************************************/
+RegionPtr
+rdpRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed)
+{
+ RegionRec reg;
+ RegionPtr rv;
+ int j;
+ BoxRec box;
+
+ DEBUG_OUT_OPS(("in rdpRestoreAreas\n"));
+ miRegionInit(&reg, NullBox, 0);
+ miRegionCopy(&reg, prgnExposed);
+ g_pScreen->RestoreAreas = g_rdpScreen.RestoreAreas;
+ rv = g_pScreen->RestoreAreas(pWin, prgnExposed);
+ rdpup_begin_update();
+ for (j = REGION_NUM_RECTS(&reg) - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ miRegionUninit(&reg);
+ g_pScreen->RestoreAreas = rdpRestoreAreas;
+ return rv;
+}
+
+/******************************************************************************/
+void
+rdpInstallColormap(ColormapPtr pmap)
+{
+ ColormapPtr oldpmap;
+
+ ErrorF("hi rdpInstallColormap\n");
+ oldpmap = g_rdpInstalledColormap;
+ if (pmap != oldpmap)
+ {
+ if(oldpmap != (ColormapPtr)None)
+ {
+ WalkTree(pmap->pScreen, TellLostMap, (char*)&oldpmap->mid);
+ }
+ /* Install pmap */
+ g_rdpInstalledColormap = pmap;
+ WalkTree(pmap->pScreen, TellGainedMap, (char*)&pmap->mid);
+ /*rfbSetClientColourMaps(0, 0);*/
+ }
+ /*g_rdpScreen.InstallColormap(pmap);*/
+}
+
+/******************************************************************************/
+void
+rdpUninstallColormap(ColormapPtr pmap)
+{
+ ColormapPtr curpmap;
+
+ ErrorF("hi rdpUninstallColormap\n");
+ curpmap = g_rdpInstalledColormap;
+ if (pmap == curpmap)
+ {
+ if (pmap->mid != pmap->pScreen->defColormap)
+ {
+ curpmap = (ColormapPtr)LookupIDByType(pmap->pScreen->defColormap,
+ RT_COLORMAP);
+ pmap->pScreen->InstallColormap(curpmap);
+ }
+ }
+}
+
+/******************************************************************************/
+int
+rdpListInstalledColormaps(ScreenPtr pScreen, Colormap* pmaps)
+{
+ ErrorF("hi rdpListInstalledColormaps\n");
+
+ *pmaps = g_rdpInstalledColormap->mid;
+ return 1;
+}
+
+/******************************************************************************/
+void
+rdpStoreColors(ColormapPtr pmap, int ndef, xColorItem* pdefs)
+{
+ ErrorF("hi rdpStoreColors\n");
+}
+
+/******************************************************************************/
+Bool
+rdpSaveScreen(ScreenPtr pScreen, int on)
+{
+ return 1;
+}
+
+/******************************************************************************/
+/* it looks like all the antialias draws go through here */
+void
+rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
+ INT16 yDst, CARD16 width, CARD16 height)
+{
+ BoxRec box;
+ PictureScreenPtr ps;
+ RegionRec reg1;
+ RegionRec reg2;
+ DrawablePtr p;
+ int j;
+ int num_clips;
+
+ DEBUG_OUT_OPS(("in rdpComposite\n"));
+ ps = GetPictureScreen(g_pScreen);
+ ps->Composite = g_rdpScreen.Composite;
+ ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height);
+ p = pDst->pDrawable;
+ if (p->type == DRAWABLE_WINDOW)
+ {
+ if (pDst->clientClipType == CT_REGION)
+ {
+ box.x1 = p->x + xDst;
+ box.y1 = p->y + yDst;
+ box.x2 = box.x1 + width;
+ box.y2 = box.y1 + height;
+ miRegionInit(&reg1, &box, 0);
+ miRegionInit(&reg2, NullBox, 0);
+ miRegionCopy(&reg2, pDst->clientClip);
+ miTranslateRegion(&reg2, p->x + pDst->clipOrigin.x,
+ p->y + pDst->clipOrigin.y);
+ miIntersect(&reg1, &reg1, &reg2);
+ num_clips = REGION_NUM_RECTS(&reg1);
+ if (num_clips > 0)
+ {
+ rdpup_begin_update();
+ for (j = num_clips - 1; j >= 0; j--)
+ {
+ box = REGION_RECTS(&reg1)[j];
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ }
+ rdpup_end_update();
+ }
+ miRegionUninit(&reg1);
+ miRegionUninit(&reg2);
+ }
+ else
+ {
+ box.x1 = p->x + xDst;
+ box.y1 = p->y + yDst;
+ box.x2 = box.x1 + width;
+ box.y2 = box.y1 + height;
+ rdpup_begin_update();
+ rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
+ rdpup_end_update();
+ }
+ }
+ ps->Composite = rdpComposite;
+}
diff --git a/Xserver/hw/rdp/rdpinput.c b/Xserver/hw/rdp/rdpinput.c
new file mode 100644
index 00000000..ba9fc677
--- /dev/null
+++ b/Xserver/hw/rdp/rdpinput.c
@@ -0,0 +1,999 @@
+/*
+Copyright 2005-2006 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.
+
+keyboard and mouse stuff
+
+*/
+
+#include "rdp.h"
+
+static DeviceIntPtr kbdDevice;
+static int g_old_button_mask = 0;
+extern int g_Bpp; /* from rdpmain.c */
+extern ScreenPtr g_pScreen; /* from rdpmain.c */
+extern rdpScreenInfo rdpScreen; /* from rdpmain.c */
+
+#define CONTROL_L_KEY_CODE MIN_KEY_CODE
+#define CONTROL_R_KEY_CODE (MIN_KEY_CODE + 1)
+#define MIN_KEY_CODE 8
+#define MAX_KEY_CODE 255
+#define NO_OF_KEYS (MAX_KEY_CODE - MIN_KEY_CODE + 1)
+#define GLYPHS_PER_KEY 2
+#define SHIFT_L_KEY_CODE (MIN_KEY_CODE + 2)
+#define SHIFT_R_KEY_CODE (MIN_KEY_CODE + 3)
+#define META_L_KEY_CODE (MIN_KEY_CODE + 4)
+#define META_R_KEY_CODE (MIN_KEY_CODE + 5)
+#define ALT_L_KEY_CODE (MIN_KEY_CODE + 6)
+#define ALT_R_KEY_CODE (MIN_KEY_CODE + 7)
+#define N_PREDEFINED_KEYS (sizeof(kbdMap) / (sizeof(KeySym) * GLYPHS_PER_KEY))
+
+/* Copied from Xvnc/lib/font/util/utilbitmap.c */
+static unsigned char g_reverse_byte[0x100] =
+{
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+
+
+static KeySym kbdMap[] =
+{
+ /* non shift shift index */
+ /* key map */
+ XK_Control_L, NoSymbol, /* 8 */
+ XK_Control_R, NoSymbol, /* 9 */
+ XK_Shift_L, NoSymbol, /* 10 */
+ XK_Shift_R, NoSymbol,
+ XK_Meta_L, NoSymbol,
+ XK_Meta_R, NoSymbol,
+ XK_Alt_L, NoSymbol,
+ XK_Alt_R, NoSymbol,
+ /* Standard US keyboard */
+ XK_space, NoSymbol,
+ XK_0, XK_parenright,
+ XK_1, XK_exclam,
+ XK_2, XK_at,
+ XK_3, XK_numbersign, /* 20 */
+ XK_4, XK_dollar,
+ XK_5, XK_percent,
+ XK_6, XK_asciicircum,
+ XK_7, XK_ampersand,
+ XK_8, XK_asterisk,
+ XK_9, XK_parenleft,
+ XK_minus, XK_underscore,
+ XK_equal, XK_plus,
+ XK_bracketleft, XK_braceleft,
+ XK_bracketright, XK_braceright, /* 30 */
+ XK_semicolon, XK_colon,
+ XK_apostrophe, XK_quotedbl,
+ XK_grave, XK_asciitilde,
+ XK_comma, XK_less,
+ XK_period, XK_greater,
+ XK_slash, XK_question,
+ XK_backslash, XK_bar,
+ XK_a, XK_A,
+ XK_b, XK_B,
+ XK_c, XK_C, /* 40 */
+ XK_d, XK_D,
+ XK_e, XK_E,
+ XK_f, XK_F,
+ XK_g, XK_G,
+ XK_h, XK_H,
+ XK_i, XK_I,
+ XK_j, XK_J,
+ XK_k, XK_K,
+ XK_l, XK_L,
+ XK_m, XK_M, /* 50 */
+ XK_n, XK_N,
+ XK_o, XK_O,
+ XK_p, XK_P,
+ XK_q, XK_Q,
+ XK_r, XK_R,
+ XK_s, XK_S,
+ XK_t, XK_T,
+ XK_u, XK_U,
+ XK_v, XK_V,
+ XK_w, XK_W, /* 60 */
+ XK_x, XK_X,
+ XK_y, XK_Y,
+ XK_z, XK_Z,
+ /* Other useful keys */
+ XK_BackSpace, NoSymbol,
+ XK_Return, NoSymbol,
+ XK_Tab, NoSymbol,
+ XK_Escape, NoSymbol,
+ XK_Delete, NoSymbol,
+ XK_Home, NoSymbol,
+ XK_End, NoSymbol, /* 70 */
+ XK_Page_Up, NoSymbol,
+ XK_Page_Down, NoSymbol,
+ XK_Up, NoSymbol,
+ XK_Down, NoSymbol,
+ XK_Left, NoSymbol,
+ XK_Right, NoSymbol,
+ XK_F1, NoSymbol,
+ XK_F2, NoSymbol,
+ XK_F3, NoSymbol,
+ XK_F4, NoSymbol, /* 80 */
+ XK_F5, NoSymbol,
+ XK_F6, NoSymbol,
+ XK_F7, NoSymbol,
+ XK_F8, NoSymbol,
+ XK_F9, NoSymbol,
+ XK_F10, NoSymbol,
+ XK_F11, NoSymbol,
+ XK_F12, NoSymbol,
+
+ XK_KP_Multiply, NoSymbol, /* 89 */
+ XK_Print, NoSymbol, /* 90 */
+ XK_Caps_Lock, NoSymbol, /* 91 */
+ XK_Num_Lock, NoSymbol, /* 92 */
+ XK_Scroll_Lock, NoSymbol, /* 93 */
+ XK_KP_Home, NoSymbol, /* 94 */
+ XK_KP_7, NoSymbol, /* 95 */
+ XK_KP_Up, NoSymbol, /* 96 */
+ XK_KP_8, NoSymbol, /* 97 */
+ XK_KP_Page_Up, NoSymbol, /* 98 */
+ XK_KP_9, NoSymbol, /* 99 */
+ XK_KP_Subtract, NoSymbol, /* 100 */
+ XK_KP_Left, NoSymbol, /* 101 */
+ XK_KP_4, NoSymbol, /* 102 */
+ XK_KP_5, NoSymbol, /* 103 */
+ XK_KP_Right, NoSymbol, /* 104 */
+ XK_KP_6, NoSymbol, /* 105 */
+ XK_KP_Add, NoSymbol, /* 106 */
+ XK_KP_End, NoSymbol, /* 107 */
+ XK_KP_1, NoSymbol, /* 108 */
+ XK_KP_Down, NoSymbol, /* 109 */
+ XK_KP_2, NoSymbol, /* 110 */
+ XK_KP_Page_Down, NoSymbol, /* 111 */
+ XK_KP_3, NoSymbol, /* 112 */
+ XK_KP_Insert, NoSymbol, /* 113 */
+ XK_KP_0, NoSymbol, /* 114 */
+ XK_Insert, NoSymbol, /* 115 */
+ XK_KP_Delete, NoSymbol, /* 116 */
+ XK_KP_Decimal, NoSymbol /* 117 */
+
+};
+
+/******************************************************************************/
+static void
+rdpSendBell()
+{
+ ErrorF("hi rdpSendBell\n");
+}
+
+/******************************************************************************/
+void
+KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8* pModMap)
+{
+ int i;
+
+ ErrorF("hi KbdDeviceInit\n");
+ kbdDevice = pDevice;
+ for (i = 0; i < MAP_LENGTH; i++)
+ {
+ pModMap[i] = NoSymbol;
+ }
+ pModMap[CONTROL_L_KEY_CODE] = ControlMask;
+ pModMap[CONTROL_R_KEY_CODE] = ControlMask;
+ pModMap[SHIFT_L_KEY_CODE] = ShiftMask;
+ pModMap[SHIFT_R_KEY_CODE] = ShiftMask;
+ pModMap[META_L_KEY_CODE] = Mod4Mask;
+ pModMap[META_R_KEY_CODE] = Mod4Mask;
+ pModMap[ALT_L_KEY_CODE] = Mod1Mask;
+ pModMap[ALT_R_KEY_CODE] = Mod1Mask;
+ pKeySyms->minKeyCode = MIN_KEY_CODE;
+ pKeySyms->maxKeyCode = MAX_KEY_CODE;
+ pKeySyms->mapWidth = GLYPHS_PER_KEY;
+ pKeySyms->map = (KeySym *)Xalloc(sizeof(KeySym) * MAP_LENGTH *
+ GLYPHS_PER_KEY);
+ if (pKeySyms->map == 0)
+ {
+ rdpLog("Xalloc failed\n");
+ exit(1);
+ }
+ for (i = 0; i < MAP_LENGTH * GLYPHS_PER_KEY ; i++)
+ {
+ pKeySyms->map[i] = NoSymbol;
+ }
+ for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++)
+ {
+ pKeySyms->map[i] = kbdMap[i];
+ }
+}
+
+/******************************************************************************/
+void
+KbdDeviceOn(void)
+{
+ ErrorF("hi KbdDeviceOn\n");
+ /*usleep(1000000);*/
+ /*ErrorF("bye KbdDeviceOn\n");*/
+}
+
+/******************************************************************************/
+void
+KbdDeviceOff(void)
+{
+ ErrorF("hi KbdDeviceOff\n");
+}
+
+/******************************************************************************/
+int
+rdpKeybdProc(DeviceIntPtr pDevice, int onoff)
+{
+ KeySymsRec keySyms;
+ CARD8 modMap[MAP_LENGTH];
+ DevicePtr pDev;
+
+ ErrorF("hi rdpKeybdProc\n");
+ pDev = (DevicePtr)pDevice;
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ KbdDeviceInit(pDevice, &keySyms, modMap);
+ InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
+ (BellProcPtr)rdpSendBell,
+ (KbdCtrlProcPtr)NoopDDA);
+ break;
+ case DEVICE_ON:
+ pDev->on = 1;
+ KbdDeviceOn();
+ break;
+ case DEVICE_OFF:
+ pDev->on = 0;
+ KbdDeviceOff();
+ break;
+ case DEVICE_CLOSE:
+ if (pDev->on)
+ {
+ KbdDeviceOff();
+ }
+ break;
+ }
+ return Success;
+}
+
+/******************************************************************************/
+void
+PtrDeviceControl(DevicePtr dev, PtrCtrl* ctrl)
+{
+ ErrorF("hi PtrDeviceControl\n");
+}
+
+/******************************************************************************/
+void
+PtrDeviceInit(void)
+{
+ ErrorF("hi PtrDeviceInit\n");
+}
+
+/******************************************************************************/
+void
+PtrDeviceOn(DeviceIntPtr pDev)
+{
+ ErrorF("hi PtrDeviceOn\n");
+}
+
+/******************************************************************************/
+void
+PtrDeviceOff(void)
+{
+ ErrorF("hi PtrDeviceOff\n");
+}
+
+/******************************************************************************/
+int
+rdpMouseProc(DeviceIntPtr pDevice, int onoff)
+{
+ BYTE map[6];
+ DevicePtr pDev;
+
+ ErrorF("hi rdpMouseProc\n");
+ pDev = (DevicePtr)pDevice;
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ PtrDeviceInit();
+ map[0] = 0;
+ map[1] = 1;
+ map[2] = 2;
+ map[3] = 3;
+ map[4] = 4;
+ map[5] = 5;
+ InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
+ PtrDeviceControl,
+ miPointerGetMotionBufferSize());
+ break;
+ case DEVICE_ON:
+ pDev->on = 1;
+ PtrDeviceOn(pDevice);
+ break;
+ case DEVICE_OFF:
+ pDev->on = 0;
+ PtrDeviceOff();
+ break;
+ case DEVICE_CLOSE:
+ if (pDev->on)
+ {
+ PtrDeviceOff();
+ }
+ break;
+ }
+ return Success;
+}
+
+/******************************************************************************/
+Bool
+rdpCursorOffScreen(ScreenPtr* ppScreen, int* x, int* y)
+{
+ /*ErrorF("hi rdpCursorOffScreen\n");*/
+ return 0;
+}
+
+/******************************************************************************/
+void
+rdpCrossScreen(ScreenPtr pScreen, Bool entering)
+{
+ /*ErrorF("hi rdpCrossScreen\n");*/
+}
+
+/******************************************************************************/
+Bool
+rdpSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+{
+ /*ErrorF("hi rdpSpriteRealizeCursor\n");*/
+ return 1;
+}
+
+/******************************************************************************/
+Bool
+rdpSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+{
+ /*ErrorF("hi rdpSpriteUnrealizeCursor\n");*/
+ return 1;
+}
+
+/******************************************************************************/
+int
+get_pixel_safe(char* data, int x, int y, int width, int height, int bpp)
+{
+ int start;
+ int shift;
+ int c;
+
+ if (x < 0)
+ {
+ return 0;
+ }
+ if (y < 0)
+ {
+ return 0;
+ }
+ if (x >= width)
+ {
+ return 0;
+ }
+ if (y >= height)
+ {
+ return 0;
+ }
+ if (bpp == 1)
+ {
+ width = (width + 7) / 8;
+ start = (y * width) + x / 8;
+ shift = x % 8;
+ c = (unsigned char)(data[start]);
+ /* todo LSBFirst */
+ return (g_reverse_byte[c] & (0x80 >> shift)) != 0;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+void
+set_pixel_safe(char* data, int x, int y, int width, int height, int bpp,
+ int pixel)
+{
+ int start;
+ int shift;
+
+ if (x < 0)
+ {
+ return;
+ }
+ if (y < 0)
+ {
+ return;
+ }
+ if (x >= width)
+ {
+ return;
+ }
+ if (y >= height)
+ {
+ return;
+ }
+ if (bpp == 1)
+ {
+ width = (width + 7) / 8;
+ start = (y * width) + x / 8;
+ shift = x % 8;
+ if (pixel & 1)
+ {
+ data[start] = data[start] | (0x80 >> shift);
+ }
+ else
+ {
+ data[start] = data[start] & ~(0x80 >> shift);
+ }
+ }
+ else if (bpp == 24)
+ {
+ *(data + (3 * (y * width + x)) + 0) = pixel >> 0;
+ *(data + (3 * (y * width + x)) + 1) = pixel >> 8;
+ *(data + (3 * (y * width + x)) + 2) = pixel >> 16;
+ }
+}
+
+/******************************************************************************/
+void
+rdpSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+{
+ char cur_data[32 * (32 * 3)];
+ char cur_mask[32 * (32 / 8)];
+ char* mask;
+ char* data;
+ int i;
+ int j;
+ int w;
+ int h;
+ int p;
+ int xhot;
+ int yhot;
+ int paddedRowBytes;
+ int fgcolor;
+ int bgcolor;
+
+ if (pCursor == 0)
+ {
+ return;
+ }
+ if (pCursor->bits == 0)
+ {
+ return;
+ }
+ w = pCursor->bits->width;
+ h = pCursor->bits->height;
+ paddedRowBytes = PixmapBytePad(w, 1);
+ xhot = pCursor->bits->xhot;
+ yhot = pCursor->bits->yhot;
+ data = (char*)(pCursor->bits->source);
+ mask = (char*)(pCursor->bits->mask);
+ fgcolor = (((pCursor->foreRed >> 8) & 0xff) << 16) |
+ (((pCursor->foreGreen >> 8) & 0xff) << 8) |
+ ((pCursor->foreBlue >> 8) & 0xff);
+ bgcolor = (((pCursor->backRed >> 8) & 0xff) << 16) |
+ (((pCursor->backGreen >> 8) & 0xff) << 8) |
+ ((pCursor->backBlue >> 8) & 0xff);
+ memset(cur_data, 0, sizeof(cur_data));
+ memset(cur_mask, 0, sizeof(cur_mask));
+ for (j = 0; j < 32; j++)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ p = get_pixel_safe(mask, i, j, paddedRowBytes * 8, h, 1);
+ set_pixel_safe(cur_mask, i, 31 - j, 32, 32, 1, !p);
+ if (p != 0)
+ {
+ p = get_pixel_safe(data, i, j, paddedRowBytes * 8, h, 1);
+ p = p ? fgcolor : bgcolor;
+ set_pixel_safe(cur_data, i, 31 - j, 32, 32, 24, p);
+ }
+ }
+ }
+ rdpup_begin_update();
+ rdpup_set_cursor(xhot, yhot, cur_data, cur_mask);
+ rdpup_end_update();
+}
+
+/******************************************************************************/
+void
+rdpSpriteMoveCursor(ScreenPtr pScreen, int x, int y)
+{
+ /*ErrorF("hi rdpSpriteMoveCursor\n");*/
+}
+
+/******************************************************************************/
+void
+PtrAddEvent(int buttonMask, int x, int y)
+{
+ xEvent ev;
+ int i;
+ unsigned long time;
+
+ time = GetTimeInMillis();
+ miPointerAbsoluteCursor(x, y, time);
+ for (i = 0; i < 5; i++)
+ {
+ if ((buttonMask ^ g_old_button_mask) & (1 << i))
+ {
+ if (buttonMask & (1 << i))
+ {
+ ev.u.u.type = ButtonPress;
+ ev.u.u.detail = i + 1;
+ ev.u.keyButtonPointer.time = time;
+ mieqEnqueue(&ev);
+ }
+ else
+ {
+ ev.u.u.type = ButtonRelease;
+ ev.u.u.detail = i + 1;
+ ev.u.keyButtonPointer.time = time;
+ mieqEnqueue(&ev);
+ }
+ }
+ }
+ g_old_button_mask = buttonMask;
+}
+
+/******************************************************************************/
+void
+KbdAddEvent(int down, int param1, int param2, int param3, int param4)
+{
+ xEvent ev;
+ unsigned long time;
+ int ch;
+
+ time = GetTimeInMillis();
+ if (down)
+ {
+ ev.u.u.type = KeyPress;
+ }
+ else
+ {
+ ev.u.u.type = KeyRelease;
+ }
+ ev.u.keyButtonPointer.time = time;
+ ch = 0;
+ switch (param3)
+ {
+ case 1: /* esc */
+ ch = 67;
+ break;
+ case 2: /* 1 or ! */
+ ch = 18;
+ break;
+ case 3: /* 2 or @ */
+ ch = 19;
+ break;
+ case 4: /* 3 or # */
+ ch = 20;
+ break;
+ case 5: /* 4 or $ */
+ ch = 21;
+ break;
+ case 6: /* 5 or % */
+ ch = 22;
+ break;
+ case 7: /* 6 or ^ */
+ ch = 23;
+ break;
+ case 8: /* 7 or & */
+ ch = 24;
+ break;
+ case 9: /* 8 or * */
+ ch = 25;
+ break;
+ case 10: /* 9 or ( */
+ ch = 26;
+ break;
+ case 11: /* 0 or ) */
+ ch = 17;
+ break;
+ case 12: /* - or _ */
+ ch = 27;
+ break;
+ case 13: /* = or + */
+ ch = 28;
+ break;
+ case 14: /* backspace */
+ ch = 64;
+ break;
+ case 15: /* tab */
+ ch = 66;
+ break;
+ case 16: /* q */
+ ch = 54;
+ break;
+ case 17: /* w */
+ ch = 60;
+ break;
+ case 18: /* e */
+ ch = 42;
+ break;
+ case 19: /* r */
+ ch = 55;
+ break;
+ case 20: /* t */
+ ch = 57;
+ break;
+ case 21: /* y */
+ ch = 62;
+ break;
+ case 22: /* u */
+ ch = 58;
+ break;
+ case 23: /* i */
+ ch = 46;
+ break;
+ case 24: /* o */
+ ch = 52;
+ break;
+ case 25: /* p */
+ ch = 53;
+ break;
+ case 26: /* [ or { */
+ ch = 29;
+ break;
+ case 27: /* ] or } */
+ ch = 30;
+ break;
+ case 28: /* enter */
+ ch = 65;
+ break;
+ case 29: /* left and right control */
+ if (param4 & 0x100) /* rdp ext flag */
+ {
+ ch = 9;
+ }
+ else
+ {
+ ch = 8;
+ }
+ break;
+ case 30: /* a */
+ ch = 38;
+ break;
+ case 31: /* s */
+ ch = 56;
+ break;
+ case 32: /* d */
+ ch = 41;
+ break;
+ case 33: /* f */
+ ch = 43;
+ break;
+ case 34: /* g */
+ ch = 44;
+ break;
+ case 35: /* h */
+ ch = 45;
+ break;
+ case 36: /* j */
+ ch = 47;
+ break;
+ case 37: /* k */
+ ch = 48;
+ break;
+ case 38: /* l */
+ ch = 49;
+ break;
+ case 39: /* : or ; */
+ ch = 31;
+ break;
+ case 40: /* ' or " */
+ ch = 32;
+ break;
+ case 41: /* ` or ~ */
+ ch = 33;
+ break;
+ case 42: /* left shift */
+ ch = 10;
+ break;
+ case 43: /* / */
+ ch = 36;
+ break;
+ case 44: /* z */
+ ch = 63;
+ break;
+ case 45: /* x */
+ ch = 61;
+ break;
+ case 46: /* c */
+ ch = 40;
+ break;
+ case 47: /* v */
+ ch = 59;
+ break;
+ case 48: /* b */
+ ch = 39;
+ break;
+ case 49: /* n */
+ ch = 51;
+ break;
+ case 50: /* m */
+ ch = 50;
+ break;
+ case 51: /* , or < */
+ ch = 34;
+ break;
+ case 52: /* . or > */
+ ch = 35;
+ break;
+ case 53: /* / or ? */
+ ch = 36;
+ break;
+ case 54: /* right shift */
+ ch = 11;
+ break;
+ case 55: /* * on keypad or print screen if ext */
+ if (param4 & 0x100) /* rdp ext flag */
+ {
+ ch = 90;
+ }
+ else
+ {
+ ch = 89;
+ }
+ break;
+ case 56: /* left and right alt */
+ if (param4 & 0x100) /* rdp ext flag */
+ {
+ ch = 15; /* right alt */
+ }
+ else
+ {
+ ch = 14; /* left alt */
+ }
+ break;
+ case 57: /* space */
+ ch = 16;
+ break;
+ case 58: /* caps lock */
+ ch = 91;
+ break;
+ case 59: /* F1 */
+ ch = 77;
+ break;
+ case 60: /* F2 */
+ ch = 78;
+ break;
+ case 61: /* F3 */
+ ch = 79;
+ break;
+ case 62: /* F4 */
+ ch = 80;
+ break;
+ case 63: /* F5 */
+ ch = 81;
+ break;
+ case 64: /* F6 */
+ ch = 82;
+ break;
+ case 65: /* F7 */
+ ch = 83;
+ break;
+ case 66: /* F8 */
+ ch = 84;
+ break;
+ case 67: /* F9 */
+ ch = 85;
+ break;
+ case 68: /* F10 */
+ ch = 86;
+ break;
+ case 69: /* Num lock */
+ ch = 92;
+ break;
+ case 70: /* Scroll lock */
+ ch = 93;
+ break;
+ case 71: /* 7 or home */
+ if (param2 == 0xffff) /* ascii 7 */
+ {
+ ch = 95; /* keypad 7 */
+ }
+ else if (param4 & 0x100)
+ {
+ ch = 69; /* non keypad home */
+ }
+ else
+ {
+ ch = 94; /* keypad home */
+ }
+ break;
+ case 72: /* 8 or up arrow */
+ if (param2 == 0xffff) /* ascii 8 */
+ {
+ ch = 97; /* keypad 8 */
+ }
+ else if (param4 & 0x100)
+ {
+ ch = 73; /* non keypad up */
+ }
+ else
+ {
+ ch = 96; /* keypad up */
+ }
+ break;
+ case 73: /* 9 or page up */
+ if (param2 == 0xffff) /* ascii 9 */
+ {
+ ch = 99; /* keypad 9 */
+ }
+ else if (param4 & 0x100)
+ {
+ ch = 71; /* non keypad page up */
+ }
+ else
+ {
+ ch = 98; /* keypad page up */
+ }
+ break;
+ case 74: /* minus on keypad */
+ ch = 100;
+ break;
+ case 75: /* 4 or left arrow */
+ if (param2 == 0xffff) /* ascii 4 */
+ {
+ ch = 102; /* keypad 4 */
+ }
+ else if (param4 & 0x100)
+ {
+ ch = 75; /* non keypad left */
+ }
+ else
+ {
+ ch = 101; /* keypad left */
+ }
+ break;
+ case 76: /* 5 on keypad */
+ ch = 103;
+ break;
+ case 77: /* 6 or right arrow */
+ if (param2 == 0xffff) /* ascii 6 */
+ {
+ ch = 105; /* keypad 6 */
+ }
+ else if (param4 & 0x100)
+ {
+ ch = 76; /* non keypad right */
+ }
+ else
+ {
+ ch = 104; /* keypad right */
+ }
+ break;
+ case 78: /* plus on keypad */
+ ch = 106;
+ break;
+ case 79: /* 1 or end */
+ if (param2 == 0xffff) /* ascii 1 */
+ {
+ ch = 108; /* keypad 1 */
+ }
+ else if (param4 & 0x100)
+ {
+ ch = 70; /* non keypad end */
+ }
+ else
+ {
+ ch = 107; /* keypad end */
+ }
+ break;
+ case 80: /* 2 or down arrow */
+ if (param2 == 0xffff) /* ascii 2 */
+ {
+ ch = 110; /* keypad 2 */
+ }
+ else if (param4 & 0x100)
+ {
+ ch = 74; /* non keypad down arrow */
+ }
+ else
+ {
+ ch = 109; /* keypad down arrow */
+ }
+ break;
+ case 81: /* 3 or page down */
+ if (param2 == 0xffff) /* ascii 3 */
+ {
+ ch = 112; /* keypad 3 */
+ }
+ else if (param4 & 0x100)
+ {
+ ch = 72; /* non keypad page down */
+ }
+ else
+ {
+ ch = 111; /* keypad page down */
+ }
+ break;
+ case 82: /* 0 or insert */
+ if (param2 == 0xffff) /* ascii 0 */
+ {
+ ch = 114; /* keypad 0 */
+ }
+ else if (param4 & 0x100)
+ {
+ ch = 115; /* non keypad insert */
+ }
+ else
+ {
+ ch = 113; /* keypad insert */
+ }
+ break;
+ case 83: /* . or delete */
+ if (param2 == 0xffff) /* ascii . */
+ {
+ ch = 117; /* keypad . */
+ }
+ else if (param4 & 0x100)
+ {
+ ch = 68; /* non keypad delete */
+ }
+ else
+ {
+ ch = 116; /* keypad delete */
+ }
+ break;
+ case 87: /* F11 */
+ ch = 87;
+ break;
+ case 88: /* F12 */
+ ch = 88;
+ break;
+ }
+ if (ch > 0)
+ {
+ ev.u.u.detail = ch;
+ mieqEnqueue(&ev);
+ }
+}
diff --git a/Xserver/hw/rdp/rdpmain.c b/Xserver/hw/rdp/rdpmain.c
new file mode 100644
index 00000000..b3a0491f
--- /dev/null
+++ b/Xserver/hw/rdp/rdpmain.c
@@ -0,0 +1,528 @@
+/*
+Copyright 2005-2006 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.
+
+This is the main file called from main.c
+Sets up the functions
+
+*/
+
+#include "rdp.h"
+
+rdpScreenInfo g_rdpScreen; /* the one screen */
+ScreenPtr g_pScreen = 0;
+int g_rdpGCIndex = -1;
+int g_firstTime = 1;
+
+/* set all these at once, use function set_bpp */
+/* only allow 8 and 16 bpp for not, adding 32 later */
+int g_bpp = 16;
+int g_Bpp = 2;
+int g_Bpp_mask = 0xffff;
+static int g_redBits = 5;
+static int g_greenBits = 6;
+static int g_blueBits = 5;
+
+extern int monitorResolution;
+extern int defaultColorVisualClass;
+extern char* display;
+
+/*static HWEventQueueType alwaysCheckForInput[2] = { 0, 1 };
+static HWEventQueueType* mieqCheckForInput[2];*/
+
+static int g_initOutputCalled = 0;
+
+/******************************************************************************/
+/* returns error, zero is good */
+static int
+set_bpp(int bpp)
+{
+ int rv;
+
+ rv = 0;
+ g_bpp = bpp;
+ if (g_bpp == 8)
+ {
+ g_Bpp = 1;
+ g_Bpp_mask = 0xff;
+ g_redBits = 3;
+ g_greenBits = 3;
+ g_blueBits = 2;
+ }
+ else if (g_bpp == 16)
+ {
+ g_Bpp = 2;
+ g_Bpp_mask = 0xffff;
+ g_redBits = 5;
+ g_greenBits = 6;
+ g_blueBits = 5;
+ }
+ else if (g_bpp == 32)
+ {
+ g_Bpp = 4;
+ g_Bpp_mask = 0xffffff;
+ g_redBits = 8;
+ g_greenBits = 8;
+ g_blueBits = 8;
+ }
+ else
+ {
+ rv = 1;
+ }
+ return rv;
+}
+
+/******************************************************************************/
+/* these are in rdpkbptr.c */
+static miPointerSpriteFuncRec rdpSpritePointerFuncs =
+{
+ rdpSpriteRealizeCursor,
+ rdpSpriteUnrealizeCursor,
+ rdpSpriteSetCursor,
+ rdpSpriteMoveCursor,
+};
+
+/******************************************************************************/
+/* these are in rdpkbptr.c */
+static miPointerScreenFuncRec rdpPointerCursorFuncs =
+{
+ rdpCursorOffScreen,
+ rdpCrossScreen,
+ miPointerWarpCursor /* don't need to set last 2 funcs
+ EnqueueEvent and NewEventScreen */
+};
+
+/******************************************************************************/
+static void
+rdpWakeupHandler(int i, pointer blockData, unsigned long err,
+ pointer pReadmask)
+{
+ int e;
+
+ /*ErrorF("rdpWakeupHandler %d\n", err);*/
+ e = (int)err;
+ if (e < 0)
+ {
+ g_pScreen->WakeupHandler = g_rdpScreen.WakeupHandler;
+ g_pScreen->WakeupHandler(i, blockData, err, pReadmask);
+ g_pScreen->WakeupHandler = rdpWakeupHandler;
+ return;
+ }
+ rdpup_check();
+ g_pScreen->WakeupHandler = g_rdpScreen.WakeupHandler;
+ g_pScreen->WakeupHandler(i, blockData, err, pReadmask);
+ g_pScreen->WakeupHandler = rdpWakeupHandler;
+}
+
+/******************************************************************************/
+/* returns boolean, true if everything is ok */
+static Bool
+rdpScreenInit(int index, ScreenPtr pScreen, int argc, char** argv)
+{
+ int dpix;
+ int dpiy;
+ int ret;
+ VisualPtr vis;
+ PictureScreenPtr ps;
+
+ g_pScreen = pScreen;
+
+ /*ErrorF("hi rdpScreenInit\n");*/
+ /*dpix = 75;
+ dpiy = 75;*/
+ dpix = 100;
+ dpiy = 100;
+ if (monitorResolution != 0)
+ {
+ dpix = monitorResolution;
+ dpiy = monitorResolution;
+ }
+ g_rdpScreen.paddedWidthInBytes = PixmapBytePad(g_rdpScreen.width,
+ g_rdpScreen.depth);
+ g_rdpScreen.bitsPerPixel = rdpBitsPerPixel(g_rdpScreen.depth);
+ ErrorF("screen width %d height %d depth %d bpp %d\n", g_rdpScreen.width,
+ g_rdpScreen.height, g_rdpScreen.depth, g_rdpScreen.bitsPerPixel);
+ ErrorF("dpix %d dpiy %d\n", dpix, dpiy);
+ if (g_rdpScreen.pfbMemory == 0)
+ {
+ g_rdpScreen.sizeInBytes =
+ (g_rdpScreen.paddedWidthInBytes * g_rdpScreen.height);
+ ErrorF("buffer size %d\n", g_rdpScreen.sizeInBytes);
+ g_rdpScreen.pfbMemory = (char*)Xalloc(g_rdpScreen.sizeInBytes);
+ memset(g_rdpScreen.pfbMemory, 0, g_rdpScreen.sizeInBytes);
+ }
+ if (g_rdpScreen.pfbMemory == 0)
+ {
+ return 0;
+ }
+ miClearVisualTypes();
+ if (defaultColorVisualClass == -1)
+ {
+ defaultColorVisualClass = TrueColor;
+ }
+ if (!miSetVisualTypes(g_rdpScreen.depth,
+ miGetDefaultVisualMask(g_rdpScreen.depth),
+ 8, defaultColorVisualClass))
+ {
+ return 0;
+ }
+ miSetPixmapDepths();
+ switch (g_rdpScreen.bitsPerPixel)
+ {
+ case 8:
+ ret = fbScreenInit(pScreen, g_rdpScreen.pfbMemory,
+ g_rdpScreen.width, g_rdpScreen.height,
+ dpix, dpiy, g_rdpScreen.paddedWidthInBytes);
+ break;
+ case 16:
+ ret = fbScreenInit(pScreen, g_rdpScreen.pfbMemory,
+ g_rdpScreen.width, g_rdpScreen.height,
+ dpix, dpiy, g_rdpScreen.paddedWidthInBytes / 2);
+ break;
+ case 32:
+ ret = fbScreenInit(pScreen, g_rdpScreen.pfbMemory,
+ g_rdpScreen.width, g_rdpScreen.height,
+ dpix, dpiy, g_rdpScreen.paddedWidthInBytes / 4);
+ break;
+ default:
+ return 0;
+ }
+ if (!ret)
+ {
+ return 0;
+ }
+
+ miInitializeBackingStore(pScreen);
+
+ /* this is for rgb, not bgr, just doing rgb for now */
+ vis = g_pScreen->visuals + g_pScreen->numVisuals;
+ while (--vis >= pScreen->visuals)
+ {
+ if ((vis->class | DynamicClass) == DirectColor)
+ {
+ vis->offsetBlue = 0;
+ vis->blueMask = (1 << g_blueBits) - 1;
+ vis->offsetGreen = g_blueBits;
+ vis->greenMask = ((1 << g_greenBits) - 1) << vis->offsetGreen;
+ vis->offsetRed = g_blueBits + g_greenBits;
+ vis->redMask = ((1 << g_redBits) - 1) << vis->offsetRed;
+ }
+ }
+
+ if (g_rdpScreen.bitsPerPixel > 4)
+ {
+ fbPictureInit(pScreen, 0, 0);
+ }
+
+ if (!AllocateGCPrivate(pScreen, g_rdpGCIndex, sizeof(rdpGCRec)))
+ {
+ FatalError("rdpScreenInit: AllocateGCPrivate failed\n");
+ }
+ /* Random screen procedures */
+ g_rdpScreen.CloseScreen = pScreen->CloseScreen;
+ /* GC procedures */
+ g_rdpScreen.CreateGC = pScreen->CreateGC;
+ /* Window Procedures */
+ g_rdpScreen.PaintWindowBackground = pScreen->PaintWindowBackground;
+ g_rdpScreen.PaintWindowBorder = pScreen->PaintWindowBorder;
+ g_rdpScreen.CopyWindow = pScreen->CopyWindow;
+ g_rdpScreen.ClearToBackground = pScreen->ClearToBackground;
+ /* Backing store procedures */
+ g_rdpScreen.RestoreAreas = pScreen->RestoreAreas;
+ g_rdpScreen.WakeupHandler = pScreen->WakeupHandler;
+ ps = GetPictureScreenIfSet(pScreen);
+ if (ps)
+ {
+ g_rdpScreen.Composite = ps->Composite;
+ }
+
+ /* testing something here */
+ /*rdpScreen.InstallColormap = pScreen->InstallColormap;*/
+
+ pScreen->blackPixel = g_rdpScreen.blackPixel;
+ pScreen->whitePixel = g_rdpScreen.whitePixel;
+
+ /* Random screen procedures */
+ pScreen->CloseScreen = rdpCloseScreen;
+ pScreen->WakeupHandler = rdpWakeupHandler;
+ if (ps)
+ {
+ ps->Composite = rdpComposite;
+ }
+ pScreen->SaveScreen = rdpSaveScreen;
+ /* GC procedures */
+ pScreen->CreateGC = rdpCreateGC;
+ /* Window Procedures */
+ pScreen->PaintWindowBackground = rdpPaintWindowBackground;
+ pScreen->PaintWindowBorder = rdpPaintWindowBorder;
+ pScreen->CopyWindow = rdpCopyWindow;
+ pScreen->ClearToBackground = rdpClearToBackground;
+ /* Backing store procedures */
+ pScreen->RestoreAreas = rdpRestoreAreas;
+ /* Colormap procedures */
+ /*pScreen->InstallColormap = rdpInstallColormap;*/
+ /*pScreen->UninstallColormap = rdpUninstallColormap;*/
+ /*pScreen->ListInstalledColormaps = rdpListInstalledColormaps;*/
+ /*pScreen->StoreColors = rdpStoreColors;*/
+ miPointerInitialize(pScreen, &rdpSpritePointerFuncs,
+ &rdpPointerCursorFuncs, 1);
+ vis = pScreen->visuals;
+ while (vis->vid != pScreen->rootVisual)
+ {
+ vis++;
+ }
+ if (vis == 0)
+ {
+ rdpLog("rdpScreenInit: couldn't find root visual\n");
+ exit(1);
+ }
+
+ /*vis->offsetBlue = 0;*/
+ /*vis->blueMask = (1 << blueBits) - 1;*/
+ /*vis->offsetGreen = blueBits;*/
+ /*vis->greenMask = ((1 << greenBits) - 1) << vis->offsetGreen;*/
+ /*vis->offsetRed = vis->offsetGreen + greenBits;*/
+ /*vis->redMask = ((1 << redBits) - 1) << vis->offsetRed;*/
+ if (g_rdpScreen.bitsPerPixel == 1)
+ {
+ ret = mfbCreateDefColormap(pScreen);
+ }
+ else
+ {
+ ret = fbCreateDefColormap(pScreen);
+ }
+ if (ret)
+ {
+ ret = rdpup_init();
+ }
+ return ret;
+}
+
+/******************************************************************************/
+/* this is the first function called, it can be called many times
+ returns the number or parameters processed
+ if it dosen't apply to the rdp part, return 0 */
+int
+ddxProcessArgument(int argc, char** argv, int i)
+{
+ /*ErrorF("hi ddxProcessArgument %s\n", argv[i]);*/
+ if (g_firstTime)
+ {
+ memset(&g_rdpScreen, 0, sizeof(g_rdpScreen));
+ g_rdpScreen.width = 800;
+ g_rdpScreen.height = 600;
+ g_rdpScreen.depth = 8;
+ set_bpp(8);
+ /*rdpScreen.whitePixel = 0xffff;*/
+ g_rdpScreen.blackPixel = 1;
+ /*rdpScreen.blackPixel = 0xffff;*/
+ g_firstTime = 0;
+ }
+ if (strcmp (argv[i], "-geometry") == 0)
+ {
+ if (i + 1 >= argc)
+ {
+ UseMsg();
+ }
+ if (sscanf(argv[i + 1], "%dx%d", &g_rdpScreen.width,
+ &g_rdpScreen.height) != 2)
+ {
+ ErrorF("Invalid geometry %s\n", argv[i + 1]);
+ UseMsg();
+ }
+ return 2;
+ }
+ if (strcmp (argv[i], "-depth") == 0)
+ {
+ if (i + 1 >= argc)
+ {
+ UseMsg();
+ }
+ g_rdpScreen.depth = atoi(argv[i + 1]);
+ if (set_bpp(g_rdpScreen.depth) != 0)
+ {
+ UseMsg();
+ }
+ return 2;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+void
+OsVendorInit(void)
+{
+ /*ErrorF("hi OsVendorInit\n");*/
+}
+
+/******************************************************************************/
+CARD32
+GetTimeInMillis(void)
+{
+ struct timeval tp;
+
+ /*ErrorF("hi GetTimeInMillis\n");*/
+ X_GETTIMEOFDAY(&tp);
+ return (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
+}
+
+/* Common pixmap formats */
+static PixmapFormatRec formats[MAXFORMATS] =
+{
+ { 1, 1, BITMAP_SCANLINE_PAD },
+ { 4, 8, BITMAP_SCANLINE_PAD },
+ { 8, 8, BITMAP_SCANLINE_PAD },
+ { 15, 16, BITMAP_SCANLINE_PAD },
+ { 16, 16, BITMAP_SCANLINE_PAD },
+ { 24, 32, BITMAP_SCANLINE_PAD },
+ { 32, 32, BITMAP_SCANLINE_PAD },
+};
+static int numFormats = 7;
+
+/******************************************************************************/
+/* InitOutput is called every time the server resets. It should call
+ AddScreen for each screen (but we only ever have one), and in turn this
+ will call rdpScreenInit. */
+void
+InitOutput(ScreenInfo* screenInfo, int argc, char** argv)
+{
+ int i;
+
+ /*ErrorF("hi InitOutput\n");*/
+ g_initOutputCalled = 1;
+ /* initialize pixmap formats */
+ screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
+ screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+ screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+ screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
+ screenInfo->numPixmapFormats = numFormats;
+ for (i = 0; i < numFormats; i++)
+ {
+ screenInfo->formats[i] = formats[i];
+ }
+ g_rdpGCIndex = AllocateGCPrivateIndex();
+ if (g_rdpGCIndex < 0)
+ {
+ FatalError("InitOutput: AllocateGCPrivateIndex failed\n");
+ }
+ if (!AddCallback(&ClientStateCallback, rdpClientStateChange, NULL))
+ {
+ rdpLog("InitOutput: AddCallback failed\n");
+ return;
+ }
+ /* initialize screen */
+ if (AddScreen(rdpScreenInit, argc, argv) == -1)
+ {
+ FatalError("Couldn't add screen\n");
+ }
+}
+
+/******************************************************************************/
+void
+InitInput(int argc, char** argv)
+{
+ DeviceIntPtr p;
+ DeviceIntPtr k;
+
+ /*ErrorF("hi InitInput\n");*/
+ k = AddInputDevice(rdpKeybdProc, 1);
+ p = AddInputDevice(rdpMouseProc, 1);
+ RegisterKeyboardDevice(k);
+ RegisterPointerDevice(p);
+ miRegisterPointerDevice(screenInfo.screens[0], p);
+ mieqInit(k, p);
+/*
+ mieqCheckForInput[0] = checkForInput[0];
+ mieqCheckForInput[1] = checkForInput[1];
+ SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]);
+*/
+}
+
+/******************************************************************************/
+void
+ddxGiveUp(void)
+{
+ char unixSocketName[32];
+
+ /*ErrorF("hi ddxGiveUp\n");*/
+ Xfree(g_rdpScreen.pfbMemory);
+ if (g_initOutputCalled)
+ {
+ sprintf(unixSocketName, "/tmp/.X11-unix/X%s", display);
+ unlink(unixSocketName);
+ }
+}
+
+/******************************************************************************/
+Bool
+LegalModifier(unsigned int key, DevicePtr pDev)
+{
+ /*ErrorF("hi LegalModifier\n");*/
+ return 1; /* true */
+}
+
+/******************************************************************************/
+void
+ProcessInputEvents(void)
+{
+ /*ErrorF("hi ProcessInputEvents\n");*/
+ /*rdpup_check();*/
+ /*if (*mieqCheckForInput[0] != *mieqCheckForInput[1])*/
+ {
+ /*ErrorF("hi ProcessInputEvents2 \n");*/
+ mieqProcessInputEvents();
+ miPointerUpdate();
+ }
+}
+
+/******************************************************************************/
+/* needed for some reason? todo
+ needs to be rfb */
+void
+rfbRootPropertyChange(PropertyPtr pProp)
+{
+ /*ErrorF("hi rdpRootPropertyChange\n");*/
+}
+
+/******************************************************************************/
+void
+AbortDDX(void)
+{
+ /*ErrorF("hi AbortDDX\n");*/
+ ddxGiveUp();
+}
+
+/******************************************************************************/
+void
+OsVendorFatalError(void)
+{
+ /*ErrorF("hi OsVendorFatalError\n");*/
+}
+
+/******************************************************************************/
+/* print the command list parameters and exit the program */
+void
+ddxUseMsg(void)
+{
+ ErrorF("\n");
+ ErrorF("Xrdp specific options\n");
+ ErrorF("-geometry WxH set framebuffer width & height\n");
+ ErrorF("-depth D set framebuffer depth\n");
+ ErrorF("\n");
+ exit(1);
+}
diff --git a/Xserver/hw/rdp/rdpmisc.c b/Xserver/hw/rdp/rdpmisc.c
new file mode 100644
index 00000000..836c83ab
--- /dev/null
+++ b/Xserver/hw/rdp/rdpmisc.c
@@ -0,0 +1,377 @@
+/*
+Copyright 2005-2006 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.
+
+the rest
+
+*/
+
+#include "rdp.h"
+
+/******************************************************************************/
+/* print a time-stamped message to the log file (stderr). */
+void
+rdpLog(char *format, ...)
+{
+ va_list args;
+ char buf[256];
+ time_t clock;
+
+ va_start(args, format);
+ time(&clock);
+ strftime(buf, 255, "%d/%m/%y %T ", localtime(&clock));
+ fprintf(stderr, buf);
+ vfprintf(stderr, format, args);
+ fflush(stderr);
+ va_end(args);
+}
+
+/******************************************************************************/
+int
+rdpBitsPerPixel(int depth)
+{
+ if (depth == 1)
+ {
+ return 1;
+ }
+ else if (depth <= 8)
+ {
+ return 8;
+ }
+ else if (depth <= 16)
+ {
+ return 16;
+ }
+ else
+ {
+ return 32;
+ }
+}
+
+/******************************************************************************/
+void
+rdpClientStateChange(CallbackListPtr* cbl, pointer myData, pointer clt)
+{
+ dispatchException &= ~DE_RESET; /* hack - force server not to reset */
+}
+
+/******************************************************************************/
+int
+DPMSSupported(void)
+{
+ return 0;
+}
+
+/******************************************************************************/
+int
+DPSMGet(int* level)
+{
+ return -1;
+}
+
+/******************************************************************************/
+void
+DPMSSet(int level)
+{
+}
+
+/******************************************************************************/
+void
+AddOtherInputDevices(void)
+{
+}
+
+/******************************************************************************/
+void
+OpenInputDevice(DeviceIntPtr dev, ClientPtr client, int* status)
+{
+}
+
+/******************************************************************************/
+int
+SetDeviceValuators(register ClientPtr client, DeviceIntPtr dev,
+ int* valuators, int first_valuator, int num_valuators)
+{
+ return BadMatch;
+}
+
+/******************************************************************************/
+int
+SetDeviceMode(register ClientPtr client, DeviceIntPtr dev, int mode)
+{
+ return BadMatch;
+}
+
+/******************************************************************************/
+int
+ChangeKeyboardDevice(DeviceIntPtr old_dev, DeviceIntPtr new_dev)
+{
+ return BadMatch;
+}
+
+/******************************************************************************/
+int
+ChangeDeviceControl(register ClientPtr client, DeviceIntPtr dev,
+ void* control)
+{
+ return BadMatch;
+}
+
+/******************************************************************************/
+int
+ChangePointerDevice(DeviceIntPtr old_dev, DeviceIntPtr new_dev,
+ unsigned char x, unsigned char y)
+{
+ return BadMatch;
+}
+
+/******************************************************************************/
+void
+CloseInputDevice(DeviceIntPtr d, ClientPtr client)
+{
+}
+
+/* the g_ functions from os_calls.c */
+
+/*****************************************************************************/
+int
+g_tcp_recv(int sck, void* ptr, int len, int flags)
+{
+#if defined(_WIN32)
+ return recv(sck, (char*)ptr, len, flags);
+#else
+ return recv(sck, ptr, len, flags);
+#endif
+}
+
+/*****************************************************************************/
+void
+g_tcp_close(int sck)
+{
+ if (sck == 0)
+ {
+ return;
+ }
+ shutdown(sck, 2);
+#if defined(_WIN32)
+ closesocket(sck);
+#else
+ close(sck);
+#endif
+}
+
+/*****************************************************************************/
+int
+g_tcp_last_error_would_block(int sck)
+{
+#if defined(_WIN32)
+ return WSAGetLastError() == WSAEWOULDBLOCK;
+#else
+ return errno == EWOULDBLOCK;
+#endif
+}
+
+/*****************************************************************************/
+void
+g_sleep(int msecs)
+{
+#if defined(_WIN32)
+ Sleep(msecs);
+#else
+ usleep(msecs * 1000);
+#endif
+}
+
+/*****************************************************************************/
+int
+g_tcp_send(int sck, void* ptr, int len, int flags)
+{
+#if defined(_WIN32)
+ return send(sck, (char*)ptr, len, flags);
+#else
+ return send(sck, ptr, len, flags);
+#endif
+}
+
+/*****************************************************************************/
+void*
+g_malloc(int size, int zero)
+{
+ char* rv;
+
+ rv = (char*)malloc(size);
+ if (zero)
+ {
+ memset(rv, 0, size);
+ }
+ return rv;
+}
+
+/*****************************************************************************/
+void
+g_free(void* ptr)
+{
+ if (ptr != 0)
+ {
+ free(ptr);
+ }
+}
+
+/*****************************************************************************/
+void
+g_sprintf(char* dest, char* format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vsprintf(dest, format, ap);
+ va_end(ap);
+}
+
+/*****************************************************************************/
+int
+g_tcp_socket(void)
+{
+ int rv;
+ int i;
+
+ i = 1;
+ rv = socket(PF_INET, SOCK_STREAM, 0);
+#if defined(_WIN32)
+ setsockopt(rv, IPPROTO_TCP, TCP_NODELAY, (char*)&i, sizeof(i));
+#else
+ setsockopt(rv, IPPROTO_TCP, TCP_NODELAY, (void*)&i, sizeof(i));
+#endif
+ return rv;
+}
+
+/*****************************************************************************/
+void
+g_memcpy(void* d_ptr, const void* s_ptr, int size)
+{
+ memcpy(d_ptr, s_ptr, size);
+}
+
+/*****************************************************************************/
+int
+g_tcp_set_no_delay(int sck)
+{
+ int i;
+
+ i = 1;
+#if defined(_WIN32)
+ setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char*)&i, sizeof(i));
+#else
+ setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (void*)&i, sizeof(i));
+#endif
+ return 0;
+}
+
+/*****************************************************************************/
+int
+g_tcp_set_non_blocking(int sck)
+{
+ unsigned long i;
+
+#if defined(_WIN32)
+ i = 1;
+ ioctlsocket(sck, FIONBIO, &i);
+#else
+ i = fcntl(sck, F_GETFL);
+ i = i | O_NONBLOCK;
+ fcntl(sck, F_SETFL, i);
+#endif
+ return 0;
+}
+
+/*****************************************************************************/
+int
+g_tcp_accept(int sck)
+{
+ struct sockaddr_in s;
+#if defined(_WIN32)
+ signed int i;
+#else
+ unsigned int i;
+#endif
+
+ i = sizeof(struct sockaddr_in);
+ memset(&s, 0, i);
+ return accept(sck, (struct sockaddr*)&s, &i);
+}
+
+/*****************************************************************************/
+int
+g_tcp_select(int sck1, int sck2)
+{
+ fd_set rfds;
+ struct timeval time;
+ int max;
+ int rv;
+
+ time.tv_sec = 0;
+ time.tv_usec = 0;
+ FD_ZERO(&rfds);
+ if (sck1 > 0)
+ {
+ FD_SET(((unsigned int)sck1), &rfds);
+ }
+ if (sck2 > 0)
+ {
+ FD_SET(((unsigned int)sck2), &rfds);
+ }
+ max = sck1;
+ if (sck2 > max)
+ {
+ max = sck2;
+ }
+ rv = select(max + 1, &rfds, 0, 0, &time);
+ if (rv > 0)
+ {
+ rv = 0;
+ if (FD_ISSET(((unsigned int)sck1), &rfds))
+ {
+ rv = rv | 1;
+ }
+ if (FD_ISSET(((unsigned int)sck2), &rfds))
+ {
+ rv = rv | 2;
+ }
+ }
+ return rv;
+}
+
+/*****************************************************************************/
+int
+g_tcp_bind(int sck, char* port)
+{
+ struct sockaddr_in s;
+
+ memset(&s, 0, sizeof(struct sockaddr_in));
+ s.sin_family = AF_INET;
+ s.sin_port = htons(atoi(port));
+ s.sin_addr.s_addr = INADDR_ANY;
+ return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
+}
+
+/*****************************************************************************/
+int
+g_tcp_listen(int sck)
+{
+ return listen(sck, 2);
+}
diff --git a/Xserver/hw/rdp/rdpup.c b/Xserver/hw/rdp/rdpup.c
new file mode 100644
index 00000000..01e8a05d
--- /dev/null
+++ b/Xserver/hw/rdp/rdpup.c
@@ -0,0 +1,806 @@
+/*
+Copyright 2005-2006 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"
+/*#include "arch.h"*/
+/*#include "parse.h"*/
+/*#include "os_calls.h"*/
+
+#define DEBUG_OUT_UP(arg)
+/*#define DEBUG_OUT_UP(arg) ErrorF arg*/
+
+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_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 rdpScreenInfo g_rdpScreen; /* from rdpmain.c */
+
+extern char* display;
+
+static void
+rdpScheduleDeferredUpdate(void);
+
+/*
+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 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_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;
+}
+
+/*****************************************************************************/
+/* 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)
+ {
+ ErrorF("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)
+ {
+ ErrorF("error in rdpup_send_msg\n");
+ }
+ return rv;
+}
+
+/******************************************************************************/
+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)
+ {
+ ErrorF("error in rdpup_recv_msg\n");
+ }
+ return rv;
+}
+
+/******************************************************************************/
+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 100:
+ g_cursor_x = param1;
+ g_cursor_y = param2;
+ 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, param2, param3, param4);
+ rdpup_end_update();
+ break;
+ }
+ }
+ else
+ {
+ ErrorF("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);
+ }
+ return 1;
+}
+
+/******************************************************************************/
+int
+rdpup_check(void)
+{
+ int sel;
+
+ sel = g_tcp_select(g_listen_sck, g_sck);
+ if (sel & 1)
+ {
+ if (g_sck == 0)
+ {
+ g_sck = g_tcp_accept(g_listen_sck);
+ if (g_sck == -1)
+ {
+ g_sck = 0;
+ }
+ else
+ {
+ g_tcp_set_non_blocking(g_sck);
+ g_tcp_set_no_delay(g_sck);
+ g_connected = 1;
+ g_sck_closed = 0;
+ AddEnabledDevice(g_sck);
+ }
+ }
+ else
+ {
+ ErrorF("rejecting connection - maybe\n");
+ /* g_tcp_close(g_tcp_accept(g_listen_sck));*/
+ }
+ }
+ if (sel & 2)
+ {
+ if (rdpup_recv_msg(g_in_s) == 0)
+ {
+ rdpup_process_msg(g_in_s);
+ }
+ }
+ 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)))
+ {
+ /*ErrorF("%d %d\n", in_size, g_out_s->size);*/
+ 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;
+}
+
+/******************************************************************************/
+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;
+ 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;
+ 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, 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++;
+ 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;
+
+ 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;
+ }
+ 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;
+ }
+ /*ErrorF("%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)
+ {
+ /*ErrorF("%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_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_Bpp);
+ for (i = 0; i < lh; i++)
+ {
+ s = (g_rdpScreen.pfbMemory +
+ ((ly + i) * g_rdpScreen.paddedWidthInBytes) + (lx * g_Bpp));
+ out_uint8a(g_out_s, s, lw * g_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;
+ }
+ }
+}
+
+/******************************************************************************/
+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);
+ }
+}