From 47341aa5545e8b354c8cd45e1372f96d9e4f6c0d Mon Sep 17 00:00:00 2001
From: dscho <dscho>
Date: Tue, 14 Aug 2001 09:57:47 +0000
Subject: now lines are drawn for the example, first steps to make clients
 independent.

---
 example.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++--------------
 main.c    |  29 ++++++++++------
 rfb.h     |   2 +-
 3 files changed, 107 insertions(+), 35 deletions(-)

diff --git a/example.c b/example.c
index 2fe1d3f..22d1c04 100644
--- a/example.c
+++ b/example.c
@@ -32,36 +32,92 @@
 
 const int maxx=640, maxy=480, bpp=4;
 
-void initBuffer(char* buffer)
+/* This initializes a nice (?) background */
+
+void initBuffer(unsigned char* buffer)
 {
   int i,j;
   for(i=0;i<maxx;++i)
     for(j=0;j<maxy;++j) {
-      buffer[(j*maxx+i)*bpp]=i*256/maxx;
-      buffer[(j*maxx+i)*bpp+1]=j*256/maxy;
-      buffer[(j*maxx+i)*bpp+2]=(i+j)*256/(maxx*maxy);
-      buffer[(j*maxx+i)*bpp+3]=(i-j)*256/(maxx*maxy);
+      buffer[(j*maxx+i)*bpp+1]=(i+j)*256/(maxx+maxy); /* red */
+      buffer[(j*maxx+i)*bpp+2]=i*256/maxx; /* green */
+      buffer[(j*maxx+i)*bpp+3]=j*256/maxy; /* blue */
     }
 }
 
+/* Here we create a structure so that every client has it's own pointer */
+
+typedef struct ClientData {
+  Bool oldButton;
+  int oldx,oldy;
+} ClientData;
+
+void clientgone(rfbClientPtr cl)
+{
+  free(cl->clientData);
+}
+
+void newclient(rfbClientPtr cl)
+{
+  cl->clientData = (void*)calloc(sizeof(ClientData),1);
+  cl->clientGoneHook = clientgone;
+}
+
+/* aux function to draw a line */
+void drawline(unsigned char* buffer,int rowstride,int bpp,int x1,int y1,int x2,int y2)
+{
+  int i,j;
+  i=x1-x2; j=y1-y2;
+  if(i<0) i=-i;
+  if(j<0) j=-j;
+  if(i<j) {
+    if(y1>y2) { i=y2; y2=y1; y1=i; i=x2; x2=x1; x1=i; }
+    if(y2==y1) { if(y2>0) y1--; else y2++; }
+    for(j=y1;j<=y2;j++)
+      for(i=0;i<bpp;i++)
+	buffer[j*rowstride+(x1+(j-y1)*(x2-x1)/(y2-y1))*bpp+i]=0xff;
+  } else {
+    if(x1>x2) { i=y2; y2=y1; y1=i; i=x2; x2=x1; x1=i; }
+    for(i=x1;i<=x2;i++)
+      for(j=0;j<bpp;j++)
+	buffer[(y1+(i-x1)*(y2-y1)/(x2-x1))*rowstride+i*bpp+j]=0xff;
+  }
+}
+    
+/* Here the pointer events are handled */
+
 void doptr(int buttonMask,int x,int y,rfbClientPtr cl)
 {
+   ClientData* cd=cl->clientData;
    if(buttonMask && x>=0 && y>=0 && x<maxx && y<maxy) {
       int i,j,x1,x2,y1,y2;
-      x1=x-buttonMask; if(x1<0) x1=0;
-      x2=x+buttonMask; if(x2>maxx) x2=maxx;
-      y1=y-buttonMask; if(y1<0) y1=0;
-      y2=y+buttonMask; if(y2>maxy) y2=maxy;
-
-      for(i=x1*bpp;i<x2*bpp;i++)
-	for(j=y1;j<y2;j++)
-	  cl->screen->frameBuffer[j*cl->screen->paddedWidthInBytes+i]=0xff;
-      rfbMarkRectAsModified(cl->screen,x1,y1,x2,y2);
-      rfbGotXCutText(cl->screen,"Hallo",5);
-   }
-}
 
+      if(cd->oldButton==buttonMask) { /* draw a line */
+	drawline(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) */
+	x1=x-buttonMask; if(x1<0) x1=0;
+	x2=x+buttonMask; if(x2>maxx) x2=maxx;
+	y1=y-buttonMask; if(y1<0) y1=0;
+	y2=y+buttonMask; if(y2>maxy) y2=maxy;
+
+	for(i=x1*bpp;i<x2*bpp;i++)
+	  for(j=y1;j<y2;j++)
+	    cl->screen->frameBuffer[j*cl->screen->paddedWidthInBytes+i]=0xff;
+	rfbMarkRectAsModified(cl->screen,x1,y1,x2-1,y2-1);
+      }
 
+      /* we could get a selection like that:
+	 rfbGotXCutText(cl->screen,"Hallo",5);
+      */
+
+      cd->oldx=x; cd->oldy=y; cd->oldButton=buttonMask;
+   } else
+     cd->oldButton=0;
+}
+
+/* Here the key events are handled */
 
 void dokey(Bool down,KeySym key,rfbClientPtr cl)
 {
@@ -73,21 +129,28 @@ void dokey(Bool down,KeySym key,rfbClientPtr cl)
   }
 }
 
+/* Initialisation */
+
 int main(int argc,char** argv)
 {
-  rfbScreenInfoPtr rfbScreen = rfbDefaultScreenInit(argc,argv);
-  rfbScreen->desktopName="LibVNCServer Example";
+  rfbScreenInfoPtr rfbScreen =
+    rfbDefaultScreenInit(argc,argv,maxx,maxy,8,3,bpp);
+  rfbScreen->desktopName = "LibVNCServer Example";
   rfbScreen->frameBuffer = (char*)malloc(maxx*maxy*bpp);
-  rfbScreen->width=maxx;
-  rfbScreen->height=maxy;
-  rfbScreen->paddedWidthInBytes=maxx*bpp;
-  rfbScreen->ptrAddEvent=doptr;
-  rfbScreen->kbdAddEvent=dokey;
+  rfbScreen->rfbAlwaysShared = TRUE;
+  rfbScreen->ptrAddEvent = doptr;
+  rfbScreen->kbdAddEvent = dokey;
+  rfbScreen->newClientHook = newclient;
 
   initBuffer(rfbScreen->frameBuffer);
 
+  /* this is the blocking event loop, i.e. it never returns */
   runEventLoop(rfbScreen,40000,FALSE);
+
+  /* this is the non-blocking event loop; a background thread is started */
   runEventLoop(rfbScreen,40000,TRUE);
+
+  /* now we could do some cool things like rendering */
   while(1);
    
   return(0);
diff --git a/main.c b/main.c
index ef39aa4..9736b0d 100644
--- a/main.c
+++ b/main.c
@@ -91,7 +91,10 @@ void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y
 {
    BoxRec box;
    RegionRec region;
-   box.x1=x1; box.y1=y1; box.x2=x2; box.y2=y2;
+   int i;
+   if(x1>x2) { i=x1; x1=x2; x2=i; }
+   if(y1>y2) { i=y1; y1=y2; y2=i; }
+   box.x1=x1; box.y1=y1; box.x2=x2+1; box.y2=y2+1;
    REGION_INIT(cl->screen,&region,&box,0);
    rfbMarkRegionAsModified(rfbScreen,&region);
 }
@@ -296,10 +299,8 @@ void doNothingWithClient(rfbClientPtr cl)
 {
 }
 
-rfbScreenInfoPtr rfbDefaultScreenInit(int argc,char** argv)
+rfbScreenInfoPtr rfbDefaultScreenInit(int argc,char** argv,int width,int height,int bitsPerSample,int samplesPerPixel,int bytesPerPixel)
 {
-   int bitsPerSample,samplesPerPixel;
-   
    rfbScreenInfoPtr rfbScreen=malloc(sizeof(rfbScreenInfo));
    rfbScreen->rfbPort=5900;
    rfbScreen->socketInitDone=FALSE;
@@ -317,22 +318,22 @@ rfbScreenInfoPtr rfbDefaultScreenInit(int argc,char** argv)
    
    processArguments(rfbScreen,argc,argv);
 
-   rfbScreen->width = 640;
-   rfbScreen->height = 480;
-   rfbScreen->bitsPerPixel = rfbScreen->depth = 32;
+   rfbScreen->width = width;
+   rfbScreen->height = height;
+   rfbScreen->bitsPerPixel = rfbScreen->depth = 8*bytesPerPixel;
    gethostname(rfbScreen->rfbThisHost, 255);
-   rfbScreen->paddedWidthInBytes = 640*4;
+   rfbScreen->paddedWidthInBytes = width*bytesPerPixel;
    rfbScreen->rfbServerFormat.bitsPerPixel = rfbScreen->bitsPerPixel;
    rfbScreen->rfbServerFormat.depth = rfbScreen->depth;
    rfbScreen->rfbServerFormat.bigEndian = !(*(char *)&rfbEndianTest);
    rfbScreen->rfbServerFormat.trueColour = TRUE;
 
-   bitsPerSample = 8;
-   samplesPerPixel = 3;
+   /* Why? (TODO)
    if (samplesPerPixel != 3) {
       rfbLog("screen format not supported.  exiting.\n");
       exit(1);
    }
+   */
 
    /* This works for 16 and 32-bit, but not for 8-bit.
     What should it be for 8-bit?  (Shouldn't 8-bit use a colormap?) */
@@ -342,6 +343,14 @@ rfbScreenInfoPtr rfbDefaultScreenInit(int argc,char** argv)
    rfbScreen->rfbServerFormat.redShift = bitsPerSample * 2;
    rfbScreen->rfbServerFormat.greenShift = bitsPerSample;
    rfbScreen->rfbServerFormat.blueShift = 0;
+fprintf(stderr,"format: %d %d %d %d %d %d\n",
+	rfbScreen->rfbServerFormat.redMax,
+	rfbScreen->rfbServerFormat.greenMax,
+	rfbScreen->rfbServerFormat.blueMax,
+	rfbScreen->rfbServerFormat.redShift,
+	rfbScreen->rfbServerFormat.greenShift,
+	rfbScreen->rfbServerFormat.blueShift);
+
 
    /* We want to use the X11 REGION_* macros without having an actual
     X11 ScreenPtr, so we do this.  Pretty ugly, but at least it lets us
diff --git a/rfb.h b/rfb.h
index bc3a9bc..6836c20 100644
--- a/rfb.h
+++ b/rfb.h
@@ -524,7 +524,7 @@ void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,RegionPtr modRegion);
 void doNothingWithClient(rfbClientPtr cl);
 
 /* functions to make a vnc server */
-extern rfbScreenInfoPtr rfbDefaultScreenInit(int argc,char** argv);
+extern rfbScreenInfoPtr rfbDefaultScreenInit(int argc,char** argv,int width,int height,int bitsPerSample,int samplesPerPixel,int bytesPerPixel);
 extern void rfbScreenCleanup(rfbScreenInfoPtr screenInfo);
 
 /* call one of these two functions to service the vnc clients.
-- 
cgit v1.2.3

