Category : C Source Code
Archive   : C_WNDW.ZIP
Filename : DBFEDIT.C
All rights reserved */
/*
* This program allows the viewing, amending, deleting and adding of
* records to a dBase II Plus '.dbf' file.
*
* This program only works with files with less than 21 fields!
*/
#include "mtest.h"
#ifndef LATTICE
#define memcpy memmove
#endif
/* */
#define fileend (FN[fh].start + FN[fh].rec_len * FN[fh].prime)
int dbf_acpt(int, int, struct DBF_DEF*, enum ATTRIB);
int dbf_disp(int, int, struct DBF_DEF*, enum ATTRIB, int, int);
int dbf_init(int*, struct DBF_DEF**);
void dbf_mnt(int, int, struct DBF_DEF*, long*);
void do_search(int, char*, long*);
void mnt_scrn(int, char*);
void recblank(int);
int rec_acpt(int, int, struct DBF_DEF*);
void rec_disp(int, int, struct DBF_DEF*);
void show_nbr(int, long);
int stsearch(char*, char*);
/*
*
* Function to accept a dbase3 field
*
*/
int dbf_acpt(fh, field, format, atb)
int fh, field;
struct DBF_DEF *format;
enum ATTRIB atb;{
int z, basept, ret, x = _CURSOR.X, y = _CURSOR.Y;
enum _JUST just;
char text[255];
/* Error check */
if (fh < 5 || fh > MAXFILES || field < 0
|| field > FN[fh].start/32 - 2)
{disp_err("Parameter error in dbf_acpt", 1001); return -10;}
/* Setup */
for (z = 0 , basept = 1 ; z < field ; basept += format[z++].dbf_len);
memcpy(text, &FN[fh].record[basept], format[field].dbf_len);
text[format[field].dbf_len] = 0; /* copy to entry area */
switch ((int)format[field].dbf_type){
case 'C': just = left; break;
case 'L': just = left; break;
case 'N': just = decimal; break;
case 'D': just = date;
if (text[0] == 32)
{text[10] = -80; text[11] = text[12] = 0;}
else {text[12] = (char)atoi(&text[6]); text[6] = 0;
text[11] = (char)atoi(&text[4]); text[4] = 0;
text[10] = (char)(atoi(text) - 1980);}
memcpy (text, &text[10], 3);
break;
default: disp_err("Cannot edit memo field", 1002);
return (INCHAR == ENTER ? 0 : 1);
}
/* perform accept */
re_enter: ret = accept(text, just, atb, format[field].dbf_dig,
format[field].dbf_dec);
if (ret < 0) return ret; /* Pass through error code from accept */
if (ret && INCHAR == CTL_ENT) return ret;
switch ((int)format[field].dbf_type){
case 'C': break;
case 'L': text[0] = toupper(text[0]);
if (text[0] != 'T' && text[0] != 'F')
{disp_err("Logical field type requires 'T' or 'F'", 1);
set_crsr(x,y); goto re_enter;}
display(text, x, y, ACC_DISP);
break;
case 'N': break;
case 'D': memcpy(&text[10], text, 3);
if (text[1] != 0) sprintf(text, "%4u%2u%2u",
1980 + text[10], (int)text[11], (int)text[12]);
else strcpy(text, " ");
}
memcpy(&FN[fh].record[basept],text, format[field].dbf_len);
return ret;
} /* end of function dbf_acpt */
/*
*
* Function to display a dbase3 field
*
*/
int dbf_disp(fh, field, format, atb , x, y)
int fh, field, x, y;
struct DBF_DEF *format;
enum ATTRIB atb;{
int z, basept;
char text[255];
/* Error check */
if (fh < 5 || fh > MAXFILES || field < 0
|| field > FN[fh].start/32 - 2)
{disp_err("Parameter error in dbf_disp", 1001); return -10;}
/* Setup */
for (z = 0 , basept = 1 ; z < field ; basept += format[z++].dbf_len);
memcpy(text, &FN[fh].record[basept], format[field].dbf_len);
text[format[field].dbf_len] = 0;
switch ((int)format[field].dbf_type){
case 'N': strcpy(&text[60], text);
justify(decimal, text, &text[60], format[field].dbf_dig,
format[field].dbf_dec);
break;
case 'D': if (text[0] == 32) /* Null date */
{text[10] = -80; text[11] = text[12] = 0;}
else {text[12] = (char)atoi(&text[6]); text[6] = 0;
text[11] = (char)atoi(&text[4]); text[4] = 0;
text[10] = (char)(atoi(text) - 1980);}
date_out(text, &text[10]);
break;
default: break;
}
/* perform display */
display(text, x, y, atb);
return 0;
} /* end function dbf_disp */
/*
*
* Function to read in file and data dictionary
*
*/
int dbf_init(fields, format)
int *fields;
struct DBF_DEF **format;{
int fh, z;
char name[51], text[25];
for (z = 0; z < 8 ; KEYMATCH[z++] = 0); /* suppress function keys */
disp_err("",1); /* force display of function keys */
/* test if already initialized */
strcpy(name,"dbftest.dbf");
/* obtain file name and setup format */
for (;;){
disp_msg("",0);
display("Enter dBase 3+ file name ", 20, 1, high);
if (accept(name, left, alt_reverse, 50, 0) < 0 || INCHAR == QUIT)
goodbye(0);
if ((fh = fileopen(name, dbase3, update)) < 0) continue;
if (!fh) {disp_err("File not found - try again", 1); continue;}
if (FN[fh].start < 65)
{disp_err("Not valid dBase3+ file",1); idleloop(18);}
if (FN[fh].fnext == NULL)
disp_err("Could not load data dictionary",1);
if (FN[fh].start < 65 || FN[fh].fnext == NULL)
{fileclos(fh); continue;}
break;
} /* end for loop */
mk_wndw(5,15, 15,65, "Display of file header information");
display((byte*)FN[fh].fname, 1, 2, high);
sprintf(text, "prime = %ld", FN[fh].prime);
display(text, 2, 2, high);
sprintf(text, "start = %d", FN[fh].start);
display(text, 3, 2, high);
sprintf(text, "rec_len= %d", FN[fh].rec_len);
display(text, 4, 2, high);
sprintf(text, "write = %c", FN[fh].write);
display(text, 5, 2, high);
sprintf(text, "ftype = %d", (int)FN[fh].ftype);
display(text, 6, 2, high);
if (FN[fh].fnext == NULL)
display("NULL pointer value in fnext", 7, 2, high);
else display("Data dictionary loaded", 7, 2, high);
display("<< Press ESC key to continue >>", 9, 5, low);
while (grabchar() != ESC) disp_err("Press ESC key", 1);
rm_wndw();
*fields = dbf_fld(fh);
*format = (struct DBF_DEF *)FN[fh].fnext;
return fh;
} /* end function dbf_init */
/*
*
* Function to initialize the screen
*
*/
void mnt_scrn(fh, title)
int fh;
char *title;{
/* setup function key map */
KEYMATCH[0] = 0X428; /* PgDn, Up arrow, Ctrl+Enter */
KEYMATCH[1] = 0X104; /* PgUp, Down arrow */
KEYMATCH[2] = KEYMATCH[3] = KEYMATCH[6] = KEYMATCH[5] = 0;
KEYMATCH[4] = 0XB400; /* F3, F5, F6, F8 */
KEYMATCH[7] = 0X4800; /* Ctrl+PgDn, Ctrl+PgUp */
disp_err("",1); /* force display of new function keys */
/* Create info area at top of screen */
display("\030:Prev field PgUp:Prev Record Ctrl+PgUp:1st Record ",
1, 2, low);
display((byte*)FN[fh].fname, 1, 65, alt_low);
display("\031:Next field PgDn:Next Record Ctrl+PgDn:Last Record",
2, 2, low);
/* create edit window */
if (mk_wndw(TOP_LINE + 3, 1, SCRN_LEN, SCRN_WID, title) < 0)
goodbye(10);
} /* end function mnt_scrn */
/*
*
* Function to display a record on the screen
*
*/
void rec_disp(fh, fields, format)
int fh, fields;
struct DBF_DEF *format;{
int x = 1, z, len;
clr_wndw();
if (FN[fh].record[0] != IN_USE)
display("Record status is deleted", x++, 5, blink);
for (z = 0 ; z < fields ; z++){
display(format[z].dbf_name, x, 1, high);
dbf_disp(fh, z, format, reverse, x, 12);
len = (format[z].dbf_type != 'N' ? format[z].dbf_len :
fld_len(decimal, format[z].dbf_dig, format[z].dbf_dec));
x += len / (SCRN_WID - 12) + 1;
}
} /* end function rec_disp */
/*
*
* Function to accept a record on the screen
*
*/
int rec_acpt(fh, fields, format)
int fh, fields;
struct DBF_DEF *format;{
int x = 1, z, len, kk;
if (FN[fh].record[0] != IN_USE) x++;
for (z = 0 ; z < fields ; ){
set_crsr(x, 12);
if (dbf_acpt(fh, z, format, alt_reverse)) kk = INCHAR; else kk = 0;
switch (kk){
case 0:
case ENTER:
case CRS_DN:
len = (format[z].dbf_type != 'N' ? format[z].dbf_len :
fld_len(decimal, format[z].dbf_dig, format[z].dbf_dec));
x += len / (SCRN_WID - 12) + 1;
z++; break;
case CTL_ENT:
case CRS_UP: if (z == 0) break;
len = (format[z-1].dbf_type != 'N' ? format[z-1].dbf_len :
fld_len(decimal, format[z-1].dbf_dig,
format[z-1].dbf_dec));
x -= len / (SCRN_WID - 12) + 1;
z--; break;
default: return kk;
}
}
return 0;
} /* end function rec_acpt */
/*
*
* Function to show current record location on screen
* (uses reserved functions 'set_clr' and 'scrn_map'
*/
void show_nbr(fh, rec_nbr)
int fh;
long rec_nbr;{
char text[16];
set_clr(99, low); /* use error status color */
sprintf(text, "%5lu of %-5lu", rec_nbr, FN[fh].prime);
scrn_map(text, TOP_LINE + 2, 65); /* hairy technique */
set_clr(98, low); /* reset color */
}
/*
*
* Function to blank out a record
*
*/
void recblank(fh)
int fh;{
memset(FN[fh].record, 32, FN[fh].rec_len);
FN[fh].record[FN[fh].rec_len] = 0;
FN[fh].record[0] = IN_USE;
}
/*
*
* Find if string2 is in string1
*
*/
int stsearch(s1, s2)
char *s1, *s2;{
int len2 = strlen(s2);
char *ptr;
ptr = strchr(s1, s2[0]);
while (ptr != NULL) {
if (!strncmp(ptr, s2, len2)) return 1; /* found */
ptr = strchr(&ptr[1], s2[0]);
}
return 0;
}
/*
*
* Function to search for a specified string
*
*/
void do_search(fh, text, rec_nbr)
char *text;
int fh;
long *rec_nbr;{
int count = 0;
long base = *rec_nbr;
char out[15];
/* setup */
if (mk_wndw(5,7, 11,73, "File search through dbase3+ file") < 0)
return;
display("Remember dates are stored as yyyymmdd ('19801231' for 12/31/80)",
5, 2, low);
/* obtain search text */
display("Enter search text ", 1, 1, high);
if (accept(text, left, alt_reverse, 16, 0))
{disp_err("Search abandoned",1); rm_wndw(); return;}
concat(text, 0); /* suppress trailing spaces */
strupr(text);
/* read around through the file */
for (;;) {
if (!fileread(fh, nextrec, rec_nbr))
fileread(fh, firstrec, rec_nbr);
if (*rec_nbr == base) {disp_err("No matching text found", 1);
warble(500); idleloop(5); rm_wndw(); warble(0); return;}
if (5 == (count++)) {
sprintf(out,"Record = %6lu", *rec_nbr);
display(out, 2, 5, reverse);
if (kbhit() && disp_qry("Do you wish to stop the search"))
{rm_wndw(); return;}
count = 0;
}
strupr(&FN[fh].record[1]);
if (stsearch(&FN[fh].record[1], text))
{disp_err("Match found", 1); *rec_nbr -= 1L;
rm_wndw(); return;}
}
}
/*
*
* Function to perform file maintenance
*
*/
void dbf_mnt(fh, fields, format, rec_nbr)
int fh, fields;
long *rec_nbr;
struct DBF_DEF *format;{
int ret;
byte kk = 0;
char text[17];
/* setup */
mnt_scrn(fh, "Edit function for dBase3+ files");
if ((ret = fileread(fh, firstrec, rec_nbr)) < 0) goodbye(3);
show_nbr(fh, *rec_nbr - 1L);
text[0] = 0;
if (!ret) kk = INSERT; /* Handle special case of empty file */
/* main accept loop */
for (;;){
if (!ret && !kk) recblank(fh);
if (!kk) {rec_disp(fh, fields, format); scrnsave(0);}
switch((kk ? kk : grabchar())){
case PGUP:
case CTL_ENT: kk = 0; *rec_nbr -= 2L;
if (*rec_nbr < 1L)
{*rec_nbr = 1L; disp_err("Top of file",1);}
break;
case PGDN:
case ENTER: kk = 0;
if (*rec_nbr > FN[fh].prime)
{*rec_nbr = FN[fh].prime; disp_err("End of file", 1);}
break;
case CTL_PGUP: *rec_nbr = 1L; kk = 0; break;
case CTL_PGDN: *rec_nbr = FN[fh].prime; kk = 0; break;
case UNDO: *rec_nbr -= 1L;
if (FN[fh].record[0] != DELETED ||
!disp_qry("Do you want to UNDO the delete"))
{kk = 0; break;}
FN[fh].record[0] = IN_USE;
if (filewrit(fh, rec_nbr) < 0) goodbye(6);
kk = 0; *rec_nbr -= 1L; break;
case SEARCH: do_search(fh, text, rec_nbr);
kk = 0; break;
case INSERT: fileseek(fh, fileend);
*rec_nbr = FN[fh].prime + 1L;
recblank(fh);
rec_disp(fh, fields, format);
kk = rec_acpt(fh, fields, format);
if (filewrit(fh, rec_nbr) < 0) goodbye(7);
if (!kk && *rec_nbr > FN[fh].prime) kk = INSERT;
break;
case DELETE: *rec_nbr -= 1L; kk = 0;
if (!disp_qry("Do you really want to delete")) break;
FN[fh].record[0] = DELETED;
if (filewrit(fh, rec_nbr) < 0) goodbye(8);
*rec_nbr -= 1L; break;
case AMEND: *rec_nbr -= 1L;
if (FN[fh].record[0] != IN_USE)
{disp_err("You cannot amend a deleted record",1);
kk = 0; break;}
kk = rec_acpt(fh, fields, format);
if (filewrit(fh, rec_nbr) < 0) goodbye(9);
break;
case QUIT: return;
case HELP: helpscrn(NULL);
default: disp_msg("",0); *rec_nbr -= 1L; kk = 0;
warble(1000); idleloop(ERR_BEEP); warble(0);
break;
} /* end switch */
if (kk && *rec_nbr) *rec_nbr -= 1L;
if ((ret = fileread(fh, relative, rec_nbr)) < 0) goodbye(5);
if (!ret) {disp_err("End of file reached",1);
ret = fileread(fh, lastrec, rec_nbr);}
show_nbr(fh, *rec_nbr - 1L);
} /* end for loop */
} /* end of dbf_mnt function */
/*
*
* Main program
*
*/
void main(){
struct DBF_DEF *format;
long rec_nbr = 1L;
int fh, fields;
clr_scrn("Test of dbf access");
if ((fh = dbf_init(&fields, &format)) < 1) goodbye(2);
dbf_mnt(fh, fields, format, &rec_nbr);
fileclos(fh);
goodbye(0);
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/