home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / frei / palmsrc.arj / PALMSRC.ZIP / rfbproto.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-07-31  |  20.3 KB  |  665 lines

  1. /*
  2.  *  Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
  3.  *
  4.  *  Copyright (C) 1998 International Computer Science Institute (ICSI)
  5.  *
  6.  *  This is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This software is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this software; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  19.  *  USA.
  20.  */
  21.  
  22. /*
  23.  * rfbproto.c - functions to deal with client side of RFB protocol.
  24.  */
  25.  
  26. #include "palmVNC.h"
  27. #include "palmVNCRsc.h"
  28. #include "vncauth.h"
  29.  
  30. static Bool HandleHextileEncoding8(int x, int y, int w, int h);
  31.  
  32. int rfbsock = 0;
  33. char *desktopName;
  34. Bool useBGR233 = True;
  35. int requestedDepth = 0;
  36. Bool debug = False;
  37.  
  38. rfbPixelFormat myFormat;
  39. rfbServerInitMsg si;
  40. Bool sendUpdateRequest;
  41.  
  42. PRFBViewport palmFB;
  43.  
  44. int endianTest = 1;
  45.  
  46.  
  47. /* note that the CoRRE encoding uses this buffer and assumes it is big enough
  48.    to hold 255 * 255 * 32 bits -> 260100 bytes.  640*480 = 307200 bytes */
  49. /* also hextile assumes it is big enough to hold 16 * 16 * 32 bits */
  50.  
  51. #define BUFFER_SIZE (16*16) // that works with BGR233 only!
  52. static unsigned char buffer[BUFFER_SIZE];
  53.  
  54.  
  55. /******************************************************************
  56.  * ConnectToRFBServer
  57.  *
  58.  * connects on the networkl level
  59.  *****************************************************************/
  60. Bool ConnectToRFBServer (char *hostname, int port)
  61. {
  62.     unsigned long host = 0;
  63.  
  64.     if (!StringToIPAddr (hostname, &host)) {
  65.     printf ("Couldn't convert \"%s\" to a real host address\n", hostname);
  66.     return False;
  67.     }
  68.  
  69.     rfbsock = ConnectToTcpAddr (host, port);
  70.  
  71.     if (rfbsock < 0) {
  72.     printf ("Unable to connect to the VNC server \"%s\", port %d\n",
  73.         hostname, port);
  74.     return False;
  75.     }
  76.  
  77.     printf ("Network connection established\n");
  78.     return True;
  79. }
  80.  
  81.  
  82. /******************************************************************
  83.  * InitialiseRFBConnection.
  84.  *
  85.  * connects on the VNC protocol level, i.e. handshake, authentication, etc
  86.  *****************************************************************/
  87.  
  88. Bool InitialiseRFBConnection (int sock)
  89. {
  90.     rfbProtocolVersionMsg pv;
  91.     int majorV,minorV;
  92.     Bool authWillWork = True;
  93.     CARD32 authScheme, reasonLen;
  94.     char *reason;
  95.     CARD32 authResult;
  96.     CARD8 challenge[CHALLENGESIZE];
  97.     rfbClientInitMsg ci;
  98.     char testVer[8];
  99.  
  100.     if (!ReadExact(sock, (unsigned char*)pv, sz_rfbProtocolVersionMsg))
  101.       return False;
  102.  
  103.     PostProgressMessage ("Handshaking...", 0, 0);
  104.  
  105.     errorMessageFromReadExact = True;
  106.  
  107.     pv[sz_rfbProtocolVersionMsg] = 0;
  108.  
  109.     majorV = rfbProtocolMajorVersion;
  110.     minorV = rfbProtocolMinorVersion;
  111.  
  112.     StrPrintF (testVer, "00%d.00%d\n", majorV, minorV);
  113.  
  114.     if (StrStr (pv, "RFB") == 0) {
  115.     printf ("Not a valid VNC server\n");
  116.     return False;
  117.     }
  118.  
  119.     printf ("VNC server supports protocol version: %s\nViewer supports %d.%d\n",
  120.         pv, majorV, minorV);
  121.  
  122.     if (StrStr (pv, testVer) == 0) {
  123.        // if server is before 3.3 authentication won't work
  124.       authWillWork = False;
  125.     } 
  126.  
  127.     StrPrintF (pv, rfbProtocolVersionFormat, majorV, minorV);
  128.  
  129.     if (!WriteExact(sock, (unsigned char*)pv, sz_rfbProtocolVersionMsg)) return False;
  130.  
  131.     if (!ReadExact(sock, (unsigned char*)&authScheme, 4)) return False;
  132.  
  133.     authScheme = Swap32IfLE(authScheme);
  134.  
  135.     switch (authScheme) {
  136.  
  137.     case rfbConnFailed:
  138.     if (!ReadExact(sock, (unsigned char*)&reasonLen, 4)) return False;
  139.     reasonLen = Swap32IfLE(reasonLen);
  140.  
  141.     if ((reason = MemPtrNew (reasonLen)) == 0) {
  142.       printf ("ERROR: cannot allocate mem ptr\n");
  143.       return false;
  144.      }
  145.  
  146.     if (!ReadExact(sock, (unsigned char*)reason, (int)reasonLen)) return False;
  147.  
  148.     printf ("VNC connection failed: %s\n", reason);
  149.  
  150.     MemPtrFree (reason);
  151.  
  152.     return False;
  153.  
  154.     case rfbNoAuth:
  155.     printf ("No authentication needed\n");
  156.     break;
  157.  
  158.     case rfbVncAuth:
  159.     if (!authWillWork) {
  160.         printf (
  161.             "\nVNC server uses the old authentication scheme.\n"
  162.             "You should kill your old desktop(s) and restart.\n"
  163.             "If you really need to connect to this desktop use "
  164.             "vncviewer3.2\n\n");
  165.         return False;
  166.     }
  167.  
  168.     if (!ReadExact(sock, (unsigned char*)challenge, CHALLENGESIZE)) return False;
  169.  
  170.     vncEncryptBytes(challenge, pref.server.password);
  171.  
  172.     if (!WriteExact(sock, (unsigned char*)challenge, CHALLENGESIZE)) return False;
  173.  
  174.     if (!ReadExact(sock, (unsigned char*)&authResult, 4)) return False;
  175.  
  176.     authResult = Swap32IfLE(authResult);
  177.  
  178.     switch (authResult) {
  179.     case rfbVncAuthOK:
  180.         printf ("VNC authentication succeeded\n");
  181.         break;
  182.     case rfbVncAuthFailed:
  183.         printf ("\nVNC authentication failed\n\n");
  184.         return False;
  185.     case rfbVncAuthTooMany:
  186.         printf ("VNC authentication failed - too many tries\n");
  187.         return False;
  188.     default:
  189.         printf ("Unknown VNC authentication result: %d\n", (int)authResult);
  190.         return False;
  191.     }
  192.     break;
  193.     default:
  194.     printf ("Unknown authentication scheme from VNC server: %d\n",
  195.         (int)authScheme);
  196.     return False;
  197.     }
  198.  
  199.     ci.shared = (pref.server.sharedDesktop ? 1 : 0);
  200.  
  201.     if (!WriteExact(sock, (unsigned char*)&ci, sz_rfbClientInitMsg)) return False;
  202.  
  203.     if (!ReadExact(sock, (unsigned char*)&si, sz_rfbServerInitMsg)) return False;
  204.  
  205.     si.framebufferWidth = Swap16IfLE(si.framebufferWidth);
  206.     si.framebufferHeight = Swap16IfLE(si.framebufferHeight);
  207.     si.format.redMax = Swap16IfLE(si.format.redMax);
  208.     si.format.greenMax = Swap16IfLE(si.format.greenMax);
  209.     si.format.blueMax = Swap16IfLE(si.format.blueMax);
  210.     si.nameLength = Swap32IfLE(si.nameLength);
  211.  
  212.     palmFB.remote.w = si.framebufferWidth;
  213.     palmFB.remote.h = si.framebufferHeight;
  214.  
  215.     if ((desktopName = MemPtrNew (si.nameLength + 1)) == 0) {
  216.       printf ("ERROR: cannot allocate mem ptr\n");
  217.       return false;
  218.     }
  219.  
  220.     if (!ReadExact(sock, (unsigned char*)desktopName, (int)si.nameLength)) return False;
  221.  
  222.     desktopName[si.nameLength] = 0;
  223.  
  224.     printf ("Desktop size: %dx%d\n", si.framebufferWidth, si.framebufferHeight);
  225.     printf ("Desktop name \"%s\"\n", desktopName);
  226.  
  227.     MemPtrFree (desktopName);
  228.  
  229.     printf ("Connected to VNC server, using protocol version %d.%d\n",
  230.         rfbProtocolMajorVersion, rfbProtocolMinorVersion);
  231.  
  232.     return True;
  233. }
  234.  
  235.  
  236. /******************************************************************
  237.  * SetFormatAndEncodings
  238.  *****************************************************************/
  239. Bool SetFormatAndEncodings()
  240. {
  241.     rfbSetPixelFormatMsg spf;
  242.     unsigned char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4];
  243.     rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf;
  244.     CARD32 *encs = (CARD32 *)(&buf[sz_rfbSetEncodingsMsg]);
  245.     int len = 0;
  246.  
  247.     spf.type = rfbSetPixelFormat;
  248.     spf.format = myFormat;
  249.     spf.format.redMax = Swap16IfLE(spf.format.redMax);
  250.     spf.format.greenMax = Swap16IfLE(spf.format.greenMax);
  251.     spf.format.blueMax = Swap16IfLE(spf.format.blueMax);
  252.  
  253.     if (!WriteExact(rfbsock, (unsigned char*)&spf, sz_rfbSetPixelFormatMsg))
  254.     return False;
  255.  
  256.     se->type = rfbSetEncodings;
  257.     se->nEncodings = 0;
  258.  
  259.     // VM PalmVNC currently supports only Hextile encoding */
  260.     encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile);
  261.  
  262.     len = sz_rfbSetEncodingsMsg + se->nEncodings * 4;
  263.  
  264.     se->nEncodings = Swap16IfLE(se->nEncodings);
  265.  
  266.     if (!WriteExact(rfbsock, buf, len)) return False;
  267.  
  268.     return True;
  269. }
  270.  
  271.  
  272. /******************************************************************
  273.  * SendIncrementalFramebufferUpdateRequest
  274.  *****************************************************************/
  275. Bool SendIncrementalFramebufferUpdateRequest()
  276. {
  277.  
  278.   return SendFramebufferUpdateRequest((int)palmFB.virtual.x,
  279.         (int)palmFB.virtual.y,
  280.         (int)palmFB.virtual.w,
  281.         (int)palmFB.virtual.h,
  282.         true);
  283. }
  284.  
  285.  
  286. /******************************************************************
  287.  * SendFramebufferUpdateRequest.
  288.  *****************************************************************/
  289. Bool SendFramebufferUpdateRequest(int x, int y, int w, int h, int incremental)
  290. {
  291.     rfbFramebufferUpdateRequestMsg fur;
  292.  
  293. #ifdef DEBUG_VNC_CODING
  294.     printf ("rect req: %dx%d (%d,%d) inc %d\n",
  295.             w, h, x, y, incremental);
  296. #endif
  297.  
  298.     fur.type = rfbFramebufferUpdateRequest;
  299.     fur.incremental = incremental ? 1 : 0;
  300.     fur.x = Swap16IfLE(x);
  301.     fur.y = Swap16IfLE(y);
  302.     fur.w = Swap16IfLE(w);
  303.     fur.h = Swap16IfLE(h);
  304.  
  305.     if (!WriteExact(rfbsock, (unsigned char*)&fur,
  306.             sz_rfbFramebufferUpdateRequestMsg))
  307.     return False;
  308.  
  309.     // we do this in the event loop, it was: sendUpdateRequest = false;
  310.  
  311.     return True;
  312. }
  313.  
  314.  
  315. /******************************************************************
  316.  * SendPointerEvent.
  317.  *****************************************************************/
  318. Bool SendPointerEvent(int x, int y, int buttonMask)
  319. {
  320.     rfbPointerEventMsg pe;
  321.  
  322.     pe.type = rfbPointerEvent;
  323.     pe.buttonMask = buttonMask;
  324.     if (x < 0) x = 0;
  325.     if (y < 0) y = 0;
  326.     pe.x = Swap16IfLE(x);
  327.     pe.y = Swap16IfLE(y);
  328.     return WriteExact(rfbsock, (unsigned char*)&pe, sz_rfbPointerEventMsg);
  329. }
  330.  
  331.  
  332. /******************************************************************
  333.  * SendKeyEvent.
  334.  *****************************************************************/
  335. Bool SendKeyEvent(CARD32 key, int down)
  336. {
  337.     rfbKeyEventMsg ke;
  338.  
  339.     ke.type = rfbKeyEvent;
  340.     ke.down = down ? 1 : 0;
  341.     ke.key = Swap32IfLE(key);
  342.     return WriteExact(rfbsock, (unsigned char*)&ke, sz_rfbKeyEventMsg);
  343. }
  344.  
  345.  
  346. /******************************************************************
  347.  * SendClientCutText.
  348.  *****************************************************************/
  349. Bool SendClientCutText(char *str, int len)
  350. {
  351.     rfbClientCutTextMsg cct;
  352.  
  353. #ifdef DEBUG_VNC
  354.     printf ("%d bytes in CutText sent:\n", len);
  355.     printf ("\t\"%s\"\n", str);
  356. #endif
  357.  
  358.     cct.type = rfbClientCutText;
  359.     cct.length = Swap32IfLE (len);
  360.  
  361.     return  (WriteExact(rfbsock, (unsigned char*)&cct,
  362.             sz_rfbClientCutTextMsg) &&
  363.          WriteExact(rfbsock, (unsigned char*)str, len));
  364. }
  365.  
  366.  
  367. /******************************************************************
  368.  * HandleRFBServerMessage.
  369.  *****************************************************************/
  370. Bool HandleRFBServerMessage()
  371. {
  372.     rfbServerToClientMsg msg;
  373.  
  374.     if (!ReadExact(rfbsock, (unsigned char*)&msg, 1))
  375.     return False;
  376.  
  377.     switch (msg.type) {
  378.  
  379.     case rfbSetColourMapEntries:
  380.     {
  381.     if (!ReadExact(rfbsock, ((unsigned char*)&msg) + 1,
  382.              sz_rfbSetColourMapEntriesMsg - 1))
  383.         return False;
  384.  
  385. #ifdef DEBUG_VNC_CODING
  386.         printf ("-> colormap: n %d, NOT SUPPORTED YET\n", msg.scme.nColours);
  387. #endif
  388.     break;
  389.     }
  390.  
  391.     case rfbFramebufferUpdate:
  392.     {
  393.     rfbFramebufferUpdateRectHeader rect;
  394.     int i;
  395.  
  396.     if (!ReadExact(rfbsock, ((unsigned char*)&msg.fu) + 1,
  397.              sz_rfbFramebufferUpdateMsg - 1))
  398.         return False;
  399.  
  400.     msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
  401.  
  402. #ifdef DEBUG_VNC_CODING
  403.     printf (" %d nRects in a msg\n", msg.fu.nRects);
  404. #endif
  405.  
  406.     for (i = 0; i < msg.fu.nRects; i++) {
  407.  
  408.         if (!ReadExact(rfbsock, (unsigned char*)&rect,
  409.                  sz_rfbFramebufferUpdateRectHeader))
  410.         return False;
  411.  
  412.         rect.r.x = Swap16IfLE(rect.r.x);
  413.         rect.r.y = Swap16IfLE(rect.r.y);
  414.         rect.r.w = Swap16IfLE(rect.r.w);
  415.         rect.r.h = Swap16IfLE(rect.r.h);
  416.  
  417.         rect.encoding = Swap32IfLE(rect.encoding);
  418.  
  419.         if ((rect.r.x + rect.r.w > si.framebufferWidth) ||
  420.         (rect.r.y + rect.r.h > si.framebufferHeight))
  421.         {
  422.         printf ("rect too large: %dx%d at (%d, %d)\n",
  423.                rect.r.w, rect.r.h, rect.r.x, rect.r.y);
  424.         return False;
  425.         }
  426.  
  427.         if ((rect.r.h * rect.r.w) == 0) {
  428.         printf ("zero size rect - ignoring\n");
  429.         continue;
  430.         }
  431.  
  432.         switch (rect.encoding) {
  433.  
  434.         case rfbEncodingRaw:
  435. #ifdef DEBUG_VNC_CODING
  436.         printf ("->raw encoding: rec %dx%d, NOT SUPPORTED\n",
  437.             rect.r.h, rect.r.w);
  438. #endif
  439.         return False;
  440.         break;
  441.  
  442.         case rfbEncodingCopyRect:
  443.         {
  444. #ifdef DEBUG_VNC_CODING
  445.         printf ("-> copy rect, rect %dx%d, NOT SUPPORTED\n",
  446.             rect.r.h, rect.r.w);
  447. #endif
  448.         return False;
  449.         break;
  450.         }
  451.  
  452.         case rfbEncodingRRE:
  453.         {
  454.  
  455. #ifdef DEBUG_VNC_CODING
  456.         printf ("-> REE encoding, NOT SUPPORTED\n");
  457. #endif
  458.         return False;
  459.         }
  460.  
  461.         case rfbEncodingCoRRE:
  462.         {
  463. #ifdef DEBUG_VNC_CODING
  464.         printf ("-> CoREE encoding, NOT SUPPORTED\n");
  465. #endif
  466.         return False;
  467.         }
  468.  
  469.         case rfbEncodingHextile:
  470.         {
  471. #ifdef DEBUG_VNC_CODING
  472.         printf ("-> Hext r %dx%d (%d,%d)\n",
  473.             rect.r.w, rect.r.h, rect.r.x, rect.r.y);
  474. #endif
  475.         switch (myFormat.bitsPerPixel) {
  476.         case 8:
  477.             if (!HandleHextileEncoding8((int)rect.r.x, (int)rect.r.y,
  478.                         (int)rect.r.w, (int)rect.r.h))
  479.             return False;
  480.             break;
  481.         default:
  482. #ifdef DEBUG_VNC_CODING
  483.             printf ("-> Hextile %d bit, NOT SUPPORTED\n", myFormat.bitsPerPixel);
  484. #endif
  485.             return False;
  486.         }
  487.         break;
  488.         }
  489.  
  490.         default:
  491.         printf ("unknown rect encoding %d\n", (int)rect.encoding);
  492.         return False;
  493.         }
  494.     }
  495.  
  496.     sendUpdateRequest = True;
  497.  
  498.     break;
  499.     }
  500.  
  501.     case rfbBell:
  502.     SndPlaySystemSound ((SndSysBeepType)sndInfo);
  503.     break;
  504.  
  505.     case rfbServerCutText:
  506.     {
  507.     char *str;
  508.     Word length = 0;
  509.     Word buttonID = 0;
  510.  
  511.     if (!ReadExact(rfbsock, ((unsigned char*)&msg) + 1,
  512.              sz_rfbServerCutTextMsg - 1))
  513.         return False;
  514.  
  515.     msg.sct.length = Swap32IfLE(msg.sct.length);
  516.  
  517.     str = MemPtrNew (msg.sct.length);
  518.  
  519.     if (!ReadExact(rfbsock, (unsigned char*)str, msg.sct.length))
  520.         return False;
  521.  
  522. #ifdef DEBUG_VNC
  523.         printf ("%d bytes in CutText received\n", (Word)msg.sct.length);
  524.         printf ("\t\"%s\"\n", str);
  525. #endif
  526.     if (msg.sct.length > cbdMaxTextLength)
  527.       length = cbdMaxTextLength;
  528.     else
  529.       length = msg.sct.length;
  530.  
  531.     if ((buttonID = FrmCustomAlert (ClipboardAlert, str, " ", " ")) == 0) { // the firt button, "OK"
  532.       ClipboardAddItem (clipboardText, str, length);
  533. #ifdef DEBUG_VNC
  534.           printf ("CutText copied into clipboard\n");
  535. #endif
  536.     }
  537.  
  538.     MemPtrFree (str);
  539.  
  540.     break;
  541.     }
  542.  
  543.     default:
  544.     printf ("unknown message type %d from VNC server\n", msg.type);
  545.     return false;
  546.     }
  547.  
  548.     return true;
  549. }
  550.  
  551.  
  552. #define GET_PIXEL8(pix,ptr) ((pix)=*(ptr)++)
  553.  
  554. static Bool HandleHextileEncoding8(int rx, int ry, int rw, int rh)                   
  555. {                                                                            
  556.     CARD8 bg, fg;
  557.     int i;                                                                    
  558.     CARD8 *ptr;                                                               
  559.     short x, y;
  560.     unsigned short w, h;                                                           
  561.     short sx, sy;
  562.     unsigned short sw, sh;                                                       
  563.     CARD8 subencoding;                                                        
  564.     CARD8 nSubrects;                                                          
  565.  
  566. #ifdef DEBUG_VNC_CODING
  567.     printf ("hextile %d and %d\n", ry+rh, rx+rw);
  568. #endif
  569.                                                              
  570.     for (y = ry; y < ry+rh; y += 16) {
  571.     PostProgressMessage ("Processing...", y, ry+rh);                                        
  572.         for (x = rx; x < rx+rw; x += 16) {                                    
  573.             w = h = 16;                                                       
  574.             if (rx+rw - x < 16)                                               
  575.                 w = rx+rw - x;                                                
  576.             if (ry+rh - y < 16)                                               
  577.                 h = ry+rh - y;                                                
  578.                                                                               
  579.             if (!ReadExact(rfbsock, (unsigned char*)&subencoding, 1))                 
  580.                 return False;                                                 
  581.  
  582.             if (subencoding & rfbHextileRaw) {                                
  583.                 if (!ReadExact(rfbsock, buffer, (int)(w * h)))           
  584.                     return False;                                             
  585.                                                                               
  586.                 CopyDataToScreen ((CARD8 *)buffer, x, y, w, h);                
  587.                 continue;                                                     
  588.             }                                                                 
  589.                                                                               
  590.             if (subencoding & rfbHextileBackgroundSpecified)                  
  591.                 if (!ReadExact(rfbsock, (unsigned char*)&bg, 1))                
  592.                     return False;                                             
  593. /*                                                                             
  594. #ifdef DEBUG_VNC_CODING
  595.         printf (" spec bg %d r %dx%d (%d,%d)\n",
  596.         bg, w, h, x, y);
  597. #endif
  598. */
  599.         DrawVirtualFilledRectangle (BGR233ToPixel[bg], x, y, w, h, true);
  600.  
  601.             if (subencoding & rfbHextileForegroundSpecified)                  
  602.                 if (!ReadExact(rfbsock, (unsigned char*)&fg, 1))                
  603.                     return False;                                             
  604.                                                                               
  605.             if (!(subencoding & rfbHextileAnySubrects)) {                     
  606.                 continue;                                                     
  607.             }                                                                 
  608.                                                                               
  609.             if (!ReadExact(rfbsock, (unsigned char*)&nSubrects, 1))                   
  610.                 return False;                                                 
  611.                                                                               
  612.             ptr = (CARD8 *)buffer;                                            
  613.                                                                               
  614.             if (subencoding & rfbHextileSubrectsColoured) {                   
  615.                 if (!ReadExact(rfbsock, buffer, nSubrects * (2 + 1))) 
  616.                     return False;                                             
  617.  
  618. #ifdef DEBUG_VNC_CODING
  619.             printf (" %d subr. colored\n", nSubrects);
  620. #endif
  621.  
  622.                 for (i = 0; i < nSubrects; i++) {                             
  623.                     GET_PIXEL8(fg, ptr);                                  
  624.                     sx = rfbHextileExtractX(*ptr);                            
  625.                     sy = rfbHextileExtractY(*ptr);                            
  626.                     ptr++;                                                    
  627.                     sw = rfbHextileExtractW(*ptr);                            
  628.                     sh = rfbHextileExtractH(*ptr);                            
  629.                     ptr++;
  630. /*                                               
  631. #ifdef DEBUG_VNC_CODING
  632.                 printf (" color %d\n", fg);
  633. #endif
  634. */
  635.                 DrawVirtualFilledRectangle (BGR233ToPixel[fg],
  636.             x+sx, y+sy, sw, sh, true);
  637.                 }                                                             
  638.                                                                               
  639.             } else {                                                          
  640.                 if (!ReadExact(rfbsock, buffer, nSubrects * 2))               
  641.                     return False;                                                             
  642.  
  643.                 for (i = 0; i < nSubrects; i++) {                             
  644.                     sx = rfbHextileExtractX(*ptr);                            
  645.                     sy = rfbHextileExtractY(*ptr);                            
  646.                     ptr++;                                                    
  647.                     sw = rfbHextileExtractW(*ptr);                            
  648.                     sh = rfbHextileExtractH(*ptr);                            
  649.                     ptr++;
  650. /*
  651. #ifdef DEBUG_VNC_CODING
  652.                 printf (" color %d\n", fg);
  653. #endif
  654. */
  655.             DrawVirtualFilledRectangle (BGR233ToPixel[fg],
  656.             x+sx, y+sy, sw, sh, true);
  657.                 }                                                             
  658.             }                                                                 
  659.         }                                                                     
  660.     }                                                                         
  661.                                                                               
  662.     return True;                                                              
  663. }
  664.  
  665.