home *** CD-ROM | disk | FTP | other *** search
- /* (c) Marietta Systems, Inc 1987
- 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);
- }