/* OpenDoors Online Software Programming Toolkit * (C) Copyright 1991 - 1999 by Brian Pirie. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * File: ODEdStr.c * * Description: Implementation of od_edit_str(). This is the advanced line * editing function which requires ANSI or AVATAR graphics. * * Revisions: Date Ver Who Change * --------------------------------------------------------------- * Oct 13, 1994 6.00 BP New file header format. * Dec 09, 1994 6.00 BP Standardized coding style. * Dec 31, 1994 6.00 BP Use ODTimerSleep() instead of loop. * Aug 19, 1995 6.00 BP 32-bit portability. * Nov 11, 1995 6.00 BP Removed register keyword. * Nov 16, 1995 6.00 BP Removed oddoor.h, added odcore.h. * Nov 17, 1995 6.00 BP Use new input queue mechanism. * Dec 12, 1995 6.00 BP Added entry, exit and kernel macros. * Dec 23, 1995 6.00 BP Added EDIT_FLAG_SHOW_SIZE. * Dec 30, 1995 6.00 BP Added ODCALL for calling convention. * Jan 04, 1996 6.00 BP Use od_get_input(). * Jan 12, 1996 6.00 BP Claim exclusive use of arrow keys. * Jan 31, 1996 6.00 BP Added timeout for od_get_input(). * Feb 10, 1996 6.00 BP Fixed ...SHOW_SIZE /w ...PERMALITERAL. * Feb 13, 1996 6.00 BP Added od_get_input() flags parameter. * Feb 19, 1996 6.00 BP Changed version number to 6.00. * Mar 03, 1996 6.10 BP Begin version 6.10. * Apr 08, 1996 6.10 BP Make 'C' use word capitalization. * Aug 10, 2003 6.23 SH *nix support */ #define BUILDING_OPENDOORS #include #include #include #include "OpenDoor.h" #include "ODCore.h" #include "ODGen.h" #include "ODPlat.h" #include "ODKrnl.h" #include "ODStat.h" /* Current od_edit_str() state and settings. */ static INT anCurrentFormatOffset[80]; static BOOL abCurrentFormatLiteral[80]; static char szCurrentOriginalString[81]; static char *pszCurrentInput; static char *pszCurrentFormat; static unsigned char nCurrentStringLength; static char chCurrentBlank; /* Private helper functions used by od_edit_str(). */ static BOOL ODEditIsCharValidForPos(char chEntered, INT nPosition); static char ODEditAsCharForPos(char chEntered, INT nPosition); static void ODEditDisplayPermaliteral(WORD nFlags); /* ---------------------------------------------------------------------------- * od_edit_str() * * Provides more advanced editing capabilities than od_get_str(), requiring * ANSI, AVATAR or RIP modes. * * Parameters: pszInput - Pointer to string where inputted text is * stored. * * pszFormat - Pointer to format string, which specifies * the format of inputted text. * * nRow - The row number where the input field should * begin. * * nColumn - The column number where the input field * should begin. * * btNormalColour - Color of normal text. * * btHighlightColour - Color of highlighted text. * * chBlank - Character to display blanks with. * * nFlags - Specifies one or more flags, combined with * the bitwise-or operator. * * Return: One of a number of possible EDIT_RETURN_ values, which indicate * why the function returned. */ ODAPIDEF WORD ODCALL od_edit_str(char *pszInput, char *pszFormat, INT nRow, INT nColumn, BYTE btNormalColour, BYTE btHighlightColour, char chBlank, WORD nFlags) { char chTemp; unsigned int nCount; unsigned char chCurrentValue; char *pchCurrent; unsigned int nCursorPos; INT nKeysPressed = 0; WORD wToReturn; BOOL bInsertMode = TRUE; char chAddAtEnd = '\0'; BOOL bNormal = TRUE; tODInputEvent InputEvent; /* Log function entry if running in trace mode */ TRACE(TRACE_API, "od_edit_str()"); /* Verify that OpenDoors has been initialized. */ if(!bODInitialized) od_init(); OD_API_ENTRY(); /* Store pointers to current input string and current format string. */ pszCurrentInput=(char *)pszInput; pszCurrentFormat=(char *)pszFormat; /* Check that the parameters passed in are valid. */ if(pszCurrentInput == NULL || pszCurrentFormat == NULL || nRow < 1 || nColumn < 1) { od_control.od_error = ERR_PARAMETER; OD_API_EXIT(); return(EDIT_RETURN_ERROR); } /* Initially, the maximum length of input string is 0. */ nCurrentStringLength = 0; /* The type that is being examined. */ chCurrentValue = 0; /* Counter of position in format string. */ nCount = 0; /* Loop until we reach the end fo the format string. */ for(pchCurrent = pszCurrentFormat; *pchCurrent;) { /* Get next character from format string. */ chTemp = *pchCurrent++; /* If current character is not a literal value. */ if(chCurrentValue == '\0') { /* If format string has " or ' characters, then this is the */ /* beginning of a literal string. */ if(chTemp == 39 || chTemp == 34) { chCurrentValue = chTemp; } /* If this is not a literal character, and not a space character... */ else if(chTemp != 32) { /* Check that we haven't exceeded the maximum allowable string */ /* length. */ if(nCurrentStringLength >= 80) { od_control.od_error = ERR_PARAMETER; OD_API_EXIT(); return(EDIT_RETURN_ERROR); } /* Record format character's position. */ anCurrentFormatOffset[nCurrentStringLength] = nCount; /* Record that this character is not a literal. */ abCurrentFormatLiteral[nCurrentStringLength] = FALSE; /* Increment length of input string. */ ++nCurrentStringLength; } } /* If this is a literal character. */ else { /* Check for end of literal string. */ if(chTemp == chCurrentValue) { /* If found, stop literal string processing */ chCurrentValue = '\0'; } else { /* Check that we haven't exceeded the maximum allowable string */ /* length. */ if(nCurrentStringLength >= 80) { od_control.od_error = ERR_PARAMETER; OD_API_EXIT(); return(EDIT_RETURN_ERROR); } /* Record character's position. */ anCurrentFormatOffset[nCurrentStringLength] = nCount; /* Record that character IS a literal value. */ abCurrentFormatLiteral[nCurrentStringLength] = TRUE; /* Increment length of input string. */ ++nCurrentStringLength; } } /* Increment format string position. */ ++nCount; } /* Check that there is at least one character permitted in the input */ /* string. If not, return with a parameter error. */ if(nCurrentStringLength==0) { od_control.od_error = ERR_PARAMETER; OD_API_EXIT(); return(EDIT_RETURN_ERROR); } /* If editing an existing string. */ if(nFlags & EDIT_FLAG_EDIT_STRING) { /* Check for valid existing input string. */ if(strlen(pszCurrentInput) > nCurrentStringLength) { pszCurrentInput[nCurrentStringLength] = '\0'; } /* Start with cursor at the end of the string. */ nCursorPos = strlen(pszCurrentInput); } /* If we are not editing an existing string. */ else { /* Blank-out current string contents. */ pszCurrentInput[0] = '\0'; /* Set cursor to beginning of string. */ nCursorPos = 0; } /* Store original string, in case user cancels. */ strcpy(szCurrentOriginalString,pszCurrentInput); /* Set appropriate text color. */ od_set_attrib(btHighlightColour); /* Determine appropriate blank character */ chCurrentBlank = (nFlags & EDIT_FLAG_PASSWORD_MODE) ? ' ' : chBlank; /* Turn off insert mode if the strict input or permaliteral flags were */ /* specified. */ if((nFlags & EDIT_FLAG_STRICT_INPUT) || (nFlags & EDIT_FLAG_PERMALITERAL)) { bInsertMode = FALSE; } /* If the no-initial-redraw flag is not set, then do initial redraw. */ if(!(nFlags & EDIT_FLAG_NO_REDRAW)) { /* Set to redraw position. */ od_set_cursor(nRow, nColumn); if(nFlags & EDIT_FLAG_PASSWORD_MODE) { /* If we are in password mode, then just draw password blanks. */ od_repeat(chBlank, (BYTE)strlen(pszCurrentInput)); } else { /* Otherwise, display the actual string. */ od_disp_str(pszCurrentInput); } if(nFlags & EDIT_FLAG_PERMALITERAL) { /* If we are in permaliteral mode, then fill the remaining edit */ /* field with the literal characters. */ ODEditDisplayPermaliteral(nFlags); } else { /* Otherwise, fill the remaining edit field with the blank */ /* character. */ BYTE btRemaining = (BYTE)(nCurrentStringLength - strlen(pszCurrentInput)); if(!(nFlags & EDIT_FLAG_SHOW_SIZE)) ++btRemaining; od_repeat(chCurrentBlank, btRemaining); } } /* Claim exclusive use of arrow keys. */ ODStatStartArrowUse(); /* Set the cursor to appropriate position. */ od_set_cursor(nRow, nColumn + nCursorPos); /* Normally, we start the input loop at the keep_going tag. */ if(bNormal) goto keep_going; for(;;) { /* If auto-accept mode has been specified ... */ if(nFlags & EDIT_FLAG_AUTO_ENTER) { /* ... then check whether we have reached the end of the string. */ if(strlen(pszCurrentInput) == nCurrentStringLength) { /* Indicate that input has been accepted, rather than cancelled. */ wToReturn = EDIT_RETURN_ACCEPT; /* Return the current string to the caller, if it is valid. */ goto try_to_accept; } } keep_going: /* Check whether we have reached a literal character in permaliteral */ /* mode. If so, we will move past the permanent literal characters */ /* automatically. */ if((nFlags & EDIT_FLAG_PERMALITERAL) && (nCursorPos < nCurrentStringLength)) { if(abCurrentFormatLiteral[nCursorPos]) { if(nCursorPos < strlen(pszCurrentInput)) { goto pressed_right_arrow; } chTemp = pszCurrentFormat[anCurrentFormatOffset[nCursorPos]]; ++nKeysPressed; goto try_this_character; } } get_another_key: /* Block, waiting for the next key pressed by the user. */ od_get_input(&InputEvent, OD_NO_TIMEOUT, GETIN_NORMAL); /* Increment total number of keystrokes. */ ++nKeysPressed; if(InputEvent.EventType == EVENT_EXTENDED_KEY) { switch(InputEvent.chKeyPress) { case OD_KEY_UP: case OD_KEY_SHIFTTAB: if(nFlags & EDIT_FLAG_FIELD_MODE) { wToReturn = EDIT_RETURN_PREVIOUS; goto try_to_accept; } break; case OD_KEY_DOWN: pressed_down_arrow: if(nFlags & EDIT_FLAG_FIELD_MODE) { wToReturn = EDIT_RETURN_NEXT; goto try_to_accept; } break; case OD_KEY_RIGHT: pressed_right_arrow: /* If we are not at the end of the string. */ if(nCursorPos < strlen(pszCurrentInput)) { /* Move input position right. */ nCursorPos++; /* Move the cursor on screen. */ od_set_cursor(nRow, nColumn + nCursorPos); } if(chAddAtEnd) { chAddAtEnd = 0; goto add_another_key; } break; case OD_KEY_LEFT: pressed_left_arrow: /* If we are not at the beginning of the string. */ if(nCursorPos > 0) { /* Move input position left. */ nCursorPos--; /* Move cursor on screen. */ od_set_cursor(nRow, nColumn + nCursorPos); } /* If we are moving past a permanent literal character, */ /* then continue moving further left, if possible. */ if((nFlags & EDIT_FLAG_PERMALITERAL) && abCurrentFormatLiteral[nCursorPos] && nCursorPos > 0) { goto pressed_left_arrow; } break; case OD_KEY_HOME: /* If we are not at the beginning of the string. */ if(nCursorPos != 0) { /* Move input position to the beginning of the string. */ nCursorPos = 0; /* Move the cursor on the screen. */ od_set_cursor(nRow, nColumn); } break; case OD_KEY_END: /* If we are not at the end of the string .*/ if(nCursorPos != strlen(pszCurrentInput)) { /* Set the input position to the end of the string. */ nCursorPos=strlen(pszCurrentInput); /* Move cursor on screen. */ od_set_cursor(nRow,nColumn+nCursorPos); } break; case OD_KEY_DELETE: pressed_delete: /* Check whether delete key is permitted at this time. */ if(!(nFlags & EDIT_FLAG_STRICT_INPUT) && nCursorPos < strlen(pszCurrentInput) && !(nFlags & EDIT_FLAG_PERMALITERAL)) { /* Move remaining line, if any, to the left */ chCurrentValue = strlen(pszCurrentInput) - 1; for(nCount = nCursorPos; nCount < chCurrentValue; ++nCount) { od_putch( pszCurrentInput[nCount] = pszCurrentInput[nCount + 1]); } /* Erase the last character. */ pszCurrentInput[chCurrentValue] = '\0'; /* Blank out last character. */ od_putch(chCurrentBlank); /* Move the cursor on the screen. */ od_set_cursor(nRow, nColumn + nCursorPos); /* Update changes to string. */ goto check_cursor_char; } break; case OD_KEY_INSERT: if(!(nFlags & EDIT_FLAG_STRICT_INPUT) && !(nFlags & EDIT_FLAG_PERMALITERAL)) { /* Toggle insert setting. */ bInsertMode = !bInsertMode; } break; } } else if(InputEvent.EventType == EVENT_CHARACTER) { chTemp = InputEvent.chKeyPress; try_this_character: if(chTemp == 27) { /* If cancel key is allowed ... */ if(nFlags & EDIT_FLAG_ALLOW_CANCEL) { /* Reset the input string to the original contents. */ strcpy(pszCurrentInput, szCurrentOriginalString); /* Indicate that return reason was due to user cancelling. */ wToReturn = EDIT_RETURN_CANCEL; /* Return after redrawing the original string in the input */ /* field. */ goto exit_and_redraw; } } /* If user pressed [Enter] or [Ctrl]-[Z]. */ else if(chTemp == 13 || chTemp == 26) { /* User has accepted input. */ wToReturn = EDIT_RETURN_ACCEPT; /* Return if input string is valid. */ goto try_to_accept; } /* If the backspace key has been pressed. */ else if(chTemp == 8) { backspace_again: /* If we are not already at the beginning of the string. */ if(nCursorPos > 0) { if(nFlags & EDIT_FLAG_PERMALITERAL) { for(nCount = 0;nCount < nCursorPos; ++nCount) { if(!abCurrentFormatLiteral[nCount]) goto continue_deletion; } goto get_another_key; } continue_deletion: /* If we are at the end of the string. */ if(nCursorPos == strlen(pszCurrentInput)) { /* Erase last char in string. */ pszCurrentInput[--nCursorPos] = '\0'; if((nFlags & EDIT_FLAG_PERMALITERAL) && abCurrentFormatLiteral[nCursorPos]) { goto backspace_again; } else { /* Move to new cursor pos. */ od_set_cursor(nRow,nColumn+nCursorPos); /* Blank old character. */ od_putch(chCurrentBlank); /* Move again to cursor pos. */ od_set_cursor(nRow,nColumn+nCursorPos); } } /* If we are in the middle of the string and we are not in */ /* string input mode. */ else if(!(nFlags & EDIT_FLAG_STRICT_INPUT) && !(nFlags & EDIT_FLAG_PERMALITERAL)) { /* Move cursor left. */ --nCursorPos; /* Move cursor on screen. */ od_set_cursor(nRow, nColumn + nCursorPos); /* Goto standard delete handler. */ goto pressed_delete; } } } /* If this is a next field request. */ else if(chTemp == 9) { /* Goto down arrow handler. */ goto pressed_down_arrow; } /* If Control-Y. */ else if(chTemp == 25) { /* Erase entire contents of line. */ goto kill_whole_line; } else { /* If this is the first key pressed, and we are in autodelete mode. */ if(nKeysPressed == 1 && (nFlags & EDIT_FLAG_AUTO_DELETE)) { kill_whole_line: /* If string is not empty. */ if(strlen(pszCurrentInput) != 0) { /* Move to beginning of string. */ od_set_cursor(nRow,nColumn); /* Blank out the entire string contents. */ od_repeat(chCurrentBlank, (BYTE)strlen(pszCurrentInput)); } /* Move to new cursor position. */ od_set_cursor(nRow,nColumn); /* Update insert position. */ nCursorPos = 0; /* Blank out the current string contents. */ pszCurrentInput[0] = '\0'; } add_another_key: if(!ODEditIsCharValidForPos(chTemp,nCursorPos)) { /* If character is not a valid input char. */ if(abCurrentFormatLiteral[nCursorPos]) { if(nCursorPos < strlen(pszCurrentInput)) { if(pszCurrentInput[nCursorPos] == pszCurrentFormat[anCurrentFormatOffset[nCursorPos]]) { chAddAtEnd = chTemp; goto pressed_right_arrow; } } chAddAtEnd = chTemp; chTemp = pszCurrentFormat[anCurrentFormatOffset[nCursorPos]]; } else { continue; } } /* Convert character to correct value, if applicable. */ chTemp = ODEditAsCharForPos(chTemp, nCursorPos); /* If we are at end of string. */ if(nCursorPos >= strlen(pszCurrentInput)) { /* Reset original cursor position */ nCursorPos = strlen(pszCurrentInput); /* If there is room to add a char. */ if(nCursorPos < nCurrentStringLength) { /* If password mode */ if(nFlags & EDIT_FLAG_PASSWORD_MODE) { /* Display the password character. */ od_putch(chBlank); } /* If not in password mode. */ else { /* Display the character. */ od_putch(chTemp); } /* Store the character. */ pszCurrentInput[nCursorPos] = chTemp; /* Add a new string terminator. */ pszCurrentInput[++nCursorPos] = '\0'; } } /* If in insert mode, but not at end of string. */ else if(bInsertMode) { /* If room in string. */ if(strlen(pszCurrentInput) < nCurrentStringLength) { /* If in password mode. */ if(nFlags & EDIT_FLAG_PASSWORD_MODE) { /* Move to end. */ od_set_cursor(nRow,nColumn+strlen(pszCurrentInput)); /* Add another password character. */ od_putch(chBlank); } /* If not in password mode. */ else { /* Display the new character. */ od_putch(chTemp); /* Loop through rest of string. */ for(nCount = nCursorPos; nCount < strlen(pszCurrentInput); ++nCount) { /* Display the next remaining character. */ od_putch(pszCurrentInput[nCount]); } } pszCurrentInput[(strlen(pszCurrentInput) + 1)] = '\0'; /* Sift remaining characters forward. */ for(nCount = strlen(pszCurrentInput); nCount > nCursorPos; --nCount) { pszCurrentInput[nCount] = pszCurrentInput[nCount-1]; } /* Add new char in space. */ pszCurrentInput[nCursorPos++] = chTemp; /* Move to new cursor position. */ od_set_cursor(nRow, nColumn + nCursorPos); } else { goto get_another_key; } } /* If we are in overwrite mode, but not at end of string. */ else { /* If password mode. */ if(nFlags & EDIT_FLAG_PASSWORD_MODE) { /* Display the password character. */ od_putch(chBlank); } /* If not in password mode. */ else { /* Display the character. */ od_putch(chTemp); } /* Add character to string. */ pszCurrentInput[nCursorPos++] = chTemp; } /* If not at end of possible string. */ if(nCursorPos < nCurrentStringLength) { /* If the next character is literal constant. */ if(abCurrentFormatLiteral[nCursorPos]) { chTemp = pszCurrentFormat[anCurrentFormatOffset[nCursorPos]]; goto add_another_key; } } if(chAddAtEnd) { chTemp = chAddAtEnd; chAddAtEnd = 0; goto add_another_key; } check_cursor_char: /* If there is a character under cursor. */ if(nCursorPos < strlen(pszCurrentInput)) { /* If character corresponds to the format string. */ if(ODEditIsCharValidForPos(pszCurrentInput[nCursorPos], nCursorPos)) { /* Determine correct character for this position. */ chTemp = ODEditAsCharForPos(pszCurrentInput[nCursorPos], nCursorPos); /* If actual character is not correct. */ if(chTemp != pszCurrentInput[nCursorPos]) { /* Change character to correct value. */ pszCurrentInput[nCursorPos] = chTemp; /* If password mode. */ if(nFlags & EDIT_FLAG_PASSWORD_MODE) { /* Display the password character. */ od_putch(chBlank); } /* If not in password mode. */ else { /* Display the character. */ od_putch(chTemp); } /* Reset cursor position. */ od_set_cursor(nRow, nColumn + nCursorPos); } } } } } } /* Accept string if it is valid. */ try_to_accept: /* If string must be filled. */ if(nFlags & EDIT_FLAG_FILL_STRING) { /* If string is not filled, don't return. */ if(strlen(pszCurrentInput) != nCurrentStringLength) goto keep_going; } /* Loop through string .... */ for(nCount = 0; nCount < strlen(pszCurrentInput); ++nCount) { /* ... testing each character for validity. */ if(!ODEditIsCharValidForPos(pszCurrentInput[nCount], nCount)) goto keep_going; } /* Initially, assume that the string has not been changed. */ chCurrentValue = FALSE; /* Loop through the string. */ for(nCount = 0; nCount < strlen(pszCurrentInput); ++nCount) { /* Find correct value for each character. */ chTemp = ODEditAsCharForPos(pszCurrentInput[nCount], nCount); /* If character is not correct. */ if(chTemp != pszCurrentInput[nCount]) { /* Change char to correct value */ pszCurrentInput[nCount] = chTemp; /* Remember that string has been changed. */ chCurrentValue = TRUE; } } /* If permaliteral mode. */ if(nFlags & EDIT_FLAG_LEAVE_BLANK) { /* Count # of literal characters. */ nCount = 0; while(nCount 0) { /* Then they shouldn't be here. */ pszCurrentInput[0] = '\0'; goto exit_and_redraw; } } /* Always redraw if string was changed. */ if(chCurrentValue) goto exit_and_redraw; /* If no-redraw flag not set. */ if(!(nFlags & EDIT_FLAG_NO_REDRAW)) { exit_and_redraw: /* Set appropriate text colour. */ od_set_attrib(btNormalColour); /* Set to redraw position. */ od_set_cursor(nRow,nColumn); /* If password mode. */ if(nFlags & EDIT_FLAG_PASSWORD_MODE) { /* Display blanked-out string. */ od_repeat(chBlank, (BYTE)strlen(pszCurrentInput)); } else { /* Display actual string. */ od_disp_str(pszCurrentInput); } /* If we should keep the background. */ if(nFlags & EDIT_FLAG_KEEP_BLANK) { /* Then redraw background. */ if(nFlags & EDIT_FLAG_PERMALITERAL) { ODEditDisplayPermaliteral(nFlags); } else { od_repeat(chCurrentBlank, (BYTE)(nCurrentStringLength - strlen(pszCurrentInput) + 1)); } } /* If we should erase the background ... */ else { /* ... then do it. */ od_repeat(' ', (BYTE)(nCurrentStringLength - strlen(pszCurrentInput) + 1)); } } /* Release exclusive use of arrow keys. */ ODStatEndArrowUse(); /* Return with appropriate return value. */ OD_API_EXIT(); return(wToReturn); } /* ---------------------------------------------------------------------------- * ODEditIsCharValidForPos() *** PRIVATE FUNCTION *** * * Determines whether or not the entered character can be accepted as a valid * character (after any possible conversion by ODEditAsCharForPos() is applied) * for the specified position in the string. * * Parameters: chEntered - The character entered by the user. * * nPosition - The position in the string where this character * would be inserted. * * Return: TRUE if this character should be accepted, FALSE if not. */ static BOOL ODEditIsCharValidForPos(char chEntered, INT nPosition) { /* If this character is a literal. */ if(abCurrentFormatLiteral[nPosition]) { /* Check required literal character. */ if(chEntered != pszCurrentFormat[anCurrentFormatOffset[nPosition]]) { /* If this is not the correct literal character, then do not */ /* permit it to be entered in this position. */ return(FALSE); } return(TRUE); } /* If this position has a corresponding format control character, */ /* then check that control character. The execution path will */ /* continue out of this switch statement (rather than returning */ /* to the calling function) if and only if the entered character */ /* is valid for the format character specified. */ switch(pszCurrentFormat[anCurrentFormatOffset[nPosition]]) { /* Only numerical characters are to be permitted. */ case '#': if(chEntered < '0' || chEntered > '9') return(FALSE); break; /* Only numerical and space characters are to be permitted. */ case '%': if((chEntered < '0' || chEntered > '9') && chEntered != ' ') { return(FALSE); } break; /* Only floating point number characters are to be permitted. */ case '9': if(chEntered >= '0' && chEntered <= '9') break; if(chEntered == '.' || chEntered == '+' || chEntered == '-') break; return(FALSE); /* Only "printable" characters are to be permitted. */ case '*': if(chEntered < 32) return(FALSE); break; /* City name characters are to be permitted. */ case 'C': case 'c': if(chEntered >= 'A' && chEntered <= 'Z') break; if(chEntered >= 'a' && chEntered <= 'z') break; if(chEntered == ' ' || chEntered == ',' || chEntered == '.') break; if(chEntered == '*' || chEntered == '?') break; return(FALSE); /* If only alphabetic characters are to be permitted. */ case 'A': case 'a': case 'L': case 'l': case 'M': case 'm': case 'U': case 'u': if(chEntered>='A' && chEntered<='Z') break; if(chEntered>='a' && chEntered<='z') break; if(chEntered==' ') break; return(FALSE); /* If only date characters are to be permitted. */ case 'D': case 'd': if(chEntered>='0' && chEntered<='9') break; if(chEntered=='-' || chEntered=='/') break; return(FALSE); /* If only MS-DOS filename characters are to be permitted. */ case 'F': case 'f': if(chEntered >= 'A' && chEntered <= 'Z') break; if(chEntered >= '0' && chEntered <= '9') break; if(chEntered >= 'a' && chEntered <= 'z') break; switch(chEntered) { /* Filename separators. */ case ':': case '.': case DIRSEP: /* Wildcard characters. */ case '?': case '*': /* Other valid symbols in filenames */ case '#': case '$': case '&': case '\'': case '(': case '>': case '-': case '@': case '_': case '!': case '{': case '}': case '~': return(TRUE); } return(FALSE); /* If only hexidecimal characters are to be permitted. */ case 'H': case 'h': if(chEntered>='0' && chEntered<='9') break; if(chEntered>='A' && chEntered<='F') break; if(chEntered>='a' && chEntered<='f') break; return(FALSE); /* If only telephone number characters are to be permitted. */ case 'T': case 't': if(chEntered >= '0' && chEntered <= '9') break; if(chEntered == '-' || chEntered == '(' || chEntered == ')' || chEntered == ' ' || chEntered == '+') { break; } return(FALSE); /* If filenames with wildcards are to be permitted. */ case 'W': case 'w': if(chEntered >= 'A' && chEntered <= 'Z') break; if(chEntered >= 'a' && chEntered <= 'z') break; if(chEntered == ':' || chEntered == '.' || chEntered == DIRSEP || chEntered == '*' || chEntered == '?') { break; } return(FALSE); /* If alpha-numeric characters are to be permitted. */ case 'X': case 'x': if(chEntered >= 'A' && chEntered <= 'Z') break; if(chEntered >= 'a' && chEntered <= 'z') break; if(chEntered >= '0' && chEntered <= '9') break; if(chEntered == ' ') break; return(FALSE); /* If this is a Yes/No field. */ case 'Y': case 'y': if(chEntered == 'y' || chEntered == 'n' || chEntered == 'Y' || chEntered == 'N') { break; } return(FALSE); } /* If execution gets to this point, then the character has been approved. */ return(TRUE); } /* ---------------------------------------------------------------------------- * ODEditAsCharForPos() *** PRIVATE FUNCTION *** * * Converts the character entered by the user to a valid character for this * position in the string. For example, for fields that are set to all * upper case, this function converts the entered characte to its upper case * equivalent. * * Parameters: chEntered - Character that was entered by the user. * * nPosition - Position in the string where the character is to * be entered. * * Return: The actual character to add to the input string at this * position. */ static char ODEditAsCharForPos(char chEntered, INT nPosition) { /* If this character is a literal. */ if(abCurrentFormatLiteral[nPosition]) { /* Return the only valid char for this position. */ return(pszCurrentFormat[anCurrentFormatOffset[nPosition]]); } /* If this position has a corresponding format control character, */ /* then check that control character. */ switch(pszCurrentFormat[anCurrentFormatOffset[nPosition]]) { /* If Yes/No characters are required. */ case 'Y': case 'y': return(toupper(chEntered)); /* If filename characters are required. */ case 'F': case 'f': return(toupper(chEntered)); /* If lower case characters are required. */ case 'L': case 'l': return(tolower(chEntered)); /* If upper case characters are required. */ case 'U': case 'u': return(toupper(chEntered)); /* If automatic capitalization is required. */ case 'M': case 'm': case 'C': case 'c': /* First character is always upper case. */ if(nPosition == 0) return(toupper(chEntered)); /* Check for other base cases. */ if(abCurrentFormatLiteral[nPosition-1]) return(toupper(chEntered)); if(toupper(pszCurrentFormat[anCurrentFormatOffset[nPosition]]) != 'M' && toupper(pszCurrentFormat[anCurrentFormatOffset[nPosition]]) != 'C') { return(toupper(chEntered)); } /* If previous character is a word delimiter, then this character */ /* should be uppper case. */ if(pszCurrentInput[nPosition-1] == ' ' || pszCurrentInput[nPosition-1] == '.' || pszCurrentInput[nPosition-1] == ',' || pszCurrentInput[nPosition-1] == '-') { return(toupper(chEntered)); /* Otherwise, this should be lower */ } /* Otherwise, this character should be lower-case. */ return(tolower(chEntered)); } return(chEntered); } /* ---------------------------------------------------------------------------- * ODEditDisplayPermaliteral() *** PRIVATE FUNCTION *** * * Displays permaliterals (characters specified in the format string that * should be returned in the input string, but which the user may never * change). * * Parameters: nFlags - Flags parameter that was passed into od_edit_str(). * * Return: void */ static void ODEditDisplayPermaliteral(WORD nFlags) { INT nCount; BYTE btRepeat = 0; for(nCount = strlen(pszCurrentInput); nCount <= nCurrentStringLength; ++nCount) { if(nCount != nCurrentStringLength) { if(abCurrentFormatLiteral[nCount]) { if(btRepeat > 0) { od_repeat(chCurrentBlank, btRepeat); btRepeat = 0; } od_putch(pszCurrentFormat[anCurrentFormatOffset[nCount]]); } else { ++btRepeat; } } else { if(!(nFlags & EDIT_FLAG_SHOW_SIZE)) { ++btRepeat; } } } if(btRepeat > 0) od_repeat(chCurrentBlank, btRepeat); }