home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / extensions / server / xtest1dd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-23  |  38.0 KB  |  1,611 lines

  1. /*
  2.  *    File: xtest1dd.c
  3.  *
  4.  *    This file contains the device dependent parts of the input
  5.  *    synthesis extension.
  6.  */
  7.  
  8. /*
  9.  
  10. Copyright 1986, 1987, 1988 by Hewlett-Packard Corporation
  11. Copyright 1986, 1987, 1988 by the Massachusetts Institute of Technology
  12.  
  13. Permission to use, copy, modify, and distribute this
  14. software and its documentation for any purpose and without
  15. fee is hereby granted, provided that the above copyright
  16. notice appear in all copies and that both that copyright
  17. notice and this permission notice appear in supporting
  18. documentation, and that the name of M.I.T. not be used in
  19. advertising or publicity pertaining to distribution of the
  20. software without specific, written prior permission.
  21.  
  22. Hewlett-Packard and M.I.T. make no representations about the 
  23. suitability of this software for any purpose.  It is provided 
  24. "as is" without express or implied warranty.
  25.  
  26. This software is not subject to any license of the American
  27. Telephone and Telegraph Company or of the Regents of the
  28. University of California.
  29.  
  30. */
  31.  
  32. /***************************************************************
  33.  * include files
  34.  ***************************************************************/
  35.  
  36. #define    NEED_EVENTS
  37. #define    NEED_REPLIES
  38.  
  39. #include <stdio.h>
  40. #include "Xos.h"
  41. #include "X.h"
  42. #include "Xmd.h"
  43. #include "Xproto.h"
  44. #include "misc.h"
  45. #include "dixstruct.h"
  46. #define  XTestSERVER_SIDE
  47. #include "xtestext1.h"    
  48.  
  49. /***************************************************************
  50.  * defines
  51.  ***************************************************************/
  52.  
  53. /*
  54.  * the size of the fake input action array
  55.  */
  56. #define ACTION_ARRAY_SIZE    100
  57.  
  58. /***************************************************************
  59.  * externals
  60.  ***************************************************************/
  61.  
  62. /*
  63.  * Holds the xTestInputAction event type code.
  64.  * This is defined in xtestext1di.c.
  65.  */
  66. extern int            XTestInputActionType;
  67. /*
  68.  * Holds the xTestFakeAck event type code.
  69.  * This is defined in xtestext1di.c.
  70.  */
  71. extern int            XTestFakeAckType;
  72. /*
  73.  * used in the WriteReplyToClient macro
  74.  */
  75. extern void            (* ReplySwapVector[256]) ();
  76.  
  77. extern int            exclusive_steal;
  78.  
  79. /***************************************************************
  80.  * variables
  81.  ***************************************************************/
  82.  
  83. /*
  84.  * array to hold fake input actions
  85.  */
  86. struct {
  87.     /*
  88.      * holds the action type, one of: XTestDELAY_ACTION,
  89.      * XTestKEY_ACTION, XTestMOTION_ACTION, XTestJUMP_ACTION
  90.      */
  91.     CARD8    type;    
  92.     /*
  93.      * holds the device type, in the range 0 to 15
  94.      */
  95.     CARD8    device;
  96.     /*
  97.      * for XTestKEY_ACTION type, holds the keycode
  98.      */
  99.     CARD8    keycode;
  100.     /*
  101.      * for XTestKEY_ACTION type, holds the key up/down state
  102.      */
  103.     CARD8    keystate;
  104.     /*
  105.      * for XTestMOTION_ACTION and XTestJUMP_ACTION types,
  106.      * holds the x and y coordinates to move the mouse to
  107.      */
  108.     int    x;
  109.     int    y;
  110.     /*
  111.      * holds the time to delay (in milliseconds) before performing
  112.      * the action
  113.      */
  114.     CARD32    delay_time;
  115. }action_array[ACTION_ARRAY_SIZE];
  116.  
  117. /*
  118.  * write index for input action array
  119.  */
  120. static int            write_index = 0;
  121. /*
  122.  * read index for input action array
  123.  */
  124. static int            read_index = 0;
  125. /*
  126.  * this is where the input actions are accumulated until they are sent
  127.  * to a client (in a wire event)
  128.  */
  129. static xTestInputActionEvent    input_action_packet;
  130. /*
  131.  * holds the index (in bytes) into the input actions buffer in the
  132.  * current input action event
  133.  */
  134. static int             packet_index;
  135. /*
  136.  * set to 1 when the input action event is full and needs to be sent to the 
  137.  * client
  138.  */
  139. static int            input_action_event_full = 0;
  140. /*
  141.  * logical x position of the mouse during input action gathering
  142.  */
  143. short                xtest_mousex;
  144. /*
  145.  * logical y position of the mouse during input action gathering
  146.  */
  147. short                xtest_mousey;
  148. /*
  149.  * logical x position of the mouse during input action playback
  150.  */
  151. static short            mx;
  152. /*
  153.  * logical y position of the mouse during input action playback
  154.  */
  155. static short            my;
  156. /*
  157.  * logical x position of the mouse while we are reading fake input actions
  158.  * from the client and putting them into the fake input action array
  159.  */
  160. static short            pmousex;
  161. /*
  162.  * logical y position of the mouse while we are reading fake input actions
  163.  * from the client and putting them into the fake input action array
  164.  */
  165. static short            pmousey;
  166. /*
  167.  * The playback_on flag is set to 1 while there are input actions in the 
  168.  * input action array.  It is set to 0 when the server has received all of
  169.  * the user actions.
  170.  */
  171. int            playback_on = 0;
  172. /*
  173.  * identity of the client using XTestGetInput to get user input actions
  174.  */
  175. ClientPtr         current_xtest_client;
  176. /*
  177.  * if 1 send multiple input actions per XTestInputAction event;
  178.  * if 0 send one input action per XTestInputAction event
  179.  */
  180. static char            packed_mode;
  181. /*
  182.  * identity of the client using the XTestFakeInput function to send some
  183.  * fake input actions to the server
  184.  */
  185. ClientPtr        playback_client = NULL;
  186. /*
  187.  * Set to 1 when the XTestFAKE_ACK_REQUEST flag is set in a XTestFakeInput
  188.  * request.  Set back to 0 when all of the input actions have been sent
  189.  * to the server.
  190.  */
  191. static int            acknowledge = 0;
  192. /*
  193.  * The server's idea of the current time is saved in these variables when
  194.  * a XTestFakeInput request is received.  It is restored when all fake input
  195.  * actions are sent to the server or when the playback client disconnects.
  196.  */
  197. static int            saved_sec;
  198. static int            saved_usec;
  199. /*
  200.  * Set to 1 when there is a valid time in saved_sec and saved_usec.
  201.  */
  202. static int            time_saved = 0;
  203. /*
  204.  * holds the extension's notion of what the current time is while it is 
  205.  * sending input actions to a client
  206.  */
  207. static struct timeval        current_time;
  208. /*
  209.  * holds the time when the extension should place the next fake input action
  210.  * into the server's normal events queue
  211.  */
  212. static struct timeval        play_time;
  213. /*
  214.  * set to 1 when play_time is first set, cleared to 0 when the
  215.  * client using the extension disconnects, or when XTestReset is called
  216.  */
  217. static char            play_clock = 0;
  218. /*
  219.  * holds the amount of time left until the next input action from the
  220.  * input action array can be sent to the server
  221.  */
  222. static struct timeval        rtime;
  223. /*
  224.  * Set to 1 after the extension is done waiting for the correct time delay
  225.  * for an input action to be sent to the server.  Remains a 1 until the time
  226.  * delay for the next input action is computed.  Then set to 0 if the
  227.  * extension has to wait for the correct time delay.
  228.  */
  229. static int            go_for_next = 1;
  230. /*
  231.  * needed to restore waitime if playback is to be aborted
  232.  */
  233. static struct timeval        *restorewait;
  234. /*
  235.  * tmon special command key
  236.  *
  237.  * To use the test monitor program (called tmon) efficiently, it is
  238.  * desirable to have the extension be able to recognize a special "trigger"
  239.  * key.  If the extension did not do this, tmon would have to have the
  240.  * extension send all keyboard user input actions exclusively to tmon,
  241.  * only to have tmon send them right back if they were not the command key.
  242.  *
  243.  * If the extension can recognize the command key, then tmon can let the
  244.  * extension handle keyboard user input actions normally until the command
  245.  * key is pressed (and released), and only then have the extension start
  246.  * sending keyboard user input actions exclusively to tmon.
  247.  *
  248.  * Any key on the keyboard can be used for this command key.  It is most
  249.  * convenient if it is a low-frequency key.  If you want to generate a
  250.  * normal occurrance of this key to a client, just hit it twice.  Tmon
  251.  * will recognize the first occurrance of the key, take control of the input
  252.  * actions, and wait for certain keys.  If it sees another occurrance of the
  253.  * command key, it will send one occurrance of the command key to the
  254.  * extension, and go back to waiting.
  255.  *
  256.  * set and also referenced in device layer
  257.  * XXX there should be a way to set this through the protocol
  258.  */
  259. KeyCode            xtest_command_key = 0;
  260.  
  261. /***************************************************************
  262.  * function declarations
  263.  ***************************************************************/
  264.  
  265. void    flush_input_actions();
  266. void    XTestStealJumpData();
  267. void    XTestGenerateEvent();
  268. void    XTestGetPointerPos();
  269. void    XTestJumpPointer();
  270.  
  271. static void    parse_key_fake();
  272. static void    parse_motion_fake();
  273. static void    parse_jump_fake();
  274. static void    parse_delay_fake();
  275. static void    send_ack();
  276. static void    start_play_clock();
  277. static void    compute_action_time();
  278. static int    find_residual_time();
  279.  
  280. /*
  281.  * This function is defined in the "events.c" file in the dix part of the
  282.  * server source.
  283.  */
  284. void    WriteEventsToClient();
  285.  
  286. static CARD16    check_time_event();
  287. static CARD32    current_ms();
  288. static int    there_is_room();
  289.  
  290. /******************************************************************************
  291.  *
  292.  *     stop_stealing_input
  293.  *
  294.  *    Stop stealing input actions.
  295.  */
  296. void
  297. stop_stealing_input()
  298. {
  299. /*
  300.  * put any code that you might need to stop stealing input actions here
  301.  */
  302.     if (packet_index != 0) 
  303.     {
  304.         /*
  305.          * if there is a partially full input action event waiting
  306.          * when this function is called, send it to the client
  307.          */
  308.         flush_input_actions();
  309.     }
  310. }
  311.  
  312. /******************************************************************************
  313.  *
  314.  *     steal_input
  315.  *
  316.  *    Start stealing input actions and sending them to the passed-in client.
  317.  */
  318. void
  319. steal_input(client, mode)
  320. /*
  321.  * which client is to receive the input action events
  322.  */
  323. ClientPtr    client;
  324. /*
  325.  * what input action packing mode to use.  one of 0, XTestPACKED_MOTION,
  326.  * or XTestPACKED_ACTIONS; optionally 'or'ed with XTestEXCLUSIVE,
  327.  */
  328. CARD32        mode;
  329. {
  330.     /*
  331.      * this is necessary for gettimeofday, but is ignored
  332.      */
  333.     struct timezone    tzp;
  334.  
  335.     if (packet_index != 0) 
  336.     {
  337.         /*
  338.          * if there is a partially full input action event waiting
  339.          * when this function is called, send it to the client
  340.          */
  341.         flush_input_actions();
  342.     }
  343.     else
  344.     {    
  345.         /*
  346.          * otherwise, set up a new input action event
  347.          */
  348.         input_action_packet.type = XTestInputActionType;
  349.         packet_index = 0;
  350.     }
  351.     /*
  352.      * set up the new input action packing mode
  353.      */
  354.     packed_mode = mode & ~(XTestEXCLUSIVE);
  355.     /*
  356.      * keep track of where the mouse is
  357.      */
  358.     XTestGetPointerPos(&xtest_mousex, &xtest_mousey);
  359.     /*
  360.      * keep track of which client is getting input actions
  361.      */
  362.     current_xtest_client = client;
  363.     /*
  364.      * find out what time it is
  365.      */
  366.     gettimeofday(¤t_time, &tzp);
  367.     /*
  368.      * jump to the initial position of the mouse, using a device type of 0.
  369.      */
  370.     XTestStealJumpData(xtest_mousex, xtest_mousey, 0);
  371. }
  372.     
  373. /******************************************************************************
  374.  *
  375.  *    flush_input_actions
  376.  *
  377.  *    Write the input actions event to the current requesting client
  378.  *    and re-initialize the input action event.
  379.  */
  380. void
  381. flush_input_actions()
  382. {
  383.     /*
  384.      * pointer to the input action event
  385.      */
  386.     char            *rep;
  387.     /*
  388.      * loop index
  389.      */
  390.     int            i;
  391.  
  392.     if (packet_index == 0)
  393.     {
  394.         /*
  395.          * empty input actions event 
  396.          */
  397.         return;
  398.     }
  399.     else if (packet_index < XTestACTIONS_SIZE)
  400.     {
  401.         /*
  402.          * fill to the end of the input actions event with 0's
  403.          */
  404.         for (i = packet_index; i <XTestACTIONS_SIZE; i++)
  405.         {
  406.             input_action_packet.actions[i] = 0;
  407.         }
  408.     }
  409.     rep = (char *) (&input_action_packet);
  410.  
  411.     /*
  412.      * set the serial number of the input action event
  413.      */
  414.     input_action_packet.sequenceNumber = current_xtest_client->sequence;
  415.     /*
  416.      * send the input action event to the client
  417.      */
  418.     WriteEventsToClient(current_xtest_client, 1, (xEvent *) rep);
  419.     /*
  420.      * re-initialize the input action event
  421.      */
  422.     input_action_event_full = 0;
  423.     input_action_packet.type = XTestInputActionType;
  424.      packet_index = 0;
  425. }    
  426.  
  427. /******************************************************************************
  428.  *
  429.  *    XTestStealJumpData
  430.  *
  431.  *    Create one or more input actions and put them in the input action
  432.  *    event.  The input actions will be an (maybe) XTestDELAY_ACTION
  433.  *    and an XTestJUMP_ACTION.
  434.  */
  435. void
  436. XTestStealJumpData(jx, jy, dev_type)
  437. /*
  438.  * the x and y coordinates to jump to
  439.  */
  440. short    jx;
  441. short    jy;
  442. /*
  443.  * which device caused the jump
  444.  */
  445. int    dev_type;
  446. {    
  447.     XTestJumpInfo     *jmp_ptr;
  448.     /*
  449.      * time delta (in ms) from previous event
  450.      */
  451.     CARD16            tchar;
  452.  
  453.     /*
  454.      * Get the time delta from the previous event.  If needed,
  455.      * the check_time_event routine will put an XTestDELAY_ACTION
  456.      * type action in the input action event.
  457.      */
  458.     tchar = check_time_event();
  459.     if (!there_is_room(sizeof(XTestJumpInfo)))
  460.     {
  461.         /*
  462.          * If there isn't room in the input action event for
  463.          * an XTestJUMP_ACTION, then send that event to the
  464.          * client and start filling an empty one.
  465.          */
  466.         flush_input_actions();
  467.     }
  468.     /*
  469.      * update the logical mouse position
  470.      */
  471.     xtest_mousex = jx;
  472.     xtest_mousey = jy;
  473.     /*
  474.      * point jmp_ptr to the correct place in the input action event
  475.      */
  476.     jmp_ptr = (XTestJumpInfo *)
  477.           &(input_action_packet.actions[packet_index]);
  478.     /*
  479.      * compute the input action header
  480.      */
  481.     jmp_ptr->header = (XTestPackDeviceID(dev_type) | XTestJUMP_ACTION);    
  482.     /*
  483.      * set the x and y coordinates to jump to in the input action
  484.      */
  485.     jmp_ptr->jumpx = jx;
  486.     jmp_ptr->jumpy = jy;
  487.     /*
  488.      * set the delay time in the input action
  489.      */
  490.     jmp_ptr->delay_time = tchar;
  491.     /*
  492.      * increment the packet index by the size of the input action
  493.      */
  494.     packet_index = packet_index + sizeof(XTestJumpInfo);
  495.     if (packed_mode == 0)
  496.     {
  497.         /*
  498.          * if input actions are not packed, send the input
  499.          * action event to the client
  500.          */
  501.         flush_input_actions();
  502.     }
  503. }    
  504.  
  505. /******************************************************************************
  506.  *
  507.  *    current_ms
  508.  *
  509.  *    Returns the number of milliseconds from the passed-in time to the
  510.  *    current time, and then updates the passed-in time to the current time.
  511.  */
  512. static CARD32
  513. current_ms(otime)
  514. struct timeval    *otime;
  515. {    
  516.     struct timeval    tval;
  517.     struct timezone tzp;
  518.     unsigned long    ctime;
  519.     unsigned long    sec;
  520.     unsigned long    usec;
  521.  
  522.     /*
  523.      * get the current time
  524.      */
  525.     gettimeofday(&tval, &tzp);
  526.     if (tval.tv_usec < otime->tv_usec)
  527.     {
  528.         /*
  529.          * borrow a second's worth of microseconds if needed
  530.          */
  531.         usec = tval.tv_usec - otime->tv_usec + 1000000;
  532.         sec = tval.tv_sec - 1 - otime->tv_sec;
  533.     }
  534.     else
  535.     {
  536.         usec = tval.tv_usec - otime->tv_usec;
  537.         sec = tval.tv_sec - otime->tv_sec;
  538.     }
  539.     /*
  540.      * update the passed-in time to the new time
  541.      */
  542.     *otime = tval;
  543.     /*
  544.      * compute the number of milliseconds contained in
  545.      * 'sec' seconds and 'usec' microseconds
  546.      */
  547.     ctime = (sec * 1000000 + usec) / 1000;
  548.     return (ctime);
  549. }
  550.  
  551. /******************************************************************************
  552.  *
  553.  *    check_time_event
  554.  *
  555.  *    If time delta is > XTestSHORT_DELAY_TIME then insert a time event
  556.  *    and return 0; else return the delay time.
  557.  */
  558. static CARD16
  559. check_time_event()
  560. {
  561.     CARD32        tstamp;
  562.     CARD16        tchar;
  563.     XTestDelayInfo    *tptr;
  564.  
  565.     /*
  566.      * get the number of milliseconds between input actions
  567.      */
  568.     tstamp = current_ms(¤t_time);
  569.     /*
  570.      * if the number of milliseconds is too large to fit in a CARD16,
  571.      * then add a XTestDELAY_ACTION to the input action event.
  572.      */
  573.     if (tstamp > XTestSHORT_DELAY_TIME)
  574.     {
  575.         /*
  576.          * If there isn't room in the input action event for
  577.          * an XTestDELAY_ACTION, then send that event to the
  578.          * client and start filling an empty one.
  579.          */
  580.         if (!there_is_room(sizeof(XTestDelayInfo)))
  581.         {
  582.             flush_input_actions();
  583.         }
  584.         /*
  585.          * point tptr to the correct place in the input action event
  586.          */
  587.         tptr = (XTestDelayInfo *)
  588.                (&(input_action_packet.actions[packet_index]));
  589.         /*
  590.          * compute the input action header
  591.          */
  592.         tptr->header = XTestPackDeviceID(XTestDELAY_DEVICE_ID) |
  593.                    XTestDELAY_ACTION;
  594.         /*
  595.          * set the delay time in the input action
  596.          */
  597.         tptr->delay_time = tstamp;
  598.         /*
  599.          * increment the packet index by the size of the input action
  600.          */
  601.         packet_index = packet_index + (sizeof(XTestDelayInfo));
  602.         if (packed_mode != XTestPACKED_ACTIONS) 
  603.         {
  604.             /*
  605.              * if input actions are not packed, send the input
  606.              * action event to the client
  607.              */
  608.             flush_input_actions();
  609.         }
  610.         /*
  611.          * set the returned delay time to 0
  612.          */
  613.         tchar = 0;
  614.     }
  615.     else
  616.     {
  617.         /*
  618.          * set the returned delay time to the computed delay time
  619.          */
  620.         tchar = tstamp;
  621.     }
  622.     return(tchar);
  623. }
  624.  
  625. /******************************************************************************
  626.  *
  627.  *    there_is_room
  628.  *
  629.  *    Checks if there is room in the input_action_packet for an input action
  630.  *    of the size actsize bytes.  Returns 1 if there is space, 0 otherwise.
  631.  *
  632.  */
  633. static int
  634. there_is_room(actsize)
  635. /*
  636.  * the number of bytes of space needed
  637.  */
  638. int    actsize;
  639. {
  640.     if ((packet_index + actsize) > XTestACTIONS_SIZE)
  641.     { 
  642.         input_action_event_full = 1;
  643.         return(0);
  644.     }
  645.     else
  646.     {
  647.         return(1);
  648.     }
  649. }
  650.  
  651. /******************************************************************************
  652.  *
  653.  *    XTestStealMotionData
  654.  *
  655.  *    Put motion information from the locator into an input action.
  656.  *
  657.  *    called from x_hil.c
  658.  */
  659. void
  660. XTestStealMotionData(dx, dy, dev_type, mx, my)
  661. /*
  662.  * the x and y delta motion of the locator
  663.  */
  664. short    dx;
  665. short    dy;
  666. /*
  667.  * which locator did the moving
  668.  */
  669. int    dev_type;
  670. /*
  671.  * the x and y position of the locator before the delta motion
  672.  */
  673. short    mx;
  674. short    my;
  675. {
  676.     /*
  677.      * pointer to a XTestMOTION_ACTION input action
  678.      */
  679.     XTestMotionInfo    *fm;
  680.     /*
  681.      * time delta from previous event
  682.      */
  683.     CARD16            tchar;
  684.  
  685.     /*
  686.      * if the current position of the locator is not the same as
  687.      * the logical position, then update the logical position
  688.      */
  689.     if ((mx != xtest_mousex) || (my != xtest_mousey))
  690.     {
  691.         XTestStealJumpData(mx, my, dev_type);
  692.     }
  693.     /*
  694.      * if the delta motion is outside the range that can
  695.      * be held in a motion input action, use a jump input action
  696.      */
  697.     if ((dx > XTestMOTION_MAX) || (dx < XTestMOTION_MIN) ||
  698.         (dy > XTestMOTION_MAX) || (dy < XTestMOTION_MIN))
  699.     {
  700.         XTestStealJumpData((xtest_mousex + dx),
  701.                    (xtest_mousey + dy), dev_type);
  702.     }
  703.     else
  704.     { 
  705.         /*
  706.          * compute the new logical position of the mouse
  707.          */
  708.         xtest_mousex += dx;
  709.         xtest_mousey += dy;
  710.         /*
  711.          * Get the time delta from the previous event.  If needed,
  712.          * the check_time_event routine will put an XTestDELAY_ACTION
  713.          * type action in the input action event.
  714.          */
  715.         tchar = check_time_event();
  716.         /*
  717.          * If there isn't room in the input action event for
  718.          * an XTestDELAY_ACTION, then send that event to the
  719.          * client and start filling an empty one.
  720.          */
  721.         if (!there_is_room(sizeof(XTestMotionInfo)))
  722.         {
  723.             flush_input_actions();
  724.         /*
  725.          * point fm to the correct place in the input action event
  726.          */
  727.         }
  728.         fm = (XTestMotionInfo *)
  729.              &(input_action_packet.actions[packet_index]);
  730.         /*
  731.          * compute the input action header
  732.          */
  733.         fm->header = XTestMOTION_ACTION;
  734.         if (dx < 0)    
  735.         {  
  736.             fm->header |= XTestX_NEGATIVE;
  737.             dx = abs(dx);
  738.         }
  739.         if (dy < 0)   
  740.         {  
  741.             fm->header |= XTestY_NEGATIVE;
  742.             dy = abs(dy);
  743.         }
  744.         fm->header |= XTestPackDeviceID(dev_type);
  745.         /*
  746.          * compute the motion data byte
  747.          */
  748.         fm->motion_data = XTestPackYMotionValue(dy);
  749.         fm->motion_data |= XTestPackXMotionValue(dx);
  750.         /*
  751.          * set the delay time in the input action
  752.          */
  753.         fm->delay_time = tchar;
  754.         /*
  755.          * increment the packet index by the size of the input action
  756.          */
  757.         packet_index = packet_index + sizeof(XTestMotionInfo);
  758.         if (packed_mode == 0)
  759.         {
  760.             /*
  761.              * if input actions are not packed, send the input
  762.              * action event to the client
  763.              */
  764.             flush_input_actions();
  765.         }
  766.  
  767.     }   
  768. }
  769.  
  770. /******************************************************************************
  771.  *
  772.  *    XTestStealKeyData
  773.  *
  774.  *     Place this key data in the input_action_packet.
  775.  *
  776.  */
  777. Bool
  778. XTestStealKeyData(keycode, keystate, dev_type, locx, locy)
  779. /*
  780.  * which key/button moved
  781.  */
  782. u_char    keycode;
  783. /*
  784.  * whether the key/button was pressed or released
  785.  */
  786. char    keystate;
  787. /*
  788.  * which device caused the input action
  789.  */
  790. int    dev_type;
  791. /*
  792.  * the x and y coordinates of the locator when the action happenned
  793.  */
  794. short    locx;
  795. short    locy;
  796. {
  797.     /*
  798.      * pointer to key/button motion input action
  799.      */
  800.     XTestKeyInfo    *kp;
  801.     /*
  802.      * time delta from previous event
  803.      */
  804.     CARD16            tchar;
  805.     char        keytrans;
  806.  
  807.     /*
  808.      * update the logical position of the locator if the physical position
  809.      * of the locator is not the same as the logical position.
  810.      */
  811.     if ((locx != xtest_mousex) || (locy != xtest_mousey))
  812.     {
  813.         XTestStealJumpData(locx, locy, dev_type);
  814.     }
  815.     /*
  816.      * Get the time delta from the previous event.  If needed,
  817.      * the check_time_event routine will put an XTestDELAY_ACTION
  818.      * type action in the input action event.
  819.      */
  820.     tchar = check_time_event();
  821.     if (!there_is_room(sizeof(XTestKeyInfo)))
  822.     {
  823.         /*
  824.          * If there isn't room in the input action event for
  825.          * an XTestDELAY_ACTION, then send that event to the
  826.          * client and start filling an empty one.
  827.          */
  828.         flush_input_actions();
  829.     }
  830.     /*
  831.      * point kp to the correct place in the input action event
  832.      */
  833.     kp = (XTestKeyInfo *)
  834.          (&(input_action_packet.actions[packet_index]));
  835.     /*
  836.      * compute the input action header
  837.      */
  838.     kp->header = XTestPackDeviceID(dev_type);
  839.     if ((keystate == KeyRelease) || (keystate == ButtonRelease))
  840.     {
  841.         keytrans = XTestKEY_UP;
  842.     }
  843.     else if ((keystate == KeyPress) || (keystate == ButtonPress))
  844.     {
  845.         keytrans = XTestKEY_DOWN;
  846.     }
  847.     else
  848.     {
  849.         printf("%s: invalid key/button state %d.\n",
  850.                XTestEXTENSION_NAME,
  851.                keystate);
  852.     }
  853.     kp->header = kp->header | keytrans | XTestKEY_ACTION;
  854.     /*
  855.      * set the keycode in the input action
  856.      */
  857.     kp->keycode = keycode;
  858.     /*
  859.      * set the delay time in the input action
  860.      */
  861.     kp->delay_time = tchar;
  862.     /*
  863.      * increment the packet index by the size of the input action
  864.      */
  865.     packet_index = packet_index + sizeof(XTestKeyInfo);
  866.     /*
  867.      * if the command key has been released or input actions are not
  868.      * packed, send the input action event to the client
  869.      */
  870.      if(((keycode == xtest_command_key) && (keystate == KeyRelease)) ||
  871.        (packed_mode != XTestPACKED_ACTIONS))
  872.     {    
  873.         flush_input_actions();
  874.     }
  875.     /* return TRUE if the event should be passed on to DIX */
  876.     if (exclusive_steal)
  877.         return ((keystate == KeyRelease) &&
  878.             (keycode == xtest_command_key));
  879.     else
  880.         return ((keystate != KeyRelease) ||
  881.             (keycode != xtest_command_key));
  882. }
  883.  
  884. /******************************************************************************
  885.  *
  886.  *    parse_fake_input
  887.  *
  888.  *    Parsing routine for a XTestFakeInput request.  It will take a request
  889.  *    and parse its contents into the input action array.  Eventually the
  890.  *    XTestProcessInputAction routine will be called to take input actions
  891.  *    from the input action array and send them to the server to be handled.
  892.  */
  893. void
  894. parse_fake_input(client, req)
  895. /*
  896.  * which client did the XTestFakeInput request
  897.  */
  898. ClientPtr    client;
  899. /*
  900.  * a pointer to the xTestFakeInputReq structure sent by the client
  901.  */
  902. char        *req;
  903. {    
  904.     /*
  905.      * if set to 1, done processing input actions from the request
  906.      */
  907.     int                done = 0;
  908.     /*
  909.      * type of input action
  910.      */
  911.     CARD8            action_type;
  912.     /*
  913.      * device type
  914.      */
  915.     CARD8            dev_type;
  916.     /*
  917.      * pointer to an xTestFakeInputReq structure
  918.      */
  919.     xTestFakeInputReq    *request;
  920.     /*
  921.      * holds the index into the action list in the request
  922.      */
  923.     int            parse_index;    
  924.  
  925.     /*
  926.      * get a correct-type pointer to the client-supplied request data
  927.      */
  928.     request = (xTestFakeInputReq *) req;
  929.     /*
  930.      * save the acknowledge requested state for use in
  931.      * XTestProcessInputAction
  932.      */
  933.     acknowledge = request->ack;
  934.     /*
  935.      * set up an index into the action list in the request
  936.      */
  937.     parse_index = 0;
  938.     if (write_index >= ACTION_ARRAY_SIZE)
  939.     {
  940.         /*
  941.          * if the input action array is full, don't add any more
  942.          */
  943.         done = 1;
  944.     }
  945.     while (!done)
  946.     { 
  947.         /*
  948.          * get the type of input action in the list
  949.          */
  950.         action_type = (request->action_list[parse_index])
  951.                   & XTestACTION_TYPE_MASK;
  952.         /*
  953.          * get the type of device in the list
  954.          */
  955.         dev_type = XTestUnpackDeviceID(request->action_list[parse_index]);
  956.         /*
  957.          * process the input action appropriately
  958.          */
  959.         switch (action_type)
  960.         { 
  961.         case XTestKEY_ACTION:
  962.             parse_key_fake((XTestKeyInfo *)
  963.                        &(request->action_list[parse_index]));
  964.             parse_index = parse_index + sizeof(XTestKeyInfo);
  965.             break;
  966.         case XTestMOTION_ACTION:
  967.             parse_motion_fake((XTestMotionInfo *)
  968.                       &(request->action_list[parse_index]));
  969.             parse_index = parse_index + sizeof(XTestMotionInfo);
  970.             break;
  971.         case XTestJUMP_ACTION:
  972.             parse_jump_fake((XTestJumpInfo *)
  973.                     &(request->action_list[parse_index]));
  974.             parse_index = parse_index + sizeof(XTestJumpInfo);
  975.             break;
  976.         case XTestDELAY_ACTION:
  977.             if (dev_type == XTestDELAY_DEVICE_ID)
  978.             { 
  979.                 parse_delay_fake((XTestDelayInfo *)
  980.                          &(request->action_list[parse_index]));
  981.                 parse_index = parse_index +
  982.                           sizeof(XTestDelayInfo);
  983.             }
  984.             else
  985.             { 
  986.                 /*
  987.                  * An invalid input action header byte has
  988.                  * been detected, so there are no more
  989.                  * input actions in this request.
  990.                  * The intended invalid action header byte
  991.                  * for this case should have a value of 0.
  992.                  */
  993.                 done = 1;
  994.             }
  995.             break;
  996.         }
  997.         if (parse_index >= XTestMAX_ACTION_LIST_SIZE)
  998.         {
  999.             /*
  1000.              * entire XTestFakeInput request has been processed
  1001.              */
  1002.             done = 1;
  1003.         }
  1004.         if (write_index >= ACTION_ARRAY_SIZE) 
  1005.         {
  1006.             /*
  1007.              * no room in the input actions array
  1008.              */
  1009.             done = 1;
  1010.         }
  1011.     }
  1012.     if (write_index > read_index)
  1013.     { 
  1014.         /*
  1015.          * there are fake input actions in the input action array
  1016.          * to be given to the server
  1017.          */
  1018.         playback_on = 1;
  1019.         playback_client = client;
  1020.     } 
  1021. }
  1022.  
  1023. /******************************************************************************
  1024.  *
  1025.  *    parse_key_fake
  1026.  *
  1027.  *    Called from parse_fake_input.
  1028.  *
  1029.  *    Copy the fake key input action from its packed form into the array of
  1030.  *    pending input events.
  1031.  */
  1032. static void
  1033. parse_key_fake(fkey)
  1034. XTestKeyInfo    *fkey;
  1035. {    
  1036.     action_array[write_index].type = XTestKEY_ACTION;
  1037.     action_array[write_index].device = XTestUnpackDeviceID(fkey->header);
  1038.     action_array[write_index].keycode = fkey->keycode;
  1039.     action_array[write_index].keystate = fkey->header & XTestKEY_STATE_MASK;
  1040.     action_array[write_index].delay_time = fkey->delay_time;
  1041.     write_index++;
  1042. }
  1043.  
  1044. /******************************************************************************
  1045.  *
  1046.  *    parse_motion_fake
  1047.  *
  1048.  *    Called from parse_fake_input.
  1049.  *
  1050.  *    Copy the fake motion input action from its packed form into the array of
  1051.  *    pending input events.
  1052.  */
  1053. static void
  1054. parse_motion_fake(fmotion)
  1055. XTestMotionInfo    *fmotion;
  1056. {    
  1057.     int    dx;
  1058.     int    dy;
  1059.  
  1060.     dx = (XTestUnpackXMotionValue(fmotion->motion_data));
  1061.     dy = (XTestUnpackYMotionValue(fmotion->motion_data));
  1062.     if (((fmotion->header) & XTestX_SIGN_BIT_MASK) == XTestX_NEGATIVE)
  1063.     {
  1064.         pmousex -= dx;
  1065.     }
  1066.     else
  1067.     {
  1068.         pmousex += dx;
  1069.     }
  1070.     if (((fmotion->header) & XTestY_SIGN_BIT_MASK) == XTestY_NEGATIVE)
  1071.     {
  1072.         pmousey -= dy;
  1073.     }
  1074.     else 
  1075.     {
  1076.         pmousey += dy;
  1077.     }
  1078.     action_array[write_index].type = XTestJUMP_ACTION;
  1079.     action_array[write_index].device = XTestUnpackDeviceID(fmotion->header);
  1080.     action_array[write_index].x = pmousex;
  1081.     action_array[write_index].y = pmousey;
  1082.     action_array[write_index].delay_time = fmotion->delay_time;
  1083.     write_index++;
  1084. }
  1085.  
  1086. /******************************************************************************
  1087.  *
  1088.  *    parse_jump_fake
  1089.  *
  1090.  *    Called from parse_fake_input.
  1091.  *
  1092.  *    Copy the fake jump input action from its packed form into the array of
  1093.  *    pending input events.
  1094.  */
  1095. static void
  1096. parse_jump_fake(fjump)
  1097. XTestJumpInfo    *fjump;
  1098. {
  1099.     pmousex = fjump->jumpx;
  1100.     pmousey = fjump->jumpy;
  1101.     action_array[write_index].type = XTestJUMP_ACTION;
  1102.     action_array[write_index].device = XTestUnpackDeviceID(fjump->header);
  1103.     action_array[write_index].x = pmousex;
  1104.     action_array[write_index].y = pmousey;
  1105.     action_array[write_index].delay_time = fjump->delay_time;
  1106.     write_index++;
  1107. }
  1108.  
  1109. /******************************************************************************
  1110.  *
  1111.  *    parse_delay_fake
  1112.  *
  1113.  *    Called from parse_fake_input.
  1114.  *
  1115.  *    Copy the fake delay input action from its packed form into the array of
  1116.  *    pending input events.
  1117.  */
  1118. static void
  1119. parse_delay_fake(tevent)
  1120. XTestDelayInfo    *tevent;
  1121. {
  1122.     action_array[write_index].type = XTestDELAY_ACTION;
  1123.     action_array[write_index].delay_time = tevent->delay_time;
  1124.     write_index++;
  1125. }
  1126.  
  1127. /******************************************************************************
  1128.  *
  1129.  *    XTestComputeWaitTime
  1130.  *
  1131.  *    Compute the amount of time the server should wait before sending the
  1132.  *    next monitor event in playback mode.
  1133.  */
  1134. void
  1135. XTestComputeWaitTime(waittime)
  1136. struct timeval    *waittime;
  1137. {    
  1138.     /*
  1139.      * The playback_on flag is set to 1 in parse_fake_input.  It is set to
  1140.      * 0 in XTestProcessInputAction if the server has replayed all input
  1141.      * actions.
  1142.      */
  1143.     if (playback_on)
  1144.     {  
  1145.         if (!play_clock)
  1146.         {
  1147.             /*
  1148.              * if the playback clock has never been set,
  1149.              * then do it now
  1150.              */
  1151.             start_play_clock();
  1152.         }
  1153.         /*
  1154.          * We need to save the waittime the first time through.  This
  1155.          * is a value the server uses, and we have to restore it when
  1156.          * all of the input actions are processed by the server.
  1157.          */
  1158.         if (!time_saved)
  1159.         {
  1160.             saved_sec = waittime->tv_sec;
  1161.             saved_usec = waittime->tv_usec; 
  1162.             time_saved = 1;
  1163.         }    
  1164.         if (go_for_next) 
  1165.         {
  1166.             /*
  1167.              * if we just processed an input action, figure out
  1168.              * how long to wait for the next input action
  1169.              */
  1170.             compute_action_time(&rtime);
  1171.         }
  1172.         else  
  1173.         {
  1174.             /*
  1175.              * else just find out how much more time to wait
  1176.              * on the current input action
  1177.              */
  1178.             (void)find_residual_time(&rtime);
  1179.         }
  1180.         waittime->tv_sec = rtime.tv_sec;
  1181.         waittime->tv_usec = rtime.tv_usec;
  1182.     }
  1183. }
  1184.  
  1185. /******************************************************************************
  1186.  *
  1187.  *    XTestProcessInputAction
  1188.  *
  1189.  *    If there are any input actions in the input action array,
  1190.  *    then take one out and process it.
  1191.  *
  1192.  */
  1193. int
  1194. XTestProcessInputAction(readable, waittime)
  1195. /*
  1196.  * This is the value that a 'select' function returned just before this
  1197.  * routine was called.  If the select timed out, this value will be 0.
  1198.  *
  1199.  * This extension modifies the select call's timeout value to cause the
  1200.  * select to time out when the next input action is ready to given to
  1201.  * the server.  This routine is called immediately after the select, to 
  1202.  * give it a chance to process an input action.  If we have an input action
  1203.  * to process and the only reason that the select returned was because it
  1204.  * timed out, then we change the select value to 1 and return 1 instead of 0.
  1205.  */
  1206. int        readable;
  1207. /*
  1208.  * this is the timeout value that the select was called with
  1209.  */
  1210. struct timeval    *waittime;
  1211. {    
  1212.     /*
  1213.      * if playback_on is 0, then the input action array is empty
  1214.      */
  1215.     if (playback_on)
  1216.     { 
  1217.         restorewait = waittime;
  1218.         /*
  1219.          * figure out if we need to wait for the next input action
  1220.          */
  1221.         if (find_residual_time(&rtime) > 0) 
  1222.         {
  1223.             /*
  1224.              * still have to wait before processing the current
  1225.              * input action
  1226.              */
  1227.             go_for_next = 0;
  1228.         }
  1229.         else 
  1230.         {
  1231.             /*
  1232.              * don't have to wait any longer before processing
  1233.              * the current input action
  1234.              */
  1235.             go_for_next = 1;
  1236.         }
  1237.         /*
  1238.          * if we have an input action to process and the only reason
  1239.          * that the select returned was because it timed out, then we
  1240.          * change the select value to 1 and return 1 instead of 0
  1241.          */
  1242.         if (readable == 0) 
  1243.         {
  1244.             readable++;            
  1245.         }
  1246.         /*
  1247.          * if we don't need to wait, then get an input action from
  1248.          * the input action array and process it
  1249.          */
  1250.         if (go_for_next)
  1251.         {  
  1252.             /*
  1253.              * There are three possible types of input actions in
  1254.              * the input action array (motion input actions are
  1255.              * converted to jump input actions before being put
  1256.              * into the input action array).  Delay input actions 
  1257.              * are processed by the compute_action_time function
  1258.              * which is called from XTestComputeWaitTime.  The
  1259.              * other two types of input actions are processed here.
  1260.              */
  1261.             if (action_array[read_index].type == XTestJUMP_ACTION)
  1262.             {    
  1263.                 XTestJumpPointer(
  1264.                     action_array[read_index].x, 
  1265.                     action_array[read_index].y, 
  1266.                     action_array[read_index].device);
  1267.                 mx = action_array[read_index].x;
  1268.                 my = action_array[read_index].y;
  1269.             }
  1270.             if (action_array[read_index].type == XTestKEY_ACTION)
  1271.                 XTestGenerateEvent(
  1272.                      action_array[read_index].device, 
  1273.                      action_array[read_index].keycode, 
  1274.                      action_array[read_index].keystate,
  1275.                      mx,
  1276.                      my);
  1277.             read_index++;
  1278.             /*
  1279.              * if all input actions are processed, then restore 
  1280.              * the server state 
  1281.              */
  1282.             if (read_index >= write_index)
  1283.             { 
  1284.                 waittime->tv_sec = saved_sec;
  1285.                 waittime->tv_usec = saved_usec;
  1286.                 time_saved = 0;
  1287.                 playback_on = 0;
  1288.                 if (acknowledge) 
  1289.                 { 
  1290.                     /*
  1291.                      * if the playback client is waiting
  1292.                      * for an xTestFakeAck event, send
  1293.                      * it to him
  1294.                      */
  1295.                     send_ack(playback_client);        
  1296.                     acknowledge = 0;
  1297.                 }
  1298.                 write_index = 0;
  1299.                 read_index = 0;
  1300.                 playback_client = (ClientPtr) NULL;
  1301.                 play_clock = 0;
  1302.             }
  1303.         }
  1304.     }
  1305.     return(readable);
  1306. }
  1307.  
  1308. /******************************************************************************
  1309.  *
  1310.  *    send_ack
  1311.  *
  1312.  *    send an xTestFakeAck event to the client
  1313.  */
  1314. static void
  1315. send_ack(client)
  1316. ClientPtr    client;
  1317. {
  1318.     xTestFakeAckEvent  rep;
  1319.  
  1320.     /*
  1321.      * set the serial number of the xTestFakeAck event
  1322.      */
  1323.     rep.sequenceNumber = client->sequence;
  1324.     rep.type = XTestFakeAckType;
  1325.     WriteEventsToClient(client, 1, (xEvent *) &rep);        
  1326. }        
  1327.  
  1328. /******************************************************************************
  1329.  *
  1330.  *    start_play_clock
  1331.  *
  1332.  *    start the clock for play back.
  1333.  */
  1334. static void
  1335. start_play_clock()
  1336. {
  1337.     /*
  1338.      * tzp is used with the gettimeofday function, but is ignored
  1339.      */
  1340.     struct timezone tzp;
  1341.  
  1342.     gettimeofday(&play_time, &tzp);
  1343.     /*
  1344.      * flag that play_time is valid
  1345.      */
  1346.     play_clock = 1;
  1347. }
  1348.  
  1349. /******************************************************************************
  1350.  *
  1351.  *    compute_action_time
  1352.  *
  1353.  *    Set the play clock to the time when the next input action should be put
  1354.  *    into the server's input queue.  Fill the rtime structure with values
  1355.  *    for the delta until the time for the next input action.
  1356.  */
  1357. static void
  1358. compute_action_time(rtime)
  1359. struct timeval    *rtime;
  1360. {
  1361.     /*
  1362.      * holds the delay time in milliseconds
  1363.      */
  1364.     unsigned long    dtime;
  1365.     /*
  1366.      * holds the number of microseconds in the sum of the dtime value
  1367.      * and the play_time value
  1368.      */
  1369.     unsigned long    tot_usec;
  1370.     /*
  1371.      * holds the number of seconds and microseconds in the
  1372.      * dtime value
  1373.      */
  1374.     unsigned long     sec;
  1375.     unsigned long     usec;
  1376.     /*
  1377.      * holds the current time
  1378.      */
  1379.     struct timeval    btime;
  1380.     /*
  1381.      * used with the gettimeofday function but ignored
  1382.      */
  1383.     struct timezone tzp;
  1384.  
  1385.     /*
  1386.      * Put the time from the current input action in dtime
  1387.      */
  1388.     dtime = action_array[read_index].delay_time;
  1389.     /*
  1390.      * If the current input action is a delay input action,
  1391.      * add in the time from the following input action.
  1392.      */
  1393.     if ((action_array[read_index].type == XTestDELAY_ACTION) &&
  1394.         ((read_index + 1) < write_index))
  1395.     {  
  1396.         read_index++;
  1397.         dtime = dtime + action_array[read_index].delay_time;
  1398.     }
  1399.     /*
  1400.      * compute the number of seconds and microseconds in the
  1401.      * dtime value
  1402.      */
  1403.       sec = dtime / 1000;
  1404.       usec = (dtime % 1000) * 1000;
  1405.     /*
  1406.      * get the current time in btime
  1407.      */
  1408.     gettimeofday(&btime, &tzp);
  1409.     /*
  1410.      * compute the number of microseconds in the sum of the dtime value
  1411.      * and the current usec value
  1412.      */
  1413.     tot_usec = btime.tv_usec + usec;
  1414.     /*
  1415.      * if it is greater than one second's worth, adjust the seconds
  1416.      */
  1417.     if (tot_usec >= 1000000)
  1418.     { 
  1419.         tot_usec -= 1000000;
  1420.         sec++;
  1421.     }
  1422.     play_time.tv_usec = tot_usec;
  1423.     play_time.tv_sec = btime.tv_sec + sec;
  1424.     /*
  1425.      * put the time until the next input action in rtime
  1426.      */
  1427.     rtime->tv_sec = sec;
  1428.     rtime->tv_usec = usec;
  1429. }
  1430.  
  1431. /******************************************************************************
  1432.  *
  1433.  *    find_residual_time
  1434.  *
  1435.  *    Find the time interval from the current time to the value in play_time.
  1436.  *    This is the time to wait till putting the next input action into the
  1437.  *    server's input queue.  If the time is already up, reset play_time to
  1438.  *    the current time.
  1439.  */
  1440. static int
  1441. find_residual_time(rtime)
  1442. struct timeval    *rtime;
  1443. {
  1444.     /*
  1445.      * if > 0, there is time to wait.  If < 0, then don't wait
  1446.      */
  1447.     int        wait = 1;
  1448.     /*
  1449.      * holds the current time
  1450.      */
  1451.     struct timeval    btime;
  1452.     /*
  1453.      * used with the gettimeofday function but ignored
  1454.      */
  1455.     struct timezone tzp;
  1456.     /*
  1457.      * holds the current time in seconds and microseconds
  1458.      */
  1459.     unsigned long    bsec;
  1460.     unsigned long    busec;
  1461.     /*
  1462.      * holds the playback time in seconds and microseconds
  1463.      */
  1464.     unsigned long    psec;
  1465.     unsigned long    pusec;
  1466.  
  1467.     /*
  1468.      * get the current time in btime
  1469.      */
  1470.     gettimeofday(&btime, &tzp);
  1471.     /*
  1472.      * get the current time in seconds and microseconds
  1473.      */
  1474.     bsec = btime.tv_sec;
  1475.     busec = btime.tv_usec;
  1476.     /*
  1477.      * get the playback time in seconds and microseconds
  1478.      */
  1479.     psec = play_time.tv_sec;
  1480.     pusec = play_time.tv_usec;
  1481.     /*
  1482.      * if the current time is already later than the playback time,
  1483.      * we don't need to wait
  1484.      */
  1485.     if (bsec > psec)    
  1486.     {
  1487.         wait = -1;
  1488.     }
  1489.     else
  1490.     { 
  1491.         if (bsec == psec)
  1492.         { 
  1493.             /*
  1494.              * if the current and playback times have the same
  1495.              * second value, then compare the microsecond values
  1496.              */
  1497.             if ( busec >= pusec) 
  1498.             { 
  1499.                 /*
  1500.                  * if the current time is already later than
  1501.                  * the playback time, we don't need to wait
  1502.                  */
  1503.                 wait = -1;
  1504.             }
  1505.             else
  1506.             { 
  1507.                 rtime->tv_usec = pusec - busec;
  1508.                 rtime->tv_sec = 0;
  1509.             }
  1510.         }
  1511.         else    
  1512.         { 
  1513.             if (busec > pusec)
  1514.             { 
  1515.                 /*
  1516.                  * 'borrow' a second's worth of microseconds
  1517.                  * from the seconds left to wait
  1518.                  */
  1519.                 rtime->tv_usec = 1000000 - busec + pusec;
  1520.                 psec--;
  1521.                 rtime->tv_sec = psec - bsec;
  1522.             }
  1523.             else
  1524.             { 
  1525.                 rtime->tv_sec = psec - bsec;
  1526.                 rtime->tv_usec = pusec - busec;
  1527.             }
  1528.         }
  1529.     }
  1530.     if (wait < 0)
  1531.     { 
  1532.         /*
  1533.          * if don't need to wait, set the playback time
  1534.          * to the current time
  1535.          */
  1536.         gettimeofday(&play_time, &tzp);
  1537.         /*
  1538.          * set the time to wait to 0
  1539.          */
  1540.         rtime->tv_sec = 0;
  1541.         rtime->tv_usec = 0;
  1542.     }
  1543.     return(wait);
  1544. }
  1545.     
  1546. /******************************************************************************
  1547.  *
  1548.  *    abort_play_back
  1549.  */
  1550. void
  1551. abort_play_back()
  1552. {
  1553.     /*
  1554.      * If we were playing back input actions at the time of the abort,
  1555.      * restore the original wait time for the select in the main wait
  1556.      * loop of the server
  1557.      */
  1558.     if (playback_on)
  1559.     {
  1560.         restorewait->tv_sec = saved_sec;
  1561.         restorewait->tv_usec = saved_usec;
  1562.     }
  1563.     /*
  1564.      * make the input action array empty
  1565.      */
  1566.     read_index = 0;
  1567.     write_index = 0;
  1568.     /*
  1569.      * we are no longer playing back anything
  1570.      */
  1571.     playback_on = 0;
  1572.     play_clock = 0;
  1573.     go_for_next = 1;
  1574.     /*
  1575.      * there is no valid wait time saved any more
  1576.      */
  1577.     time_saved = 0;
  1578.     /*
  1579.      * there are no valid clients using this extension
  1580.      */
  1581.     playback_client = (ClientPtr) NULL;
  1582.     current_xtest_client = (ClientPtr) NULL;
  1583. }
  1584.  
  1585. /******************************************************************************
  1586.  *
  1587.  *    return_input_array_size
  1588.  *
  1589.  *    Return the number of input actions in the input action array.
  1590.  */
  1591. void
  1592. return_input_array_size(client)
  1593. /*
  1594.  * which client to send the reply to
  1595.  */
  1596. ClientPtr    client;
  1597. {
  1598.     xTestQueryInputSizeReply  rep;
  1599.  
  1600.     rep.type = X_Reply;
  1601.     /*
  1602.      * set the serial number of the reply
  1603.      */
  1604.     rep.sequenceNumber = client->sequence;
  1605.     rep.length = 0;
  1606.     rep.size_return = ACTION_ARRAY_SIZE;
  1607.     WriteReplyToClient(client,
  1608.                sizeof(xTestQueryInputSizeReply),
  1609.                (caddr_t) &rep);        
  1610. }        
  1611.