~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to common/ivs/libvncserver/cursor.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 gutsy)
  • Revision ID: james.westby@ubuntu.com-20080617134654-cl0gi4u524cv1ici
Tags: 1:1.0.9~rc3-1
* Package new upstream version
  - upstream ported the code to qt4.4 (Closes: #481974)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * cursor.c - support for cursor shape updates.
3
 
 */
4
 
 
5
 
/*
6
 
 *  Copyright (C) 2000, 2001 Const Kaplinsky.  All Rights Reserved.
7
 
 *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
8
 
 *
9
 
 *  This is free software; you can redistribute it and/or modify
10
 
 *  it under the terms of the GNU General Public License as published by
11
 
 *  the Free Software Foundation; either version 2 of the License, or
12
 
 *  (at your option) any later version.
13
 
 *
14
 
 *  This software is distributed in the hope that it will be useful,
15
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 
 *  GNU General Public License for more details.
18
 
 *
19
 
 *  You should have received a copy of the GNU General Public License
20
 
 *  along with this software; if not, write to the Free Software
21
 
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
22
 
 *  USA.
23
 
 */
24
 
 
25
 
#include <rfb/rfb.h>
26
 
 
27
 
/*
28
 
 * Send cursor shape either in X-style format or in client pixel format.
29
 
 */
30
 
 
31
 
rfbBool
32
 
rfbSendCursorShape(cl)
33
 
    rfbClientPtr cl;
34
 
{
35
 
    rfbCursorPtr pCursor;
36
 
    rfbFramebufferUpdateRectHeader rect;
37
 
    rfbXCursorColors colors;
38
 
    int saved_ublen;
39
 
    int bitmapRowBytes, maskBytes, dataBytes;
40
 
    int i, j;
41
 
    uint8_t *bitmapData;
42
 
    uint8_t bitmapByte;
43
 
 
44
 
    pCursor = cl->screen->getCursorPtr(cl);
45
 
    /*if(!pCursor) return TRUE;*/
46
 
 
47
 
    if (cl->useRichCursorEncoding) {
48
 
      if(pCursor && !pCursor->richSource)
49
 
        MakeRichCursorFromXCursor(cl->screen,pCursor);
50
 
      rect.encoding = Swap32IfLE(rfbEncodingRichCursor);
51
 
    } else {
52
 
       if(pCursor && !pCursor->source)
53
 
         MakeXCursorFromRichCursor(cl->screen,pCursor);
54
 
       rect.encoding = Swap32IfLE(rfbEncodingXCursor);
55
 
    }
56
 
 
57
 
    /* If there is no cursor, send update with empty cursor data. */
58
 
 
59
 
    if ( pCursor && pCursor->width == 1 &&
60
 
         pCursor->height == 1 &&
61
 
         pCursor->mask[0] == 0 ) {
62
 
        pCursor = NULL;
63
 
    }
64
 
 
65
 
    if (pCursor == NULL) {
66
 
        if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) {
67
 
            if (!rfbSendUpdateBuf(cl))
68
 
                return FALSE;
69
 
        }
70
 
        rect.r.x = rect.r.y = 0;
71
 
        rect.r.w = rect.r.h = 0;
72
 
        memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
73
 
               sz_rfbFramebufferUpdateRectHeader);
74
 
        cl->ublen += sz_rfbFramebufferUpdateRectHeader;
75
 
 
76
 
        cl->rfbCursorShapeBytesSent += sz_rfbFramebufferUpdateRectHeader;
77
 
        cl->rfbCursorShapeUpdatesSent++;
78
 
 
79
 
        if (!rfbSendUpdateBuf(cl))
80
 
            return FALSE;
81
 
 
82
 
        return TRUE;
83
 
    }
84
 
 
85
 
    /* Calculate data sizes. */
86
 
 
87
 
    bitmapRowBytes = (pCursor->width + 7) / 8;
88
 
    maskBytes = bitmapRowBytes * pCursor->height;
89
 
    dataBytes = (cl->useRichCursorEncoding) ?
90
 
        (pCursor->width * pCursor->height *
91
 
         (cl->format.bitsPerPixel / 8)) : maskBytes;
92
 
 
93
 
    /* Send buffer contents if needed. */
94
 
 
95
 
    if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
96
 
         sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
97
 
        if (!rfbSendUpdateBuf(cl))
98
 
            return FALSE;
99
 
    }
100
 
 
101
 
    if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
102
 
         sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
103
 
        return FALSE;           /* FIXME. */
104
 
    }
105
 
 
106
 
    saved_ublen = cl->ublen;
107
 
 
108
 
    /* Prepare rectangle header. */
109
 
 
110
 
    rect.r.x = Swap16IfLE(pCursor->xhot);
111
 
    rect.r.y = Swap16IfLE(pCursor->yhot);
112
 
    rect.r.w = Swap16IfLE(pCursor->width);
113
 
    rect.r.h = Swap16IfLE(pCursor->height);
114
 
 
115
 
    memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
116
 
    cl->ublen += sz_rfbFramebufferUpdateRectHeader;
117
 
 
118
 
    /* Prepare actual cursor data (depends on encoding used). */
119
 
 
120
 
    if (!cl->useRichCursorEncoding) {
121
 
        /* XCursor encoding. */
122
 
        colors.foreRed   = (char)(pCursor->foreRed   >> 8);
123
 
        colors.foreGreen = (char)(pCursor->foreGreen >> 8);
124
 
        colors.foreBlue  = (char)(pCursor->foreBlue  >> 8);
125
 
        colors.backRed   = (char)(pCursor->backRed   >> 8);
126
 
        colors.backGreen = (char)(pCursor->backGreen >> 8);
127
 
        colors.backBlue  = (char)(pCursor->backBlue  >> 8);
128
 
 
129
 
        memcpy(&cl->updateBuf[cl->ublen], (char *)&colors, sz_rfbXCursorColors);
130
 
        cl->ublen += sz_rfbXCursorColors;
131
 
 
132
 
        bitmapData = (uint8_t *)pCursor->source;
133
 
 
134
 
        for (i = 0; i < pCursor->height; i++) {
135
 
            for (j = 0; j < bitmapRowBytes; j++) {
136
 
                bitmapByte = bitmapData[i * bitmapRowBytes + j];
137
 
                cl->updateBuf[cl->ublen++] = (char)bitmapByte;
138
 
            }
139
 
        }
140
 
    } else {
141
 
        /* RichCursor encoding. */
142
 
       int bpp1=cl->screen->rfbServerFormat.bitsPerPixel/8,
143
 
         bpp2=cl->format.bitsPerPixel/8;
144
 
       (*cl->translateFn)(cl->translateLookupTable,
145
 
                       &(cl->screen->rfbServerFormat),
146
 
                       &cl->format, (char*)pCursor->richSource,
147
 
                       &cl->updateBuf[cl->ublen],
148
 
                       pCursor->width*bpp1, pCursor->width, pCursor->height);
149
 
 
150
 
       cl->ublen += pCursor->width*bpp2*pCursor->height;
151
 
    }
152
 
 
153
 
    /* Prepare transparency mask. */
154
 
 
155
 
    bitmapData = (uint8_t *)pCursor->mask;
156
 
 
157
 
    for (i = 0; i < pCursor->height; i++) {
158
 
        for (j = 0; j < bitmapRowBytes; j++) {
159
 
            bitmapByte = bitmapData[i * bitmapRowBytes + j];
160
 
            cl->updateBuf[cl->ublen++] = (char)bitmapByte;
161
 
        }
162
 
    }
163
 
 
164
 
    /* Send everything we have prepared in the cl->updateBuf[]. */
165
 
 
166
 
    cl->rfbCursorShapeBytesSent += (cl->ublen - saved_ublen);
167
 
    cl->rfbCursorShapeUpdatesSent++;
168
 
 
169
 
    if (!rfbSendUpdateBuf(cl))
170
 
        return FALSE;
171
 
 
172
 
    return TRUE;
173
 
}
174
 
 
175
 
/*
176
 
 * Send cursor position (PointerPos pseudo-encoding).
177
 
 */
178
 
 
179
 
rfbBool
180
 
rfbSendCursorPos(rfbClientPtr cl)
181
 
{
182
 
  rfbFramebufferUpdateRectHeader rect;
183
 
 
184
 
  if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
185
 
    if (!rfbSendUpdateBuf(cl))
186
 
      return FALSE;
187
 
  }
188
 
 
189
 
  rect.encoding = Swap32IfLE(rfbEncodingPointerPos);
190
 
  rect.r.x = Swap16IfLE(cl->screen->cursorX);
191
 
  rect.r.y = Swap16IfLE(cl->screen->cursorY);
192
 
  rect.r.w = 0;
193
 
  rect.r.h = 0;
194
 
 
195
 
  memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
196
 
         sz_rfbFramebufferUpdateRectHeader);
197
 
  cl->ublen += sz_rfbFramebufferUpdateRectHeader;
198
 
 
199
 
  cl->rfbCursorPosBytesSent += sz_rfbFramebufferUpdateRectHeader;
200
 
  cl->rfbCursorPosUpdatesSent++;
201
 
 
202
 
  if (!rfbSendUpdateBuf(cl))
203
 
    return FALSE;
204
 
 
205
 
  return TRUE;
206
 
}
207
 
 
208
 
/* conversion routine for predefined cursors in LSB order */
209
 
unsigned char rfbReverseByte[0x100] = {
210
 
  /* copied from Xvnc/lib/font/util/utilbitmap.c */
211
 
        0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
212
 
        0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
213
 
        0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
214
 
        0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
215
 
        0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
216
 
        0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
217
 
        0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
218
 
        0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
219
 
        0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
220
 
        0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
221
 
        0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
222
 
        0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
223
 
        0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
224
 
        0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
225
 
        0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
226
 
        0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
227
 
        0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
228
 
        0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
229
 
        0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
230
 
        0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
231
 
        0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
232
 
        0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
233
 
        0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
234
 
        0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
235
 
        0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
236
 
        0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
237
 
        0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
238
 
        0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
239
 
        0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
240
 
        0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
241
 
        0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
242
 
        0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
243
 
};
244
 
 
245
 
void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap)
246
 
{
247
 
   int i,t=(width+7)/8*height;
248
 
   for(i=0;i<t;i++)
249
 
     bitmap[i]=rfbReverseByte[(int)bitmap[i]];
250
 
}
251
 
 
252
 
/* Cursor creation. You "paint" a cursor and let these routines do the work */
253
 
 
254
 
rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString)
255
 
{
256
 
   int i,j,w=(width+7)/8;
257
 
   rfbCursorPtr cursor = (rfbCursorPtr)calloc(1,sizeof(rfbCursor));
258
 
   char* cp;
259
 
   unsigned char bit;
260
 
 
261
 
   cursor->cleanup=TRUE;
262
 
   cursor->width=width;
263
 
   cursor->height=height;
264
 
   /*cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff;*/
265
 
   cursor->foreRed=cursor->foreGreen=cursor->foreBlue=0xffff;
266
 
   
267
 
   cursor->source = (unsigned char*)calloc(w,height);
268
 
   cursor->cleanupSource = TRUE;
269
 
   for(j=0,cp=cursorString;j<height;j++)
270
 
      for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
271
 
        if(*cp!=' ') cursor->source[j*w+i/8]|=bit;
272
 
 
273
 
   if(maskString) {
274
 
      cursor->mask = (unsigned char*)calloc(w,height);
275
 
      for(j=0,cp=maskString;j<height;j++)
276
 
        for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
277
 
          if(*cp!=' ') cursor->mask[j*w+i/8]|=bit;
278
 
   } else
279
 
     cursor->mask = (unsigned char*)rfbMakeMaskForXCursor(width,height,(char*)cursor->source);
280
 
   cursor->cleanupMask = TRUE;
281
 
 
282
 
   return(cursor);
283
 
}
284
 
 
285
 
char* rfbMakeMaskForXCursor(int width,int height,char* source)
286
 
{
287
 
   int i,j,w=(width+7)/8;
288
 
   char* mask=(char*)calloc(w,height);
289
 
   unsigned char c;
290
 
   
291
 
   for(j=0;j<height;j++)
292
 
     for(i=w-1;i>=0;i--) {
293
 
        c=source[j*w+i];
294
 
        if(j>0) c|=source[(j-1)*w+i];
295
 
        if(j<height-1) c|=source[(j+1)*w+i];
296
 
        
297
 
        if(i>0 && (c&0x80))
298
 
          mask[j*w+i-1]|=0x01;
299
 
        if(i<w-1 && (c&0x01))
300
 
          mask[j*w+i+1]|=0x80;
301
 
        
302
 
        mask[j*w+i]|=(c<<1)|c|(c>>1);
303
 
     }
304
 
   
305
 
   return(mask);
306
 
}
307
 
 
308
 
void rfbFreeCursor(rfbCursorPtr cursor)
309
 
{
310
 
   if(cursor) {
311
 
       if(cursor->cleanupRichSource && cursor->richSource)
312
 
           free(cursor->richSource);
313
 
       if(cursor->cleanupSource && cursor->source)
314
 
           free(cursor->source);
315
 
       if(cursor->cleanupMask && cursor->mask)
316
 
           free(cursor->mask);
317
 
       if(cursor->cleanup)
318
 
           free(cursor);
319
 
       else {
320
 
           cursor->cleanup=cursor->cleanupSource=cursor->cleanupMask
321
 
               =cursor->cleanupRichSource=FALSE;
322
 
           cursor->source=cursor->mask=cursor->richSource=0;
323
 
       }
324
 
   }
325
 
   
326
 
}
327
 
 
328
 
/* background and foregroud colour have to be set beforehand */
329
 
void MakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
330
 
{
331
 
   rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
332
 
   int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8,
333
 
     width=cursor->width*bpp;
334
 
   uint32_t background;
335
 
   char *back=(char*)&background;
336
 
   unsigned char bit;
337
 
 
338
 
   if(cursor->source && cursor->cleanupSource)
339
 
       free(cursor->source);
340
 
   cursor->source=(unsigned char*)calloc(w,cursor->height);
341
 
   cursor->cleanupSource=TRUE;
342
 
   
343
 
   if(format->bigEndian)
344
 
      back+=4-bpp;
345
 
 
346
 
   background=cursor->backRed<<format->redShift|
347
 
     cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
348
 
 
349
 
   for(j=0;j<cursor->height;j++)
350
 
     for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1)
351
 
       if(memcmp(cursor->richSource+j*width+i*bpp,back,bpp))
352
 
         cursor->source[j*w+i/8]|=bit;
353
 
}
354
 
 
355
 
void MakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
356
 
{
357
 
   rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
358
 
   int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8;
359
 
   uint32_t background,foreground;
360
 
   char *back=(char*)&background,*fore=(char*)&foreground;
361
 
   unsigned char *cp;
362
 
   unsigned char bit;
363
 
 
364
 
   if(cursor->richSource && cursor->cleanupRichSource)
365
 
       free(cursor->richSource);
366
 
   cp=cursor->richSource=(unsigned char*)calloc(cursor->width*bpp,cursor->height);
367
 
   cursor->cleanupRichSource=TRUE;
368
 
   
369
 
   if(format->bigEndian) {
370
 
      back+=4-bpp;
371
 
      fore+=4-bpp;
372
 
   }
373
 
 
374
 
   background=cursor->backRed<<format->redShift|
375
 
     cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
376
 
   foreground=cursor->foreRed<<format->redShift|
377
 
     cursor->foreGreen<<format->greenShift|cursor->foreBlue<<format->blueShift;
378
 
   
379
 
   for(j=0;j<cursor->height;j++)
380
 
     for(i=0,bit=0x80;i<cursor->height;i++,bit=(bit&1)?0x80:bit>>1,cp+=bpp)
381
 
       if(cursor->source[j*w+i/8]&bit) memcpy(cp,fore,bpp);
382
 
       else memcpy(cp,back,bpp);
383
 
}
384
 
 
385
 
/* functions to draw/hide cursor directly in the frame buffer */
386
 
 
387
 
void rfbUndrawCursor(rfbScreenInfoPtr s)
388
 
{
389
 
   rfbCursorPtr c=s->cursor;
390
 
   int j,x1,x2,y1,y2,bpp=s->rfbServerFormat.bitsPerPixel/8,
391
 
     rowstride=s->paddedWidthInBytes;
392
 
   LOCK(s->cursorMutex);
393
 
   if(!s->cursorIsDrawn || !c) {
394
 
     UNLOCK(s->cursorMutex);
395
 
     return;
396
 
   }
397
 
   
398
 
   /* restore what is under the cursor */
399
 
   x1=s->cursorX-c->xhot;
400
 
   x2=x1+c->width;
401
 
   if(x1<0) x1=0;
402
 
   if(x2>=s->width) x2=s->width-1;
403
 
   x2-=x1; if(x2<=0) {
404
 
     UNLOCK(s->cursorMutex);
405
 
     return;
406
 
   }
407
 
   y1=s->cursorY-c->yhot;
408
 
   y2=y1+c->height;
409
 
   if(y1<0) y1=0;
410
 
   if(y2>=s->height) y2=s->height-1;
411
 
   y2-=y1; if(y2<=0) {
412
 
     UNLOCK(s->cursorMutex);
413
 
     return;
414
 
   }
415
 
 
416
 
   /* get saved data */
417
 
   for(j=0;j<y2;j++)
418
 
     memcpy(s->frameBuffer+(y1+j)*rowstride+x1*bpp,
419
 
            s->underCursorBuffer+j*x2*bpp,
420
 
            x2*bpp);
421
 
   
422
 
   /* rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2); */
423
 
   s->cursorIsDrawn = FALSE;
424
 
   s->oldCursorX=s->cursorX;
425
 
   s->oldCursorY=s->cursorY;
426
 
   UNLOCK(s->cursorMutex);
427
 
}
428
 
 
429
 
void rfbDrawCursor(rfbScreenInfoPtr s)
430
 
{
431
 
   rfbCursorPtr c=s->cursor;
432
 
   int i,j,x1,x2,y1,y2,i1,j1,bpp=s->rfbServerFormat.bitsPerPixel/8,
433
 
     rowstride=s->paddedWidthInBytes,
434
 
     bufSize,w;
435
 
   rfbBool wasChanged=FALSE;
436
 
 
437
 
   if(!c) return;
438
 
   LOCK(s->cursorMutex);
439
 
   if(s->cursorIsDrawn) {
440
 
     /* is already drawn */
441
 
     UNLOCK(s->cursorMutex);
442
 
     return;
443
 
   }
444
 
 
445
 
   if(s->cursor && s->underCursorBuffer &&
446
 
                   (s->cursorX!=s->oldCursorX || s->cursorY!=s->oldCursorY)) {
447
 
           int x1=s->oldCursorX-s->cursor->xhot,x2=x1+s->cursor->width;
448
 
           int y1=s->oldCursorY-s->cursor->yhot,y2=y1+s->cursor->height;
449
 
           rfbMarkRectAsModified(s,x1,y1,x2,y2);
450
 
   }
451
 
   bufSize=c->width*c->height*bpp;
452
 
   w=(c->width+7)/8;
453
 
   if(s->underCursorBufferLen<bufSize) {
454
 
      if(s->underCursorBuffer!=NULL)
455
 
        free(s->underCursorBuffer);
456
 
      s->underCursorBuffer=malloc(bufSize);
457
 
      s->underCursorBufferLen=bufSize;
458
 
   }
459
 
   /* save what is under the cursor */
460
 
   i1=j1=0; /* offset in cursor */
461
 
   x1=s->cursorX-c->xhot;
462
 
   x2=x1+c->width;
463
 
   if(x1<0) { i1=-x1; x1=0; }
464
 
   if(x2>=s->width) x2=s->width-1;
465
 
   x2-=x1; if(x2<=0) {
466
 
     UNLOCK(s->cursorMutex);
467
 
     return; /* nothing to do */
468
 
   }
469
 
   y1=s->cursorY-c->yhot;
470
 
   y2=y1+c->height;
471
 
   if(y1<0) { j1=-y1; y1=0; }
472
 
   if(y2>=s->height) y2=s->height-1;
473
 
   y2-=y1; if(y2<=0) {
474
 
     UNLOCK(s->cursorMutex);
475
 
     return; /* nothing to do */
476
 
   }
477
 
 
478
 
   /* save data */
479
 
   for(j=0;j<y2;j++) {
480
 
     char* dest=s->underCursorBuffer+j*x2*bpp;
481
 
     const char* src=s->frameBuffer+(y1+j)*rowstride+x1*bpp;
482
 
     unsigned int count=x2*bpp;
483
 
     if(wasChanged || memcmp(dest,src,count)) {
484
 
       wasChanged=TRUE;
485
 
       memcpy(dest,src,count);
486
 
     }
487
 
   }
488
 
   
489
 
   if(!c->richSource)
490
 
     MakeRichCursorFromXCursor(s,c);
491
 
   
492
 
   /* now the cursor has to be drawn */
493
 
   for(j=0;j<y2;j++)
494
 
     for(i=0;i<x2;i++)
495
 
       if((c->mask[(j+j1)*w+(i+i1)/8]<<((i+i1)&7))&0x80)
496
 
         memcpy(s->frameBuffer+(j+y1)*rowstride+(i+x1)*bpp,
497
 
                c->richSource+(j+j1)*c->width*bpp+(i+i1)*bpp,bpp);
498
 
 
499
 
   if(wasChanged)
500
 
     rfbMarkRectAsModified(s,x1,y1,x1+x2,y1+y2);
501
 
   s->cursorIsDrawn = TRUE;
502
 
   UNLOCK(s->cursorMutex);
503
 
}
504
 
 
505
 
/* for debugging */
506
 
 
507
 
void rfbPrintXCursor(rfbCursorPtr cursor)
508
 
{
509
 
   int i,i1,j,w=(cursor->width+7)/8;
510
 
   unsigned char bit;
511
 
   for(j=0;j<cursor->height;j++) {
512
 
      for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
513
 
        if(cursor->source[j*w+i]&bit) putchar('#'); else putchar(' ');
514
 
      putchar(':');
515
 
      for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
516
 
        if(cursor->mask[j*w+i]&bit) putchar('#'); else putchar(' ');
517
 
      putchar('\n');
518
 
   }
519
 
}
520
 
 
521
 
void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c,rfbBool freeOld)
522
 
{
523
 
  LOCK(rfbScreen->cursorMutex);
524
 
  while(rfbScreen->cursorIsDrawn) {
525
 
    UNLOCK(rfbScreen->cursorMutex);
526
 
    rfbUndrawCursor(rfbScreen);
527
 
    LOCK(rfbScreen->cursorMutex);
528
 
  }
529
 
 
530
 
  free(rfbScreen->underCursorBuffer);
531
 
  rfbScreen->underCursorBuffer=0;
532
 
 
533
 
  if(rfbScreen->cursor && (freeOld || rfbScreen->cursor->cleanup))
534
 
    rfbFreeCursor(rfbScreen->cursor);
535
 
 
536
 
  rfbScreen->cursor = c;
537
 
 
538
 
  UNLOCK(rfbScreen->cursorMutex);
539
 
}