home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
database
/
datamage.zip
/
CODE.ZIP
/
MAGEISAM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-24
|
88KB
|
4,317 lines
/*****************************************************************************
* *
* I can but assume that you are a better C programmer than my humble *
* self. I have had no formal training in this language, but have *
* taught it to myself by doing it. *
* *
* The DATAMAGE ISAM is, at the very least, unique. You are looking for *
* something VERY complex and hard to understand. What you will find is *
* the epitome of simplicity. *
* *
* DATAMAGE makes use of the real facility offered by a computer: SPEED. *
* This raw material is harnessed to the work of data management system *
* through the application of BRUTE FORCE COMPUTING. *
* *
* If properly applied, BRUTE FORCE can have benifits. In this case they *
* are low overhead and speed. DATAMAGE indexes up to five string fields *
* in only ten bytes per record. Since there's less of it "out there" to *
* pick through we can get at it faster. *
* *
* To pick up on the DATAMAGE ISAM look the sample program: MAGEDEMO.C *
* over. It uses a few of the functions in the library and calls many *
* of the functions in the core library as well. *
* *
* All the functions have a comment line to describe their use. The vars *
* passed are named descriptively. The code is sparsly documented. I *
* didn't plan to release it; there would be more comments if I did. *
* *
* Like I said in the HCWP_LIB.C file: NO attempt has been made to be *
* "cute" with the code. Rather, I have attempted to write it so that *
* those new to C might have a chance to understand it. *
* *
*****************************************************************************/
#include <dos.h>
#include <math.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "c:\qc\pf\hcwp_lib.h"
BYTE readf, /* flag for necessity of getting files from disk */
pth_str [81], /* holds current path */
r_buff [256], /* small buffer - misc tasks */
f_buff [10241], /* large buffer - read/write records */
files_loaded; /* number DATAMAGE files currently open */
SWORD ftot [2];
typedef struct /* structure holding field definitions */
{
BYTE name [27]; /* name of field */
BYTE type; /* 0=date 1=string 2=numeric 3=dollar */
BYTE length; /* length of field */
BYTE spare; /* explained below */
BYTE abs; /* absolute field number */
WORD offset; /* offset of field in record */
} fdef;
/* definition of fdef.spare:
switch (fdef.type)
{
case 0: defines date field format: 0=mm/dd/yy 1=dd/mm/yy
case 1: defines index mode for string: 0=none 1=unique 2=normal 3=cross
case 2: defines number of decimals to maintain in numeric field
case 3: always 2, defines precision of dollar format field
} */
typedef struct /* structure holding loaded datafiles */
{
/* NOMINCLATURE */
BYTE dir [51]; /* directory name holding file */
BYTE des [41]; /* description of loaded file */
/* NUMERIC DATA */
DWORD rcd_len; /* length of record in bytes */
WORD num_rcds; /* number of records in file */
WORD num_flds; /* number of fields in file */
/* array of far pointers to type fdef (defined above) */
fdef far * key [200];
/* data relating to idnexes and searches of same */
BYTE indexes; /* holds number of indexed fields */
BYTE indexed_fields [5]; /* holds numbers of indexed fields */
BYTE unique_field; /* 1 = unique fields 2=no */
BYTE cross_fields; /* number of cross-indexed fields */
BYTE cross_cntr; /* number of cross-indexed fields selected */
BYTE write_sw; /* 0=no write to file, 1=write record */
DWORD rw_sw; /* 0=not ready for read
1=ready after (row * 7800) + col */
BYTE i_case [5]; /* 1=ignore case/spacing in search 0=no */
SWORD index_results [5]; /* holds index of record being checked */
SWORD disk_index [5]; /* holds indexs read fron disk - buffer */
/* LOAD INFORMATION */
WORD sequence; /* file sequence# of record in buffer */
WORD next_rcd; /* sequence of next record */
WORD r_number; /* record number of record in buffer */
BYTE m_name [53]; /* main datafile path/filename */
BYTE i_name [53]; /* index file path/filename */
BYTE c_name [53]; /* control file path/filename */
/* FILE POINTERS TO THE THREE ASSOCIATED FILES */
FILE * main; /* pointer for main datafile buffer */
FILE * indx; /* pointer for index file buffer */
FILE * ctrl; /* pointer for control file buffer */
/* MARKER FILE INFORMATION */
BYTE mkr_active; /* 0=process file, 1=process marker */
FILE * marker; /* pointer for marker file buffer */
WORD m_num_rcds; /* holds number of records in mkr */
WORD m_next_rcd; /* holds next record seq in marker */
BYTE m_rcd_len; /* holds record length in marker */
BYTE b_levels; /* holds number of search levels */
SBYTE bs_sw; /* binary search switch
-10 = inactive
-2 = search counter 2
-1 = search counter 1
0 = search record numbers
1 = search disk data */
BYTE asf [8] [3]; /* holds details of current binary order
pos 0 = target field + 1
pos 1 = format:
1 = nromal
2 = name
3 = string as numeric
pos 2 = ignore case/spacing
(not recorded - user selected)
0 = no, 1 = yes */
BYTE counter_sw; /* 0= no counters in marker,
1= counter 1 in marker,
2= counter 2 in marker,
3= both */
SBYTE c1_sw; /* -1= counter is inactive,
0-8=decimal precision,
9=no rounding */
double c1_val; /* value of counter 1, if any */
SBYTE c2_sw; /* as above */
double c2_val; /* value of counter 2, if any */
/* BUFFER */
BYTE far * buff; /* buffer for this file */
} file_info;
file_info fi [8]; /* change the 8 to your max open files */
typedef struct /* structure holding data for display */
{
BYTE r_val; /* holds return value if selected */
BYTE disp [65]; /* holds string to be displayed */
BYTE rtrn [65]; /* holds string to be returned */
} w_data;
w_data far window_data [200];
typedef struct /* structure holding files found */
{
BYTE name [13]; /* holds name of dir or file */
BYTE desc [37]; /* holds description of file */
}files_found;
files_found far files [2] [50];
/* FUNCTIONS INCLUDED IN THIS MODULE */
void far decoder ();
SWORD far index_field (BYTE * target);
void far set_field (BYTE, BYTE, BYTE, BYTE *);
void far get_field (BYTE, WORD, BYTE, BYTE *);
BYTE far read_field (BYTE, WORD, WORD, BYTE *);
BYTE far write_field (BYTE, WORD, WORD, BYTE *);
BYTE far index_MAGErecord (BYTE);
BYTE far find_MAGErecord (BYTE, WORD, BYTE, WORD);
BYTE far find_MAGErecord_nmbr (BYTE, WORD);
BYTE far access_MAGE_record (BYTE, BYTE, BYTE);
BYTE far write_MAGErcd (BYTE);
BYTE far read_MAGErcd (BYTE, WORD);
BYTE far read_next_rcd (BYTE, BYTE *);
void far print_MAGE_record (BYTE file);
BYTE far search_MAGE_files (BYTE, BYTE);
BYTE far vs_MAGE_recrd (BYTE, BYTE, BYTE *);
BYTE far get_files (BYTE *, BYTE);
BYTE far select_datafile ();
BYTE far open_file (BYTE);
void far close_file (BYTE);
BYTE far condit_open (BYTE, BYTE, BYTE *);
BYTE far ready_files (SBYTE);
BYTE far get_next_rno (BYTE);
BYTE far show_files (BYTE);
BYTE far show_datafiles (BYTE);
BYTE far show_fields (BYTE, BYTE);
BYTE far show_menu ();
void far fill_window (BYTE, SWORD *, SWORD *, BYTE);
BYTE far work_window (BYTE, SWORD *, SWORD *, BYTE);
void far window_line (BYTE, BYTE, BYTE, BYTE);
SWORD far get_curr_fno (BYTE file, WORD field);
BYTE far get_cntr (BYTE, BYTE, double *, BYTE *);
BYTE far load_marker (BYTE, BYTE *);
WORD far minpt (BYTE, BYTE, BYTE *);
/* local functions */
void a_menu (BYTE, BYTE);
void a_line (BYTE, WORD, WORD, BYTE *);
void new_a_screen (BYTE, SWORD, BYTE *);
void field_line (BYTE, WORD);
/*-------------------------------------------------------------------------*/
SWORD far get_curr_fno (BYTE file, WORD field)
{
/* returns the current field number of an absolute field */
SWORD d = 0;
SWORD ret_val = -1;
if (fi [file].key [field] -> abs == field) return (field);
while (d < fi [file].num_flds && ret_val == -1)
{
if (fi [file].key [d] -> abs == field) ret_val = d;
d++;
}
return (ret_val);
}
void far decoder ()
{
/* provides ignoring of case, spacing and double chars for index searches */
BYTE d, m, chr, last_chr = 0, len;
len = strlen (c_s [0]);
for (d = 0, m = 0; m < len; m++)
{
chr = c_s [0] [m];
if (chr > 96 && chr < 123) chr -= 32;
if (m && chr == last_chr) continue;
if ( (chr > 64 && chr < 91) ||
(chr > 47 && chr < 58) )
c_s [1] [d++] = chr;
last_chr = chr;
}
c_s [1] [d] = 0;
/* printf ("\n%s\n%s\n", c_s [0], c_s [1]); */
}
void far set_field (BYTE file, BYTE field, BYTE nmbr, BYTE * source)
{
/* sets field into file buffer */
BYTE register d;
BYTE far * target;
target = fi [file].buff + fi [file].key [field] -> offset;
for (d = 0; d < nmbr && d < fi [file].key [field] -> length;)
* (target + d++) = * (source + d);
}
void far get_field (BYTE file, WORD field, BYTE nmbr, BYTE * target)
{
/* gets field from file buffer */
BYTE register d;
BYTE far * source;
source = fi [file].buff + fi [file].key [field] -> offset;
for (d = 0; d < nmbr && d < fi [file].key [field] -> length;)
* (target + d++) = * (source + d);
if (fi [file].key [field] -> type < 2) * (target + d) = 0;
}
BYTE far read_field (BYTE file, WORD sequence, WORD fieldno, BYTE * target)
{
/* reads field from DATAMAGE file, FILE MUST BE OPEN!! */
BYTE c;
DWORD offset;
offset = (fi [file].rcd_len * sequence) +
fi [file].key [fieldno] -> offset;
if (offset > (DWORD) fi [file].rcd_len * fi [file].num_rcds) return (1);
c = fseek (fi [file].main, offset, SEEK_SET);
fread (target, 1, fi [file].key [fieldno] -> length, fi [file].main);
if (fi [file].key [fieldno] -> type < 2)
target [fi [file].key [fieldno] -> length] = 0;
return (0);
}
BYTE far write_field (BYTE file, WORD sequence, WORD fieldno, BYTE * target)
{
/* writes field into DATAMAGE file, FILE MUST BE OPEN!! */
BYTE c, d, len;
DWORD offset;
len = fi [file].key [fieldno] -> length;
offset = (fi [file].rcd_len * sequence) +
fi [file].key [fieldno] -> offset;
if (offset > (DWORD) fi [file].num_rcds * fi [file].rcd_len) return (1);
for (d = 0; d < 40; d++) r_buff [d] = 32;
for (d = 0; d < len && d < 35;) r_buff [d++] = target [d];
c = fseek (fi [file].main, offset, SEEK_SET);
fwrite( (void *) r_buff, len, 1, fi [file].main);
return (0);
}
SWORD far index_field (BYTE * target)
{
/* returns DATAMAGE index of targeted field */
BYTE b, len, m, y, z, err = 0;
SWORD x = -32768;
SDWORD check;
len = strlen (target);
for (b = 0; b < len; b++)
{
/* char to index */
y = target [b];
m = y; z = b + 1;
/* emulate BASIC's MOD function */
while (m >= z) m -= z;
check = x;
if (! m) check += y;
else check += (y + z) * m;
if (check > 32767) x = 0;
if (! m) x += y;
else x += (y + z) * m;
}
return (x);
}
BYTE far index_MAGErecord (BYTE file)
{
/* indexes record in buffer of file passed,
results in fi [file].index_results [] */
BYTE a, b, c, d, e, j;
for (d = 0; d < 5; d++) fi [file].index_results [d] = -32768;
fi [file].cross_cntr = 0; c = 0; e = 0;
for (a = 0; a < fi [file].indexes; a++)
{
j = fi [file].indexed_fields [a];
get_field (file, j, fi [file].key [j] -> length, c_s [0]);
/* remove trailing spaces */
rtrim (c_s [0]);
/* decode index string */
decoder ();
/* place index and string into search area */
fi [file].index_results [a] = index_field (c_s [1]);
if (fi [file].i_case [a]) strcpy (gp_str [a], c_s [1]);
else strcpy (gp_str [a], c_s [0]);
/* increment cross conter for screen check */
if (fi [file].key [j] -> spare == 3) fi [file].cross_cntr += 1;
/* set unique switch for screen check */
if (fi [file].key [j] -> spare == 1) e = 1;
/* end search of linklist if all keys found */
c++;
if (c == fi [file].indexes) a = fi [file].indexes;
}
if ( (fi [file].unique_field && ! e) &&
(fi [file].cross_fields &&
b < fi [file].cross_fields) )
return (1);
else return (0);
}
/* search types:
0=all indexes, check new record
1=all unique indexes, find a record
2=all non-unique indexes, find records
3=all corss indexes, find a record
type two search DOES NOT absolutely identify the record found!
returns:
0=yeah, I found it
1=no match found
setting search type to > 0 will cause function to read record
into targeted file buffer
*/
BYTE far find_MAGErecord (BYTE file, WORD start,
BYTE search_type, WORD unique_field)
{
BYTE a, b, c, close_sw [3], m, wfg = 0;
SBYTE g;
SWORD i, x;
DWORD offset = 0;
for (c = 0; c < 3; c++) close_sw [c] = 0;
if (search_type == 2)
{
for (m = 0, a = 0; a < fi [file].indexes; a++)
if (fi [file].index_results [a] > -32768) m++;
if (! m) return (1);
}
else m = fi [file].cross_fields;
/* open ctrl file */
c = condit_open (file, 3, "rb");
switch (c)
{
case 0:
{
fseek (fi [file].ctrl, (DWORD) 0, SEEK_SET);
break;
}
case 1: {close_sw [2] = 1; break;}
case 2: return (1);
}
/* open index file */
c = condit_open (file, 2, "rb");
switch (c)
{
case 0: break;
case 1:
{
close_sw [1] = 1;
break;
}
case 2: return (1);
}
/* open main file */
c = condit_open (file, 1, "rb");
switch (c)
{
case 0: break;
case 1: {close_sw [0] = 1; break;}
case 2: return (1);
}
for (i = start; ! wfg && i <= fi [file].num_rcds; i++)
{
/* don't check blank rcd */
fread (& x, 2, 1, fi [file].ctrl);
if (! x) continue;
/* don't check current rcd in search type 0 */
if (! search_type && i == fi [file].sequence) continue;
/* read index data */
fseek (fi [file].indx, (DWORD) i * 10, SEEK_SET);
fread (fi [file].disk_index, 10, 1, fi [file].indx);
b = 0; /* check indexes */
for (a = 0; ! wfg && a < fi [file].indexes; a++)
{
/* determine field # of index to check */
c = fi [file].indexed_fields [a];
/* skip indexes according to search_type */
if (search_type && search_type != 2 &&
fi [file].key [c] -> spare != search_type) continue;
if ( (search_type == 1) &&
( (unique_field && c != unique_field) || (! unique_field
&& fi [file].index_results [a] == -32768) ) ) continue;
/* skip blank indexes for type 2 check */
if (search_type == 2 && fi [file].index_results [a] == -32768)
continue;
/* skip non-unique index for new record check */
if (! search_type && fi [file].key [c] -> spare == 2) continue;
/* compare index values */
/*
locate (0,0); prnt (" ");
locate (0,0); printf ("%hi", fi [file].index_results [a]);
locate (0,40); prnt (" ");
locate (0,40); printf ("%hi", fi [file].disk_index [a]);
wait (1);
*/
if (fi [file].index_results [a] !=
fi [file].disk_index [a]) continue;
/* get indexed field from disk */
read_field (file, i, c, c_s [0]);
/* remove trailing spaces */
rtrim (c_s [0]);
/* decode disk string if ignoring case */
if (fi [file].i_case [a]) decoder ();
else strcpy (c_s [1], c_s [0]);
/* compare disk string to entry */
/*
locate (0,0); prnt (c_s [1]); prnt ("*");
locate (0,40); prnt (gp_str [a]); prnt ("*");
*/
g = strcmp (c_s [1], gp_str [a]);
if (g == 0) /* match found */
{
switch (search_type)
{
case 0: /* dup record check */
{
/* unique match */
if (fi [file].key [c] -> spare == 1)
{wfg = 1; a = 5;}
/* cross match */
if (fi [file].key [c] -> spare == 3
&& ++b >= m) {wfg = 1; a = 5;}
break;
}
case 1: /* unique */
{
wfg = 1; a = 5;
break;
}
case 2: /* non-unique */
case 3: /* cross */
{
if (++b >= m) {wfg = 1; a = 5;}
break;
}
}
}
}
}
if (close_sw [1]) {fclose (fi [file].indx); fi [file].indx = NULL;}
if (wfg && search_type) /* read record in */
{
offset = fi [file].rcd_len * --i;
c = fseek ( fi [file].main, offset, SEEK_SET);
fread ( (void *) f_buff, fi [file].rcd_len, 1, fi [file].main);
set_far (fi [file].buff, f_buff, fi [file].rcd_len);
fi [file].sequence = i;
c = fseek (fi [file].ctrl, (DWORD) fi [file].sequence * 2, SEEK_SET);
fread (& x, 2, 1, fi [file].ctrl);
fi [file].r_number = x;
}
if (close_sw [2]) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
if (close_sw [0]) {fclose (fi [file].main); fi [file].main = NULL;}
if (wfg) return (0);
return (1);
fmr_abort:
if (close_sw [2]) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
if (close_sw [1]) {fclose (fi [file].indx); fi [file].indx = NULL;}
if (close_sw [0]) {fclose (fi [file].main); fi [file].main = NULL;}
return (2);
}
BYTE far find_MAGErecord_nmbr (BYTE file, WORD search_val)
{
/* finds DATAMAGE record via user-assigned number */
BYTE c, wfg = 0;
WORD close_sw = 0, f = 0, i = 0, x = 0;
SWORD rno;
DWORD offset = 0;
/* open control file */
c = condit_open (file, 3, "r+b");
switch (c)
{
case 0:
{
fseek (fi [file].ctrl, (DWORD) 0, SEEK_SET);
break;
}
case 1:
{
close_sw = 1;
break;
}
case 2: return (1);
}
/* search control file */
while (i <= fi [file].num_rcds && ! wfg)
{
fread (& rno, 2, 1, fi [file].ctrl);
if (rno == search_val) {wfg = 1; x = i;}
i ++;
}
if (close_sw) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
/* return 1 if not found */
if (! wfg) return (1);
/* open main file */
c = condit_open (file, 1, "r+b"); close_sw = 0;
switch (c)
{
case 0: break;
case 1: {close_sw = 1; break;}
case 2: return (1);
}
/* compute offset of record found */
offset = fi [file].rcd_len * x;
/* read record in */
c = fseek (fi [file].main, offset, SEEK_SET);
fread ( (void *) f_buff, fi [file].rcd_len, 1, fi [file].main);
set_far (fi [file].buff, f_buff, fi [file].rcd_len);
/* place sequence/record number of record found */
fi [file].sequence = x;
fi [file].r_number = search_val;
/* a-tha, a-tha, a-that's all, kiddies */
if (close_sw) {fclose (fi [file].main); fi [file].main = NULL;}
return (0);
}
BYTE far search_MAGE_files (BYTE file, BYTE enty_point)
{
/* searches indexes in any DATAMAGE file, provides input, too */
BYTE a, b, c, c_e = 0, choice, d, f, ftsw = 0, line = 3,
search_type, wfg = 0, wfg2 = 0, search [5] [251];
WORD start = 0, x;
double fl;
if (! fi [file].indexes) return (1);
if (enty_point) goto search_indexes;
get_mode:
strcpy (prompts [0], "SEARCH ON:");
strcpy (prompts [1], "1=RECORD NUMBERS");
strcpy (prompts [2], "2=FILE INDEXES");
strcpy (prompts [3], "3=ABORT");
choice = get_v_choice (3, 0, 0);
if (choice == 3) return (1);
if (choice == 1)
{
clw (3); locate (22,21);
prnt ("ENTER TARGET RECORD NUMBER: ");
a = inpt (2, 5, 1, 0, 0, 32, user_enty);
if (! a) {beep(); goto get_mode;}
fl = atof (user_enty);
if (fl < 1 || fl > 32000)
{
clw (3); locate (22,19);
prnt ("LEGAL RECORD NUMBERS ARE FROM 1 TO 32,000");
wait (4); goto get_mode;
}
x = fl;
c = find_MAGErecord_nmbr (file, x);
if (c)
{
clw (3); beep(); locate (22, 28);
prnt ("THAT NUMBER WAS NOT FOUND!");
wait (4); goto get_mode;
}
return (0);
}
search_indexes:
for (d = 0; d < 5; d++) fi [file].index_results [d] = -32768;
ready_files (file);
clw (2); search_type = 1;
while (! wfg)
{
for (d = 0; d < fi [file].indexes && ! wfg; d++)
{
c = fi [file].indexed_fields [d];
b = fi [file].key [c] -> length;
if (fi [file].key [c] -> spare != search_type) continue;
locate (line, 7);
f_prnt (fi [file].key [c] -> name);
if (ftsw) strcpy (user_enty, search [d]);
else user_enty [0] = 0;
field_line (file, c);
f = cntrstrp ();
clw (3); locate (22, f); prnt (c_s [2]);
locate (line, 40); line += 2;
a = minpt (file, c, user_enty);
if (! a)
{
search [d] [0] = 0;
continue;
}
strcpy (search [d], user_enty);
strcpy (prompts [0], "CASE/SPACING OPTIONS:");
strcpy (prompts [1], "1=IGNORE");
strcpy (prompts [2], "2=MATCH");
choice = get_v_choice (2, 0, 0) - 1;
if (choice) fi [file].i_case [d] = 0;
else fi [file].i_case [d] = 1;
/* remove trailing spaces, place in file buffer */
rtrim (user_enty);
set_field (file, c, b, user_enty);
/* decode index string */
strcpy (c_s [0], user_enty);
decoder ();
/* place index value and string into search area */
fi [file].index_results [d] = index_field (c_s [1]);
if (fi [file].i_case [d]) strcpy (gp_str [d], c_s [1]);
else strcpy (gp_str [d], c_s [0]);
switch (search_type)
{
case 1: {wfg = 1; break;}
case 2: break;
case 3: {c_e ++; break;}
}
}
if (wfg) continue;
switch (search_type)
{
case 1: {search_type = 3; break;}
case 2: {wfg = 1; break;}
case 3:
{
if (c_e >= fi [file].cross_fields) {wfg = 1; break;}
search_type = 2;
}
}
}
switch (search_type)
{
case 1:
case 3:
{
c = find_MAGErecord (file, (WORD) 0, search_type, 0);
/* no match */
if (c)
{
strcpy (prompts [0], "NO MATCH FOUND");
strcpy (prompts [1], "1=RETRY");
strcpy (prompts [2], "2=ABORT");
wfg2 = get_v_choice (2, 0, 0) + 1;
break;
}
/* read record in */
read_MAGErcd (file, fi [file].sequence);
break;
}
case 2:
{
clw (2); clw (3);
beep(); locate (12, 8);
prnt ("YOU WILL HAVE TO SELECT A RECORD FROM MULTIPLE POSSIBLE MATCHES");
see_screen ();
while (! wfg2)
{
c = find_MAGErecord (file, start, search_type, 0);
if (c)
{
strcpy (prompts [0], "NO MATCH FOUND");
strcpy (prompts [1], "1=RETRY");
strcpy (prompts [2], "2=ABORT");
wfg2 = get_v_choice (2, 0, 0) + 1;
continue;
}
start = fi [file].sequence;
c = access_MAGE_record (file, 0, 1);
strcpy (prompts [0], "SEARCH OPTIONS:");
strcpy (prompts [1], "1=DESIRED RECORD WAS DISPLAYED");
strcpy (prompts [2], "2=CONTINUE SEARCH");
c = get_v_choice (2, 0, 0) - 1;
if (! c) wfg2 = 1;
else start++;
}
}
}
switch (wfg2)
{
case 0:
case 1: return (0);
case 2:
{
wfg = 0; wfg2 = 0; line = 3; c_e = 0;
ftsw = 1; start = 0; goto get_mode;
}
case 3: return (1);
}
}
BYTE far ready_files (SBYTE level)
{
/* wipes a DATAMAGE buffer, pass -1 to prepare ALL open buffers */
BYTE d;
WORD i;
double zero = 0, msbzero;
dieeetomsbin (& zero, & msbzero);
for (d = 0; d <= files_loaded; d++)
{
if (level + 1 && d != level) continue;
/* safety valve */
if (fi [d].buff == NULL) continue;
/* clear file buffer */
for (i = 0; i < fi [d].rcd_len; i++)
* (fi [d].buff + i) = 32;
/* set numerics to 0 */
for (i = 0; i < fi [d].num_flds; i++)
if (fi [d].key [i] ->type > 1)
set_far (fi [d].buff + fi [d].key [i] -> offset,
(BYTE *) & msbzero, 8);
}
return (0);
}
BYTE far condit_open (BYTE file, BYTE nmbr, BYTE * o_str)
{
/* opens a file in the fi structure if it's not already open
file nmbr: 1=main file 2=index file 3=control file
returns: 0=file was open 1=opened file 2=bombed */
BYTE ret_val = 0;
switch (nmbr)
{
case 1:
{
if (fi [file].main != NULL) break;
if ( (fi [file].main = fopen (fi [file].m_name, o_str))
== NULL) ret_val = 2;
else ret_val = 1;
break;
}
case 2:
{
if (fi [file].indx != NULL) break;
if ( (fi [file].indx = fopen (fi [file].i_name, o_str))
== NULL) ret_val = 2;
else ret_val = 1;
break;
}
case 3:
{
if (fi [file].ctrl != NULL) break;
if ( (fi [file].ctrl = fopen (fi [file].c_name, o_str))
== NULL) ret_val = 2;
else ret_val = 1;
break;
}
}
return (ret_val);
}
BYTE far write_MAGErcd (BYTE file)
{
/* writes record in buffer, updates control file (rcd#),
writes indexes if any. Call index_MAGErecord to fill index values */
BYTE c, o_type [5], close_sw;
SWORD rno = fi [file].r_number;
void * buff = & rno;
if (fi [file].num_rcds) strcpy (o_type, "rb+");
else strcpy (o_type, "wb+");
/* update ctrl file */
c = condit_open (file, 3, o_type); close_sw = 0;
switch (c)
{
case 0: break;
case 1: {close_sw = 1; break;}
case 2: return (1);
}
c = fseek (fi [file].ctrl, (DWORD) fi [file].sequence * 2, SEEK_SET);
fwrite (buff, 2, 1, fi [file].ctrl);
if (close_sw) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
else fflush (fi [file].ctrl);
/* update num rcds */
if (fi [file].sequence >= fi [file].num_rcds)
fi [file].num_rcds = fi [file].sequence + 1;
/* update main file */
buff = f_buff;
c = condit_open (file, 1, o_type); close_sw = 0;
switch (c)
{
case 0: break;
case 1: {close_sw = 1; break;}
case 2: return (1);
}
get_far (f_buff, fi [file].buff, fi [file].rcd_len);
c = fseek (fi [file].main, (DWORD) fi [file].sequence *
fi [file].rcd_len, SEEK_SET);
fwrite (buff, fi [file].rcd_len, 1, fi [file].main);
if (close_sw) {fclose (fi [file].main); fi [file].main = NULL;}
else fflush (fi [file].main);
/* update index file */
if (fi [file].indexes)
{
c = condit_open (file, 2, o_type); close_sw = 0;
switch (c)
{
case 0: break;
case 1: {close_sw = 1; break;}
case 2: return (1);
}
buff = fi [file].index_results;
c = fseek (fi [file].indx,
(DWORD) fi [file].sequence * 10, SEEK_SET);
fwrite (buff, 10, 1, fi [file].indx);
if (close_sw) {fclose (fi [file].indx); fi [file].indx = NULL;}
else fflush (fi [file].indx);
}
return (0);
}
BYTE far read_MAGErcd (BYTE file, WORD seq)
{
/* reads DATAMAGE record from disk into fi [file].buff */
BYTE c, close_sw;
SWORD rno;
/* open main file */
c = condit_open (file, 1, "r+b"); close_sw = 0;
switch (c)
{
case 0: break;
case 1: {close_sw = 1; break;}
case 2: return (1);
}
/* read main file */
c = fseek (fi [file].main, (DWORD) seq * fi [file].rcd_len, SEEK_SET);
fread (f_buff, fi [file].rcd_len, 1, fi [file].main);
if (close_sw) {fclose (fi [file].main); fi [file].main = NULL;}
set_far (fi [file].buff, f_buff, fi [file].rcd_len);
/* get record number from ctrl file */
fi [file].sequence = seq;
c = condit_open (file, 3, "r+b"); close_sw = 0;
switch (c)
{
case 0: break;
case 1: {close_sw = 1; break;}
case 2: return (1);
}
c = fseek (fi [file].ctrl, (DWORD) fi [file].sequence * 2, SEEK_SET);
fread (& rno, 2, 1, fi [file].ctrl);
fi [file].r_number = rno;
if (close_sw) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
return (0);
}
BYTE far get_next_rno (BYTE file)
{
/* finds next available record number and file sequence
places seq in fi [file].sequence, record # in fi [file].r_number */
BYTE c, close_sw, wfg = 0, choice, a;
WORD i = 0, x = 0, y, z = 0;
SWORD rno, crno, rno2, bigno = 0, crsq = 0, far * base;
SDWORD enty;
choose1:
save_window (2); clw(2);
save_window (3); clw(3);
strcpy (c_s [0], "RECORD NUMBER IN:");
strcpy (c_s [1], fi [file].des);
c = cntrstrp ();
locate (12, c); prnt (c_s [2]);
strcpy (prompts [0], "SELECT MODE:");
strcpy (prompts [1], "1=AUTO SELECT");
strcpy (prompts [2], "2=KEYBOARD ENTRY");
a = get_v_choice(2, 0, 0);
repl_window (2); repl_window (3);
/* open control file */
c = condit_open (file, 3, "rb"); close_sw = 0;
switch (c)
{
case 0: break;
case 1:
{
close_sw = 1;
break;
}
case 2: wfg = 1;
}
c = fseek (fi [file].ctrl, (DWORD) 0, SEEK_SET);
if (! fi [file].num_rcds) wfg = 1;
if (wfg)
{
beep();
strcpy (prompts [0], "DATAFILE ON DISK HAS NO RECORDS");
strcpy (prompts [1], "1=OK");
strcpy (prompts [2], "2=ABORT");
choice = get_v_choice (2, 0, 0);
if (choice == 2) return (wfg);
}
switch (a)
{
case 1:
{
if (wfg) {crno = 1; break;}
y = (fi [file].num_rcds * 2) + 10;
base = (SWORD far *) _fmalloc (y);
if (base == NULL) {mem_fail(); goto get_rnumber;}
/* load record #s into ram, find hole if any */
while (i < fi [file].num_rcds)
{
fread (& rno, 2, 1, fi [file].ctrl);
if (! rno)
{
if (! crsq) crsq = i;
i++; continue;
}
if (rno > bigno) bigno = rno;
* (base + x) = rno; i++; x++;
}
if (x) x--;
if (! crsq) crsq = fi [file].num_rcds;
/*
cls(); locate (0,0);
for (y = 0; y <= x; y ++) printf ("%hu ", * (base + y));
get_one (& nrml_val, & fi [file].ctrl_val);
*/
clw(3); locate (22, 15);
prnt ("FINDING NEXT AVAILABLE RECORD NUMBER, PLEASE WAIT");
/* sort record numbers */
for (y = 0; y < x; y++)
{
if (* (base + y) <= * (base + y + 1) )
{
if (z) {y = z; z = 0;}
continue;
}
if (! z) z = y;
rno = * (base + y); rno2 = y + 1;
* (base + y) = * (base + rno2);
* (base + rno2) = rno;
if (y) y-= 2;
}
/*
cls(); locate (0,0);
for (y = 0; y <= x; y++) printf ("%hu ", * (base + y));
get_one (& nrml_val, & ctrl_val);
*/
/* check sorted rcd #s for missing # */
y = 0; crno = 0; i = 1;
while (y < x && ! crno)
{
if (* (base + y) != i) crno = i;
y++; i++;
}
if (! crno) crno = bigno + 1;
_ffree (base);
break;
}
case 2:
{
get_rnumber:
clw(3); locate (22, 21);
prnt ("ENTER NUMBER FOR NEW RECORD:");
inpt (2, 5, 1, 0, 0, 32, user_enty);
enty = atol (user_enty);
if (enty < 1 || enty > 32000) {beep(); goto choose1;}
crno = enty;
if (wfg) break;
clw(3); locate (22, 23);
prnt ("CHECKING YOUR ENTRY, PLEASE WAIT");
crsq = 0; i = 0; wfg = 0;
while (i <= fi [file].num_rcds && ! wfg)
{
fread ( (void *) & rno, 1, 2, fi [file].ctrl);
if (! crsq && ! rno) crsq = i;
if (rno > bigno) bigno = rno;
if (rno == crno) wfg = 1;
i++;
}
if (! crsq) crsq = fi [file].num_rcds;
if (wfg)
{
clw(3); beep(); locate (22, 23);
prnt ("THAT RECORD NUMBER HAS BEEN USED");
wait (4); goto get_rnumber;
}
}
}
if (close_sw) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
/* place sequence/number found in file struct */
fi [file].sequence = crsq; fi [file].r_number = crno;
/* clear buffer */
ready_files (file);
return (0);
}
BYTE far get_files (BYTE * tgt_ext, BYTE level)
{
/* if level == 0 finds DATAMAGE dirs, otherwise finds files w/ given ext */
BYTE c, ctr = 0, ftsw = 0, x, y, wfg = 0;
FILE * target;
struct find_t finfo;
ftot [level] = 0;
strcpy (gp_str [11], gp_str [10]);
strcat (gp_str [11], "\\*.");
if (level) strcat (gp_str [11], tgt_ext);
while (! wfg)
{
if (! ftsw)
{
if (level) c = _dos_findfirst (gp_str [11], 0 || 32, & finfo);
else c = _dos_findfirst (gp_str [11], 16, & finfo);
ftsw = 1;
}
else c = _dos_findnext (& finfo);
if (c) {wfg = 1; continue;}
strcpy (gp_str [2], gp_str [10]);
y = gp_str [2] [strlen (gp_str [2]) - 1];
if (y != 92) strcat (gp_str [2], "\\");
strcat (gp_str [2], finfo.name);
if (! level) strcat (gp_str [2], "\\cityname.sad");
if ( (target = fopen (gp_str [2], "r")) != NULL)
{
fgets (f_buff, 37, target);
fclose (target);
strcpy (gp_str [14], finfo.name);
for (c = strlen (gp_str [14]); c < 12; c++)
gp_str [14] [c] = 32;
gp_str [14] [c] = 0;
set_farst (files [level] [ctr].name, gp_str [14]);
strncpy (gp_str [13], f_buff + 1, 35);
set_farst (files [level] [ctr].desc, gp_str [13]);
ctr ++;
}
}
ftot [level] = ctr;
if (ctr) return (1);
return (0);
}
BYTE far show_files (BYTE level)
{
/* displays files found */
BYTE d, m, wfg, x;
SWORD top_line = 0, curr_line = 0;
strcpy (gp_str [4], ".DIR");
for (d = 0; d < ftot [level]; d++)
{
window_data [d].r_val = d;
for (m = 0; m < 62; m++) window_data [d].disp [m] = 32;
window_data [d].disp [m] = 0;
for (x = 0, m = 3; m < 15; m++)
window_data [d].disp [m] = files [level] [d].name [x++];
if (! level)
for (x = 0, m = 11; m < 15; m++)
window_data [d].disp [m] = gp_str [4] [x++];
for (x = 0, m = 23; m < 58; m++)
window_data [d].disp [m] = files [level] [d].desc [x++];
}
save_window (9); clw (9);
window_border (4);
locate (3,14); prnt ("FILENAME");
locate (3,37); prnt ("USER-ASSIGNED DESCRIPTION");
fill_window (5, & curr_line, & top_line, level);
x = work_window (5, & curr_line, & top_line, level);
repl_window (9);
return (x);
}
BYTE far select_datafile()
{
/* combines get_files and show_files to select DATAMAGE datafile */
BYTE c, x = 1, wfg = 0;
while (! wfg )
{
if (readf)
{
clw (3);
strcpy (c_s [0], "READING DIRECTORY OF:");
strcpy (c_s [1], gp_str [10]);
x = cntrstrp ();
locate (22, x);
prnt (c_s [2]);
}
x = get_files ("<DIR>", 0);
c = (80 - strlen (gp_str [17]) ) /2;
clw (3);
locate (22, c); prnt (gp_str [17]);
if (x)
{
x = show_files (0);
if (x) {readf = 0; wfg = 1; continue;}
}
save_window (3);
clw(2); clw(3); beep();
if (! ftot [0])
{
locate (10, 25);
prnt ("NO DATAMAGE FILES WERE FOUND");
}
locate (14, 13);
prnt ("ENTER PATHNAME FOR LOAD FILE, OR PRESS RETURN TO ABORT");
locate (22,19);
x = inpt (1, 40, 1, 0, 0, 32, user_enty);
repl_window (3);
if (! x) {wfg = 2; continue;}
strcpy (gp_str [10], user_enty); readf = 1;
strcpy (pth_str, user_enty);
clw (2);
}
return (wfg - 1);
}
BYTE far open_file (BYTE fs)
{
/* opens DATAMAGE file, fills structure fi [fs] with details,
allocates buffer, berbps beeby, kicks tires.... */
BYTE c, d, iocb, ret_val = 0, x;
WORD r_len = 0;
void * buff;
FILE * target, * t2;
struct
{
BYTE st1 [2];
BYTE filler2 [13];
BYTE st2 [2];
BYTE filler3 [12];
BYTE st3 [2];
BYTE filler4 [12];
BYTE st4 [7];
BYTE filler5 [50];
} kbuff;
buff = & kbuff;
strcpy (gp_str[10], gp_str [1]);
strcpy (gp_str[2], gp_str [1]);
strcpy (gp_str[3], gp_str [1]);
strcat (gp_str[1], "\\KEY.SAD");
strcat (gp_str[2], "\\HEADINGS.SAD");
strcat (gp_str[3], "\\CITYNAME.SAD");
/* get description of file */
t2 = fopen (gp_str[3], "r");
if (t2 == NULL) strcpy (fi [fs].des, "NO DESCRIPTION FOUND");
else
{
fgets (f_buff, 40, t2);
f_buff [36] = 0; rtrim (f_buff);
strcpy (fi [fs].des, f_buff + 1);
}
fclose (t2);
open:
if ( ( ( target = fopen (gp_str[1], "r") ) == NULL) ||
( ( t2 = fopen (gp_str[2], "r") ) == NULL) )
{
fclose (target); fclose (t2);
clw (2); clw (3); locate (12, 24); beep ();
prnt ("Desired file could not be opened.");
strcpy (prompts [0], "YOU MAY:");
strcpy (prompts [1], "1=RETRY LOAD");
strcpy (prompts [2], "2=ABORT LOAD");
d = get_v_choice (2, 0, 0);
if (d == 1) goto open;
ret_val = 1; goto of_end;
}
setbuf (target, NULL);
iocb = fileno(target);
/* fill file structure */
/* set path strings to open definition files */
strcpy (fi [fs].dir, gp_str [10]);
strcpy (fi [fs].m_name, gp_str [10]);
strcpy (fi [fs].i_name, gp_str [10]);
strcpy (fi [fs].c_name, gp_str [10]);
strcat (fi [fs].m_name, "\\YOURDATA.RAD");
strcat (fi [fs].i_name, "\\FILEINDX.RAD");
strcat (fi [fs].c_name, "\\CTRLFILE.RAD");
/* set file pointers to null, MUST be set to null after closing!
Many ISAM functions will open these pointers if they are not NULL,
and close them if they were not open - see condit_open function.
DO NOT use local file pointers in your routines! If the ISAM adds
a new record into a file open on another iocb NASTY things happen!
ALL YOU NEED TO DO is to remember in your code to SET THESE BUGGERS
BACK TO NULL after you close them! The ISAM will take it from there
and open/close them if necessary. */
fi [fs].ctrl = NULL;
fi [fs].indx = NULL;
fi [fs].main = NULL;
fi [fs].marker = NULL;
/* zero indexing data */
fi [fs].indexes = 0;
fi [fs].cross_fields = 0;
fi [fs].unique_field = 0;
fi [fs].cross_cntr = 0;
fi [fs].next_rcd = 0;
fi [fs].m_next_rcd = 0;
fi [fs].mkr_active = 0;
fi [fs].rw_sw = 0;
fi [fs].bs_sw = - 10;
d = 0;
/* read in fields */
while (! eof(iocb))
{
fgets (buff, 50, target);
if (! strlen(buff)) continue;
fi [fs].key [d] = _fmalloc (sizeof (fdef));
if (fi [fs].key [d] == NULL)
{
mem_fail ();
ret_val = 1;
goto of_end;
}
fgets (r_buff, 30, t2);
set_farst (fi [fs].key [d] -> name, r_buff);
fi [fs].key [d] -> type = atoi (kbuff.st1);
fi [fs].key [d] -> length = atoi (kbuff.st2);
fi [fs].key [d] -> spare = atoi (kbuff.st3);
fi [fs].key [d] -> abs = atoi (kbuff.st4);
fi [fs].key [d] -> offset = r_len;
r_len += fi [fs].key [d] -> length;
/*
locate (0,0); prnt (" ");
locate (0,0); printf ("%u, %hu, %u, %u",
fi [fs].key [d] -> type,
fi [fs].key [d] -> length,
fi [fs].key [d] -> spare,
fi [fs].key [d] -> abs);
wait (1);
*/
/* detect indexing */
if (fi [fs].key [d] -> type == 1 &&
fi [fs].key [d] -> spare)
{
fi [fs].indexed_fields [fi [fs].indexes] = d;
fi [fs].indexes += 1;
if (fi [fs].key [d] -> spare == 3) fi [fs].cross_fields += 1;
if (fi [fs].key [d] -> spare == 1) fi [fs].unique_field = 1;
}
d++;
}
fclose (target); fclose (t2);
/* set number of fields */
fi [fs].num_flds = d;
/* set record length */
fi [fs].rcd_len = r_len;
/* get number of records */
if ( ( target = fopen (fi [fs].c_name, "rb") ) == NULL)
fi [fs].num_rcds = 0;
else fi [fs].num_rcds = filelength(fileno(target)) / 2;
/* allocate file buffer */
if (fi [fs].buff != NULL)
{
_ffree (fi [fs].buff);
fi [fs].buff = NULL;
}
if ((fi [fs].buff = _fmalloc (fi [fs].rcd_len + 5)) == NULL)
{mem_fail(); ret_val = 1;}
of_end:
fclose (target);
return (ret_val);
}
void far close_file (BYTE file)
{
/* frees DATAMAGE file structure for re-use */
WORD i;
if (fi [file].buff != NULL)
{
_ffree (fi [file].buff);
fi [file].buff = NULL;
}
for (i = 0; i < 200; i++)
{
if (fi [file].key [i] != NULL)
{
_ffree (fi [file].key [i]);
fi [file].key [i] = NULL;
}
}
}
BYTE far show_datafiles (BYTE start)
{
/* shows currently loaded files, user selects */
BYTE d, m, wfg, y, e = 0;
SBYTE x;
SWORD top_line = 0, curr_line = 0;
for (d = start; d < files_loaded; d++, e++)
{
window_data [e].r_val = d;
for (m = 0; m < 62; m++) window_data [e].disp [m] = 32;
window_data [e].disp [m] = 0;
x = y = strlen (fi [d].dir); wfg = 0;
while (x > - 1 && ! wfg)
{
if (fi [d].dir [x] == 92 || fi [d].dir [x] == 58)
wfg = x + 1;
x--;
}
if (wfg) x = wfg; else x = 0;
for (m = 3; m < 11 && x < y;)
window_data [e].disp [m++] = fi [d] .dir [x++];
y = strlen (fi [d].des) + 23;
for (x = 0, m = 23; m < 58 && m < y;)
window_data [e].disp [m++] = fi [d].des [x++];
}
ftot [1] = files_loaded - start;
save_window (8); clw (8);
window_border (6);
locate (9, 14); prnt ("FILENAME");
locate (9, 37); prnt ("USER-ASSIGNED DESCRIPTION");
fill_window (7, & curr_line, & top_line, 1);
x = work_window (7, & curr_line, & top_line, 1);
repl_window (8);
if (x) return (0); else return (1);
}
BYTE far show_fields (BYTE level, BYTE type)
{
/* shows fields in file passed, on type */
BYTE x, what [17];
WORD d, m, z;
SWORD top_line = 0, curr_line = 0;
switch (type)
{
case 0: strcpy (what, "DATE"); break;
case 1: strcpy (what, "STRING"); break;
case 2:
case 3: strcpy (what, "NUMERIC"); break;
case 4: strcpy (what, "INDEXED"); break;
case 5: strcpy (what, "NON-INDEXED"); break;
case 9: strcpy (what, "ALL");
}
for (z = 0, d = 0; d < fi [level].num_flds; d++)
{
switch (type)
{
case 0:
case 1:
{
if (fi [level].key [d] -> type != type) continue;
break;
}
case 2:
case 3:
{
if (fi [level].key [d] -> type < 2) continue;
break;
}
case 4:
{
if (fi [level].key [d] -> type != 1 ||
fi [level].key [d] -> spare != 1) continue;
break;
}
case 5:
{
if (fi [level].key [d] -> type != 1) continue;
if (fi [level].key [d] -> spare == 1 ||
fi [level].key [d] -> spare == 3) continue;
break;
}
case 9: ;
}
window_data [z].r_val = d;
for (m = 0; m < 62; m++) window_data [z].disp [m] = 32;
window_data [z].disp [m] = 0;
itoa (d + 1, gp_str [4], 10);
strcat (gp_str [4], ".");
x = 0; m = 1;
while (gp_str [4] [x])
window_data [z].disp [m++] = gp_str [4] [x++];
x = 0; m = 7;
get_farst (gp_str [4], fi [level].key [d] -> name);
while (gp_str [4] [x])
window_data [z].disp [m++] = gp_str [4] [x++];
switch (fi [level].key [d] -> type)
{
case 0:
{
strcpy (gp_str [4], "DATE: ");
if (! fi [level].key [d] -> spare)
strcat (gp_str [4], "MM/DD/YY");
else strcat (gp_str [4], "DD/MM/YY");
break;
}
case 1:
{
strcpy (gp_str [4], "STRING: ");
switch (fi [level].key [d] -> spare)
{
case 0: strcat (gp_str [4], "NO IDX"); break;
case 1: strcat (gp_str [4], "IDX UN"); break;
case 2: strcat (gp_str [4], "IDX"); break;
case 3: strcat (gp_str [4], "IDX CR"); break;
}
break;
}
case 2:
{
strcpy (gp_str [4], "NUMERIC: ");
itoa (fi [level].key [d] -> spare, gp_str [5], 10 );
strcat (gp_str [4], gp_str [5]);
strcat (gp_str [4], " DECS");
break;
}
case 3:
{
strcpy (gp_str [4], "DOLLAR FORMAT");
break;
}
}
x = 0; m = 34;
for (x = 0; x < strlen (gp_str [4]); )
window_data [z].disp [m++] = gp_str [4] [x++];
x = 0; m = 52;
strcpy (gp_str [4], "BYTES: ");
itoa (fi [level].key [d] -> length, gp_str [5], 10);
strcat (gp_str [4], gp_str [5]);
for (x = 0; x < strlen (gp_str [4]);)
window_data [z].disp [m++] = gp_str [4] [x++];
z ++;
}
if (! z)
{
clw(3); locate (22,20); beep();
strcpy (c_s [0], "NO ");
strcat (c_s [0], what);
strcpy (c_s [1], " FIELDS WERE FOUND");
x = cntrstrp();
locate (22, x); prnt (c_s [2]); wait (4); return (1);
}
ftot [1] = z;
save_window (9); clw (9);
window_border (4);
strcpy (c_s [0], what);
strcat (c_s [0], " FIELDS IN: ");
strcpy (c_s [1], fi [level].dir);
x = cntrstrp();
locate (3, x); prnt (c_s [2]);
fill_window (5, & curr_line, & top_line, 1);
x = work_window (5, & curr_line, & top_line, 1);
repl_window (9);
if (x) return (0); else return (1);
}
BYTE far show_menu ()
{
/* shows content of a menu file, expects path/filename in gp_str [13] */
BYTE c, d = 0, fno, m, wfg, x;
SWORD top_line = 0, curr_line = 0;
FILE * target;
target = fopen (gp_str [13], "r");
if (target == NULL) {beep(); return (1);}
setbuf (target, NULL);
fno = fileno (target);
save_window (4); window_border (4);
while (! eof (fno) )
{
/* get display value */
fgets (f_buff, 80, target);
if (eof (fno) ) wfg = 1;
eol_strip (f_buff);
/* put disp val in window ram */
for (m = 0; m < 62; m++) window_data [d].disp [m] = 32;
window_data [d].disp [m] = 0;
c = strlen (f_buff);
if (c > 62) c = 62;
for (m = 0; m < c; m++) window_data [d].disp [m] = f_buff [m];
if (eof (fno) ) continue;
/* get return value */
fgets (f_buff, 80, target);
eol_strip (f_buff);
c = strlen (f_buff);
if (c > 62) c = 62;
for (m = 0; m < c; m++) window_data [d].rtrn [m] = f_buff [m];
window_data [d].rtrn [m] = 0;
window_data [d++].r_val = d;
if (d >= 199) wfg = 1;
}
fclose (target); ftot [1] = d;
fill_window (5, & curr_line, & top_line, 1);
x = work_window (5, & curr_line, & top_line, 1);
repl_window (4);
return 0;
}
void far fill_window (BYTE w, SWORD * curr_line, SWORD * top_line, BYTE level)
{
/* universal window fill routine, works from window_data */
BYTE m, l;
clw (w);
l = (w_a [w] .lrr - w_a [w] .ulr);
for (* curr_line = 0; * curr_line <= l; * curr_line += 1)
{
m = * curr_line + * top_line;
if (m > ftot [level] - 1) continue;
window_line (w, * curr_line, m, 0);
}
* curr_line = l / 2;
if (* curr_line > ftot [level] - 1) * curr_line = ftot [level] - 1;
}
void far window_line (BYTE w, BYTE l, BYTE x, BYTE revsw)
{
/* universal window line routine, works from window_data */
BYTE z;
if (revsw) z = 120;
else z = w_a [w].attr;
locate (l + w_a [w] .ulr, w_a [w] .ulc);
f_clr_prnt (window_data [x].disp, z);
}
BYTE far work_window (BYTE w, SWORD * curr_line, SWORD * top_line, BYTE level)
{
/* universal window work routine, works from window_data
returns numeric choice in global nrml_val */
BYTE x, wfg = 0, ret_val = 1;
SBYTE dy = 0, w_lines = w_a [w] .lrr - w_a [w] .ulr + 1;
while (! wfg)
{
window_line (w, * curr_line, * curr_line + * top_line, 1);
get_one (& ctrl_val, & nrml_val);
window_line (w, * curr_line, * curr_line + * top_line, 0);
if (nrml_val)
{
switch (nrml_val)
{
case 27 :
{
wfg = 1; ret_val = 0;
nrml_val = 0; continue;
}
case 13 :
{
wfg = 1;
nrml_val = window_data [* top_line + * curr_line].r_val;
continue;
}
default : beep (); continue;
}
}
switch (ctrl_val)
{
case 71: /* home */
* top_line = 0;
fill_window (w, curr_line, top_line, level);
if (ftot [level] >= 7) * curr_line = 7;
else * curr_line = ftot [level] - 1;
continue;
case 72: /* line up */
if ( (* curr_line) - 1 >= 0) {* curr_line -= 1; continue;}
if ( (* top_line) - 1 < 0) {beep(); continue;}
* top_line -= 1;
scroll_window (w, 2, 1);
window_line (w, dy, * curr_line, 0);
continue;
case 73: /* page up */
* top_line -= w_lines;
if (* top_line < 0) * top_line = 0;
fill_window (w, curr_line, top_line, level);
continue;
case 79: /* end */
* top_line = ftot [level] - w_lines;
if (* top_line < 0) * top_line = 0;
fill_window (w, curr_line, top_line, level);
if (ftot [level] >= 7) * curr_line = 7;
else * curr_line = ftot [level] - 1;
continue;
case 80: /* line down */
x = * curr_line + 1;
if (x <= w_lines - 1)
{
if (x < ftot [level]) * curr_line += 1; else beep();
continue;
}
if ( (* top_line) + w_lines + 1 > ftot [level])
{beep (); continue;}
* top_line += 1;
scroll_window (w, 1, 1);
window_line (w, w_lines - 1, * top_line + w_lines - 1, 0);
continue;
case 81: /* page down */
* top_line += w_lines;
if (* top_line > ftot [level] - w_lines)
* top_line = ftot [level] - w_lines;
if (* top_line < 0) * top_line = 0;
fill_window (w, curr_line, top_line, level);
continue;
default: beep(); continue;
}
}
return (ret_val);
}
BYTE vs_line (BYTE file, BYTE field, SWORD line,
SWORD subscr, BYTE revsw, SWORD far * base)
{
/* print line routine for browse_file */
BYTE b, c, d, z;
WORD x;
SWORD rno;
DWORD offset;
double temp, msbin;
/* clear buffer */
for (d = 0; d < 62; d++) gp_str [0] [d] = 32;
gp_str [0] [d] = 0;
/* get offset of next record from array */
x = * (base + subscr);
/* offset in control file */
offset = (DWORD) x * 2;
/* read in record number */
c = fseek (fi [file].ctrl, offset, SEEK_SET);
fread (& rno, 2, 1, fi [file].ctrl);
/* put record number in buffer */
sprintf (gp_str [11], "%hi", rno);
b = strlen (gp_str [11]);
for (c = 2, d = 0; d < b;) gp_str [0] [c++] = gp_str [11] [d++];
/* offset in main file */
offset = (fi [file].rcd_len * x) + fi [file].key [field] -> offset;
/* read in field */
c = fseek (fi [file].main, offset, SEEK_SET);
fread (f_buff, 1, fi [file].key [field] -> length, fi [file].main);
f_buff [fi [file].key [field] -> length] = 0;
if (fi [file].key [field] -> type < 2) rtrim (f_buff);
else
{
c = dmsbintoieee ( (double *) f_buff, & temp);
strcpy (gp_str [4], "%. lf");
gp_str [4] [2] = fi [file].key [field] -> spare + 48;
sprintf (f_buff, gp_str [4], temp);
}
/* place field in buffer */
b = strlen (f_buff);
for (c = 13, d = 0; d < b && c < 62;)
gp_str [0] [c++] = f_buff [d++];
/* select attribute */
if (revsw) z = 120;
else z = w_a [5].attr;
/* do line */
locate (line + 5, 9);
clr_prnt (gp_str [0], z);
return (0);
}
BYTE fill_vs (BYTE file, BYTE field, SWORD * curr_line,
SWORD * top_line, WORD last, SWORD far * base)
{
/* fill routine for browse_file */
BYTE c;
SWORD m;
for (* curr_line = 0; * curr_line < 14; * curr_line += 1)
{
m = * curr_line + * top_line;
if (m > last - 1) continue;
c = vs_line (file, field, * curr_line, m, 0, base);
if (c) return (1);
}
* curr_line = 7;
if (* curr_line > last - 1) * curr_line = last - 1;
return (0);
}
void vs_menu (BYTE file, SWORD line)
{
/* menu for browse_file */
clw (3);
locate (21,6);
prnt ("FILE: ");
prnt (fi [file].dir);
locate (21, 58);
prnt ("LOCATION: ");
locate (22,6);
prnt ("CONTROL KEYS: \x018 \x019 Page-Up Page-Down Home End");
locate (23,6);
prnt ("Press <RETURN> to select record, <ESC> to bypass, F to select field.");
}
BYTE far vs_MAGE_recrd (BYTE file, BYTE field, BYTE * error_str)
{
/* browses target file, returns record selected in fi [file].sequence */
BYTE c, close_sw [3], wfg = 0, ret_val;
WORD i = 0, n = 0, x;
SWORD rno, top_line = 0, curr_line = 0;
DWORD offset = 0;
SWORD far * base;
BYTE fill_vs (BYTE, BYTE, SWORD *,
SWORD *, WORD, SWORD far *);
BYTE vs_line (BYTE, BYTE, SWORD,
SWORD, BYTE, SWORD far *);
void vs_menu (BYTE, SWORD);
for (c = 0; c < 3; c++) close_sw [c] = 0;
clw (3); locate (22,22);
prnt ("PREPARING FILE BROWSE, PLEASE WAIT....");
/* open ctrl file */
c = condit_open (file, 3, "r+b");
switch (c)
{
case 0: break;
case 1: {close_sw [2] = 1; break;}
case 2: {wfg = 1; goto check_open;}
}
c = fseek (fi [file].ctrl, offset, SEEK_SET);
/* open main file */
c = condit_open (file, 1, "r+b");
switch (c)
{
case 0: break;
case 1:
{
close_sw [0] = 1;
break;
}
case 2: wfg = 1;
}
check_open:
if (wfg)
{
strcpy (error_str, "UNABLE TO ACCESS BROWSE FILES");
ret_val = 2;
goto bf_end;
}
while (i < fi [file].num_rcds)
{
fread (& rno, 2, 1, fi [file].ctrl);
if (rno) n++;
i ++;
}
if (! n)
{
strcpy (error_str, "BROWSE FILE HAS NO RECORDS");
ret_val = 2;
goto bf_end;
}
base = (SWORD far *) _fmalloc ( (n * 2) + 10);
if (base == NULL)
{
strcpy (error_str, "INSUFFICIANT MEMORY FOR FILE BROWSE");
ret_val = 2;
goto bf_end;
}
i = x = 0;
fseek (fi [file].ctrl, (DWORD) 0, SEEK_SET);
while (i < fi [file].num_rcds)
{
fread (& rno, 2, 1, fi [file].ctrl);
if (rno) * (base + x++) = i;
i ++;
}
save_window (4); window_border (4);
vs_menu (file, top_line + curr_line);
c = fill_vs (file, field, & curr_line, & top_line, n, base);
if (c) {ret_val = 1; goto bf_end_2;}
while (! wfg)
{
sprintf (gp_str [6],"%hi", top_line + curr_line + 1);
for (c = 0; c < 7; c++)
if (gp_str [6] [c] == 0) gp_str [6] [c] = 32;
gp_str [6] [c] = 0;
locate (21, 68);
prnt (gp_str [6]);
c = vs_line (file, field, curr_line,
curr_line + top_line, 1, base);
if (c) {wfg = 1; ret_val = 1; continue;}
get_one (& ctrl_val, & nrml_val);
c = vs_line (file, field, curr_line,
curr_line + top_line, 0, base);
if (c) {wfg = 1; ret_val = 1; continue;}
if (nrml_val)
{
switch (nrml_val)
{
case 27 :
{
wfg = 1; ret_val = 1;
nrml_val = 0; break;
}
case 13 :
{
wfg = 1; ret_val = 0;
i = top_line + curr_line;
x = * (base + i);
offset = fi [file].rcd_len * x;
/* read record in */
c = fseek (fi [file].main, offset, SEEK_SET);
fread (f_buff, fi [file].rcd_len, 1, fi [file].main);
set_far (fi [file].buff, f_buff, fi [file].rcd_len);
/* place sequence number of record found */
fi [file].sequence = x;
/* place record number of record found */
fseek (fi [file].ctrl, (DWORD) x * 2, SEEK_SET);
fread (& rno, 2, 1, fi [file].ctrl);
fi [file].r_number = rno;
break;
}
case 'f':
case 'F':
{
clw (3); locate (22,31);
prnt ("SELECT VIEW FIELD");
c = show_fields (file, 9);
if (! c) field = nrml_val;
c = fill_vs (file, field,
& curr_line, & top_line, n, base);
if (c) return (1);
vs_menu (file, top_line + curr_line);
break;
}
default : beep (); break;
}
continue;
}
switch (ctrl_val)
{
case 71: /* home */
{
top_line = 0; clw (5);
c = fill_vs (file, field, & curr_line,
& top_line, n, base);
if (c) return (1);
if (n >= 7) curr_line = 7;
else curr_line = n - 1;
continue;
}
case 72: /* line up */
{
if ( (curr_line) - 1 >= 0) {curr_line -= 1; continue;}
if ( (top_line) - 1 < 0) {beep(); continue;}
top_line -= 1;
scroll_window (5, 2, 1);
c = (file, field, 0, curr_line, 0);
if (c) return (1);
continue;
}
case 73: /* page up */
{
top_line -= 14; clw (5);
if (top_line < 0) top_line = 0;
c = fill_vs (file, field,
& curr_line, & top_line, n, base);
if (c) return (1);
continue;
}
case 79: /* end */
{
top_line = n - 14; clw (5);
if (top_line < 0) top_line = 0;
c = fill_vs (file, field,
& curr_line, & top_line, n, base);
if (c) return (1);
if (n >= 7) curr_line = 7;
else curr_line = n - 1;
continue;
}
case 80: /* line down */
{
x = curr_line + 1;
if (x <= 13)
{
if (x < n) curr_line += 1; else beep();
continue;
}
if ( (top_line) + 15 > n)
{beep (); continue;}
top_line += 1;
scroll_window (5, 1, 1);
c = vs_line (file, field,
13, top_line + 13, 0, base);
if (c) {wfg = 1; ret_val = 1; continue;}
continue;
}
case 81: /* page down */
{
top_line += 14; clw (5);
if (top_line > n - 14)
top_line = n - 14;
if (top_line < 0) top_line = 0;
c = fill_vs (file, field,
& curr_line, & top_line, n, base);
if (c) return (1);
continue;
}
default: beep(); continue;
}
}
bf_end_2:
_ffree (base);
bf_end:
clw (4); repl_window (4);
if (close_sw [0]) {fclose (fi [file].main); fi [file].main = NULL;}
if (close_sw [3]) {fclose (fi [file].ctrl); fi [file].ctrl = NULL;}
return (ret_val);
}
void pmr_heading (BYTE * page)
{
/* prints heading for mage record */
BYTE d;
if (* page) lpt_char (12);
* page += 1;
lpt_eol ();
lpt_line (79, 42);
lpt_blanks (3);
strcpy (c_s [0], "DATAMAGE - SCREEN MAKER REPORT RUN ON: ");
_strdate (c_s [1]);
strcat (c_s [1], " AT: ");
_strtime (gp_str [11]);
gp_str [11] [5] = 0;
strcat (c_s [1], gp_str [11]);
d = cntrstrp ();
lpt_tab (d);
lpt_string (c_s [2]);
lpt_blanks (3);
strcpy (c_s [0], "CONTENTS OF TEST RECORD");
strcpy (c_s [1], "PAGE: ");
itoa (* page, gp_str [5], 10);
strcat (c_s [1], gp_str [5]);
d = cntrstrp ();
lpt_tab (d);
lpt_string (c_s [2]);
lpt_blanks (3);
lpt_line (79, 42);
lpt_blanks (2);
}
void field_line (BYTE file, WORD field)
{
strcpy (c_s [0], "FIELD # ");
itoa (field + 1, gp_str [13], 10);
strcat (c_s [0], gp_str [13]);
strcat (c_s [0], ". NAME: ");
get_farst (gp_str [13], fi [file].key [field] -> name);
strcat (c_s [0], gp_str [13]);
strcpy (c_s [1], "TYPE: ");
switch (fi [file].key [field] -> type)
{
case 0:
{
strcat (c_s [1], "DATE FIELD: ");
if (fi [file].key [field] -> spare == 1)
strcat (c_s [1], "MM/DD/YY");
else strcat (c_s [1], "DD/MM/YY");
break;
}
case 1:
{
strcat (c_s [1], "STRING");
switch (fi [file].key [field] -> spare)
{
case 1:
{
strcat (c_s [1], ", INDEXED UNIQUE");
break;
}
case 2:
{
strcat (c_s [1], ", INDEXED");
break;
}
case 3:
{
strcat (c_s [1], ", CROSS-INDEXED");
break;
}
}
break;
}
case 2:
{
strcat (c_s [1], "NUMERIC");
switch (fi [file].key [field] -> spare)
{
case 9:
{
strcat (c_s [1], ", FLOATING POINT");
break;
}
default:
{
itoa (fi [file].key [field] -> spare, gp_str [12], 10);
strcat (c_s [1], ", ");
strcat (c_s [1], gp_str [12]);
strcat (c_s [1], " DECIMALS");
break;
}
}
break;
}
case 3: strcat (c_s [1], "NUMERIC, DOLLAR FMT");
}
}
void far print_MAGE_record (BYTE file)
{
/* prints DATAMAGE record - must be in buffer when called */
BYTE c, dollar, l, line = 13, page = 0;
WORD d, len, x;
double temp;
pmr_heading (& page);
for (d = 0; d < fi [file].num_flds; d++)
{
itoa (d + 1, gp_str [5], 10);
strcat (gp_str [5], ".");
lpt_string (gp_str [5]);
lpt_tab (10);
lpt_f_string (fi [file].key [d] -> name);
lpt_tab (40);
len = fi [file].key [d] -> length;
get_far (user_enty,
fi [file].buff + fi [file].key [d] -> offset,
len);
if (fi [file].key [d] -> type < 2)
{
user_enty [len] = 0; rtrim (user_enty);
if (len <= 35) {lpt_string (user_enty); lpt_eol ();}
else
{
x = l = 0;
while (x < len)
{
l = len - x;
if (l > 35) l = 35;
for (c = 0; c < l; c++)
lpt_char (user_enty [c + x]);
lpt_eol ();
x += l; line ++;
if (line > 59) {pmr_heading (& page); line = 13;}
if (x < len) lpt_tab (40);
}
}
line ++;
if (line > 59) {pmr_heading (& page); line = 13;}
continue;
}
dmsbintoieee ( (double *) user_enty, & temp);
strcpy (gp_str [4], "%. lf");
gp_str [4] [2] = fi [file].key [d] -> spare + 48;
sprintf (c_s [0], gp_str [4], temp);
dollar = 0;
if (fi [file].key [d] -> type == 3) dollar = 1;
dlr_format (dollar, 1);
lpt_string (c_s [2]); lpt_eol ();
line ++;
if (line > 59) {pmr_heading (& page); line = 13;}
}
lpt_char (12);
}
void new_a_screen (BYTE file, SWORD st, BYTE * acc)
{
/* fill routine for access screen */
WORD d, line = 0, x = st + 9;
clw (2);
for (d = st; d < x; d++)
a_line (file, d, line++, acc);
}
void a_line (BYTE file, WORD field, WORD line, BYTE * acc)
{
/* line print routine for access screen */
BYTE c, d, row;
WORD len;
double temp, msbin;
row = (line * 2) + 2;
locate (row, 7);
itoa (field + 1, gp_str [11], 10);
strcat (gp_str [11], ".");
prnt (gp_str [11]);
locate (row, 13);
f_prnt (fi [file].key [field] -> name);
locate (row, 40);
len = fi [file].key [field] -> length;
if (len > 35) len = 35;
if (fi [file].key [field] -> type < 2)
{
get_field (file, field, len, gp_str [11]);
gp_str [11] [len] = 0;
c = 1; d = fi [file].key [field] -> length;
if (d > 35) d = 35;
}
else
{
get_field (file, field, 8, (BYTE *) & msbin);
dmsbintoieee (& msbin, & temp);
if (temp != 0)
{
strcpy (gp_str [4], "%. lf");
gp_str [4] [2] = fi [file].key [field] -> spare + 48;
d = sprintf (gp_str [11], gp_str [4], temp);
}
else {strcpy (gp_str [11], "0"); d = 1;}
for (; d < 17; d++) gp_str [11] [d] = 32;
gp_str [11] [d] = 0;
c = 2; d = 17;
}
if (* (acc + field) )
{
locate (row, 40);
ipt_box (40, row, d, 32, 0, 0, gp_str [11]);
}
else prnt (gp_str [11]);
}
void a_menu (BYTE file, BYTE entry)
{
/* menu for access screen */
if (entry) strcpy (gp_str [6], "NEW");
else gp_str [6] [0] = 0;
strcat (gp_str [6], "RECORD NUMBER: ");
clw (3); locate (21,6);
prnt (gp_str [6]);
sprintf (gp_str [6],"%hu", fi [file].r_number);
prnt (gp_str [6]);
locate (21, 32);
prnt ("IN FILE: "); prnt (fi [file].des);
locate (22,6);
prnt ("CONTROL KEYS: \x018 \x019 Pg-Up Pg-Dn Home End Write Print Quit");
locate (23,6);
prnt ("Locate the flasher and press <RETURN> to enter/edit data in fields");
}
BYTE far access_MAGE_record (BYTE file, BYTE entry, BYTE rd_only)
{
/* provides entry/update of records in a DATAMAGE file
record to edit must be in buffer, unless entry switch is set
returns 0 if record (re)written, 1 if quit */
BYTE acc [200], c, choice, d, day, dte_fmt, ftsw = 0,
len, month, row, sl = 0, wfg = 0, wfg2;
WORD year;
SWORD st = 0;
double temp, msbin;
if (entry) rd_only = 0;
/* clear field accessed switches */
for (d = 0; d < 200; d++) acc [d] = 0;
if (entry) get_next_rno (file);
new_a_screen (file, st, acc);
while (! wfg)
{
if (! ftsw) {a_menu (file, entry); ftsw = 1;}
c = (sl * 2) + 2;
locate (c, 7);
itoa (st + sl + 1, gp_str [11], 10);
strcat (gp_str [11], ".");
clr_prnt (gp_str [11], attr + 128);
get_one (& ctrl_val, & nrml_val);
locate (c, 7);
clr_prnt (gp_str [11], attr);
y_n ();
if (nrml_val)
{
switch (nrml_val)
{
default : {beep (); continue;}
case 'p':
case 'P':
{
ftsw = 0;
strcpy (prompts [0], "PRINT THIS RECORD?");
choice = get_v_choice (2, 0, 0) - 1;
if (choice) continue;
clw (3); locate (22,22);
prnt ("READY YOUR PRINTER, AND PRESS ANY KEY");
get_one (& nrml_val, & ctrl_val);
print_MAGE_record (file);
break;
}
case 'q':
case 'Q':
{
ftsw = 0;
strcpy (prompts [0], "ABANDON THIS RECORD?");
choice = get_v_choice (2, 0, 0) - 1;
if (! choice) {wfg = 2; continue;}
break;
}
case 'w':
case 'W':
{
ftsw = 0;
if (rd_only)
{
clw(3); beep (); locate (22,27);
prnt ("RECORD ACCESS IS READ ONLY");
wait (4);
break;
}
strcpy (prompts [0], "WRITE THIS RECORD?");
choice = get_v_choice (2, 0, 0) - 1;
if (choice) continue;
/* index completed record */
if (fi [file].indexes)
{
for (c = 0; c < 5; c++)
fi [file].i_case [c] = 0;
d = index_MAGErecord (file);
if ( (fi [file].unique_field ||
fi [file].cross_fields) &&
fi [file].num_rcds)
{
c = find_MAGErecord (file, (WORD) 0, 0, 0);
if (! c)
{
clw (3); beep(); locate (22, 17);
prnt ("DUPLICATE RECORD FOUND, CAN NOT WRITE RECORD");
wait (4); continue;
}
}
}
/* write new record into main file */
clw(3); locate (22, 26);
prnt ("WRITING NEW RECORD TO DISK");
write_MAGErcd (file);
wfg = 1; continue;
}
case 13 :
{
if (rd_only)
{
clw(3); beep (); locate (22,27);
prnt ("RECORD ACCESS IS READ ONLY");
ftsw = 0; wait (4);
break;
}
c = st + sl; acc [c] = 1; ftsw = 0;
field_line (file, c);
row = cntrstrp ();
clw (3); locate (22, row); prnt (c_s [2]);
if (fi [file].key [c] -> type < 2)
{
d = fi [file].key [c] -> length;
get_field (file, (WORD) c, d, user_enty);
}
else
{
get_field (file, (WORD) c, 8, (BYTE *) & msbin);
dmsbintoieee (& msbin, & temp);
d = 0;
if (temp != 0)
{
strcpy (gp_str [4], "%. lf");
gp_str [4] [2] =
fi [file].key [c] -> spare + 48;
d = sprintf (user_enty, gp_str [4], temp);
}
for (; d < 17; d++) user_enty [d] = 32;
user_enty [d] = 0;
}
inp_field:
locate ( (BYTE) ((sl * 2) + 2), 38);
len = minpt (file, c, user_enty); wfg2 = 0;
switch (fi [file].key [c] -> type)
{
case 0:
{
if (len)
{
dte_fmt = fi [file].key [c] -> spare;
d = parse_date (user_enty,
& dte_fmt, & day,
& month, & year,
& temp);
if (d) {wfg2 = 1; break;}
}
}
case 1:
{
set_field (file, c,
fi [file].key [c] -> length,
user_enty);
break;
}
case 3:
{
strcpy (gp_str [4], "%. lf");
gp_str [4] [2] =
fi [file].key[c] -> spare + 48;
temp = atof (user_enty);
d = sprintf (user_enty, gp_str [4], temp);
for (; d < 17; d++) user_enty [d] = 32;
user_enty [17] = 0;
locate ((sl * 2) + 2, 40);
prnt (user_enty);
temp = atof (user_enty);
dieeetomsbin (& temp, & msbin);
set_field (file, c, 8, (BYTE *) & msbin);
}
}
if (wfg2) {beep(); goto inp_field;}
if ( (st + sl + 2) > fi [file].num_flds) break;
if (sl < 8) sl += 1;
else
{
st += 1; scroll_window (2, 1, 2);
a_line (file, st + 8, (WORD) 8, acc);
}
}
}
continue;
}
switch (ctrl_val)
{
case 71: /* home */
{
st = 0; sl = 5;
new_a_screen (file, st, acc);
continue;
}
case 72: /* line up */
{
if (sl) sl -= 1;
else
{
if (st - 1 < 0) {beep(); continue;}
st -= 1; scroll_window (2, 2, 2);
a_line (file, st, (WORD) 0, acc);
}
continue;
}
case 73: /* page up */
{
st -= 9;
if (st < 0) st = 0;
new_a_screen (file, st, acc);
continue;
}
case 79: /* end */
{
st = fi [file].num_flds - 9;
if (st < 0) st = 0;
new_a_screen (file, st, acc);
sl = 5;
continue;
}
case 80: /* line down */
{
if ( (st + sl + 2) > fi [file].num_flds)
{beep(); continue;}
if (sl < 8) sl += 1;
else
{
st += 1; scroll_window (2, 1, 2);
a_line (file, st + 8, (WORD) 8, acc);
}
continue;
}
case 81: /* page down */
{
st += 9;
if (st > fi [file].num_flds - 9)
st = fi [file].num_flds - 9;
if (st < 0) st = 0;
new_a_screen (file, st, acc);
continue;
}
default: beep();
}
}
no_cursor();
return (wfg) - 1;
}
BYTE far read_next_rcd (BYTE file, BYTE * error_str)
{
/* gets next record in file if no marker active,
next record in marker file if marker active
returns: 0=OK - I did that, 1=end of file, 2=error
note that this function opens control file and LEAVES IT OPEN */
BYTE b, ret_val;
WORD seq, recno;
double msbin;
/* set error message, just in case */
strcpy (gp_str [6], "READ INTO CONTROL FILE FAILED");
strcpy (gp_str [9], "READ INTO MARKER FILE FAILED");
start:
if (fi [file].mkr_active)
{
/* check for eof */
if (fi [file].m_next_rcd >= fi [file].m_num_rcds) return (1);
/* determine next record sequence in marker */
fseek (fi [file].marker, ((DWORD) fi [file].m_next_rcd *
fi [file].m_rcd_len) + 125, SEEK_SET);
b = fread (& seq, 1, 2, fi [file].marker);
if (b != 2)
{
strcpy (error_str, gp_str [6]);
return (2);
}
/* read in first counter value, if any */
if (fi [file].m_rcd_len > 2)
{
b = fread (& msbin, 1, 8, fi [file].marker);
if (b != 8)
{
strcpy (error_str, gp_str [9]);
return (2);
}
if (fi [file].c1_sw) dmsbintoieee(& msbin, & fi [file].c1_val);
else dmsbintoieee(& msbin, & fi [file].c2_val);
}
/* read in second counter value, if any */
if (fi [file].m_rcd_len > 10)
{
b = fread (& msbin, 1, 8, fi [file].marker);
if (b != 8)
{
strcpy (error_str, gp_str [9]);
return (2);
}
dmsbintoieee(& msbin, & fi [file].c2_val);
}
/* markers were written by BASIC, where 1 is zero */
seq --;
/* increment record sequence */
fi [file].m_next_rcd += 1;
}
else
{
/* check for eof */
if (fi [file].next_rcd >= fi [file].num_rcds) return (1);
/* determine next record sequence in file */
seq = fi [file].next_rcd;
/* increment record sequence */
fi [file].next_rcd += 1;
}
/* open control file if not already open */
b = condit_open (file, 3, "rb");
if (b == 2)
{
strcpy (error_str, "UNABLE TO OPEN CONTROL FILE");
return (2);
}
/* find desired record in control file */
fseek (fi [file].ctrl, (DWORD) seq, SEEK_SET);
/* verify that desired record has not been deleted */
b = fread (& recno, 1, 2, fi [file].ctrl);
if (b != 2)
{
strcpy (error_str, gp_str [6]);
return (2);
}
/* bypass deleted record */
if (recno == 0) goto start;
/* read record into buffer */
ret_val = read_MAGErcd (file, seq);
return (ret_val);
}
BYTE far get_cntr (BYTE file, BYTE cntr, double * target, BYTE * error_str)
{
/* gets counter value for current record from DATAMAGE MARKER file */
if (! fi [file].mkr_active)
{
strcpy (error_str, "NO MARKER ACTIVE FOR FILE: ");
itoa (file, gp_str [11], 10);
strcat (error_str, gp_str [11]);
return (1);
}
if ( fi [file].counter_sw == 0 ||
(cntr == 1 && fi [file].counter_sw == 2) ||
(cntr == 2 && fi [file].counter_sw == 1) )
{
strcpy (error_str, "COUNTER: ");
itoa (cntr, gp_str [11], 10);
strcat (error_str, gp_str [11]);
strcat (error_str, " INACTIVE IN FILE: ");
itoa (file + 1, gp_str [11], 10);
strcat (error_str, gp_str [11]);
return (1);
}
if (cntr == 1) * target = fi [file].c1_val;
else * target = fi [file].c2_val;
return (0);
}
/* DATAMAGE marker files
Like any good programmer I am LOATHE to waste as much as a single byte
of disk space or memory. But the MARKER FILES are written by BASIC,
and the smallest memory item it provides is a short (SWORD here).
Anyhow, the MARKER files start off with a quotated 37 byte string that
holds the user's description of the maker file, with no cr-lf.
Then the first "header" is 40 bytes long. Not all of them are currently
used, some are reserved for future expansion so as not to make every-
body's markers obsolete when they get an update. There are no more
cr-lfs in the file until you get to the end, where the user-assigned
names of the two counters are stored in quotated strings.
The following are all SWORDS:
Next is the number of records in the MARKER.
Next is the binary search switch (detailed in the fi struct, above).
Next is the number of binary search levels.
Next is counter 1 switch, detailed below.
Next is counter 2 switch, detailed below.
Now we move to offset 77 in the file, and read in the binary search
targets, and their formats. The second "header" is 48 bytes long.
See asf [8] [3] in the fi structure atop this file.
The records in the MARKER file start at offset 125. The records are
recorded as FILE SEQUENCES. You might do well to check their record
number in the CTRLFILE.RAD. They might have been deleted! See the
get_next_rcrd function.
Finally, there are the two quotated, 37 byte strings with cr-lfs for
the names of the counters.
Note that the marker file is left open. It must, of course, remain
open while being processed. You will need to close it at some point.
This function does everything you might wish to do with a marker. If
you don't plan to use the binary searches feel free to REMOVE the code
that does that. But keep a copy of the original, for future programs.
*/
BYTE far load_marker (BYTE file, BYTE * error_str)
{
BYTE b, d;
BYTE asf [8] [3];
WORD i, j;
WORD num_rcds;
SBYTE counter_sw;
SBYTE bs_sw;
SBYTE b_levels;
SBYTE c1_sw;
SBYTE c2_sw;
BYTE rcd_len;
struct
{
SBYTE high_byte;
BYTE low_byte;
} tgt;
/* close marker file if currently open */
if (fi [file].marker)
{
fclose (fi [file].marker);
fi [file].marker = NULL;
fi [file].mkr_active = 0;
}
/* set error just in case */
strcpy (error_str, "BAD MARKER FILE");
/* init asf array */
for (d = 0; d < 7; d++)
for (b = 0; b < 2; b++) asf [d] [b] = 0;
if ((fi [file].marker = fopen (gp_str [10], "r+b")) == NULL)
{
strcpy (error_str, "UNABLE TO OPEN MARKER FILE");
return (1);
}
/* get marker description */
fread (gp_str [13], 1, 37, fi [file].marker);
gp_str [13] [37] = 0;
/* test for valid marker file */
if (gp_str [13] [0] != 34 || gp_str [13] [36] != 34) return (1);
/* get number of records in marker */
b = fread (& num_rcds, 1, 2, fi [file].marker);
if (b != 2) return (1);
/* get counter switch */
b = fread (& tgt, 1, 2, fi [file].marker);
if (b != 2) return (1);
counter_sw = tgt.high_byte;
/* determine length of record in marker file */
switch (counter_sw)
{
case 0: rcd_len = 2; break;
case 1:
case 2: rcd_len = 10; break;
case 3: rcd_len = 18;
}
/* get binary search switch 1= active, 2=no */
b = fread (& tgt, 1, 2, fi [file].marker);
if (b != 2) return (1);
bs_sw = tgt.high_byte;
/* get number of binary search targets */
b = fread (& tgt, 1, 2, fi [file].marker);
if (b != 2) return (1);
b_levels = tgt.high_byte;
/* get c1 switch */
b = fread (& tgt, 1, 2, fi [file].marker);
if (b != 2) return (1);
c1_sw = tgt.high_byte;
/* get c2 switch */
b = fread (& tgt, 1, 2, fi [file].marker);
if (b != 2) return (1);
c2_sw = tgt.high_byte;
/* move to binary fields in marker file */
d = fseek (fi [file].marker, (DWORD) 77, SEEK_SET);
/* read in binary search targets, if any */
if (bs_sw > 0)
for (d = 0; d < b_levels; d++)
{
b = fread (& tgt, 1, 2, fi [file].marker);
if (b != 2) return (1);
i = get_curr_fno(file, tgt.high_byte);
if (i == -1)
{
clw (2); beep(); locate (12, 12);
prnt ("MARKER CONTAINS FIELDS DELETED FROM FILE - LOAD ABORTED!");
see_screen ();
return (1);
}
asf [d] [0] = (BYTE) i;
b = fread (& tgt, 1, 2, fi [file].marker);
if (b != 2) return (1);
asf [d] [1] = tgt.high_byte;
b = fread (& tgt, 1, 2, fi [file].marker);
if (b != 2) return (1);
asf [d] [2] = tgt.high_byte;
}
/* fill fi [file] struct */
fi [file].m_num_rcds = num_rcds;
fi [file].counter_sw = counter_sw;
fi [file].bs_sw = bs_sw;
fi [file].b_levels = b_levels;
fi [file].c1_sw = c1_sw;
fi [file].c2_sw = c2_sw;
fi [file].m_rcd_len = rcd_len;
fi [file].m_next_rcd = 0;
/* fill fi [file].asf array */
for (d = 0; d < 7; d++)
for (b = 0; b < 2; b++)
fi [file].asf [d] [b] = asf [d] [b];
/* reset file to first record */
fi [file].next_rcd = 0;
/* activate marker */
fi [file].mkr_active = 1;
/* move to records in marker file */
d = fseek (fi [file].marker, (DWORD) 125, SEEK_SET);
/* a-tha a-tha a-that's ALL, kiddies */
return (0);
}
WORD far minpt (BYTE file, BYTE field, BYTE * t_str)
{
/* performs kybd input for DATAMAGE fields */
BYTE c, cc, cl, d, inst = 0, len, psw = 0, scr_pos,
start = 0, max, tgt_pos, type, wfg = 0, x;
SBYTE s;
BYTE * test;
if (fi [file].key[field] -> type < 2)
{
len = max = fi [file].key [field] -> length;
if (max > 35) max = 35;
type = 1;
}
else
{
len = max = 17;
type = 2;
}
find_cursor (& cl, & cc); cc += 2;
ipt_box (cc, cl, max, 32, 1, 1, t_str);
rtrim (t_str);
d = x = strlen (t_str);
if (x > max) x = 0;
scr_pos = cc + x;
tgt_pos = x;
for (; d < len; d++) t_str [d] = 32;
t_str [len] = 0;
locate (cl, scr_pos);
nrml_cursor ();
/* detect decimal if numeric seeded input */
if (type == 2)
{
test = strstr (t_str, ".");
if (test == NULL) psw = 0;
else psw = 1;
}
while (! wfg)
{
get_one (& ctrl_val, & nrml_val);
if (nrml_val)
{
if ((type == 1 && nrml_val > 31 && nrml_val < 126) ||
(type == 2 && nrml_val > 44 && nrml_val < 58))
{
if (type == 2)
{
/* decimal */
if (nrml_val == 46)
{
if (psw == 1) {beep (); continue;}
psw = 1;
}
/* minus sign */
if (nrml_val == 45 &&
(tgt_pos > 0 || t_str [0] == 45))
{beep (); continue;}
}
if (tgt_pos >= len) {beep (); continue;}
if (! inst)
{
t_str [tgt_pos++] = nrml_val;
if ((scr_pos - cc) < max)
{
tele_out (nrml_val);
scr_pos++;
}
else
{
locate (cl, cc);
x = ++start + max;
for (d = start; d < x; d++)
tele_out (t_str [d]);
locate (cl, scr_pos);
}
}
else
{
if (t_str [len - 1] != 32) {beep (); continue;}
for (d = len; d > tgt_pos; d--)
t_str [d] = t_str [d - 1];
t_str [tgt_pos++] = nrml_val;
if (scr_pos - cc + 1> max) ++start;
else scr_pos++;
locate (cl, cc); no_cursor();
x = start + max;
for (d = start; d < x; d++) tele_out (t_str [d]);
locate (cl, scr_pos); full_cursor();
}
continue;
}
switch (nrml_val)
{
case 8 : /* backspace */
{
if (scr_pos <= cc) {beep (); continue;}
if (scr_pos - cc <= start) --start;
else --scr_pos;
--tgt_pos;
locate (cl, scr_pos);
goto del_char;
}
/* return */
case 13: {wfg = 2; continue;}
case 27: /* escape */
{
no_cursor ();
locate (cl, cc);
line_out (max, 32);
locate (cl, cc);
tgt_pos = 0; scr_pos = cc; inst = 0;
for (d = 0; d < len; d++) t_str [d] = 32;
nrml_cursor ();
start = t_str [len] = 0;
beep (); continue;
}
default : {beep (); continue;}
}
}
switch (ctrl_val)
{
case 71 : /* home */
{
start = tgt_pos = 0; scr_pos = cc;
locate (cl, scr_pos); no_cursor();
for (d = 0; d < max; d++) tele_out (t_str [d]);
locate (cl, scr_pos);
if (inst) full_cursor ();
else nrml_cursor ();
continue;
}
case 75 : /* left arrow */
{
if (tgt_pos < 1) {beep(); continue;}
if (scr_pos > cc)
{
locate (cl, --scr_pos);
--tgt_pos;
continue;
}
if (start < 1) {beep (); continue;}
locate (cl, cc);
x = --start + max;
for (d = start; d < x; d++) tele_out (t_str [d]);
--tgt_pos;
locate (cl, scr_pos); no_cursor();
if (inst) full_cursor ();
else nrml_cursor ();
continue;
}
case 115: /* ctrl + left arrow */
{
if (! tgt_pos) {beep(); continue;}
x = tgt_pos;
while (x && t_str [x] != 32) --x;
while (x && t_str [x] == 32) --x;
while (x && t_str [x] != 32) --x;
if (x) ++x;
c = tgt_pos - x; tgt_pos -= c;
if (scr_pos - cc - c > -1) scr_pos -= c;
else
{
s = start - c;
if (s < 0)
{
scr_pos -= 0 - s;
s = 0; beep();
}
start = s;
locate (cl, cc); no_cursor();
x = start + max;
for (d = start; d < x; d++) tele_out (t_str [d]);
if (inst) full_cursor ();
else nrml_cursor ();
}
locate (cl, scr_pos);
continue;
}
case 77 : /* right arrow */
{
if (tgt_pos >= len) {beep(); continue;}
if (scr_pos - cc < max)
{
locate (cl, ++scr_pos);
++tgt_pos;
continue;
}
if (start >= (len - max)) {beep(); continue;}
locate (cl, cc); no_cursor();
x = ++start + max; ++tgt_pos;
for (d = start; d < x; d++) tele_out (t_str [d]);
locate (cl, scr_pos);
if (inst) full_cursor ();
else nrml_cursor ();
continue;
}
case 116: /* ctrl + right arrow */
{
c = 0; x = tgt_pos;
while (x < len && c < 2)
{
if (! c)
{
if (t_str [x] != 32) x++;
else c++;
continue;
}
if (t_str [x] == 32) x++;
else c++;
}
if (c < 2) continue;
c = x - tgt_pos;
if (scr_pos - cc + c < max)
{
tgt_pos += c;
scr_pos += c;
}
else
{
d = start + c;
if (d > len) x = len - d;
else x = c;
tgt_pos += x; start += x;
locate (cl, cc); no_cursor();
x = start + max;
for (d = start; d < x; d++) tele_out (t_str [d]);
if (inst) full_cursor ();
else nrml_cursor ();
}
locate (cl, scr_pos);
continue;
}
case 79 : /* end */
{
tgt_pos = len - 1; scr_pos = max + cc - 1;
start = len - max;
locate (cl, cc); no_cursor();
x = start + max;
for (d = start; d < x; d++) tele_out (t_str [d]);
locate (cl, scr_pos);
if (inst) full_cursor ();
else nrml_cursor ();
continue;
}
case 82 : /* insert */
{
if (inst == 0)
{
inst = 1;
full_cursor ();
continue;
}
inst = 0; nrml_cursor ();
continue;
}
case 83 : /* delete */
{
if (tgt_pos > len) {beep (); continue;}
del_char:
if (t_str [tgt_pos] == 46) psw = 0;
for (d = tgt_pos; d < len; d++)
t_str [d] = t_str [d + 1];
t_str [len] = 32;
locate (cl, cc); no_cursor();
x = start + max;
for (d = start; d < x; d++) tele_out (t_str [d]);
locate (cl, scr_pos);
if (inst) full_cursor ();
else nrml_cursor ();
continue;
}
default: {beep (); continue;}
}
}
ipt_box (cc, cl, max, 32, 1, 0, t_str);
no_cursor ();
rtrim (t_str);
return (strlen (t_str));
}