home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * Field editing system.
- *
- * (C) 1990 Vision Software
- *
- * $Id: field.c 1.102 91/05/04 17:19:08 pcalvin beta $
- *
- * Comments:
- *
- * This class provides EDIT with the individual field control. In the
- * future, we may be used by other classes that require formated input..
- *
- * Bugs:
- *
- * Probably, none documented.
- *
- */
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
-
- #include <stdhdr.h>
-
- #include <adl.h>
- #include <menu.h>
- #include <field.h>
-
- #include "lowlevel.h"
-
- /*
- * Title/Information field contruction..
- */
- IF::IF(WINDOW &rwndDest,ROW rowStart,COL colStart,SZ sz) : rwnd(rwndDest)
- {
- szMessage = sz;
- row = rowStart;
- col = colStart;
- }
-
- /*
- * Say the title/message field
- */
- VOID IF::SayMessage()
- {
- rwnd.SayAt(RowEdit(),ColLeft(),szMessage);
- }
-
- /*
- * Answers with the row for this field..
- */
- ROW IF::RowEdit()
- {
- return (row);
- }
-
- /*
- * Answers with left edge of this field..
- */
- COL IF::ColLeft()
- {
- return (col);
- }
-
- /*
- * Answers with the right edge of this field..
- */
- COL IF::ColRight()
- {
- return (col + strlen(szMessage));
- }
-
- /*
- * Edit field construction.
- */
- ED::ED(WINDOW &rwnd,ROW rowStart,COL colStart,SZ szMsg,SZ szDest,CCH cch,SZ szHelpInfo,CENT cent,PENT pent,CENT centDefault) : IF(rwnd,rowStart,colStart,szMsg)
- {
- Assert(szMsg != szNil);
- AssertSz(centDefault < cent,"Default for field not within range");
-
- sz = szDest;
- szHelp = szHelpInfo;
- dcol = strlen(szMsg) + 2;
- szPicture = szNil;
- chPicture = 'X';
- cchMax = cch;
- cchMac = cchNil;
- cchCurrent = cchNil;
- pfnValid = pfnNil;
- pvValid = pvNil;
- centValid = cent;
- pentValid = pent;
- szDefault = pent[centDefault].sz;
- SetUnchanged();
- SetCursor();
- fCareAboutChanges = fTrue;
- fNumeric = fFalse;
- }
-
- ED::ED(WINDOW &rwnd,ROW rowStart,COL colStart,SZ szMsg,SZ szDest,CHAR ch,CCH cch,SZ szHelpInfo,SZ szDflt) : IF(rwnd,rowStart,colStart,szMsg)
- {
- Assert(szMsg != szNil);
-
- sz = szDest;
- szHelp = szHelpInfo;
- dcol = strlen(szMsg) + 2;
- szPicture = szNil;
- chPicture = ch;
- cchMax = cch;
- cchMac = cchNil;
- cchCurrent = cchNil;
- pfnValid = pfnNil;
- pvValid = pvNil;
- centValid = centNil;
- pentValid = pentNil;
- szDefault = szDflt;
- SetUnchanged();
- SetCursor();
- fCareAboutChanges = fTrue;
- fNumeric = (ch == '9');
- }
-
- ED::ED(WINDOW &rwnd,ROW rowStart,COL colStart,SZ szMsg,SZ szDest,SZ szPic,SZ szHelpInfo,SZ szDflt) : IF(rwnd,rowStart,colStart,szMsg)
- {
- Assert(szPic != szNil);
- Assert(szMsg != szNil);
-
- sz = szDest;
- szHelp = szHelpInfo;
- szPicture = szPic;
- dcol = strlen(szMsg) + 2;
- cchMax = strlen(szPicture);
- cchMac = cchNil;
- cchCurrent = cchNil;
- pfnValid = pfnNil;
- pvValid = pvNil;
- centValid = centNil;
- pentValid = pentNil;
- szDefault = szDflt;
- SetUnchanged();
- SetCursor();
- fCareAboutChanges = fTrue;
- fNumeric = fFalse;
- }
-
- /*
- * Answers if the contents are valid given whatever validation procedure..
- */
- BOOL ED::FValidate()
- {
- BOOL fValid = fTrue;
-
- if (pentValid != pentNil && !FInRange())
- fValid = FValidateRange();
- else if (pfnValid != pfnNil)
- fValid = FValidateFunction();
-
- return (fValid);
- }
-
- /*
- * Non-standard fields may be modified after being created..
- */
- VOID ED::Adjust(PFN pfn,VOID *pv,BOOL fCareIfFieldChanges)
- {
- pfnValid = pfn;
- pvValid = pv;
- fCareAboutChanges = fCareIfFieldChanges;
- }
-
- /*
- * Replaces the current help information..
- */
- VOID ED::UpdateHelp(HELP &rhelp)
- {
- rhelp.Replace(szHelp);
- }
-
- /*
- * Checks to see if the current input is in the validation array. This
- * Array could be in any order, so a linear search is needed..
- */
- BOOL ED::FInRange()
- {
- BOOL fFound = fFalse;
- PENT pent = pentValid;
- CENT cent = centNil;
-
- /*
- * We simply traverse the array, looking for a match. To avoid
- * to many strcmp()s, it is only called if the first letter matches..
- */
- while (!fFound && cent < centValid)
- {
- if (*sz == *pent->sz && strcmp(sz,pent->sz) == 0)
- {
- fFound = fTrue;
- }
- else
- {
- cent++;
- pent++;
- }
- }
-
- return (fFound);
- }
-
- /*
- * Answers if SZ is in the given list of choices..
- * In addition, to direct the user to the correct title, that title
- * is presented here in white..
- */
- BOOL ED::FValidateRange()
- {
- ROW row = rwnd.RowQuery() + RowEdit() - 2;
- COL col = rwnd.ColQuery() + ColLeft() - 1;
- POPUP pop(row,col,centValid,pentValid);
- CENT cent = pop.CentGet();
- BOOL fSelected = fFalse;
-
- if (cent != centError)
- {
- strcpy(sz,pentValid[cent].sz);
- fChanges = fTrue;
- SayEdit(fTrue);
- fSelected = fTrue;
- }
-
- return (fSelected);
- }
-
- /*
- * Answers if SZ is legal based upon the function call..
- */
- BOOL ED::FValidateFunction()
- {
- return (pfnValid(sz,pvValid));
- }
-
- /*
- * Answers with the picture character for this position in the edit
- */
- CHAR ED::ChPicture()
- {
- if (szPicture == szNil)
- return (chPicture);
- else
- return (szPicture[cchCurrent]);
- }
-
- /*
- * Updates display for the current edit. Redraws the entire field. Also,
- * asserts the field length is set properly..
- */
- VOID ED::SayEdit(BOOL fCurrent)
- {
- CURSOR crs(fFalse);
-
- /*
- * Assert the length is setup properly
- */
- cchMac = cchNil;
-
- /*
- * Maximum current width is field width..
- */
- while (sz[cchMac] != chNil && cchMac < cchMax)
- cchMac++;
-
- /*
- * Remove/Insert leading WS depending if we are editing a numeric field.
- */
- if (fNumeric)
- {
- Verify(fCurrent ? FStripLeader() : FInsertLeader());
- }
-
- /*
- * Left Justify output within field, and determine the display colour
- */
- SZ szOutput = SzTempPaddedFromSzCch(sz,cchMax);
- CO coBack = (fCurrent) ? coGreen : coCyan;
-
- /*
- * Output..
- */
- rwnd.SayAt(RowEdit(),ColLeft(),szOutput,coBlack,coBack);
- }
-
- /*
- * Strips leading WS from the edit
- */
- BOOL ED::FStripLeader()
- {
- CCH cch = cchNil;
-
- /*
- * Search for the end..
- */
- while (cch < cchMac && sz[cch] == chSpace)
- cch++;
-
- /*
- * Now, copy over..
- */
- if (cch != cchNil && cch < cchMac)
- {
- CCH cchNewMac = cchMac - cch;
-
- memmove(&sz[cchNil],&sz[cch],cchNewMac);
- sz[cchNewMac] = chNil;
- cchMac = cchNewMac;
- }
-
- return (fTrue);
- }
-
- /*
- * Inserts leading WS into the header
- */
- BOOL ED::FInsertLeader()
- {
- if (cchMac < cchMax)
- {
- CCH cch = cchMax - cchMac;
-
- memmove(&sz[cch],&sz[cchNil],cchMac);
- memset(sz,chSpace,cch);
- }
-
- return (fTrue);
- }
-
- /*
- * Sets the cursor at the far right of the edit.
- */
- VOID ED::SetCursor()
- {
- cchCurrent = cchNil;
-
- /*
- * Maximum is field width..
- */
- while (sz[cchCurrent] != chNil && cchCurrent < cchMax)
- cchCurrent++;
- }
-
-
- /*
- * Inserts a character at the current position
- */
- BOOL ED::FInsertCd(CD cd)
- {
- Assert(cchMac <= cchMax);
-
- CHAR ch = (CHAR)cd;
-
- if (FValidChCh(ch,ChPicture()))
- {
- /*
- * Do not write past the end of the region..
- */
- if (cchCurrent >= cchMax)
- cchCurrent--;
-
- /*
- * Make room for this new character.
- */
- for (CCH cch = cchMac; cch > cchCurrent; cch--)
- {
- if (cch < cchMax)
- sz[cch] = sz[cch-1];
- }
-
- /*
- * Now, insert this character..
- */
- sz[cchCurrent] = ch;
-
- /*
- * Adjust floating length..
- */
- if (cchMac < cchMax)
- cchMac++;
-
- /*
- * Don't forget the \0 at the end if the key
- */
- if (cchMac < cchMax)
- sz[cchMac] = chNil;
-
- SayEdit(fTrue);
- fChanges = fTrue;
- CursorRight();
- }
-
- return (fTrue);
- }
-
- /*
- * Cursor manipulation functions
- * Right: Must be careful if cchMac == cchMax
- */
- VOID ED::CursorRight()
- {
- cchCurrent++;
-
- /*
- * Now, assert it is within range..
- */
- if (cchCurrent > cchMac)
- cchCurrent--;
- }
-
-
- /*
- * Left: Trivial..
- */
- VOID ED::CursorLeft()
- {
- if (cchCurrent > cchNil)
- cchCurrent--;
- }
-
-
- /*
- * Deletes the current character
- */
- BOOL ED::FDelete()
- {
- if (cchCurrent > 0)
- {
- cchCurrent -= 1;
- fChanges = fTrue;
- if (DcolOffset() != 0)
- rwnd.SetRowCol(RowEdit(),ColEdit());
-
- rwnd.PutCh(' ',coBlack,coGreen);
- }
- else if (cchMax == 1)
- {
- fChanges = fTrue;
- rwnd.PutCh(' ',coBlack,coGreen);
- }
-
- /*
- * No matter where in the edit we were, or what size the field
- * is, set that character to chNil
- */
- sz[cchCurrent] = chNil;
-
- return (fTrue);
- }
-
- /*
- * Cursor positioning. DcolOffset computes where to place the cursor.
- * Normally, this is one character ahead of the current. If we are
- * are at the limit of the field, it is simply there..
- */
- COL ED::DcolOffset()
- {
- return ((cchCurrent == cchMax) ? 0 : 1);
- }
-
- /*
- * Answers with the left edge of the (edit) field.
- */
- COL ED::ColLeft()
- {
- return (IF::ColLeft()+dcol);
- }
-
- /*
- * Answers with the current column position for this edit..
- */
- COL ED::ColEdit()
- {
- return (ColLeft()+cchCurrent-1+DcolOffset());
- }
-
- /*
- * Answers with the far right hand column for this edit..
- */
- COL ED::ColRight()
- {
- return (ColLeft()+cchMax);
- }
-
- /*
- * Forces the field to be considered unchanged
- */
- VOID ED::SetUnchanged()
- {
- fChanges = fFalse;
- }
-
- /*
- * Answers if this field has changed. Should consider if we care..
- */
- BOOL ED::FModified()
- {
- return ((fCareAboutChanges) ? fChanges : fFalse);
- }
-
- /*
- * Input validation routines. This function evalutes the picture and
- * the input character. Answers if it is legal given the input..
- * If the character is NOT valid, but MAY be mapped onto a valid
- * character, that is done and we answer fTrue.
- */
- BOOL ED::FValidChCh(CHAR &rch,CHAR chPicture)
- {
- /*
- * PICTURE Templates:
- * X- Any printable character
- * 9- Digits
- * A- Upper case letters, any other char
- * a- Lower case letters, any other char
- * U- Upper case letters only
- * L- Lower case letters only
- * N- Upper case Letters, Numbers
- * n- Lower case Letters, Numbers
- */
- switch (chPicture)
- {
- case 'X':
- return (isprint(rch));
- case '9':
- return (isdigit(rch));
- case 'A':
- return (isalpha(rch) ? isupper(rch = toupper(rch)) : isprint(rch));
- case 'a':
- return (isalpha(rch) ? islower(rch = tolower(rch)) : isprint(rch));
- case 'U':
- return (isupper(rch = toupper(rch)));
- case 'L':
- return (islower(rch = tolower(rch)));
- case 'N':
- return (isalnum(rch));
- default:
- return (fFalse);
- }
- }
-
- /*
- * Answers if the picture for the current position is "CONSTANT"
- */
- BOOL ED::FIsConstantPic()
- {
- BOOL fConstant = fTrue;
-
- switch (ChPicture())
- {
- case 'X':
- case '9':
- case 'A':
- case 'a':
- case 'U':
- case 'L':
- case 'N':
- fConstant = fFalse;
- }
-
- return (fConstant);
- }
-
- /*
- * Clear() either inserts the default value or clears the field.
- */
- VOID ED::Clear()
- {
- Assert(sz != szNil);
-
- if (szDefault != szNil)
- strcpy(sz,szDefault);
- else
- strcpy(sz,"");
- }
-
- /*
- * Displays the delimiters for this edit..
- */
- VOID ED::ShowDelimiters(CHAR chLeft,CHAR chRight)
- {
- rwnd.SetRowCol(RowEdit(),ColLeft()-1);
- rwnd.PutCh(chLeft);
- rwnd.SetRowCol(RowEdit(),ColLeft()+cchMax);
- rwnd.PutCh(chRight);
- }
-