/* (c) Marietta Systems, Inc 1987 * All rights reserved */ /* * This program sets up the dictionary for a dBase3+ file * * The maximum number of fields is 20, and memo fields are not supported */ #include "mtest.h" int dbf_cr(char*); int dbf_init(int*, struct DBF_DEF*, char*, int); int dbf_name(byte*); void linedisp(struct DBF_DEF*, int); int lineacpt(struct DBF_DEF*, int); void lineshuf(struct DBF_DEF*, int, int); #define point "\075\020" /* * * Function to create dbase3+ file & setup data dictionary * */ int dbf_cr(name) char *name;{ struct DBF_DEF format[20]; int fields = 0, fld = 0, fh = fileopen(name, dbase3, recreate), z, ret; byte kk = 0; if (fh < 0) return fh; /* setup */ for (z = 0; z < 20; format[z++].dbf_type = 'C') format[z].dbf_name[0] = format[z].dbf_len = format[z].dbf_dec = 0; /* setup function key map */ KEYMATCH[0] = 0X430; /* Up & right arrow, Ctrl+Enter */ KEYMATCH[1] = 0X108; /* Down & left arrow */ KEYMATCH[2] = KEYMATCH[3] = KEYMATCH[6] = KEYMATCH[7] = 0; KEYMATCH[4] = 0X3000; /* F5, F6 */ disp_err("",1); /* force display of new function keys */ if (1 > mk_wndw(TOP_LINE + 1, 1, SCRN_LEN - 1, 80, "Enter data dictionary details for dBase3+ file")) goodbye(13); kk = INSERT; /* must first insert into an empty dictionary */ linedisp(format, 0); /* main accept loop */ for(;;){ if (!kk) linedisp(format, fld); display(point, fld+1, 5, blink); set_crsr(fld+1, 1); if (!kk) kk = grabchar(); display(": ", fld+1, 5, high); switch((int)kk){ case CRS_UP: if (fld) fld--; kk = 0; break; case CRS_DN: if (fld < 20 && fld < fields) fld++; kk = 0; break; case CRS_RT: case ENTER: case TAB: if (fld == fields) {kk = INSERT; break;} if ((ret = lineacpt(format, fld)) < 0) goodbye(11); kk = (ret ? INCHAR : 0); if (format[fld].dbf_name[0] == 0 && fields != fld) {lineshuf(format, fld, 1); fields--;} break; case QUIT: kk = 0; break; case INSERT: if (fields >= 20) {disp_err("No more fields allowed",1); break;} if (fld < fields) lineshuf(format, fld, -1); if ((ret = lineacpt(format, fld)) < 0) goodbye(11); kk = (ret ? INCHAR : 0); if (format[fld].dbf_name[0] == 0) lineshuf(format, fld, 1); else {fld++; fields++;} if (!kk && fld >= fields - 1) kk = INSERT; break; case DELETE:if (fields && fld < fields) {lineshuf(format, fld, 1); fields--;} kk = 0; break; case HELP: if (mk_wndw(3,48,13,80,"Dictionary help") > 1){ display("To change a line, move the ",1,1,high); display(" cursor with the up and down ",2,1,high); display(" keys, then make your selec- ",3,1,high); display(" tion with the Enter key. ",4,1,high); display("To insert a line press F5 key ",5,1,high); display("To delete a line press F6 key ",6,1,high); display("To exit, press the F10 key ",7,1,high); display("<< Press ESC key to continue>>",9,1,low); while(grabchar() != ESC) disp_err("Press ESC key", 2); rm_wndw(); } kk = 0; break; default: warble(1000); idleloop(ERR_BEEP); warble(0); kk = 0; break; } /* end switch */ if (INCHAR == QUIT && disp_qry("Have you completed entry")) break; } /* end for loop */ ret = ((fields && disp_qry("Write the dictionary to file")) ? dbf_init(&fh, format, name, fields) : -1); fileclos(fh); rm_wndw(); return ret; } /* end function dbf_cr */ /* * * Function to write dictionary to new dbase3+ file * */ int dbf_init(fh, format, name, fields) int *fh, fields; struct DBF_DEF *format; char *name;{ int z; short *sptr; long rec_nbr = 0L; fileinit(*fh, 0, 32, 0L); /* nil start, 32 byte record file */ memset(FN[*fh].record, 0, 32); /* write the system header 32 byte record */ FN[*fh].record[0] = SYS_REC; sptr = (short *) &FN[*fh].record[8]; sptr[0] = fields * 32 + 33; /* start of data */ for (sptr[1] = 1, z = 0 ; z < fields ; z++) {sptr[1] += format[z].dbf_len;} /* data record length */ if (filewrit(*fh, &rec_nbr) < 0) goto error; /* write the field dictionary records */ for (z = 0 ; z < fields ; z++){ memset(FN[*fh].record, 0, 32); memcpy(FN[*fh].record, format[z].dbf_name, 11); FN[*fh].record[11] = format[z].dbf_type; FN[*fh].record[16] = format[z].dbf_len; FN[*fh].record[17] = format[z].dbf_dec; if (filewrit(*fh, &rec_nbr) < 0) goto error; } /* write the dBase3+ header terminator */ FN[*fh].rec_len = 1; /* hairy but necessary technique here */ FN[*fh].record[0] = 0X0D; if (filewrit(*fh, &rec_nbr) < 0) goto error; FN[*fh].rec_len = 32; FN[*fh].prime = 0L; /* set file record count back to zero */ return 0; error: fileclos(*fh); disp_msg("Terminate?? in dbf_init ",(int)rec_nbr + 100); read_kb(); *fh = fileopen(name, dbase3, recreate); return -1; } /* end function dbf_init */ /* * * Function to display line of data dictionary * */ void linedisp(format, line) struct DBF_DEF *format; int line; { byte text[12]; display("Name: ", line + 1, 1, high); justify(left, text, format[line].dbf_name, 10, 0); display(text, 0, 0, ACC_DISP); display(" Type: ", 0, 0, high); switch((int)format[line].dbf_type){ case 0: case 32: case 'C':display("Character", 0, 0, ACC_DISP); break; case 'D':display("Date ", 0, 0, ACC_DISP); break; case 'L':display("Logical ", 0, 0, ACC_DISP); break; case 'M':display("Memo ", 0, 0, ACC_DISP); break; case 'N':display("Numeric ", 0, 0, ACC_DISP); break; default: display("?????????", 0, 0, ACC_DISP); break; } display(" Size: ", 0, 0, high); if (format[line].dbf_type == 'N') sprintf(text,"%3u %u",format[line].dbf_len, format[line].dbf_dec); else sprintf(text, "%3u ", format[line].dbf_len); display(text, 0, 0, ACC_DISP); display(" ", line+1, 45, low); } /* end function linedisp */ /* * * Function to validate a dbase3+ field name * */ int dbf_name (name) byte *name;{ int z, len; concat(name, 0); /* strip trailing spaces */ strupr(name); /* turn alpha characters into uppercase */ len = strlen(name); if (len > 10 || !len || !isalpha(name[0])) goto error; for (z = 1 ; z < len ; z++) if (!isalpha(name[z]) && !isdigit(name[z]) && name[z] != '_') goto error; return 1; error: disp_err("Invalid character in fieldname",3); return 0; } /* * * Function to accept a new line in dictionary * */ #define CR_MSG0 " " #define CR_MSG1 " Char, Date, Logical, Numeric " #define CR_MSG2 " Maximum of 254 bytes in size " #define CR_MSG3 " Maximum of 32 bytes in Numeric" #define CR_MSG4 " Maximum of 8 decimal places " #define CR_MSG5 " Only A - Z, 0 - 9, and _ " int lineacpt(format, fld) struct DBF_DEF *format; int fld;{ int ret, ans, z; char text[12]; /* */ name: display(CR_MSG5, fld+1, 48, low); set_crsr(fld+1, 7); ret = accept(format[fld].dbf_name, left, alt_reverse, 10, 0); if (ret && INCHAR != CRS_RT) goto end; if (!dbf_name(format[fld].dbf_name)) goto name; display(format[fld].dbf_name, fld+1, 7, ACC_DISP); for (z = 0 ; z < 20 ; z++) if (z != fld && !strcmp((byte*)format[fld].dbf_name, (byte*)format[z].dbf_name)) {disp_err("Duplicate name",3); goto name;} /* */ type: display(CR_MSG1, fld+1, 48, low); set_crsr(fld+1, 25); text[0] = format[fld].dbf_type; text[1] = 0; ret = accept(text, left, alt_reverse, 1, 0); if (ret) if (INCHAR == CTL_ENT || INCHAR == CRS_LT) goto name; else if (INCHAR != CRS_RT) goto end; format[fld].dbf_type = text[0] = toupper(text[0]); /* */ switch ((int)text[0]){ case 'C': display("Character", fld+1, 25, ACC_DISP); sprintf(text, "%3u", format[fld].dbf_len); c_size: display(CR_MSG2, fld+1, 48, low); set_crsr(fld+1, 42); ret = accept(text, code, alt_low, 3, 0); if (ret) if (INCHAR == CTL_ENT || INCHAR == CRS_LT) goto type; else break; if ((ans = atoi(text)) > 254 || !ans) {disp_err("size must be 1 thru 254", 1); goto c_size;} format[fld].dbf_len = ans; break; case 'D': break; case 'L': break; case 'N': display("Numeric ", fld+1, 25, ACC_DISP); n1_size: sprintf(text, "%3u", format[fld].dbf_len); display(CR_MSG3, fld+1, 48, low); set_crsr(fld+1, 42); ret = accept(text, code, alt_low, 3, 0); if (ret) if (INCHAR == CTL_ENT || INCHAR == CRS_LT) goto type; else if (INCHAR != CRS_RT) break; if ((ans = atoi(text)) > 32 || !ans) {disp_err("size must be 1 thru 32", 1); goto n1_size;} format[fld].dbf_len = ans; n2_size: sprintf(text, "%1u", format[fld].dbf_dec); display(CR_MSG4, fld+1, 48, low); set_crsr(fld+1, 46); ret = accept(text, code, alt_low, 1, 0); if (ret) if (INCHAR == CTL_ENT || INCHAR == CRS_LT) goto n1_size; else break; if ((ans = atoi(text)) > 8) {disp_err("Maximum of 8 decimal places", 1); goto n2_size;} format[fld].dbf_dec = ans; break; default: disp_err("Invalid type selection", 1); goto type; } /* end switch */ /* exit validation */ end: if (!format[fld].dbf_name[0]) return ret; /* empty */ switch((int)format[fld].dbf_type){ case 'C': format[fld].dbf_dec = 0; if (format[fld].dbf_len == 255) goto c_size; break; case 'D': format[fld].dbf_len = 8; format[fld].dbf_dec = 0; break; case 'L': format[fld].dbf_len = 1; format[fld].dbf_dec = 0; break; case 'N': if (format[fld].dbf_len > 32) goto n1_size; if (format[fld].dbf_dec > 8) goto n2_size; if (format[fld].dbf_dec + 2 > format[fld].dbf_len) goto n1_size; break; default: goto type; } /* end switch */ display(CR_MSG0, fld+1, 48, low); /* blank out help area */ if (!format[fld].dbf_len) memset(format[fld].dbf_name, 0, 11); linedisp(format, fld); return ret; } /* end function lineacpt */ /* * * Function to shuffle up and down the dictionary display * */ void lineshuf(format, fld, up) struct DBF_DEF *format; int fld, up;{ int to, from, base; up = (up < 0 ? -1 : 1); scroll(up, fld); /* scroll window up or down */ to = (up > 0 ? fld : 19); from = (up > 0 ? fld + 1 : 18); base = (up > 0 ? 19 : fld); for (; base != to ; to += up, from += up){ memcpy(format[to].dbf_name, format[from].dbf_name, 11); format[to].dbf_type = format[from].dbf_type; format[to].dbf_len = format[from].dbf_len; format[to].dbf_dec = format[from].dbf_dec; } memset(format[to].dbf_name, 0, 11); format[to].dbf_type = 'C'; format[to].dbf_len = 0; format[to].dbf_dec = 0; if (up < 0) linedisp(format, fld); } /* end function lineshuf */ /* * * Main section * */ void main(){ char name[51]; int z, fh; clr_scrn("dBase3+ dictionary create"); strcpy(name, "dbftest.dbf"); for (;;){ for (z = 0 ; z < 8 ; KEYMATCH[z++] = 0); disp_err("",1); display("Enter file name ", 20, 2, low); if (accept(name, left, alt_reverse, 50, 0)) goodbye(0); if ((fh = fileopen(name, dbase3, readonly)) < 0) continue; if (fh && FN[fh].fnext != NULL && !disp_qry("Do you wish to overwrite file")) {fileclos(fh); continue;} else if (fh) {fileclos(fh); if (fileback(name) < 1) continue;} if (!dbf_cr(name)) {name[0] = 0; disp_err("Dictionary created", 1);} else disp_err("Error end to dict create", 2); } }