/*******************************************************************************
;*******************************************************************************
;**                                                                           **
;**                  COPYRIGHT 2001-2012 NUANCE COMMUNICATIONS                **
;**                                                                           **
;**               NUANCE COMMUNICATIONS PROPRIETARY INFORMATION               **
;**                                                                           **
;**     This software is supplied under the terms of a license agreement      **
;**     or non-disclosure agreement with Nuance Communications and may not    **
;**     be copied or disclosed except in accordance with the terms of that    **
;**     agreement.                                                            **
;**                                                                           **
;*******************************************************************************
;**                                                                           **
;**     FileName: et9aiptable.h                                               **
;**                                                                           **
;**  Description: Inflection point and segment management.                    **
;**                                                                           **
;*******************************************************************************
;******************************************************************************/


#ifndef _IPTABLE_H_
#define _IPTABLE_H_             1

#include "et9abuildconfig.h"

#include "et9ageometry.h"
#include "et9aswapitypes.h"
#include "et9auidefaults.h"
#include "et9adbm.h"
#include "et9abackend.h"
#include "et9afixeddata.h"


/* don't mangle the function name if compile under C++ */
#if defined(__cplusplus)
extern "C" {
#endif

#define __ET9A_DEBUG_MEM_SIZE           0

#define _SWYPE_MAX_FIXED_DATA           ((QVGA_MAX_X / Z1_FIXED_INTERVAL) * ET9MAXUDBWORDSIZE)
#define _SWYPE_MAX_PATH_POINTS          (_SWYPE_MAX_FIXED_DATA / 10)
#define _SWYPE_MAX_IPS                  ((ET9MAXUDBWORDSIZE * 3) / 2)
#define _SWYPE_MAX_CHANGE_DATA          (_SWYPE_MAX_IPS * 4)
#define _SWYPE_MAX_DOUBLE_LETTER_IPS    (_SWYPE_MAX_IPS / 5)
#define _SWYPE_MAX_EXIT_IPS             (_SWYPE_MAX_IPS / 10)

#define USE_DISTANCE2Y8_IP          1
#define USE_DISTANCE2Y8_SEGMENT     1
#define USE_HIGHER_LOW_THRESHOLDS   1

#define END_PATH_AT_DISCONTINUITY   0           /* Let IPTable handle any apparent end-of-path irregularities */

        /*  #define DEBUG_IPT                               1   // Support code for IP dumping */
        /*  #define DEBUG_IPT1A                             1   // Dump IPs at each new provisionally identified IP */
        /*  #define DEBUG_IPT1A1                            1   // Debug output on conversion of PEN_UP to SOFT_UP */
        /*  #define DEBUG_IPT1B                             1   // Dump IP table after each change */
        /*  #define DEBUG_IPT1C1                            1   // Dump final IP table prior to search */
        /*  #define DEBUG_IPT1C2                            1   // Dump final IP table following search */
        /*  #define DEBUG_IPT1C3A                           1   // Dump final IP table just before re-processing */
        /*  #define DEBUG_IPT1C3B                           1   // Dump final IP table just after re-processing */
        /*  #define DEBUG_IPT2                              1   // Detailed output on sign-change DoubleLetter IP identification */
        /*  #define DEBUG_IPT3                              1   // Detailed output on sign-change DoubleLetter IP identification - Include ouput on "No change" */
        /*  #define DEBUG_IPT4                              1   // Detailed output on PATHCHANGE IP identification - includes changes in D2SumAv, D2Threshold, etc. */
        /*  #define DEBUG_IPT5                              1   // Detailed output on secondary DoubleLetter IP identification - includes changes in D2Sum2Av, etc. */
        /*  #define DEBUG_IPT6                              1   // Detailed output on PathDivision IP identification */
        /*  #define DEBUG_IPT7                              1   // Detailed output on filtering errant data near PenDown/PenUp */
    #if (DEBUG_IPT1A || DEBUG_IPT1A1 || DEBUG_IPT1B || DEBUG_IPT1C1 || DEBUG_IPT1C2 || DEBUG_IPT1C3A || DEBUG_IPT1C3B)
        #ifdef      DEBUG_IPT
            #undef   DEBUG_IPT
        #endif
        #define     DEBUG_IPT                               1
    #endif
    #if (DEBUG_IPT2 || DEBUG_IPT3 || DEBUG_IPT4 || DEBUG_IPT5 || DEBUG_IPT6 || DEBUG_IPT7)
        #ifdef      DEBUG_IPT
            #undef   DEBUG_IPT
        #endif
        #define     DEBUG_IPT                               1
    #endif


#define IPT_IDENTIFY_SOFT    1
#define IPT_OK               0
#define IPT_FAILURE         -1
#define UNINITIALIZED       -1
#define IPT_NO_MATCH        -2
#define IPT_INVALID         -3
#define IPT_TRANSPOSE       -4
#define IPT_OMIT            -5
#define IPT_FIX_MATCH       -6

#define CALCULATE_ROW        0
#define ROW_FINISHED         1

#define IPTABLEROW_POOL_SIZE    12      /* Keep up to 12 IPTableRow objects in available pool */
#define MATCHDATA_POOL_SIZE     (4 * N_KEYS_MAX)      /* Keep up to 4 SWCMatchData objects for each key in available pool */

/* Allow slightly more than twice the maximum number of letters in a word to allow for multiple Multiple-IP scribble gestures  */
/*   in languages with long words and many double letters (think Finnish...) */
#define MAX_PATH_IP_COUNT   ((2 * DEFAULT_WORD_SIZE) + 4)

#define IP_DISTANCES1       0x01
#define SEG_DISTANCES1      0x02
#define INITIAL_DISTANCES   0x03
#define ADJ_IP_DISTANCES1   0x04
#define SEG_DISTANCES2      0x08
#define ADJ_IP_DISTANCES2   0x10
#define FINAL_DISTANCES     0x1C
#define RECALCULATE_ROW     0x20
#define IP_FINISHED         0x1F

#define X_AND_Y_NO_CHANGE   0x00
#define X_POS_TO_NEG        0x01
#define X_NEG_TO_POS        0x02
#define Y_POS_TO_NEG        0x04
#define Y_NEG_TO_POS        0x08
#define X_AND_Y_BOTH_CHANGE 0x10

#define Z1_CANCELLED         1         /* Flag of normal Cancel after at least partial input path */
#define Z1_DELETE_WORD       2         /* Flag of Cancel gesture with no preceding input path */

/* Define minimum distances that will be added to all actual key-IP and key-segment distances */
/* This is to prevent a low frequency word whose keys happen to coincide with the path from */
/* overpowering a much higher frequency word.  Separate values are defined for actual distance */
/* minima and weighted distance minima. */
#define MIN_IP_DISTANCE8        0

#define MIN_IP_WDISTANCE8       1                           /* Essentially 0 */

/* Use higher minimum for PenUp to facilitate overshoot / low-frequency word conflict? */
#define MIN_PENUP_WDISTANCE8    1
#define MIN_PENDOWN_WDISTANCE8  1
#define MIN_IP_DISTANCE8_PENUP_OVERSHOOT        (pThis->m_backend->sScreenGeometry.keyRadius * 8)   /* 1.0 x Key Radius */
#define MIN_PENUP_UNDERSHOOT_PATH_LENGTH8           (7 * pThis->m_backend->sScreenGeometry.keyWidth * 4)    /* 3.5 * Key Width */
#define PENUP_UNDERSHOOT_PATH_INDEX_OFFSET          ((2 * pThis->m_backend->sScreenGeometry.keyWidth) / Z1_FIXED_INTERVAL)
#define SEGMENT_DISTANCE8_PENUP_UNDERSHOOT_THRESHOLD1   (pThis->m_backend->sScreenGeometry.keyRadius * 8)       /* 1.0 x Key Radius */
#define SEGMENT_DISTANCE8_PENUP_UNDERSHOOT_THRESHOLD2   (3 * pThis->m_backend->sScreenGeometry.keyRadius * 4)   /* 1.5 x Key Radius */
#define MAX_UNDERSHOOT_SEGMENT_RATIO                  (float)1.045  /* Do not apply undershoot adjustment unless path segment is relatively straight */

#define MAX_SEGMENT_DISTANCE8_PENUP_OVERSHOOT   (pThis->m_backend->sScreenGeometry.keyRadius * 11)  /* 1.375 x Key Radius */

#define MIN_IP_DISTANCE8_PENDOWN_OVERSHOOT      (pThis->m_backend->sScreenGeometry.keyRadius * 8)   /* 1.0 x Key Radius */
#define MAX_SEGMENT_DISTANCE8_PENDOWN_OVERSHOOT (pThis->m_backend->sScreenGeometry.keyRadius * 8)   /* 1.0 x Key Radius */

#define MIN_SEGMENT_DISTANCE8   1

#define MIN_SEGMENT_WDISTANCE8  (pThis->m_backend->sScreenGeometry.keyRadius * 8)           /* 1.0 x Key Radius */

#define SEGMENT_WDISTANCE_FACTOR    2.50        /* Larger value increases weighted distance for segment matches */
#define SEGMENT_WEIGHT_FACTOR       1.25        /* Larger value increases weighting for segment matches */

#define LENGTH_FACTOR_LENGTH_THRESHOLD8   (3*pThis->m_backend->sScreenGeometry.keyWidth*8)  /* LengthFactor effect increased for longer segments, decreased for shorter */
#define LENGTH_FACTOR_ADJUST_RATIO_MAX    (float)3.0            /* LengthFactor effect increases up to 9 key widths, then maxes out */
#define LENGTH_FACTOR_MAX                 (float)2.5            /* LengthFactor maxes out at 2.5 */


#define SIGNIFICANT_CURVATURE_DIFFERENCE  (float)25.0
#define SIGNIFICANT_CURVATURE_RATIO       (float)1.05
#define MAX_CURVATURE_RATIO               (float)1.33     /* Limit how much curvature is allowed in using heuristic for segment point matching */
/*#define MAX_NO_PENALTY_CURVATURE_RATIO    (float)2.0      // Limit how much curvature is allowed in matching successive keys without imposing a penalty */

#define INCREASED_DOUBLE_PENALTY_MAX_CURVATURE_RATIO   (float)1.25     /* Limit how much curvature is allowed in order to impose increased double letter gesture penalties */

#define PATH_DIVISION_SEG_MATCH_MARGIN      (pThis->m_backend->sScreenGeometry.keyHeight/Z1_FIXED_INTERVAL)

#define LOOPING_PATH_PORTION_THRESHOLD1     (float)0.4      /* If we loop for at least a "half-circle" */
#define LOOPING_PATH_PORTION_FACTOR1        (float)2.5      /* Divide actual distance by 1.0 - 1.25 */
#define LOOPING_PATH_PORTION_THRESHOLD2     (float)0.55     /* If we loop for at least 5/8 of a "circle" */
#define LOOPING_PATH_PORTION_FACTOR2        (float)2.75     /* Divide actual distance by 1.5625 - 1.875 */
#define LOOPING_PATH_PORTION_THRESHOLD3     (float)0.75     /* If we loop for close to a "full-circle" */
#define LOOPING_PATH_PORTION_FACTOR3        (float)3.0      /* Divide actual distance by 2.25 - 3.0 */

#define DISCONTINUITY_SEARCH_LIMIT     ((int)(20/Z1_FIXED_INTERVAL))        /* Don't back up PenUp location more than 4 fixed intervals */

#define MAX_HORIZONTAL_NEIGHBOR_DISTANCE    (2 * pThis->m_backend->sScreenGeometry.keyWidth/3)
#define MAX_VERTICAL_NEIGHBOR_DISTANCE      (3 * pThis->m_backend->sScreenGeometry.keyHeight/4)
#define MAX_NEIGHBOR_INTERVALS              8

#define ANGLE_DELETION_THRESHOLD_WEIGHT     (float)5.0          /* Don't delete Angle IP if weight exceeds 5.0 */

/* Define weights for each IP type */
/*#define PenDownWeight           (float)7.0 */
#define PenDownWeight           (float)6.0
/*#define PenUpWeight               4 */
/*#define PenUpWeight             (float)5.0 */
#define PenUpWeight             (float)4.5
#define AngleWeight             (float)4.0
/*#define AnglePenaltyWeight        (float)5.5 */
#define AnglePenaltyWeight      (float)6.25
#define AnglePenaltyWeightCredit (float)5.0
#define AngleWeightMax          (float)7.0
#define DoubleLetterWeight      (float)9.0
#define SingleKeyToDoubleIPWeight   (float)3.0
#define MultipleIPsWeight       (float)7.0
#define MultipleLetterWeight    (float)4.0
/*#define SoftDownWeight            1 */
#define SoftDownWeight          (float)2.0
/*#define SoftUpWeight              1 */
#define SoftUpWeight            (float)3.0
#define ExitUpWeight            (float)0.75
#define PauseWeight             (float)3.0
#define MultipleWeight          (float)0.0
#define PauseAngleWeight        (AngleWeight * PAUSE_ANGLE_WEIGHT_FACTOR)
#define PauseAngleWeightMax     (AngleWeightMax * PAUSE_ANGLE_WEIGHT_FACTOR)
#define TapWeight               (float)0.0
#define TapHoldWeight           (float)0.0
#define ExitWeight              (float)0.0
#define EntryWeight             (float)0.0

/*#define SegmentWeight           1.0         // Adjusted w.r.t. AngleWeight by weighting by D2Sum ratio */
#define SegmentWeight           2.5         /* Adjusted w.r.t. AngleWeight by weighting by D2Sum ratio */


#if USE_DISTANCE2Y8_IP
/* Thresholds for non-linear distance calculation (y-coordinate difference doubled) */

#if     USE_HIGHER_LOW_THRESHOLDS
/* Thresholds for Search Level 1 */
#define PenDownThreshold8           (8*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.0 * KEY_RADIUS */
#define PenUpThreshold8             (8*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.0 * KEY_RADIUS */
#define AngleThreshold8             (8*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.0 * KEY_RADIUS */
#define DoubleLetterThreshold8      (11*pThis->m_backend->sScreenGeometry.keyRadius*2)      /* 2.75 * KEY_RADIUS */
#define SoftDownThreshold8          (7*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.5 * KEY_RADIUS */
#define SoftUpThreshold8            (7*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.5 * KEY_RADIUS */
#define PauseThreshold8             (5*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.5 * KEY_RADIUS */
#define PauseAngleThreshold8        (13*pThis->m_backend->sScreenGeometry.keyRadius*2)      /* 3.25 * KEY_RADIUS */
#define MultipleThreshold8          (13*pThis->m_backend->sScreenGeometry.keyRadius*2)      /* 3.25 * KEY_RADIUS */
#else
/* Thresholds for Search Level 1 */
#define PenDownThreshold8           (7*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.5 * KEY_RADIUS */
/*#define PenUpThreshold8               (8*pThis->m_backend->sScreenGeometry.keyRadius*4)       // 4.0 * KEY_RADIUS */
#define PenUpThreshold8             (7*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.5 * KEY_RADIUS */
#define AngleThreshold8             (7*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.5 * KEY_RADIUS */
#define DoubleLetterThreshold8      (5*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.5 * KEY_RADIUS */
#define SoftDownThreshold8          (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
#define SoftUpThreshold8            (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
#define PauseThreshold8             (4*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.0 * KEY_RADIUS */
#define PauseAngleThreshold8        (5*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.5 * KEY_RADIUS */
#define MultipleThreshold8          (5*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.5 * KEY_RADIUS */
#endif

#define TapThreshold8               (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
#define TapHoldThreshold8           (3*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 1.5 * KEY_RADIUS */

/* Thresholds for Search Level 3 (level 2 interpolated) */
#define PenDownThreshold8_2         (11*pThis->m_backend->sScreenGeometry.keyRadius*4)      /* 5.5 * KEY_RADIUS */
#define PenUpThreshold8_2           (12*pThis->m_backend->sScreenGeometry.keyRadius*4)      /* 6.0 * KEY_RADIUS */
#define AngleThreshold8_2           (11*pThis->m_backend->sScreenGeometry.keyRadius*4)      /* 5.5 * KEY_RADIUS */
#define DoubleLetterThreshold8_2    (9*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.5 * KEY_RADIUS */
#define SoftDownThreshold8_2        (9*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.5 * KEY_RADIUS */
#define SoftUpThreshold8_2          (9*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.5 * KEY_RADIUS */
#define PauseThreshold8_2           (8*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.0 * KEY_RADIUS */
#define PauseAngleThreshold8_2      (8*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.0 * KEY_RADIUS */
#define MultipleThreshold8_2        (8*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.0 * KEY_RADIUS */
#define TapThreshold8_2             (12*pThis->m_backend->sScreenGeometry.keyRadius*4)      /* 6.0 * KEY_RADIUS */
#define TapHoldThreshold8_2         (8*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.0 * KEY_RADIUS */

#else
/* Thresholds for linear distance calculation (y-coordinate difference NOT doubled) */

/* Thresholds for Search Level 1 */
#define PenDownThreshold8           (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
#define PenUpThreshold8             (7*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.5 * KEY_RADIUS */
#define AngleThreshold8             (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
#define DoubleLetterThreshold8      (4*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.0 * KEY_RADIUS */
#define SoftDownThreshold8          (5*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.5 * KEY_RADIUS */
#define SoftUpThreshold8            (5*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.5 * KEY_RADIUS */
#define PauseThreshold8             (3*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 1.5 * KEY_RADIUS */
#define PauseAngleThreshold8        (4*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.0 * KEY_RADIUS */
#define MultipleThreshold8          (4*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.0 * KEY_RADIUS */
#define TapThreshold8               (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
#define TapHoldThreshold8           (3*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 1.5 * KEY_RADIUS */

/* Thresholds for Search Level 3 (level 2 interpolated) */
#define PenDownThreshold8_2         (8*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.0 * KEY_RADIUS */
#define PenUpThreshold8_2           (9*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.5 * KEY_RADIUS */
#define AngleThreshold8_2           (8*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.0 * KEY_RADIUS */
#define DoubleLetterThreshold8_2    (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
#define SoftDownThreshold8_2        (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
#define SoftUpThreshold8_2          (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
#define PauseThreshold8_2           (5*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.5 * KEY_RADIUS */
#define PauseAngleThreshold8_2      (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
#define MultipleThreshold8_2        (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
#define TapThreshold8_2             (7*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.5 * KEY_RADIUS */
#define TapHoldThreshold8_2         (5*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.5 * KEY_RADIUS */

#endif

#if     USE_DISTANCE2Y8_SEGMENT
    /* Note that key-to-segment distance thresholds are compared against "unweighted" */
    /*   (linear) distance8() distances, rather than non-linear distance2y8() distances */
    #define SegmentThreshold8_1         (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
    #define PointIPSumLimit_1           (11*pThis->m_backend->sScreenGeometry.keyRadius*2)      /* 2.75 * KEY_RADIUS */

    #define SegmentThreshold8_2         (8*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.0 * KEY_RADIUS */
    #define PointIPSumLimit_2           (10*pThis->m_backend->sScreenGeometry.keyRadius*4)      /* 5.0 * KEY_RADIUS */

#else
    /* Thresholds for linear distance calculation (y-coordinate difference NOT doubled) */

    #if     USE_HIGHER_LOW_THRESHOLDS
        /*#define SegmentThreshold8_1   (4*pThis->m_backend->sScreenGeometry.keyRadius*4)       // 2.0 * KEY_RADIUS */
        #define SegmentThreshold8_1     (9*pThis->m_backend->sScreenGeometry.keyRadius*2)       /* 2.25 * KEY_RADIUS */
        #define PointIPSumLimit_1       (11*pThis->m_backend->sScreenGeometry.keyRadius*2)      /* 2.75 * KEY_RADIUS */

        #define SegmentThreshold8_2     (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
        #define PointIPSumLimit_2       (13*pThis->m_backend->sScreenGeometry.keyRadius*2)      /* 3.25 * KEY_RADIUS */

    #else
        #define SegmentThreshold8_1     (9*pThis->m_backend->sScreenGeometry.keyRadius*2)       /* 2.25 * KEY_RADIUS */
        #define PointIPSumLimit_1       (11*pThis->m_backend->sScreenGeometry.keyRadius*2)      /* 2.75 * KEY_RADIUS */

        #define SegmentThreshold8_2     (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
        #define PointIPSumLimit_2       (13*pThis->m_backend->sScreenGeometry.keyRadius*2)      /* 3.25 * KEY_RADIUS */

    #endif

#endif

/* Thresholds for PenUp and PenUp "Overshoot" matching use linear distance calculation */
    /* Currently: 0.67 <= IPFactor <= 0.90 */
    /*            0.65 <= segmentFactor <= 1.00     (as function of Z1Level) */
    /* Then interpolate between 1st and 2nd threshold based on Pen Speed */

#define PenUpOvershoot_IPThreshold8             (9*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 4.5 * KEY_RADIUS */
#define PenUpOvershoot_IPThreshold8_2           (12*pThis->m_backend->sScreenGeometry.keyRadius*4)      /* 6.0 * KEY_RADIUS */

#define PenUpOvershoot_SegmentThreshold8_1      (3*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 1.5 * KEY_RADIUS */
#define PenUpOvershoot_SegmentThreshold8_2      (9*pThis->m_backend->sScreenGeometry.keyRadius*2)       /* 2.25 * KEY_RADIUS */

#define PenUpUndershoot_IPThreshold8            (5*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 2.5 * KEY_RADIUS = (1.65 - 2.25) * KEY_RADIUS */
#define PenUpUndershoot_IPThreshold8_2          (7*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.5 * KEY_RADIUS = (2.35 - 3.15) * KEY_RADIUS */
#define PenUpUndershoot_SegmentThreshold8_1     (2*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 1.0 * KEY_RADIUS = (0.65 - 1.00) * KEY_RADIUS */
#define PenUpUndershoot_SegmentThreshold8_2     (7*pThis->m_backend->sScreenGeometry.keyRadius*2)       /* 1.75 * KEY_RADIUS = (1.14 - 1.75) * KEY_RADIUS */

/* Thresholds for PenDown and PenDown "Overshoot" matching use linear distance calculation */
#define PenDownOvershoot_IPThreshold8           (6*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 3.0 * KEY_RADIUS */
#define PenDownOvershoot_IPThreshold8_2         (10*pThis->m_backend->sScreenGeometry.keyRadius*4)      /* 5.0 * KEY_RADIUS */

#define PenDownOvershoot_SegmentThreshold8_1        (2*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 1.0 * KEY_RADIUS */
#define PenDownOvershoot_SegmentThreshold8_2        (3*pThis->m_backend->sScreenGeometry.keyRadius*4)       /* 1.5 * KEY_RADIUS */

#define MaxSearchLevel                  3
#define SearchLevelMinVal               0
#define ThisSearchVal                   1
#define SearchLevelMaxVal               2

#define IP_THRESHOLD_FACTOR_LEVEL_INIT          (float)0.65
#define SEGMENT_THRESHOLD_FACTOR_LEVEL_INIT     (float)0.80

/* NOTE: Removed code that multiplied IPFactor by (float)1.2 when IPFactor < 1.0. */
/*   Thus, previous value of 0.50 would now be equivalent to a value of 0.6. */
/*   Thus, 0.67 represents about a 10% actual increase over previous value. */
#define IP_THRESHOLD_FACTOR_LEVEL_MIN           (float)0.67

#define IP_THRESHOLD_FACTOR_LEVEL_MAX           (float)0.90
#define SEGMENT_THRESHOLD_FACTOR_LEVEL_MIN      (float)0.65

#define SEGMENT_THRESHOLD_FACTOR_LEVEL_MAX      (float)1.0

/* Define flags for m_IPFlags field */
#define REQUIRED_IP         0x01        /* IP that MUST be matched to a letter */
#define ANGLE_IP            0x02        /* IP determined by acute path angle */
#define PAUSE_IP            0x04        /* IP associated with location of pause in stylus motion */
#define DIACRITIC_IP        0x08        /* IP associated with path location on "Diacritic Gesture" */
#define OVERSHOOT_IP        0x10        /* IP that is may be associated with "overshoot" in the input pattern */
#define MULTIPLE_IP         0x20        /* IP that can be one of the IPs in a Multiple-IP Double Letter gesture */
/* Unused: 0x40 (Was SWYPE_TAP_IP, IP at origin of path for a Type-Swype gesture.) */
#define EXIT_IP             0x80        /* IP associated with path exiting from top of keyboard */

#define TAP_IP              0x00        /* IP associated with screen tap */

#define PAUSE_ANGLE_WEIGHT_FACTOR               (float)0.67     /* Reduce weight by 1/3 */
#define PAUSE_ANGLE_WEIGHT_FACTOR_2             (float)0.33     /* Reduce weight by 2/3 */


typedef enum IPType_e
{
    PenDown = 1,
    PenUp,
    Angle,
    DoubleLetter,
    SoftDown,
    SoftUp,
    Pause,
    PauseAngle,
    Exit,
    Entry,
    Multiple,
    PathDivision,
    Tap,
    TapHold,
    MaxIPType
}
IPType;

enum VectorIPData
{
    VSlopeBack = 1,
    VSlopeForward,
    VSlopeNextIP
};

/* Forward declarations */
struct   SWCIPAnalyzer_s;
typedef struct SWCIPTableRow_s SWCIPTableRow;

struct SWCIPTableRow_s
{
    /* IP location data */
    _SWPoint m_IPLocation;       /* Coordinates of IP */
    _SWPoint exitLoc;            /* If bottomRow is true, the coordinates of the first prior point on the path below the botom of the keyboard */
    _SWPoint gestureLoc;           /* If this IP was generated during a doubleLetter gesture, the coordinates of the center of the gesture */
    IPType  m_IPType;
    BYTE1   m_IPFlags;          /* Flags for characteristics based on IPType */
    BYTE1   m_RowFilled;        /* Flag that all data for this row has been filled in, or needs to be re-calculated */
    BYTE1   m_MergeCount;       /* Number of originally separate IPs that have been merged together to form this IP */
    SBYTE2  m_IPIndex;          /* Sequential index of IP in list */
    SBYTE2  m_ForwardMultipleCount;     /* Number of following IPs that can be combined in a "scribble" gesture */
    SBYTE2  m_BackwardMultipleCount;    /* Number of preceding IPs that can be combined in a "scribble" gesture */
    SBYTE2  m_DoubleIPIndex;    /* Set to integer ID of doubleLetter gesture within which this IP was detected */
    BYTE4   m_TimeOffset;       /* Time offset at IP Location */
    SBYTE2  m_IPPosition;       /* Distance along path to IP from PEN_DOWN Location */
    SBYTE2  m_SegmentLen8;      /* Distance8 along path to IP from preceding IP */
    SBYTE2  m_LineLen8;         /* Straight-line Distance to IP from preceding IP */
    SBYTE2  m_exitIndex;        /* If this segment began with an entry IP, the IP index of the preceding Exit IP, else -1 */
    ET9BOOL bottomRow;          /* Set true iff m_IPLocation.y is > SWDbm_keyboardHeight */
    ET9BOOL signChangesOK;
    ET9BOOL m_ForceShowWCW;     /* Force showing of WCW for 1-letter words when multiple DoubleLetter gesture loops performed (set in penDown IP) */
    BYTE1   rubbedKey;          /* If Z1 path or Tap is processed that can also map to a rubbed key, the key is specified here in the PenDown or Tap IP */
    float   m_fIPWeight;        /* Weight assigned to this IP */
    float   m_fSkipPenalty;     /* Skip penalty assigned to this IP */
    float   m_fLengthRatio;     /* Ratio: (m_SegmentLen8/m_LineLen8) */
    float   m_fLengthFactor;    /* Computed from m_fLengthRatio */
    float   gestureRatio;       /* Ratio of DoubleLetter gesture width to height (or vice versa; will always be <= 1.0) */
    float   circleScore;        /* Score based on av. radius, max. dimension, and radius variance */
    SBYTE2  m_FixedIndexIn;     /* Index of m_aFixedMouseData of point corresponding to IP on entering path */
    SBYTE2  m_FixedIndexOut;    /* Index of m_aFixedMouseData of point corresponding to IP on exiting path */
    SBYTE2  gestureIn;          /* Index of m_aFixedMouseData of point corresponding to start of enclosing doubleLetter gesture */
                                /* OR, if DoubleLetter IP, the fixed index of the first included IP */
    SBYTE2  gestureOut;         /* Index of m_aFixedMouseData of point corresponding to end of enclosing doubleLetter gesture */
                                /* OR, if DoubleLetter IP, the fixed index of the last included IP */
    SBYTE2  gestureIPCount;     /* Number of IPs generated within DoubleGesture */
    SBYTE2  gestureIPIndexIn;   /* if DoubleLetter IP, the IP index of the first included IP */
    SBYTE2  gestureIPIndexOut;  /* if DoubleLetter IP, the IP index of the last included IP */
    SBYTE2  m_IPPosIndex;       /* Index of m_aFixedMouseData of point corresponding to IP "central" point */
    SBYTE2  minX;               /* Minimum X-coordinate of any point in gesture */
    SBYTE2  maxX;               /* Maximum X-coordinate of any point in gesture */
    SBYTE2  minY;               /* Minimum Y-coordinate of any point in gesture */
    SBYTE2  maxY;               /* Maximum Y-coordinate of any point in gesture */
    SBYTE2  debugData;          /* Spare field for debugging */
    BYTE2   m_IPWDistance8[N_KEYS_MAX]; /* Weighted distance8 of each key (or W_DISTANCE8_MAX flag) from IP */
    BYTE2   m_IPDistance8[N_KEYS_MAX];  /* Actual (unweighted) Distance8 of each key from IP */
    BYTE2   m_IPAdjDistance8[N_KEYS_MAX];   /* (unweighted) Distance8 of each key from IP, adjusted for overshoot if appropriate */
    BYTE2   m_SegmentWDistance8[N_KEYS_MAX];    /* Weighted distance8 of each key (or W_DISTANCE8_MAX flag) from preceding */
                                                /*   line segment */
    BYTE2   m_SegmentDistance8[N_KEYS_MAX]; /* Actual (unweighted) Distance8 of each key from preceding */
                                            /*   line segment */
    SBYTE2  m_LinePos[N_KEYS_MAX];      /* Where m_SegmentDistance[i] != W_DISTANCE8_MAX, the position along */
                                        /* the segment closest to Key i */
    SBYTE2  m_D2LocalMaxPos[N_KEYS_MAX]; /* Where m_SegmentDistance[i] != W_DISTANCE8_MAX, the position along */
                                         /* the segment within Z1_SEGMENT_MATCH_D2SUM_LIMIT of m_LinePos[i] where */
                                         /* where the 2nd difference sum reaches a local maximum */
    float   m_SegmentWeight[N_KEYS_MAX];/* Where m_SegmentWDistance[i] != W_DISTANCE8_MAX, the adjusted weight used */
                                        /* in calculating m_SegmentWDistance8[i] for Key i */
};

    ET9PRIVATE void ET9FARCALL SWCIPTableRow_Construct(SWCIPTableRow *pThis, _SWPoint IPLocation, IPType IPKind, SBYTE2 wIPIndex, BYTE4 dwTimeOffset,
                        SBYTE2 wFixedIndexIn, SBYTE2 wFixedIndexOut, SBYTE2 debugDataVal)
    {
        pThis->m_IPLocation = IPLocation;
        pThis->m_IPType = IPKind;
        pThis->m_IPIndex = wIPIndex;
        pThis->m_TimeOffset = dwTimeOffset;
        pThis->m_FixedIndexIn = wFixedIndexIn;
        pThis->m_FixedIndexOut = wFixedIndexOut;
        pThis->debugData = debugDataVal;
    }

struct SWCIPTable_s
{
#if DEBUG_SHOW_RECALC_COUNTS
    int   IPDistanceCalcCount, SegDistanceCalcCount;
#endif
    /* The following threshold arrays are set as follows: */
    /*      ArrayXXX[SearchLevelMinVal] and ArrayXXX[SearchLevelMaxVal] are set with respect to constants defining a (maximum) lower */
    /*          and upper bound for the threshold value.  The specific values set are a function of either IPFactor (where 0.67 <= IPFactor <= 0.9) */
    /*          or segmentFactor (where 0.65 <= IPFactor <= 1.0), where IPFactor and segmentFactor vary within their respective ranges as a */
    /*          function of the current value of Z1OperationSetting. */
    /*      ArrayXXX[ThisSearchVal] is interpolated between ArrayXXX[SearchLevelMinVal] and ArrayXXX[SearchLevelMaxVal] as a function of */
    /*          the pen speed in the current input path.  This is the value actually used in the current search. */

    BYTE2 IPthreshold8[MaxIPType][MaxSearchLevel];  /* Distance8 thresholds for each IP type and search level */
    BYTE2 SegmentThreshold8[MaxSearchLevel];    /* Distance8 thresholds for segment matches at each search level */
    BYTE2 PenUpOvershootIPThreshold8[MaxSearchLevel];           /* Distance8 thresholds for key-to-PenUp IP overshoot testing */
    BYTE2 PenUpOvershootSegmentThreshold8[MaxSearchLevel];      /* Distance8 thresholds for key-to-segment PenUp overshoot testing */
    BYTE2 PenUpUndershootIPThreshold8[MaxSearchLevel];          /* Distance8 thresholds for key-to-PenUp IP undershoot testing */
    BYTE2 PenUpUndershootSegmentThreshold8[MaxSearchLevel];     /* Distance8 thresholds for key-to-segment PenUp undershoot testing */
    BYTE2 PenDownOvershootIPThreshold8[MaxSearchLevel];         /* Distance8 thresholds for key-to-PenDown IP overshoot testing */
    BYTE2 PenDownOvershootSegmentThreshold8[MaxSearchLevel];    /* Distance8 thresholds for key-to-segment PenDown overshoot testing */
    BYTE2 PointIPSumLimit[MaxSearchLevel];  /* Qualifying thresholds for segment matches at each search level */
    SWCIPTableRow *lastExitIP, *prevExitIP;

    BYTE2 m_actualPathLength;         /* Total length of current input path */

    SBYTE2 m_ExitXPos[DEFAULT_WORD_SIZE];       /* Up to DEFAULT_WORD_SIZE x-coordinates of where path exits keyboard */
    SBYTE2 m_EntryXPos[DEFAULT_WORD_SIZE];      /* Up to DEFAULT_WORD_SIZE x-coordinates of where path re-enters keyboard */
    SBYTE2 m_EntryPosIndex[DEFAULT_WORD_SIZE];  /* Up to DEFAULT_WORD_SIZE fixed indices of where path re-enters keyboard */
    SBYTE2 m_ShiftPos[DEFAULT_WORD_SIZE];       /* Up to DEFAULT_WORD_SIZE positions along the path */
                                                /*   where the path exits from the top of the keyboard */
    SBYTE2 m_ShiftLocCount;         /* Number of m_ShiftPos[] locations recorded */
    ET9BOOL  m_ShiftAll;               /* CAPLOCK gesture flag to Upper-case all letters */
    ET9BOOL  firstLetterShiftGesture;  /* If true, initial shift gesture is highly likely to be intended for first letter of word */

#if ENABLE_DIACRITIC_GESTURES
    SBYTE2 m_DiacriticExitXPos[DEFAULT_WORD_SIZE];      /* Up to DEFAULT_WORD_SIZE x-coordinates of where path exits from the botoom of the keyboard */
    SBYTE2 m_DiacriticEntryXPos[DEFAULT_WORD_SIZE];     /* Up to DEFAULT_WORD_SIZE x-coordinates of where path re-enters keyboard */
    SBYTE2 m_DiacriticEntryPosIndex[DEFAULT_WORD_SIZE]; /* Up to DEFAULT_WORD_SIZE fixed indices of where path re-enters keyboard */
    SBYTE2 m_DiacriticPos[DEFAULT_WORD_SIZE];           /* Up to DEFAULT_WORD_SIZE positions along the path */
                                                        /*   where the path exits from the botoom of the keyboard */
    SBYTE2 m_DiacriticLocCount;                         /* Number of m_DiacriticPos[] locations recorded */
#endif

    SBYTE2 m_penUpDoubleIPIndex;
    SBYTE2 m_wDoubleIPCount;        /* Number of DoubleLetter IPs found in input path */
    SBYTE2 wIPCount;
    SBYTE2 wIPPoolCount;
    SBYTE2 rowBoundary[KEY_ROWS_MAX];   /* Lower bounds of keyboard rows */

    /* IP table data arrays */
    SWCIPTableRow       m_IPTableRowPool[_SWYPE_MAX_IPS];
    SWCIPTableRow       m_IPTableRowOverflow;
    SWCIPTableRow       *m_aIPTable[_SWYPE_MAX_IPS];
    SWCIPTableRow       *m_aIPTable2[_SWYPE_MAX_DOUBLE_LETTER_IPS];    /* List of DoubleLetter IPs found */

    SWFixedData         *m_aPathPoints[_SWYPE_MAX_PATH_POINTS];
    ET9U16              wPathPointCount;

    BackEnd             *m_backend;
};

    ET9PRIVATE void ET9FARCALL SWCIPTable_Initialize();

    /* SavedCodeSegments/SearchDB.cpp/154 */
    ET9PRIVATE void ET9FARCALL SWCIPTable_Construct(SWCIPTable *pThis);

    ET9PRIVATE void ET9FARCALL SWCIPTable_SetIPThresholdLevels(SWCIPTable *pThis, float IPFactor, float segmentFactor);

    /* clear table data */
    ET9PRIVATE void ET9FARCALL SWCIPTable_ClearIPTable(SWCIPTable *pThis);

    /* access shared data array through a function that can */
    /* use a semaphore to only allow one process */
    /* to access it at a time */
    ET9PRIVATE SWCIPTableRow ** ET9FARCALL SWCIPTable_GetIPTableArray(SWCIPTable *pThis);
    ET9PRIVATE SWCIPTableRow ** ET9FARCALL SWCIPTable_GetIPTableArray2(SWCIPTable *pThis);

    ET9PRIVATE void ET9FARCALL SWCIPTableRow_insert(
                           _ET9AWSPContext *pContext,
                           SWCIPTableRow **pRowTable,
                           ET9S16 nIndex,
                           ET9S16 *pnCount,
                           ET9S16 nCapacity,
                           SWCIPTableRow *pItem);
    ET9PRIVATE void ET9FARCALL SWCIPTableRow_append(
                           _ET9AWSPContext *pContext,
                           SWCIPTableRow **pRowTable,
                           ET9S16 *pnCount,
                           ET9S16 nCapacity,
                           SWCIPTableRow *pItem);
    ET9PRIVATE void ET9FARCALL SWCIPTableRow_erase(
                           _ET9AWSPContext *pContext,
                           SWCIPTableRow **pRowTable,
                           ET9S16 nIndex,
                           ET9S16 *pnCount);
    ET9PRIVATE void ET9FARCALL SWFixedData_append(SWCIPTable *pThis, SWFixedData *pItem);

    static ET9INLINE ET9BOOL SWCIPTable_IPCalcNeeded(SWCIPTable *pThis, SWCIPTableRow *ipDat, BYTE1 flag)  { ET9_UNUSED(pThis); return (ET9BOOL)((ipDat != NULL) && ((ipDat->m_RowFilled & flag) != flag)); }

    /* Recalculate IPTable values based on updated thresholds */
    ET9PRIVATE void ET9FARCALL SWCIPTable_reProcessIPTable(SWCIPTable *pThis, ALGORITHM_TYPE searchAlgorithm);

    /* functions to signal the events */
    ET9PRIVATE ET9BOOL ET9FARCALL SWCIPTable_CheckSignalDetectZ1Input(SWCIPTable *pThis);

    /* Data access functions */
    ET9PRIVATE ET9BOOL ET9FARCALL SWCIPTable_SetIPTableAnalyzedFlag(SWCIPTable *pThis, ET9BOOL analysisDone);
    ET9PRIVATE SBYTE2 ET9FARCALL SWCIPTable_GetIPTableSize(SWCIPTable *pThis);
    ET9PRIVATE SWCIPTableRow* ET9FARCALL SWCIPTable_GetIPTableRow(SWCIPTable *pThis, SBYTE2 *IPIndex);
    ET9PRIVATE SWCIPTableRow* ET9FARCALL SWCIPTable_GetIPTable2Row(SWCIPTable *pThis, SBYTE2 IPIndex);
    ET9PRIVATE void ET9FARCALL SWCIPTable_RemoveIPTable2Row(SWCIPTable *pThis, SBYTE2 IPIndex);
    ET9PRIVATE SBYTE2 ET9FARCALL SWCIPTable_GetFixedDataSize(SWCIPTable *pThis, BYTE2 searchLevel);
    ET9PRIVATE _SWPoint ET9FARCALL SWCIPTable_GetFixedPoint(SWCIPTable *pThis, SBYTE2 fixedIndex, BYTE2 searchLevel, SBYTE2 callNum);
    ET9PRIVATE SBYTE4 ET9FARCALL SWCIPTable_GetFixedD2Sum(SWCIPTable *pThis, SBYTE2 fixedIndex, BYTE2 searchLevel);
    ET9PRIVATE SBYTE2 ET9FARCALL SWCIPTable_PathExitsKeyboard(SWCIPTable *pThis, SBYTE2 fixedIndex1, SBYTE2 fixedIndex2, SBYTE2 *exitXpos);

    /* Data writing functions */
    ET9PRIVATE void  ET9FARCALL SWCIPTable_deleteIP(SWCIPTable *pThis, SWCIPTableRow *ipData, ET9BOOL removeIP, SBYTE2 callNum);
    ET9PRIVATE ET9BOOL ET9FARCALL SWCIPTable_includeAdjacentIP(SWCIPTableRow *ipDouble, SWCIPTableRow *ipData);
    ET9PRIVATE void  ET9FARCALL SWCIPTable_setDoubleIPFields(SWCIPTableRow *ipDouble, SWCIPTableRow *ipData);
    ET9PRIVATE void  ET9FARCALL SWCIPTable_convertIPtoPauseAngle(SWCIPTableRow *ipData, float adjustmentFactor);
    ET9PRIVATE void  ET9FARCALL SWCIPTable_recordIncludedIP(SWCIPTable *pThis, SWCIPTableRow *ipDouble, SWCIPTableRow *ipData, SBYTE2 callID);
#if DEBUG_IPT
    ET9PRIVATE void  ET9FARCALL SWCIPTable_dumpIPType(SWCIPTable *pThis, SWCIPTableRow *ipData);
    ET9PRIVATE void  ET9FARCALL SWCIPTable_dumpIPs(SWCIPTable *pThis, SWIPTableRowArray * pIPTable, SWIPTableRowArray * pIPTable2, SBYTE2 callNum, SWCIPTableRow *ipData);
#endif
    ET9PRIVATE SBYTE2 ET9FARCALL SWCIPTable_AddIPtoTable2(SWCIPTable *pThis, SWCIPTableRow *ipData);
    ET9PRIVATE SBYTE2 ET9FARCALL SWCIPTable_AddIPtoTable(SWCIPTable *pThis, SWCIPTableRow *ipData);
    ET9PRIVATE SWCIPTableRow* ET9FARCALL SWCIPTable_NewIPTableRow(SWCIPTable *pThis, _SWPoint IPLocation, IPType IPKind, SBYTE2 wIPIndex, BYTE4 dwTimeOffset,
                        SBYTE2 wFixedIndexIn, SBYTE2 wFixedIndexOut, SBYTE2 debugDataVal, ET9BOOL checkForPathDivision);
    ET9PRIVATE SWCIPTableRow* ET9FARCALL SWCIPTable_ObtainIPTableRow(SWCIPTable *pThis, _SWPoint IPLocation, IPType IPKind, SBYTE2 wIPIndex, BYTE4 dwTimeOffset,
                        SBYTE2 wFixedIndexIn, SBYTE2 wFixedIndexOut, SBYTE2 debugDataVal);
    ET9PRIVATE ET9BOOL ET9FARCALL SWCIPTable_PointsInSameRow(SWCIPTable *pThis, SBYTE2 *y1, SBYTE2 y2, SBYTE2 margin, ET9BOOL setY1);
    ET9PRIVATE SBYTE2 ET9FARCALL SWCIPTable_CheckMultipleIPsSequence(SWCIPTable *pThis, SBYTE2 checkIPIndex);
    ET9PRIVATE void  ET9FARCALL SWCIPTable_SetIPDistances1(SWCIPTable *pThis, SWCIPTableRow *ipData);
    ET9PRIVATE BYTE2 ET9FARCALL SWCIPTable_SetIPDistance8(SWCIPTable *pThis, SWCIPTableRow *ipData, SWCIPTableRow *ipData0, SWCIPTableRow *ipData2, BYTE1 keyIndex, BYTE2 searchLevel);
    ET9PRIVATE void  ET9FARCALL SWCIPTable_SetSegDistances(SWCIPTable *pThis, SWCIPTableRow *ipData0, SWCIPTableRow *ipData1, BYTE2 searchLevel);
    ET9PRIVATE void  ET9FARCALL SWCIPTable_SetSegmentDistance8(SWCIPTable *pThis, SWCIPTableRow *ipData0, SWCIPTableRow *ipData1, BYTE1 keyIndex, BYTE2 searchLevel);

    ET9PRIVATE void  ET9FARCALL SWCIPTable_DoProcessTableRows(SWCIPTable *pThis);                   /* SearchDB, essentially. Find words in the dictionary, etc, etc. Was the code executed in the separate IPTable thread. */

    /* IP Table data item processor */
    ET9PRIVATE void  ET9FARCALL SWCIPTable_ProcessIPTableRow(SWCIPTable *pThis, SBYTE2 IPIndex);

    /* Show results on screen */
    ET9BOOL ET9FARCALL SWCIPTable_RenderData(SWCIPTable *pThis, ET9BOOL showPath);

    ET9PRIVATE void ET9FARCALL SWCIPTable_SetActualPathLength(SWCIPTable *pThis, BYTE2 value) {
        pThis->m_actualPathLength = value;
    }

    ET9PRIVATE BYTE2 ET9FARCALL SWCIPTable_GetActualPathLength(const SWCIPTable *pThis) {
        return pThis->m_actualPathLength;
    }

    ET9PRIVATE SBYTE2 ET9FARCALL SWCIPTable_GetDoubleIPCount(const SWCIPTable *pThis) {
        return pThis->m_wDoubleIPCount;
    }

    ET9PRIVATE void ET9FARCALL SWCIPTable_SetShiftAll(SWCIPTable *pThis, ET9BOOL value) {
        pThis->m_ShiftAll = value;
        pThis->m_backend->pContext->__SPATH_Status.bHasAllCapsGesture = value;
    }

    ET9PRIVATE void ET9FARCALL SWCIPTable_SetPenUpDoubleIPIndex(SWCIPTable *pThis, SBYTE2 value) {
        pThis->m_penUpDoubleIPIndex = value;
    }

/* End don't mangle the function name if compile under C++ */
#if defined(__cplusplus)
    }
#endif

#endif



/* eof */
