Listing 1 (GetTouch.c)

/*----------------------------------------------------*
 *                                                    *
 * Module:     GetTouch.c                             *
 * Purpose:    To provide an intelligent interface    *
 *             to the Elographics ELODEV TSR from an  *
 *             application that must distinguish      *
 *             between button and curve type touches. *
 * Author:     W. Harvey Gray                         *
 * Compiler:   Microsoft 5.0                          *
 *                                                    *
 * External    GetTouch                               *
 * Functions:  InitializeTouch                        *
 *             ReplayTouch                            *
 *             SetButtonRadius                        *
 *             TouchInfo                              *
 *                                                    *
 * Variables:  There are no external variables used   *
 *             or defined by this module.             *
 *                                                    *
 * Copyright 1992, W. Harvey Gray. May be used        *
 *   freely, if authorship and publication are        *
 *   acknowledged.                                    *
 *                                                    *
 *----------------------------------------------------*/

#include <math.h>
#include <stdio.h>

#include "dvrfunc.h"
#include "GetTouch.h"

/*----------------------------------------------------*
 *                module defines                      *
 *----------------------------------------------------*/

#define TOUCH_BUF_NUM 50   /* Internal buffer size.   */

/*----------------------------------------------------*
 *                static variables                    *
 *----------------------------------------------------*/

static boolean is_button;       /* Is a button flag   */
static boolean from_tbuff;  /* Touch in buffer flag   */
static boolean overflow,   /* Buff storage exceeded   */

static int num_returned;      /* Total touch points   */
static int num_touch;       /* Count of touch points  */
static int ut;           /* Touch point untouch flag  */
static int xt;           /* Touch point x coordinate  */
static int yt;           /* Touch point y coordinate  */

static long radius2;      /* Square of button radius  */
static long dist2;              /* Distance variable  */
static long xcen;             /* X centroid of touch  */
static long xsum;           /* X sum of touch points  */
static long ycen;             /* Y centroid of touch  */
static long ysum;           /* Y sum of touch points  */

/*----------------------------------------------------*
 *                touch buffer and pointers           *
 *----------------------------------------------------*/

static struct touchit touch_information;

static struct touchit *pti = &touch_information;

static struct touchxy touch[TOUCH_BUF_NUM];
static struct touchxy tub;

static struct touchxy *ptouch : &touch[0];
static struct touchxy *ptub = &tub;

/*----------------------------------------------------*
 *                static prototypes                   *
 *----------------------------------------------------*/

static struct touchxy *buffered( boolean * );
static struct touchxy *unbuffered( boolean * );

static void buffer_touch( void );
static void store_touch( struct touchxy * );

/*----------------------------------------------------*
 *     extern function GetTouch()                     *
 *----------------------------------------------------*/

struct touchxy *GetTouch( boolean *button ) {

/*----------------------------------------------------*
 * Purpose:                                           *
 *                                                    *
 *   Function GetTouch doesn't accept any inputs      *
 * from the caller and returns two values. If         *
 * there is a touch in progress, then GetTouch        *
 * returns a pointer to a struct that contains the    *
 * next touch point coordinate pair. If no touch      *
 * is in progress, then GetTouch returns a NULL       *
 * pointer to a touchxy struct. Also returned via     *
 * a pointer to the boolean button variable is the    *
 * logical value of the button flag. If TRUE, then    *   
 * the touch should be interpreted like the user      *
 * touched a button. If FALSE, then the touch         *
 * should be interpreted like the user is drawing     *
 * a curve.                                           *
 *                                                    *
 *----------------------------------------------------*/
   if ( from_tbuff )
      return buffered( button );
   /*------------------------------------------------*
    *  If there is no touch, then return immedi-     *
    * ately pointing to a null touch point.          *
    *------------------------------------------------*/
   
   if ( ! gettouch( &xt, &yt, &ut ) )
      return (struct touchxy *) NULL;
      
   /*------------------------------------------------*
    * If the space in the touch buffer has been      *
    * exceeded, then simply return the touch point.  *
    *------------------------------------------------*/
   
   if ( overflow )
      return unbuffered( button );
   
   /*------------------------------------------------*
    * The last special case occurs when an           *
    * untouch occurs on the first touch point. If    *
    * this happens, simply return the untouch pt.    *
    *------------------------------------------------*/
   
   else if ( ut ) {
   
      ptub->xt = xt;
      ptub->yt = yt;
      ptub->ut = ut;
      *button = TRUE;
      
      return ptub;
   }
   
   /*------------------------------------------------*
    *   If here, then the touch point is the first   *
    * touch point of a new touch. Begin by buffer-   *
    * ing (at most) TOUCH_BUF_NUM touch points.       *
    *------------------------------------------------*/
   
   is_button = TRUE;      /* Assume it's a button.   */
   num_touch = 1;  /* Init. number of touch points   */
   
   ptouch = &touch[0];  /* Init. touch buffer ptr.   */
   ptouch->xt = xt;           /* Store touch point   */
   ptouch->yt = yt;
   ptouch->ut = ut;
   
   xcen = xsum = (long) xt; /* Init. touch pt cen.   */
   ycen = ysum = (long) yt;
   
   buffer_touch();        /* Fill the touch buffer   */
   
   /*------------------------------------------------*
    *   Setup so that the touch can be extracted     *
    * from its internal buffer and return the        *
    * first touch point.                             *
    *------------------------------------------------*/
   
   from_tbuff = TRUE;
   num_returned = 1;
   
   ptouch = &touch[0];
   *button = is_button;
   
   return ptouch;
}

/*---------------------------------------------------*
 *     extern function InitializeTouch()             *
 *---------------------------------------------------*/

void InitializeTouch( void ) {

/*---------------------------------------------------*
 * Purpose:                                          *
 *                                                   *
 *   Initialize the internal variables of the        *
 * GetTouch module.                                  *
 *                                                   *
 *---------------------------------------------------*/

   is_button = FALSE;
   from_tbuff = FALSE;
   overflow = FALSE;
   
   num_returned = 0;
   num_touch = 0;
   ut = FALSE;
   xt = 0;
   yt = 0;
   
   radius2 = 0;
   dist2 = 0;
   xcen = 0;
   xsum = 0;
   ycen = 0;
   ysum = 0;
   
   return;
}

/*---------------------------------------------------*
 *    extern function   ReplayTouch()                *
 *---------------------------------------------------*/

void Replaytouch( boolean set_button ) {

/*---------------------------------------------------*
 * Purpose:                                          *
 *                                                   *
 *   Replays a touch, if there is one in the buffer. *
 *                                                   *
 *---------------------------------------------------*/
   if ( from_tbuff ) {      /* Lose, if no buffer.  */
   
      num_returned = 0;
      ptouch = &touch[-1];   /* It will be ++'ed.  */
      is_button = set_button;
   }
   return;
}

/*--------------------------------------------------*
 *     extern function SetButtonRadius()            *
 *--------------------------------------------------*

void SetButtonRadius( int radius ) {

/*--------------------------------------------------*
 * Purpose:                                         *
 *                                                  *
 *   Sends the button radius to this module.        *
 *                                                  *
 *--------------------------------------------------*/

   radius2 = (long) radius * radius;
}

/*--------------------------------------------------*
 *     extern function  TouchInfo()                 *
 *--------------------------------------------------*/

struct touchit *TouchInfo( void ) {

/*--------------------------------------------------*
 * Purpose:                                         *
 *                                                  *
 *   Returns a pointer to a struct that contains    *
 * touch information.                               *
 *                                                  *
*---------------------------------------------------*/

   pti->xcen = (int) ( xsum / (long) num_touch );
   pti->ycen = (int) ( ysum / (long) num_touch );
   pti->n = num_touch;
   pti->button = is_button;
   
   return pti;
}

/*--------------------------------------------------*
 *     static function buffer_touch()               *
  *--------------------------------------------------*/

static void buffer_touch( void ) {

/*--------------------------------------------------*
 * Purpose:                                         *
 *                                                  *
 *   Fill up the touch buffer by reading and storing*
 * touch points. Several conditions stop filling    *
 * the touch buffer: if there are too many touch    *
 * points for the buffer, stop buffering; if the    *
 * touch is determined to not be a button, then     *
 * there is no need to continue buffering; or if    *
 * an untouch is encountered, then quit buffering.  *
 *                                                  *
 *--------------------------------------------------*/

   while (num_touch < TOUCH_BUF_NUM ) {
      if ( gettouch( &txt, &yt, &ut)){
         
         num_touch++;
         store touch( ++ptouch );
         
         if ( dist2 > radius2 ) {
            
            /* If here, then not a button push. */
                          /* Stop buffering. */
            is_button = FALSE;
            break;
         }
         if ( ut ) {
                          /* Stop buffering. */
            overflow = FALSE;
            break;
         }
      }
   }
   return;
}

/*--------------------------------------------------*
 *     static function buffered()                   *
 *--------------------------------------------------*/

static struct touchxy *buffered( boolean *button ) {

/*--------------------------------------------------*
 * Purpose:                                         *
 *                                                  *
 *   Returns a buffered touch checking for the end  *
 * of the internal touch buffer. If the end of the  *
 * buffer is encountered, then several conditional  *
 * flags are set.                                   *
 *                                                  *
 *--------------------------------------------------*/

   num_returned++;
   ptouch++;
   *button = is_button;
                          /* Exhausted buffer? */
   
   if ( num_returned == num touch ||
       num_returned > TOUCH_BUF_NUM ) {
   
      from_tbuff = FALSE;
      overflow = TRUE;
   }
                          /* Untouch buffered? */
   if ( ptouch->ut ) {
   
      from tbuff = FALSE;
      overflow = FALSE;
   }
   return ptouch;
}

/*---------------------------------------------------*
 *     static function store_touch()                 *
 *---------------------------------------------------*/

static void store_touch( struct touchxy *pt ) {

/*---------------------------------------------------*
 * Purpose:                                          *
 *                                                   *
 *   Stores touch point into a touch point struct    *
 * and calculates the instantaneous average touch    *
 * coordinates and the distance between this touch   *
 * point's coordinate and the touches average        *
 * coordinate.                                       *
 *                                                   *
 *---------------------------------------------------*/

   pt->xt = xt;
   pt->yt = yt;
   pt->ut = ut;
   
   xsum += xt;
   ysum += yt;
   xcen = xsum / (long) num_touch;
   ycen = ysum / (long) num_touch;
   
   dist 2 = (xt - xcen) * (xt - xcen) +
           (yt - ycen) * (yt - ycen);
   
   return;
}

/*---------------------------------------------------*
 *     static function   unbuffered()                *
 *---------------------------------------------------*/

static struct touchxy *unbuffered ( boolean *button ) {

/*---------------------------------------------------*
 * Purpose:                                          *
 *                                                   *
 *   Returns an unbuffered touch point.              *
 * Additionally, it sets the button                  *
 * flag if it is determined that the touch's         *
 * distance exceeds the buttons's radius.            *
 *                                                   *
 *---------------------------------------------------*/

   num_touch++;
   store_touch( ptub );
   
   if ( dist2 > radius2 ) {
   
      is_button = FALSE;    /* Touch is button. */
   }
   *button = is_button;
   
   if ( ut )       /* If untouch, reset function. */
      overflow = FALSE;
   
   return ptub;
}
/* End of File */