home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / database / datamage.zip / CODE.ZIP / MAGEISAM.C < prev    next >
C/C++ Source or Header  |  1991-09-24  |  88KB  |  4,317 lines

  1. /*****************************************************************************
  2. *                                                                            *
  3. *   I can but assume that you are a better C programmer than my humble       *
  4. *   self.  I have had no formal training in this language, but have          *
  5. *   taught it to myself by doing it.                                         *
  6. *                                                                            *
  7. *   The DATAMAGE ISAM is, at the very least, unique.  You are looking for    *
  8. *   something VERY complex and hard to understand.  What you will find is    *
  9. *   the epitome of simplicity.                                               *
  10. *                                                                            *
  11. *   DATAMAGE makes use of the real facility offered by a computer: SPEED.    *
  12. *   This raw material is harnessed to the work of data management system     *
  13. *   through the application of BRUTE FORCE COMPUTING.                        *
  14. *                                                                            *
  15. *   If properly applied, BRUTE FORCE can have benifits.  In this case they   *
  16. *   are low overhead and speed.  DATAMAGE indexes up to five string fields   *
  17. *   in only ten bytes per record.  Since there's less of it "out there" to   *
  18. *   pick through we can get at it faster.                                    *
  19. *                                                                            *
  20. *   To pick up on the DATAMAGE ISAM look the sample program: MAGEDEMO.C      *
  21. *   over.  It uses a few of the functions in the library and calls many      *
  22. *   of the functions in the core library as well.                            *
  23. *                                                                            *
  24. *   All the functions have a comment line to describe their use.  The vars   *
  25. *   passed are named descriptively.   The code is sparsly documented.  I     *
  26. *   didn't plan to release it; there would be more comments if I did.        *
  27. *                                                                            *
  28. *   Like I said in the HCWP_LIB.C file:  NO attempt has been made to be      *
  29. *   "cute" with the code.  Rather, I have attempted to write it so that      *
  30. *   those new to C might have a chance to understand it.                     *
  31. *                                                                            *
  32. *****************************************************************************/
  33.  
  34. #include <dos.h>
  35. #include <math.h>
  36. #include <malloc.h>
  37. #include <stdio.h>
  38. #include <string.h>
  39. #include <stdlib.h>
  40.  
  41. #include "c:\qc\pf\hcwp_lib.h"
  42.  
  43. BYTE readf,             /*  flag for necessity of getting files from disk  */
  44.      pth_str [81],      /*  holds current path  */
  45.     r_buff [256],      /*  small buffer - misc tasks  */
  46.     f_buff [10241],    /*  large buffer - read/write records  */
  47.     files_loaded;      /*  number DATAMAGE files currently open  */
  48.  
  49. SWORD ftot [2];
  50.  
  51. typedef struct                     /* structure holding field definitions */
  52.     {
  53.     BYTE   name [27];            /* name of field */
  54.     BYTE   type;                 /* 0=date 1=string 2=numeric 3=dollar */
  55.     BYTE   length;               /* length of field */
  56.     BYTE   spare;                /* explained below */
  57.     BYTE   abs;                  /* absolute field number */
  58.     WORD   offset;               /* offset of field in record */
  59.     } fdef;
  60.  
  61. /*  definition of fdef.spare:
  62.  
  63. switch (fdef.type)
  64.     {
  65.     case 0: defines date field format: 0=mm/dd/yy 1=dd/mm/yy
  66.     case 1: defines index mode for string: 0=none 1=unique 2=normal 3=cross
  67.     case 2: defines number of decimals to maintain in numeric field
  68.     case 3: always 2, defines precision of dollar format field
  69.     }  */
  70.  
  71. typedef struct                    /* structure holding loaded datafiles */
  72.     {
  73.     /*  NOMINCLATURE  */
  74.  
  75.     BYTE dir [51];               /* directory name holding file */
  76.     BYTE des [41];               /* description of loaded file  */
  77.  
  78.     /*  NUMERIC DATA  */
  79.  
  80.     DWORD rcd_len;               /* length of record in bytes */
  81.     WORD num_rcds;               /* number of records in file */
  82.     WORD num_flds;               /* number of fields in file  */
  83.  
  84.     /*  array of far pointers to type fdef (defined above)  */
  85.  
  86.     fdef far * key [200];
  87.  
  88.     /*  data relating to idnexes and searches of same  */
  89.  
  90.     BYTE indexes;                /* holds number of indexed fields  */
  91.     BYTE indexed_fields [5];     /* holds numbers of indexed fields  */
  92.  
  93.     BYTE unique_field;           /* 1 = unique fields 2=no  */
  94.  
  95.     BYTE cross_fields;           /* number of cross-indexed fields  */
  96.     BYTE cross_cntr;             /* number of cross-indexed fields selected  */
  97.  
  98.     BYTE write_sw;               /* 0=no write to file, 1=write record  */
  99.     DWORD rw_sw;                 /* 0=not ready for read
  100.                               1=ready after (row * 7800) + col */
  101.  
  102.     BYTE  i_case [5];            /*  1=ignore case/spacing in search 0=no */
  103.     SWORD index_results [5];     /*  holds index of record being checked  */
  104.     SWORD disk_index    [5];     /*  holds indexs read fron disk - buffer  */
  105.  
  106.     /*  LOAD INFORMATION  */
  107.  
  108.     WORD sequence;               /* file sequence# of record in buffer  */
  109.     WORD next_rcd;               /* sequence of next record             */
  110.     WORD r_number;               /* record number of record in buffer   */
  111.  
  112.     BYTE m_name [53];            /* main datafile path/filename      */
  113.     BYTE i_name [53];            /* index file path/filename         */
  114.     BYTE c_name [53];            /* control file path/filename       */
  115.  
  116.     /*  FILE POINTERS TO THE THREE ASSOCIATED FILES  */
  117.  
  118.     FILE * main;                 /* pointer for main datafile buffer */
  119.     FILE * indx;                 /* pointer for index file buffer    */
  120.     FILE * ctrl;                 /* pointer for control file buffer  */
  121.  
  122.     /*  MARKER FILE INFORMATION  */
  123.  
  124.     BYTE mkr_active;             /* 0=process file, 1=process marker */
  125.  
  126.     FILE * marker;               /* pointer for marker file buffer   */
  127.  
  128.     WORD m_num_rcds;             /* holds number of records in mkr   */
  129.  
  130.     WORD m_next_rcd;             /* holds next record seq in marker  */
  131.  
  132.     BYTE m_rcd_len;             /* holds record length in marker    */
  133.  
  134.     BYTE b_levels;                /* holds number of search levels    */
  135.  
  136.     SBYTE bs_sw;                /*  binary search switch
  137.                                     -10 = inactive
  138.                                    -2  = search counter 2
  139.                                    -1  = search counter 1
  140.                                      0  = search record numbers
  141.                                      1  = search disk data        */
  142.  
  143.     BYTE asf [8] [3];            /*  holds details of current binary order
  144.  
  145.                                pos 0 = target field + 1
  146.  
  147.                                pos 1 = format:
  148.                                        1 = nromal
  149.                                        2 = name
  150.                                        3 = string as numeric
  151.  
  152.                                pos 2 = ignore case/spacing
  153.                                         (not recorded - user selected)
  154.                                        0 = no, 1 = yes         */
  155.  
  156.     BYTE counter_sw;             /*  0= no counters in marker,
  157.                                       1= counter 1 in marker,
  158.                                   2= counter 2 in marker,
  159.                                   3= both  */
  160.  
  161.     SBYTE c1_sw;                 /*  -1= counter is inactive,
  162.                                 0-8=decimal precision,
  163.                                9=no rounding  */
  164.  
  165.     double c1_val;                /*  value of counter 1, if any  */
  166.  
  167.     SBYTE c2_sw;                 /*  as above  */
  168.  
  169.     double c2_val;                /*  value of counter 2, if any  */
  170.  
  171.     /*  BUFFER  */
  172.  
  173.     BYTE far * buff;             /* buffer for this file */
  174.     } file_info;
  175.  
  176. file_info fi [8];                 /*  change the 8 to your max open files */
  177.  
  178. typedef struct                   /* structure holding data for display */
  179.     {
  180.     BYTE r_val;                 /* holds return value if selected */
  181.     BYTE disp [65];             /* holds string to be displayed */
  182.     BYTE rtrn [65];             /* holds string to be returned */
  183.     } w_data;
  184.  
  185. w_data far window_data [200];
  186.  
  187. typedef struct                    /* structure holding files found */
  188.     {
  189.     BYTE name  [13];             /* holds name of dir or file */
  190.     BYTE desc  [37];             /* holds description of file */
  191.     }files_found;
  192.  
  193. files_found far files [2] [50];
  194.  
  195. /*  FUNCTIONS INCLUDED IN THIS MODULE  */
  196.  
  197.     void           far decoder         ();
  198.     SWORD          far index_field     (BYTE * target);
  199.  
  200.     void           far set_field       (BYTE, BYTE, BYTE, BYTE *);
  201.     void           far get_field       (BYTE, WORD, BYTE, BYTE *);
  202.     BYTE           far read_field      (BYTE, WORD, WORD, BYTE *);
  203.     BYTE           far write_field     (BYTE, WORD, WORD, BYTE *);
  204.  
  205.     BYTE           far index_MAGErecord (BYTE);
  206.     BYTE           far find_MAGErecord  (BYTE, WORD, BYTE, WORD);
  207.     BYTE           far find_MAGErecord_nmbr (BYTE, WORD);
  208.     BYTE           far access_MAGE_record  (BYTE, BYTE, BYTE);
  209.  
  210.     BYTE           far write_MAGErcd   (BYTE);
  211.     BYTE           far read_MAGErcd    (BYTE, WORD);
  212.     BYTE         far read_next_rcd     (BYTE, BYTE *);
  213.  
  214.     void           far print_MAGE_record (BYTE file);
  215.  
  216.     BYTE           far search_MAGE_files (BYTE, BYTE);
  217.     BYTE           far vs_MAGE_recrd   (BYTE, BYTE, BYTE *);
  218.  
  219.     BYTE           far get_files       (BYTE *, BYTE);
  220.     BYTE           far select_datafile ();
  221.  
  222.     BYTE           far open_file       (BYTE);
  223.     void           far close_file      (BYTE);
  224.     BYTE           far condit_open     (BYTE, BYTE, BYTE *);
  225.  
  226.     BYTE           far ready_files     (SBYTE);
  227.     BYTE           far get_next_rno    (BYTE);
  228.  
  229.     BYTE           far show_files      (BYTE);
  230.     BYTE           far show_datafiles  (BYTE);
  231.     BYTE           far show_fields     (BYTE, BYTE);
  232.     BYTE           far show_menu       ();
  233.  
  234.     void           far fill_window     (BYTE, SWORD *, SWORD *, BYTE);
  235.     BYTE           far work_window     (BYTE, SWORD *, SWORD *, BYTE);
  236.     void           far window_line     (BYTE, BYTE, BYTE, BYTE);
  237.  
  238.     SWORD         far get_curr_fno     (BYTE file, WORD field);
  239.  
  240.     BYTE         far get_cntr         (BYTE, BYTE, double *, BYTE *);
  241.     BYTE         far load_marker    (BYTE, BYTE *);
  242.  
  243.     WORD         far minpt         (BYTE, BYTE, BYTE *);
  244.  
  245.  
  246.     /*  local functions  */
  247.  
  248.     void         a_menu             (BYTE, BYTE);
  249.     void         a_line             (BYTE, WORD, WORD, BYTE *);
  250.     void         new_a_screen         (BYTE, SWORD, BYTE *);
  251.     void           field_line          (BYTE, WORD);
  252.  
  253. /*-------------------------------------------------------------------------*/
  254.  
  255. SWORD far get_curr_fno (BYTE file, WORD field)
  256.     {
  257. /*    returns the current field number of an absolute field  */
  258.  
  259.     SWORD d = 0;
  260.  
  261.     SWORD ret_val = -1;
  262.  
  263.     if (fi [file].key [field] -> abs == field) return (field);
  264.  
  265.     while (d < fi [file].num_flds && ret_val == -1)
  266.         {
  267.         if (fi [file].key [d] -> abs == field) ret_val = d;
  268.  
  269.         d++;
  270.         }
  271.  
  272.     return (ret_val);
  273.     }
  274.  
  275. void far decoder ()
  276.     {
  277. /*  provides ignoring of case, spacing and double chars for index searches  */
  278.  
  279.     BYTE d, m, chr, last_chr = 0, len;
  280.  
  281.     len = strlen (c_s [0]);
  282.  
  283.     for (d = 0, m = 0; m < len; m++)
  284.         {
  285.         chr = c_s [0] [m];
  286.  
  287.         if (chr > 96 && chr < 123) chr -= 32;
  288.  
  289.         if (m && chr == last_chr) continue;
  290.  
  291.         if ( (chr > 64 && chr < 91) ||
  292.             (chr > 47 && chr < 58) )
  293.              c_s [1] [d++] = chr;
  294.  
  295.         last_chr = chr;
  296.         }
  297.  
  298.     c_s [1] [d] = 0;
  299.     /*  printf ("\n%s\n%s\n", c_s [0], c_s [1]);  */
  300.     }
  301.  
  302. void far set_field (BYTE file, BYTE field, BYTE nmbr, BYTE * source)
  303.     {
  304. /*  sets field into file buffer  */
  305.  
  306.     BYTE register d;
  307.  
  308.     BYTE far * target;
  309.  
  310.     target = fi [file].buff + fi [file].key [field] -> offset;
  311.  
  312.     for (d = 0; d < nmbr && d < fi [file].key [field] -> length;)
  313.          * (target + d++) = * (source + d);
  314.     }
  315.  
  316. void far get_field (BYTE file, WORD field, BYTE nmbr, BYTE * target)
  317.     {
  318. /*  gets field from file buffer  */
  319.  
  320.     BYTE register d;
  321.  
  322.     BYTE far * source;
  323.  
  324.     source = fi [file].buff + fi [file].key [field] -> offset;
  325.  
  326.     for (d = 0; d < nmbr && d < fi [file].key [field] -> length;)
  327.          * (target + d++) = * (source + d);
  328.  
  329.     if (fi [file].key [field] -> type < 2) * (target + d) = 0;
  330.     }
  331.  
  332. BYTE far read_field (BYTE file, WORD sequence, WORD fieldno, BYTE * target)
  333.     {
  334. /*  reads field from DATAMAGE file, FILE MUST BE OPEN!!  */
  335.  
  336.     BYTE c;
  337.  
  338.     DWORD offset;
  339.  
  340.     offset = (fi [file].rcd_len * sequence) +
  341.             fi [file].key  [fieldno] -> offset;
  342.  
  343.     if (offset > (DWORD) fi [file].rcd_len * fi [file].num_rcds) return (1);
  344.  
  345.     c = fseek (fi [file].main, offset, SEEK_SET);
  346.  
  347.     fread (target, 1, fi [file].key [fieldno] -> length, fi [file].main);
  348.  
  349.     if (fi [file].key  [fieldno] -> type < 2)
  350.         target [fi [file].key [fieldno] -> length] = 0;
  351.  
  352.     return (0);
  353.     }
  354.  
  355. BYTE far write_field (BYTE file, WORD sequence, WORD fieldno, BYTE * target)
  356.     {
  357. /*  writes field into DATAMAGE file, FILE MUST BE OPEN!!  */
  358.  
  359.     BYTE c, d, len;
  360.  
  361.     DWORD offset;
  362.  
  363.     len = fi [file].key [fieldno] -> length;
  364.  
  365.     offset = (fi [file].rcd_len * sequence) +
  366.             fi [file].key [fieldno] -> offset;
  367.  
  368.     if (offset > (DWORD) fi [file].num_rcds * fi [file].rcd_len) return (1);
  369.  
  370.     for (d = 0; d < 40; d++) r_buff [d] = 32;
  371.  
  372.     for (d = 0; d < len && d < 35;) r_buff [d++] = target [d];
  373.  
  374.     c = fseek (fi [file].main, offset, SEEK_SET);
  375.     fwrite( (void *) r_buff, len, 1, fi [file].main);
  376.  
  377.     return (0);
  378.     }
  379.  
  380. SWORD far index_field (BYTE * target)
  381.     {
  382. /*  returns DATAMAGE index of targeted field  */
  383.  
  384.     BYTE b, len, m, y, z, err = 0;
  385.  
  386.     SWORD x = -32768;
  387.  
  388.     SDWORD check;
  389.  
  390.     len = strlen (target);
  391.  
  392.     for (b = 0; b < len; b++)
  393.         {
  394.         /*  char to index  */
  395.  
  396.         y = target [b];
  397.  
  398.         m = y; z = b + 1;
  399.  
  400.         /*  emulate BASIC's MOD function  */
  401.  
  402.         while (m >= z) m -= z;
  403.  
  404.         check = x;
  405.  
  406.         if (! m) check += y;
  407.         else check += (y + z) * m;
  408.  
  409.         if (check > 32767) x = 0;
  410.  
  411.         if (! m) x += y;
  412.         else x += (y + z) * m;
  413.         }
  414.  
  415.     return (x);
  416.     }
  417.  
  418. BYTE far index_MAGErecord (BYTE file)
  419.     {
  420. /*   indexes record in buffer of file passed,
  421.     results in fi [file].index_results []  */
  422.  
  423.     BYTE a, b, c, d, e, j;
  424.  
  425.     for (d = 0; d < 5; d++) fi [file].index_results [d] = -32768;
  426.  
  427.     fi [file].cross_cntr = 0; c = 0; e = 0;
  428.  
  429.     for (a = 0; a < fi [file].indexes; a++)
  430.         {
  431.         j = fi [file].indexed_fields [a];
  432.  
  433.         get_field (file, j, fi [file].key [j] -> length, c_s [0]);
  434.  
  435.         /*  remove trailing spaces  */
  436.  
  437.         rtrim (c_s [0]);
  438.  
  439.         /*  decode index string  */
  440.  
  441.         decoder ();
  442.  
  443.         /*  place index and string into search area  */
  444.  
  445.         fi [file].index_results [a] = index_field (c_s [1]);
  446.  
  447.         if (fi [file].i_case [a]) strcpy (gp_str [a], c_s [1]);
  448.  
  449.         else strcpy (gp_str [a], c_s [0]);
  450.  
  451.         /*  increment cross conter for screen check  */
  452.  
  453.         if (fi [file].key [j] -> spare == 3) fi [file].cross_cntr += 1;
  454.  
  455.         /*  set unique switch for screen check  */
  456.  
  457.         if (fi [file].key [j] -> spare == 1) e = 1;
  458.  
  459.         /*  end search of linklist if all keys found  */
  460.  
  461.         c++;
  462.  
  463.         if (c == fi [file].indexes) a = fi [file].indexes;
  464.         }
  465.  
  466.     if ( (fi [file].unique_field && ! e) &&
  467.         (fi [file].cross_fields &&
  468.          b < fi [file].cross_fields) )
  469.          return (1);
  470.  
  471.     else return (0);
  472.     }
  473.  
  474. /*  search types:
  475.  
  476. 0=all indexes, check new record
  477.  
  478. 1=all unique indexes, find a record
  479.  
  480. 2=all non-unique indexes, find records
  481.  
  482. 3=all corss indexes, find a record
  483.  
  484. type two search DOES NOT absolutely identify the record found!
  485.  
  486. returns:
  487.  
  488. 0=yeah, I found it
  489.  
  490. 1=no match found
  491.  
  492. setting search type to > 0 will cause function to read record
  493. into targeted file buffer
  494.  
  495. */
  496.  
  497. BYTE far find_MAGErecord (BYTE file, WORD start,
  498.                      BYTE search_type, WORD unique_field)
  499.     {
  500.     BYTE a, b, c, close_sw [3], m, wfg = 0;
  501.  
  502.     SBYTE g;
  503.  
  504.     SWORD i, x;
  505.  
  506.     DWORD offset = 0;
  507.  
  508.     for (c = 0; c < 3; c++) close_sw [c] = 0;
  509.  
  510.     if (search_type == 2)
  511.         {
  512.         for (m = 0, a = 0; a < fi [file].indexes; a++)
  513.             if (fi [file].index_results [a] > -32768) m++;
  514.  
  515.         if (! m) return (1);
  516.         }
  517.  
  518.     else m = fi [file].cross_fields;
  519.  
  520.     /*  open ctrl file  */
  521.  
  522.     c = condit_open (file, 3, "rb");
  523.  
  524.     switch (c)
  525.         {
  526.         case 0:
  527.             {
  528.             fseek (fi [file].ctrl, (DWORD) 0, SEEK_SET);
  529.  
  530.             break;
  531.             }
  532.  
  533.         case 1: {close_sw [2] = 1; break;}
  534.  
  535.         case 2: return (1);
  536.         }
  537.  
  538.     /*  open index file  */
  539.  
  540.     c = condit_open (file, 2, "rb");
  541.  
  542.     switch (c)
  543.         {
  544.         case 0: break;
  545.  
  546.         case 1:
  547.             {
  548.             close_sw [1] = 1;
  549.             break;
  550.             }
  551.  
  552.         case 2: return (1);
  553.         }
  554.  
  555.  
  556.     /*  open main file  */
  557.  
  558.     c = condit_open (file, 1, "rb");
  559.  
  560.     switch (c)
  561.         {
  562.         case 0: break;
  563.  
  564.         case 1: {close_sw [0] = 1; break;}
  565.  
  566.         case 2: return (1);
  567.         }
  568.  
  569.     for (i = start; ! wfg && i <= fi [file].num_rcds; i++)
  570.         {
  571.         /*  don't check blank rcd  */
  572.  
  573.         fread (& x, 2, 1, fi [file].ctrl);
  574.  
  575.         if (! x) continue;
  576.  
  577.         /*  don't check current rcd in search type 0 */
  578.  
  579.         if (! search_type && i == fi [file].sequence) continue;
  580.  
  581.         /*  read index data  */
  582.  
  583.         fseek (fi [file].indx, (DWORD) i * 10, SEEK_SET);
  584.         fread (fi [file].disk_index, 10, 1, fi [file].indx);
  585.  
  586.         b = 0;  /*  check indexes  */
  587.  
  588.         for (a = 0; ! wfg && a < fi [file].indexes; a++)
  589.             {
  590.             /*  determine field # of index to check  */
  591.  
  592.             c = fi [file].indexed_fields [a];
  593.  
  594.             /*  skip indexes according to search_type  */
  595.  
  596.             if (search_type && search_type != 2 &&
  597.                 fi [file].key [c] -> spare != search_type) continue;
  598.  
  599.             if ( (search_type == 1) &&
  600.                ( (unique_field && c != unique_field) || (! unique_field
  601.                 && fi [file].index_results [a] == -32768) ) ) continue;
  602.  
  603.             /*  skip blank indexes for type 2 check  */
  604.  
  605.             if (search_type == 2 && fi [file].index_results [a] == -32768)
  606.                 continue;
  607.  
  608.             /*  skip non-unique index for new record check  */
  609.  
  610.             if (! search_type && fi [file].key [c] -> spare == 2) continue;
  611.  
  612.             /*  compare index values  */
  613.  
  614. /*
  615.             locate (0,0); prnt ("         ");
  616.             locate (0,0); printf ("%hi", fi [file].index_results [a]);
  617.  
  618.             locate (0,40); prnt ("         ");
  619.             locate (0,40); printf ("%hi", fi [file].disk_index [a]);
  620.  
  621.             wait (1);
  622. */
  623.  
  624.             if (fi [file].index_results [a] !=
  625.                 fi [file].disk_index [a]) continue;
  626.  
  627.             /*  get indexed field from disk  */
  628.  
  629.             read_field (file, i, c, c_s [0]);
  630.  
  631.             /*  remove trailing spaces  */
  632.  
  633.             rtrim (c_s [0]);
  634.  
  635.             /*  decode disk string if ignoring case */
  636.  
  637.             if (fi [file].i_case [a]) decoder ();
  638.  
  639.             else strcpy (c_s [1], c_s [0]);
  640.  
  641.             /*  compare disk string to entry  */
  642.  
  643. /*
  644.             locate (0,0); prnt (c_s [1]); prnt ("*");
  645.             locate (0,40); prnt (gp_str [a]); prnt ("*");
  646. */
  647.  
  648.             g = strcmp (c_s [1], gp_str [a]);
  649.  
  650.             if (g == 0)  /*  match found  */
  651.                 {
  652.                 switch (search_type)
  653.                     {
  654.                     case 0:  /*  dup record check  */
  655.                         {
  656.                         /*  unique match */
  657.  
  658.                         if (fi [file].key  [c] -> spare == 1)
  659.                             {wfg = 1; a = 5;}
  660.  
  661.                         /*  cross  match */
  662.  
  663.                         if (fi [file].key [c] -> spare == 3
  664.                             && ++b >= m) {wfg = 1; a = 5;}
  665.  
  666.                         break;
  667.                         }
  668.  
  669.  
  670.                     case 1:  /*  unique  */
  671.                         {
  672.                         wfg = 1; a = 5;
  673.                         break;
  674.                         }
  675.  
  676.                     case 2:  /*  non-unique  */
  677.                     case 3:  /*  cross       */
  678.                         {
  679.                         if (++b >= m) {wfg = 1; a = 5;}
  680.  
  681.                         break;
  682.                         }
  683.  
  684.                     }
  685.  
  686.  
  687.                 }
  688.  
  689.             }
  690.  
  691.         }
  692.  
  693.     if (close_sw [1]) {fclose (fi [file].indx); fi [file].indx = NULL;}
  694.  
  695.     if (wfg && search_type)  /*  read record in  */
  696.         {
  697.         offset = fi [file].rcd_len * --i;
  698.  
  699.         c = fseek ( fi [file].main, offset, SEEK_SET);
  700.         fread ( (void *) f_buff, fi [file].rcd_len, 1, fi [file].main);
  701.  
  702.         set_far (fi [file].buff, f_buff, fi [file].rcd_len);
  703.  
  704.         fi [file].sequence = i;
  705.  
  706.         c = fseek (fi [file].ctrl, (DWORD) fi [file].sequence * 2, SEEK_SET);
  707.  
  708.         fread (& x, 2, 1, fi [file].ctrl);
  709.  
  710.         fi [file].r_number = x;
  711.         }
  712.  
  713.     if (close_sw [2]) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
  714.     if (close_sw [0]) {fclose (fi [file].main); fi [file].main = NULL;}
  715.  
  716.     if (wfg) return (0);
  717.     return (1);
  718.  
  719. fmr_abort:
  720.  
  721.     if (close_sw [2]) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
  722.     if (close_sw [1]) {fclose (fi [file].indx); fi [file].indx = NULL;}
  723.     if (close_sw [0]) {fclose (fi [file].main); fi [file].main = NULL;}
  724.  
  725.     return (2);
  726.     }
  727.  
  728. BYTE far find_MAGErecord_nmbr (BYTE file, WORD search_val)
  729.     {
  730. /*  finds DATAMAGE record via user-assigned number  */
  731.  
  732.     BYTE c, wfg = 0;
  733.  
  734.     WORD close_sw = 0, f = 0, i = 0, x = 0;
  735.  
  736.     SWORD rno;
  737.  
  738.     DWORD offset = 0;
  739.  
  740.     /*  open control file  */
  741.  
  742.     c = condit_open (file, 3, "r+b");
  743.  
  744.     switch (c)
  745.         {
  746.         case 0:
  747.             {
  748.             fseek (fi [file].ctrl, (DWORD) 0, SEEK_SET);
  749.  
  750.             break;
  751.             }
  752.  
  753.         case 1:
  754.             {
  755.             close_sw = 1;
  756.             break;
  757.             }
  758.  
  759.         case 2: return (1);
  760.         }
  761.  
  762.     /*  search control file  */
  763.  
  764.     while (i <= fi [file].num_rcds && ! wfg)
  765.         {
  766.         fread (& rno, 2, 1, fi [file].ctrl);
  767.  
  768.         if (rno == search_val) {wfg = 1; x = i;}
  769.         i ++;
  770.         }
  771.  
  772.     if (close_sw) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
  773.  
  774.     /*  return 1 if not found  */
  775.  
  776.     if (! wfg) return (1);
  777.  
  778.     /*  open main file  */
  779.  
  780.     c = condit_open (file, 1, "r+b"); close_sw = 0;
  781.  
  782.     switch (c)
  783.         {
  784.         case 0: break;
  785.  
  786.         case 1: {close_sw = 1; break;}
  787.  
  788.         case 2: return (1);
  789.         }
  790.  
  791.     /*  compute offset of record found  */
  792.  
  793.     offset = fi [file].rcd_len * x;
  794.  
  795.     /*  read record in  */
  796.  
  797.     c = fseek (fi [file].main, offset, SEEK_SET);
  798.     fread ( (void *) f_buff, fi [file].rcd_len, 1, fi [file].main);
  799.  
  800.  
  801.     set_far (fi [file].buff, f_buff, fi [file].rcd_len);
  802.  
  803.     /*  place sequence/record number of record found  */
  804.  
  805.     fi [file].sequence = x;
  806.     fi [file].r_number = search_val;
  807.  
  808.     /* a-tha, a-tha, a-that's all, kiddies */
  809.  
  810.     if (close_sw) {fclose (fi [file].main); fi [file].main = NULL;}
  811.  
  812.     return (0);
  813.     }
  814.  
  815. BYTE far search_MAGE_files (BYTE file, BYTE enty_point)
  816.     {
  817. /*   searches indexes in any DATAMAGE file, provides input, too  */
  818.  
  819.     BYTE a, b, c, c_e = 0, choice, d, f, ftsw = 0, line = 3,
  820.         search_type, wfg = 0, wfg2 = 0, search [5] [251];
  821.  
  822.     WORD start = 0, x;
  823.  
  824.     double fl;
  825.  
  826.     if (! fi [file].indexes) return (1);
  827.  
  828.     if (enty_point) goto search_indexes;
  829.  
  830. get_mode:
  831.  
  832.     strcpy (prompts [0], "SEARCH ON:");
  833.  
  834.     strcpy (prompts [1], "1=RECORD NUMBERS");
  835.     strcpy (prompts [2], "2=FILE INDEXES");
  836.     strcpy (prompts [3], "3=ABORT");
  837.  
  838.     choice = get_v_choice (3, 0, 0);
  839.  
  840.     if (choice == 3) return (1);
  841.  
  842.     if (choice == 1)
  843.         {
  844.         clw (3); locate (22,21);
  845.         prnt ("ENTER TARGET RECORD NUMBER: ");
  846.  
  847.         a = inpt (2, 5, 1, 0, 0, 32, user_enty);
  848.         if (! a) {beep(); goto get_mode;}
  849.  
  850.         fl = atof (user_enty);
  851.  
  852.         if (fl < 1 || fl > 32000)
  853.             {
  854.             clw (3); locate (22,19);
  855.             prnt ("LEGAL RECORD NUMBERS ARE FROM 1 TO 32,000");
  856.             wait (4); goto get_mode;
  857.             }
  858.  
  859.         x = fl;
  860.  
  861.         c = find_MAGErecord_nmbr (file, x);
  862.  
  863.         if (c)
  864.             {
  865.             clw (3); beep(); locate (22, 28);
  866.             prnt ("THAT NUMBER WAS NOT FOUND!");
  867.             wait (4); goto get_mode;
  868.             }
  869.  
  870.         return (0);
  871.         }
  872.  
  873. search_indexes:
  874.  
  875.     for (d = 0; d < 5; d++) fi [file].index_results [d] = -32768;
  876.  
  877.     ready_files (file);
  878.  
  879.     clw (2); search_type = 1;
  880.  
  881.     while (! wfg)
  882.         {
  883.         for (d = 0; d < fi [file].indexes && ! wfg; d++)
  884.             {
  885.             c = fi [file].indexed_fields [d];
  886.  
  887.             b = fi [file].key [c] -> length;
  888.  
  889.             if (fi [file].key [c] -> spare != search_type) continue;
  890.  
  891.             locate (line, 7);
  892.  
  893.             f_prnt (fi [file].key [c] -> name);
  894.  
  895.             if (ftsw) strcpy (user_enty, search [d]);
  896.             else user_enty [0] = 0;
  897.  
  898.             field_line (file, c);
  899.  
  900.             f = cntrstrp ();
  901.  
  902.             clw (3); locate (22, f); prnt (c_s [2]);
  903.  
  904.             locate (line, 40); line += 2;
  905.  
  906.             a = minpt (file, c, user_enty);
  907.  
  908.             if (! a)
  909.                 {
  910.                 search [d] [0] = 0;
  911.  
  912.                 continue;
  913.                 }
  914.  
  915.             strcpy (search [d], user_enty);
  916.  
  917.             strcpy (prompts [0], "CASE/SPACING OPTIONS:");
  918.  
  919.             strcpy (prompts [1], "1=IGNORE");
  920.             strcpy (prompts [2], "2=MATCH");
  921.  
  922.             choice = get_v_choice (2, 0, 0) - 1;
  923.  
  924.             if (choice) fi [file].i_case [d] = 0;
  925.             else fi [file].i_case [d] = 1;
  926.  
  927.             /*  remove trailing spaces, place in file buffer  */
  928.  
  929.             rtrim (user_enty);
  930.             set_field (file, c, b, user_enty);
  931.  
  932.             /*  decode index string  */
  933.  
  934.             strcpy (c_s [0], user_enty);
  935.  
  936.             decoder ();
  937.  
  938.             /*  place index value and string into search area  */
  939.  
  940.             fi [file].index_results [d] = index_field (c_s [1]);
  941.  
  942.             if (fi [file].i_case [d]) strcpy (gp_str [d], c_s [1]);
  943.  
  944.             else strcpy (gp_str [d], c_s [0]);
  945.  
  946.             switch (search_type)
  947.                 {
  948.                 case 1:  {wfg = 1; break;}
  949.  
  950.                 case 2:  break;
  951.  
  952.                 case 3:  {c_e ++; break;}
  953.                 }
  954.  
  955.             }
  956.  
  957.         if (wfg) continue;
  958.  
  959.         switch (search_type)
  960.             {
  961.             case 1:  {search_type = 3; break;}
  962.  
  963.             case 2:  {wfg = 1; break;}
  964.  
  965.             case 3:
  966.                 {
  967.                 if (c_e >= fi [file].cross_fields) {wfg = 1; break;}
  968.                 search_type = 2;
  969.                 }
  970.  
  971.             }
  972.  
  973.         }
  974.  
  975.     switch (search_type)
  976.         {
  977.         case 1:
  978.         case 3:
  979.             {
  980.             c = find_MAGErecord (file, (WORD) 0, search_type, 0);
  981.  
  982.             /*  no match  */
  983.  
  984.             if (c)
  985.                 {
  986.                 strcpy (prompts [0], "NO MATCH FOUND");
  987.  
  988.                 strcpy (prompts [1], "1=RETRY");
  989.                 strcpy (prompts [2], "2=ABORT");
  990.  
  991.                 wfg2 = get_v_choice (2, 0, 0) + 1;
  992.  
  993.                 break;
  994.                 }
  995.  
  996.             /*  read record in  */
  997.  
  998.             read_MAGErcd (file, fi [file].sequence);
  999.  
  1000.             break;
  1001.             }
  1002.  
  1003.         case 2:
  1004.             {
  1005.             clw (2); clw (3);
  1006.             beep(); locate (12, 8);
  1007.             prnt ("YOU WILL HAVE TO SELECT A RECORD FROM MULTIPLE POSSIBLE MATCHES");
  1008.             see_screen ();
  1009.  
  1010.             while (! wfg2)
  1011.                 {
  1012.                 c = find_MAGErecord (file, start, search_type, 0);
  1013.  
  1014.                 if (c)
  1015.                     {
  1016.                     strcpy (prompts [0], "NO MATCH FOUND");
  1017.  
  1018.                     strcpy (prompts [1], "1=RETRY");
  1019.                     strcpy (prompts [2], "2=ABORT");
  1020.  
  1021.                     wfg2 = get_v_choice (2, 0, 0) + 1;
  1022.                     continue;
  1023.                     }
  1024.  
  1025.                 start = fi [file].sequence;
  1026.  
  1027.                 c = access_MAGE_record (file, 0, 1);
  1028.  
  1029.                 strcpy (prompts [0], "SEARCH OPTIONS:");
  1030.  
  1031.                 strcpy (prompts [1], "1=DESIRED RECORD WAS DISPLAYED");
  1032.                 strcpy (prompts [2], "2=CONTINUE SEARCH");
  1033.  
  1034.                 c = get_v_choice (2, 0, 0) - 1;
  1035.  
  1036.                 if (! c) wfg2 = 1;
  1037.                 else start++;
  1038.                 }
  1039.  
  1040.             }
  1041.  
  1042.         }
  1043.  
  1044.     switch (wfg2)
  1045.         {
  1046.         case 0:
  1047.         case 1: return (0);
  1048.  
  1049.         case 2:
  1050.             {
  1051.             wfg = 0; wfg2 = 0; line = 3; c_e = 0;
  1052.             ftsw = 1; start = 0; goto get_mode;
  1053.             }
  1054.  
  1055.         case 3: return (1);
  1056.         }
  1057.  
  1058.     }
  1059.  
  1060. BYTE far ready_files (SBYTE level)
  1061.     {
  1062. /*  wipes a DATAMAGE buffer, pass -1 to prepare ALL open buffers  */
  1063.  
  1064.     BYTE d;
  1065.  
  1066.     WORD i;
  1067.  
  1068.     double zero = 0, msbzero;
  1069.  
  1070.     dieeetomsbin (& zero, & msbzero);
  1071.  
  1072.     for (d = 0; d <= files_loaded; d++)
  1073.         {
  1074.         if (level + 1 && d != level) continue;
  1075.  
  1076.         /*  safety valve  */
  1077.  
  1078.         if (fi [d].buff == NULL) continue;
  1079.  
  1080.         /*  clear file buffer  */
  1081.  
  1082.         for (i = 0; i < fi [d].rcd_len; i++)
  1083.             * (fi [d].buff + i) = 32;
  1084.  
  1085.         /*  set numerics to 0  */
  1086.  
  1087.         for (i = 0; i < fi [d].num_flds; i++)
  1088.  
  1089.             if (fi [d].key [i] ->type > 1)
  1090.                 set_far (fi [d].buff + fi [d].key [i] -> offset,
  1091.                         (BYTE *) & msbzero, 8);
  1092.         }
  1093.  
  1094.     return (0);
  1095.     }
  1096.  
  1097. BYTE far condit_open (BYTE file, BYTE nmbr, BYTE * o_str)
  1098.     {
  1099. /*   opens a file in the fi structure if it's not already open
  1100.     file nmbr:  1=main file  2=index file  3=control file
  1101.     returns:  0=file was open  1=opened file  2=bombed  */
  1102.  
  1103.     BYTE ret_val = 0;
  1104.  
  1105.     switch (nmbr)
  1106.         {
  1107.         case 1:
  1108.             {
  1109.             if (fi [file].main != NULL) break;
  1110.  
  1111.             if ( (fi [file].main = fopen (fi [file].m_name, o_str))
  1112.                 == NULL) ret_val = 2;
  1113.  
  1114.             else ret_val = 1;
  1115.  
  1116.             break;
  1117.             }
  1118.  
  1119.         case 2:
  1120.             {
  1121.             if (fi [file].indx != NULL) break;
  1122.  
  1123.             if ( (fi [file].indx = fopen (fi [file].i_name, o_str))
  1124.                 == NULL) ret_val = 2;
  1125.  
  1126.             else ret_val = 1;
  1127.  
  1128.             break;
  1129.             }
  1130.  
  1131.         case 3:
  1132.             {
  1133.             if (fi [file].ctrl != NULL) break;
  1134.  
  1135.             if ( (fi [file].ctrl = fopen (fi [file].c_name, o_str))
  1136.                 == NULL) ret_val = 2;
  1137.  
  1138.             else ret_val = 1;
  1139.  
  1140.             break;
  1141.             }
  1142.  
  1143.         }
  1144.  
  1145.     return (ret_val);
  1146.     }
  1147.  
  1148. BYTE far write_MAGErcd (BYTE file)
  1149.     {
  1150. /*   writes record in buffer, updates control file (rcd#),
  1151.     writes indexes if any. Call index_MAGErecord to fill index values  */
  1152.  
  1153.     BYTE c, o_type [5], close_sw;
  1154.  
  1155.     SWORD rno = fi [file].r_number;
  1156.  
  1157.     void * buff = & rno;
  1158.  
  1159.     if (fi [file].num_rcds) strcpy (o_type, "rb+");
  1160.     else strcpy (o_type, "wb+");
  1161.  
  1162.     /*  update ctrl file  */
  1163.  
  1164.     c = condit_open (file, 3, o_type); close_sw = 0;
  1165.  
  1166.     switch (c)
  1167.         {
  1168.         case 0: break;
  1169.  
  1170.         case 1: {close_sw = 1; break;}
  1171.  
  1172.         case 2: return (1);
  1173.         }
  1174.  
  1175.     c = fseek (fi [file].ctrl, (DWORD) fi [file].sequence * 2, SEEK_SET);
  1176.  
  1177.     fwrite (buff, 2, 1, fi [file].ctrl);
  1178.  
  1179.     if (close_sw) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
  1180.     else fflush (fi [file].ctrl);
  1181.  
  1182.     /*  update num rcds  */
  1183.  
  1184.     if (fi [file].sequence >= fi [file].num_rcds)
  1185.         fi [file].num_rcds = fi [file].sequence + 1;
  1186.  
  1187.     /*  update main file  */
  1188.  
  1189.     buff = f_buff;
  1190.  
  1191.     c = condit_open (file, 1, o_type); close_sw = 0;
  1192.  
  1193.     switch (c)
  1194.         {
  1195.         case 0: break;
  1196.  
  1197.         case 1: {close_sw = 1; break;}
  1198.  
  1199.         case 2: return (1);
  1200.         }
  1201.  
  1202.     get_far (f_buff, fi [file].buff, fi [file].rcd_len);
  1203.  
  1204.     c = fseek (fi [file].main, (DWORD) fi [file].sequence *
  1205.                         fi [file].rcd_len, SEEK_SET);
  1206.  
  1207.     fwrite (buff, fi [file].rcd_len, 1, fi [file].main);
  1208.  
  1209.     if (close_sw) {fclose (fi [file].main); fi [file].main = NULL;}
  1210.     else fflush (fi [file].main);
  1211.  
  1212.      /*  update index file  */
  1213.  
  1214.     if (fi [file].indexes)
  1215.         {
  1216.         c = condit_open (file, 2, o_type); close_sw = 0;
  1217.  
  1218.         switch (c)
  1219.             {
  1220.             case 0: break;
  1221.  
  1222.             case 1: {close_sw = 1; break;}
  1223.  
  1224.             case 2: return (1);
  1225.             }
  1226.  
  1227.         buff = fi [file].index_results;
  1228.  
  1229.         c = fseek (fi [file].indx,
  1230.                  (DWORD) fi [file].sequence * 10, SEEK_SET);
  1231.  
  1232.         fwrite (buff, 10, 1, fi [file].indx);
  1233.  
  1234.         if (close_sw) {fclose (fi [file].indx); fi [file].indx = NULL;}
  1235.         else fflush (fi [file].indx);
  1236.         }
  1237.  
  1238.     return (0);
  1239.     }
  1240.  
  1241. BYTE far read_MAGErcd (BYTE file, WORD seq)
  1242.     {
  1243. /*  reads DATAMAGE record from disk into fi [file].buff  */
  1244.  
  1245.     BYTE c, close_sw;
  1246.  
  1247.     SWORD rno;
  1248.  
  1249.     /*  open main file  */
  1250.  
  1251.     c = condit_open (file, 1, "r+b"); close_sw = 0;
  1252.  
  1253.     switch (c)
  1254.         {
  1255.         case 0: break;
  1256.  
  1257.         case 1: {close_sw = 1; break;}
  1258.  
  1259.         case 2: return (1);
  1260.         }
  1261.  
  1262.     /*  read main file  */
  1263.  
  1264.     c = fseek (fi [file].main, (DWORD) seq * fi [file].rcd_len, SEEK_SET);
  1265.  
  1266.     fread (f_buff, fi [file].rcd_len, 1, fi [file].main);
  1267.  
  1268.     if (close_sw) {fclose (fi [file].main); fi [file].main = NULL;}
  1269.  
  1270.     set_far (fi [file].buff, f_buff, fi [file].rcd_len);
  1271.  
  1272.     /*  get record number from ctrl file  */
  1273.  
  1274.     fi [file].sequence = seq;
  1275.  
  1276.     c = condit_open (file, 3, "r+b"); close_sw = 0;
  1277.  
  1278.     switch (c)
  1279.         {
  1280.         case 0: break;
  1281.  
  1282.         case 1: {close_sw = 1; break;}
  1283.  
  1284.         case 2: return (1);
  1285.         }
  1286.  
  1287.     c = fseek (fi [file].ctrl, (DWORD) fi [file].sequence * 2, SEEK_SET);
  1288.  
  1289.     fread (& rno, 2, 1, fi [file].ctrl);
  1290.  
  1291.     fi [file].r_number = rno;
  1292.  
  1293.     if (close_sw) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
  1294.  
  1295.     return (0);
  1296.     }
  1297.  
  1298. BYTE far get_next_rno (BYTE file)
  1299.     {
  1300. /*   finds next available record number and file sequence
  1301.     places seq in fi [file].sequence, record # in fi [file].r_number  */
  1302.  
  1303.     BYTE c, close_sw, wfg = 0, choice, a;
  1304.  
  1305.     WORD i = 0, x = 0, y, z = 0;
  1306.  
  1307.     SWORD rno, crno, rno2, bigno = 0, crsq = 0, far * base;
  1308.  
  1309.     SDWORD enty;
  1310.  
  1311.  
  1312. choose1:
  1313.  
  1314.     save_window (2); clw(2);
  1315.     save_window (3); clw(3);
  1316.  
  1317.     strcpy (c_s [0], "RECORD NUMBER IN:");
  1318.     strcpy (c_s [1], fi [file].des);
  1319.     c = cntrstrp ();
  1320.  
  1321.     locate (12, c); prnt (c_s [2]);
  1322.  
  1323.     strcpy (prompts [0], "SELECT MODE:");
  1324.  
  1325.     strcpy (prompts [1], "1=AUTO SELECT");
  1326.     strcpy (prompts [2], "2=KEYBOARD ENTRY");
  1327.  
  1328.     a = get_v_choice(2, 0, 0);
  1329.  
  1330.     repl_window (2); repl_window (3);
  1331.  
  1332.     /*  open control file  */
  1333.  
  1334.     c = condit_open (file, 3, "rb"); close_sw = 0;
  1335.  
  1336.     switch (c)
  1337.         {
  1338.         case 0: break;
  1339.  
  1340.         case 1:
  1341.             {
  1342.             close_sw = 1;
  1343.             break;
  1344.             }
  1345.  
  1346.         case 2: wfg = 1;
  1347.         }
  1348.  
  1349.     c = fseek (fi [file].ctrl, (DWORD) 0, SEEK_SET);
  1350.  
  1351.     if (! fi [file].num_rcds) wfg = 1;
  1352.  
  1353.     if (wfg)
  1354.         {
  1355.         beep();
  1356.  
  1357.         strcpy (prompts [0], "DATAFILE ON DISK HAS NO RECORDS");
  1358.  
  1359.         strcpy (prompts [1], "1=OK");
  1360.         strcpy (prompts [2], "2=ABORT");
  1361.  
  1362.         choice = get_v_choice (2, 0, 0);
  1363.  
  1364.         if (choice == 2) return (wfg);
  1365.         }
  1366.  
  1367.     switch (a)
  1368.         {
  1369.         case 1:
  1370.             {
  1371.             if (wfg) {crno = 1; break;}
  1372.  
  1373.             y = (fi [file].num_rcds * 2) + 10;
  1374.             base = (SWORD far *) _fmalloc (y);
  1375.  
  1376.             if (base == NULL) {mem_fail(); goto get_rnumber;}
  1377.  
  1378.             /*  load record #s into ram, find hole if any  */
  1379.  
  1380.             while (i < fi [file].num_rcds)
  1381.                 {
  1382.                 fread (& rno, 2, 1, fi [file].ctrl);
  1383.  
  1384.                 if (! rno)
  1385.                     {
  1386.                     if (! crsq) crsq = i;
  1387.                     i++; continue;
  1388.                     }
  1389.  
  1390.                 if (rno > bigno) bigno = rno;
  1391.  
  1392.                 * (base + x) = rno; i++; x++;
  1393.                 }
  1394.  
  1395.             if (x) x--;
  1396.  
  1397.             if (! crsq) crsq = fi [file].num_rcds;
  1398. /*
  1399.             cls(); locate (0,0);
  1400.             for (y = 0; y <= x; y ++) printf ("%hu  ", * (base + y));
  1401.             get_one (& nrml_val, & fi [file].ctrl_val);
  1402. */
  1403.             clw(3); locate (22, 15);
  1404.             prnt ("FINDING NEXT AVAILABLE RECORD NUMBER, PLEASE WAIT");
  1405.  
  1406.             /*  sort record numbers  */
  1407.  
  1408.             for (y = 0; y < x; y++)
  1409.                 {
  1410.                 if (* (base + y) <= * (base + y + 1) )
  1411.                     {
  1412.                     if (z) {y = z; z = 0;}
  1413.                     continue;
  1414.                     }
  1415.  
  1416.                 if (! z) z = y;
  1417.  
  1418.                 rno = * (base + y); rno2 = y + 1;
  1419.                 * (base + y) = * (base + rno2);
  1420.                 * (base + rno2) = rno;
  1421.  
  1422.                 if (y) y-= 2;
  1423.                 }
  1424.  
  1425. /*
  1426.             cls(); locate (0,0);
  1427.             for (y = 0; y <= x; y++) printf ("%hu  ", * (base + y));
  1428.             get_one (& nrml_val, & ctrl_val);
  1429. */
  1430.  
  1431.             /*  check sorted rcd #s for missing #  */
  1432.  
  1433.             y = 0; crno = 0; i = 1;
  1434.  
  1435.             while (y < x && ! crno)
  1436.                 {
  1437.                 if (* (base + y) != i) crno = i;
  1438.                 y++; i++;
  1439.                 }
  1440.  
  1441.             if (! crno) crno = bigno + 1;
  1442.  
  1443.             _ffree (base);
  1444.  
  1445.             break;
  1446.             }
  1447.  
  1448.         case 2:
  1449.             {
  1450.  
  1451. get_rnumber:
  1452.  
  1453.             clw(3); locate (22, 21);
  1454.             prnt ("ENTER NUMBER FOR NEW RECORD:");
  1455.             inpt (2, 5, 1, 0, 0, 32, user_enty);
  1456.             enty = atol (user_enty);
  1457.  
  1458.             if (enty < 1 || enty > 32000) {beep(); goto choose1;}
  1459.  
  1460.             crno = enty;
  1461.  
  1462.             if (wfg) break;
  1463.  
  1464.             clw(3); locate (22, 23);
  1465.             prnt ("CHECKING YOUR ENTRY, PLEASE WAIT");
  1466.  
  1467.             crsq = 0; i = 0; wfg = 0;
  1468.  
  1469.             while (i <= fi [file].num_rcds && ! wfg)
  1470.                 {
  1471.                 fread ( (void *) & rno, 1, 2, fi [file].ctrl);
  1472.  
  1473.                 if (! crsq && ! rno) crsq = i;
  1474.  
  1475.                 if (rno > bigno) bigno = rno;
  1476.  
  1477.                 if (rno == crno) wfg = 1;
  1478.  
  1479.                 i++;
  1480.                 }
  1481.  
  1482.             if (! crsq) crsq = fi [file].num_rcds;
  1483.  
  1484.             if (wfg)
  1485.                 {
  1486.                 clw(3); beep(); locate (22, 23);
  1487.                 prnt ("THAT RECORD NUMBER HAS BEEN USED");
  1488.                 wait (4); goto get_rnumber;
  1489.                 }
  1490.  
  1491.             }
  1492.  
  1493.         }
  1494.  
  1495.     if (close_sw) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
  1496.  
  1497.     /*  place sequence/number found in file struct  */
  1498.  
  1499.     fi [file].sequence = crsq; fi [file].r_number = crno;
  1500.  
  1501.     /*  clear buffer  */
  1502.  
  1503.     ready_files (file);
  1504.  
  1505.     return (0);
  1506.     }
  1507.  
  1508. BYTE far get_files (BYTE * tgt_ext, BYTE level)
  1509.     {
  1510. /*  if level == 0 finds DATAMAGE dirs, otherwise finds files w/ given ext  */
  1511.  
  1512.     BYTE c, ctr = 0, ftsw = 0, x, y, wfg = 0;
  1513.  
  1514.     FILE * target;
  1515.  
  1516.     struct find_t finfo;
  1517.  
  1518.     ftot [level] = 0;
  1519.  
  1520.     strcpy (gp_str [11], gp_str [10]);
  1521.     strcat (gp_str [11], "\\*.");
  1522.  
  1523.     if (level) strcat (gp_str [11], tgt_ext);
  1524.  
  1525.     while (! wfg)
  1526.         {
  1527.         if (! ftsw)
  1528.             {
  1529.             if (level) c = _dos_findfirst (gp_str [11], 0 || 32, & finfo);
  1530.             else c = _dos_findfirst (gp_str [11], 16, & finfo);
  1531.  
  1532.             ftsw = 1;
  1533.             }
  1534.  
  1535.         else c = _dos_findnext (& finfo);
  1536.  
  1537.         if (c) {wfg = 1; continue;}
  1538.  
  1539.         strcpy (gp_str [2], gp_str [10]);
  1540.  
  1541.         y = gp_str [2] [strlen (gp_str [2]) - 1];
  1542.         if (y != 92) strcat (gp_str [2], "\\");
  1543.  
  1544.         strcat (gp_str [2], finfo.name);
  1545.         if (! level) strcat (gp_str [2], "\\cityname.sad");
  1546.  
  1547.         if ( (target = fopen (gp_str [2], "r")) != NULL)
  1548.             {
  1549.             fgets (f_buff, 37, target);
  1550.             fclose (target);
  1551.  
  1552.             strcpy (gp_str [14], finfo.name);
  1553.  
  1554.             for (c = strlen (gp_str [14]); c < 12; c++)
  1555.                 gp_str [14] [c] = 32;
  1556.  
  1557.             gp_str [14] [c] = 0;
  1558.  
  1559.             set_farst (files [level] [ctr].name, gp_str [14]);
  1560.  
  1561.             strncpy (gp_str [13], f_buff + 1, 35);
  1562.             set_farst (files [level] [ctr].desc, gp_str [13]);
  1563.  
  1564.             ctr ++;
  1565.             }
  1566.  
  1567.         }
  1568.  
  1569.     ftot [level] = ctr;
  1570.  
  1571.     if (ctr) return (1);
  1572.     return (0);
  1573.     }
  1574.  
  1575. BYTE far show_files (BYTE level)
  1576.     {
  1577. /*  displays files found  */
  1578.  
  1579.     BYTE d, m, wfg, x;
  1580.     SWORD top_line = 0, curr_line = 0;
  1581.  
  1582.     strcpy (gp_str [4], ".DIR");
  1583.  
  1584.     for (d = 0; d < ftot [level]; d++)
  1585.         {
  1586.         window_data [d].r_val = d;
  1587.  
  1588.         for (m = 0; m < 62; m++) window_data [d].disp [m] = 32;
  1589.  
  1590.         window_data [d].disp [m] = 0;
  1591.  
  1592.         for (x = 0, m = 3; m < 15; m++)
  1593.             window_data [d].disp [m] = files [level] [d].name [x++];
  1594.  
  1595.         if (! level)
  1596.             for (x = 0, m = 11; m < 15; m++)
  1597.                 window_data [d].disp [m] = gp_str [4] [x++];
  1598.  
  1599.         for (x = 0, m = 23; m < 58; m++)
  1600.             window_data [d].disp [m] = files [level] [d].desc [x++];
  1601.         }
  1602.  
  1603.     save_window (9); clw (9);
  1604.  
  1605.     window_border (4);
  1606.  
  1607.     locate (3,14); prnt ("FILENAME");
  1608.     locate (3,37); prnt ("USER-ASSIGNED DESCRIPTION");
  1609.  
  1610.     fill_window (5, & curr_line, & top_line, level);
  1611.  
  1612.     x = work_window (5, & curr_line, & top_line, level);
  1613.  
  1614.     repl_window (9);
  1615.  
  1616.     return (x);
  1617.     }
  1618.  
  1619. BYTE far select_datafile()
  1620.     {
  1621. /*  combines get_files and show_files to select DATAMAGE datafile  */
  1622.  
  1623.     BYTE c, x = 1, wfg = 0;
  1624.  
  1625.     while (! wfg )
  1626.         {
  1627.         if (readf)
  1628.             {
  1629.             clw (3);
  1630.  
  1631.             strcpy (c_s [0], "READING DIRECTORY OF:");
  1632.             strcpy (c_s [1], gp_str [10]);
  1633.             x = cntrstrp ();
  1634.  
  1635.             locate (22, x);
  1636.             prnt (c_s [2]);
  1637.             }
  1638.  
  1639.         x = get_files ("<DIR>", 0);
  1640.  
  1641.         c = (80 - strlen (gp_str [17]) ) /2;
  1642.  
  1643.         clw (3);
  1644.         locate (22, c); prnt (gp_str [17]);
  1645.  
  1646.         if (x)
  1647.             {
  1648.             x = show_files (0);
  1649.  
  1650.             if (x) {readf = 0; wfg = 1; continue;}
  1651.             }
  1652.  
  1653.         save_window (3);
  1654.  
  1655.         clw(2); clw(3); beep();
  1656.  
  1657.         if (! ftot [0])
  1658.             {
  1659.             locate (10, 25);
  1660.  
  1661.             prnt ("NO DATAMAGE FILES  WERE FOUND");
  1662.             }
  1663.  
  1664.         locate (14, 13);
  1665.         prnt ("ENTER PATHNAME FOR LOAD FILE, OR PRESS RETURN TO ABORT");
  1666.  
  1667.         locate (22,19);
  1668.         x = inpt (1, 40, 1, 0, 0, 32, user_enty);
  1669.  
  1670.         repl_window (3);
  1671.  
  1672.         if (! x) {wfg = 2; continue;}
  1673.  
  1674.         strcpy (gp_str [10], user_enty); readf = 1;
  1675.         strcpy (pth_str, user_enty);
  1676.         clw (2);
  1677.         }
  1678.  
  1679.     return (wfg - 1);
  1680.     }
  1681.  
  1682. BYTE far open_file (BYTE fs)
  1683.     {
  1684. /*   opens DATAMAGE file, fills structure fi [fs] with details,
  1685.     allocates buffer, berbps beeby, kicks tires....  */
  1686.  
  1687.     BYTE c, d, iocb, ret_val = 0, x;
  1688.  
  1689.     WORD r_len = 0;
  1690.  
  1691.     void * buff;
  1692.  
  1693.     FILE * target, * t2;
  1694.  
  1695.     struct
  1696.         {
  1697.         BYTE    st1 [2];
  1698.         BYTE    filler2 [13];
  1699.         BYTE    st2 [2];
  1700.         BYTE    filler3 [12];
  1701.         BYTE    st3 [2];
  1702.         BYTE    filler4 [12];
  1703.         BYTE    st4 [7];
  1704.         BYTE    filler5 [50];
  1705.         } kbuff;
  1706.  
  1707.     buff = & kbuff;
  1708.  
  1709.     strcpy (gp_str[10], gp_str [1]);
  1710.  
  1711.     strcpy (gp_str[2], gp_str [1]);
  1712.     strcpy (gp_str[3], gp_str [1]);
  1713.  
  1714.     strcat (gp_str[1], "\\KEY.SAD");
  1715.     strcat (gp_str[2], "\\HEADINGS.SAD");
  1716.     strcat (gp_str[3], "\\CITYNAME.SAD");
  1717.  
  1718.     /*  get description of file  */
  1719.  
  1720.     t2 = fopen (gp_str[3], "r");
  1721.  
  1722.     if (t2 == NULL) strcpy (fi [fs].des, "NO DESCRIPTION FOUND");
  1723.  
  1724.     else
  1725.         {
  1726.         fgets (f_buff, 40, t2);
  1727.  
  1728.         f_buff [36] = 0; rtrim (f_buff);
  1729.  
  1730.         strcpy (fi [fs].des, f_buff + 1);
  1731.         }
  1732.  
  1733.     fclose (t2);
  1734.  
  1735. open:
  1736.  
  1737.     if ( ( ( target = fopen (gp_str[1], "r") ) == NULL) ||
  1738.        ( ( t2 = fopen (gp_str[2], "r") ) == NULL) )
  1739.         {
  1740.         fclose (target); fclose (t2);
  1741.         clw (2); clw (3); locate (12, 24); beep ();
  1742.         prnt ("Desired file could not be opened.");
  1743.  
  1744.         strcpy (prompts [0], "YOU MAY:");
  1745.  
  1746.         strcpy (prompts [1], "1=RETRY LOAD");
  1747.         strcpy (prompts [2], "2=ABORT LOAD");
  1748.  
  1749.         d = get_v_choice (2, 0, 0);
  1750.  
  1751.         if (d == 1) goto open;
  1752.  
  1753.         ret_val = 1; goto of_end;
  1754.         }
  1755.  
  1756.     setbuf (target, NULL);
  1757.  
  1758.     iocb = fileno(target);
  1759.  
  1760.     /*  fill file structure  */
  1761.  
  1762.     /*  set path strings to open definition files  */
  1763.  
  1764.     strcpy (fi [fs].dir, gp_str [10]);
  1765.  
  1766.     strcpy (fi [fs].m_name, gp_str [10]);
  1767.     strcpy (fi [fs].i_name, gp_str [10]);
  1768.     strcpy (fi [fs].c_name, gp_str [10]);
  1769.  
  1770.     strcat (fi [fs].m_name, "\\YOURDATA.RAD");
  1771.     strcat (fi [fs].i_name, "\\FILEINDX.RAD");
  1772.     strcat (fi [fs].c_name, "\\CTRLFILE.RAD");
  1773.  
  1774.     /*  set file pointers to null, MUST be set to null after closing!
  1775.         Many ISAM functions will open these pointers if they are not NULL,
  1776.         and close them if they were not open - see condit_open function.
  1777.  
  1778.         DO NOT use local file pointers in your routines!  If the ISAM adds
  1779.         a new record into a file open on another iocb NASTY things happen!
  1780.  
  1781.         ALL YOU NEED TO DO is to remember in your code to SET THESE BUGGERS
  1782.         BACK TO NULL after you close them!  The ISAM will take it from there
  1783.         and open/close them if necessary.  */
  1784.  
  1785.     fi [fs].ctrl = NULL;
  1786.     fi [fs].indx = NULL;
  1787.     fi [fs].main = NULL;
  1788.     fi [fs].marker = NULL;
  1789.  
  1790.     /*  zero indexing data  */
  1791.  
  1792.     fi [fs].indexes = 0;
  1793.     fi [fs].cross_fields = 0;
  1794.     fi [fs].unique_field = 0;
  1795.     fi [fs].cross_cntr = 0;
  1796.     fi [fs].next_rcd = 0;
  1797.     fi [fs].m_next_rcd = 0;
  1798.     fi [fs].mkr_active = 0;
  1799.     fi [fs].rw_sw = 0;
  1800.     fi [fs].bs_sw = - 10;
  1801.  
  1802.     d = 0;
  1803.  
  1804.     /*  read in fields  */
  1805.  
  1806.     while (! eof(iocb))
  1807.         {
  1808.         fgets (buff, 50, target);
  1809.  
  1810.         if (! strlen(buff)) continue;
  1811.  
  1812.         fi [fs].key [d] = _fmalloc (sizeof (fdef));
  1813.  
  1814.         if (fi [fs].key [d] == NULL)
  1815.             {
  1816.             mem_fail ();
  1817.             ret_val = 1;
  1818.             goto of_end;
  1819.             }
  1820.  
  1821.         fgets (r_buff, 30, t2);
  1822.  
  1823.         set_farst (fi [fs].key [d] -> name, r_buff);
  1824.  
  1825.         fi [fs].key [d] -> type = atoi (kbuff.st1);
  1826.         fi [fs].key [d] -> length = atoi (kbuff.st2);
  1827.         fi [fs].key [d] -> spare = atoi (kbuff.st3);
  1828.         fi [fs].key [d] -> abs = atoi (kbuff.st4);
  1829.  
  1830.         fi [fs].key [d] -> offset = r_len;
  1831.         r_len += fi [fs].key [d] -> length;
  1832.  
  1833.         /*
  1834.  
  1835.         locate (0,0); prnt ("               ");
  1836.         locate (0,0); printf ("%u, %hu, %u, %u",
  1837.         fi [fs].key [d] -> type,
  1838.         fi [fs].key [d] -> length,
  1839.         fi [fs].key [d] -> spare,
  1840.         fi [fs].key [d] -> abs);
  1841.  
  1842.         wait (1);
  1843.  
  1844.         */
  1845.  
  1846.         /*  detect indexing  */
  1847.  
  1848.         if (fi [fs].key [d] -> type == 1 &&
  1849.             fi [fs].key [d] -> spare)
  1850.             {
  1851.             fi [fs].indexed_fields [fi [fs].indexes] = d;
  1852.             fi [fs].indexes += 1;
  1853.  
  1854.             if (fi [fs].key [d] -> spare == 3) fi [fs].cross_fields += 1;
  1855.  
  1856.             if (fi [fs].key [d] -> spare == 1) fi [fs].unique_field = 1;
  1857.             }
  1858.  
  1859.         d++;
  1860.         }
  1861.  
  1862.     fclose (target); fclose (t2);
  1863.  
  1864.     /*  set number of fields  */
  1865.  
  1866.     fi [fs].num_flds = d;
  1867.  
  1868.     /*  set record length  */
  1869.  
  1870.     fi [fs].rcd_len = r_len;
  1871.  
  1872.     /*  get number of records  */
  1873.  
  1874.     if ( ( target = fopen (fi [fs].c_name, "rb") ) == NULL)
  1875.         fi [fs].num_rcds = 0;
  1876.  
  1877.     else fi [fs].num_rcds = filelength(fileno(target)) / 2;
  1878.  
  1879.     /*  allocate file buffer  */
  1880.  
  1881.     if (fi [fs].buff != NULL)
  1882.         {
  1883.         _ffree (fi [fs].buff);
  1884.         fi [fs].buff = NULL;
  1885.         }
  1886.  
  1887.     if ((fi [fs].buff = _fmalloc (fi [fs].rcd_len + 5)) == NULL)
  1888.         {mem_fail(); ret_val = 1;}
  1889.  
  1890. of_end:
  1891.  
  1892.     fclose (target);
  1893.  
  1894.     return (ret_val);
  1895.     }
  1896.  
  1897. void far close_file (BYTE file)
  1898.     {
  1899. /*  frees DATAMAGE file structure for re-use  */
  1900.  
  1901.     WORD i;
  1902.  
  1903.     if (fi [file].buff != NULL)
  1904.         {
  1905.         _ffree (fi [file].buff);
  1906.         fi [file].buff = NULL;
  1907.         }
  1908.  
  1909.     for (i = 0; i < 200; i++)
  1910.         {
  1911.         if (fi [file].key [i] != NULL)
  1912.             {
  1913.             _ffree (fi [file].key [i]);
  1914.             fi [file].key [i] = NULL;
  1915.             }
  1916.  
  1917.         }
  1918.  
  1919.     }
  1920.  
  1921. BYTE far show_datafiles (BYTE start)
  1922.     {
  1923. /*  shows currently loaded files, user selects  */
  1924.  
  1925.     BYTE d, m, wfg, y, e = 0;
  1926.  
  1927.     SBYTE x;
  1928.  
  1929.     SWORD top_line = 0, curr_line = 0;
  1930.  
  1931.     for (d = start; d < files_loaded; d++, e++)
  1932.         {
  1933.         window_data [e].r_val = d;
  1934.  
  1935.         for (m = 0; m < 62; m++) window_data [e].disp [m] = 32;
  1936.  
  1937.         window_data [e].disp [m] = 0;
  1938.  
  1939.         x = y = strlen (fi [d].dir); wfg = 0;
  1940.  
  1941.         while (x > - 1 && ! wfg)
  1942.             {
  1943.             if (fi [d].dir [x] == 92 || fi [d].dir [x] == 58)
  1944.                 wfg = x + 1;
  1945.  
  1946.             x--;
  1947.             }
  1948.  
  1949.         if (wfg) x = wfg; else x = 0;
  1950.  
  1951.         for (m = 3; m < 11 && x < y;)
  1952.             window_data [e].disp [m++] = fi [d] .dir [x++];
  1953.  
  1954.         y = strlen (fi [d].des) + 23;
  1955.  
  1956.         for (x = 0, m = 23; m < 58 && m < y;)
  1957.             window_data [e].disp [m++] = fi [d].des [x++];
  1958.         }
  1959.  
  1960.     ftot [1] = files_loaded - start;
  1961.  
  1962.     save_window (8); clw (8);
  1963.  
  1964.     window_border (6);
  1965.  
  1966.     locate (9, 14); prnt ("FILENAME");
  1967.     locate (9, 37); prnt ("USER-ASSIGNED DESCRIPTION");
  1968.  
  1969.     fill_window (7, & curr_line, & top_line, 1);
  1970.  
  1971.     x = work_window (7, & curr_line, & top_line, 1);
  1972.  
  1973.     repl_window (8);
  1974.  
  1975.     if (x) return (0); else return (1);
  1976.     }
  1977.  
  1978. BYTE far show_fields (BYTE level, BYTE type)
  1979.     {
  1980. /*  shows fields in file passed, on type  */
  1981.  
  1982.     BYTE x, what [17];
  1983.     WORD d, m, z;
  1984.  
  1985.     SWORD top_line = 0, curr_line = 0;
  1986.  
  1987.     switch (type)
  1988.         {
  1989.         case 0: strcpy (what, "DATE"); break;
  1990.  
  1991.         case 1: strcpy (what, "STRING"); break;
  1992.  
  1993.         case 2:
  1994.         case 3: strcpy (what, "NUMERIC"); break;
  1995.  
  1996.         case 4: strcpy (what, "INDEXED"); break;
  1997.  
  1998.         case 5: strcpy (what, "NON-INDEXED"); break;
  1999.  
  2000.         case 9: strcpy (what, "ALL");
  2001.         }
  2002.  
  2003.     for (z = 0, d = 0; d < fi [level].num_flds; d++)
  2004.         {
  2005.         switch (type)
  2006.             {
  2007.             case 0:
  2008.             case 1:
  2009.                 {
  2010.                 if (fi [level].key [d] -> type != type) continue;
  2011.                 break;
  2012.                 }
  2013.  
  2014.             case 2:
  2015.             case 3:
  2016.                 {
  2017.                 if (fi [level].key [d] -> type < 2) continue;
  2018.                 break;
  2019.                 }
  2020.  
  2021.             case 4:
  2022.                 {
  2023.                 if (fi [level].key [d] -> type != 1  ||
  2024.                     fi [level].key [d] -> spare != 1) continue;
  2025.  
  2026.                 break;
  2027.                 }
  2028.  
  2029.             case 5:
  2030.                 {
  2031.                 if (fi [level].key [d] -> type != 1) continue;
  2032.  
  2033.                 if (fi [level].key [d] -> spare == 1 ||
  2034.                     fi [level].key [d] -> spare == 3) continue;
  2035.  
  2036.                 break;
  2037.                 }
  2038.  
  2039.             case 9: ;
  2040.             }
  2041.  
  2042.         window_data [z].r_val = d;
  2043.  
  2044.         for (m = 0; m < 62; m++) window_data [z].disp [m] = 32;
  2045.  
  2046.         window_data [z].disp [m] = 0;
  2047.  
  2048.         itoa (d + 1, gp_str [4], 10);
  2049.         strcat (gp_str [4], ".");
  2050.  
  2051.         x = 0; m = 1;
  2052.  
  2053.         while (gp_str [4] [x])
  2054.             window_data [z].disp [m++] = gp_str [4] [x++];
  2055.  
  2056.         x = 0; m = 7;
  2057.  
  2058.         get_farst (gp_str [4], fi [level].key [d] -> name);
  2059.  
  2060.         while (gp_str [4] [x])
  2061.             window_data [z].disp [m++] = gp_str [4] [x++];
  2062.  
  2063.         switch (fi [level].key [d] -> type)
  2064.             {
  2065.             case 0:
  2066.                 {
  2067.                 strcpy (gp_str [4], "DATE:   ");
  2068.  
  2069.                 if (! fi [level].key [d] -> spare)
  2070.                     strcat (gp_str [4], "MM/DD/YY");
  2071.  
  2072.                 else strcat (gp_str [4], "DD/MM/YY");
  2073.                 break;
  2074.                 }
  2075.  
  2076.             case 1:
  2077.                  {
  2078.                 strcpy (gp_str [4], "STRING: ");
  2079.  
  2080.                 switch (fi [level].key [d] -> spare)
  2081.                     {
  2082.                     case 0: strcat (gp_str [4], "NO IDX"); break;
  2083.                     case 1: strcat (gp_str [4], "IDX UN"); break;
  2084.                     case 2: strcat (gp_str [4], "IDX"); break;
  2085.                     case 3: strcat (gp_str [4], "IDX CR"); break;
  2086.                     }
  2087.                 break;
  2088.                 }
  2089.  
  2090.             case 2:
  2091.                 {
  2092.                 strcpy (gp_str [4], "NUMERIC: ");
  2093.                 itoa (fi [level].key [d] -> spare, gp_str [5], 10 );
  2094.                 strcat (gp_str [4], gp_str [5]);
  2095.                 strcat (gp_str [4], " DECS");
  2096.                 break;
  2097.                 }
  2098.  
  2099.             case 3:
  2100.                 {
  2101.                 strcpy (gp_str [4], "DOLLAR  FORMAT");
  2102.                 break;
  2103.                 }
  2104.  
  2105.             }
  2106.  
  2107.         x = 0; m = 34;
  2108.  
  2109.         for (x = 0; x < strlen (gp_str [4]); )
  2110.             window_data [z].disp [m++] = gp_str [4] [x++];
  2111.  
  2112.         x = 0; m = 52;
  2113.  
  2114.         strcpy (gp_str [4], "BYTES: ");
  2115.         itoa (fi [level].key [d] -> length, gp_str [5], 10);
  2116.         strcat (gp_str [4], gp_str [5]);
  2117.  
  2118.         for (x = 0; x < strlen (gp_str [4]);)
  2119.             window_data [z].disp [m++] = gp_str [4] [x++];
  2120.  
  2121.         z ++;
  2122.         }
  2123.  
  2124.     if (! z)
  2125.         {
  2126.         clw(3); locate (22,20); beep();
  2127.  
  2128.         strcpy (c_s [0], "NO ");
  2129.         strcat (c_s [0], what);
  2130.         strcpy (c_s [1], " FIELDS WERE FOUND");
  2131.         x = cntrstrp();
  2132.  
  2133.         locate (22, x); prnt (c_s [2]); wait (4); return (1);
  2134.         }
  2135.  
  2136.     ftot [1] = z;
  2137.  
  2138.     save_window (9); clw (9);
  2139.  
  2140.     window_border (4);
  2141.  
  2142.     strcpy (c_s [0], what);
  2143.     strcat (c_s [0], " FIELDS IN: ");
  2144.     strcpy (c_s [1], fi [level].dir);
  2145.     x = cntrstrp();
  2146.  
  2147.     locate (3, x); prnt (c_s [2]);
  2148.  
  2149.     fill_window (5, & curr_line, & top_line, 1);
  2150.  
  2151.     x = work_window (5, & curr_line, & top_line, 1);
  2152.  
  2153.     repl_window (9);
  2154.  
  2155.     if (x) return (0); else return (1);
  2156.     }
  2157.  
  2158. BYTE far show_menu ()
  2159.     {
  2160. /*   shows content of a menu file, expects path/filename in gp_str [13]  */
  2161.  
  2162.     BYTE c, d = 0, fno, m, wfg, x;
  2163.  
  2164.     SWORD top_line = 0, curr_line = 0;
  2165.  
  2166.     FILE * target;
  2167.  
  2168.     target = fopen (gp_str [13], "r");
  2169.  
  2170.     if (target == NULL) {beep(); return (1);}
  2171.  
  2172.     setbuf (target, NULL);
  2173.  
  2174.     fno = fileno (target);
  2175.  
  2176.     save_window (4); window_border (4);
  2177.  
  2178.     while (! eof (fno) )
  2179.         {
  2180.         /*  get display value  */
  2181.  
  2182.         fgets (f_buff, 80, target);
  2183.  
  2184.         if (eof (fno) ) wfg = 1;
  2185.  
  2186.         eol_strip (f_buff);
  2187.  
  2188.         /*  put disp val in window ram  */
  2189.  
  2190.         for (m = 0; m < 62; m++) window_data [d].disp [m] = 32;
  2191.  
  2192.         window_data [d].disp [m] = 0;
  2193.  
  2194.         c = strlen (f_buff);
  2195.         if (c > 62) c = 62;
  2196.  
  2197.         for (m = 0; m < c; m++) window_data [d].disp [m] = f_buff [m];
  2198.  
  2199.         if (eof (fno) ) continue;
  2200.  
  2201.         /*  get return value  */
  2202.  
  2203.         fgets (f_buff, 80, target);
  2204.  
  2205.         eol_strip (f_buff);
  2206.  
  2207.         c = strlen (f_buff);
  2208.         if (c > 62) c = 62;
  2209.  
  2210.         for (m = 0; m < c; m++) window_data [d].rtrn [m] = f_buff [m];
  2211.  
  2212.         window_data [d].rtrn [m] = 0;
  2213.  
  2214.         window_data [d++].r_val = d;
  2215.  
  2216.         if (d >= 199) wfg = 1;
  2217.         }
  2218.  
  2219.     fclose (target); ftot [1] = d;
  2220.  
  2221.     fill_window (5, & curr_line, & top_line, 1);
  2222.  
  2223.     x = work_window (5, & curr_line, & top_line, 1);
  2224.  
  2225.     repl_window (4);
  2226.  
  2227.     return 0;
  2228.     }
  2229.  
  2230. void far fill_window (BYTE w, SWORD * curr_line, SWORD * top_line, BYTE level)
  2231.     {
  2232. /*  universal window fill routine, works from window_data  */
  2233.  
  2234.     BYTE m, l;
  2235.  
  2236.     clw (w);
  2237.  
  2238.     l = (w_a [w] .lrr - w_a [w] .ulr);
  2239.  
  2240.     for (* curr_line = 0; * curr_line <= l; * curr_line += 1)
  2241.             {
  2242.             m = * curr_line + * top_line;
  2243.  
  2244.             if (m > ftot [level] - 1) continue;
  2245.             window_line (w, * curr_line, m, 0);
  2246.             }
  2247.  
  2248.     * curr_line = l / 2;
  2249.  
  2250.     if (* curr_line > ftot [level] - 1) * curr_line = ftot [level] - 1;
  2251.     }
  2252.  
  2253. void far window_line (BYTE w, BYTE l, BYTE x, BYTE revsw)
  2254.     {
  2255. /*  universal window line routine, works from window_data  */
  2256.  
  2257.     BYTE z;
  2258.  
  2259.     if (revsw) z = 120;
  2260.     else z = w_a [w].attr;
  2261.  
  2262.     locate (l + w_a [w] .ulr, w_a [w] .ulc);
  2263.     f_clr_prnt (window_data [x].disp, z);
  2264.     }
  2265.  
  2266. BYTE far work_window (BYTE w, SWORD * curr_line, SWORD * top_line, BYTE level)
  2267.     {
  2268. /*   universal window work routine, works from window_data
  2269.     returns numeric choice in global nrml_val  */
  2270.  
  2271.     BYTE x, wfg = 0, ret_val = 1;
  2272.  
  2273.     SBYTE dy = 0, w_lines = w_a [w] .lrr - w_a [w] .ulr + 1;
  2274.  
  2275.     while (! wfg)
  2276.         {
  2277.         window_line (w, * curr_line, * curr_line + * top_line, 1);
  2278.         get_one (& ctrl_val, & nrml_val);
  2279.  
  2280.         window_line (w, * curr_line, * curr_line + * top_line, 0);
  2281.  
  2282.         if (nrml_val)
  2283.             {
  2284.             switch (nrml_val)
  2285.                 {
  2286.                 case 27 :
  2287.                     {
  2288.                     wfg = 1; ret_val = 0;
  2289.                     nrml_val = 0; continue;
  2290.                     }
  2291.  
  2292.                 case 13 :
  2293.                     {
  2294.                     wfg = 1;
  2295.                     nrml_val = window_data [* top_line + * curr_line].r_val;
  2296.                     continue;
  2297.                     }
  2298.  
  2299.                 default : beep (); continue;
  2300.                 }
  2301.             }
  2302.  
  2303.         switch (ctrl_val)
  2304.             {
  2305.             case 71:        /* home */
  2306.                 * top_line = 0;
  2307.                 fill_window (w, curr_line, top_line, level);
  2308.                 if (ftot [level] >= 7) * curr_line = 7;
  2309.                 else * curr_line = ftot [level] - 1;
  2310.                 continue;
  2311.  
  2312.             case 72:        /* line up */
  2313.                 if ( (* curr_line) - 1 >= 0) {* curr_line -= 1; continue;}
  2314.                 if ( (* top_line) - 1 < 0) {beep(); continue;}
  2315.                 * top_line -= 1;
  2316.                 scroll_window (w, 2, 1);
  2317.                 window_line (w, dy, * curr_line, 0);
  2318.                 continue;
  2319.  
  2320.             case 73:        /* page up */
  2321.                 * top_line -= w_lines;
  2322.                 if (* top_line < 0) * top_line = 0;
  2323.                 fill_window (w, curr_line, top_line, level);
  2324.                 continue;
  2325.  
  2326.             case 79:        /* end */
  2327.                 * top_line = ftot [level] - w_lines;
  2328.                 if (* top_line < 0) * top_line = 0;
  2329.                 fill_window (w, curr_line, top_line, level);
  2330.                 if (ftot [level] >= 7) * curr_line = 7;
  2331.                 else * curr_line = ftot [level] - 1;
  2332.                 continue;
  2333.  
  2334.             case 80:        /* line down */
  2335.                 x = * curr_line + 1;
  2336.  
  2337.                 if (x <= w_lines - 1)
  2338.                     {
  2339.                     if (x < ftot [level]) * curr_line += 1; else beep();
  2340.                     continue;
  2341.                     }
  2342.  
  2343.                 if ( (* top_line) + w_lines + 1 > ftot [level])
  2344.                     {beep (); continue;}
  2345.  
  2346.                 * top_line += 1;
  2347.                 scroll_window (w, 1, 1);
  2348.                 window_line (w, w_lines - 1, * top_line + w_lines - 1, 0);
  2349.                 continue;
  2350.  
  2351.             case 81:        /* page down */
  2352.                 * top_line += w_lines;
  2353.  
  2354.                 if (* top_line > ftot [level] - w_lines)
  2355.                     * top_line = ftot [level] - w_lines;
  2356.  
  2357.                 if (* top_line < 0) * top_line = 0;
  2358.                 fill_window (w, curr_line, top_line, level);
  2359.                 continue;
  2360.  
  2361.             default: beep(); continue;
  2362.             }
  2363.  
  2364.         }
  2365.  
  2366.     return (ret_val);
  2367.     }
  2368.  
  2369. BYTE vs_line (BYTE file, BYTE field, SWORD line,
  2370.                SWORD subscr, BYTE revsw, SWORD far * base)
  2371.     {
  2372. /*  print line routine for browse_file  */
  2373.  
  2374.     BYTE b, c, d, z;
  2375.  
  2376.     WORD x;
  2377.  
  2378.     SWORD rno;
  2379.  
  2380.     DWORD offset;
  2381.  
  2382.     double temp, msbin;
  2383.  
  2384.     /*  clear buffer  */
  2385.  
  2386.     for (d = 0; d < 62; d++) gp_str [0] [d] = 32;
  2387.     gp_str [0] [d] = 0;
  2388.  
  2389.     /*  get offset of next record from array  */
  2390.  
  2391.     x = * (base + subscr);
  2392.  
  2393.     /*  offset in control file  */
  2394.  
  2395.     offset = (DWORD) x * 2;
  2396.  
  2397.     /*  read in record number  */
  2398.  
  2399.     c = fseek (fi [file].ctrl, offset, SEEK_SET);
  2400.     fread (& rno, 2, 1, fi [file].ctrl);
  2401.  
  2402.     /*  put record number in buffer  */
  2403.  
  2404.     sprintf (gp_str [11], "%hi", rno);
  2405.  
  2406.     b = strlen (gp_str [11]);
  2407.  
  2408.     for (c = 2, d = 0; d < b;) gp_str [0] [c++] = gp_str [11] [d++];
  2409.  
  2410.     /*  offset in main file  */
  2411.  
  2412.     offset = (fi [file].rcd_len * x) + fi [file].key [field] -> offset;
  2413.  
  2414.     /*  read in field  */
  2415.  
  2416.     c = fseek (fi [file].main, offset, SEEK_SET);
  2417.     fread (f_buff, 1, fi [file].key  [field] -> length, fi [file].main);
  2418.  
  2419.     f_buff [fi [file].key  [field] -> length] = 0;
  2420.  
  2421.     if (fi [file].key  [field] -> type < 2) rtrim (f_buff);
  2422.  
  2423.     else
  2424.         {
  2425.         c = dmsbintoieee ( (double *) f_buff, & temp);
  2426.  
  2427.         strcpy (gp_str [4], "%. lf");
  2428.         gp_str [4] [2] = fi [file].key  [field] -> spare + 48;
  2429.  
  2430.         sprintf (f_buff, gp_str [4], temp);
  2431.         }
  2432.  
  2433.     /*  place field in buffer  */
  2434.  
  2435.     b = strlen (f_buff);
  2436.  
  2437.     for (c = 13, d = 0; d < b && c < 62;)
  2438.         gp_str [0] [c++] = f_buff [d++];
  2439.  
  2440.     /* select attribute  */
  2441.  
  2442.     if (revsw) z = 120;
  2443.     else z = w_a [5].attr;
  2444.  
  2445.     /*  do line  */
  2446.  
  2447.     locate (line + 5, 9);
  2448.  
  2449.     clr_prnt (gp_str [0], z);
  2450.  
  2451.     return (0);
  2452.     }
  2453.  
  2454. BYTE fill_vs (BYTE file, BYTE field, SWORD * curr_line,
  2455.                SWORD * top_line, WORD last, SWORD far * base)
  2456.     {
  2457. /*  fill routine for browse_file  */
  2458.  
  2459.     BYTE c;
  2460.  
  2461.     SWORD m;
  2462.  
  2463.     for (* curr_line = 0; * curr_line < 14; * curr_line += 1)
  2464.             {
  2465.             m = * curr_line + * top_line;
  2466.  
  2467.             if (m > last - 1) continue;
  2468.  
  2469.             c = vs_line (file, field, * curr_line, m, 0, base);
  2470.             if (c) return (1);
  2471.             }
  2472.  
  2473.     * curr_line = 7;
  2474.  
  2475.     if (* curr_line > last - 1) * curr_line = last - 1;
  2476.  
  2477.     return (0);
  2478.     }
  2479.  
  2480. void vs_menu (BYTE file, SWORD line)
  2481.     {
  2482. /*   menu for browse_file  */
  2483.  
  2484.     clw (3);
  2485.     locate (21,6);
  2486.     prnt ("FILE:  ");
  2487.  
  2488.     prnt (fi [file].dir);
  2489.  
  2490.     locate (21, 58);
  2491.     prnt ("LOCATION: ");
  2492.  
  2493.     locate (22,6);
  2494.     prnt ("CONTROL KEYS:    \x018  \x019     Page-Up      Page-Down      Home      End");
  2495.     locate (23,6);
  2496.     prnt ("Press <RETURN> to select record, <ESC> to bypass, F to select field.");
  2497.  
  2498.     }
  2499.  
  2500. BYTE far vs_MAGE_recrd (BYTE file, BYTE field, BYTE * error_str)
  2501.     {
  2502. /*   browses target file, returns record selected in fi [file].sequence  */
  2503.  
  2504.     BYTE c, close_sw [3], wfg = 0, ret_val;
  2505.  
  2506.     WORD i = 0, n = 0, x;
  2507.  
  2508.     SWORD rno, top_line = 0, curr_line = 0;
  2509.  
  2510.     DWORD offset = 0;
  2511.  
  2512.     SWORD far * base;
  2513.  
  2514.     BYTE           fill_vs             (BYTE, BYTE, SWORD *,
  2515.                                  SWORD *, WORD, SWORD far *);
  2516.  
  2517.     BYTE           vs_line             (BYTE, BYTE, SWORD,
  2518.                                  SWORD, BYTE, SWORD far *);
  2519.  
  2520.     void           vs_menu             (BYTE, SWORD);
  2521.  
  2522.     for (c = 0; c < 3; c++) close_sw [c] = 0;
  2523.  
  2524.     clw (3); locate (22,22);
  2525.     prnt ("PREPARING FILE BROWSE, PLEASE WAIT....");
  2526.  
  2527.     /*  open ctrl file  */
  2528.  
  2529.     c = condit_open (file, 3, "r+b");
  2530.  
  2531.     switch (c)
  2532.         {
  2533.         case 0: break;
  2534.  
  2535.         case 1: {close_sw [2] = 1; break;}
  2536.  
  2537.         case 2: {wfg = 1; goto check_open;}
  2538.         }
  2539.  
  2540.     c = fseek (fi [file].ctrl, offset, SEEK_SET);
  2541.  
  2542.     /*  open main file  */
  2543.  
  2544.     c = condit_open (file, 1, "r+b");
  2545.  
  2546.     switch (c)
  2547.         {
  2548.         case 0: break;
  2549.  
  2550.         case 1:
  2551.             {
  2552.             close_sw [0] = 1;
  2553.             break;
  2554.             }
  2555.  
  2556.         case 2: wfg = 1;
  2557.         }
  2558.  
  2559. check_open:
  2560.  
  2561.     if (wfg)
  2562.         {
  2563.         strcpy (error_str, "UNABLE TO ACCESS BROWSE FILES");
  2564.  
  2565.         ret_val = 2;
  2566.         goto bf_end;
  2567.         }
  2568.  
  2569.     while (i < fi [file].num_rcds)
  2570.         {
  2571.  
  2572.         fread (& rno, 2, 1, fi [file].ctrl);
  2573.  
  2574.         if (rno) n++;
  2575.  
  2576.         i ++;
  2577.         }
  2578.  
  2579.     if (! n)
  2580.         {
  2581.         strcpy (error_str, "BROWSE FILE HAS NO RECORDS");
  2582.  
  2583.         ret_val = 2;
  2584.         goto bf_end;
  2585.         }
  2586.     base = (SWORD far *) _fmalloc ( (n * 2) + 10);
  2587.  
  2588.     if (base == NULL)
  2589.         {
  2590.         strcpy (error_str, "INSUFFICIANT MEMORY FOR FILE BROWSE");
  2591.  
  2592.         ret_val = 2;
  2593.         goto bf_end;
  2594.         }
  2595.  
  2596.     i = x = 0;
  2597.  
  2598.     fseek (fi [file].ctrl, (DWORD) 0, SEEK_SET);
  2599.  
  2600.     while (i < fi [file].num_rcds)
  2601.         {
  2602.         fread (& rno, 2, 1, fi [file].ctrl);
  2603.  
  2604.         if (rno) * (base + x++) = i;
  2605.  
  2606.         i ++;
  2607.         }
  2608.  
  2609.     save_window (4); window_border (4);
  2610.  
  2611.     vs_menu (file, top_line + curr_line);
  2612.  
  2613.     c = fill_vs (file, field, & curr_line, & top_line, n, base);
  2614.  
  2615.     if (c) {ret_val = 1; goto bf_end_2;}
  2616.  
  2617.     while (! wfg)
  2618.         {
  2619.         sprintf (gp_str [6],"%hi", top_line + curr_line + 1);
  2620.  
  2621.         for (c = 0; c < 7; c++)
  2622.             if (gp_str [6] [c] == 0) gp_str [6] [c] = 32;
  2623.  
  2624.         gp_str [6] [c] = 0;
  2625.  
  2626.         locate (21, 68);
  2627.         prnt (gp_str [6]);
  2628.  
  2629.         c = vs_line (file, field, curr_line,
  2630.                    curr_line + top_line, 1, base);
  2631.  
  2632.         if (c) {wfg = 1; ret_val = 1; continue;}
  2633.  
  2634.         get_one (& ctrl_val, & nrml_val);
  2635.  
  2636.         c = vs_line (file, field, curr_line,
  2637.                    curr_line + top_line, 0, base);
  2638.  
  2639.         if (c) {wfg = 1; ret_val = 1; continue;}
  2640.  
  2641.         if (nrml_val)
  2642.             {
  2643.             switch (nrml_val)
  2644.                 {
  2645.                 case 27 :
  2646.                     {
  2647.                     wfg = 1; ret_val = 1;
  2648.                     nrml_val = 0; break;
  2649.                     }
  2650.  
  2651.                 case 13 :
  2652.                     {
  2653.                     wfg = 1; ret_val = 0;
  2654.  
  2655.                     i = top_line + curr_line;
  2656.  
  2657.                     x = * (base + i);
  2658.  
  2659.                     offset = fi [file].rcd_len * x;
  2660.  
  2661.                     /*  read record in  */
  2662.  
  2663.                     c = fseek (fi [file].main, offset, SEEK_SET);
  2664.                     fread (f_buff, fi [file].rcd_len, 1, fi [file].main);
  2665.  
  2666.                     set_far (fi [file].buff, f_buff, fi [file].rcd_len);
  2667.  
  2668.                     /*  place sequence number of record found  */
  2669.  
  2670.                     fi [file].sequence = x;
  2671.  
  2672.                     /*  place record number of record found  */
  2673.  
  2674.                     fseek (fi [file].ctrl, (DWORD) x * 2, SEEK_SET);
  2675.  
  2676.                     fread (& rno, 2, 1, fi [file].ctrl);
  2677.  
  2678.                     fi [file].r_number = rno;
  2679.  
  2680.                     break;
  2681.                     }
  2682.  
  2683.                 case 'f':
  2684.                 case 'F':
  2685.                     {
  2686.                     clw (3); locate (22,31);
  2687.                     prnt ("SELECT VIEW FIELD");
  2688.  
  2689.                     c = show_fields (file, 9);
  2690.  
  2691.                     if (! c) field = nrml_val;
  2692.  
  2693.                     c = fill_vs (file, field,
  2694.                                   & curr_line, & top_line, n, base);
  2695.  
  2696.                     if (c) return (1);
  2697.  
  2698.  
  2699.                     vs_menu (file, top_line + curr_line);
  2700.                     break;
  2701.                     }
  2702.  
  2703.                 default : beep (); break;
  2704.                 }
  2705.  
  2706.             continue;
  2707.             }
  2708.  
  2709.         switch (ctrl_val)
  2710.             {
  2711.             case 71:        /* home */
  2712.                 {
  2713.                 top_line = 0; clw (5);
  2714.  
  2715.                 c = fill_vs (file, field, & curr_line,
  2716.                               & top_line, n, base);
  2717.  
  2718.                 if (c) return (1);
  2719.  
  2720.                 if (n >= 7) curr_line = 7;
  2721.                 else curr_line = n - 1;
  2722.                 continue;
  2723.                 }
  2724.  
  2725.             case 72:        /* line up */
  2726.                 {
  2727.                 if ( (curr_line) - 1 >= 0) {curr_line -= 1; continue;}
  2728.                 if ( (top_line) - 1 < 0) {beep(); continue;}
  2729.                 top_line -= 1;
  2730.                 scroll_window (5, 2, 1);
  2731.  
  2732.                 c =  (file, field, 0, curr_line, 0);
  2733.                 if (c) return (1);
  2734.  
  2735.                 continue;
  2736.                 }
  2737.  
  2738.             case 73:        /* page up */
  2739.                 {
  2740.                 top_line -= 14; clw (5);
  2741.                 if (top_line < 0) top_line = 0;
  2742.  
  2743.                 c = fill_vs (file, field,
  2744.                               & curr_line, & top_line, n, base);
  2745.  
  2746.                 if (c) return (1);
  2747.  
  2748.                 continue;
  2749.                 }
  2750.  
  2751.             case 79:        /* end */
  2752.                 {
  2753.                 top_line = n - 14; clw (5);
  2754.                 if (top_line < 0) top_line = 0;
  2755.  
  2756.                 c = fill_vs (file, field,
  2757.                               & curr_line, & top_line, n, base);
  2758.  
  2759.                 if (c) return (1);
  2760.  
  2761.                 if (n >= 7) curr_line = 7;
  2762.                 else curr_line = n - 1;
  2763.  
  2764.                 continue;
  2765.                 }
  2766.  
  2767.             case 80:        /* line down */
  2768.                 {
  2769.                 x = curr_line + 1;
  2770.  
  2771.                 if (x <= 13)
  2772.                     {
  2773.                     if (x < n) curr_line += 1; else beep();
  2774.                     continue;
  2775.                     }
  2776.  
  2777.                 if ( (top_line) + 15 > n)
  2778.                     {beep (); continue;}
  2779.  
  2780.                 top_line += 1;
  2781.                 scroll_window (5, 1, 1);
  2782.  
  2783.                 c = vs_line (file, field,
  2784.                               13, top_line + 13, 0, base);
  2785.  
  2786.                 if (c) {wfg = 1; ret_val = 1; continue;}
  2787.  
  2788.                 continue;
  2789.                 }
  2790.  
  2791.             case 81:        /* page down */
  2792.                 {
  2793.                 top_line += 14; clw (5);
  2794.  
  2795.                 if (top_line > n - 14)
  2796.                     top_line = n - 14;
  2797.  
  2798.                 if (top_line < 0) top_line = 0;
  2799.  
  2800.                 c = fill_vs (file, field,
  2801.                               & curr_line, & top_line, n, base);
  2802.  
  2803.                 if (c) return (1);
  2804.  
  2805.                 continue;
  2806.                 }
  2807.  
  2808.             default: beep(); continue;
  2809.             }
  2810.  
  2811.         }
  2812.  
  2813. bf_end_2:
  2814.  
  2815.     _ffree (base);
  2816.  
  2817. bf_end:
  2818.  
  2819.     clw (4); repl_window (4);
  2820.  
  2821.     if (close_sw [0]) {fclose (fi [file].main); fi [file].main = NULL;}
  2822.     if (close_sw [3]) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
  2823.  
  2824.     return (ret_val);
  2825.     }
  2826.  
  2827. void pmr_heading (BYTE * page)
  2828.     {
  2829. /*   prints heading for mage record  */
  2830.  
  2831.     BYTE d;
  2832.  
  2833.     if (* page) lpt_char (12);
  2834.     * page += 1;
  2835.  
  2836.     lpt_eol ();
  2837.     lpt_line (79, 42);
  2838.     lpt_blanks (3);
  2839.  
  2840.     strcpy (c_s [0], "DATAMAGE - SCREEN MAKER REPORT RUN ON: ");
  2841.  
  2842.     _strdate (c_s [1]);
  2843.     strcat (c_s [1], "  AT: ");
  2844.     _strtime (gp_str [11]);
  2845.     gp_str [11] [5] = 0;
  2846.     strcat (c_s [1], gp_str [11]);
  2847.  
  2848.     d = cntrstrp ();
  2849.  
  2850.     lpt_tab (d);
  2851.     lpt_string (c_s [2]);
  2852.     lpt_blanks (3);
  2853.  
  2854.     strcpy (c_s [0], "CONTENTS OF TEST RECORD");
  2855.  
  2856.     strcpy (c_s [1], "PAGE: ");
  2857.  
  2858.     itoa (* page, gp_str [5], 10);
  2859.     strcat (c_s [1], gp_str [5]);
  2860.  
  2861.     d = cntrstrp ();
  2862.  
  2863.     lpt_tab (d);
  2864.     lpt_string (c_s [2]);
  2865.     lpt_blanks (3);
  2866.  
  2867.     lpt_line (79, 42);
  2868.     lpt_blanks (2);
  2869.     }
  2870.  
  2871. void field_line (BYTE file, WORD field)
  2872.     {
  2873.     strcpy (c_s [0], "FIELD # ");
  2874.  
  2875.     itoa (field + 1, gp_str [13], 10);
  2876.     strcat (c_s [0], gp_str [13]);
  2877.  
  2878.     strcat (c_s [0], ". NAME: ");
  2879.     get_farst (gp_str [13], fi [file].key  [field] -> name);
  2880.     strcat (c_s [0], gp_str [13]);
  2881.  
  2882.     strcpy (c_s [1], "TYPE: ");
  2883.  
  2884.     switch (fi [file].key  [field] -> type)
  2885.         {
  2886.         case 0:
  2887.             {
  2888.             strcat (c_s [1], "DATE FIELD:   ");
  2889.  
  2890.             if (fi [file].key  [field] -> spare == 1)
  2891.                 strcat (c_s [1], "MM/DD/YY");
  2892.  
  2893.             else strcat (c_s [1],  "DD/MM/YY");
  2894.  
  2895.             break;
  2896.             }
  2897.  
  2898.         case 1:
  2899.             {
  2900.             strcat (c_s [1], "STRING");
  2901.  
  2902.             switch (fi [file].key  [field] -> spare)
  2903.                 {
  2904.                 case 1:
  2905.                     {
  2906.                     strcat (c_s [1], ", INDEXED UNIQUE");
  2907.                     break;
  2908.                     }
  2909.  
  2910.                 case 2:
  2911.                     {
  2912.                     strcat (c_s [1], ", INDEXED");
  2913.                     break;
  2914.                     }
  2915.  
  2916.                 case 3:
  2917.                     {
  2918.                     strcat (c_s [1], ", CROSS-INDEXED");
  2919.                     break;
  2920.                     }
  2921.  
  2922.                 }
  2923.  
  2924.             break;
  2925.             }
  2926.  
  2927.         case 2:
  2928.             {
  2929.             strcat (c_s [1], "NUMERIC");
  2930.  
  2931.             switch (fi [file].key  [field] -> spare)
  2932.                 {
  2933.                 case 9:
  2934.                     {
  2935.                     strcat (c_s [1], ", FLOATING POINT");
  2936.                     break;
  2937.                     }
  2938.  
  2939.                 default:
  2940.                     {
  2941.                     itoa (fi [file].key  [field] -> spare, gp_str [12], 10);
  2942.                     strcat (c_s [1], ", ");
  2943.                     strcat (c_s [1], gp_str [12]);
  2944.                     strcat (c_s [1], " DECIMALS");
  2945.                     break;
  2946.                     }
  2947.  
  2948.                 }
  2949.  
  2950.             break;
  2951.             }
  2952.  
  2953.         case 3: strcat (c_s [1], "NUMERIC, DOLLAR FMT");
  2954.         }
  2955.  
  2956.     }
  2957.  
  2958. void far print_MAGE_record (BYTE file)
  2959.     {
  2960. /*   prints DATAMAGE record - must be in buffer when called  */
  2961.  
  2962.     BYTE c, dollar, l, line = 13, page = 0;
  2963.  
  2964.     WORD d, len, x;
  2965.  
  2966.     double temp;
  2967.  
  2968.     pmr_heading (& page);
  2969.  
  2970.     for (d = 0; d < fi [file].num_flds; d++)
  2971.         {
  2972.         itoa (d + 1, gp_str [5], 10);
  2973.         strcat (gp_str [5], ".");
  2974.         lpt_string (gp_str [5]);
  2975.  
  2976.         lpt_tab (10);
  2977.         lpt_f_string (fi [file].key  [d] -> name);
  2978.  
  2979.         lpt_tab (40);
  2980.  
  2981.         len = fi [file].key [d] -> length;
  2982.  
  2983.         get_far (user_enty,
  2984.                 fi [file].buff + fi [file].key  [d] -> offset,
  2985.                 len);
  2986.  
  2987.         if (fi [file].key [d] -> type < 2)
  2988.             {
  2989.             user_enty [len] = 0; rtrim (user_enty);
  2990.  
  2991.             if (len <= 35) {lpt_string (user_enty); lpt_eol ();}
  2992.  
  2993.             else
  2994.                 {
  2995.                 x = l = 0;
  2996.  
  2997.                 while (x < len)
  2998.                     {
  2999.                     l = len - x;
  3000.  
  3001.                     if (l > 35) l = 35;
  3002.  
  3003.                     for (c = 0; c < l; c++)
  3004.                         lpt_char (user_enty [c + x]);
  3005.  
  3006.                     lpt_eol ();
  3007.  
  3008.                     x += l; line ++;
  3009.  
  3010.                     if (line > 59) {pmr_heading (& page); line = 13;}
  3011.  
  3012.                     if (x < len) lpt_tab (40);
  3013.                     }
  3014.  
  3015.                 }
  3016.  
  3017.             line ++;
  3018.             if (line > 59) {pmr_heading (& page); line = 13;}
  3019.  
  3020.             continue;
  3021.             }
  3022.  
  3023.         dmsbintoieee ( (double *) user_enty, & temp);
  3024.  
  3025.         strcpy (gp_str [4], "%. lf");
  3026.         gp_str [4] [2] = fi [file].key  [d] -> spare + 48;
  3027.  
  3028.         sprintf (c_s [0], gp_str [4], temp);
  3029.  
  3030.         dollar = 0;
  3031.         if (fi [file].key  [d] -> type == 3) dollar = 1;
  3032.  
  3033.         dlr_format (dollar, 1);
  3034.  
  3035.         lpt_string (c_s [2]); lpt_eol ();
  3036.  
  3037.         line ++;
  3038.         if (line > 59) {pmr_heading (& page); line = 13;}
  3039.         }
  3040.  
  3041.     lpt_char (12);
  3042.     }
  3043.  
  3044. void new_a_screen (BYTE file, SWORD st, BYTE * acc)
  3045.     {
  3046. /*   fill routine for access screen  */
  3047.  
  3048.     WORD d, line = 0, x = st + 9;
  3049.  
  3050.     clw (2);
  3051.  
  3052.     for (d = st; d < x; d++)
  3053.         a_line (file, d, line++, acc);
  3054.     }
  3055.  
  3056. void a_line (BYTE file, WORD field, WORD line, BYTE * acc)
  3057.     {
  3058. /*   line print routine for access screen  */
  3059.  
  3060.     BYTE c, d, row;
  3061.  
  3062.     WORD len;
  3063.  
  3064.     double temp, msbin;
  3065.  
  3066.     row = (line * 2) + 2;
  3067.  
  3068.     locate (row, 7);
  3069.     itoa (field + 1, gp_str [11], 10);
  3070.     strcat (gp_str [11], ".");
  3071.     prnt (gp_str [11]);
  3072.  
  3073.     locate (row, 13);
  3074.     f_prnt (fi [file].key [field] -> name);
  3075.  
  3076.     locate (row, 40);
  3077.  
  3078.     len = fi [file].key [field] -> length;
  3079.     if (len > 35) len = 35;
  3080.  
  3081.     if (fi [file].key [field] -> type < 2)
  3082.         {
  3083.         get_field (file, field, len, gp_str [11]);
  3084.  
  3085.         gp_str [11] [len] = 0;
  3086.  
  3087.         c = 1; d = fi [file].key [field] -> length;
  3088.  
  3089.         if (d > 35) d = 35;
  3090.         }
  3091.  
  3092.     else
  3093.         {
  3094.         get_field (file, field, 8, (BYTE *) & msbin);
  3095.         dmsbintoieee (& msbin, & temp);
  3096.  
  3097.         if (temp != 0)
  3098.             {
  3099.             strcpy (gp_str [4], "%. lf");
  3100.             gp_str [4] [2] = fi [file].key [field] -> spare + 48;
  3101.  
  3102.             d = sprintf (gp_str [11], gp_str [4], temp);
  3103.             }
  3104.  
  3105.         else {strcpy (gp_str [11], "0"); d = 1;}
  3106.  
  3107.         for (; d < 17; d++) gp_str [11] [d] = 32;
  3108.  
  3109.         gp_str [11] [d] = 0;
  3110.  
  3111.         c = 2; d = 17;
  3112.         }
  3113.  
  3114.     if (* (acc + field) )
  3115.         {
  3116.         locate (row, 40);
  3117.  
  3118.         ipt_box (40, row, d, 32, 0, 0, gp_str [11]);
  3119.         }
  3120.  
  3121.     else prnt (gp_str [11]);
  3122.     }
  3123.  
  3124. void a_menu (BYTE file, BYTE entry)
  3125.     {
  3126. /*   menu for access screen  */
  3127.  
  3128.     if (entry) strcpy (gp_str [6], "NEW");
  3129.     else gp_str [6] [0] = 0;
  3130.  
  3131.     strcat (gp_str [6], "RECORD NUMBER: ");
  3132.  
  3133.     clw (3); locate (21,6);
  3134.     prnt (gp_str [6]);
  3135.  
  3136.     sprintf (gp_str [6],"%hu", fi [file].r_number);
  3137.     prnt (gp_str [6]);
  3138.  
  3139.     locate (21, 32);
  3140.     prnt ("IN FILE: "); prnt (fi [file].des);
  3141.  
  3142.     locate (22,6);
  3143.     prnt ("CONTROL KEYS:   \x018   \x019   Pg-Up  Pg-Dn  Home  End  Write  Print  Quit");
  3144.  
  3145.     locate (23,6);
  3146.     prnt ("Locate the flasher and press <RETURN> to enter/edit  data in fields");
  3147.     }
  3148.  
  3149. BYTE far access_MAGE_record (BYTE file, BYTE entry, BYTE rd_only)
  3150.     {
  3151. /*   provides entry/update of records in a DATAMAGE file
  3152.     record to edit must be in buffer, unless entry switch is set
  3153.     returns 0 if record (re)written, 1 if quit  */
  3154.  
  3155.     BYTE acc [200], c, choice, d, day, dte_fmt, ftsw = 0,
  3156.         len, month, row, sl = 0, wfg = 0, wfg2;
  3157.  
  3158.     WORD year;
  3159.  
  3160.     SWORD st = 0;
  3161.  
  3162.     double temp, msbin;
  3163.  
  3164.     if (entry) rd_only = 0;
  3165.  
  3166.     /*  clear field accessed switches  */
  3167.  
  3168.     for (d = 0; d < 200; d++) acc [d] = 0;
  3169.  
  3170.     if (entry) get_next_rno (file);
  3171.  
  3172.     new_a_screen (file, st, acc);
  3173.  
  3174.     while (! wfg)
  3175.         {
  3176.         if (! ftsw) {a_menu (file, entry); ftsw = 1;}
  3177.  
  3178.         c = (sl * 2) + 2;
  3179.  
  3180.         locate (c, 7);
  3181.         itoa (st + sl + 1, gp_str [11], 10);
  3182.         strcat (gp_str [11], ".");
  3183.         clr_prnt (gp_str [11], attr + 128);
  3184.  
  3185.         get_one (& ctrl_val, & nrml_val);
  3186.  
  3187.         locate (c, 7);
  3188.         clr_prnt (gp_str [11], attr);
  3189.  
  3190.         y_n ();
  3191.  
  3192.         if (nrml_val)
  3193.             {
  3194.             switch (nrml_val)
  3195.                 {
  3196.                 default : {beep (); continue;}
  3197.  
  3198.                 case 'p':
  3199.                 case 'P':
  3200.                     {
  3201.                     ftsw = 0;
  3202.  
  3203.                     strcpy (prompts [0], "PRINT THIS RECORD?");
  3204.  
  3205.                     choice = get_v_choice (2, 0, 0) - 1;
  3206.  
  3207.                     if (choice) continue;
  3208.  
  3209.                     clw (3); locate (22,22);
  3210.                     prnt ("READY YOUR PRINTER, AND PRESS ANY KEY");
  3211.  
  3212.                     get_one (& nrml_val, & ctrl_val);
  3213.  
  3214.                     print_MAGE_record (file);
  3215.  
  3216.                     break;
  3217.                     }
  3218.  
  3219.                 case 'q':
  3220.                 case 'Q':
  3221.                     {
  3222.                     ftsw = 0;
  3223.  
  3224.                     strcpy (prompts [0], "ABANDON THIS RECORD?");
  3225.  
  3226.                     choice = get_v_choice (2, 0, 0) - 1;
  3227.  
  3228.                     if (! choice) {wfg = 2; continue;}
  3229.  
  3230.                     break;
  3231.                     }
  3232.  
  3233.                 case 'w':
  3234.                 case 'W':
  3235.                     {
  3236.                     ftsw = 0;
  3237.  
  3238.                     if (rd_only)
  3239.                         {
  3240.                         clw(3); beep (); locate (22,27);
  3241.                         prnt ("RECORD ACCESS IS READ ONLY");
  3242.                         wait (4);
  3243.  
  3244.                         break;
  3245.                         }
  3246.  
  3247.                     strcpy (prompts [0], "WRITE THIS RECORD?");
  3248.  
  3249.                     choice = get_v_choice (2, 0, 0) - 1;
  3250.  
  3251.                     if (choice) continue;
  3252.  
  3253.                     /*  index completed record  */
  3254.  
  3255.                     if (fi [file].indexes)
  3256.                         {
  3257.                         for (c = 0; c < 5; c++)
  3258.                             fi [file].i_case [c] = 0;
  3259.  
  3260.                         d = index_MAGErecord (file);
  3261.  
  3262.                         if ( (fi [file].unique_field ||
  3263.                              fi [file].cross_fields) &&
  3264.                             fi [file].num_rcds)
  3265.                             {
  3266.                             c = find_MAGErecord (file, (WORD) 0, 0, 0);
  3267.  
  3268.                             if (! c)
  3269.                                 {
  3270.                                 clw (3); beep(); locate (22, 17);
  3271.  
  3272.                                 prnt ("DUPLICATE RECORD FOUND,  CAN NOT WRITE RECORD");
  3273.                                 wait (4); continue;
  3274.                                 }
  3275.  
  3276.                             }
  3277.  
  3278.                         }
  3279.  
  3280.                     /*  write new record into main file  */
  3281.  
  3282.                     clw(3); locate (22, 26);
  3283.                     prnt ("WRITING NEW  RECORD TO DISK");
  3284.  
  3285.                     write_MAGErcd (file);
  3286.  
  3287.                     wfg = 1; continue;
  3288.                     }
  3289.  
  3290.                 case 13 :
  3291.                     {
  3292.                     if (rd_only)
  3293.                         {
  3294.                         clw(3); beep (); locate (22,27);
  3295.                         prnt ("RECORD ACCESS IS READ ONLY");
  3296.  
  3297.                         ftsw = 0; wait (4);
  3298.  
  3299.                         break;
  3300.                         }
  3301.  
  3302.                     c = st + sl; acc [c] = 1; ftsw = 0;
  3303.  
  3304.                     field_line (file, c);
  3305.  
  3306.                     row = cntrstrp ();
  3307.  
  3308.                     clw (3); locate (22, row); prnt (c_s [2]);
  3309.  
  3310.                     if (fi [file].key [c] -> type < 2)
  3311.                         {
  3312.                         d = fi [file].key [c] -> length;
  3313.  
  3314.                         get_field (file, (WORD) c, d, user_enty);
  3315.                         }
  3316.  
  3317.                     else
  3318.                         {
  3319.                         get_field (file, (WORD) c, 8, (BYTE *) & msbin);
  3320.                         dmsbintoieee (& msbin, & temp);
  3321.  
  3322.                         d = 0;
  3323.  
  3324.                         if (temp != 0)
  3325.                             {
  3326.                             strcpy (gp_str [4], "%. lf");
  3327.                             gp_str [4] [2] =
  3328.                                 fi [file].key [c] -> spare + 48;
  3329.  
  3330.                             d = sprintf (user_enty, gp_str [4], temp);
  3331.                             }
  3332.  
  3333.                         for (; d < 17; d++) user_enty [d] = 32;
  3334.  
  3335.                         user_enty [d] = 0;
  3336.                         }
  3337.  
  3338. inp_field:
  3339.  
  3340.                     locate ( (BYTE) ((sl * 2) + 2), 38);
  3341.  
  3342.                     len = minpt (file, c, user_enty); wfg2 = 0;
  3343.  
  3344.                     switch (fi [file].key [c] -> type)
  3345.                         {
  3346.                         case 0:
  3347.                             {
  3348.                              if (len)
  3349.                                 {
  3350.                                 dte_fmt = fi [file].key [c] -> spare;
  3351.  
  3352.                                 d = parse_date (user_enty,
  3353.                                              & dte_fmt, & day,
  3354.                                              & month, & year,
  3355.                                              & temp);
  3356.  
  3357.                                 if (d) {wfg2 = 1; break;}
  3358.                                 }
  3359.  
  3360.                                    }
  3361.  
  3362.                         case 1:
  3363.                             {
  3364.                             set_field (file, c,
  3365.                                        fi [file].key [c] -> length,
  3366.                                      user_enty);
  3367.                             break;
  3368.                             }
  3369.  
  3370.                         case 3:
  3371.                             {
  3372.                             strcpy (gp_str [4], "%. lf");
  3373.                             gp_str [4] [2] =
  3374.                                 fi [file].key[c] -> spare + 48;
  3375.  
  3376.                             temp = atof (user_enty);
  3377.                             d = sprintf (user_enty, gp_str [4], temp);
  3378.  
  3379.                             for (; d < 17; d++) user_enty [d] = 32;
  3380.  
  3381.                             user_enty [17] = 0;
  3382.  
  3383.                             locate ((sl * 2) + 2, 40);
  3384.                             prnt (user_enty);
  3385.  
  3386.                             temp = atof (user_enty);
  3387.                             dieeetomsbin (& temp, & msbin);
  3388.  
  3389.                             set_field (file, c, 8, (BYTE *) & msbin);
  3390.                             }
  3391.  
  3392.                         }
  3393.  
  3394.                     if (wfg2) {beep(); goto inp_field;}
  3395.  
  3396.                     if ( (st + sl + 2) > fi [file].num_flds) break;
  3397.  
  3398.                     if (sl < 8) sl += 1;
  3399.  
  3400.                     else
  3401.                         {
  3402.                         st += 1; scroll_window (2, 1, 2);
  3403.  
  3404.                         a_line (file, st + 8, (WORD) 8, acc);
  3405.                         }
  3406.  
  3407.                     }
  3408.  
  3409.                 }
  3410.  
  3411.             continue;
  3412.             }
  3413.  
  3414.         switch (ctrl_val)
  3415.             {
  3416.             case 71:        /* home */
  3417.                 {
  3418.                 st = 0; sl = 5;
  3419.                 new_a_screen (file, st, acc);
  3420.                 continue;
  3421.                 }
  3422.  
  3423.             case 72:        /* line up */
  3424.                 {
  3425.                 if (sl) sl -= 1;
  3426.  
  3427.                 else
  3428.                     {
  3429.                     if (st - 1 < 0) {beep(); continue;}
  3430.  
  3431.                     st -= 1; scroll_window (2, 2, 2);
  3432.  
  3433.                     a_line (file, st, (WORD) 0, acc);
  3434.                     }
  3435.  
  3436.                 continue;
  3437.                 }
  3438.  
  3439.             case 73:        /* page up */
  3440.                 {
  3441.                 st -= 9;
  3442.  
  3443.                 if (st < 0) st = 0;
  3444.  
  3445.                 new_a_screen (file, st, acc);
  3446.  
  3447.                 continue;
  3448.                 }
  3449.  
  3450.             case 79:        /* end */
  3451.                 {
  3452.                 st = fi [file].num_flds - 9;
  3453.  
  3454.                 if (st < 0) st = 0;
  3455.  
  3456.                 new_a_screen (file, st, acc);
  3457.  
  3458.                 sl = 5;
  3459.  
  3460.                 continue;
  3461.                 }
  3462.  
  3463.             case 80:        /* line down */
  3464.                 {
  3465.                 if ( (st + sl + 2) > fi [file].num_flds)
  3466.                     {beep(); continue;}
  3467.  
  3468.                 if (sl < 8) sl += 1;
  3469.  
  3470.                 else
  3471.                     {
  3472.                     st += 1; scroll_window (2, 1, 2);
  3473.  
  3474.                     a_line (file, st + 8, (WORD) 8, acc);
  3475.                     }
  3476.  
  3477.                 continue;
  3478.                 }
  3479.  
  3480.             case 81:        /* page down */
  3481.                 {
  3482.                 st += 9;
  3483.  
  3484.                 if (st > fi [file].num_flds - 9)
  3485.                     st = fi [file].num_flds - 9;
  3486.  
  3487.                 if (st < 0) st = 0;
  3488.  
  3489.                 new_a_screen (file, st, acc);
  3490.  
  3491.                 continue;
  3492.                 }
  3493.  
  3494.             default: beep();
  3495.             }
  3496.  
  3497.         }
  3498.  
  3499.     no_cursor();
  3500.     return (wfg) - 1;
  3501.     }
  3502.  
  3503. BYTE far read_next_rcd (BYTE file, BYTE * error_str)
  3504.     {
  3505.     /*  gets next record in file if no marker active,
  3506.         next record in marker file if marker active
  3507.  
  3508.         returns: 0=OK - I did that, 1=end of file, 2=error
  3509.  
  3510.         note that this function opens control file and LEAVES IT OPEN  */
  3511.  
  3512.     BYTE b, ret_val;
  3513.  
  3514.     WORD seq, recno;
  3515.  
  3516.     double msbin;
  3517.  
  3518.     /*  set error message, just in case */
  3519.  
  3520.     strcpy (gp_str [6], "READ INTO CONTROL FILE FAILED");
  3521.     strcpy (gp_str [9], "READ INTO MARKER FILE FAILED");
  3522.  
  3523. start:
  3524.  
  3525.     if (fi [file].mkr_active)
  3526.         {
  3527.         /*  check for eof  */
  3528.  
  3529.         if (fi [file].m_next_rcd >= fi [file].m_num_rcds) return (1);
  3530.  
  3531.         /*  determine next record sequence in marker  */
  3532.  
  3533.         fseek (fi [file].marker, ((DWORD) fi [file].m_next_rcd *
  3534.               fi [file].m_rcd_len) + 125, SEEK_SET);
  3535.  
  3536.         b = fread (& seq, 1, 2, fi [file].marker);
  3537.         if (b != 2)
  3538.             {
  3539.             strcpy (error_str, gp_str [6]);
  3540.             return (2);
  3541.             }
  3542.  
  3543.         /*  read in first counter value, if any  */
  3544.  
  3545.         if (fi [file].m_rcd_len > 2)
  3546.             {
  3547.             b = fread (& msbin, 1, 8, fi [file].marker);
  3548.             if (b != 8)
  3549.                 {
  3550.                 strcpy (error_str, gp_str [9]);
  3551.                 return (2);
  3552.                 }
  3553.  
  3554.             if (fi [file].c1_sw) dmsbintoieee(& msbin, & fi [file].c1_val);
  3555.             else dmsbintoieee(& msbin, & fi [file].c2_val);
  3556.             }
  3557.  
  3558.         /*  read in second counter value, if any  */
  3559.  
  3560.         if (fi [file].m_rcd_len > 10)
  3561.             {
  3562.             b = fread (& msbin, 1, 8, fi [file].marker);
  3563.             if (b != 8)
  3564.                 {
  3565.                 strcpy (error_str, gp_str [9]);
  3566.                 return (2);
  3567.                 }
  3568.  
  3569.             dmsbintoieee(& msbin, & fi [file].c2_val);
  3570.             }
  3571.  
  3572.         /*  markers were written by BASIC, where 1 is zero  */
  3573.  
  3574.         seq --;
  3575.  
  3576.         /*  increment record sequence  */
  3577.  
  3578.         fi [file].m_next_rcd += 1;
  3579.         }
  3580.  
  3581.     else
  3582.         {
  3583.         /*  check for eof  */
  3584.  
  3585.         if (fi [file].next_rcd >= fi [file].num_rcds) return (1);
  3586.  
  3587.         /*  determine next record sequence in file  */
  3588.  
  3589.         seq = fi [file].next_rcd;
  3590.  
  3591.         /*  increment record sequence  */
  3592.  
  3593.         fi [file].next_rcd += 1;
  3594.         }
  3595.  
  3596.     /*  open control file if not already open  */
  3597.  
  3598.     b = condit_open (file, 3, "rb");
  3599.     if (b == 2)
  3600.         {
  3601.         strcpy (error_str, "UNABLE TO OPEN CONTROL FILE");
  3602.         return (2);
  3603.         }
  3604.  
  3605.     /*  find desired record in control file  */
  3606.  
  3607.     fseek (fi [file].ctrl, (DWORD) seq, SEEK_SET);
  3608.  
  3609.     /*  verify that desired record has not been deleted  */
  3610.  
  3611.     b = fread (& recno, 1, 2, fi [file].ctrl);
  3612.     if (b != 2)
  3613.         {
  3614.         strcpy (error_str, gp_str [6]);
  3615.         return (2);
  3616.         }
  3617.  
  3618.     /*  bypass deleted record  */
  3619.  
  3620.     if (recno == 0) goto start;
  3621.  
  3622.     /*  read record into buffer  */
  3623.  
  3624.     ret_val = read_MAGErcd (file, seq);
  3625.  
  3626.     return (ret_val);
  3627.     }
  3628.  
  3629. BYTE far get_cntr (BYTE file, BYTE cntr, double * target, BYTE * error_str)
  3630.     {
  3631. /*    gets counter value for current record from DATAMAGE MARKER file  */
  3632.  
  3633.     if (! fi [file].mkr_active)
  3634.         {
  3635.         strcpy (error_str, "NO MARKER ACTIVE FOR FILE: ");
  3636.         itoa (file, gp_str [11], 10);
  3637.         strcat (error_str, gp_str [11]);
  3638.         return (1);
  3639.         }
  3640.  
  3641.     if ( fi [file].counter_sw == 0 ||
  3642.          (cntr == 1 && fi [file].counter_sw == 2) ||
  3643.          (cntr == 2 && fi [file].counter_sw == 1) )
  3644.         {
  3645.         strcpy (error_str, "COUNTER: ");
  3646.         itoa (cntr, gp_str [11], 10);
  3647.         strcat (error_str, gp_str [11]);
  3648.         strcat (error_str, " INACTIVE IN FILE: ");
  3649.         itoa (file + 1, gp_str [11], 10);
  3650.         strcat (error_str, gp_str [11]);
  3651.         return (1);
  3652.         }
  3653.  
  3654.     if (cntr == 1) * target = fi [file].c1_val;
  3655.     else * target = fi [file].c2_val;
  3656.  
  3657.     return (0);
  3658.     }
  3659.  
  3660. /*    DATAMAGE marker files
  3661.  
  3662.     Like any good programmer I am LOATHE to waste as much as a single byte
  3663.     of disk space or memory.  But the MARKER FILES are written by BASIC,
  3664.     and the smallest memory item it provides is a short (SWORD here).
  3665.  
  3666.     Anyhow, the MARKER files start off with a quotated 37 byte string that
  3667.     holds the user's description of the maker file, with no cr-lf.
  3668.  
  3669.     Then the first "header" is 40 bytes long.  Not all of them are currently
  3670.     used, some are reserved for future expansion so as not to make every-
  3671.     body's markers obsolete when they get an update.  There are no more
  3672.     cr-lfs in the file until you get to the end, where the user-assigned
  3673.     names of the two counters are stored in quotated strings.
  3674.  
  3675.     The following are all SWORDS:
  3676.  
  3677.     Next is the number of records in the MARKER.
  3678.  
  3679.     Next is the binary search switch (detailed in the fi struct, above).
  3680.  
  3681.     Next is the number of binary search levels.
  3682.  
  3683.     Next is counter 1 switch, detailed below.
  3684.  
  3685.     Next is counter 2 switch, detailed below.
  3686.  
  3687.     Now we move to offset 77 in the file, and read in the binary search
  3688.     targets, and their formats.  The second "header" is 48 bytes long.
  3689.     See asf [8] [3] in the fi structure atop this file.
  3690.  
  3691.     The records in the MARKER file start at offset 125.  The records are
  3692.     recorded as FILE SEQUENCES.  You might do well to check their record
  3693.     number in the CTRLFILE.RAD.  They might have been deleted!  See the
  3694.     get_next_rcrd function.
  3695.  
  3696.     Finally, there are the two quotated, 37 byte strings with cr-lfs for
  3697.     the names of the counters.
  3698.  
  3699.     Note that the marker file is left open.  It must, of course, remain
  3700.     open while being processed.  You will need to close it at some point.
  3701.  
  3702.     This function does everything you might wish to do with a marker.  If
  3703.     you don't plan to use the binary searches feel free to REMOVE the code
  3704.     that does that.  But keep a copy of the original, for future programs.
  3705. */
  3706.  
  3707. BYTE far load_marker (BYTE file, BYTE * error_str)
  3708.     {
  3709.     BYTE b, d;
  3710.  
  3711.     BYTE asf [8] [3];
  3712.  
  3713.     WORD i, j;
  3714.  
  3715.     WORD num_rcds;
  3716.     SBYTE counter_sw;
  3717.     SBYTE bs_sw;
  3718.     SBYTE b_levels;
  3719.     SBYTE c1_sw;
  3720.     SBYTE c2_sw;
  3721.     BYTE rcd_len;
  3722.  
  3723.     struct
  3724.         {
  3725.         SBYTE high_byte;
  3726.         BYTE  low_byte;
  3727.         } tgt;
  3728.  
  3729.     /*  close marker file if currently open  */
  3730.  
  3731.     if (fi [file].marker)
  3732.         {
  3733.         fclose (fi [file].marker);
  3734.         fi [file].marker = NULL;
  3735.  
  3736.         fi [file].mkr_active = 0;
  3737.         }
  3738.  
  3739.     /*  set error just in case  */
  3740.  
  3741.     strcpy (error_str, "BAD MARKER FILE");
  3742.  
  3743.     /*  init asf array  */
  3744.  
  3745.     for (d = 0; d < 7; d++)
  3746.         for (b = 0; b < 2; b++) asf [d] [b] = 0;
  3747.  
  3748.      if ((fi [file].marker = fopen (gp_str [10], "r+b")) == NULL)
  3749.         {
  3750.         strcpy (error_str, "UNABLE TO OPEN MARKER FILE");
  3751.         return (1);
  3752.         }
  3753.  
  3754.     /*  get marker description  */
  3755.  
  3756.     fread (gp_str [13], 1, 37, fi [file].marker);
  3757.     gp_str [13] [37] = 0;
  3758.  
  3759.     /*  test for valid marker file  */
  3760.  
  3761.     if (gp_str [13] [0] != 34 || gp_str [13] [36] != 34) return (1);
  3762.  
  3763.     /*  get number of records in marker  */
  3764.  
  3765.     b = fread (& num_rcds, 1, 2, fi [file].marker);
  3766.     if (b != 2) return (1);
  3767.  
  3768.     /*  get counter switch  */
  3769.  
  3770.     b = fread (& tgt, 1, 2, fi [file].marker);
  3771.     if (b != 2) return (1);
  3772.  
  3773.     counter_sw = tgt.high_byte;
  3774.  
  3775.     /*  determine length of record in marker file  */
  3776.  
  3777.      switch (counter_sw)
  3778.         {
  3779.         case 0: rcd_len = 2; break;
  3780.         case 1:
  3781.         case 2: rcd_len = 10; break;
  3782.         case 3: rcd_len = 18;
  3783.         }
  3784.  
  3785.     /*  get binary search switch 1= active, 2=no  */
  3786.  
  3787.     b = fread (& tgt, 1, 2, fi [file].marker);
  3788.     if (b != 2) return (1);
  3789.  
  3790.     bs_sw = tgt.high_byte;
  3791.  
  3792.      /*  get number of binary search targets  */
  3793.  
  3794.     b = fread (& tgt, 1, 2, fi [file].marker);
  3795.     if (b != 2) return (1);
  3796.  
  3797.     b_levels = tgt.high_byte;
  3798.  
  3799.     /*  get c1 switch  */
  3800.  
  3801.     b = fread (& tgt, 1, 2, fi [file].marker);
  3802.     if (b != 2) return (1);
  3803.  
  3804.     c1_sw = tgt.high_byte;
  3805.  
  3806.     /*  get c2 switch  */
  3807.  
  3808.     b = fread (& tgt, 1, 2, fi [file].marker);
  3809.     if (b != 2) return (1);
  3810.  
  3811.     c2_sw = tgt.high_byte;
  3812.  
  3813.     /*  move to binary fields in marker file  */
  3814.  
  3815.     d = fseek (fi [file].marker, (DWORD) 77, SEEK_SET);
  3816.  
  3817.     /*  read in binary search targets, if any  */
  3818.  
  3819.     if (bs_sw > 0)
  3820.          for (d = 0; d < b_levels; d++)
  3821.             {
  3822.             b = fread (& tgt, 1, 2, fi [file].marker);
  3823.             if (b != 2) return (1);
  3824.  
  3825.               i = get_curr_fno(file, tgt.high_byte);
  3826.  
  3827.             if (i == -1)
  3828.                 {
  3829.                 clw (2); beep(); locate (12, 12);
  3830.                 prnt ("MARKER CONTAINS FIELDS DELETED FROM FILE - LOAD ABORTED!");
  3831.  
  3832.                 see_screen ();
  3833.  
  3834.                 return (1);
  3835.                 }
  3836.  
  3837.               asf [d] [0] = (BYTE) i;
  3838.  
  3839.             b = fread (& tgt, 1, 2, fi [file].marker);
  3840.             if (b != 2) return (1);
  3841.  
  3842.               asf [d] [1] = tgt.high_byte;
  3843.  
  3844.             b = fread (& tgt, 1, 2, fi [file].marker);
  3845.             if (b != 2) return (1);
  3846.  
  3847.               asf [d] [2] = tgt.high_byte;
  3848.             }
  3849.  
  3850.     /*  fill fi [file] struct  */
  3851.  
  3852.     fi [file].m_num_rcds = num_rcds;
  3853.     fi [file].counter_sw = counter_sw;
  3854.     fi [file].bs_sw = bs_sw;
  3855.     fi [file].b_levels = b_levels;
  3856.     fi [file].c1_sw = c1_sw;
  3857.     fi [file].c2_sw = c2_sw;
  3858.     fi [file].m_rcd_len = rcd_len;
  3859.     fi [file].m_next_rcd = 0;
  3860.  
  3861.     /*  fill fi [file].asf array  */
  3862.  
  3863.     for (d = 0; d < 7; d++)
  3864.         for (b = 0; b < 2; b++)
  3865.             fi [file].asf [d] [b] = asf [d] [b];
  3866.  
  3867.     /*  reset file to first record  */
  3868.  
  3869.     fi [file].next_rcd = 0;
  3870.  
  3871.     /*  activate marker  */
  3872.  
  3873.     fi [file].mkr_active = 1;
  3874.  
  3875.     /*  move to records in marker file  */
  3876.  
  3877.     d = fseek (fi [file].marker, (DWORD) 125, SEEK_SET);
  3878.  
  3879.     /*  a-tha a-tha a-that's ALL, kiddies  */
  3880.  
  3881.     return (0);
  3882.     }
  3883.  
  3884. WORD far minpt (BYTE file, BYTE field, BYTE * t_str)
  3885.     {
  3886. /*  performs kybd input for DATAMAGE fields  */
  3887.  
  3888.     BYTE c, cc, cl, d, inst = 0, len, psw = 0, scr_pos,
  3889.          start = 0, max, tgt_pos, type, wfg = 0, x;
  3890.  
  3891.     SBYTE s;
  3892.  
  3893.     BYTE * test;
  3894.  
  3895.     if (fi [file].key[field] -> type < 2)
  3896.         {
  3897.         len = max = fi [file].key [field] -> length;
  3898.  
  3899.         if (max > 35) max = 35;
  3900.  
  3901.         type = 1;
  3902.         }
  3903.  
  3904.     else
  3905.         {
  3906.         len = max = 17;
  3907.  
  3908.         type = 2;
  3909.         }
  3910.  
  3911.     find_cursor (& cl, & cc); cc += 2;
  3912.  
  3913.     ipt_box (cc, cl, max, 32, 1, 1, t_str);
  3914.  
  3915.     rtrim (t_str);
  3916.  
  3917.     d = x = strlen (t_str);
  3918.  
  3919.     if (x > max) x = 0;
  3920.  
  3921.     scr_pos = cc + x;
  3922.  
  3923.     tgt_pos = x;
  3924.  
  3925.     for (; d < len; d++) t_str [d] = 32;
  3926.  
  3927.     t_str [len] = 0;
  3928.  
  3929.     locate (cl, scr_pos);
  3930.  
  3931.     nrml_cursor ();
  3932.  
  3933.     /*  detect decimal if numeric seeded input  */
  3934.  
  3935.     if (type == 2)
  3936.         {
  3937.         test = strstr (t_str, ".");
  3938.  
  3939.         if (test == NULL) psw = 0;
  3940.         else psw = 1;
  3941.         }
  3942.  
  3943.     while (! wfg)
  3944.         {
  3945.         get_one (& ctrl_val, & nrml_val);
  3946.  
  3947.         if (nrml_val)
  3948.             {
  3949.             if ((type == 1 && nrml_val > 31 && nrml_val < 126) ||
  3950.                 (type == 2 && nrml_val > 44 && nrml_val < 58))
  3951.                 {
  3952.                 if (type == 2)
  3953.                     {
  3954.                     /*  decimal  */
  3955.  
  3956.                     if (nrml_val == 46)
  3957.                         {
  3958.                         if (psw == 1) {beep (); continue;}
  3959.  
  3960.                         psw = 1;
  3961.                         }
  3962.  
  3963.                     /*  minus sign  */
  3964.  
  3965.                     if (nrml_val == 45 &&
  3966.                         (tgt_pos > 0 || t_str [0] == 45))
  3967.                         {beep (); continue;}
  3968.                     }
  3969.  
  3970.                 if (tgt_pos >= len) {beep (); continue;}
  3971.  
  3972.                 if (! inst)
  3973.                     {
  3974.                     t_str [tgt_pos++] = nrml_val;
  3975.  
  3976.                     if ((scr_pos - cc) < max)
  3977.                         {
  3978.                         tele_out (nrml_val);
  3979.  
  3980.                         scr_pos++;
  3981.                         }
  3982.  
  3983.                     else
  3984.                         {
  3985.                         locate (cl, cc);
  3986.  
  3987.                         x = ++start + max;
  3988.  
  3989.                         for (d = start; d < x; d++)
  3990.                             tele_out (t_str [d]);
  3991.  
  3992.                         locate (cl, scr_pos);
  3993.                         }
  3994.  
  3995.                     }
  3996.  
  3997.                 else
  3998.                     {
  3999.                     if (t_str [len - 1] != 32) {beep (); continue;}
  4000.  
  4001.                     for (d = len; d > tgt_pos; d--)
  4002.                         t_str [d] = t_str [d - 1];
  4003.  
  4004.                     t_str [tgt_pos++] = nrml_val;
  4005.  
  4006.                     if (scr_pos - cc + 1> max) ++start;
  4007.                     else scr_pos++;
  4008.  
  4009.                     locate (cl, cc); no_cursor();
  4010.  
  4011.                     x = start + max;
  4012.  
  4013.                     for (d = start; d < x; d++) tele_out (t_str [d]);
  4014.  
  4015.                     locate (cl, scr_pos); full_cursor();
  4016.                     }
  4017.  
  4018.                 continue;
  4019.                 }
  4020.  
  4021.             switch (nrml_val)
  4022.                 {
  4023.                 case 8 :    /*  backspace */
  4024.                     {
  4025.                     if (scr_pos <= cc) {beep (); continue;}
  4026.  
  4027.                     if (scr_pos - cc <= start) --start;
  4028.                          else --scr_pos;
  4029.  
  4030.                     --tgt_pos;
  4031.  
  4032.                     locate (cl, scr_pos);
  4033.  
  4034.                     goto del_char;
  4035.                     }
  4036.  
  4037.                 /*  return  */
  4038.  
  4039.                 case 13: {wfg = 2; continue;}
  4040.  
  4041.                 case 27:  /*  escape  */
  4042.                     {
  4043.                     no_cursor ();
  4044.                     locate (cl, cc);
  4045.                     line_out (max, 32);
  4046.  
  4047.                     locate (cl, cc);
  4048.  
  4049.                     tgt_pos = 0; scr_pos = cc; inst = 0;
  4050.  
  4051.                     for (d = 0; d < len; d++) t_str [d] = 32;
  4052.  
  4053.                     nrml_cursor ();
  4054.  
  4055.                     start = t_str [len] = 0;
  4056.  
  4057.                     beep (); continue;
  4058.                     }
  4059.  
  4060.                 default : {beep (); continue;}
  4061.                 }
  4062.  
  4063.             }
  4064.  
  4065.         switch (ctrl_val)
  4066.             {
  4067.             case 71 :  /*  home  */
  4068.                 {
  4069.                 start = tgt_pos = 0; scr_pos = cc;
  4070.  
  4071.                 locate (cl, scr_pos); no_cursor();
  4072.  
  4073.                 for (d = 0; d < max; d++) tele_out (t_str [d]);
  4074.  
  4075.                 locate (cl, scr_pos);
  4076.  
  4077.                 if (inst) full_cursor ();
  4078.                 else nrml_cursor ();
  4079.  
  4080.                 continue;
  4081.                 }
  4082.  
  4083.             case 75 :  /*  left arrow  */
  4084.                 {
  4085.                 if (tgt_pos < 1) {beep(); continue;}
  4086.  
  4087.                 if (scr_pos > cc)
  4088.                     {
  4089.                     locate (cl, --scr_pos);
  4090.  
  4091.                     --tgt_pos;
  4092.  
  4093.                     continue;
  4094.                     }
  4095.  
  4096.                 if (start < 1) {beep (); continue;}
  4097.  
  4098.                 locate (cl, cc);
  4099.  
  4100.                 x = --start + max;
  4101.  
  4102.                 for (d = start; d < x; d++) tele_out (t_str [d]);
  4103.  
  4104.                 --tgt_pos;
  4105.  
  4106.                 locate (cl, scr_pos); no_cursor();
  4107.  
  4108.                 if (inst) full_cursor ();
  4109.                 else nrml_cursor ();
  4110.  
  4111.                 continue;
  4112.                 }
  4113.  
  4114.             case 115:  /*  ctrl + left arrow  */
  4115.                 {
  4116.                 if (! tgt_pos) {beep(); continue;}
  4117.  
  4118.                 x = tgt_pos;
  4119.  
  4120.                 while (x && t_str [x] != 32) --x;
  4121.  
  4122.                 while (x && t_str [x] == 32) --x;
  4123.  
  4124.                 while (x && t_str [x] != 32) --x;
  4125.  
  4126.                 if (x) ++x;
  4127.  
  4128.                     c = tgt_pos - x; tgt_pos -= c;
  4129.  
  4130.                 if (scr_pos - cc - c > -1) scr_pos -= c;
  4131.  
  4132.                 else
  4133.                     {
  4134.                     s = start - c;
  4135.  
  4136.                     if (s < 0)
  4137.                         {
  4138.                         scr_pos -= 0 - s;
  4139.  
  4140.                         s = 0; beep();
  4141.                         }
  4142.  
  4143.                     start = s;
  4144.  
  4145.                     locate (cl, cc); no_cursor();
  4146.  
  4147.                     x = start + max;
  4148.  
  4149.                     for (d = start; d < x; d++) tele_out (t_str [d]);
  4150.  
  4151.                     if (inst) full_cursor ();
  4152.                     else nrml_cursor ();
  4153.                     }
  4154.  
  4155.                 locate (cl, scr_pos);
  4156.  
  4157.                 continue;
  4158.                 }
  4159.  
  4160.             case 77 :  /*  right arrow  */
  4161.                 {
  4162.                 if (tgt_pos >= len) {beep(); continue;}
  4163.  
  4164.                 if (scr_pos - cc < max)
  4165.                     {
  4166.                     locate (cl, ++scr_pos);
  4167.  
  4168.                     ++tgt_pos;
  4169.  
  4170.                     continue;
  4171.                     }
  4172.  
  4173.                 if (start >= (len - max)) {beep(); continue;}
  4174.  
  4175.                 locate (cl, cc); no_cursor();
  4176.  
  4177.                 x = ++start + max; ++tgt_pos;
  4178.  
  4179.                 for (d = start; d < x; d++) tele_out (t_str [d]);
  4180.  
  4181.                 locate (cl, scr_pos);
  4182.  
  4183.                 if (inst) full_cursor ();
  4184.                 else nrml_cursor ();
  4185.  
  4186.                 continue;
  4187.                 }
  4188.  
  4189.             case 116:  /*  ctrl + right arrow  */
  4190.                 {
  4191.                 c = 0; x = tgt_pos;
  4192.  
  4193.                 while (x < len && c < 2)
  4194.                     {
  4195.                     if (! c)
  4196.                         {
  4197.                         if (t_str [x] != 32) x++;
  4198.                         else c++;
  4199.  
  4200.                         continue;
  4201.                         }
  4202.  
  4203.                     if (t_str [x] == 32) x++;
  4204.                     else c++;
  4205.                     }
  4206.  
  4207.                 if (c < 2) continue;
  4208.  
  4209.                     c = x - tgt_pos;
  4210.  
  4211.                 if (scr_pos - cc + c < max)
  4212.                     {
  4213.                     tgt_pos += c;
  4214.  
  4215.                     scr_pos += c;
  4216.                     }
  4217.  
  4218.                 else
  4219.                     {
  4220.                     d = start + c;
  4221.  
  4222.                     if (d > len) x = len - d;
  4223.                     else x = c;
  4224.  
  4225.                     tgt_pos += x; start += x;
  4226.  
  4227.                     locate (cl, cc); no_cursor();
  4228.  
  4229.                     x = start + max;
  4230.  
  4231.                     for (d = start; d < x; d++) tele_out (t_str [d]);
  4232.  
  4233.                     if (inst) full_cursor ();
  4234.                     else nrml_cursor ();
  4235.                     }
  4236.  
  4237.                 locate (cl, scr_pos);
  4238.  
  4239.                 continue;
  4240.                 }
  4241.  
  4242.             case 79 :  /*  end  */
  4243.                 {
  4244.                 tgt_pos = len - 1; scr_pos = max + cc - 1;
  4245.  
  4246.                 start = len - max;
  4247.  
  4248.                 locate (cl, cc); no_cursor();
  4249.  
  4250.                 x = start + max;
  4251.  
  4252.                 for (d = start; d < x; d++) tele_out (t_str [d]);
  4253.  
  4254.                 locate (cl, scr_pos);
  4255.  
  4256.                 if (inst) full_cursor ();
  4257.                 else nrml_cursor ();
  4258.  
  4259.                 continue;
  4260.                 }
  4261.  
  4262.             case 82 :  /*  insert  */
  4263.                 {
  4264.                 if (inst == 0)
  4265.                     {
  4266.                     inst = 1;
  4267.                     full_cursor ();
  4268.  
  4269.                     continue;
  4270.                     }
  4271.  
  4272.                 inst = 0; nrml_cursor ();
  4273.                 continue;
  4274.                 }
  4275.  
  4276.             case 83 :  /*  delete  */
  4277.                 {
  4278.                 if (tgt_pos > len) {beep (); continue;}
  4279.  
  4280. del_char:
  4281.  
  4282.  
  4283.                 if (t_str [tgt_pos] == 46) psw = 0;
  4284.  
  4285.                 for (d = tgt_pos; d < len; d++)
  4286.                     t_str [d] = t_str [d + 1];
  4287.  
  4288.                 t_str [len] = 32;
  4289.  
  4290.                 locate (cl, cc); no_cursor();
  4291.  
  4292.                 x = start + max;
  4293.  
  4294.                 for (d = start; d < x; d++) tele_out (t_str [d]);
  4295.  
  4296.                 locate (cl, scr_pos);
  4297.  
  4298.                 if (inst) full_cursor ();
  4299.                 else nrml_cursor ();
  4300.  
  4301.                 continue;
  4302.                 }
  4303.  
  4304.             default: {beep (); continue;}
  4305.             }
  4306.  
  4307.         }
  4308.  
  4309.     ipt_box (cc, cl, max, 32, 1, 0, t_str);
  4310.  
  4311.     no_cursor ();
  4312.  
  4313.     rtrim (t_str);
  4314.  
  4315.     return (strlen (t_str));
  4316.     }
  4317.