From 5b40f518c187e172658e91c42eef713312485a79 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Tue, 6 Mar 2012 11:49:15 -0800 Subject: [PATCH] xorg: add rdp X1 source --- xorg/X11R7.6/rdp/Makefile | 87 ++ xorg/X11R7.6/rdp/gcops.h | 98 ++ xorg/X11R7.6/rdp/rdp.h | 447 ++++++++ xorg/X11R7.6/rdp/rdpdraw.c | 2170 +++++++++++++++++++++++++++++++++++ xorg/X11R7.6/rdp/rdpinput.c | 837 ++++++++++++++ xorg/X11R7.6/rdp/rdpmain.c | 803 +++++++++++++ xorg/X11R7.6/rdp/rdpmisc.c | 487 ++++++++ xorg/X11R7.6/rdp/rdpup.c | 1078 +++++++++++++++++ 8 files changed, 6007 insertions(+) create mode 100644 xorg/X11R7.6/rdp/Makefile create mode 100644 xorg/X11R7.6/rdp/gcops.h create mode 100644 xorg/X11R7.6/rdp/rdp.h create mode 100644 xorg/X11R7.6/rdp/rdpdraw.c create mode 100644 xorg/X11R7.6/rdp/rdpinput.c create mode 100644 xorg/X11R7.6/rdp/rdpmain.c create mode 100644 xorg/X11R7.6/rdp/rdpmisc.c create mode 100644 xorg/X11R7.6/rdp/rdpup.c diff --git a/xorg/X11R7.6/rdp/Makefile b/xorg/X11R7.6/rdp/Makefile new file mode 100644 index 00000000..fca19322 --- /dev/null +++ b/xorg/X11R7.6/rdp/Makefile @@ -0,0 +1,87 @@ + +#X11RDPBASE is an environment variable that needs to be set + +INCBASE = $(X11RDPBASE)/include +LIBBASE = $(X11RDPBASE)/lib + +OBJS = rdpmain.o rdpdraw.o rdpinput.o rdpmisc.o rdpup.o miinitext.o fbcmap.o + +LIBS = ../../dbe/.libs/libdbe.a \ + ../../dix/.libs/libdix.a \ + ../../fb/.libs/libfb.a \ + ../../mfb/.libs/libmfb.a \ + ../../mi/.libs/libmi.a \ + ../../os/.libs/libos.a \ + ../../randr/.libs/librandr.a \ + ../../record/.libs/librecord.a \ + ../../render/.libs/librender.a \ + ../../xkb/.libs/libxkb.a \ + ../../XTrap/.libs/libxtrap.a \ + ../../Xext/.libs/libXext.a \ + ../../Xi/.libs/libXi.a \ + ../../GL/glx/.libs/libglx.a \ + ../../GL/mesa/.libs/libGLcore.a \ + ../../xfixes/.libs/libxfixes.a \ + librdp.a \ + -lfreetype -lz -lm -lXfont -lXau -lXdmcp + +CFLAGS = -O2 -fno-strength-reduce \ + -I../../include \ + -I../../cfb \ + -I../../mfb \ + -I../../mi \ + -I$(INCBASE) \ + -I$(INCBASE)/X11 \ + -I$(INCBASE)/X11/fonts \ + -I$(INCBASE)/X11/extensions \ + -I$(INCBASE)/xorg \ + -I$(INCBASE)/pixman-1 \ + -I../../os \ + -I../../render \ + -I../xfree86/common \ + -I../xfree86/os-support \ + -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE -D_REENTRANT \ + -DGLX_USE_MESA -DXRECORD -D_GNU_SOURCE -DXAPPGROUP \ + -DXCSECURITY -DTOGCUP -DSINGLEDEPTH -DXFree86Server \ + -DDBE -DEVI -DXVMC -DFONTCACHE -DGCCUSESGAS -DSTATIC_COLOR \ + -DAVOID_GLYPHBLT -DFUNCPROTO=15 -DNARROWPROTO -DDDXOSFATALERROR \ + -DPART_NET -DDDXTIME -D_HAVE_XALLOC_DECLS \ + \ + -DXFIXES \ + -DSMART_SCHEDULE -DSERVER_LOCK -DGLXEXT -DSHAPE -DRENDER -DRANDR \ + -DBIGREQS -D_POSIX_SOURCE -D_BSD_SOURCE -DSCREENSAVER -DXF86BIGFONT \ + -DXCMISC -DXTEST -DXTRAP -DXV -DXSYNC -DMITMISC -DPANORAMIX \ + -DDPMSExtension -DXvExtension -DXvMCExtension -DXResExtension \ + -DMITSHM -DPIXPRIV -DNDEBUG -DDDXOSINIT -DXKB -DXINPUT + +# -pedantic + +# these are defined in xorg-server.h +# -D_XOPEN_SOURCE=500L +# -DX_BYTE_ORDER=X_LITTLE_ENDIAN +# -DSMART_SCHEDULE -DSERVER_LOCK -DGLXEXT -DSHAPE -DRENDER -DRANDR +# -DBIGREQS -D_POSIX_SOURCE -D_BSD_SOURCE -DSCREENSAVER -DXF86BIGFONT +# -DXCMISC -DXTEST -DXTRAP -DXV -DXSYNC -DMITMISC -DPANORAMIX +# -DDPMSExtension -DXvExtension -DXvMCExtension -DXResExtension +# -DMITSHM -DPIXPRIV -DNDEBUG -DDDXOSINIT + +# these are not needed I think +# -Dlinux -D__i386__ + +LDFLAGS = -L$(LIBBASE) -Wl,-rpath,$(LIBBASE) + +all: X11rdp + +X11rdp: $(OBJS) + $(AR) rvu librdp.a $(OBJS) + ranlib librdp.a + $(CC) $(LDFLAGS) -o X11rdp $(LIBS) $(LIBS) + +clean: + rm -f $(OBJS) librdp.a + +miinitext.o: ../../mi/miinitext.c + $(CC) $(CFLAGS) -c ../../mi/miinitext.c + +fbcmap.o: ../../fb/fbcmap.c + $(CC) $(CFLAGS) -c ../../fb/fbcmap.c diff --git a/xorg/X11R7.6/rdp/gcops.h b/xorg/X11R7.6/rdp/gcops.h new file mode 100644 index 00000000..52889b82 --- /dev/null +++ b/xorg/X11R7.6/rdp/gcops.h @@ -0,0 +1,98 @@ +/* +Copyright 2005-2012 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +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/xorg/X11R7.6/rdp/rdp.h b/xorg/X11R7.6/rdp/rdp.h new file mode 100644 index 00000000..ee68d511 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdp.h @@ -0,0 +1,447 @@ +/* +Copyright 2005-2012 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#if defined(__arm__) && !defined(__arm32__) +#define __arm32__ +#endif + +#include "xorg-server.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "X.h" +#define NEED_EVENTS +#include "Xproto.h" +#include "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 "dix.h" +#include "X11/keysym.h" +#include "dixfontstr.h" +#include "fontstruct.h" +#include "cursorstr.h" +#include "picturestr.h" +#include "XKBstr.h" +#include "inputstr.h" +#include "randrstr.h" + +/* test to see if this is xorg source or xfree86 */ +#ifdef XORGSERVER +# define RDP_IS_XORG +#else +# include +# if (XF86_VERSION_MAJOR == 4 && XF86_VERSION_MINOR > 3) +# define RDP_IS_XFREE86 +# elif (XF86_VERSION_MAJOR > 4) +# define RDP_IS_XFREE86 +# else +# define RDP_IS_XORG +# endif +#endif + +#define X11RDPVER "0.5.0" + +#define PixelDPI 100 +#define PixelToMM(_size) (((_size) * 254 + (PixelDPI) * 5) / ((PixelDPI) * 10)) + +/* Per-screen (framebuffer) structure. There is only one of these, since we + don't allow the X server to have multiple screens. */ +struct _rdpScreenInfoRec +{ + 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; + /* Pixmap procedures */ + CreatePixmapProcPtr CreatePixmap; + DestroyPixmapProcPtr DestroyPixmap; + /* Window Procedures */ + PaintWindowBackgroundProcPtr PaintWindowBackground; + PaintWindowBorderProcPtr PaintWindowBorder; + CopyWindowProcPtr CopyWindow; + ClearToBackgroundProcPtr ClearToBackground; + ScreenWakeupHandlerProcPtr WakeupHandler; + CompositeProcPtr Composite; + /* Backing store procedures */ + RestoreAreasProcPtr RestoreAreas; + + int rdp_width; + int rdp_height; + int rdp_bpp; + int rdp_Bpp; + int rdp_Bpp_mask; +}; +typedef struct _rdpScreenInfoRec rdpScreenInfoRec; +typedef rdpScreenInfoRec* rdpScreenInfoPtr; + +struct _rdpGCRec +{ + GCFuncs* funcs; + GCOps* ops; +}; +typedef struct _rdpGCRec 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); +int +g_tcp_local_socket_dgram(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 sck3); +int +g_tcp_bind(int sck, char* port); +int +g_tcp_local_bind(int sck, char* port); +int +g_tcp_listen(int sck); + +/* rdpdraw.c */ +Bool +rdpCloseScreen(int i, ScreenPtr pScreen); +PixmapPtr +rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth); +Bool +rdpDestroyPixmap(PixmapPtr pPixmap); +Bool +rdpDestroyPixmap(PixmapPtr pPixmap); +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); + + +/* rdpinput.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); +void +KbdSync(int param1); + +/* 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(X_BYTE_ORDER) +# if X_BYTE_ORDER == X_LITTLE_ENDIAN +# define L_ENDIAN +# else +# define B_ENDIAN +# endif +#else +# error Unknown endianness in rdp.h +#endif +/* check if we need to align data */ +/* check if we need to align data */ +#if defined(__sparc__) || defined(__alpha__) || defined(__hppa__) || \ + defined(__AIX__) || defined(__PPC__) || defined(__mips__) || \ + defined(__ia64__) || defined(__ppc__) || defined(__arm__) +#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/xorg/X11R7.6/rdp/rdpdraw.c b/xorg/X11R7.6/rdp/rdpdraw.c new file mode 100644 index 00000000..e209b1c4 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpdraw.c @@ -0,0 +1,2170 @@ +/* +Copyright 2005-2012 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Xserver drawing ops and funcs + +*/ + +#include "rdp.h" +#include "gcops.h" + +#if 1 +#define DEBUG_OUT_FUNCS(arg) +#define DEBUG_OUT_OPS(arg) +#else +#define DEBUG_OUT_FUNCS(arg) ErrorF arg +#define DEBUG_OUT_OPS(arg) ErrorF arg +#endif + +extern rdpScreenInfoRec 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: + rdpLog("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(®, NullBox, 0); + cd = rdp_get_clip(®, pDstDrawable, pGC); + if (cd == 1) + { + } + else if (cd == 2) + { + } + miRegionUninit(®); + 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)g_malloc(sizeof(DDXPointRec) * npt, 0); + } + 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) + { + g_free(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)g_malloc(sizeof(DDXPointRec) * npt, 0); + 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); + g_free(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*)g_malloc(nseg * sizeof(xSegment), 0); + 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(); + } + } + g_free(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*)g_malloc(sizeof(xRectangle) * nrects, 0); + 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*)g_malloc(nrects * 4 * sizeof(xRectangle), 0); + 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); + g_free(regRects); + g_free(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*)g_malloc(narcs * sizeof(xRectangle), 0); + 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); + g_free(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*)g_malloc(sizeof(xRectangle) * nrectFill, 0); + for (i = 0; i < nrectFill; i++) + { + copy_of_rects[i] = prectInit[i]; + } + fill_reg = miRectsToRegion(nrectFill, copy_of_rects, CT_NONE); + g_free(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 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 rdpPolyFillArc\n")); + GC_OP_PROLOGUE(pGC); + rects = 0; + if (narcs > 0) + { + rects = (xRectangle*)g_malloc(narcs * sizeof(xRectangle), 0); + 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->PolyFillArc(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); + g_free(rects); + 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(®, NullBox, 0); + if (count == 0) + { + cd = 0; + } + else + { + cd = rdp_get_clip(®, 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(®1, &box, 0); + miIntersect(®, ®, ®1); + num_clips = REGION_NUM_RECTS(®); + if (num_clips > 0) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_end_update(); + } + miRegionUninit(®1); + } + miRegionUninit(®); + 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(®, NullBox, 0); + if (count == 0) + { + cd = 0; + } + else + { + cd = rdp_get_clip(®, 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(®1, &box, 0); + miIntersect(®, ®, ®1); + num_clips = REGION_NUM_RECTS(®); + if (num_clips > 0) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_end_update(); + } + miRegionUninit(®1); + } + miRegionUninit(®); + 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(®, NullBox, 0); + if (nglyph == 0) + { + cd = 0; + } + else + { + cd = rdp_get_clip(®, 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(®, ®, &box_reg); + num_clips = REGION_NUM_RECTS(®); + if (num_clips > 0) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_end_update(); + } + miRegionUninit(&box_reg); + } + miRegionUninit(®); + 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(®, NullBox, 0); + if (nglyph == 0) + { + cd = 0; + } + else + { + cd = rdp_get_clip(®, 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(®, ®, &box_reg); + num_clips = REGION_NUM_RECTS(®); + if (num_clips > 0) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_end_update(); + } + miRegionUninit(&box_reg); + } + miRegionUninit(®); + 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; +} + +/******************************************************************************/ +PixmapPtr +rdpCreatePixmap(ScreenPtr pScreen, int width, int height, int depth) +{ + PixmapPtr rv; + + ErrorF("rdpCreatePixmap:\n"); + ErrorF(" in width %d height %d depth %d\n", width, height, depth); + pScreen->CreatePixmap = g_rdpScreen.CreatePixmap; + rv = pScreen->CreatePixmap(pScreen, width, height, depth); + pScreen->CreatePixmap = rdpCreatePixmap; + ErrorF(" out width %d height %d depth %d\n", rv->drawable.width, + rv->drawable.height, rv->drawable.depth); + return rv; +} + +/******************************************************************************/ +Bool +rdpDestroyPixmap(PixmapPtr pPixmap) +{ + Bool rv; + ScreenPtr pScreen; + + ErrorF("rdpDestroyPixmap:\n"); + ErrorF(" refcnt %d\n", pPixmap->refcnt); + pScreen = pPixmap->drawable.pScreen; + pScreen->DestroyPixmap = g_rdpScreen.DestroyPixmap; + rv = pScreen->DestroyPixmap(pPixmap); + pScreen->DestroyPixmap = rdpDestroyPixmap; + return rv; +} + +/******************************************************************************/ +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 + { + rdpLog("error in rdpCreateGC, CreateGC failed\n"); + } + g_pScreen->CreateGC = rdpCreateGC; + } + else + { + rdpLog("error in rdpCreateGC, g_rdpGCIndex is -1\n"); + } + return rv; +} + +/******************************************************************************/ +void +rdpPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what) +{ + int j; + RegionRec reg; + BoxRec box; + + DEBUG_OUT_OPS(("in rdpPaintWindowBackground\n")); + miRegionInit(®, NullBox, 0); + miRegionCopy(®, 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(®) - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[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(®) - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + } + else + { + for (j = REGION_NUM_RECTS(®) - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + } + rdpup_end_update(); + miRegionUninit(®); + 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(®, NullBox, 0); + miRegionCopy(®, 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(®) - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[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(®) - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_fill_rect(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + } + else + { + for (j = REGION_NUM_RECTS(®) - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + } + rdpup_end_update(); + miRegionUninit(®); + 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(®, NullBox, 0); + miRegionCopy(®, 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(®); + /* 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(®)[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(®)[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(®); + 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(®, &box, 0); + miIntersect(®, ®, &pWin->clipList); + rdpup_begin_update(); + for (j = REGION_NUM_RECTS(®) - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_end_update(); + miRegionUninit(®); + } + 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(®, NullBox, 0); + miRegionCopy(®, prgnExposed); + g_pScreen->RestoreAreas = g_rdpScreen.RestoreAreas; + rv = g_pScreen->RestoreAreas(pWin, prgnExposed); + rdpup_begin_update(); + for (j = REGION_NUM_RECTS(®) - 1; j >= 0; j--) + { + box = REGION_RECTS(®)[j]; + rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_end_update(); + miRegionUninit(®); + g_pScreen->RestoreAreas = rdpRestoreAreas; + return rv; +} + +/******************************************************************************/ +void +rdpInstallColormap(ColormapPtr pmap) +{ + ColormapPtr oldpmap; + + 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; + + 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) +{ + *pmaps = g_rdpInstalledColormap->mid; + return 1; +} + +/******************************************************************************/ +void +rdpStoreColors(ColormapPtr pmap, int ndef, xColorItem* pdefs) +{ +} + +/******************************************************************************/ +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(®1, &box, 0); + miRegionInit(®2, NullBox, 0); + miRegionCopy(®2, pDst->clientClip); + miTranslateRegion(®2, p->x + pDst->clipOrigin.x, + p->y + pDst->clipOrigin.y); + miIntersect(®1, ®1, ®2); + num_clips = REGION_NUM_RECTS(®1); + if (num_clips > 0) + { + rdpup_begin_update(); + for (j = num_clips - 1; j >= 0; j--) + { + box = REGION_RECTS(®1)[j]; + rdpup_send_area(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1); + } + rdpup_end_update(); + } + miRegionUninit(®1); + miRegionUninit(®2); + } + 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/xorg/X11R7.6/rdp/rdpinput.c b/xorg/X11R7.6/rdp/rdpinput.c new file mode 100644 index 00000000..68e77196 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpinput.c @@ -0,0 +1,837 @@ +/* +Copyright 2005-2012 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +keyboard and mouse stuff + +*/ + +/* control notes */ +/* rdesktop sends control before scan code 69 but it doesn't set the + flags right so control down is used to determine between pause and + num lock */ +/* this should be fixed in rdesktop */ +/* g_pause_spe flag for specal control sent by ms client before scan code + 69 is sent to tell that its pause, not num lock. both pause and num + lock use scan code 69 */ + +/* tab notes */ +/* mstsc send tab up without a tab down to mark the mstsc has gained focus + this should have sure control alt and shift are all up + rdesktop does not do this */ +/* this should be fixed in rdesktop */ + +#include "rdp.h" + +#if 1 +#define DEBUG_OUT_INPUT(arg) +#else +#define DEBUG_OUT_INPUT(arg) ErrorF arg +#endif + +static DeviceIntPtr g_kbdDevice = 0; +static int g_old_button_mask = 0; +static int g_pause_spe = 0; +static int g_ctrl_down = 0; +static int g_alt_down = 0; +static int g_shift_down = 0; +static int g_tab_down = 0; +/* this is toggled every time num lock key is released, not like the + above *_down vars */ +static int g_scroll_lock_down = 0; + +#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 +/* control */ +#define CONTROL_L_KEY_CODE 37 +#define CONTROL_R_KEY_CODE 109 +/* shift */ +#define SHIFT_L_KEY_CODE 50 +#define SHIFT_R_KEY_CODE 62 +/* win keys */ +#define SUPER_L_KEY_CODE 115 +#define SUPER_R_KEY_CODE 116 +/* alt */ +#define ALT_L_KEY_CODE 64 +#define ALT_R_KEY_CODE 113 +/* caps lock */ +#define CAPS_LOCK_KEY_CODE 66 +/* num lock */ +#define NUM_LOCK_KEY_CODE 77 + +#define N_PREDEFINED_KEYS \ + (sizeof(g_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 g_kbdMap[] = +{ + NoSymbol, NoSymbol, /* 8 */ + XK_Escape, NoSymbol, /* 9 */ + XK_1, XK_exclam, /* 10 */ + XK_2, XK_at, + XK_3, XK_numbersign, + 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_0, XK_parenright, + XK_minus, XK_underscore, /* 20 */ + XK_equal, XK_plus, + XK_BackSpace, NoSymbol, + XK_Tab, XK_ISO_Left_Tab, + XK_Q, NoSymbol, + XK_W, NoSymbol, + XK_E, NoSymbol, + XK_R, NoSymbol, + XK_T, NoSymbol, + XK_Y, NoSymbol, + XK_U, NoSymbol, /* 30 */ + XK_I, NoSymbol, + XK_O, NoSymbol, + XK_P, NoSymbol, + XK_bracketleft, XK_braceleft, + XK_bracketright, XK_braceright, + XK_Return, NoSymbol, + XK_Control_L, NoSymbol, + XK_A, NoSymbol, + XK_S, NoSymbol, + XK_D, NoSymbol, /* 40 */ + XK_F, NoSymbol, + XK_G, NoSymbol, + XK_H, NoSymbol, + XK_J, NoSymbol, + XK_K, NoSymbol, + XK_L, NoSymbol, + XK_semicolon, XK_colon, + XK_apostrophe, XK_quotedbl, + XK_grave, XK_asciitilde, + XK_Shift_L, NoSymbol, /* 50 */ + XK_backslash, XK_bar, + XK_Z, NoSymbol, + XK_X, NoSymbol, + XK_C, NoSymbol, + XK_V, NoSymbol, + XK_B, NoSymbol, + XK_N, NoSymbol, + XK_M, NoSymbol, + XK_comma, XK_less, + XK_period, XK_greater, /* 60 */ + XK_slash, XK_question, + XK_Shift_R, NoSymbol, + XK_KP_Multiply, NoSymbol, + XK_Alt_L, NoSymbol, + XK_space, NoSymbol, + XK_Caps_Lock, NoSymbol, + XK_F1, NoSymbol, + XK_F2, NoSymbol, + XK_F3, NoSymbol, + XK_F4, NoSymbol, /* 70 */ + XK_F5, NoSymbol, + XK_F6, NoSymbol, + XK_F7, NoSymbol, + XK_F8, NoSymbol, + XK_F9, NoSymbol, + XK_F10, NoSymbol, + XK_Num_Lock, NoSymbol, + XK_Scroll_Lock, NoSymbol, + XK_KP_Home, XK_KP_7, + XK_KP_Up, XK_KP_8, /* 80 */ + XK_KP_Prior, XK_KP_9, + XK_KP_Subtract, NoSymbol, + XK_KP_Left, XK_KP_4, + XK_KP_Begin, XK_KP_5, + XK_KP_Right, XK_KP_6, + XK_KP_Add, NoSymbol, + XK_KP_End, XK_KP_1, + XK_KP_Down, XK_KP_2, + XK_KP_Next, XK_KP_3, + XK_KP_Insert, XK_KP_0, /* 90 */ + XK_KP_Delete, XK_KP_Decimal, + NoSymbol, NoSymbol, + NoSymbol, NoSymbol, + NoSymbol, NoSymbol, + XK_F11, NoSymbol, + XK_F12, NoSymbol, + XK_Home, NoSymbol, + XK_Up, NoSymbol, + XK_Prior, NoSymbol, + XK_Left, NoSymbol, /* 100 */ + XK_Print, NoSymbol, + XK_Right, NoSymbol, + XK_End, NoSymbol, + XK_Down, NoSymbol, + XK_Next, NoSymbol, + XK_Insert, NoSymbol, + XK_Delete, NoSymbol, + XK_KP_Enter, NoSymbol, + XK_Control_R, NoSymbol, + XK_Pause, NoSymbol, /* 110 */ + XK_Print, NoSymbol, + XK_KP_Divide, NoSymbol, + XK_Alt_R, NoSymbol, + NoSymbol, NoSymbol, + XK_Super_L, NoSymbol, + XK_Super_R, NoSymbol, + XK_Menu, NoSymbol, + NoSymbol, NoSymbol, + NoSymbol, NoSymbol, + NoSymbol, NoSymbol, /* 120 */ + NoSymbol, NoSymbol +}; + +/******************************************************************************/ +static void +rdpSendBell(void) +{ + DEBUG_OUT_INPUT(("rdpSendBell\n")); +} + +/******************************************************************************/ +void +KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8* pModMap) +{ + int i; + + DEBUG_OUT_INPUT(("KbdDeviceInit\n")); + g_kbdDevice = pDevice; + for (i = 0; i < MAP_LENGTH; i++) + { + pModMap[i] = NoSymbol; + } + pModMap[SHIFT_L_KEY_CODE] = ShiftMask; + pModMap[SHIFT_R_KEY_CODE] = ShiftMask; + pModMap[CAPS_LOCK_KEY_CODE] = LockMask; + pModMap[CONTROL_L_KEY_CODE] = ControlMask; + pModMap[CONTROL_R_KEY_CODE] = ControlMask; + pModMap[ALT_L_KEY_CODE] = Mod1Mask; + pModMap[ALT_R_KEY_CODE] = Mod1Mask; + pModMap[NUM_LOCK_KEY_CODE] = Mod2Mask; + pModMap[SUPER_L_KEY_CODE] = Mod4Mask; + pModMap[SUPER_R_KEY_CODE] = Mod4Mask; + pKeySyms->minKeyCode = MIN_KEY_CODE; + pKeySyms->maxKeyCode = MAX_KEY_CODE; + pKeySyms->mapWidth = GLYPHS_PER_KEY; + i = sizeof(KeySym) * MAP_LENGTH * GLYPHS_PER_KEY; + pKeySyms->map = (KeySym*)g_malloc(i, 1); + if (pKeySyms->map == 0) + { + rdpLog("KbdDeviceInit g_malloc 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] = g_kbdMap[i]; + } +} + +/******************************************************************************/ +void +KbdDeviceOn(void) +{ + DEBUG_OUT_INPUT(("KbdDeviceOn\n")); +} + +/******************************************************************************/ +void +KbdDeviceOff(void) +{ + DEBUG_OUT_INPUT(("KbdDeviceOff\n")); +} + +/******************************************************************************/ +int +rdpKeybdProc(DeviceIntPtr pDevice, int onoff) +{ + KeySymsRec keySyms; + CARD8 modMap[MAP_LENGTH]; + DevicePtr pDev; + + DEBUG_OUT_INPUT(("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(DeviceIntPtr dev, PtrCtrl* ctrl) +{ + DEBUG_OUT_INPUT(("PtrDeviceControl\n")); +} + +/******************************************************************************/ +void +PtrDeviceInit(void) +{ + DEBUG_OUT_INPUT(("PtrDeviceInit\n")); +} + +/******************************************************************************/ +void +PtrDeviceOn(DeviceIntPtr pDev) +{ + DEBUG_OUT_INPUT(("PtrDeviceOn\n")); +} + +/******************************************************************************/ +void +PtrDeviceOff(void) +{ + DEBUG_OUT_INPUT(("PtrDeviceOff\n")); +} + +/******************************************************************************/ +int +rdpMouseProc(DeviceIntPtr pDevice, int onoff) +{ + BYTE map[6]; + DevicePtr pDev; + + DEBUG_OUT_INPUT(("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) +{ + DEBUG_OUT_INPUT(("rdpCursorOffScreen\n")); + return 0; +} + +/******************************************************************************/ +void +rdpCrossScreen(ScreenPtr pScreen, Bool entering) +{ + DEBUG_OUT_INPUT(("rdpCrossScreen\n")); +} + +/******************************************************************************/ +Bool +rdpSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + DEBUG_OUT_INPUT(("rdpSpriteRealizeCursor\n")); + return 1; +} + +/******************************************************************************/ +Bool +rdpSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + DEBUG_OUT_INPUT(("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]); +#if (X_BYTE_ORDER == X_LITTLE_ENDIAN) + return (g_reverse_byte[c] & (0x80 >> shift)) != 0; +#else + return (c & (0x80 >> shift)) != 0; +#endif + } + 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; + /* ErrorF("xhot %d yhot %d\n", xhot, 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) +{ + DEBUG_OUT_INPUT(("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 +check_keysa(void) +{ + xEvent ev; + unsigned long time; + + time = GetTimeInMillis(); + if (g_ctrl_down != 0) + { + memset(&ev, 0, sizeof(ev)); + ev.u.u.type = KeyRelease; + ev.u.keyButtonPointer.time = time; + ev.u.u.detail = g_ctrl_down; + mieqEnqueue(&ev); + g_ctrl_down = 0; + } + if (g_alt_down != 0) + { + memset(&ev, 0, sizeof(ev)); + ev.u.u.type = KeyRelease; + ev.u.keyButtonPointer.time = time; + ev.u.u.detail = g_alt_down; + mieqEnqueue(&ev); + g_alt_down = 0; + } + if (g_shift_down != 0) + { + memset(&ev, 0, sizeof(ev)); + ev.u.u.type = KeyRelease; + ev.u.keyButtonPointer.time = time; + ev.u.u.detail = g_shift_down; + mieqEnqueue(&ev); + g_shift_down = 0; + } +} + +/******************************************************************************/ +void +KbdAddEvent(int down, int param1, int param2, int param3, int param4) +{ + xEvent ev; + unsigned long time; + int rdp_scancode; + int x_scancode; + int is_ext; + int is_spe; + + memset(&ev, 0, sizeof(ev)); + ev.u.u.type = down ? KeyPress : KeyRelease; + time = GetTimeInMillis(); + ev.u.keyButtonPointer.time = time; + rdp_scancode = param3; + is_ext = param4 & 256; /* 0x100 */ + is_spe = param4 & 512; /* 0x200 */ + x_scancode = 0; + switch (rdp_scancode) + { + case 15: /* tab */ + if (!down && !g_tab_down) + { + check_keysa(); + /* leave x_scancode 0 here, we don't want the tab key up */ + } + else + { + x_scancode = 23; + } + g_tab_down = down; + break; + case 28: /* Enter or Return */ + x_scancode = is_ext ? 108 : 36; + break; + case 29: /* left or right ctrl */ + /* this is to handle special case with pause key sending + control first */ + if (is_spe) + { + if (down) + { + g_pause_spe = 1; + } + /* leave x_scancode 0 here, we don't want the control key down */ + } + else + { + x_scancode = is_ext ? 109 : 37; + g_ctrl_down = down ? x_scancode : 0; + } + break; + case 42: /* left shift */ + x_scancode = 50; + g_shift_down = down ? x_scancode : 0; + break; + case 53: /* / */ + x_scancode = is_ext ? 112 : 61; + break; + case 54: /* right shift */ + x_scancode = 62; + g_shift_down = down ? x_scancode : 0; + break; + case 55: /* * on KP or Print Screen */ + x_scancode = is_ext ? 111 : 63; + break; + case 56: /* left or right alt */ + x_scancode = is_ext ? 113 : 64; + g_alt_down = down ? x_scancode : 0; + break; + case 69: /* Pause or Num Lock */ + if (g_pause_spe) + { + x_scancode = 110; + if (!down) + { + g_pause_spe = 0; + } + } + else + { + x_scancode = g_ctrl_down ? 110 : 77; + } + break; + case 70: /* scroll lock */ + x_scancode = 78; + if (!down) + { + g_scroll_lock_down = !g_scroll_lock_down; + } + break; + case 71: /* 7 or Home */ + x_scancode = is_ext ? 97 : 79; + break; + case 72: /* 8 or Up */ + x_scancode = is_ext ? 98 : 80; + break; + case 73: /* 9 or PgUp */ + x_scancode = is_ext ? 99 : 81; + break; + case 75: /* 4 or Left */ + x_scancode = is_ext ? 100 : 83; + break; + case 77: /* 6 or Right */ + x_scancode = is_ext ? 102 : 85; + break; + case 79: /* 1 or End */ + x_scancode = is_ext ? 103 : 87; + break; + case 80: /* 2 or Down */ + x_scancode = is_ext ? 104 : 88; + break; + case 81: /* 3 or PgDn */ + x_scancode = is_ext ? 105 : 89; + break; + case 82: /* 0 or Insert */ + x_scancode = is_ext ? 106 : 90; + break; + case 83: /* . or Delete */ + x_scancode = is_ext ? 107 : 91; + break; + case 91: /* left win key */ + x_scancode = 115; + break; + case 92: /* right win key */ + x_scancode = 116; + break; + case 93: /* menu key */ + x_scancode = 117; + break; + default: + x_scancode = rdp_scancode + MIN_KEY_CODE; + break; + } + if (x_scancode > 0) + { + ev.u.u.detail = x_scancode; + mieqEnqueue(&ev); + } +} + +/******************************************************************************/ +/* notes - + we should use defines or something for the keyc->state below + scroll lock doesn't seem to be a modifier in X +*/ +void +KbdSync(int param1) +{ + KeyClassPtr keyc; + + if (g_kbdDevice == 0) + { + return; + } + keyc = g_kbdDevice->key; + if (keyc == 0) + { + return; + } + if ((!(keyc->state & 0x02)) != (!(param1 & 4))) /* caps lock */ + { + KbdAddEvent(1, 58, 0, 58, 0); + KbdAddEvent(0, 58, 49152, 58, 49152); + } + if ((!(keyc->state & 0x10)) != (!(param1 & 2))) /* num lock */ + { + KbdAddEvent(1, 69, 0, 69, 0); + KbdAddEvent(0, 69, 49152, 69, 49152); + } + if ((!(g_scroll_lock_down)) != (!(param1 & 1))) /* scroll lock */ + { + KbdAddEvent(1, 70, 0, 70, 0); + KbdAddEvent(0, 70, 49152, 70, 49152); + } +} diff --git a/xorg/X11R7.6/rdp/rdpmain.c b/xorg/X11R7.6/rdp/rdpmain.c new file mode 100644 index 00000000..9f2161c9 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpmain.c @@ -0,0 +1,803 @@ +/* +Copyright 2005-2012 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +This is the main file called from main.c +Sets up the functions + +*/ + +#include "rdp.h" + +#if 1 +#define DEBUG_OUT(arg) +#else +#define DEBUG_OUT(arg) ErrorF arg +#endif + +rdpScreenInfoRec g_rdpScreen; /* the one screen */ +ScreenPtr g_pScreen = 0; +int g_rdpGCIndex = -1; +/* set all these at once, use function set_bpp */ +int g_bpp = 16; +int g_Bpp = 2; +int g_Bpp_mask = 0xffff; +static int g_firstTime = 1; +static int g_redBits = 5; +static int g_greenBits = 6; +static int g_blueBits = 5; +static int g_initOutputCalled = 0; +/* Common pixmap formats */ +static PixmapFormatRec g_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 g_numFormats = 7; +static miPointerSpriteFuncRec g_rdpSpritePointerFuncs = +{ + /* these are in rdpinput.c */ + rdpSpriteRealizeCursor, + rdpSpriteUnrealizeCursor, + rdpSpriteSetCursor, + rdpSpriteMoveCursor, +}; +static miPointerScreenFuncRec g_rdpPointerCursorFuncs = +{ + /* these are in rdpinput.c */ + rdpCursorOffScreen, + rdpCrossScreen, + miPointerWarpCursor /* don't need to set last 2 funcs + EnqueueEvent and NewEventScreen */ +}; + +#define FB_GET_SCREEN_PIXMAP(s) ((PixmapPtr) ((s)->devPrivate)) + +static OsTimerPtr g_updateTimer = 0; +static XID g_wid = 0; + +static Bool +rdpRandRGetInfo(ScreenPtr pScreen, Rotation* pRotations); +static Bool +rdpRandRSetConfig(ScreenPtr pScreen, Rotation rotateKind, int rate, + RRScreenSizePtr pSize); + +/******************************************************************************/ +/* 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 == 15) + { + g_Bpp = 2; + g_Bpp_mask = 0x7fff; + g_redBits = 5; + g_greenBits = 5; + g_blueBits = 5; + } + 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 == 24) + { + g_Bpp = 4; + g_Bpp_mask = 0xffffff; + g_redBits = 8; + g_greenBits = 8; + g_blueBits = 8; + } + 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; +} + +/******************************************************************************/ +static void +rdpWakeupHandler(int i, pointer blockData, unsigned long err, + pointer pReadmask) +{ + g_pScreen->WakeupHandler = g_rdpScreen.WakeupHandler; + g_pScreen->WakeupHandler(i, blockData, err, pReadmask); + g_pScreen->WakeupHandler = rdpWakeupHandler; +} + +/******************************************************************************/ +static void +rdpBlockHandler1(pointer blockData, OSTimePtr pTimeout, pointer pReadmask) +{ +} + +/******************************************************************************/ +static void +rdpWakeupHandler1(pointer blockData, int result, pointer pReadmask) +{ + rdpup_check(); +} + +/******************************************************************************/ +/* returns boolean, true if everything is ok */ +static Bool +rdpScreenInit(int index, ScreenPtr pScreen, int argc, char** argv) +{ + int dpix; + int dpiy; + int ret; + Bool vis_found; + VisualPtr vis; + PictureScreenPtr ps; + rrScrPrivPtr pRRScrPriv; + + g_pScreen = pScreen; + + /*dpix = 75; + dpiy = 75;*/ + dpix = PixelDPI; + dpiy = PixelDPI; + 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("\n"); + ErrorF("X11rdp, an X server for xrdp\n"); + ErrorF("Version %s\n", X11RDPVER); + ErrorF("Copyright (C) 2005-2008 Jay Sorg\n"); + ErrorF("See http://xrdp.sf.net for information on xrdp.\n"); +#if defined(XORG_VERSION_CURRENT) && defined (XVENDORNAME) + ErrorF("Underlying X server release %d, %s\n", + XORG_VERSION_CURRENT, XVENDORNAME); +#endif +#if defined(XORG_RELEASE) + ErrorF("Xorg %s\n", XORG_RELEASE); +#endif + 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*)g_malloc(2048 * 2048 * 4, 1); + } + if (g_rdpScreen.pfbMemory == 0) + { + rdpLog("rdpScreenInit g_malloc failed\n"); + return 0; + } + miClearVisualTypes(); + if (defaultColorVisualClass == -1) + { + defaultColorVisualClass = TrueColor; + } + if (!miSetVisualTypes(g_rdpScreen.depth, + miGetDefaultVisualMask(g_rdpScreen.depth), + 8, defaultColorVisualClass)) + { + rdpLog("rdpScreenInit miSetVisualTypes failed\n"); + 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 - 1); + 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; + } + vis--; + } + + 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; + /* Pixmap procudures */ + g_rdpScreen.CreatePixmap = pScreen->CreatePixmap; + g_rdpScreen.DestroyPixmap = pScreen->DestroyPixmap; + /* 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; + } + 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; + /* Pixmap procedures */ + /* pScreen->CreatePixmap = rdpCreatePixmap; */ + /* pScreen->DestroyPixmap = rdpDestroyPixmap; */ + /* Window Procedures */ + pScreen->PaintWindowBackground = rdpPaintWindowBackground; + pScreen->PaintWindowBorder = rdpPaintWindowBorder; + pScreen->CopyWindow = rdpCopyWindow; + pScreen->ClearToBackground = rdpClearToBackground; + /* Backing store procedures */ + pScreen->RestoreAreas = rdpRestoreAreas; + miPointerInitialize(pScreen, &g_rdpSpritePointerFuncs, + &g_rdpPointerCursorFuncs, 1); + + vis_found = 0; + vis = g_pScreen->visuals + (g_pScreen->numVisuals - 1); + while (vis >= pScreen->visuals) + { + if (vis->vid == pScreen->rootVisual) + { + vis_found = 1; + } + vis--; + } + if (!vis_found) + { + rdpLog("rdpScreenInit: couldn't find root visual\n"); + exit(1); + } + if (g_rdpScreen.bitsPerPixel == 1) + { + ret = mfbCreateDefColormap(pScreen); + } + else + { + ret = fbCreateDefColormap(pScreen); + } + if (ret) + { + ret = rdpup_init(); + } + if (ret) + { + RegisterBlockAndWakeupHandlers(rdpBlockHandler1, rdpWakeupHandler1, NULL); + } + if (!RRScreenInit(pScreen)) + { + ErrorF("rdpmain.c: RRScreenInit: screen init failed\n"); + } + else + { + pRRScrPriv = rrGetScrPriv(pScreen); + pRRScrPriv->rrGetInfo = rdpRandRGetInfo; + pRRScrPriv->rrSetConfig = rdpRandRSetConfig; + } + 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) +{ + if (g_firstTime) + { + memset(&g_rdpScreen, 0, sizeof(g_rdpScreen)); + g_rdpScreen.width = 800; + g_rdpScreen.height = 600; + g_rdpScreen.depth = 24; + set_bpp(24); + g_rdpScreen.blackPixel = 1; + g_firstTime = 0; + RRExtensionInit(); + } + 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) +{ +} + +/******************************************************************************/ +/* ddxInitGlobals - called by |InitGlobals| from os/util.c */ +void +ddxInitGlobals(void) +{ +} + +/******************************************************************************/ +int +XkbDDXSwitchScreen(DeviceIntPtr dev, KeyCode key, XkbAction* act) +{ + return 1; +} + +/******************************************************************************/ +int +XkbDDXPrivate(DeviceIntPtr dev, KeyCode key, XkbAction* act) +{ + return 0; +} + +/******************************************************************************/ +int +XkbDDXTerminateServer(DeviceIntPtr dev, KeyCode key, XkbAction* act) +{ + GiveUp(1); + return 0; +} + +/******************************************************************************/ +/* 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; + + 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 = g_numFormats; + for (i = 0; i < g_numFormats; i++) + { + screenInfo->formats[i] = g_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; + + k = AddInputDevice(rdpKeybdProc, 1); + p = AddInputDevice(rdpMouseProc, 1); + RegisterKeyboardDevice(k); + RegisterPointerDevice(p); + /* screenInfo must be globally defined */ + miRegisterPointerDevice(screenInfo.screens[0], p); + mieqInit(k, p); +} + +/******************************************************************************/ +void +ddxGiveUp(void) +{ + char unixSocketName[64]; + + g_free(g_rdpScreen.pfbMemory); + if (g_initOutputCalled) + { + sprintf(unixSocketName, "/tmp/.X11-unix/X%s", display); + unlink(unixSocketName); + sprintf(unixSocketName, "/tmp/.xrdp/xrdp_disconnect_display_%s", display); + unlink(unixSocketName); + } +} + +/******************************************************************************/ +Bool +LegalModifier(unsigned int key, DevicePtr pDev) +{ + return 1; /* true */ +} + +/******************************************************************************/ +void +ProcessInputEvents(void) +{ + mieqProcessInputEvents(); + miPointerUpdate(); +} + +/******************************************************************************/ +/* needed for some reason? todo + needs to be rfb */ +void +rfbRootPropertyChange(PropertyPtr pProp) +{ +} + +/******************************************************************************/ +void +AbortDDX(void) +{ + ddxGiveUp(); +} + +/******************************************************************************/ +void +OsVendorFatalError(void) +{ +} + +/******************************************************************************/ +/* print the command list parameters and exit the program */ +void +ddxUseMsg(void) +{ + ErrorF("\n"); + ErrorF("X11rdp specific options\n"); + ErrorF("-geometry WxH set framebuffer width & height\n"); + ErrorF("-depth D set framebuffer depth\n"); + ErrorF("\n"); + exit(1); +} + +/******************************************************************************/ +void +OsVendorPreInit(void) +{ +} + +/******************************************************************************/ +/* + * Answer queries about the RandR features supported. + 1280x1024+0+0 359mm x 287mm + */ +static Bool +rdpRandRGetInfo(ScreenPtr pScreen, Rotation* pRotations) +{ + int n; + int width; + int height; + int mmwidth; + int mmheight; + Rotation rotateKind; + RRScreenSizePtr pSize; + rrScrPrivPtr pRRScrPriv; + + ErrorF("rdpRandRGetInfo:\n"); + + pRRScrPriv = rrGetScrPriv(pScreen); + + DEBUG_OUT(("rdpRandRGetInfo: nSizes %d\n", pRRScrPriv->nSizes)); + for (n = 0; n < pRRScrPriv->nSizes; n++) + { + DEBUG_OUT(("rdpRandRGetInfo: width %d height %d\n", + pRRScrPriv->pSizes[n].width, + pRRScrPriv->pSizes[n].height)); + } + + /* Don't support rotations, yet */ + *pRotations = RR_Rotate_0; + + /* Bail if no depth has a visual associated with it */ + for (n = 0; n < pScreen->numDepths; n++) + { + if (pScreen->allowedDepths[n].numVids) + { + break; + } + } + if (n == pScreen->numDepths) + { + return FALSE; + } + + /* Only one allowed rotation for now */ + rotateKind = RR_Rotate_0; + + for (n = 0; n < pRRScrPriv->nSizes; n++) + { + RRRegisterSize(pScreen, pRRScrPriv->pSizes[n].width, + pRRScrPriv->pSizes[n].height, + pRRScrPriv->pSizes[n].mmWidth, + pRRScrPriv->pSizes[n].mmHeight); + } + /* + * Register supported sizes. This can be called many times, but + * we only support one size for now. + */ + +#if 0 + width = 800; + height = 600; + mmwidth = PixelToMM(width); + mmheight = PixelToMM(height); + RRRegisterSize(pScreen, width, height, mmwidth, mmheight); + + width = 1024; + height = 768; + mmwidth = PixelToMM(width); + mmheight = PixelToMM(height); + RRRegisterSize(pScreen, width, height, mmwidth, mmheight); + + width = 1280; + height = 1024; + mmwidth = PixelToMM(width); + mmheight = PixelToMM(height); + RRRegisterSize(pScreen, width, height, mmwidth, mmheight); +#endif + + width = g_rdpScreen.rdp_width; + height = g_rdpScreen.rdp_height; + mmwidth = PixelToMM(width); + mmheight = PixelToMM(height); + pSize = RRRegisterSize(pScreen, width, height, mmwidth, mmheight); + + /* Tell RandR what the current config is */ + RRSetCurrentConfig(pScreen, rotateKind, 0, pSize); + + return TRUE; +} + +/******************************************************************************/ +static CARD32 +rdpDeferredDrawCallback(OsTimerPtr timer, CARD32 now, pointer arg) +{ + WindowPtr pWin; + + DEBUG_OUT(("rdpDeferredDrawCallback:\n")); + pWin = (WindowPtr)arg; + DeleteWindow(pWin, None); + /* + FreeResource(g_wid, RT_NONE); + g_wid = 0; + */ +return 0; +} + +/******************************************************************************/ +/* for lack of a better way, a window is created that covers a the area and + when its deleted, it's invalidated */ +static int +rdpInvalidateArea(ScreenPtr pScreen, int x, int y, int cx, int cy) +{ + WindowPtr rootWindow; + WindowPtr pWin; + int result; + int attri; + XID attributes[4]; + Mask mask; + + DEBUG_OUT(("rdpInvalidateArea:\n")); + rootWindow = GetCurrentRootWindow(); + if (rootWindow != 0) + { + mask = 0; + attri = 0; + attributes[attri++] = pScreen->blackPixel; + mask |= CWBackPixel; + attributes[attri++] = xTrue; + mask |= CWOverrideRedirect; + if (g_wid == 0) + { + g_wid = FakeClientID(0); + } + pWin = CreateWindow(g_wid, rootWindow, + x, y, cx, cy, 0, InputOutput, mask, + attributes, 0, serverClient, + wVisual(rootWindow), &result); + if (result == 0) + { + MapWindow(pWin, serverClient); + DeleteWindow(pWin, None); +#if 0 + g_updateTimer = TimerSet(g_updateTimer, 0, 50, + rdpDeferredDrawCallback, pWin); +#endif + } + } + return 0; +} + +/******************************************************************************/ +/* + * Respond to resize/rotate request from either X Server or X client app + */ +static Bool +rdpRandRSetConfig(ScreenPtr pScreen, Rotation rotateKind, int rate, + RRScreenSizePtr pSize) +{ + PixmapPtr screenPixmap; + WindowPtr rootWindow; + BoxRec box; + RegionRec temp; + + if ((pSize->width < 1) || (pSize->height < 1)) + { + ErrorF("rdpRandRSetConfig: error width %d height %d\n", + pSize->width, pSize->height); + return FALSE; + } + ErrorF("rdpRandRSetConfig: width %d height %d\n", + pSize->width, pSize->height); + g_rdpScreen.width = pSize->width; + g_rdpScreen.height = pSize->height; + g_rdpScreen.paddedWidthInBytes = + PixmapBytePad(g_rdpScreen.width, g_rdpScreen.depth); + g_rdpScreen.sizeInBytes = + g_rdpScreen.paddedWidthInBytes * g_rdpScreen.height; + pScreen->width = pSize->width; + pScreen->height = pSize->height; + DEBUG_OUT(("rdpRandRSetConfig: pScreen %dx%d pSize %dx%d\n", + pScreen->mmWidth, pScreen->mmHeight, + pSize->mmWidth, pSize->mmHeight)); + pScreen->mmWidth = pSize->mmWidth; + pScreen->mmHeight = pSize->mmHeight; +#if 0 + g_free(g_rdpScreen.pfbMemory); + g_rdpScreen.pfbMemory = (char*)g_malloc(g_rdpScreen.sizeInBytes, 1); +#endif + screenPixmap = FB_GET_SCREEN_PIXMAP(pScreen); + if (screenPixmap != 0) + { + DEBUG_OUT(("rdpRandRSetConfig: resizing screenPixmap [%p] to %dx%d, " + "currently at %dx%d\n", + (void*)screenPixmap, pSize->width, pSize->height, + screenPixmap->drawable.width, screenPixmap->drawable.height)); + pScreen->ModifyPixmapHeader(screenPixmap, + pSize->width, pSize->height, + g_rdpScreen.depth, g_rdpScreen.bitsPerPixel, + g_rdpScreen.paddedWidthInBytes, + g_rdpScreen.pfbMemory); + DEBUG_OUT(("rdpRandRSetConfig: resized to %dx%d\n", + screenPixmap->drawable.width, screenPixmap->drawable.height)); + /* memset(g_rdpScreen.pfbMemory, 0xff, 2048 * 2048 * 4); */ + } + rootWindow = GetCurrentRootWindow(); + if (rootWindow != 0) + { + DEBUG_OUT(("rdpRandRSetConfig: rootWindow %p\n", (void*)rootWindow)); + box.x1 = 0; + box.y1 = 0; + box.x2 = pSize->width; + box.y2 = pSize->height; + miRegionInit(&rootWindow->winSize, &box, 1); + miRegionInit(&rootWindow->borderSize, &box, 1); + miRegionReset(&rootWindow->borderClip, &box); + miRegionBreak(&rootWindow->clipList); + rootWindow->drawable.width = pSize->width; + rootWindow->drawable.height = pSize->height; + ResizeChildrenWinSize(rootWindow, 0, 0, 0, 0); + } + rdpInvalidateArea(g_pScreen, 0, 0, g_rdpScreen.width, g_rdpScreen.height); + return TRUE; +} diff --git a/xorg/X11R7.6/rdp/rdpmisc.c b/xorg/X11R7.6/rdp/rdpmisc.c new file mode 100644 index 00000000..930aff66 --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpmisc.c @@ -0,0 +1,487 @@ +/* +Copyright 2005-2012 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +the rest + +*/ + +#include "rdp.h" + +#include + +Bool noFontCacheExtension = 1; + +/******************************************************************************/ +/* 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) || (errno == EINPROGRESS); +#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; + +#ifdef _XSERVER64 + /* I thought xalloc whould work here but I guess not, why, todo */ + rv = (char*)malloc(size); +#else + rv = (char*)Xalloc(size); +#endif + if (zero) + { + if (rv != 0) + { + memset(rv, 0, size); + } + } + return rv; +} + +/*****************************************************************************/ +void +g_free(void* ptr) +{ + if (ptr != 0) + { +#ifdef _XSERVER64 + /* I thought xfree whould work here but I guess not, why, todo */ + free(ptr); +#else + Xfree(ptr); +#endif + } +} + +/*****************************************************************************/ +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)); + setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (void*)&i, sizeof(i)); +#endif + return rv; +} + +/*****************************************************************************/ +int +g_tcp_local_socket_dgram(void) +{ +#if defined(_WIN32) + return 0; +#else + return socket(AF_UNIX, SOCK_DGRAM, 0); +#endif +} + +/*****************************************************************************/ +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, int sck3) +{ + 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); + } + if (sck3 > 0) + { + FD_SET(((unsigned int)sck3), &rfds); + } + max = sck1; + if (sck2 > max) + { + max = sck2; + } + if (sck3 > max) + { + max = sck3; + } + 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; + } + if (FD_ISSET(((unsigned int)sck3), &rfds)) + { + rv = rv | 4; + } + } + else + { + rv = 0; + } + 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_local_bind(int sck, char* port) +{ +#if defined(_WIN32) + return -1; +#else + struct sockaddr_un s; + + memset(&s, 0, sizeof(struct sockaddr_un)); + s.sun_family = AF_UNIX; + strcpy(s.sun_path, port); + return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_un)); +#endif +} + +/*****************************************************************************/ +int +g_tcp_listen(int sck) +{ + return listen(sck, 2); +} + +/* + stub for XpClient* functions. +*/ + +/*****************************************************************************/ +Bool +XpClientIsBitmapClient(ClientPtr client) +{ + return 1; +} + +/*****************************************************************************/ +Bool +XpClientIsPrintClient(ClientPtr client, FontPathElementPtr fpe) +{ + return 0; +} + +/*****************************************************************************/ +int +PrinterOptions(int argc, char** argv, int i) +{ + return i; +} + +/*****************************************************************************/ +void +PrinterInitOutput(ScreenInfo* pScreenInfo, int argc, char** argv) +{ +} + +/*****************************************************************************/ +void +PrinterUseMsg(void) +{ +} + +/*****************************************************************************/ +void +PrinterInitGlobals(void) +{ +} + +/*****************************************************************************/ +void +FontCacheExtensionInit(INITARGS) +{ +} diff --git a/xorg/X11R7.6/rdp/rdpup.c b/xorg/X11R7.6/rdp/rdpup.c new file mode 100644 index 00000000..9124f88e --- /dev/null +++ b/xorg/X11R7.6/rdp/rdpup.c @@ -0,0 +1,1078 @@ +/* +Copyright 2005-2012 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#include "rdp.h" + +#if 1 +#define DEBUG_OUT_UP(arg) +#else +#define DEBUG_OUT_UP(arg) ErrorF arg +#endif + +static int g_listen_sck = 0; +static int g_sck = 0; +static int g_sck_closed = 0; +static int g_connected = 0; + +static int g_dis_listen_sck = 0; +static int g_dis_sck = 0; +static int g_dis_sck_closed = 0; +static int g_dis_connected = 0; + +static int g_begin = 0; +static struct stream* g_out_s = 0; +static struct stream* g_in_s = 0; +static int g_button_mask = 0; +static int g_cursor_x = 0; +static int g_cursor_y = 0; +static OsTimerPtr g_timer = 0; +static int g_scheduled = 0; +static int g_count = 0; +extern ScreenPtr g_pScreen; /* from rdpmain.c */ +extern int g_Bpp; /* from rdpmain.c */ +extern int g_Bpp_mask; /* from rdpmain.c */ +extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */ + +/* +0 GXclear, 0 +1 GXnor, DPon +2 GXandInverted, DPna +3 GXcopyInverted, Pn +4 GXandReverse, PDna +5 GXinvert, Dn +6 GXxor, DPx +7 GXnand, DPan +8 GXand, DPa +9 GXequiv, DPxn +a GXnoop, D +b GXorInverted, DPno +c GXcopy, P +d GXorReverse, PDno +e GXor, DPo +f GXset 1 +*/ + +static int g_rdp_opcodes[16] = +{ + 0x00, /* GXclear 0x0 0 */ + 0x88, /* GXand 0x1 src AND dst */ + 0x44, /* GXandReverse 0x2 src AND NOT dst */ + 0xcc, /* GXcopy 0x3 src */ + 0x22, /* GXandInverted 0x4 NOT src AND dst */ + 0xaa, /* GXnoop 0x5 dst */ + 0x66, /* GXxor 0x6 src XOR dst */ + 0xee, /* GXor 0x7 src OR dst */ + 0x11, /* GXnor 0x8 NOT src AND NOT dst */ + 0x99, /* GXequiv 0x9 NOT src XOR dst */ + 0x55, /* GXinvert 0xa NOT dst */ + 0xdd, /* GXorReverse 0xb src OR NOT dst */ + 0x33, /* GXcopyInverted 0xc NOT src */ + 0xbb, /* GXorInverted 0xd NOT src OR dst */ + 0x77, /* GXnand 0xe NOT src OR NOT dst */ + 0xff /* GXset 0xf 1 */ +}; + +/*****************************************************************************/ +/* returns error */ +static int +rdpup_send(char* data, int len) +{ + int sent; + + DEBUG_OUT_UP(("rdpup_send - sending %d bytes\n", len)); + if (g_sck_closed) + { + return 1; + } + while (len > 0) + { + sent = g_tcp_send(g_sck, data, len, 0); + if (sent == -1) + { + if (g_tcp_last_error_would_block(g_sck)) + { + g_sleep(1); + } + else + { + RemoveEnabledDevice(g_sck); + g_connected = 0; + g_tcp_close(g_sck); + g_sck = 0; + g_sck_closed = 1; + return 1; + } + } + else if (sent == 0) + { + RemoveEnabledDevice(g_sck); + g_connected = 0; + g_tcp_close(g_sck); + g_sck = 0; + g_sck_closed = 1; + return 1; + } + else + { + data += sent; + len -= sent; + } + } + return 0; +} + +/******************************************************************************/ +static int +rdpup_send_msg(struct stream* s) +{ + int len; + int rv; + + rv = 1; + if (s != 0) + { + len = s->end - s->data; + if (len > s->size) + { + rdpLog("overrun error len %d count %d\n", len, g_count); + } + s_pop_layer(s, iso_hdr); + out_uint16_le(s, 1); + out_uint16_le(s, g_count); + out_uint32_le(s, len - 8); + rv = rdpup_send(s->data, len); + } + if (rv != 0) + { + rdpLog("error in rdpup_send_msg\n"); + } + return rv; +} + +/******************************************************************************/ +static CARD32 +rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) +{ + if (g_connected && g_begin) + { + DEBUG_OUT_UP(("end %d\n", g_count)); + out_uint16_le(g_out_s, 2); + g_count++; + s_mark_end(g_out_s); + rdpup_send_msg(g_out_s); + } + g_count = 0; + g_begin = 0; + g_scheduled = 0; + return 0; +} + +/******************************************************************************/ +static void +rdpScheduleDeferredUpdate(void) +{ + if (!g_scheduled) + { + g_scheduled = 1; + g_timer = TimerSet(g_timer, 0, 40, rdpDeferredUpdateCallback, 0); + } +} + +/******************************************************************************/ +/* returns error */ +static int +rdpup_recv(char* data, int len) +{ + int rcvd; + + if (g_sck_closed) + { + return 1; + } + while (len > 0) + { + rcvd = g_tcp_recv(g_sck, data, len, 0); + if (rcvd == -1) + { + if (g_tcp_last_error_would_block(g_sck)) + { + g_sleep(1); + } + else + { + RemoveEnabledDevice(g_sck); + g_connected = 0; + g_tcp_close(g_sck); + g_sck = 0; + g_sck_closed = 1; + return 1; + } + } + else if (rcvd == 0) + { + RemoveEnabledDevice(g_sck); + g_connected = 0; + g_tcp_close(g_sck); + g_sck = 0; + g_sck_closed = 1; + return 1; + } + else + { + data += rcvd; + len -= rcvd; + } + } + return 0; +} + +/******************************************************************************/ +static int +rdpup_recv_msg(struct stream* s) +{ + int len; + int rv; + + rv = 1; + if (s != 0) + { + init_stream(s, 4); + rv = rdpup_recv(s->data, 4); + if (rv == 0) + { + in_uint32_le(s, len); + if (len > 3) + { + init_stream(s, len); + rv = rdpup_recv(s->data, len - 4); + } + } + } + if (rv != 0) + { + rdpLog("error in rdpup_recv_msg\n"); + } + return rv; +} + +/******************************************************************************/ +/* + this from miScreenInit + pScreen->mmWidth = (xsize * 254 + dpix * 5) / (dpix * 10); + pScreen->mmHeight = (ysize * 254 + dpiy * 5) / (dpiy * 10); +*/ +static int +process_screen_size_msg(int width, int height, int bpp) +{ + RRScreenSizePtr pSize; + int mmwidth; + int mmheight; + int error; + + ErrorF("process_screen_size_msg: set width %d height %d bpp %d\n", + width, height, bpp); + g_rdpScreen.rdp_width = width; + g_rdpScreen.rdp_height = height; + g_rdpScreen.rdp_bpp = bpp; + if (bpp < 15) + { + g_rdpScreen.rdp_Bpp = 1; + g_rdpScreen.rdp_Bpp_mask = 0xff; + } + else if (bpp == 15) + { + g_rdpScreen.rdp_Bpp = 2; + g_rdpScreen.rdp_Bpp_mask = 0x7fff; + } + else if (bpp == 16) + { + g_rdpScreen.rdp_Bpp = 2; + g_rdpScreen.rdp_Bpp_mask = 0xffff; + } + else if (bpp > 16) + { + g_rdpScreen.rdp_Bpp = 4; + g_rdpScreen.rdp_Bpp_mask = 0xffffff; + } + mmwidth = PixelToMM(width); + mmheight = PixelToMM(height); + pSize = RRRegisterSize(g_pScreen, width, height, mmwidth, mmheight); + RRSetCurrentConfig(g_pScreen, RR_Rotate_0, 0, pSize); + if ((g_rdpScreen.width != width) || (g_rdpScreen.height != height)) + { + error = RRSetScreenConfig(g_pScreen, RR_Rotate_0, 0, pSize); + if (error == BadImplementation) + { + ErrorF("process_screen_size_msg: RRSetScreenConfig returned " + "BadImplementation\n"); + } + } +} + +/******************************************************************************/ +static int +l_bound_by(int val, int low, int high) +{ + if (val > high) + { + val = high; + } + if (val < low) + { + val = low; + } + return val; +} + +/******************************************************************************/ +static int +rdpup_process_msg(struct stream* s) +{ + int msg_type; + int msg; + int param1; + int param2; + int param3; + int param4; + + in_uint16_le(s, msg_type); + if (msg_type == 103) + { + in_uint32_le(s, msg); + in_uint32_le(s, param1); + in_uint32_le(s, param2); + in_uint32_le(s, param3); + in_uint32_le(s, param4); + DEBUG_OUT_UP(("rdpup_process_msg - msg %d param1 %d param2 %d param3 %d \ +param4 %d\n", msg, param1, param2, param3, param4)); + switch (msg) + { + case 15: /* key down */ + case 16: /* key up */ + KbdAddEvent(msg == 15, param1, param2, param3, param4); + break; + case 17: /* from RDP_INPUT_SYNCHRONIZE */ + KbdSync(param1); + break; + case 100: + /* without the minus 2, strange things happen when dragging + past the width or height */ + g_cursor_x = l_bound_by(param1, 0, g_rdpScreen.width - 2); + g_cursor_y = l_bound_by(param2, 0, g_rdpScreen.height - 2); + PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y); + break; + case 101: + g_button_mask = g_button_mask & (~1); + PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y); + break; + case 102: + g_button_mask = g_button_mask | 1; + PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y); + break; + case 103: + g_button_mask = g_button_mask & (~4); + PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y); + break; + case 104: + g_button_mask = g_button_mask | 4; + PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y); + break; + case 105: + g_button_mask = g_button_mask & (~2); + PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y); + break; + case 106: + g_button_mask = g_button_mask | 2; + PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y); + break; + case 107: + g_button_mask = g_button_mask & (~8); + PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y); + break; + case 108: + g_button_mask = g_button_mask | 8; + PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y); + break; + case 109: + g_button_mask = g_button_mask & (~16); + PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y); + break; + case 110: + g_button_mask = g_button_mask | 16; + PtrAddEvent(g_button_mask, g_cursor_x, g_cursor_y); + break; + case 200: + rdpup_begin_update(); + rdpup_send_area((param1 >> 16) & 0xffff, param1 & 0xffff, + (param2 >> 16) & 0xffff, param2 & 0xffff); + rdpup_end_update(); + break; + case 300: + process_screen_size_msg(param1, param2, param3); + break; + } + } + else + { + rdpLog("unknown message type in rdpup_process_msg\n"); + } + return 0; +} + +/******************************************************************************/ +int +rdpup_init(void) +{ + char text[256]; + int i; + + i = atoi(display); + if (i < 1) + { + return 0; + } + g_sprintf(text, "62%2.2d", i); + if (g_in_s == 0) + { + make_stream(g_in_s); + init_stream(g_in_s, 8192); + } + if (g_out_s == 0) + { + make_stream(g_out_s); + init_stream(g_out_s, 8192 * g_Bpp + 100); + } + if (g_listen_sck == 0) + { + g_listen_sck = g_tcp_socket(); + if (g_tcp_bind(g_listen_sck, text) != 0) + { + return 0; + } + g_tcp_listen(g_listen_sck); + AddEnabledDevice(g_listen_sck); + } + g_dis_listen_sck = g_tcp_local_socket_dgram(); + if (g_dis_listen_sck != 0) + { + g_sprintf(text, "/tmp/.xrdp/xrdp_disconnect_display_%s", display); + if (g_tcp_local_bind(g_dis_listen_sck, text) == 0) + { + AddEnabledDevice(g_dis_listen_sck); + } + else + { + rdpLog("g_tcp_local_bind failed [%s]\n", text); + } + } + return 1; +} + +/******************************************************************************/ +int +rdpup_check(void) +{ + int sel; + int new_sck; + char buf[8]; + + sel = g_tcp_select(g_listen_sck, g_sck, g_dis_listen_sck); + if (sel & 1) + { + new_sck = g_tcp_accept(g_listen_sck); + if (new_sck == -1) + { + } + else + { + if (g_sck != 0) + { + /* should maybe ask is user wants to allow here with timeout */ + rdpLog("replacing connection, already got a connection\n"); + RemoveEnabledDevice(g_sck); + g_connected = 0; + g_tcp_close(g_sck); + g_sck = 0; + g_sck_closed = 1; + } + rdpLog("got a connection\n"); + g_sck = new_sck; + g_tcp_set_non_blocking(g_sck); + g_tcp_set_no_delay(g_sck); + g_connected = 1; + g_sck_closed = 0; + g_begin = 0; + AddEnabledDevice(g_sck); + } + } + if (sel & 2) + { + if (rdpup_recv_msg(g_in_s) == 0) + { + rdpup_process_msg(g_in_s); + } + } + if (sel & 4) + { + if (g_tcp_recv(g_dis_listen_sck, buf, 4, 0) > 0) + { + if (g_sck != 0) + { + rdpLog("disconnecting session via user request\n"); + RemoveEnabledDevice(g_sck); + g_connected = 0; + g_tcp_close(g_sck); + g_sck = 0; + g_sck_closed = 1; + } + } + } + return 0; +} + +/******************************************************************************/ +int +rdpup_begin_update(void) +{ + if (g_connected) + { + if (g_begin) + { + return 0; + } + init_stream(g_out_s, 0); + s_push_layer(g_out_s, iso_hdr, 8); + out_uint16_le(g_out_s, 1); + DEBUG_OUT_UP(("begin %d\n", g_count)); + g_begin = 1; + g_count = 1; + } + return 0; +} + +/******************************************************************************/ +int +rdpup_end_update(void) +{ + if (g_connected && g_begin) + { + rdpScheduleDeferredUpdate(); + } + return 0; +} + +/******************************************************************************/ +int +rdpup_pre_check(int in_size) +{ + if (!g_begin) + { + rdpup_begin_update(); + } + if ((g_out_s->p - g_out_s->data) > (g_out_s->size - (in_size + 20))) + { + s_mark_end(g_out_s); + rdpup_send_msg(g_out_s); + g_count = 0; + init_stream(g_out_s, 0); + s_push_layer(g_out_s, iso_hdr, 8); + } + return 0; +} + +/******************************************************************************/ +int +rdpup_fill_rect(short x, short y, int cx, int cy) +{ + if (g_connected) + { + DEBUG_OUT_UP((" rdpup_fill_rect\n")); + rdpup_pre_check(10); + out_uint16_le(g_out_s, 3); + g_count++; + out_uint16_le(g_out_s, x); + out_uint16_le(g_out_s, y); + out_uint16_le(g_out_s, cx); + out_uint16_le(g_out_s, cy); + } + return 0; +} + +/******************************************************************************/ +int +rdpup_screen_blt(short x, short y, int cx, int cy, short srcx, short srcy) +{ + if (g_connected) + { + DEBUG_OUT_UP((" rdpup_screen_blt\n")); + rdpup_pre_check(14); + out_uint16_le(g_out_s, 4); + g_count++; + out_uint16_le(g_out_s, x); + out_uint16_le(g_out_s, y); + out_uint16_le(g_out_s, cx); + out_uint16_le(g_out_s, cy); + out_uint16_le(g_out_s, srcx); + out_uint16_le(g_out_s, srcy); + } + return 0; +} + +/******************************************************************************/ +int +rdpup_set_clip(short x, short y, int cx, int cy) +{ + if (g_connected) + { + DEBUG_OUT_UP((" rdpup_set_clip\n")); + rdpup_pre_check(10); + out_uint16_le(g_out_s, 10); + g_count++; + out_uint16_le(g_out_s, x); + out_uint16_le(g_out_s, y); + out_uint16_le(g_out_s, cx); + out_uint16_le(g_out_s, cy); + } + return 0; +} + +/******************************************************************************/ +int +rdpup_reset_clip(void) +{ + if (g_connected) + { + DEBUG_OUT_UP((" rdpup_reset_clip\n")); + rdpup_pre_check(2); + out_uint16_le(g_out_s, 11); + g_count++; + } + return 0; +} + +#define COLOR8(r, g, b) \ + ((((r) >> 5) << 0) | (((g) >> 5) << 3) | (((b) >> 6) << 6)) +#define COLOR15(r, g, b) \ + ((((r) >> 3) << 10) | (((g) >> 3) << 5) | (((b) >> 3) << 0)) +#define COLOR16(r, g, b) \ + ((((r) >> 3) << 11) | (((g) >> 2) << 5) | (((b) >> 3) << 0)) +#define COLOR24(r, g, b) \ + ((((r) >> 0) << 0) | (((g) >> 0) << 8) | (((b) >> 0) << 16)) +#define SPLITCOLOR32(r, g, b, c) \ +{ \ + r = ((c) >> 16) & 0xff; \ + g = ((c) >> 8) & 0xff; \ + b = (c) & 0xff; \ +} + +int +convert_pixel(int in_pixel) +{ + int red; + int green; + int blue; + int rv; + + rv = 0; + if (g_rdpScreen.depth == 24) + { + if (g_rdpScreen.rdp_bpp == 24) + { + rv = in_pixel; + SPLITCOLOR32(red, green, blue, rv); + rv = COLOR24(red, green, blue); + } + else if (g_rdpScreen.rdp_bpp == 16) + { + rv = in_pixel; + SPLITCOLOR32(red, green, blue, rv); + rv = COLOR16(red, green, blue); + } + else if (g_rdpScreen.rdp_bpp == 15) + { + rv = in_pixel; + SPLITCOLOR32(red, green, blue, rv); + rv = COLOR15(red, green, blue); + } + else if (g_rdpScreen.rdp_bpp == 8) + { + rv = in_pixel; + SPLITCOLOR32(red, green, blue, rv); + rv = COLOR8(red, green, blue); + } + } + else if (g_rdpScreen.depth == g_rdpScreen.rdp_bpp) + { + return in_pixel; + } + return rv; +} + +int +convert_pixels(void* src, void* dst, int num_pixels) +{ + unsigned int pixel; + unsigned int red; + unsigned int green; + unsigned int blue; + unsigned int* src32; + unsigned int* dst32; + unsigned short* dst16; + unsigned char* dst8; + int index; + + if (g_rdpScreen.depth == g_rdpScreen.rdp_bpp) + { + memcpy(dst, src, num_pixels * g_Bpp); + return 0; + } + if (g_rdpScreen.depth == 24) + { + src32 = (unsigned int*)src; + if (g_rdpScreen.rdp_bpp == 24) + { + dst32 = (unsigned int*)dst; + for (index = 0; index < num_pixels; index++) + { + pixel = *src32; + *dst32 = pixel; + dst32++; + src32++; + } + } + else if (g_rdpScreen.rdp_bpp == 16) + { + dst16 = (unsigned short*)dst; + for (index = 0; index < num_pixels; index++) + { + pixel = *src32; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR16(red, green, blue); + *dst16 = pixel; + dst16++; + src32++; + } + } + else if (g_rdpScreen.rdp_bpp == 15) + { + dst16 = (unsigned short*)dst; + for (index = 0; index < num_pixels; index++) + { + pixel = *src32; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR15(red, green, blue); + *dst16 = pixel; + dst16++; + src32++; + } + } + else if (g_rdpScreen.rdp_bpp == 8) + { + dst8 = (unsigned char*)dst; + for (index = 0; index < num_pixels; index++) + { + pixel = *src32; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR8(red, green, blue); + *dst8 = pixel; + dst8++; + src32++; + } + } + } + return 0; +} + +/******************************************************************************/ +int +rdpup_set_fgcolor(int fgcolor) +{ + if (g_connected) + { + DEBUG_OUT_UP((" rdpup_set_fgcolor\n")); + rdpup_pre_check(6); + out_uint16_le(g_out_s, 12); + g_count++; + fgcolor = fgcolor & g_Bpp_mask; + fgcolor = convert_pixel(fgcolor) & g_rdpScreen.rdp_Bpp_mask; + out_uint32_le(g_out_s, fgcolor); + } + return 0; +} + +/******************************************************************************/ +int +rdpup_set_bgcolor(int bgcolor) +{ + if (g_connected) + { + DEBUG_OUT_UP((" rdpup_set_bgcolor\n")); + rdpup_pre_check(6); + out_uint16_le(g_out_s, 13); + g_count++; + bgcolor = bgcolor & g_Bpp_mask; + bgcolor = convert_pixel(bgcolor) & g_rdpScreen.rdp_Bpp_mask; + out_uint32_le(g_out_s, bgcolor); + } + return 0; +} + +/******************************************************************************/ +int +rdpup_set_opcode(int opcode) +{ + if (g_connected) + { + DEBUG_OUT_UP((" rdpup_set_opcode\n")); + rdpup_pre_check(4); + out_uint16_le(g_out_s, 14); + g_count++; + out_uint16_le(g_out_s, g_rdp_opcodes[opcode & 0xf]); + } + return 0; +} + +/******************************************************************************/ +int +rdpup_set_pen(int style, int width) +{ + if (g_connected) + { + DEBUG_OUT_UP((" rdpup_set_pen\n")); + rdpup_pre_check(6); + out_uint16_le(g_out_s, 17); + g_count++; + out_uint16_le(g_out_s, style); + out_uint16_le(g_out_s, width); + } + return 0; +} + +/******************************************************************************/ +int +rdpup_draw_line(short x1, short y1, short x2, short y2) +{ + if (g_connected) + { + DEBUG_OUT_UP((" rdpup_draw_line\n")); + rdpup_pre_check(10); + out_uint16_le(g_out_s, 18); + g_count++; + out_uint16_le(g_out_s, x1); + out_uint16_le(g_out_s, y1); + out_uint16_le(g_out_s, x2); + out_uint16_le(g_out_s, y2); + } + return 0; +} + +/******************************************************************************/ +int +rdpup_set_cursor(short x, short y, char* cur_data, char* cur_mask) +{ + if (g_connected) + { + DEBUG_OUT_UP((" rdpup_set_cursor\n")); + rdpup_pre_check(6 + 32 * (32 * 3) + 32 * (32 / 8)); + out_uint16_le(g_out_s, 19); + g_count++; + x = MAX(0, x); + x = MIN(31, x); + y = MAX(0, y); + y = MIN(31, y); + out_uint16_le(g_out_s, x); + out_uint16_le(g_out_s, y); + out_uint8a(g_out_s, cur_data, 32 * (32 * 3)); + out_uint8a(g_out_s, cur_mask, 32 * (32 / 8)); + } + return 0; +} + +/******************************************************************************/ +static int +get_single_color(int x, int y, int w, int h) +{ + int rv; + int i; + int j; + int p; + unsigned char* i8; + unsigned short* i16; + unsigned int* i32; + + rv = -1; + if (g_Bpp == 1) + { + for (i = 0; i < h; i++) + { + i8 = (unsigned char*)(g_rdpScreen.pfbMemory + + ((y + i) * g_rdpScreen.paddedWidthInBytes) + (x * g_Bpp)); + if (i == 0) + { + p = *i8; + } + for (j = 0; j < w; j++) + { + if (i8[j] != p) + { + return -1; + } + } + } + rv = p; + } + else if (g_Bpp == 2) + { + for (i = 0; i < h; i++) + { + i16 = (unsigned short*)(g_rdpScreen.pfbMemory + + ((y + i) * g_rdpScreen.paddedWidthInBytes) + (x * g_Bpp)); + if (i == 0) + { + p = *i16; + } + for (j = 0; j < w; j++) + { + if (i16[j] != p) + { + return -1; + } + } + } + rv = p; + } + else if (g_Bpp == 4) + { + for (i = 0; i < h; i++) + { + i32 = (unsigned int*)(g_rdpScreen.pfbMemory + + ((y + i) * g_rdpScreen.paddedWidthInBytes) + (x * g_Bpp)); + if (i == 0) + { + p = *i32; + } + for (j = 0; j < w; j++) + { + if (i32[j] != p) + { + return -1; + } + } + } + rv = p; + } + return rv; +} + +/******************************************************************************/ +/* split the bitmap up into 64 x 64 pixel areas */ +void +rdpup_send_area(int x, int y, int w, int h) +{ + char* s; + int i; + int single_color; + int lx; + int ly; + int lh; + int lw; + + if (x >= g_rdpScreen.width) + { + return; + } + if (y >= g_rdpScreen.height) + { + return; + } + if (x < 0) + { + w += x; + x = 0; + } + if (y < 0) + { + h += y; + y = 0; + } + if (w <= 0) + { + return; + } + if (h <= 0) + { + return; + } + if (x + w > g_rdpScreen.width) + { + w = g_rdpScreen.width - x; + } + if (y + h > g_rdpScreen.height) + { + h = g_rdpScreen.height - y; + } + DEBUG_OUT_UP(("%d\n", w * h)); + if (g_connected && g_begin) + { + DEBUG_OUT_UP((" rdpup_send_area\n")); + ly = y; + while (ly < y + h) + { + lx = x; + while (lx < x + w) + { + lw = MIN(64, (x + w) - lx); + lh = MIN(64, (y + h) - ly); + single_color = get_single_color(lx, ly, lw, lh); + if (single_color != -1) + { + DEBUG_OUT_UP(("%d sending single color\n", g_count)); + rdpup_set_fgcolor(single_color); + rdpup_fill_rect(lx, ly, lw, lh); + } + else + { + rdpup_pre_check(lw * lh * g_rdpScreen.rdp_Bpp + 42); + out_uint16_le(g_out_s, 5); + g_count++; + out_uint16_le(g_out_s, lx); + out_uint16_le(g_out_s, ly); + out_uint16_le(g_out_s, lw); + out_uint16_le(g_out_s, lh); + out_uint32_le(g_out_s, lw * lh * g_rdpScreen.rdp_Bpp); + for (i = 0; i < lh; i++) + { + s = (g_rdpScreen.pfbMemory + + ((ly + i) * g_rdpScreen.paddedWidthInBytes) + (lx * g_Bpp)); + convert_pixels(s, g_out_s->p, lw); + g_out_s->p += lw * g_rdpScreen.rdp_Bpp; + } + out_uint16_le(g_out_s, lw); + out_uint16_le(g_out_s, lh); + out_uint16_le(g_out_s, 0); + out_uint16_le(g_out_s, 0); + } + lx += 64; + } + ly += 64; + } + } +}