/* SD2_FEDI.C - Screen Door II Field Edit Routines Copyright (c), 1988 By T.A. Daneliuk Last Modified: 08-11-88 These routines edit a specific field in accordance with the definitions in a structure type called SD2_FIELD. On entry, the calling routine passes a pointer to such a field. On return, SD2_NOERR is returned if the edit was successful. An error code is returned if the edit failed for some reason. This will occur under the following conditions: The pointer passed to sd2_fedit() is NULL (SD2_NULFPTR) The passed structure points to a Prompt field (SD2_ENOTRES) The the "field" structure member is NULL (SD2_EFNULL) The function will not accept any characters which do not meet the character validation conditions, and will not return until the whole field validation function passes successfully. */ #include <stdio.h> #include <string.h> #include <sd2_defs.h> #include <ctype.h> #if ANSI static BOOL end_fld(struct SD2_FIELD *x); static BOOL mask_val(struct SD2_FIELD *x, KEYSTR *y, FLEN z); #else static BOOL end_fld(); static BOOL mask_val(); #endif static BOOL firsttime; /*====================== MAIN FIELD EDITING FUNCTION =========================*/ ERRCODE sd2_fedit(fldptr, retnkey) struct SD2_FIELD *fldptr; KEYSTR *retnkey; { ERRCODE fedit_status; BOOL fediting; KEYSTR key, ktemp; BOOL fmodified; FLEN fposn, flen, rlen, temp; BOOL ins_mode; BOOL paint; BOOL get_next_key; BOOL store_key; fedit_status = SD2_NOERR; if (fldptr == NULL) /* See If Bad Pointer Passed */ fedit_status = SD2_NULFPTR; if (fldptr->ftype != FLD_RESP) /* See If Response Allowed */ fedit_status = SD2_ENOTRES; else if (fldptr->field == NULL) /* Is Response Fld. Ptr. OK? */ fedit_status = SD2_EFNULL; firsttime = TRUE; /* Setup The State Machine */ fediting = TRUE; fmodified = FALSE; fposn = 0; ins_mode = FALSE; paint = TRUE; get_next_key = TRUE; while ((fediting == TRUE) && (fedit_status == SD2_NOERR)) { if (paint == TRUE) { if ((fldptr->mask != NULL) && (fldptr->field[fposn] != '\0')) { temp = fposn; /* Make Any Case Corrections For Char. Val. */ while (fldptr->field[temp] != '\0') { mask_val(fldptr, &(fldptr->field[temp]), temp); temp++; } } sd2_fdsply(fldptr, fmodified, fposn); /* Display Updates */ } sd2_rowcol(fldptr->frow, (fldptr->fcol)+fposn); /* Position Cursor */ (ins_mode==TRUE ? sd2_cursor(CURBLK) : sd2_cursor(CURSML)); if (get_next_key == TRUE) { key = sd2_keyin(); /* Get Next Keystroke */ *retnkey = key; /* Save For Return */ } flen = strlen(fldptr->field); /* Current Field Length */ rlen = fldptr->rlen; /* Maximum Field Length */ /* Inter-Field, Exit-Field, & Exit-Screen All Force End Of Field Editing */ if ((key == NXTFLD) || (key == PRVFLD) || (key == FSTFLD) || (key == LSTFLD) || (key == EXTFLD) || (key == EXTSCR)) { if (end_fld(fldptr) == TRUE) /* All Field Validations OK */ { fediting = FALSE; /* Done With Field Editing */ fposn = 0; /* For Cosmetic Consistency */ } } else if (key == SD2_EBAD_CTRL); /* Ignore Bad Control Sequences */ else if (key == CURLFT) { if (flen > 0) /* If Nothing In Field, Can't Move*/ fposn = (fposn == 0 ? flen : --fposn); /* Wrap If Neces.*/ fposn = (fposn == rlen ? --fposn : fposn); paint = FALSE; } else if (key == CURRGT) { if (flen > 0) fposn = (fposn == flen ? 0: ++fposn); fposn = (fposn == rlen ? 0 : fposn); paint = FALSE; get_next_key = TRUE; /* We Might Just Have Put A New Char */ } else if (key == BEGFLD) { fposn = 0; paint = FALSE; } else if (key == ENDFLD) { fposn = flen; fposn = (fposn == rlen ? --fposn : fposn); paint = FALSE; } else if (key == CLRFLD) { fposn = 0; fldptr->field[0] = '\0'; paint = TRUE; fmodified = TRUE; firsttime = TRUE; /* Force Whole Field Repaint */ } else if (key == CLREND) { fldptr->field[fposn] = '\0'; paint = TRUE; fmodified = TRUE; firsttime = TRUE; } else if (key == INSERT) { if (flen < rlen) /* No Insert On Full Field */ { ins_mode = (ins_mode == TRUE ? FALSE : TRUE); paint = FALSE; } } else if (key == DELETE) { store_key = TRUE; if (fldptr->field[fposn] != '\0') { if (fldptr->mask != NULL) /* Make Sure Moving Left Is OK*/ { temp = fposn; /* Can Current Character */ ktemp = fldptr->field[temp+1];/* Legally Move Over? */ while(ktemp != '\0') /* Check All Remaining */ { store_key = store_key && mask_val(fldptr, &ktemp, temp); temp++; ktemp = fldptr->field[temp+1]; } } } if (store_key == TRUE) /* Character Validations OK */ { strcpy(&(fldptr->field[fposn]), &(fldptr->field[fposn+1])); fldptr->field[flen-1] = '\0'; fmodified = TRUE; paint = TRUE; } else if (get_next_key == FALSE) /* Were Trying To Bkspc */ fposn++; get_next_key = TRUE; /* In Case We Just Backspaced */ } else if (key == BKSPC) { if (fposn > 0) /* No Bksp. @ Fld. Beginning */ { --fposn; /* Just Backup One Position And Delete */ key = DELETE; get_next_key = FALSE; /* Inhibit Keyboard Read */ } } else if (key == HELPKEY) { if (fldptr->rhelp != NULL) /* Help Is Avail.*/ sd2_help(fldptr->rhelp); } else /* We Have A Data Keystroke */ { store_key = TRUE; /* Do Character Validations */ if ((key == ' ') && (fldptr->rspace == FALSE)) /* Spaces Allowed? */ store_key = FALSE; if (fldptr->mask != NULL) /* Do Only If Char Validations Enabled */ { store_key = store_key && mask_val(fldptr, &key, fposn); if (ins_mode == TRUE) /* Check All Subsequent If Inserting */ { if (fldptr->field[fposn] != '\0') /* Only If Not At End */ { temp = fposn; /* Can Current Character */ ktemp = fldptr->field[temp]; /* Legally Move Over? */ while(ktemp != '\0') /* Check All Remaining */ { store_key = store_key && mask_val(fldptr, &ktemp, temp+1); temp++; ktemp = fldptr->field[temp]; } } } } if (store_key == TRUE) /* Character Passed Validation */ { if (ins_mode == TRUE) { temp = flen; while(temp >= fposn) { fldptr->field[temp+1] = fldptr->field[temp]; --temp; } fldptr->field[fposn] = key; if ((flen+1) == rlen) /* Field Now Is Filled */ { ins_mode = FALSE; sd2_cursor(CURSML); } } else { if (fldptr->field[fposn] == '\0') fldptr->field[fposn+1] = '\0'; fldptr->field[fposn] = key; } key = CURRGT; /* Move Cursor Over One */ get_next_key = FALSE; /* Before Getting Next */ fmodified = TRUE; /* Keystroke */ paint = TRUE; } } } sd2_fdsply(fldptr, FALSE, fposn); return(fedit_status); } /*========================== DISPLAY A FIELD =================================*/ void sd2_fdsply(fld, modified, cposn) struct SD2_FIELD *fld; BOOL modified; FLEN cposn; { FLEN x, y; char fill[2]; sd2_cursor(CUROFF); /* Turn Off Cursor */ if (modified == FALSE) /* Use Default Colors, No Fill */ { /* Use Input Color And Fill */ x = strlen(fld->field); fill[0] = fld->rclear; fill[1] = '\0'; sd2_rowcol(fld->frow, (fld->fcol)+cposn); /* Position Cursor */ sd2_aputs(&(fld->field[cposn]), fld->fattrib); /* Display String */ while (x < fld->rlen) { sd2_rowcol(fld->frow, (fld->fcol)+x); /* Clear Any Fill Chars. */ sd2_aputs(fill, fld->cattrib); x++; } } else { /* Use Input Color And Fill */ y = x = strlen(fld->field); fill[0] = fld->rfill; fill[1] = '\0'; if (firsttime == TRUE) /* First Time Display Whole Field */ { firsttime = FALSE; cposn = 0; } else /* At Most, Only Need 1 Fill Char */ y = (y == fld->rlen ? y : (fld->rlen) - 1); sd2_rowcol(fld->frow, (fld->fcol)+cposn); /* Position Cursor */ sd2_aputs(&(fld->field[cposn]), fld->rattrib); /* Display String */ while (y < fld->rlen) /* Have To Add A Fill Char */ { sd2_rowcol(fld->frow, (fld->fcol)+x); /* Then Fill Chars. */ sd2_aputs(fill, fld->rattrib); ++y; ++x; } } } /*======================= END FIELD PROCESSING ===============================*/ static BOOL end_fld(fld) /* Does Whole Fld, RReq, User Validation, etc. */ struct SD2_FIELD *fld; /* Returns True If All OK, False If Not */ { ERRCODE status; char *errmsg; static char mfill[] = "This Field Must Be Filled!"; static char rreqd[] = "This Field Requires A Response!"; status = SD2_NOERR; if ((fld->rmustfill == TRUE) && (strlen(fld->field) != fld->rlen)) { status = SD2_MUSTFIL; errmsg = mfill; } else if ((fld->rreqd == TRUE) && (fld->field[0] == '\0')) { status = SD2_RESREQD; errmsg = rreqd; } else if (fld->rvalid != NULL) { errmsg = (*(fld->rvalid)) (fld); if (errmsg != NULL) status = SD2_IEUVALID; } if ((status != SD2_NOERR) && (fld->flderr != NULL)) (*(fld->flderr)) (fld, status, errmsg); if (status != SD2_NOERR) return(FALSE); else return(TRUE); } /*============== CHECK A CHARACTER AGAINST THE MASK CONDITION ================*/ static BOOL mask_val(fldptr, key, fposn) /* Returns TRUE If All OK */ struct SD2_FIELD *fldptr; KEYSTR *key; FLEN fposn; { BOOL store_key, btemp; FLEN temp, temp1; KEYSTR ktemp; store_key = TRUE; switch(fldptr->mask[fposn]) /* Check For Relevant Validation */ { case SD2_LITERAL_N: case SD2_LITERAL_L: case SD2_LITERAL_U: switch (fldptr->mask[fposn]) { case SD2_LITERAL_N: /* No Case Conversion */ break; /* Do Nothing */ case SD2_LITERAL_L: *key = tolower(*key); break; case SD2_LITERAL_U: *key = toupper(*key); break; } break; case SD2_ALPHA_N: case SD2_ALPHA_L: case SD2_ALPHA_U: if (isalpha(*key)) { switch (fldptr->mask[fposn]) { case SD2_ALPHA_N: break; case SD2_ALPHA_L: *key = tolower(*key); break; case SD2_ALPHA_U: *key = toupper(*key); break; } } else store_key = FALSE; break; case SD2_ALPHANUM_N: case SD2_ALPHANUM_L: case SD2_ALPHANUM_U: if (isalnum(*key)) { switch (fldptr->mask[fposn]) { case SD2_ALPHANUM_N: break; case SD2_ALPHANUM_L: *key = tolower(*key); break; case SD2_ALPHANUM_U: *key = toupper(*key); break; } } else store_key = FALSE; break; case SD2_BINARY: if (*key != '0' && *key != '1') store_key = FALSE; break; case SD2_OCTAL: if (!isdigit(*key) || (*key > '7')) store_key = FALSE; break; case SD2_DECIMAL: if (!isdigit(*key)) store_key = FALSE; break; case SD2_HEX_N: case SD2_HEX_L: case SD2_HEX_U: if (!isxdigit(*key)) store_key = FALSE; else switch (fldptr->mask[fposn]) { case SD2_HEX_N: break; case SD2_HEX_L: *key = tolower(*key); break; case SD2_HEX_U: *key = toupper(*key); break; } break; case SD2_FLOATING: if (!isdigit(*key) && (*key != '+') && (*key != '-') && (*key != '.')) store_key = FALSE; break; case SD2_SCIENT_N: case SD2_SCIENT_L: case SD2_SCIENT_U: if (!isdigit(*key) && (*key != '+') && (*key != '-') && (*key != '.') && (*key != 'e') && (*key != 'E')) store_key = FALSE; else switch (fldptr->mask[fposn]) { case SD2_SCIENT_N: break; case SD2_SCIENT_L: *key = tolower(*key); break; case SD2_SCIENT_U: *key = toupper(*key); break; } break; case SD2_FINANCIAL: if (!isdigit(*key) && (*key != '+') && (*key != '-') && (*key != '.') && (*key != '$')) store_key = FALSE; break; case SD2_YN_N: case SD2_YN_L: case SD2_YN_U: if ((toupper(*key) != 'Y') && (toupper(*key) != 'N')) store_key = FALSE; else switch (fldptr->mask[fposn]) { case SD2_YN_N: break; case SD2_YN_L: *key = tolower(*key); break; case SD2_YN_U: *key = toupper(*key); break; } break; case SD2_LIST0: case SD2_LIST1: case SD2_LIST2: case SD2_LIST3: case SD2_LIST4: case SD2_LIST5: case SD2_LIST6: case SD2_LIST7: case SD2_LIST8: case SD2_LIST9: if (fldptr->v_lists != NULL) /* Only If Enabled */ { temp = (fldptr->mask[fposn]) - '0'; /* Only Works In ASCII*/ if (fldptr->v_lists[temp] != NULL) { btemp = FALSE; /* Scan Literal List And Look */ temp1 = 0; /* For Matching Character */ ktemp = 'x'; /* Dummy So While Below Works */ while ((btemp == FALSE) && (ktemp != '\0')) { ktemp = fldptr->v_lists[temp][temp1]; if (*key == ktemp) btemp = TRUE; ++temp1; } store_key = store_key && btemp; } } break; default: /* Invalid Validation Code, Ignore *key */ store_key = FALSE; break; } return(store_key); }