/* --------- entry.c ---------- */ #include #include #include #include #include #include #include "twindow.h" #include "keys.h" #define FIELDCHAR '_' int insert_mode = FALSE; /* insert mode, TRUE/FALSE */ extern int helpkey; /* -------- local prototypes -------- */ void addfield(WINDOW *wnd, FIELD *fld); void disp_field(WINDOW *wnd, char *bf, char *msk); void data_value(WINDOW *wnd, FIELD *fld); void insert_status(void); int read_field(WINDOW *wnd, FIELD *fld); void right_justify(char *s); void right_justify_zero_fill(char *s); int validate_date(char *s); int endstroke(int c); int spaces(char *c); /* -------- initialize a template --------- */ void init_template(WINDOW *wnd) { FIELD *fld, *fl; fld = FHEAD; while (fld) { fl = fld->fnxt; free(fld); fld = fl; } FHEAD = FTAIL = NULL; } /* ------ establish a field in a template ------- */ FIELD *establish_field(wnd, cl, rw, msk, bf, ty) WINDOW *wnd; int rw; int cl; char *msk; char *bf; int ty; { FIELD *fld; if ( (fld = malloc(sizeof(FIELD))) == NULL) return NULL; fld->fmask = msk; fld->frow = rw; fld->fcol = cl; fld->fbuff = bf; fld->ftype = ty; fld->fprot = 0; fld->fnxt = fld->fprv = NULL; fld->fvalid = NULL; fld->fhelp = NULL; fld->fhwin = NULL; fld->flx = fld->fly = 0; addfield(wnd, fld); return fld; } /* ----- add a field to the end of the list ------ */ static void addfield(WINDOW *wnd, FIELD *fld) { if (FTAIL) { fld->fprv = FTAIL; FTAIL->fnxt = fld; } FTAIL = fld; if (!FHEAD) FHEAD = fld; } /* -------- display a data field ------ */ static void disp_field(WINDOW *wnd, char *bf, char *msk) { while (*msk) { wputchar(wnd, *msk != FIELDCHAR ? *msk : *bf++); msk++; } } /* ------- display the data value in a field ------ */ static void data_value(WINDOW *wnd, FIELD *fld) { wcursor(wnd, fld->fcol, fld->frow); disp_field(wnd, fld->fbuff, fld->fmask); } /* ------ display all the fields in a window ------- */ void field_tally(WINDOW *wnd) { FIELD *fld; fld = FHEAD; while (fld != NULL) { data_value(wnd, fld); fld = fld->fnxt; } } /* ----- set a field's help window ------- */ void field_window(FIELD *fld, char *hwin, int x, int y) { fld->fhwin=hwin; fld->flx = x; fld->fly = y; } /*page*/ /* ------- clear a template to all blanks ------ */ void clear_template(WINDOW *wnd) { FIELD *fld; char *bf, *msk; fld = FHEAD; while (fld != NULL) { bf = fld->fbuff; msk = fld->fmask; while (*msk) { if (*msk == FIELDCHAR) *bf++ = ' '; msk++; } fld = fld->fnxt; } field_tally(wnd); } /* ---------- set insert/exchange cursor shape ----------- */ static void insert_status() { set_cursor_type(insert_mode ? 0x0106 : 0x0607); } /*page*/ /* ------- read a field from the keyboard ------------- */ static int read_field(WINDOW *wnd, FIELD *fld) { char *mask = fld->fmask, *buff = fld->fbuff; int done = FALSE, c, column; column = fld->fcol; while (*mask != FIELDCHAR) { column++; mask++; } while (TRUE) { wcursor(wnd, column, fld->frow); c = get_char(); if (fld->ftype == 'A') c = toupper(c); clear_message(); switch (c) { case '\b': case BS: if (buff == fld->fbuff) { done = c == BS; break; } --buff; do { --mask; --column; } while (*mask != FIELDCHAR); if (c == BS) break; case DEL: movmem(buff+1, buff, strlen(buff)); *(buff+strlen(buff)) = ' '; wcursor(wnd, column, fld->frow); disp_field(wnd, buff, mask); break; case FWD: do { column++; mask++; } while (*mask && *mask != FIELDCHAR); buff++; break; case INS: insert_mode ^= TRUE; insert_status(); break; case '.': if (fld->ftype == 'C') { if (*mask++ && *buff == ' ') { *buff++ = '0'; if (*mask++ && *buff == ' ') *buff++ = '0'; } right_justify(fld->fbuff); wcursor(wnd, fld->fcol, fld->frow); disp_field(wnd, fld->fbuff, fld->fmask); column = fld->fcol+strlen(fld->fmask)-2; mask = fld->fmask+strlen(fld->fmask)-2; buff = fld->fbuff+strlen(fld->fbuff)-2; break; } default: if (endstroke(c)) { done = TRUE; break; } if (toupper(fld->ftype)!='A'&&!isdigit(c)) { error_message("Numbers only"); break; } if (insert_mode) { movmem(buff, buff+1, strlen(buff)-1); disp_field(wnd, buff, mask); wcursor(wnd, column, fld->frow); } *buff++ = c; wputchar(wnd, c); do { column++; mask++; } while (*mask && *mask != FIELDCHAR); if (!*mask) c = FWD; break; } if (!*mask) done = TRUE; if (done) { if (fld->ftype == 'D' && c != ESC && validate_date(fld->fbuff) != OK) return ERROR; break; } } if (c != ESC && toupper(fld->ftype) != 'A') { if (fld->ftype == 'C') { if (*mask++ && *buff == ' ') { *buff++ = '0'; if (*mask++ && *buff == ' ') *buff++ = '0'; } } if (fld->ftype == 'Z' || fld->ftype == 'D') right_justify_zero_fill(fld->fbuff); else right_justify(fld->fbuff); wcursor(wnd, fld->fcol, fld->frow); disp_field(wnd, fld->fbuff, fld->fmask); } return c; } /*page*/ /* ---------- test c for an ending keystroke ----------- */ static int endstroke(int c) { switch (c) { case '\r': case '\n': case '\t': case ESC: case F1: case F2: case F3: case F4: case F5: case F6: case F7: case F8: case F9: case F10: case PGUP: case PGDN: case HOME: case END: case UP: case DN: return TRUE; default: return FALSE; } } /*page*/ /* ------- right justify, space fill -------- */ static void right_justify(char *s) { int len; len = strlen(s); while (*s == ' ' || *s == '0' && len) { len--; *s++ = ' '; } if (len) while (*(s+(len-1)) == ' ') { movmem(s, s+1, len-1); *s = ' '; } } /* ---------- right justify, zero fill --------------- */ static void right_justify_zero_fill(char *s) { int len; if (spaces(s)) return; len = strlen(s); while (*(s + len - 1) == ' ') { movmem(s, s + 1, len-1); *s = '0'; } } /* ----------- test for spaces -------- */ int spaces(char *c) { while (*c == ' ') c++; return !*c; } /*page*/ /* -------------- validate a date ----------------- */ static int validate_date(char *s) { static int days [] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; char date [7]; int mo; strcpy(date, s); if (spaces(date)) return OK; days[1] = (atoi(date+4)%4) ? 28 : 29; *(date + 4) = '\0'; mo = atoi(date+2); *(date+2) = '\0'; if (mo && mo<13 && atoi(date) && atoi(date)<=days[mo-1]) return OK; error_message("Invalid date"); return ERROR; } /* ----- Process data entry for a screen template. ---- */ int data_entry(WINDOW *wnd) { FIELD *fld; int exitcode, isvalid, done=FALSE, oldhelpkey=helpkey; field_tally(wnd); fld = FHEAD; /* ---- collect data from keyboard into screen ---- */ while (fld != NULL && done == FALSE) { set_help(fld->fhwin, fld->flx, fld->fly); helpkey = (fld->fhelp) ? 0 : oldhelpkey; wcursor(wnd, fld->fcol, fld->frow); if (fld->fprot == FALSE) { reverse_video(wnd); data_value(wnd, fld); wcursor(wnd, fld->fcol, fld->frow); exitcode = read_field(wnd, fld); isvalid = (exitcode != ESC && fld->fvalid) ? (*(fld->fvalid))(fld->fbuff) : OK; } else { exitcode = FWD; isvalid = OK; } if (isvalid == OK) { normal_video(wnd); data_value(wnd, fld); switch (exitcode) { /* passed edit */ case F1: if (fld->fhelp) { (*(fld->fhelp))(fld->fbuff); data_value(wnd, fld); } break; case DN: case '\r': case '\t': case FWD: fld = fld->fnxt; if (fld == NULL) fld = FHEAD; break; case UP: case BS: fld = fld->fprv; if (fld == NULL) fld = FTAIL; break; default: done = endstroke(exitcode); break; } } } helpkey = oldhelpkey; return (exitcode); } /* --------- display a window prompt -------- */ void wprompt(WINDOW *wnd, int x, int y, char *s) { wcursor(wnd, x, y); wprintf(wnd, s); }