home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / pmvnc100.zip / proto.c < prev    next >
C/C++ Source or Header  |  1999-08-03  |  18KB  |  704 lines

  1. /*
  2.  * proto.c - PM VNC Viewer, RFB Protocol Handling
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7.  
  8. #define INCL_PM
  9. #include <os2.h>
  10.  
  11. #include "pmvncdef.h"
  12. #include "vncauth.h"
  13.  
  14. /*
  15.  * VNC Session Context - depends on Pixel Format
  16.  */
  17.  
  18. VNCPTR  VncCtx = &VncCtx32 ;
  19.  
  20. UCHAR   VncGreeting[] = "Please wait - initial screen loading" ;
  21.  
  22. /*
  23.  * disable input till session ready
  24.  */
  25.  
  26. static  BOOL    inputReady = FALSE ;
  27.  
  28. /*
  29.  * chkVersion - Exchange Protocol Version
  30.  */
  31.  
  32. static  BOOL    authWillWork = TRUE ;
  33. static  int     verMajor, verMinor  ;
  34.  
  35. static  BOOL    chkVersion(void)
  36. {
  37.     rfbProtocolVersionMsg   pv ;
  38.     int     major, minor ;
  39.     
  40.     if (netRecv(pv, sz_rfbProtocolVersionMsg) != TRUE) {
  41.         netFail("failed to recv RFB Version") ;
  42.         return FALSE ;
  43.     }
  44.     pv[sz_rfbProtocolVersionMsg] = '\0' ;
  45.  
  46.     if (sscanf(pv, rfbProtocolVersionFormat, &major, &minor) != 2) {
  47.         netFail("failed to get Protocol Version") ;
  48.     return FALSE ;
  49.     }
  50.     
  51.     TRACE("Server RFB Protocol Version %d.%d\n", major, minor) ;
  52.     
  53.     if (major != rfbProtocolMajorVersion) {
  54.         netFail("RFB Major Version Unmatch") ;
  55.     return FALSE ;
  56.     }
  57.     if (minor < rfbProtocolMinorVersion) {
  58.         authWillWork = FALSE ;
  59.     } else {
  60.         major = rfbProtocolMajorVersion ;
  61.         minor = rfbProtocolMinorVersion ;
  62.     }
  63.     sprintf(pv, rfbProtocolVersionFormat, major, minor) ;
  64.     
  65.     if (netSend(pv, sz_rfbProtocolVersionMsg) != TRUE) {
  66.         netFail("failed to send Protocol Version") ;
  67.     return FALSE ;
  68.     } 
  69.     verMajor = major ;
  70.     verMinor = minor ;
  71.     
  72.     return TRUE ;
  73. }
  74.  
  75. /*
  76.  * chkAuth - Authentication
  77.  */
  78.  
  79. static  UCHAR   authChallenge[CHALLENGESIZE] ;
  80.  
  81. static  BOOL    chkAuth(void)
  82. {
  83.     CARD32  authScheme, reasonLen, authResult ;
  84.     PUCHAR  reason ;
  85.     
  86.     /*
  87.      * get auth. scheme
  88.      */
  89.      
  90.     if (netRecv((PUCHAR) &authScheme, sizeof(CARD32)) != TRUE) {
  91.         netFail("failed to recv Auth. Scheme") ;
  92.     return FALSE ;
  93.     }
  94.     authScheme = swap32(authScheme) ;
  95.     
  96.     TRACE("Auth. Scheme %d\n", authScheme) ;
  97.     
  98.     if (authScheme == rfbNoAuth) {
  99.         TRACE("no authentication needed\n") ;
  100.     return TRUE ;
  101.     }
  102.     if (authScheme == rfbConnFailed) {
  103.         if (netRecv((PUCHAR) &reasonLen, sizeof(CARD32)) != TRUE) {
  104.         netFail("failed to recv reason length") ;
  105.         return FALSE ;
  106.     }
  107.     reasonLen = swap32(reasonLen) ;
  108.     
  109.     if ((reason = malloc(reasonLen)) == NULL) {
  110.         netFail("failed to alloc reason buffer") ;
  111.         return FALSE ;
  112.     }
  113.     if (netRecv(reason, reasonLen) != TRUE) {
  114.         netFail("failed to recv reason") ;
  115.         return FALSE ;
  116.     }
  117.     netFail(reason) ;       /* don't free 'reason'  */
  118.     return FALSE ;
  119.     }    
  120.     if (authScheme != rfbVncAuth) {
  121.         netFail("unknown authenticaion scheme") ;
  122.         return FALSE ;
  123.     }
  124.  
  125.     /*
  126.      * case of rfbVncAuth
  127.      */
  128.      
  129.     if (! authWillWork) {
  130.         netFail("VNC Server uses old Auth. scheme") ;
  131.         return FALSE ;
  132.     }
  133.     if (netRecv(authChallenge, CHALLENGESIZE) != TRUE) {
  134.         netFail("failed to recv auth. challenge") ;
  135.         return FALSE ;
  136.     }
  137.     netNotify(WM_VNC_AUTH, NULL, MPFROMP(authChallenge)) ;
  138.         /*
  139.      * then window thread encode 'authChallenge' 
  140.      * and calls protoSendAuth
  141.      */
  142.     if (netRecv((PUCHAR) &authResult, sizeof(CARD32)) != TRUE) {
  143.         netFail("failed to recv auth. result") ;
  144.         return FALSE ;
  145.     }
  146.     authResult = swap32(authResult) ;
  147.     
  148.     TRACE("auth. result %d\n", authResult) ;
  149.     
  150.     switch (authResult) {
  151.     case rfbVncAuthOK :
  152.         TRACE("rfbVncAuthOK\n") ;
  153.         return TRUE ;
  154.     case rfbVncAuthFailed :
  155.         netFail("rfbVncAuthFailed") ;
  156.     return FALSE ;
  157.     case rfbVncAuthTooMany :
  158.         netFail("rfbVncAuthTooMany") ;
  159.     return FALSE ;
  160.     default :
  161.         netFail("unknown VNC auth. result") ;
  162.     return FALSE ;
  163.     }
  164.     return FALSE ;      /* not reach here   */
  165. }
  166.  
  167. /*
  168.  * protoSendAuth - Send Authentication Data
  169.  */
  170.  
  171. BOOL    protoSendAuth(void)
  172. {
  173.     if (netSend(authChallenge, CHALLENGESIZE) != TRUE) {
  174.         netFail("failed to Send Auth.") ;
  175.     return FALSE ;
  176.     }
  177.     return TRUE ;
  178. }
  179.  
  180. /*
  181.  * chkInit - Client/Server Initialization Message
  182.  */
  183.  
  184. static  rfbServerInitMsg    ServerInit ;
  185. static  PUCHAR              ServerDesk ;
  186.  
  187. static  BOOL    chkInit(void)
  188. {
  189.     rfbClientInitMsg    ci ;
  190.     rfbServerInitMsg    si ;
  191.     int     cx, cy ;
  192.     
  193.     /*
  194.      * send Client Initialization Message
  195.      */
  196.      
  197.     ci.shared = (SessOptShared ? 1 : 0) ;
  198.  
  199.     if (netSend((PUCHAR) &ci, sz_rfbClientInitMsg) != TRUE) {
  200.         netFail("failed to send ClientInit") ;
  201.     return FALSE ;
  202.     }
  203.     
  204.     /*
  205.      * recv Server Initialization Message
  206.      */
  207.  
  208.     if (netRecv((PUCHAR) &si, sz_rfbServerInitMsg) != TRUE) {
  209.         netFail("failed to recv ServerInit") ;
  210.     return FALSE ;
  211.     }
  212.     
  213.     si.framebufferWidth  = swap16(si.framebufferWidth)  ;
  214.     si.framebufferHeight = swap16(si.framebufferHeight) ;
  215.     si.format.redMax   = swap16(si.format.redMax)   ;
  216.     si.format.greenMax = swap16(si.format.greenMax) ;
  217.     si.format.blueMax  = swap16(si.format.blueMax)  ;
  218.     si.nameLength = swap32(si.nameLength) ;
  219.  
  220.     memcpy(&ServerInit, &si, sizeof(rfbServerInitMsg)) ;
  221.  
  222.     if ((ServerDesk = malloc(si.nameLength + 2)) == NULL) {
  223.         netFail("failed to alloc desktop name") ;
  224.     return FALSE ;
  225.     }
  226.     memset(ServerDesk, 0, si.nameLength + 2) ;
  227.     
  228.     if (netRecv(ServerDesk, si.nameLength) != TRUE) {
  229.         netFail("failed to recv desktop name") ;
  230.     return FALSE ;
  231.     }
  232.     
  233.     cx = si.framebufferWidth  ;
  234.     cy = si.framebufferHeight ;
  235.  
  236. #if 1
  237.     printf("Remote Desktop [%s] %d x %d\n", ServerDesk, cx, cy) ;
  238.     printf("Server's natural format is\n") ;
  239.     printf("    bitsPerPixel %d, depth %d, bigEndian %s, trueColour %s\n",
  240.                 si.format.bitsPerPixel, si.format.depth,
  241.         (si.format.bigEndian ? "TRUE" : "FALSE"),
  242.         (si.format.trueColour ? "TRUE" : "FALSE")) ;
  243.     printf("    red   Max %d, shift %d\n", 
  244.                 si.format.redMax,   si.format.redShift) ;
  245.     printf("    green Max %d, shift %d\n",
  246.                 si.format.greenMax, si.format.greenShift) ;
  247.     printf("    blue  Max %d, shift %d\n", 
  248.                 si.format.blueMax,  si.format.blueShift) ;
  249. #endif
  250.  
  251.     if ((*VncCtx->rectInit) (cx, cy) != TRUE) {
  252.         netFail("failed to initialize frame buffer") ;
  253.     return FALSE ;
  254.     }
  255.     
  256.     netNotify(WM_VNC_INIT, MPFROM2SHORT(cx, cy), MPFROMP(ServerDesk)) ;
  257.     
  258.     return TRUE ;
  259. }
  260.  
  261. /*
  262.  * protoConnInit - Initialize RFB Connection
  263.  */
  264.  
  265. BOOL    protoConnInit(void)
  266. {
  267.     int     nColors ;
  268.  
  269.     nColors = queryColorIndex() ;
  270.  
  271.     /*
  272.      * Select Protocol Context
  273.      */
  274.      
  275.     switch (SessPixelFormat) {
  276.     case PIXFMT_32 :
  277.         VncCtx = &VncCtx32 ;
  278.     break ;
  279.     case PIXFMT_8  :
  280.         VncCtx = (nColors >= 256) ? &VncCtx8 : &VncCtx4Tiny ;
  281.     break ;
  282.     case PIXFMT_TINY  :
  283.         VncCtx = &VncCtx4Tiny ;
  284.     break ;
  285.     case PIXFMT_GRAY  :
  286.         VncCtx = &VncCtx4Gray ;
  287.     break ;
  288.     default        :
  289.         VncCtx = &VncCtx32 ;
  290.     break ;
  291.     }
  292.  
  293.     if (chkVersion() != TRUE) {
  294.         return FALSE ;
  295.     }
  296.     if (chkAuth() != TRUE) {
  297.         return FALSE ;
  298.     }
  299.     if (chkInit() != TRUE) {
  300.         return FALSE ;
  301.     }
  302.     return TRUE ;
  303. }
  304.  
  305. /*
  306.  * protoConnInfo - query connection info.
  307.  */
  308.  
  309. PUCHAR  protoConnInfo(rfbServerInitMsg *si, int *major, int *minor)
  310. {
  311.     *si = ServerInit  ;
  312.     *major = verMajor ;
  313.     *minor = verMinor ;
  314.     return ServerDesk ;
  315. }
  316.  
  317. /*
  318.  * protoSendFmtEnc - send SetPixelFormat & SetEncodings
  319.  */
  320.  
  321. #define MAX_ENCODINGS   10
  322.  
  323. static  CARD32  DefaultEncodingsTab[] = {
  324.     rfbEncodingHextile,
  325.     rfbEncodingCoRRE,
  326.     rfbEncodingRRE,
  327.     rfbEncodingRaw                  /* at last */
  328. } ;
  329.  
  330. #define     DefaultEncodingsNum (sizeof(DefaultEncodingsTab)/sizeof(CARD32))
  331.  
  332. BOOL    protoSendFmtEnc(void)
  333. {
  334.     rfbSetPixelFormatMsg    spf ;
  335.     rfbSetEncodingsMsg      *se ;
  336.     CARD32  *encs  ;
  337.     CARD16  num    ;
  338.     int     i, len ;
  339.     UCHAR   buf[sz_rfbSetEncodingsMsg + sizeof(CARD32) * MAX_ENCODINGS] ;
  340.     
  341.     /*
  342.      * send SetPixelFormat Message
  343.      */
  344.  
  345.     spf.type = rfbSetPixelFormat ;
  346.     spf.format = VncCtx->rectFormat ;
  347.     
  348.     spf.format.redMax   = swap16(spf.format.redMax)   ;
  349.     spf.format.greenMax = swap16(spf.format.greenMax) ;
  350.     spf.format.blueMax  = swap16(spf.format.blueMax)  ;
  351.     
  352.     if (netSend((PUCHAR) &spf, sz_rfbSetPixelFormatMsg) != TRUE) {
  353.         netFail("failed to send SetPixelFormat") ;
  354.     return FALSE ;
  355.     }
  356.     
  357.     /*
  358.      * send SetEncodings Message
  359.      */
  360.      
  361.     se   = (rfbSetEncodingsMsg *) &buf[0] ;
  362.     encs = (CARD32 *) &buf[sz_rfbSetEncodingsMsg] ;
  363.     
  364.     se->type = rfbSetEncodings ;
  365.     len = sz_rfbSetEncodingsMsg ;
  366.     num = 0 ;
  367.     
  368.     TRACE("Pref Encoding %d\n", SessPreferredEncoding) ;
  369.  
  370.     *encs++ = swap32(rfbEncodingCopyRect)  ;    /* always on top    */
  371.     num += 1 ;
  372.     len += sizeof(CARD32)  ;
  373.  
  374.     *encs++ = swap32(SessPreferredEncoding) ;   /* then preferred one   */
  375.     num += 1 ;
  376.     len += sizeof(CARD32)  ;
  377.  
  378.     for (i = 0 ; i < DefaultEncodingsNum ; i++) {   /* as default   */
  379.         *encs++ = swap32(DefaultEncodingsTab[i]) ;
  380.     num += 1 ;
  381.     len += sizeof(CARD32)  ;
  382.     }
  383.     se->nEncodings = swap16(num) ;
  384.  
  385.     if (netSend(buf, len) != TRUE) {
  386.         netFail("failed to send SetEncodings") ;
  387.     return FALSE ;
  388.     }
  389.     
  390.     inputReady = TRUE ;
  391.  
  392.     return TRUE ;
  393. }
  394.  
  395. /*
  396.  * protoSendRequest - send FramebufferUpdateRequest
  397.  */
  398.  
  399. BOOL    protoSendRequest(BOOL inc, PRECTL rect)
  400. {
  401.     rfbFramebufferUpdateRequestMsg  fur ;
  402.     RECTL   full ;
  403.     
  404.     fur.type = rfbFramebufferUpdateRequest ;
  405.     fur.incremental = inc ? 1 : 0 ;
  406.     
  407.     if (rect == NULL) {
  408.     full.xLeft   = 0 ;
  409.     full.yBottom = 0 ;
  410.     full.xRight  = ServerInit.framebufferWidth  ;
  411.     full.yTop    = ServerInit.framebufferHeight ;
  412.         rect = &full ;
  413.     }
  414.     fur.x = swap16(rect->xLeft) ;
  415.     fur.w = swap16(rect->xRight - rect->xLeft) ;
  416.     fur.y = swap16(ServerInit.framebufferHeight - rect->yTop) ;
  417.     fur.h = swap16(rect->yTop - rect->yBottom) ;
  418.     
  419.     if (netSend((PUCHAR) &fur, sz_rfbFramebufferUpdateRequestMsg) != TRUE) {
  420.         netFail("failed to send FramebufferUpdateRequest") ;
  421.     return FALSE ;
  422.     }
  423.     return TRUE ;
  424. }
  425.  
  426. /*
  427.  * protoSetColourMapEntries
  428.  *      not expected for TRUE COLOR, but read and skip message
  429.  */
  430.  
  431. static  BOOL    protoSetColourMapEntries(rfbServerToClientMsg *msg)
  432. {
  433.     int     i ;
  434.     CARD16  rgb[3] ;
  435.     
  436.     TRACE("rfbSetColourMapEntries - unexpected, skip\n") ;
  437.     
  438.     if (netRecv(((PUCHAR) msg) + 1, sz_rfbSetColourMapEntriesMsg - 1) != TRUE) {
  439.         netFail("failed to recv rfbSetColourMapEntires") ;
  440.     return FALSE ;
  441.     }
  442.     
  443.     msg->scme.firstColour = swap16(msg->scme.firstColour) ;
  444.     msg->scme.nColours    = swap16(msg->scme.nColours)    ;
  445.     
  446.     for (i = 0 ; i < msg->scme.nColours ; i++) {
  447.         if (netRecv((PUCHAR) rgb, sizeof(rgb)) != TRUE) {
  448.         netFail("failed to recv rfbSetColourMapEntires, RGB") ;
  449.         return FALSE ;
  450.     }
  451.     }
  452.     return TRUE ;
  453. }
  454.  
  455. /*
  456.  * protoBell - notify to window thread to ring a bell
  457.  */
  458.  
  459. static  BOOL    protoBell(rfbServerToClientMsg *msg)
  460. {
  461.     TRACE("rfbBell\n") ;
  462.     
  463.     netNotify(WM_VNC_BELL, NULL, NULL) ;
  464.     return TRUE ;
  465. }
  466.  
  467. /*
  468.  * protoServerCutText - read cut text and notify to window
  469.  */
  470.  
  471. static  BOOL    protoServerCutText(rfbServerToClientMsg *msg)
  472. {
  473.     PUCHAR  str ;
  474.     
  475.     TRACE("rfbServerCutText\n") ;
  476.     
  477.     if (netRecv(((PUCHAR) msg) + 1, sz_rfbServerCutTextMsg - 1) != TRUE) {
  478.         netFail("failed to recv rfbServerCutTextMsg") ;
  479.     return FALSE ;
  480.     }
  481.  
  482.     msg->sct.length = swap32(msg->sct.length) ;
  483.  
  484.     if ((str = malloc(msg->sct.length + 2)) == NULL) {
  485.         netFail("failed to alloc for rfbServerCutText") ;
  486.     return FALSE ;
  487.     }
  488.     
  489.     if (netRecv(str, msg->sct.length) != TRUE) {
  490.         netFail("failed to recv rfbServerCutText, text") ;
  491.     return FALSE ;
  492.     }
  493.     str[msg->sct.length] = '\0' ;
  494.     
  495.     netNotify(WM_VNC_CLIP, NULL, MPFROMP(str)) ;    /* disposed in window */
  496.  
  497.     return TRUE ;
  498. }
  499.  
  500. /*
  501.  * protoFramebufferUpdate
  502.  */
  503.  
  504. static  int     xmin, xmax, ymin, ymax ;
  505.  
  506. #define regnInit()              \
  507.     {                           \
  508.         xmax = ymax = 0 ;       \
  509.         xmin = ymin = 0xffff ;  \
  510.     }
  511. #define regnJoin(x, y, w, h)                                \
  512.     {                                                       \
  513.     xmin = ((x) < xmin) ? (x) : xmin ;                  \
  514.     ymin = ((y) < ymin) ? (y) : ymin ;                  \
  515.         xmax = (((x) + (w)) > xmax) ? ((x) + (w)) : xmax ;  \
  516.     ymax = (((y) + (h)) > ymax) ? ((y) + (h)) : ymax ;  \
  517.     }
  518. #define regnUpdate()                                                    \
  519.     {                                                                   \
  520.         netNotify(WM_VNC_UPDATE,                                        \
  521.                MPFROM2SHORT(xmin, ServerInit.framebufferHeight - ymax),    \
  522.         MPFROM2SHORT((xmax - xmin), (ymax - ymin))) ;               \
  523.     }
  524.     
  525. static  BOOL    protoFramebufferUpdate(rfbServerToClientMsg *msg)
  526. {
  527.     rfbFramebufferUpdateRectHeader  rect ;
  528.     int     i    ;
  529.     BOOL    stat ;
  530.     int     x, y, w, h ;
  531.  
  532.     if (netRecv(((PUCHAR) msg) + 1, sz_rfbFramebufferUpdateMsg - 1) != TRUE) {
  533.         netFail("failed to recv rfbFramebufferUpdateMsg") ;
  534.     return FALSE ;
  535.     }
  536.     msg->fu.nRects = swap16(msg->fu.nRects) ;
  537.  
  538.     regnInit() ;
  539.     
  540.     for (i = 0 ; i < msg->fu.nRects ; i++) {
  541.  
  542.         if (netRecv((PUCHAR) &rect, sz_rfbFramebufferUpdateRectHeader) != TRUE) {
  543.         netFail("failed to recv rfbFramebufferUpdateRectHeader") ;
  544.         return FALSE ;
  545.     }
  546.     rect.r.x = x = swap16(rect.r.x) ;
  547.     rect.r.y = y = swap16(rect.r.y) ;
  548.     rect.r.w = w = swap16(rect.r.w) ;
  549.     rect.r.h = h = swap16(rect.r.h) ;
  550.     rect.encoding = swap32(rect.encoding) ;
  551.     
  552.         if ((rect.r.x + rect.r.w) > ServerInit.framebufferWidth) {
  553.         netFail("rect too large (width)") ;
  554.         netDump((PUCHAR) &rect, sz_rfbFramebufferUpdateRectHeader) ;
  555.         return FALSE ;
  556.     }
  557.     if ((rect.r.y + rect.r.h) > ServerInit.framebufferHeight) {
  558.         netFail("rect too large (height)") ;
  559.         netDump((PUCHAR) &rect, sz_rfbFramebufferUpdateRectHeader) ;
  560.         return FALSE ;
  561.     }
  562.     if (rect.r.w == 0 || rect.r.h == 0) {
  563.         TRACE("empty rectangle, skip\n") ;
  564.         continue ;
  565.     }
  566.     
  567.     switch (rect.encoding) {
  568.         case rfbEncodingRaw      :
  569.         stat = (*VncCtx->rectRaw) (&rect.r) ;
  570.         break ;
  571.     case rfbEncodingCopyRect :
  572.         stat = (*VncCtx->rectCopy) (&rect.r) ;
  573.         break ;
  574.     case rfbEncodingRRE      :
  575.         stat = (*VncCtx->rectRRE) (&rect.r) ;
  576.         break ;
  577.     case rfbEncodingCoRRE    :
  578.         stat = (*VncCtx->rectCoRRE) (&rect.r) ;
  579.         break ;
  580.     case rfbEncodingHextile  :
  581.         stat = (*VncCtx->rectTile) (&rect.r) ;
  582.         break ;
  583.     default :
  584.         netFail("unknown rect encoding") ;
  585.         stat = FALSE ;
  586.             break ;
  587.     }
  588.     if (stat != TRUE) {
  589.         return FALSE ;
  590.     }
  591.         regnJoin(x, y, w, h) ;
  592.     }
  593.     regnUpdate() ;
  594.  
  595.     if (winIconized() == FALSE) {
  596.         protoSendRequest(TRUE, NULL) ;
  597.     }
  598.     return TRUE ;
  599. }
  600.  
  601. /*
  602.  * protoDispatch - entry for Server -> Client Message Handling
  603.  */
  604.  
  605. BOOL    protoDispatch(void)
  606. {
  607.     rfbServerToClientMsg    msg ;
  608.     
  609.     if (netRecv((PUCHAR) &msg, 1) != TRUE) {
  610.         netFail("failed to recv Server -> Client Msg") ;
  611.     return FALSE ;
  612.     }
  613.     
  614.     switch (msg.type) {
  615.     case rfbSetColourMapEntries :
  616.         return protoSetColourMapEntries(&msg) ;
  617.     case rfbFramebufferUpdate :
  618.         return protoFramebufferUpdate(&msg) ;
  619.     case rfbBell :
  620.         return protoBell(&msg) ;
  621.     case rfbServerCutText :
  622.         return protoServerCutText(&msg) ;
  623.     }
  624.     netFail("unknown message from Server") ;
  625.     return FALSE ;
  626. }
  627.  
  628. /*
  629.  * protoSendMouEvent - send Pointer Event
  630.  */
  631.  
  632. BOOL    protoSendMouEvent(USHORT state, PPOINTL pt)
  633. {
  634.     rfbPointerEventMsg  pe ;
  635.     
  636.     if (SessOptViewonly) {
  637.         return TRUE ;
  638.     }
  639.     if (! inputReady) {
  640.         return TRUE ;
  641.     }
  642.     
  643.     pe.type = rfbPointerEvent ;
  644.     pe.buttonMask = (UCHAR) (state & 0xff) ;
  645.     pe.x = swap16((USHORT) pt->x) ;
  646.     pe.y = swap16((USHORT) pt->y) ;
  647.     
  648.     return netSend((PUCHAR) &pe, sz_rfbPointerEventMsg) ;
  649. }
  650.  
  651. /*
  652.  * protoSendKeyEvent - send Keyboard Event
  653.  */
  654.  
  655. BOOL    protoSendKeyEvent(BOOL down, ULONG key)
  656. {
  657.     rfbKeyEventMsg  ke ;
  658.     
  659.     if (SessOptViewonly) {
  660.         return TRUE ;
  661.     }
  662.     if (! inputReady) {
  663.         return TRUE ;
  664.     }
  665.     
  666.     ke.type = rfbKeyEvent  ;
  667.     ke.down = down ? 1 : 0 ;
  668.     ke.key  = swap32(key)  ;
  669.     
  670.     return netSend((PUCHAR) &ke, sz_rfbKeyEventMsg) ;
  671. }
  672.  
  673. /*
  674.  * protoSendCutText - send Client Cut Text
  675.  */
  676.  
  677. BOOL    protoSendCutText(PUCHAR text)
  678. {
  679.     rfbClientCutTextMsg *cct ;
  680.     int     len     ;
  681.     PUCHAR  buf, dp ;
  682.     BOOL    stat    ;
  683.     
  684.     if ((buf = malloc(sz_rfbClientCutTextMsg + strlen(text))) == NULL) {
  685.         return FALSE ;
  686.     }
  687.     cct = (rfbClientCutTextMsg *) buf  ;
  688.     dp  = buf + sz_rfbClientCutTextMsg ;
  689.  
  690.     for (len = 0 ; *text != '\0' ; len++, text++) {
  691.         if (*text == '\r') {
  692.         continue ;      /* skip CR */
  693.     }
  694.         dp[len] = *text ;
  695.     }
  696.     
  697.     cct->type   = rfbClientCutText ;
  698.     cct->length = swap32(len)      ;
  699.     
  700.     stat = netSend(buf, sz_rfbClientCutTextMsg + len) ;
  701.     free(buf)   ;
  702.     return stat ;
  703. }
  704.