This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/deps/odoors/ODEdStr.c
2017-03-19 07:49:46 +10:00

1240 lines
40 KiB
C

/* 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 <ctype.h>
#include <stddef.h>
#include <string.h>
#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<strlen(pszCurrentInput))
{
if(abCurrentFormatLiteral[nCount])
{
++nCount;
}
else
{
break;
}
}
/* If only literals in string. */
if(strlen(pszCurrentInput) == nCount && 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);
}