diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | auth.c | 2 | ||||
-rw-r--r-- | cursor.c | 4 | ||||
-rw-r--r-- | example.c | 14 | ||||
-rw-r--r-- | httpd.c | 4 | ||||
-rw-r--r-- | main.c | 8 | ||||
-rw-r--r-- | pnmshow.c | 2 | ||||
-rw-r--r-- | rfb.h | 13 | ||||
-rw-r--r-- | rfbserver.c | 8 | ||||
-rwxr-xr-x | sraRegion.c | 1658 | ||||
-rwxr-xr-x | sraRegion.h | 120 | ||||
-rw-r--r-- | tight.c | 13 | ||||
-rw-r--r-- | vncauth.c | 1 |
13 files changed, 927 insertions, 924 deletions
@@ -2,7 +2,7 @@ INCLUDES=-I. VNCSERVERLIB=-L. -lvncserver -L/usr/local/lib -lz -ljpeg # for Solaris -#CC=gcc +CC=gcc #EXTRALIBS=-lsocket -lnsl -L/usr/X/lib # for FreeBSD @@ -16,7 +16,7 @@ VNCSERVERLIB=-L. -lvncserver -L/usr/local/lib -lz -ljpeg # The code for 3 Bytes/Pixel is not very efficient! FLAG24 = -DALLOW24BPP -OPTFLAGS=-g -Wall +OPTFLAGS=-g -Wall -pedantic #OPTFLAGS=-O2 -Wall CFLAGS=$(OPTFLAGS) $(PTHREADDEF) $(FLAG24) $(INCLUDES) $(EXTRAINCLUDES) -DBACKCHANNEL RANLIB=ranlib @@ -84,7 +84,7 @@ rfbAuthProcessClientMessage(cl) return; } - if(!cl->screen->passwordCheck(cl,response,CHALLENGESIZE)) { + if(!cl->screen->passwordCheck(cl,(const char*)response,CHALLENGESIZE)) { rfbLog("rfbAuthProcessClientMessage: password check failed\n"); authResult = Swap32IfLE(rfbVncAuthFailed); if (WriteExact(cl, (char *)&authResult, 4) < 0) { @@ -143,7 +143,7 @@ rfbSendCursorShape(cl) bpp2=cl->format.bitsPerPixel/8; (*cl->translateFn)(cl->translateLookupTable, &(cl->screen->rfbServerFormat), - &cl->format, pCursor->richSource, + &cl->format, (char*)pCursor->richSource, &cl->updateBuf[cl->ublen], pCursor->width*bpp1, pCursor->width, pCursor->height); @@ -241,7 +241,7 @@ rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskSt for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++) if(*cp!=' ') cursor->mask[j*w+i/8]|=bit; } else - cursor->mask = (unsigned char*)rfbMakeMaskForXCursor(width,height,cursor->source); + cursor->mask = (unsigned char*)rfbMakeMaskForXCursor(width,height,(char*)cursor->source); return(cursor); } @@ -79,14 +79,14 @@ enum rfbNewClientAction newclient(rfbClientPtr cl) void newframebuffer(rfbScreenInfoPtr screen, int width, int height) { - char *oldfb, *newfb; + unsigned char *oldfb, *newfb; maxx = width; maxy = height; - oldfb = screen->frameBuffer; - newfb = (char*)malloc(maxx * maxy * bpp); + oldfb = (unsigned char*)screen->frameBuffer; + newfb = (unsigned char*)malloc(maxx * maxy * bpp); initBuffer(newfb); - rfbNewFramebuffer(screen, newfb, maxx, maxy, 8, 3, bpp); + rfbNewFramebuffer(screen, (char*)newfb, maxx, maxy, 8, 3, bpp); free(oldfb); /*** FIXME: Re-install cursor. ***/ @@ -133,7 +133,7 @@ void doptr(int buttonMask,int x,int y,rfbClientPtr cl) int i,j,x1,x2,y1,y2; if(cd->oldButton==buttonMask) { /* draw a line */ - drawline(cl->screen->frameBuffer,cl->screen->paddedWidthInBytes,bpp, + drawline((unsigned char*)cl->screen->frameBuffer,cl->screen->paddedWidthInBytes,bpp, x,y,cd->oldx,cd->oldy); rfbMarkRectAsModified(cl->screen,x,y,cd->oldx,cd->oldy); } else { /* draw a point (diameter depends on button) */ @@ -174,7 +174,7 @@ void dokey(Bool down,KeySym key,rfbClientPtr cl) else if(key==XK_Page_Up) { if(cl->screen->cursorIsDrawn) rfbUndrawCursor(cl->screen); - initBuffer(cl->screen->frameBuffer); + initBuffer((unsigned char*)cl->screen->frameBuffer); rfbMarkRectAsModified(cl->screen,0,0,maxx,maxy); } else if (key == XK_Up) { if (maxx < 1024) { @@ -283,7 +283,7 @@ int main(int argc,char** argv) rfbScreen->newClientHook = newclient; rfbScreen->httpDir = "./classes"; - initBuffer(rfbScreen->frameBuffer); + initBuffer((unsigned char*)rfbScreen->frameBuffer); rfbDrawString(rfbScreen,&radonFont,20,100,"Hello, World!",0xffffff); /* This call creates a mask and then a cursor: */ @@ -22,6 +22,7 @@ */ #include <stdio.h> +#include <unistd.h> #include <sys/types.h> #ifdef WIN32 #include <winsock.h> @@ -68,7 +69,6 @@ FILE* httpFP = NULL; static char buf[BUF_SIZE]; static size_t buf_filled=0; - /* * httpInitSockets sets up the TCP socket to listen for HTTP connections. */ @@ -303,7 +303,7 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen) /* Open the file */ - if ((fd = fopen(fullFname, "r")) <= 0) { + if ((fd = fopen(fullFname, "r")) == 0) { rfbLogPerror("httpProcessInput: open"); WriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); httpCloseSock(rfbScreen); @@ -32,7 +32,9 @@ #include "rfb.h" #include "sraRegion.h" +#ifdef HAVE_PTHREADS MUTEX(logMutex); +#endif int rfbEnableLogging=1; @@ -380,11 +382,11 @@ void defaultSetXCutText(char* text, int len, rfbClientPtr cl) /* TODO: add a nice VNC or RFB cursor */ -#if defined(WIN32) || defined(sparc) +#if defined(WIN32) || defined(sparc) || !defined(NO_STRICT_ANSI) static rfbCursor myCursor = { - "\000\102\044\030\044\102\000", - "\347\347\176\074\176\347\347", + (unsigned char*)"\000\102\044\030\044\102\000", + (unsigned char*)"\347\347\176\074\176\347\347", 8, 7, 3, 3, 0, 0, 0, 0xffff, 0xffff, 0xffff, @@ -12,7 +12,7 @@ int main(int argc,char** argv) { FILE* in=stdin; int i,j,k,width,height,paddedWidth; - unsigned char buffer[1024]; + char buffer[1024]; rfbScreenInfoPtr rfbScreen; if(argc>1) { @@ -45,12 +45,9 @@ typedef CARD32 Pixel; /* typedef CARD32 KeySym; */ typedef unsigned long KeySym; #define SIGNED signed -/* for some strange reason, "typedef signed char Bool;" yields a four byte - signed int on IRIX, but only for rfbserver.o!!! */ -#ifdef Bool -#undef Bool -#endif -#define Bool signed char + +typedef signed char Bool; + #undef FALSE #define FALSE 0 #undef TRUE @@ -90,6 +87,10 @@ typedef unsigned long KeySym; #include <sys/endian.h> #endif +#ifdef __sgi__ +typedef int socklen_t; +#endif + #ifndef _BYTE_ORDER #define _BYTE_ORDER __BYTE_ORDER #endif diff --git a/rfbserver.c b/rfbserver.c index f2dfada..bfc2e91 100644 --- a/rfbserver.c +++ b/rfbserver.c @@ -25,6 +25,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "rfb.h" #include "sraRegion.h" #ifdef WIN32 @@ -76,7 +77,9 @@ void rfbIncrClientRef(rfbClientPtr cl) {} void rfbDecrClientRef(rfbClientPtr cl) {} #endif +#ifdef HAVE_PTHREADS MUTEX(rfbClientListMutex); +#endif struct rfbClientIterator { rfbClientPtr next; @@ -86,6 +89,11 @@ struct rfbClientIterator { void rfbClientListInit(rfbScreenInfoPtr rfbScreen) { + if(sizeof(Bool)!=1) { + /* a sanity check */ + fprintf(stderr,"Bool's size is not 1 (%d)!\n",sizeof(Bool)); + exit(1); + } rfbScreen->rfbClientHead = NULL; INIT_MUTEX(rfbClientListMutex); } diff --git a/sraRegion.c b/sraRegion.c index f94f4d4..47f3e78 100755 --- a/sraRegion.c +++ b/sraRegion.c @@ -1,829 +1,829 @@ -/* -=- sraRegion.c
- * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin
- *
- * A general purpose region clipping library
- * Only deals with rectangular regions, though.
- */
-
-#include "rfb.h"
-#include "sraRegion.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-
-/* -=- Internal Span structure */
-
-struct sraRegion;
-
-typedef struct sraSpan {
- struct sraSpan *_next;
- struct sraSpan *_prev;
- int start;
- int end;
- struct sraRegion *subspan;
-} sraSpan;
-
-typedef struct sraRegion {
- sraSpan front;
- sraSpan back;
-} sraSpanList;
-
-/* -=- Span routines */
-
-sraSpanList *sraSpanListDup(const sraSpanList *src);
-void sraSpanListDestroy(sraSpanList *list);
-
-sraSpan *
-sraSpanCreate(int start, int end, const sraSpanList *subspan) {
- sraSpan *item = (sraSpan*)malloc(sizeof(sraSpan));
- item->_next = item->_prev = NULL;
- item->start = start;
- item->end = end;
- item->subspan = sraSpanListDup(subspan);
- return item;
-}
-
-sraSpan *
-sraSpanDup(const sraSpan *src) {
- sraSpan *span;
- if (!src) return NULL;
- span = sraSpanCreate(src->start, src->end, src->subspan);
- return span;
-}
-
-void
-sraSpanInsertAfter(sraSpan *newspan, sraSpan *after) {
- newspan->_next = after->_next;
- newspan->_prev = after;
- after->_next->_prev = newspan;
- after->_next = newspan;
-}
-
-void
-sraSpanInsertBefore(sraSpan *newspan, sraSpan *before) {
- newspan->_next = before;
- newspan->_prev = before->_prev;
- before->_prev->_next = newspan;
- before->_prev = newspan;
-}
-
-void
-sraSpanRemove(sraSpan *span) {
- span->_prev->_next = span->_next;
- span->_next->_prev = span->_prev;
-}
-
-void
-sraSpanDestroy(sraSpan *span) {
- if (span->subspan) sraSpanListDestroy(span->subspan);
- free(span);
-}
-
-void
-sraSpanCheck(const sraSpan *span, const char *text) {
- /* Check the span is valid! */
- if (span->start == span->end) {
- printf(text);
- printf(":%d-%d\n", span->start, span->end);
- exit(0);
- }
-}
-
-/* -=- SpanList routines */
-
-void sraSpanPrint(const sraSpan *s);
-
-void
-sraSpanListPrint(const sraSpanList *l) {
- sraSpan *curr;
- if (!l) {
- printf("NULL");
- return;
- }
- curr = l->front._next;
- printf("[");
- while (curr != &(l->back)) {
- sraSpanPrint(curr);
- curr = curr->_next;
- }
- printf("]");
-}
-
-void
-sraSpanPrint(const sraSpan *s) {
- printf("(%d-%d)", (s->start), (s->end));
- if (s->subspan)
- sraSpanListPrint(s->subspan);
-}
-
-sraSpanList *
-sraSpanListCreate() {
- sraSpanList *item = (sraSpanList*)malloc(sizeof(sraSpanList));
- item->front._next = &(item->back);
- item->front._prev = NULL;
- item->back._prev = &(item->front);
- item->back._next = NULL;
- return item;
-}
-
-sraSpanList *
-sraSpanListDup(const sraSpanList *src) {
- sraSpanList *newlist;
- sraSpan *newspan, *curr;
-
- if (!src) return NULL;
- newlist = sraSpanListCreate();
- curr = src->front._next;
- while (curr != &(src->back)) {
- newspan = sraSpanDup(curr);
- sraSpanInsertBefore(newspan, &(newlist->back));
- curr = curr->_next;
- }
-
- return newlist;
-}
-
-void
-sraSpanListDestroy(sraSpanList *list) {
- sraSpan *curr, *next;
- while (list->front._next != &(list->back)) {
- curr = list->front._next;
- next = curr->_next;
- sraSpanRemove(curr);
- sraSpanDestroy(curr);
- curr = next;
- }
- free(list);
-}
-
-void
-sraSpanListMakeEmpty(sraSpanList *list) {
- sraSpan *curr, *next;
- while (list->front._next != &(list->back)) {
- curr = list->front._next;
- next = curr->_next;
- sraSpanRemove(curr);
- sraSpanDestroy(curr);
- curr = next;
- }
- list->front._next = &(list->back);
- list->front._prev = NULL;
- list->back._prev = &(list->front);
- list->back._next = NULL;
-}
-
-Bool
-sraSpanListEqual(const sraSpanList *s1, const sraSpanList *s2) {
- sraSpan *sp1, *sp2;
-
- if (!s1) {
- if (!s2) {
- return 1;
- } else {
- printf("sraSpanListEqual:incompatible spans (only one NULL!)\n");
- exit(1);
- }
- }
-
- sp1 = s1->front._next;
- sp2 = s2->front._next;
- while ((sp1 != &(s1->back)) &&
- (sp2 != &(s2->back))) {
- if ((sp1->start != sp2->start) ||
- (sp1->end != sp2->end) ||
- (!sraSpanListEqual(sp1->subspan, sp2->subspan))) {
- return 0;
- }
- sp1 = sp1->_next;
- sp2 = sp2->_next;
- }
-
- if ((sp1 == &(s1->back)) && (sp2 == &(s2->back))) {
- return 1;
- } else {
- return 0;
- }
-}
-
-Bool
-sraSpanListEmpty(const sraSpanList *list) {
- return (list->front._next == &(list->back));
-}
-
-unsigned long
-sraSpanListCount(const sraSpanList *list) {
- sraSpan *curr = list->front._next;
- unsigned long count = 0;
- while (curr != &(list->back)) {
- if (curr->subspan) {
- count += sraSpanListCount(curr->subspan);
- } else {
- count += 1;
- }
- curr = curr->_next;
- }
- return count;
-}
-
-void
-sraSpanMergePrevious(sraSpan *dest) {
- sraSpan *prev = dest->_prev;
- while ((prev->end == dest->start) &&
- (prev->_prev) &&
- (sraSpanListEqual(prev->subspan, dest->subspan))) {
- /*
- printf("merge_prev:");
- sraSpanPrint(prev);
- printf(" & ");
- sraSpanPrint(dest);
- printf("\n");
- */
- dest->start = prev->start;
- sraSpanRemove(prev);
- sraSpanDestroy(prev);
- prev = dest->_prev;
- }
-}
-
-void
-sraSpanMergeNext(sraSpan *dest) {
- sraSpan *next = dest->_next;
- while ((next->start == dest->end) &&
- (next->_next) &&
- (sraSpanListEqual(next->subspan, dest->subspan))) {
-/*
- printf("merge_next:");
- sraSpanPrint(dest);
- printf(" & ");
- sraSpanPrint(next);
- printf("\n");
- */
- dest->end = next->end;
- sraSpanRemove(next);
- sraSpanDestroy(next);
- next = dest->_next;
- }
-}
-
-void
-sraSpanListOr(sraSpanList *dest, const sraSpanList *src) {
- sraSpan *d_curr, *s_curr;
- int s_start, s_end;
-
- if (!dest) {
- if (!src) {
- return;
- } else {
- printf("sraSpanListOr:incompatible spans (only one NULL!)\n");
- exit(1);
- }
- }
-
- d_curr = dest->front._next;
- s_curr = src->front._next;
- s_start = s_curr->start;
- s_end = s_curr->end;
- while (s_curr != &(src->back)) {
-
- /* - If we are at end of destination list OR
- If the new span comes before the next destination one */
- if ((d_curr == &(dest->back)) ||
- (d_curr->start >= s_end)) {
- /* - Add the span */
- sraSpanInsertBefore(sraSpanCreate(s_start, s_end,
- s_curr->subspan),
- d_curr);
- if (d_curr != &(dest->back))
- sraSpanMergePrevious(d_curr);
- s_curr = s_curr->_next;
- s_start = s_curr->start;
- s_end = s_curr->end;
- } else {
-
- /* - If the new span overlaps the existing one */
- if ((s_start < d_curr->end) &&
- (s_end > d_curr->start)) {
-
- /* - Insert new span before the existing destination one? */
- if (s_start < d_curr->start) {
- sraSpanInsertBefore(sraSpanCreate(s_start,
- d_curr->start,
- s_curr->subspan),
- d_curr);
- sraSpanMergePrevious(d_curr);
- }
-
- /* Split the existing span if necessary */
- if (s_end < d_curr->end) {
- sraSpanInsertAfter(sraSpanCreate(s_end,
- d_curr->end,
- d_curr->subspan),
- d_curr);
- d_curr->end = s_end;
- }
- if (s_start > d_curr->start) {
- sraSpanInsertBefore(sraSpanCreate(d_curr->start,
- s_start,
- d_curr->subspan),
- d_curr);
- d_curr->start = s_start;
- }
-
- /* Recursively OR subspans */
- sraSpanListOr(d_curr->subspan, s_curr->subspan);
-
- /* Merge this span with previous or next? */
- if (d_curr->_prev != &(dest->front))
- sraSpanMergePrevious(d_curr);
- if (d_curr->_next != &(dest->back))
- sraSpanMergeNext(d_curr);
-
- /* Move onto the next pair to compare */
- if (s_end > d_curr->end) {
- s_start = d_curr->end;
- d_curr = d_curr->_next;
- } else {
- s_curr = s_curr->_next;
- s_start = s_curr->start;
- s_end = s_curr->end;
- }
- } else {
- /* - No overlap. Move to the next destination span */
- d_curr = d_curr->_next;
- }
- }
- }
-}
-
-Bool
-sraSpanListAnd(sraSpanList *dest, const sraSpanList *src) {
- sraSpan *d_curr, *s_curr, *d_next;
-
- if (!dest) {
- if (!src) {
- return 1;
- } else {
- printf("sraSpanListAnd:incompatible spans (only one NULL!)\n");
- exit(1);
- }
- }
-
- d_curr = dest->front._next;
- s_curr = src->front._next;
- while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
-
- /* - If we haven't reached a destination span yet then move on */
- if (d_curr->start >= s_curr->end) {
- s_curr = s_curr->_next;
- continue;
- }
-
- /* - If we are beyond the current destination span then remove it */
- if (d_curr->end <= s_curr->start) {
- sraSpan *next = d_curr->_next;
- sraSpanRemove(d_curr);
- sraSpanDestroy(d_curr);
- d_curr = next;
- continue;
- }
-
- /* - If we partially overlap a span then split it up or remove bits */
- if (s_curr->start > d_curr->start) {
- /* - The top bit of the span does not match */
- d_curr->start = s_curr->start;
- }
- if (s_curr->end < d_curr->end) {
- /* - The end of the span does not match */
- sraSpanInsertAfter(sraSpanCreate(s_curr->end,
- d_curr->end,
- d_curr->subspan),
- d_curr);
- d_curr->end = s_curr->end;
- }
-
- /* - Now recursively process the affected span */
- if (!sraSpanListAnd(d_curr->subspan, s_curr->subspan)) {
- /* - The destination subspan is now empty, so we should remove it */
- sraSpan *next = d_curr->_next;
- sraSpanRemove(d_curr);
- sraSpanDestroy(d_curr);
- d_curr = next;
- } else {
- /* Merge this span with previous or next? */
- if (d_curr->_prev != &(dest->front))
- sraSpanMergePrevious(d_curr);
-
- /* - Move on to the next span */
- d_next = d_curr;
- if (s_curr->end >= d_curr->end) {
- d_next = d_curr->_next;
- }
- if (s_curr->end <= d_curr->end) {
- s_curr = s_curr->_next;
- }
- d_curr = d_next;
- }
- }
-
- while (d_curr != &(dest->back)) {
- sraSpan *next = d_curr->_next;
- sraSpanRemove(d_curr);
- sraSpanDestroy(d_curr);
- d_curr=next;
- }
-
- return !sraSpanListEmpty(dest);
-}
-
-Bool
-sraSpanListSubtract(sraSpanList *dest, const sraSpanList *src) {
- sraSpan *d_curr, *s_curr;
-
- if (!dest) {
- if (!src) {
- return 1;
- } else {
- printf("sraSpanListSubtract:incompatible spans (only one NULL!)\n");
- exit(1);
- }
- }
-
- d_curr = dest->front._next;
- s_curr = src->front._next;
- while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) {
-
- /* - If we haven't reached a destination span yet then move on */
- if (d_curr->start >= s_curr->end) {
- s_curr = s_curr->_next;
- continue;
- }
-
- /* - If we are beyond the current destination span then skip it */
- if (d_curr->end <= s_curr->start) {
- d_curr = d_curr->_next;
- continue;
- }
-
- /* - If we partially overlap the current span then split it up */
- if (s_curr->start > d_curr->start) {
- sraSpanInsertBefore(sraSpanCreate(d_curr->start,
- s_curr->start,
- d_curr->subspan),
- d_curr);
- d_curr->start = s_curr->start;
- }
- if (s_curr->end < d_curr->end) {
- sraSpanInsertAfter(sraSpanCreate(s_curr->end,
- d_curr->end,
- d_curr->subspan),
- d_curr);
- d_curr->end = s_curr->end;
- }
-
- /* - Now recursively process the affected span */
- if ((!d_curr->subspan) || !sraSpanListSubtract(d_curr->subspan, s_curr->subspan)) {
- /* - The destination subspan is now empty, so we should remove it */
- sraSpan *next = d_curr->_next;
- sraSpanRemove(d_curr);
- sraSpanDestroy(d_curr);
- d_curr = next;
- } else {
- /* Merge this span with previous or next? */
- if (d_curr->_prev != &(dest->front))
- sraSpanMergePrevious(d_curr);
- if (d_curr->_next != &(dest->back))
- sraSpanMergeNext(d_curr);
-
- /* - Move on to the next span */
- if (s_curr->end > d_curr->end) {
- d_curr = d_curr->_next;
- } else {
- s_curr = s_curr->_next;
- }
- }
- }
-
- return !sraSpanListEmpty(dest);
-}
-
-/* -=- Region routines */
-
-sraRegion *
-sraRgnCreate() {
- return (sraRegion*)sraSpanListCreate();
-}
-
-sraRegion *
-sraRgnCreateRect(int x1, int y1, int x2, int y2) {
- sraSpanList *vlist, *hlist;
- sraSpan *vspan, *hspan;
-
- /* - Build the horizontal portion of the span */
- hlist = sraSpanListCreate();
- hspan = sraSpanCreate(x1, x2, NULL);
- sraSpanInsertAfter(hspan, &(hlist->front));
-
- /* - Build the vertical portion of the span */
- vlist = sraSpanListCreate();
- vspan = sraSpanCreate(y1, y2, hlist);
- sraSpanInsertAfter(vspan, &(vlist->front));
-
- sraSpanListDestroy(hlist);
-
- return (sraRegion*)vlist;
-}
-
-sraRegion *
-sraRgnCreateRgn(const sraRegion *src) {
- return (sraRegion*)sraSpanListDup((sraSpanList*)src);
-}
-
-void
-sraRgnDestroy(sraRegion *rgn) {
- sraSpanListDestroy((sraSpanList*)rgn);
-}
-
-void
-sraRgnMakeEmpty(sraRegion *rgn) {
- sraSpanListMakeEmpty((sraSpanList*)rgn);
-}
-
-/* -=- Boolean Region ops */
-
-Bool
-sraRgnAnd(sraRegion *dst, const sraRegion *src) {
- return sraSpanListAnd((sraSpanList*)dst, (sraSpanList*)src);
-}
-
-void
-sraRgnOr(sraRegion *dst, const sraRegion *src) {
- sraSpanListOr((sraSpanList*)dst, (sraSpanList*)src);
-}
-
-Bool
-sraRgnSubtract(sraRegion *dst, const sraRegion *src) {
- return sraSpanListSubtract((sraSpanList*)dst, (sraSpanList*)src);
-}
-
-void
-sraRgnOffset(sraRegion *dst, int dx, int dy) {
- sraSpan *vcurr, *hcurr;
-
- vcurr = ((sraSpanList*)dst)->front._next;
- while (vcurr != &(((sraSpanList*)dst)->back)) {
- vcurr->start += dy;
- vcurr->end += dy;
-
- hcurr = vcurr->subspan->front._next;
- while (hcurr != &(vcurr->subspan->back)) {
- hcurr->start += dx;
- hcurr->end += dx;
- hcurr = hcurr->_next;
- }
-
- vcurr = vcurr->_next;
- }
-}
-
-Bool
-sraRgnPopRect(sraRegion *rgn, sraRect *rect, unsigned long flags) {
- sraSpan *vcurr, *hcurr;
- sraSpan *vend, *hend;
- Bool right2left = flags & 2;
- Bool bottom2top = flags & 1;
-
- /* - Pick correct order */
- if (bottom2top) {
- vcurr = ((sraSpanList*)rgn)->back._prev;
- vend = &(((sraSpanList*)rgn)->front);
- } else {
- vcurr = ((sraSpanList*)rgn)->front._next;
- vend = &(((sraSpanList*)rgn)->back);
- }
-
- if (vcurr != vend) {
- rect->y1 = vcurr->start;
- rect->y2 = vcurr->end;
-
- /* - Pick correct order */
- if (right2left) {
- hcurr = vcurr->subspan->back._prev;
- hend = &(vcurr->subspan->front);
- } else {
- hcurr = vcurr->subspan->front._next;
- hend = &(vcurr->subspan->back);
- }
-
- if (hcurr != hend) {
- rect->x1 = hcurr->start;
- rect->x2 = hcurr->end;
-
- sraSpanRemove(hcurr);
- sraSpanDestroy(hcurr);
-
- if (sraSpanListEmpty(vcurr->subspan)) {
- sraSpanRemove(vcurr);
- sraSpanDestroy(vcurr);
- }
-
-#if 0
- printf("poprect:(%dx%d)-(%dx%d)\n",
- rect->x1, rect->y1, rect->x2, rect->y2);
-#endif
- return 1;
- }
- }
-
- return 0;
-}
-
-unsigned long
-sraRgnCountRects(const sraRegion *rgn) {
- unsigned long count = sraSpanListCount((sraSpanList*)rgn);
- return count;
-}
-
-Bool
-sraRgnEmpty(const sraRegion *rgn) {
- return sraSpanListEmpty((sraSpanList*)rgn);
-}
-
-/* iterator stuff */
-sraRectangleIterator *sraRgnGetIterator(sraRegion *s)
-{
- /* these values have to be multiples of 4 */
-#define DEFSIZE 4
-#define DEFSTEP 8
- sraRectangleIterator *i =
- (sraRectangleIterator*)malloc(sizeof(sraRectangleIterator));
- if(!i)
- return(0);
-
- /* we have to recurse eventually. So, the first sPtr is the pointer to
- the sraSpan in the first level. the second sPtr is the pointer to
- the sraRegion.back. The third and fourth sPtr are for the second
- recursion level and so on. */
- i->sPtrs = (sraSpan**)malloc(sizeof(sraSpan*)*DEFSIZE);
- if(!i->sPtrs) {
- free(i);
- return(0);
- }
- i->ptrSize = DEFSIZE;
- i->sPtrs[0] = &(s->front);
- i->sPtrs[1] = &(s->back);
- i->ptrPos = 0;
- i->reverseX = 0;
- i->reverseY = 0;
- return(i);
-}
-
-sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,Bool reverseX,Bool reverseY)
-{
- sraRectangleIterator *i = sraRgnGetIterator(s);
- if(reverseY) {
- i->sPtrs[1] = &(s->front);
- i->sPtrs[0] = &(s->back);
- }
- i->reverseX = reverseX;
- i->reverseY = reverseY;
- return(i);
-}
-
-Bool sraReverse(sraRectangleIterator *i)
-{
- return( ((i->ptrPos&2) && i->reverseX) ||
- (!(i->ptrPos&2) && i->reverseY));
-}
-
-sraSpan* sraNextSpan(sraRectangleIterator *i)
-{
- if(sraReverse(i))
- return(i->sPtrs[i->ptrPos]->_prev);
- else
- return(i->sPtrs[i->ptrPos]->_next);
-}
-
-Bool sraRgnIteratorNext(sraRectangleIterator* i,sraRect* r)
-{
- /* is the subspan finished? */
- while(sraNextSpan(i) == i->sPtrs[i->ptrPos+1]) {
- i->ptrPos -= 2;
- if(i->ptrPos < 0) /* the end */
- return(0);
- }
-
- i->sPtrs[i->ptrPos] = sraNextSpan(i);
-
- /* is this a new subspan? */
- while(i->sPtrs[i->ptrPos]->subspan) {
- if(i->ptrPos+2 > i->ptrSize) { /* array is too small */
- i->ptrSize += DEFSTEP;
- i->sPtrs = (sraSpan**)realloc(i->sPtrs, sizeof(sraSpan*)*i->ptrSize);
- }
- i->ptrPos =+ 2;
- if(sraReverse(i)) {
- i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->back._prev;
- i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->front);
- } else {
- i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->front._next;
- i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->back);
- }
- }
-
- if((i->ptrPos%4)!=2) {
- fprintf(stderr,"sraRgnIteratorNext: offset is wrong (%d%%4!=2)\n",i->ptrPos);
- exit(-1);
- }
-
- r->y1 = i->sPtrs[i->ptrPos-2]->start;
- r->y2 = i->sPtrs[i->ptrPos-2]->end;
- r->x1 = i->sPtrs[i->ptrPos]->start;
- r->x2 = i->sPtrs[i->ptrPos]->end;
-
- return(-1);
-}
-
-void sraRgnReleaseIterator(sraRectangleIterator* i)
-{
- free(i->sPtrs);
- free(i);
-}
-
-void
-sraRgnPrint(const sraRegion *rgn) {
- sraSpanListPrint((sraSpanList*)rgn);
-}
-
-Bool
-sraClipRect(int *x, int *y, int *w, int *h,
- int cx, int cy, int cw, int ch) {
- if (*x < cx) {
- *w -= (cx-*x);
- *x = cx;
- }
- if (*y < cy) {
- *h -= (cy-*y);
- *y = cy;
- }
- if (*x+*w > cx+cw) {
- *w = (cx+cw)-*x;
- }
- if (*y+*h > cy+ch) {
- *h = (cy+ch)-*y;
- }
- return (*w>0) && (*h>0);
-}
-
-/* test */
-
-#ifdef SRA_TEST
-/* pipe the output to sort|uniq -u and you'll get the errors. */
-int main(int argc, char** argv)
-{
- sraRegionPtr region, region1, region2;
- sraRectangleIterator* i;
- sraRect rect;
- Bool b;
-
- region = sraRgnCreateRect(10, 10, 600, 300);
- region1 = sraRgnCreateRect(40, 50, 350, 200);
- region2 = sraRgnCreateRect(0, 0, 20, 40);
-
- sraRgnPrint(region);
- printf("\n[(10-300)[(10-600)]]\n\n");
-
- b = sraRgnSubtract(region, region1);
- printf("%s ",b?"true":"false");
- sraRgnPrint(region);
- printf("\ntrue [(10-50)[(10-600)](50-200)[(10-40)(350-600)](200-300)[(10-600)]]\n\n");
-
- sraRgnOr(region, region2);
- printf("%ld\n6\n\n", sraRgnCountRects(region));
-
- i = sraRgnGetIterator(region);
- while(sraRgnIteratorNext(i, &rect))
- printf("%dx%d+%d+%d ",
- rect.x2-rect.x1,rect.y2-rect.y1,
- rect.x1,rect.y1);
- sraRgnReleaseIterator(i);
- printf("\n20x10+0+0 600x30+0+10 590x10+10+40 30x150+10+50 250x150+350+50 590x100+10+200\n\n");
-
- i = sraRgnGetReverseIterator(region,1,0);
- while(sraRgnIteratorNext(i, &rect))
- printf("%dx%d+%d+%d ",
- rect.x2-rect.x1,rect.y2-rect.y1,
- rect.x1,rect.y1);
- sraRgnReleaseIterator(i);
- printf("\n20x10+0+0 600x30+0+10 590x10+10+40 250x150+350+50 30x150+10+50 590x100+10+200\n\n");
-
- i = sraRgnGetReverseIterator(region,1,1);
- while(sraRgnIteratorNext(i, &rect))
- printf("%dx%d+%d+%d ",
- rect.x2-rect.x1,rect.y2-rect.y1,
- rect.x1,rect.y1);
- sraRgnReleaseIterator(i);
- printf("\n590x100+10+200 250x150+350+50 30x150+10+50 590x10+10+40 600x30+0+10 20x10+0+0\n\n");
-
- return(0);
-}
-#endif
+/* -=- sraRegion.c + * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin + * + * A general purpose region clipping library + * Only deals with rectangular regions, though. + */ + +#include "rfb.h" +#include "sraRegion.h" + +#include <stdlib.h> +#include <stdio.h> + +/* -=- Internal Span structure */ + +struct sraRegion; + +typedef struct sraSpan { + struct sraSpan *_next; + struct sraSpan *_prev; + int start; + int end; + struct sraRegion *subspan; +} sraSpan; + +typedef struct sraRegion { + sraSpan front; + sraSpan back; +} sraSpanList; + +/* -=- Span routines */ + +sraSpanList *sraSpanListDup(const sraSpanList *src); +void sraSpanListDestroy(sraSpanList *list); + +sraSpan * +sraSpanCreate(int start, int end, const sraSpanList *subspan) { + sraSpan *item = (sraSpan*)malloc(sizeof(sraSpan)); + item->_next = item->_prev = NULL; + item->start = start; + item->end = end; + item->subspan = sraSpanListDup(subspan); + return item; +} + +sraSpan * +sraSpanDup(const sraSpan *src) { + sraSpan *span; + if (!src) return NULL; + span = sraSpanCreate(src->start, src->end, src->subspan); + return span; +} + +void +sraSpanInsertAfter(sraSpan *newspan, sraSpan *after) { + newspan->_next = after->_next; + newspan->_prev = after; + after->_next->_prev = newspan; + after->_next = newspan; +} + +void +sraSpanInsertBefore(sraSpan *newspan, sraSpan *before) { + newspan->_next = before; + newspan->_prev = before->_prev; + before->_prev->_next = newspan; + before->_prev = newspan; +} + +void +sraSpanRemove(sraSpan *span) { + span->_prev->_next = span->_next; + span->_next->_prev = span->_prev; +} + +void +sraSpanDestroy(sraSpan *span) { + if (span->subspan) sraSpanListDestroy(span->subspan); + free(span); +} + +void +sraSpanCheck(const sraSpan *span, const char *text) { + /* Check the span is valid! */ + if (span->start == span->end) { + printf(text); + printf(":%d-%d\n", span->start, span->end); + exit(0); + } +} + +/* -=- SpanList routines */ + +void sraSpanPrint(const sraSpan *s); + +void +sraSpanListPrint(const sraSpanList *l) { + sraSpan *curr; + if (!l) { + printf("NULL"); + return; + } + curr = l->front._next; + printf("["); + while (curr != &(l->back)) { + sraSpanPrint(curr); + curr = curr->_next; + } + printf("]"); +} + +void +sraSpanPrint(const sraSpan *s) { + printf("(%d-%d)", (s->start), (s->end)); + if (s->subspan) + sraSpanListPrint(s->subspan); +} + +sraSpanList * +sraSpanListCreate() { + sraSpanList *item = (sraSpanList*)malloc(sizeof(sraSpanList)); + item->front._next = &(item->back); + item->front._prev = NULL; + item->back._prev = &(item->front); + item->back._next = NULL; + return item; +} + +sraSpanList * +sraSpanListDup(const sraSpanList *src) { + sraSpanList *newlist; + sraSpan *newspan, *curr; + + if (!src) return NULL; + newlist = sraSpanListCreate(); + curr = src->front._next; + while (curr != &(src->back)) { + newspan = sraSpanDup(curr); + sraSpanInsertBefore(newspan, &(newlist->back)); + curr = curr->_next; + } + + return newlist; +} + +void +sraSpanListDestroy(sraSpanList *list) { + sraSpan *curr, *next; + while (list->front._next != &(list->back)) { + curr = list->front._next; + next = curr->_next; + sraSpanRemove(curr); + sraSpanDestroy(curr); + curr = next; + } + free(list); +} + +void +sraSpanListMakeEmpty(sraSpanList *list) { + sraSpan *curr, *next; + while (list->front._next != &(list->back)) { + curr = list->front._next; + next = curr->_next; + sraSpanRemove(curr); + sraSpanDestroy(curr); + curr = next; + } + list->front._next = &(list->back); + list->front._prev = NULL; + list->back._prev = &(list->front); + list->back._next = NULL; +} + +Bool +sraSpanListEqual(const sraSpanList *s1, const sraSpanList *s2) { + sraSpan *sp1, *sp2; + + if (!s1) { + if (!s2) { + return 1; + } else { + printf("sraSpanListEqual:incompatible spans (only one NULL!)\n"); + exit(1); + } + } + + sp1 = s1->front._next; + sp2 = s2->front._next; + while ((sp1 != &(s1->back)) && + (sp2 != &(s2->back))) { + if ((sp1->start != sp2->start) || + (sp1->end != sp2->end) || + (!sraSpanListEqual(sp1->subspan, sp2->subspan))) { + return 0; + } + sp1 = sp1->_next; + sp2 = sp2->_next; + } + + if ((sp1 == &(s1->back)) && (sp2 == &(s2->back))) { + return 1; + } else { + return 0; + } +} + +Bool +sraSpanListEmpty(const sraSpanList *list) { + return (list->front._next == &(list->back)); +} + +unsigned long +sraSpanListCount(const sraSpanList *list) { + sraSpan *curr = list->front._next; + unsigned long count = 0; + while (curr != &(list->back)) { + if (curr->subspan) { + count += sraSpanListCount(curr->subspan); + } else { + count += 1; + } + curr = curr->_next; + } + return count; +} + +void +sraSpanMergePrevious(sraSpan *dest) { + sraSpan *prev = dest->_prev; + while ((prev->end == dest->start) && + (prev->_prev) && + (sraSpanListEqual(prev->subspan, dest->subspan))) { + /* + printf("merge_prev:"); + sraSpanPrint(prev); + printf(" & "); + sraSpanPrint(dest); + printf("\n"); + */ + dest->start = prev->start; + sraSpanRemove(prev); + sraSpanDestroy(prev); + prev = dest->_prev; + } +} + +void +sraSpanMergeNext(sraSpan *dest) { + sraSpan *next = dest->_next; + while ((next->start == dest->end) && + (next->_next) && + (sraSpanListEqual(next->subspan, dest->subspan))) { +/* + printf("merge_next:"); + sraSpanPrint(dest); + printf(" & "); + sraSpanPrint(next); + printf("\n"); + */ + dest->end = next->end; + sraSpanRemove(next); + sraSpanDestroy(next); + next = dest->_next; + } +} + +void +sraSpanListOr(sraSpanList *dest, const sraSpanList *src) { + sraSpan *d_curr, *s_curr; + int s_start, s_end; + + if (!dest) { + if (!src) { + return; + } else { + printf("sraSpanListOr:incompatible spans (only one NULL!)\n"); + exit(1); + } + } + + d_curr = dest->front._next; + s_curr = src->front._next; + s_start = s_curr->start; + s_end = s_curr->end; + while (s_curr != &(src->back)) { + + /* - If we are at end of destination list OR + If the new span comes before the next destination one */ + if ((d_curr == &(dest->back)) || + (d_curr->start >= s_end)) { + /* - Add the span */ + sraSpanInsertBefore(sraSpanCreate(s_start, s_end, + s_curr->subspan), + d_curr); + if (d_curr != &(dest->back)) + sraSpanMergePrevious(d_curr); + s_curr = s_curr->_next; + s_start = s_curr->start; + s_end = s_curr->end; + } else { + + /* - If the new span overlaps the existing one */ + if ((s_start < d_curr->end) && + (s_end > d_curr->start)) { + + /* - Insert new span before the existing destination one? */ + if (s_start < d_curr->start) { + sraSpanInsertBefore(sraSpanCreate(s_start, + d_curr->start, + s_curr->subspan), + d_curr); + sraSpanMergePrevious(d_curr); + } + + /* Split the existing span if necessary */ + if (s_end < d_curr->end) { + sraSpanInsertAfter(sraSpanCreate(s_end, + d_curr->end, + d_curr->subspan), + d_curr); + d_curr->end = s_end; + } + if (s_start > d_curr->start) { + sraSpanInsertBefore(sraSpanCreate(d_curr->start, + s_start, + d_curr->subspan), + d_curr); + d_curr->start = s_start; + } + + /* Recursively OR subspans */ + sraSpanListOr(d_curr->subspan, s_curr->subspan); + + /* Merge this span with previous or next? */ + if (d_curr->_prev != &(dest->front)) + sraSpanMergePrevious(d_curr); + if (d_curr->_next != &(dest->back)) + sraSpanMergeNext(d_curr); + + /* Move onto the next pair to compare */ + if (s_end > d_curr->end) { + s_start = d_curr->end; + d_curr = d_curr->_next; + } else { + s_curr = s_curr->_next; + s_start = s_curr->start; + s_end = s_curr->end; + } + } else { + /* - No overlap. Move to the next destination span */ + d_curr = d_curr->_next; + } + } + } +} + +Bool +sraSpanListAnd(sraSpanList *dest, const sraSpanList *src) { + sraSpan *d_curr, *s_curr, *d_next; + + if (!dest) { + if (!src) { + return 1; + } else { + printf("sraSpanListAnd:incompatible spans (only one NULL!)\n"); + exit(1); + } + } + + d_curr = dest->front._next; + s_curr = src->front._next; + while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) { + + /* - If we haven't reached a destination span yet then move on */ + if (d_curr->start >= s_curr->end) { + s_curr = s_curr->_next; + continue; + } + + /* - If we are beyond the current destination span then remove it */ + if (d_curr->end <= s_curr->start) { + sraSpan *next = d_curr->_next; + sraSpanRemove(d_curr); + sraSpanDestroy(d_curr); + d_curr = next; + continue; + } + + /* - If we partially overlap a span then split it up or remove bits */ + if (s_curr->start > d_curr->start) { + /* - The top bit of the span does not match */ + d_curr->start = s_curr->start; + } + if (s_curr->end < d_curr->end) { + /* - The end of the span does not match */ + sraSpanInsertAfter(sraSpanCreate(s_curr->end, + d_curr->end, + d_curr->subspan), + d_curr); + d_curr->end = s_curr->end; + } + + /* - Now recursively process the affected span */ + if (!sraSpanListAnd(d_curr->subspan, s_curr->subspan)) { + /* - The destination subspan is now empty, so we should remove it */ + sraSpan *next = d_curr->_next; + sraSpanRemove(d_curr); + sraSpanDestroy(d_curr); + d_curr = next; + } else { + /* Merge this span with previous or next? */ + if (d_curr->_prev != &(dest->front)) + sraSpanMergePrevious(d_curr); + + /* - Move on to the next span */ + d_next = d_curr; + if (s_curr->end >= d_curr->end) { + d_next = d_curr->_next; + } + if (s_curr->end <= d_curr->end) { + s_curr = s_curr->_next; + } + d_curr = d_next; + } + } + + while (d_curr != &(dest->back)) { + sraSpan *next = d_curr->_next; + sraSpanRemove(d_curr); + sraSpanDestroy(d_curr); + d_curr=next; + } + + return !sraSpanListEmpty(dest); +} + +Bool +sraSpanListSubtract(sraSpanList *dest, const sraSpanList *src) { + sraSpan *d_curr, *s_curr; + + if (!dest) { + if (!src) { + return 1; + } else { + printf("sraSpanListSubtract:incompatible spans (only one NULL!)\n"); + exit(1); + } + } + + d_curr = dest->front._next; + s_curr = src->front._next; + while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) { + + /* - If we haven't reached a destination span yet then move on */ + if (d_curr->start >= s_curr->end) { + s_curr = s_curr->_next; + continue; + } + + /* - If we are beyond the current destination span then skip it */ + if (d_curr->end <= s_curr->start) { + d_curr = d_curr->_next; + continue; + } + + /* - If we partially overlap the current span then split it up */ + if (s_curr->start > d_curr->start) { + sraSpanInsertBefore(sraSpanCreate(d_curr->start, + s_curr->start, + d_curr->subspan), + d_curr); + d_curr->start = s_curr->start; + } + if (s_curr->end < d_curr->end) { + sraSpanInsertAfter(sraSpanCreate(s_curr->end, + d_curr->end, + d_curr->subspan), + d_curr); + d_curr->end = s_curr->end; + } + + /* - Now recursively process the affected span */ + if ((!d_curr->subspan) || !sraSpanListSubtract(d_curr->subspan, s_curr->subspan)) { + /* - The destination subspan is now empty, so we should remove it */ + sraSpan *next = d_curr->_next; + sraSpanRemove(d_curr); + sraSpanDestroy(d_curr); + d_curr = next; + } else { + /* Merge this span with previous or next? */ + if (d_curr->_prev != &(dest->front)) + sraSpanMergePrevious(d_curr); + if (d_curr->_next != &(dest->back)) + sraSpanMergeNext(d_curr); + + /* - Move on to the next span */ + if (s_curr->end > d_curr->end) { + d_curr = d_curr->_next; + } else { + s_curr = s_curr->_next; + } + } + } + + return !sraSpanListEmpty(dest); +} + +/* -=- Region routines */ + +sraRegion * +sraRgnCreate() { + return (sraRegion*)sraSpanListCreate(); +} + +sraRegion * +sraRgnCreateRect(int x1, int y1, int x2, int y2) { + sraSpanList *vlist, *hlist; + sraSpan *vspan, *hspan; + + /* - Build the horizontal portion of the span */ + hlist = sraSpanListCreate(); + hspan = sraSpanCreate(x1, x2, NULL); + sraSpanInsertAfter(hspan, &(hlist->front)); + + /* - Build the vertical portion of the span */ + vlist = sraSpanListCreate(); + vspan = sraSpanCreate(y1, y2, hlist); + sraSpanInsertAfter(vspan, &(vlist->front)); + + sraSpanListDestroy(hlist); + + return (sraRegion*)vlist; +} + +sraRegion * +sraRgnCreateRgn(const sraRegion *src) { + return (sraRegion*)sraSpanListDup((sraSpanList*)src); +} + +void +sraRgnDestroy(sraRegion *rgn) { + sraSpanListDestroy((sraSpanList*)rgn); +} + +void +sraRgnMakeEmpty(sraRegion *rgn) { + sraSpanListMakeEmpty((sraSpanList*)rgn); +} + +/* -=- Boolean Region ops */ + +Bool +sraRgnAnd(sraRegion *dst, const sraRegion *src) { + return sraSpanListAnd((sraSpanList*)dst, (sraSpanList*)src); +} + +void +sraRgnOr(sraRegion *dst, const sraRegion *src) { + sraSpanListOr((sraSpanList*)dst, (sraSpanList*)src); +} + +Bool +sraRgnSubtract(sraRegion *dst, const sraRegion *src) { + return sraSpanListSubtract((sraSpanList*)dst, (sraSpanList*)src); +} + +void +sraRgnOffset(sraRegion *dst, int dx, int dy) { + sraSpan *vcurr, *hcurr; + + vcurr = ((sraSpanList*)dst)->front._next; + while (vcurr != &(((sraSpanList*)dst)->back)) { + vcurr->start += dy; + vcurr->end += dy; + + hcurr = vcurr->subspan->front._next; + while (hcurr != &(vcurr->subspan->back)) { + hcurr->start += dx; + hcurr->end += dx; + hcurr = hcurr->_next; + } + + vcurr = vcurr->_next; + } +} + +Bool +sraRgnPopRect(sraRegion *rgn, sraRect *rect, unsigned long flags) { + sraSpan *vcurr, *hcurr; + sraSpan *vend, *hend; + Bool right2left = flags & 2; + Bool bottom2top = flags & 1; + + /* - Pick correct order */ + if (bottom2top) { + vcurr = ((sraSpanList*)rgn)->back._prev; + vend = &(((sraSpanList*)rgn)->front); + } else { + vcurr = ((sraSpanList*)rgn)->front._next; + vend = &(((sraSpanList*)rgn)->back); + } + + if (vcurr != vend) { + rect->y1 = vcurr->start; + rect->y2 = vcurr->end; + + /* - Pick correct order */ + if (right2left) { + hcurr = vcurr->subspan->back._prev; + hend = &(vcurr->subspan->front); + } else { + hcurr = vcurr->subspan->front._next; + hend = &(vcurr->subspan->back); + } + + if (hcurr != hend) { + rect->x1 = hcurr->start; + rect->x2 = hcurr->end; + + sraSpanRemove(hcurr); + sraSpanDestroy(hcurr); + + if (sraSpanListEmpty(vcurr->subspan)) { + sraSpanRemove(vcurr); + sraSpanDestroy(vcurr); + } + +#if 0 + printf("poprect:(%dx%d)-(%dx%d)\n", + rect->x1, rect->y1, rect->x2, rect->y2); +#endif + return 1; + } + } + + return 0; +} + +unsigned long +sraRgnCountRects(const sraRegion *rgn) { + unsigned long count = sraSpanListCount((sraSpanList*)rgn); + return count; +} + +Bool +sraRgnEmpty(const sraRegion *rgn) { + return sraSpanListEmpty((sraSpanList*)rgn); +} + +/* iterator stuff */ +sraRectangleIterator *sraRgnGetIterator(sraRegion *s) +{ + /* these values have to be multiples of 4 */ +#define DEFSIZE 4 +#define DEFSTEP 8 + sraRectangleIterator *i = + (sraRectangleIterator*)malloc(sizeof(sraRectangleIterator)); + if(!i) + return(0); + + /* we have to recurse eventually. So, the first sPtr is the pointer to + the sraSpan in the first level. the second sPtr is the pointer to + the sraRegion.back. The third and fourth sPtr are for the second + recursion level and so on. */ + i->sPtrs = (sraSpan**)malloc(sizeof(sraSpan*)*DEFSIZE); + if(!i->sPtrs) { + free(i); + return(0); + } + i->ptrSize = DEFSIZE; + i->sPtrs[0] = &(s->front); + i->sPtrs[1] = &(s->back); + i->ptrPos = 0; + i->reverseX = 0; + i->reverseY = 0; + return(i); +} + +sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,Bool reverseX,Bool reverseY) +{ + sraRectangleIterator *i = sraRgnGetIterator(s); + if(reverseY) { + i->sPtrs[1] = &(s->front); + i->sPtrs[0] = &(s->back); + } + i->reverseX = reverseX; + i->reverseY = reverseY; + return(i); +} + +Bool sraReverse(sraRectangleIterator *i) +{ + return( ((i->ptrPos&2) && i->reverseX) || + (!(i->ptrPos&2) && i->reverseY)); +} + +sraSpan* sraNextSpan(sraRectangleIterator *i) +{ + if(sraReverse(i)) + return(i->sPtrs[i->ptrPos]->_prev); + else + return(i->sPtrs[i->ptrPos]->_next); +} + +Bool sraRgnIteratorNext(sraRectangleIterator* i,sraRect* r) +{ + /* is the subspan finished? */ + while(sraNextSpan(i) == i->sPtrs[i->ptrPos+1]) { + i->ptrPos -= 2; + if(i->ptrPos < 0) /* the end */ + return(0); + } + + i->sPtrs[i->ptrPos] = sraNextSpan(i); + + /* is this a new subspan? */ + while(i->sPtrs[i->ptrPos]->subspan) { + if(i->ptrPos+2 > i->ptrSize) { /* array is too small */ + i->ptrSize += DEFSTEP; + i->sPtrs = (sraSpan**)realloc(i->sPtrs, sizeof(sraSpan*)*i->ptrSize); + } + i->ptrPos =+ 2; + if(sraReverse(i)) { + i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->back._prev; + i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->front); + } else { + i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->front._next; + i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->back); + } + } + + if((i->ptrPos%4)!=2) { + fprintf(stderr,"sraRgnIteratorNext: offset is wrong (%d%%4!=2)\n",i->ptrPos); + exit(-1); + } + + r->y1 = i->sPtrs[i->ptrPos-2]->start; + r->y2 = i->sPtrs[i->ptrPos-2]->end; + r->x1 = i->sPtrs[i->ptrPos]->start; + r->x2 = i->sPtrs[i->ptrPos]->end; + + return(-1); +} + +void sraRgnReleaseIterator(sraRectangleIterator* i) +{ + free(i->sPtrs); + free(i); +} + +void +sraRgnPrint(const sraRegion *rgn) { + sraSpanListPrint((sraSpanList*)rgn); +} + +Bool +sraClipRect(int *x, int *y, int *w, int *h, + int cx, int cy, int cw, int ch) { + if (*x < cx) { + *w -= (cx-*x); + *x = cx; + } + if (*y < cy) { + *h -= (cy-*y); + *y = cy; + } + if (*x+*w > cx+cw) { + *w = (cx+cw)-*x; + } + if (*y+*h > cy+ch) { + *h = (cy+ch)-*y; + } + return (*w>0) && (*h>0); +} + +/* test */ + +#ifdef SRA_TEST +/* pipe the output to sort|uniq -u and you'll get the errors. */ +int main(int argc, char** argv) +{ + sraRegionPtr region, region1, region2; + sraRectangleIterator* i; + sraRect rect; + Bool b; + + region = sraRgnCreateRect(10, 10, 600, 300); + region1 = sraRgnCreateRect(40, 50, 350, 200); + region2 = sraRgnCreateRect(0, 0, 20, 40); + + sraRgnPrint(region); + printf("\n[(10-300)[(10-600)]]\n\n"); + + b = sraRgnSubtract(region, region1); + printf("%s ",b?"true":"false"); + sraRgnPrint(region); + printf("\ntrue [(10-50)[(10-600)](50-200)[(10-40)(350-600)](200-300)[(10-600)]]\n\n"); + + sraRgnOr(region, region2); + printf("%ld\n6\n\n", sraRgnCountRects(region)); + + i = sraRgnGetIterator(region); + while(sraRgnIteratorNext(i, &rect)) + printf("%dx%d+%d+%d ", + rect.x2-rect.x1,rect.y2-rect.y1, + rect.x1,rect.y1); + sraRgnReleaseIterator(i); + printf("\n20x10+0+0 600x30+0+10 590x10+10+40 30x150+10+50 250x150+350+50 590x100+10+200\n\n"); + + i = sraRgnGetReverseIterator(region,1,0); + while(sraRgnIteratorNext(i, &rect)) + printf("%dx%d+%d+%d ", + rect.x2-rect.x1,rect.y2-rect.y1, + rect.x1,rect.y1); + sraRgnReleaseIterator(i); + printf("\n20x10+0+0 600x30+0+10 590x10+10+40 250x150+350+50 30x150+10+50 590x100+10+200\n\n"); + + i = sraRgnGetReverseIterator(region,1,1); + while(sraRgnIteratorNext(i, &rect)) + printf("%dx%d+%d+%d ", + rect.x2-rect.x1,rect.y2-rect.y1, + rect.x1,rect.y1); + sraRgnReleaseIterator(i); + printf("\n590x100+10+200 250x150+350+50 30x150+10+50 590x10+10+40 600x30+0+10 20x10+0+0\n\n"); + + return(0); +} +#endif diff --git a/sraRegion.h b/sraRegion.h index 3d7c50c..1bbedf6 100755 --- a/sraRegion.h +++ b/sraRegion.h @@ -1,60 +1,60 @@ -#ifndef SRAREGION_H
-#define SRAREGION_H
-
-/* -=- SRA - Simple Region Algorithm
- * A simple rectangular region implementation.
- * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin
- */
-
-/* -=- sraRect */
-
-typedef struct _rect {
- int x1;
- int y1;
- int x2;
- int y2;
-} sraRect;
-
-typedef struct sraRegion sraRegion;
-
-/* -=- Region manipulation functions */
-
-extern sraRegion *sraRgnCreate();
-extern sraRegion *sraRgnCreateRect(int x1, int y1, int x2, int y2);
-extern sraRegion *sraRgnCreateRgn(const sraRegion *src);
-
-extern void sraRgnDestroy(sraRegion *rgn);
-extern void sraRgnMakeEmpty(sraRegion *rgn);
-extern Bool sraRgnAnd(sraRegion *dst, const sraRegion *src);
-extern void sraRgnOr(sraRegion *dst, const sraRegion *src);
-extern Bool sraRgnSubtract(sraRegion *dst, const sraRegion *src);
-
-extern void sraRgnOffset(sraRegion *dst, int dx, int dy);
-
-extern Bool sraRgnPopRect(sraRegion *region, sraRect *rect,
- unsigned long flags);
-
-extern unsigned long sraRgnCountRects(const sraRegion *rgn);
-extern Bool sraRgnEmpty(const sraRegion *rgn);
-
-/* -=- rectangle iterator */
-
-typedef struct sraRectangleIterator {
- Bool reverseX,reverseY;
- int ptrSize,ptrPos;
- struct sraSpan** sPtrs;
-} sraRectangleIterator;
-
-extern sraRectangleIterator *sraRgnGetIterator(sraRegion *s);
-extern sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,Bool reverseX,Bool reverseY);
-extern Bool sraRgnIteratorNext(sraRectangleIterator *i,sraRect *r);
-extern void sraRgnReleaseIterator(sraRectangleIterator *i);
-
-void sraRgnPrint(const sraRegion *s);
-
-/* -=- Rectangle clipper (for speed) */
-
-extern Bool sraClipRect(int *x, int *y, int *w, int *h,
- int cx, int cy, int cw, int ch);
-
-#endif
+#ifndef SRAREGION_H +#define SRAREGION_H + +/* -=- SRA - Simple Region Algorithm + * A simple rectangular region implementation. + * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin + */ + +/* -=- sraRect */ + +typedef struct _rect { + int x1; + int y1; + int x2; + int y2; +} sraRect; + +typedef struct sraRegion sraRegion; + +/* -=- Region manipulation functions */ + +extern sraRegion *sraRgnCreate(); +extern sraRegion *sraRgnCreateRect(int x1, int y1, int x2, int y2); +extern sraRegion *sraRgnCreateRgn(const sraRegion *src); + +extern void sraRgnDestroy(sraRegion *rgn); +extern void sraRgnMakeEmpty(sraRegion *rgn); +extern Bool sraRgnAnd(sraRegion *dst, const sraRegion *src); +extern void sraRgnOr(sraRegion *dst, const sraRegion *src); +extern Bool sraRgnSubtract(sraRegion *dst, const sraRegion *src); + +extern void sraRgnOffset(sraRegion *dst, int dx, int dy); + +extern Bool sraRgnPopRect(sraRegion *region, sraRect *rect, + unsigned long flags); + +extern unsigned long sraRgnCountRects(const sraRegion *rgn); +extern Bool sraRgnEmpty(const sraRegion *rgn); + +/* -=- rectangle iterator */ + +typedef struct sraRectangleIterator { + Bool reverseX,reverseY; + int ptrSize,ptrPos; + struct sraSpan** sPtrs; +} sraRectangleIterator; + +extern sraRectangleIterator *sraRgnGetIterator(sraRegion *s); +extern sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,Bool reverseX,Bool reverseY); +extern Bool sraRgnIteratorNext(sraRectangleIterator *i,sraRect *r); +extern void sraRgnReleaseIterator(sraRectangleIterator *i); + +void sraRgnPrint(const sraRegion *s); + +/* -=- Rectangle clipper (for speed) */ + +extern Bool sraClipRect(int *x, int *y, int *w, int *h, + int cx, int cy, int cw, int ch); + +#endif @@ -429,12 +429,7 @@ ExtendSolidArea(cl, x, y, w, h, colorValue, x_ptr, y_ptr, w_ptr, h_ptr) *w_ptr += cx - (*x_ptr + *w_ptr); } -static Bool -CheckSolidTile(cl, x, y, w, h, colorPtr, needSameColor) - rfbClientPtr cl; - int x, y, w, h; - CARD32 *colorPtr; - Bool needSameColor; +static Bool CheckSolidTile(rfbClientPtr cl, int x, int y, int w, int h, CARD32* colorPtr, Bool needSameColor) { switch(cl->screen->rfbServerFormat.bitsPerPixel) { case 32: @@ -449,11 +444,7 @@ CheckSolidTile(cl, x, y, w, h, colorPtr, needSameColor) #define DEFINE_CHECK_SOLID_FUNCTION(bpp) \ \ static Bool \ -CheckSolidTile##bpp(cl, x, y, w, h, colorPtr, needSameColor) \ - rfbClientPtr cl; \ - int x, y, w, h; \ - CARD32 *colorPtr; \ - Bool needSameColor; \ +CheckSolidTile##bpp(rfbClientPtr cl, int x, int y, int w, int h, CARD32* colorPtr, Bool needSameColor) \ { \ CARD##bpp *fbptr; \ CARD##bpp colorValue; \ @@ -24,6 +24,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <math.h> #include <sys/types.h> #include <sys/stat.h> #include <time.h> |