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