home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / PEN / PENTKT / UTIL / PENCAL / ALIGN.C next >
C/C++ Source or Header  |  1995-04-14  |  25KB  |  795 lines

  1. /*DDK*************************************************************************/
  2. /*                                                                           */
  3. /* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
  4. /*                                                                           */
  5. /*    The following IBM OS/2 WARP source code is provided to you solely for  */
  6. /*    the purpose of assisting you in your development of OS/2 WARP device   */
  7. /*    drivers. You may use this code in accordance with the IBM License      */
  8. /*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
  9. /*    Copyright statement may not be removed.                                */
  10. /*                                                                           */
  11. /*****************************************************************************/
  12. /***************************************************************************\
  13.  *
  14.  *  alignment
  15.  *
  16. \***************************************************************************/
  17.  
  18. #define INCL_DOSFILEMGR   /* File Manager values */
  19. #define INCL_DOSDEVICES   /* Device values */
  20. #define INCL_DOSSEMAPHORES
  21. #include <os2.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <limits.h>
  26. #include "penei.h"
  27. #include "penioctl.h"
  28. #include "cal.h"
  29.  
  30. #define FILE_SIZE   0L
  31. #define EABUF 0L
  32. #define MAX_SAMPLE_SIZE 100
  33. #define MIN_SAMPLE_SIZE 10
  34. #define MIN_THRESHOLD   2
  35. #define THRESH_DIV      1000;
  36. //#define SAMPLE_RATE_DIV 2;
  37.   #define SAMPLE_RATE_DIV 4;   //each sample is 1/4 a second
  38. #define BEEP_TONE 300
  39. #define BEEP_TIME 75
  40. #define FAST_TIMEOUT 500
  41. #define SLOW_TIMEOUT 2500
  42.  
  43. #define ALIGN_START 1
  44. #define ALIGN_CANCEL 2
  45. #define ALIGN_TERMINATE 3
  46.  
  47. extern char IOName[];
  48. #ifdef DEBUG
  49. extern BOOL  dbfile;
  50. extern FILE  *stream;
  51. #endif
  52. extern BOOL  yinvert;
  53. extern char _DriverName[];
  54. extern char _DeviceName[];
  55.  
  56. LONG  thresX,thresY;
  57. LONG  sampleSize;
  58. APIRET  rc;
  59. HFILE IOHandle;
  60. LCAP lcap;
  61. SLUSD slusd;
  62. SLUSD slusdOrg;
  63. LONG penUnit = 1;
  64. HEV  hev;
  65. LONG alignCmd;
  66. BOOL abortAlign;
  67. LONG scrX,scrY,iconX,iconY,diconX,diconY;
  68. LONG meaX,meaY,orgX,orgY;
  69. LONG wrtQuery(SLUSD * slusd);
  70. LONG wrtSet(SLUSD * slusd);
  71. LONG getSLUSD(LCAP * lcap,SLUSD * slusd);
  72. LONG setSLUSD(LCAP * lcap,SLUSD * slusd);
  73. #ifdef DEBUG
  74. LONG savSLUSD(LCAP * lcap,SLUSD * slusd);
  75. #endif
  76.  
  77. void doAlignment (void *arg);
  78. BOOL inbounds(LONG x,LONG y,TARGETAREA * ptargetarea);
  79. LONG collectSample (LONG size,LONG * paveX,LONG * paveY,
  80.                     TARGETAREA * ptargetarea);
  81. LONG getcoord(LONG * pX,LONG * pY,TARGETAREA * ptargetarea);
  82. LONG doIO  (ULONG category, ULONG function,
  83.              PVOID pParams, LONG pcbParmLen,
  84.              PVOID pData, LONG pcbDataLen);
  85. #ifdef DEBUG
  86. void dumpTA (TARGETAREA * ptargetarea);
  87. void dumpArray(char * ptext,LONG num,LONG array[],LONG limit);
  88. #endif
  89.  
  90. APIRET APIENTRY WrtIQueryDeviceDriverName(PSZ     pszDriverName,
  91.                                           PSZ     pszDDName);
  92.  
  93. //***************************************************************************** */
  94. //
  95. // T H E S E   R O U T I N E S   A R E   C A L L E D   F R O M   T H E
  96. //         F R O M   T H E   W I N D O W   P R O C E D U R E
  97. //
  98. //***************************************************************************** */
  99.  
  100. //-----------------------------------------------------------------------------
  101. // Called once per window life to initialize access to the device
  102. //-----------------------------------------------------------------------------
  103. LONG AlignInit(LONG lscrX, LONG lscrY,LONG liconX,LONG liconY)
  104. {
  105.    ULONG Action;
  106.    PQUC  pquc;
  107.    LONG  rc;
  108.    LONG  cnt;
  109.    UCHAR numberUnits;
  110.    DDCAP ddcap;
  111.  
  112.    iconX  = liconX;
  113.    iconY  = liconY;
  114.    scrX   = lscrX;
  115.    scrY   = lscrY;
  116. #ifdef DEBUG
  117.    if (dbfile) fprintf(stream,"screen scrX=%d scrY=%d icon X=%d icon y=%d\n",
  118.                        scrX,scrY,iconX,iconY);
  119. #endif
  120.  
  121. // find the device driver
  122.  
  123.     rc=WrtIQueryDeviceDriverName(_DriverName,&(IOName[5]));
  124. #ifdef DEBUG
  125.     if (rc != 0) {
  126.         if (dbfile) fprintf(stream,"WrtIQueryDDName return code = %d\n", rc);
  127.         return(rc);
  128.     }
  129. #endif
  130.  
  131. // do the open
  132.  
  133. #ifdef DEBUG
  134.    if (dbfile) fprintf(stream,"driver=%s\n",IOName);
  135. #endif
  136.    Action = 2;
  137.    rc = DosOpen(IOName,                     /* File path name */
  138.                 &IOHandle,                  /* File handle */
  139.                 &Action,                    /* Action taken */
  140.                 FILE_SIZE,                  /* File primary allocation */
  141.                 FILE_NORMAL,                /* File attribute */
  142.                 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
  143.                 OPEN_SHARE_DENYNONE |       /* Open mode of the file */
  144.                 OPEN_ACCESS_READWRITE,
  145.                 EABUF);                     /* No extended attributes */
  146.  
  147.    if (rc != 0) {
  148. #ifdef DEBUG
  149.        if (dbfile) fprintf(stream,"Cannot open device driver\n");
  150.        if (dbfile) fprintf(stream,"DOSOPEN return code = %d\n", rc);
  151. #endif
  152.        return(rc);
  153.    }
  154.  
  155. // find the first locator device by name
  156.  
  157.    pquc.unit  = 0;
  158.    pquc.byteCount = sizeof(LCAP);
  159.    rc=doIO(PEN_CAT_DRIVER,PEN_FUNC_QUC,
  160.           &pquc, sizeof(PQUC),
  161.           &ddcap, sizeof(DDCAP));
  162.    if (rc) return (rc);
  163.    numberUnits=ddcap.unitCount;
  164. #ifdef DEBUG
  165.    if (dbfile) fprintf(stream,"number of units=%d\n",numberUnits);
  166. #endif
  167.  
  168.    for (penUnit=1; penUnit<numberUnits;penUnit++) {
  169.       pquc.unit  = penUnit;
  170.       rc=doIO(PEN_CAT_DRIVER,PEN_FUNC_QUC,
  171.               &pquc, sizeof(PQUC),
  172.               &lcap, sizeof(LCAP));
  173.       if (rc) return rc;
  174.       if (lcap.ccap.device_type==DT_LOCATOR) {
  175.          // find the last non-blank character, then terminate string
  176.          for (cnt=1;cnt<SIZEOF_DEVICE_NAME&&lcap.ccap.device_name[cnt];cnt++);
  177.          for (cnt--;cnt>0&&lcap.ccap.device_name[cnt]==' ';cnt--);
  178.          lcap.ccap.device_name[cnt+1]=0;
  179.          if (!stricmp(_DeviceName,lcap.ccap.device_name)) {
  180.             rc = -1;
  181.             break;
  182.          }
  183.       }
  184.    } /* endfor */
  185.    if (rc==0) {
  186. #ifdef DEBUG
  187.       if (dbfile) fprintf(stream,"device not found\n");
  188. #endif
  189.       return 1;
  190.    }
  191. #ifdef DEBUG
  192.    else {
  193.       if (dbfile) fprintf(stream,"unit number = %d\n",penUnit);
  194.    }
  195. #endif
  196.  
  197. // calculate limits based on device capabilities
  198.  
  199. #ifdef DEBUG
  200.    if (dbfile) fprintf(stream,"sampleRate=%d xExent=%d yExent=%d ",
  201.        lcap.sample_rate,lcap.dev_x_extent,lcap.dev_y_extent);
  202. #endif
  203.    diconX=(iconX*lcap.dev_x_extent)/scrX;
  204.    diconY=(iconX*lcap.dev_y_extent)/scrY;
  205. #ifdef DEBUG
  206.    if (dbfile) fprintf(stream,"dicon X=%d dicon y=%d\n",
  207.                        diconX,diconY);
  208. #endif
  209.    sampleSize=lcap.sample_rate/SAMPLE_RATE_DIV;
  210.    if (sampleSize<MIN_SAMPLE_SIZE) sampleSize=MIN_SAMPLE_SIZE;
  211.    if (sampleSize>MAX_SAMPLE_SIZE) sampleSize=MAX_SAMPLE_SIZE;
  212.  
  213.  
  214.    thresX=lcap.dev_x_extent/THRESH_DIV;
  215.    if (thresX<MIN_THRESHOLD) thresX=MIN_THRESHOLD;
  216.  
  217.    thresY=lcap.dev_y_extent/THRESH_DIV;
  218.    if (thresY<MIN_THRESHOLD) thresY=MIN_THRESHOLD;
  219. #ifdef DEBUG
  220.    if (dbfile) fprintf(stream,"sampleSize=%d thresX=%d thresY=%d\n",
  221.                        sampleSize,thresX,thresY);
  222. #endif
  223.  
  224. // get the command semaphore set up
  225.  
  226.    rc=DosCreateEventSem(0,&hev,0L,0L);
  227.    if (rc != 0) {
  228. #ifdef DEBUG
  229.        if (dbfile) fprintf(stream,"DosCreateEventSem rc=%d\n", rc);
  230. #endif
  231.        return(rc);
  232.    }
  233.  
  234. // get the standard locator unit specific data (SLUSD) incase of cancel to
  235. // restore to entry values
  236.  
  237.    rc = wrtQuery(&slusd);
  238.    if (rc != 0) {
  239. #ifdef DEBUG
  240.        if (dbfile) fprintf(stream,"wrtQuery rc=%d\n", rc);
  241. #endif
  242.        return(rc);
  243.    }
  244.    slusdOrg=slusd;      // save incase of cancel
  245.  
  246.    rc = getSLUSD( &lcap, &slusd );
  247.    if ( rc != 0 ) {
  248. #ifdef DEBUG
  249.       if ( dbfile ) fprintf( stream, "getSLUSD rc = %d\n", rc );
  250. #endif
  251.       return( rc );
  252.     }
  253. // start the alignment thread
  254.  
  255.    rc = _beginthread(doAlignment,NULL,8192,NULL);
  256.    if (rc == -1) {
  257. #ifdef DEBUG
  258.        if (dbfile) fprintf(stream,"beginthread rc=%d\n", rc);
  259. #endif
  260.        return(rc);
  261.    }
  262.  
  263.    return 0;
  264. }
  265.  
  266. //-----------------------------------------------------------------------------
  267. // Signal the background thread to do an alignment
  268. //-----------------------------------------------------------------------------
  269. void AlignStart(void)
  270. {
  271. #ifdef DEBUG
  272.    if (dbfile) fprintf(stream,"****** S T A R T ******************\n");
  273. #endif
  274.    alignCmd=ALIGN_START;
  275.    DosPostEventSem(hev);
  276. }
  277.  
  278. //-----------------------------------------------------------------------------
  279. // Sinal the background thread stop alignment and wait for next command
  280. //-----------------------------------------------------------------------------
  281. void AlignStop(void)
  282. {
  283. #ifdef DEBUG
  284.    if (dbfile) fprintf(stream,"****** S T O P ********************\n");
  285. #endif
  286.    alignCmd=ALIGN_CANCEL;
  287.    abortAlign=TRUE;
  288.    DosPostEventSem(hev);
  289. }
  290.  
  291. //-----------------------------------------------------------------------------
  292. // Cancel and restore original settings
  293. //-----------------------------------------------------------------------------
  294. void AlignCancel(void)
  295. {
  296. #ifdef DEBUG
  297.    if (dbfile) fprintf(stream,"****** C A N C E L ****************\n");
  298. #endif
  299.    rc = setSLUSD(&lcap,&slusdOrg);
  300. #ifdef DEBUG
  301.    if (rc != 0) {
  302.        if (dbfile) fprintf(stream,"setSLUSD rc=%d\n", rc);
  303.    }
  304. #endif
  305. }
  306.  
  307. //-----------------------------------------------------------------------------
  308. // Set up shipped defaults
  309. //-----------------------------------------------------------------------------
  310. void AlignDefaults(void)
  311. {
  312. #ifdef DEBUG
  313.    if (dbfile) fprintf(stream,"****** D E F A U L T S ************\n");
  314. #endif
  315.    slusd.Xorigin=slusd.XoriginDefault;
  316.    slusd.XmeasuredExtent=lcap.dev_x_extent;
  317.    slusd.Yorigin=slusd.YoriginDefault;
  318.    slusd.YmeasuredExtent=lcap.dev_y_extent;
  319.    rc = setSLUSD(&lcap,&slusd);
  320. #ifdef DEBUG
  321.    if (rc != 0) {
  322.        if (dbfile) fprintf(stream,"setSLUSD rc=%d\n", rc);
  323.    }
  324. #endif
  325. }
  326.  
  327. //-----------------------------------------------------------------------------
  328. // Save these setting to be persistent
  329. //-----------------------------------------------------------------------------
  330. void AlignCommit(void)
  331. {
  332. #ifdef DEBUG
  333.    if (dbfile) fprintf(stream,"****** C O M M I T ****************\n");
  334. #endif
  335.    rc = wrtSet(&slusd);
  336. #ifdef DEBUG
  337.    if (rc != 0) {
  338.        if (dbfile) fprintf(stream,"wrtSet rc=%d\n", rc);
  339.    }
  340.    savSLUSD(&lcap,&slusd);   //for debug file
  341. #endif
  342. }
  343.  
  344. //-----------------------------------------------------------------------------
  345. // Called once at end of window life
  346. //-----------------------------------------------------------------------------
  347. void AlignTerminate(void)
  348. {
  349. #ifdef DEBUG
  350.    if (dbfile) fprintf(stream,"****** T E R M I N A T E **********\n");
  351. #endif
  352.    alignCmd=ALIGN_TERMINATE;
  353.    DosPostEventSem(hev);
  354.    DosClose(IOHandle);
  355. }
  356.  
  357. //***************************************************************************** */
  358. //
  359. // T H E S E   R O U T I N E S   E X E C U T E  U N D E R  T H E
  360. //             B A C K   G R O U N D   T H R E A D
  361. //
  362. //***************************************************************************** */
  363.  
  364. //-----------------------------------------------------------------------------
  365. // B A C K G R O U N D   T H R E A D   M A I N   L O O P
  366. //-----------------------------------------------------------------------------
  367. // Background thread waits for commands
  368. //  - Drive window proc and do an alignment
  369. //  - Canel out of alignment and wait for next command
  370. //  - Terminate background thread
  371. //-----------------------------------------------------------------------------
  372. void doAlignment (void *arg)
  373. {
  374.    TARGETAREA Stargetarea;
  375.    TARGETAREA Dtargetarea;
  376.    ULONG postCount;
  377.    LONG  x,y;
  378.    APIRET  rc;
  379.    LONG  getrc;
  380.    LONG  aveXlow,aveYlow,aveXhigh,aveYhigh,tempY;
  381.    LONG  meaX,meaY,orgX,orgY;
  382.  
  383. // wait for command to continue
  384.  
  385.    do {
  386.  
  387.       rc=DosWaitEventSem(hev,SEM_INDEFINITE_WAIT);
  388.       if (rc != 0) {
  389. #ifdef DEBUG
  390.           if (dbfile) fprintf(stream,"$$DosWaitEventSem rc=%d\n", rc);
  391. #endif
  392.           return;
  393.       }
  394.       rc=DosResetEventSem(hev,&postCount);
  395.       if (rc != 0) {
  396. #ifdef DEBUG
  397.           if (dbfile) fprintf(stream,"$$DosResetEventSem rc=%d\n", rc);
  398. #endif
  399.           return;
  400.  
  401.       }
  402.  
  403.       if (alignCmd == ALIGN_START) {
  404.  
  405.          abortAlign=FALSE;
  406.          aveXlow=aveYlow=aveXhigh=aveYhigh=0;
  407.  
  408. // UPPER LEFT
  409.  
  410.          Stargetarea.xlow=0;
  411.          Stargetarea.xcen=iconX/2;
  412.          Stargetarea.xhigh=iconX;
  413.          Stargetarea.ylow=scrY-iconY;
  414.          Stargetarea.ycen=Stargetarea.ylow+iconY/2;
  415.          Stargetarea.yhigh=scrY;
  416.          notifyPM (PAINT_TARGET,&Stargetarea);
  417.          Dtargetarea.xlow=0;
  418.          Dtargetarea.xcen=diconX/2;
  419.          Dtargetarea.xhigh=diconX;
  420.          if (yinvert) {
  421.             Dtargetarea.ylow=lcap.dev_y_extent-diconY;
  422.             Dtargetarea.ycen=Dtargetarea.ylow+diconY/2;
  423.             Dtargetarea.yhigh=lcap.dev_y_extent;
  424.          } else {
  425.             Dtargetarea.ylow=0;
  426.             Dtargetarea.ycen=diconY/2;
  427.             Dtargetarea.yhigh=diconY;
  428.          } /* endif */
  429.          getrc=getcoord(&x,&y,&Dtargetarea);
  430.          if (getrc) continue;
  431.          aveXlow+=x;
  432.          aveYlow+=y;
  433.          DosBeep(BEEP_TONE,BEEP_TIME);
  434.  
  435. // UPPER RIGHT
  436.  
  437.          Stargetarea.xlow=scrX-iconX;
  438.          Stargetarea.xcen=Stargetarea.xlow+iconX/2;
  439.          Stargetarea.xhigh=scrX;
  440.          Stargetarea.ylow=scrY-iconY;
  441.          Stargetarea.ycen=Stargetarea.ylow+iconY/2;
  442.          Stargetarea.yhigh=scrY;
  443.          notifyPM (PAINT_TARGET,&Stargetarea);
  444.          Dtargetarea.xlow=lcap.dev_x_extent-diconX;
  445.          Dtargetarea.xcen=Dtargetarea.xlow+diconX/2;
  446.          Dtargetarea.xhigh=lcap.dev_x_extent;
  447.          if (yinvert) {
  448.             Dtargetarea.ylow=lcap.dev_y_extent-diconY;
  449.             Dtargetarea.ycen=Dtargetarea.ylow+diconY/2;
  450.             Dtargetarea.yhigh=lcap.dev_y_extent;
  451.          } else {
  452.             Dtargetarea.ylow=0;
  453.             Dtargetarea.ycen=diconY/2;
  454.             Dtargetarea.yhigh=diconY;
  455.          } /* endif */
  456.          getrc=getcoord(&x,&y,&Dtargetarea);
  457.          if (getrc) continue;
  458.          aveXhigh+=x;
  459.          aveYlow +=y;
  460.          DosBeep(BEEP_TONE,BEEP_TIME);
  461.  
  462. // LOWER RIGHT
  463.  
  464.          Stargetarea.xlow=scrX-iconX;
  465.          Stargetarea.xcen=Stargetarea.xlow+iconX/2;
  466.          Stargetarea.xhigh=scrX;
  467.          Stargetarea.ylow=0;
  468.          Stargetarea.ycen=iconY/2;
  469.          Stargetarea.yhigh=iconY;
  470.          notifyPM (PAINT_TARGET,&Stargetarea);
  471.          Dtargetarea.xlow=lcap.dev_x_extent-diconX;
  472.          Dtargetarea.xcen=Dtargetarea.xlow+diconX/2;
  473.          Dtargetarea.xhigh=lcap.dev_x_extent;
  474.          if (yinvert) {
  475.             Dtargetarea.ylow=0;
  476.             Dtargetarea.ycen=diconY/2;
  477.             Dtargetarea.yhigh=diconY;
  478.          } else {
  479.             Dtargetarea.ylow=lcap.dev_y_extent-diconY;
  480.             Dtargetarea.ycen=Dtargetarea.ylow+diconY/2;
  481.             Dtargetarea.yhigh=lcap.dev_y_extent;
  482.          } /* endif */
  483.          getrc=getcoord(&x,&y,&Dtargetarea);
  484.          if (getrc) continue;
  485.          aveXhigh+=x;
  486.          aveYhigh+=y;
  487.          DosBeep(BEEP_TONE,BEEP_TIME);
  488.  
  489. // LOWER LEFT
  490.  
  491.          Stargetarea.xlow=0;
  492.          Stargetarea.xcen=iconX/2;
  493.          Stargetarea.xhigh=iconX;
  494.          Stargetarea.ylow=0;
  495.          Stargetarea.ycen=iconY/2;
  496.          Stargetarea.yhigh=iconY;
  497.          notifyPM (PAINT_TARGET,&Stargetarea);
  498.          Dtargetarea.xlow=0;
  499.          Dtargetarea.xcen=diconX/2;
  500.          Dtargetarea.xhigh=diconX;
  501.          if (yinvert) {
  502.             Dtargetarea.ylow=0;
  503.             Dtargetarea.ycen=diconY/2;
  504.             Dtargetarea.yhigh=diconY;
  505.          } else {
  506.             Dtargetarea.ylow=lcap.dev_y_extent-diconY;
  507.             Dtargetarea.ycen=Dtargetarea.ylow+diconY/2;
  508.             Dtargetarea.yhigh=lcap.dev_y_extent;
  509.          } /* endif */
  510.          getrc=getcoord(&x,&y,&Dtargetarea);
  511.          if (getrc) continue;
  512.          aveXlow +=x;
  513.          aveYhigh+=y;
  514.          DosBeep(BEEP_TONE,BEEP_TIME);
  515.  
  516. // calculate adjustment - extrapolate measured extents
  517.  
  518. #ifdef DEBUG
  519.          if (dbfile) fprintf(stream,"$$**** C A L C U L A T E **********\n");
  520. #endif
  521.          aveXlow/=2;aveXhigh/=2;aveYlow/=2;aveYhigh/=2;
  522.  
  523.          if (yinvert) {
  524.            tempY   = aveYlow;
  525.            aveYlow = aveYhigh;
  526.            aveYhigh= tempY;
  527.          } /* endif */
  528.  
  529. #ifdef DEBUG
  530.          if (dbfile) fprintf(stream,"$$actual ave pts x=%d %d y=%d %d\n",
  531.                      aveXlow,aveXhigh,aveYlow,aveYhigh);
  532. #endif
  533.          meaX=(lcap.dev_x_extent*(aveXhigh-aveXlow))/(lcap.dev_x_extent-diconX);
  534.          meaY=(lcap.dev_y_extent*(aveYhigh-aveYlow))/(lcap.dev_y_extent-diconY);
  535. #ifdef DEBUG
  536.          if (dbfile) fprintf(stream,"$$extraplated measured extents x=%d y=%d\n",
  537.                              meaX,meaY);
  538. #endif
  539.  
  540. // calculate origin adjustment
  541.  
  542.          aveXlow = (aveXlow * lcap.dev_x_extent)/meaX;
  543.          aveXhigh= (aveXhigh* lcap.dev_x_extent)/meaX;
  544.          aveYlow = (aveYlow * lcap.dev_y_extent)/meaY;
  545.          aveYhigh= (aveYhigh* lcap.dev_y_extent)/meaY;
  546. #ifdef DEBUG
  547.          if (dbfile) fprintf(stream,"$$scaled ave pts x=%d %d y=%d %d\n",
  548.                      aveXlow,aveXhigh,aveYlow,aveYhigh);
  549. #endif
  550.          orgX = ((LONG)lcap.dev_x_extent-aveXhigh-aveXlow)/2;
  551.          orgY = ((LONG)lcap.dev_y_extent-aveYhigh-aveYlow)/2;
  552. #ifdef DEBUG
  553.          if (dbfile) fprintf(stream,"$$origin adjustment x=%d y=%d \n",
  554.                      orgX,orgY);
  555. #endif
  556.          slusd.Xorigin=orgX;
  557.          slusd.XmeasuredExtent=meaX;
  558.          slusd.Yorigin=orgY;
  559.          slusd.YmeasuredExtent=meaY;
  560.          rc = setSLUSD(&lcap,&slusd);
  561. #ifdef DEBUG
  562.          if (rc != 0) {
  563.              if (dbfile) fprintf(stream,"$$setSLUSD rc=%d\n", rc);
  564.          }
  565. #endif
  566.  
  567. // complete
  568.  
  569.          notifyPM (ALIGNMENT_DONE,NULL);
  570.  
  571.       } /* endif */
  572.  
  573.    } while (alignCmd != ALIGN_TERMINATE); /* enddo */
  574.  
  575. #ifdef DEBUG
  576.    if (dbfile) fprintf(stream,"$$ thread terminating\n");
  577. #endif
  578.    rc=DosCloseEventSem(hev);
  579. #ifdef DEBUG
  580.    if (rc != 0) {
  581.        if (dbfile) fprintf(stream,"$$DosCloseEventSem rc=%d\n", rc);
  582.        return;
  583.    }
  584. #endif
  585. }
  586.  
  587. //-----------------------------------------------------------------------------
  588. // check if point is in the bounds of the target structure
  589. //-----------------------------------------------------------------------------
  590. BOOL inbounds(LONG x,LONG y,TARGETAREA * ptargetarea)
  591. {
  592.    x += (LONG) slusd.Xorigin;
  593.    y += (LONG) slusd.Yorigin;
  594. #ifdef DEBUG
  595.    if (dbfile) fprintf(stream,"$$X=%d Y=%d \n", x,y); for debugging
  596.    if (dbfile) dumpTA (ptargetarea);
  597. #endif
  598.  
  599. // check out x
  600.  
  601.    if (ptargetarea->xlow==0) {
  602.       if (x>ptargetarea->xhigh) {
  603.          return(FALSE);
  604.       } /* endif */
  605.    } else {
  606.       if (x<ptargetarea->xlow) {
  607.          return(FALSE);
  608.       } /* endif */
  609.    } /* endif */
  610.  
  611. // check out y
  612.  
  613.    if (ptargetarea->ylow==0) {
  614.       if (y>ptargetarea->yhigh) {
  615.          return(FALSE);
  616.       } /* endif */
  617.    } else {
  618.       if (y<ptargetarea->ylow) {
  619.          return(FALSE);
  620.       } /* endif */
  621.    } /* endif */
  622.  
  623.    return(TRUE);
  624.  
  625. }
  626.  
  627. //-----------------------------------------------------------------------------
  628. // collect a sample point by averageing points in a collection array
  629. //-----------------------------------------------------------------------------
  630. LONG collectSample (LONG size,LONG * paveX,LONG * paveY,
  631.                     TARGETAREA * ptargetarea)
  632. {
  633.    LONG xarray[MAX_SAMPLE_SIZE];
  634.    LONG yarray[MAX_SAMPLE_SIZE];
  635.    int  i;
  636.    LONG temp;
  637.    PQLRC pqlrc;
  638.    DQLRC dqlrc;
  639.    LONG  rc;
  640.    BOOL  stat;
  641.  
  642.    pqlrc.unit = penUnit;
  643.    if (size>MAX_SAMPLE_SIZE) size=MAX_SAMPLE_SIZE; // protect ourselves
  644.  
  645. // collect points
  646.  
  647.    pqlrc.timeout = SLOW_TIMEOUT;
  648.    do {
  649.       for (i=0; i<size; i++) {
  650.          rc=doIO(PEN_CAT_LOCATOR,PEN_FUNC_QLRC,
  651.                  &pqlrc, sizeof(PQLRC),
  652.                  &dqlrc, sizeof(DQLRC));
  653.          if (rc) return rc;
  654.          if (abortAlign) return 1;
  655.          xarray[i]= dqlrc.xRaw;
  656.          yarray[i]= dqlrc.yRaw;
  657.          if (dqlrc.rc != QLRC_VALID) {
  658. #ifdef DEBUG
  659.          if (dbfile) fprintf(stream,"$$ !!! VALID !!!\n"); //for debug
  660. #endif
  661.             pqlrc.timeout = SLOW_TIMEOUT; //slow down again
  662. #ifdef DEBUG
  663.          dumpArray("timX=",dqlrc.rc,xarray,i+1);
  664.          dumpArray("timY ",dqlrc.rc,yarray,i+1);
  665. #endif
  666.             break;
  667.          } /* endif */
  668.          stat = inbounds(dqlrc.xRaw,dqlrc.yRaw,ptargetarea);
  669.          if (!stat) {
  670. #ifdef DEBUG
  671.             if (dbfile) fprintf(stream,"$$ !!! NOT IN BOUNDS !!!\n"); //for debug
  672. #endif
  673.             pqlrc.timeout = SLOW_TIMEOUT;    //slow down again
  674. #ifdef DEBUG
  675.             dumpArray("bndX=",stat,xarray,i+1);
  676.             dumpArray("bndY ",stat,yarray,i+1);
  677. #endif
  678.             break;
  679.          } /* endif */
  680.          pqlrc.timeout = FAST_TIMEOUT;          // don't wait so long
  681.       }
  682.    } while (i<size); /* enddo */
  683.  
  684. // calculate average
  685.  
  686.    for (temp=0,i=0; i<size; i++) temp+=xarray[i];
  687.    *paveX=temp/size;
  688.    for (temp=0,i=0; i<size; i++) temp+=yarray[i];
  689.    *paveY=temp/size;
  690.  
  691. #ifdef DEBUG
  692.    dumpArray("aveX=",*paveX,xarray,size);
  693.    dumpArray("aveY ",*paveY,yarray,size);
  694. #endif
  695.  
  696.    return 0;
  697. }
  698.  
  699. //-----------------------------------------------------------------------------
  700. // compare samples until reports settle down
  701. //-----------------------------------------------------------------------------
  702. LONG getcoord(LONG * pX,LONG * pY,TARGETAREA * ptargetarea)
  703. {
  704.    LONG aveX,aveY,lastaveX,lastaveY,lastaveX2,lastaveY2;
  705.    LONG xbound,ybound;
  706.  
  707. #ifdef DEBUG
  708.    if (dbfile) fprintf(stream,"$$***** G E T C O O R D ***********\n");
  709.    if (dbfile) dumpTA (ptargetarea);
  710. #endif
  711.  
  712. // collect samples until the result settles within the threshold
  713.  
  714.    aveX=aveY=lastaveX=lastaveY=-1;
  715.    do {
  716.       lastaveX2=lastaveX;lastaveY2=lastaveY;
  717.       lastaveX=aveX;lastaveY=aveY;
  718.       rc = collectSample (sampleSize,&aveX,&aveY,ptargetarea);
  719.       if (rc) return rc;
  720.  
  721. // this check makes sure the last three samples are close enough
  722. // }  while ((abs(lastaveX-aveX)>thresX)||(abs(lastaveY-aveY)>thresY)||
  723. //           (abs(lastaveX2-aveX)>thresX)||(abs(lastaveY2-aveY)>thresY) );
  724.  
  725. // this check makes sure the last two   samples are close enough. This is
  726. // alot quicker, but could be less accurate
  727.    }  while ((abs(lastaveX-aveX)>thresX)||(abs(lastaveY-aveY)>thresY) );
  728.  
  729. #ifdef DEBUG
  730.    if (dbfile) fprintf(stream,"$$x=%d y=%d\n",aveX,aveY);
  731. #endif
  732.    *pX=aveX;*pY=aveY;
  733. #ifdef DEBUG
  734.    if (dbfile) fprintf(stream,"$$RETURN FROM GETCOORD\n");
  735. #endif
  736.    return 0;
  737. }
  738.  
  739. //***************************************************************************** */
  740. //  S U P P O R T   R O U T I N E S
  741. //***************************************************************************** */
  742.  
  743. //-----------------------------------------------------------------------------
  744. // Issue IOCTL to device driver
  745. //-----------------------------------------------------------------------------
  746. LONG doIO  (ULONG category, ULONG function,
  747.              PVOID pParams, LONG pcbParmLen,
  748.              PVOID pData, LONG pcbDataLen)
  749. {
  750.    ULONG   ParmLengthInOut;
  751.    ULONG   DataLengthInOut;
  752.    APIRET  rc;
  753.  
  754.    ParmLengthInOut = pcbParmLen;
  755.    DataLengthInOut = pcbDataLen;
  756.    rc = DosDevIOCtl(IOHandle, category, function,
  757.                     pParams, pcbParmLen,&ParmLengthInOut,
  758.                     pData, pcbDataLen,&DataLengthInOut);
  759. #ifdef DEBUG
  760.    if (rc != 0)
  761.    {
  762.        if (dbfile) fprintf(stream,"IOCTL failed, return code = %d\n", (SHORT)rc);
  763.    }
  764. #endif
  765.    return(rc);
  766. }
  767.  
  768. #ifdef DEBUG
  769. //-----------------------------------------------------------------------------
  770. // debug dump of the target area structure
  771. //-----------------------------------------------------------------------------
  772. void dumpTA (TARGETAREA * ptargetarea)
  773. {
  774.    if (dbfile) {
  775.       fprintf(stream,"$$xlow=%d xcen=%d xhigh=%d ylow=%d ycen=%d yhigh=%d\n",
  776.               ptargetarea->xlow,ptargetarea->xcen,ptargetarea->xhigh,
  777.               ptargetarea->ylow,ptargetarea->ycen,ptargetarea->yhigh);
  778.    } /* endif */
  779. }
  780.  
  781. //-----------------------------------------------------------------------------
  782. // debug dump of collected points in a point collection arrary
  783. //-----------------------------------------------------------------------------
  784. void dumpArray(char * ptext,LONG num,LONG array[],LONG limit)
  785. {
  786.    int  i;
  787.  
  788.    if (dbfile) {
  789.       fprintf(stream,"$$%s%d",ptext,num);
  790.       for (i=0; i < limit; i++) fprintf(stream," %d",array[i]);
  791.       fprintf(stream,"\n");
  792.    } /* endif */
  793. }
  794. #endif
  795.