home *** CD-ROM | disk | FTP | other *** search
- // Zinc Interface Library - FMTSTR.CPP
- // COPYRIGHT (C) 1990, 1991. All Rights Reserved.
- // Zinc Software Incorporated. Pleasant Grove, Utah USA
-
- #include "ui_win.hpp"
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
-
- FS_STATE::FS_STATE(FS_STATE& src)
- {
- isMarked = src.isMarked;
- cursor = src.cursor;
- int srcTextLen = (src.text) ? strlen(src.text) : 0;
- text = new char[srcTextLen + 1];
- strcpy(text, src.text);
- }
-
- void FS_STATE::operator = (FS_STATE& src)
- {
- isMarked = src.isMarked;
- cursor = src.cursor;
- strcpy(text, src.text);
- }
-
- int FS_STATE::operator == (FS_STATE& rightOperand)
- {
- return (isMarked == rightOperand.isMarked &&
- cursor == rightOperand.cursor && !strcmp(text, rightOperand.text));
- }
-
- int FS_STATE::operator != (FS_STATE& rightOperand)
- {
- return (isMarked != rightOperand.isMarked ||
- cursor != rightOperand.cursor || strcmp(this->text, rightOperand.text));
- }
-
- UIW_FORMATTED_STRING::UIW_FORMATTED_STRING(int left, int top, int width,
- char *_text, char *_editMask, char *_literalMask, USHORT _woFlags,
- int (*_validate)(void *object, int ccode)) :
- UI_WINDOW_OBJECT(left, top, width, 1, _woFlags, WOAF_NO_FLAGS)
- {
- windowID[0] = ID_STRING;
- windowID[1] = ID_FORMATTED_STRING;
- search.type = ID_FORMATTED_STRING;
-
- Validate = _validate;
- int editMaskLen = strlen(_editMask);
- editMaskLen = Min(editMaskLen, width);
- int litMaskLen = strlen(_literalMask);
- editMask = new char[editMaskLen+1];
- memcpy(editMask, _editMask, editMaskLen);
- editMask[editMaskLen] = '\0';
- literalMask = new char[editMaskLen+1];
- memcpy(literalMask, _literalMask, editMaskLen);
- literalMask[editMaskLen] = '\0';
- if (litMaskLen < editMaskLen)
- memset(literalMask + litMaskLen, '?', editMaskLen - litMaskLen);
- maskLen = editMaskLen;
- fieldWidth = width;
- int textLen = TextLength();
- int passedLength = ui_strlen(_text);
- if (FlagSet(_woFlags, WOF_NO_ALLOCATE_DATA))
- state.text = _text;
- else
- {
- state.text = new char[textLen + 1];
- int actualLen = Min(textLen, passedLength);
- if (_text)
- memcpy(state.text, _text, actualLen);
- state.text[actualLen] = '\0';
- }
- }
-
- UIW_FORMATTED_STRING::~UIW_FORMATTED_STRING()
- {
- if (FlagSet(woFlags, WOF_NO_ALLOCATE_DATA))
- state.text = 0; // So FS_STATE destructor doesn't free it.
- delete editMask;
- delete literalMask;
- }
-
- void UIW_FORMATTED_STRING::DataSet(char *newText)
- {
- if (newText)
- {
- if (FlagSet(woFlags, WOF_NO_ALLOCATE_DATA))
- state.text = newText;
- else
- {
- delete state.text;
- int textLen = TextLength();
- state.text = new char[textLen + 1];
- int actualLen = strlen(newText);
- actualLen = Min(textLen, actualLen);
- memcpy(state.text, newText, actualLen);
- state.text[actualLen] = '\0';
- }
- }
- UI_WINDOW_OBJECT::Redisplay(FALSE);
- }
-
- int UIW_FORMATTED_STRING::Event(const UI_EVENT &event)
- {
- int viewOnly = FlagSet(woFlags, WOF_VIEW_ONLY) ? TRUE : FALSE;
- int ccode = UI_WINDOW_OBJECT::LogicalEvent(event, ID_STRING);
- int cellWidth = display->TextWidth("W");
- UI_REGION region;
- UI_WINDOW_OBJECT::Border(0, region, 0);
- int width = (region.right + 1 - region.left) / cellWidth;
- USHORT key;
- if (ccode == S_SIZE)
- {
- fieldWidth = width;
- maskLen = strlen(editMask);
- if (maskLen > fieldWidth)
- maskLen = fieldWidth;
- ccode = S_CREATE;
- }
- if (ccode == S_CREATE)
- {
- state.isMarked = FALSE;
- state.cursor = 0;
- FixText();
- }
- FS_STATE oldStateInfo(state);
- UCHAR forceDisplay = FALSE;
- UCHAR reDisplay = TRUE;
- UCHAR displayCheckRegion = FALSE;
- int needValidate = NeedsValidation();
-
- if (!FlagSet(woStatus, WOS_CURRENT))
- state.isMarked = FALSE;
- switch (ccode)
- {
- case E_KEY:
- key = event.rawCode & 0xFF;
- if ((key == '\b' || key >= ' ') && !viewOnly)
- {
- if (key == '\b')
- BackspaceKey();
- else
- RegularKey(key);
- }
- else
- {
- reDisplay = FALSE;
- ccode = S_UNKNOWN;
- }
- break;
-
- case L_LEFT:
- woStatus |= WOS_NO_AUTO_CLEAR;
- if (state.cursor > 0)
- state.cursor--;
- else
- ccode = S_UNKNOWN;
- break;
-
- case L_RIGHT:
- woStatus |= WOS_NO_AUTO_CLEAR;
- if (state.text[state.cursor + 1])
- state.cursor++;
- else
- ccode = S_UNKNOWN;
- break;
-
- case L_BOL:
- woStatus |= WOS_NO_AUTO_CLEAR;
- state.cursor = 0;
- break;
-
- case L_EOL:
- woStatus |= WOS_NO_AUTO_CLEAR;
- state.cursor = ui_strlen(state.text) - 1;
- break;
-
- case L_DELETE:
- if (viewOnly)
- break;
- else if (state.isMarked)
- CutBlock();
- else
- DeleteKey();
- woStatus |= WOS_NO_AUTO_CLEAR;
- break;
-
- case L_DELETE_EOL:
- if (viewOnly)
- break;
- else if (state.isMarked)
- CutBlock();
- else
- {
- int originalCursor = state.cursor;
- while (state.text[state.cursor])
- {
- DeleteKey();
- state.cursor++;
- }
- state.cursor = originalCursor;
- }
- woStatus |= WOS_NO_AUTO_CLEAR;
- break;
-
- case L_MARK:
- state.isMarked = !state.isMarked;
- break;
-
- case L_VIEW:
- eventManager->DeviceState(event.type, DM_EDIT);
- reDisplay = FALSE;
- break;
-
- case L_CUT:
- if (!viewOnly)
- {
- if (state.isMarked)
- CutBlock();
- else
- reDisplay = FALSE;
- break;
- }
- // If view only, treat a CUT as a copy.
-
- case L_COPY_MARK:
- if (state.isMarked)
- CopyBlock();
- else
- reDisplay = FALSE;
- break;
-
- case L_CUT_PASTE:
- if (state.isMarked)
- {
- if (viewOnly)
- CopyBlock();
- else
- CutBlock();
- break;
- }
- // Continue to L_PASTE.
-
- case L_PASTE:
- if (!viewOnly)
- {
- if (event.type != E_KEY)
- SetCursor((event.position.column - region.left) / cellWidth, width);
- PasteBlock();
- }
- break;
-
- case L_CONTINUE_MARK:
- if (markColumn != (event.position.column - region.left) / cellWidth)
- state.isMarked = TRUE;
- break;
-
- case L_BEGIN_MARK:
- state.isMarked = FALSE;
- markColumn = (event.position.column - region.left) / cellWidth;
- SetCursor(markColumn, width);
- forceDisplay = TRUE; // Force cursor to get updated.
- break;
-
- case S_CURRENT:
- woStatus &= ~WOS_UNANSWERED;
- if (needValidate)
- (*Validate)(this, ccode);
- displayCheckRegion = TRUE;
- break;
-
- case S_DISPLAY_ACTIVE:
- displayCheckRegion = TRUE;
- break;
-
- case S_NON_CURRENT:
- if ( needValidate && (*Validate)(this, ccode) != 0 )
- {
- ccode = S_ERROR;
- woStatus |= WOS_INVALID;
- reDisplay = FALSE;
- break;
- }
- woStatus &= ~WOS_INVALID;
- // else fall through to S_DISPLAY_INACTIVE.
-
- case S_DISPLAY_INACTIVE:
- state.isMarked = FALSE;
- displayCheckRegion = TRUE;
- break;
-
- case S_ERROR_RESPONSE:
- woStatus |= event.rawCode;
- forceDisplay = TRUE;
- break;
-
- default:
- ccode = UI_WINDOW_OBJECT::Event(event);
- reDisplay = FALSE;
- break;
- }
-
- if (displayCheckRegion)
- {
- forceDisplay = TRUE;
- if ( !UI_WINDOW_OBJECT::NeedsUpdate(event, ccode) &&
- oldStateInfo == state )
- reDisplay = FALSE;
- else
- UI_WINDOW_OBJECT::Border(ccode, region, lastPalette);
- }
-
- char dText[256];
- int cursorColumn;
- if (reDisplay)
- {
- if (FlagSet(woStatus, WOS_UNANSWERED))
- FixText();
- if (forceDisplay || oldStateInfo != state)
- {
- cursorColumn = Expand(dText);
- Redisplay(region, width, dText);
- UpdateCursor(region, width, dText, cursorColumn);
- }
- }
- else if (ccode == S_CURRENT)
- {
- cursorColumn = Expand(dText);
- UpdateCursor(region, width, dText, cursorColumn);
- }
- return (ccode);
- }
-
- void UIW_FORMATTED_STRING::BackspaceKey()
- {
- if (state.cursor > 0)
- {
- state.cursor--;
- DeleteKey();
- }
- woStatus |= WOS_CHANGED | WOS_NO_AUTO_CLEAR;
- }
-
- int UIW_FORMATTED_STRING::CalcLeading(int width, char *dText)
- {
- int textLen = strlen(dText);
- int leading = 0;
- if (woFlags & WOF_JUSTIFY_CENTER)
- leading = Min((fieldWidth - textLen) / 2, width);
- else if (woFlags & WOF_JUSTIFY_RIGHT)
- leading = Min(fieldWidth - textLen, width);
- if (leading < 0)
- leading = 0;
- return leading;
- }
-
- void UIW_FORMATTED_STRING::CopyBlock()
- {
- char dText[40];
-
- Expand(dText);
-
- pasteLength = (USHORT) strlen(dText);
- if (pasteBuffer)
- delete pasteBuffer;
- pasteBuffer = new char[pasteLength];
- if (pasteBuffer)
- memcpy(pasteBuffer, dText, pasteLength);
-
- state.isMarked = FALSE;
- woStatus |= WOS_CHANGED | WOS_NO_AUTO_CLEAR;
- }
-
- void UIW_FORMATTED_STRING::CutBlock()
- {
- CopyBlock();
- int textIndex = 0;
- for (int i = 0; state.text[textIndex] && i < maskLen; i++)
- {
- if (editMask[i] != 'L')
- state.text[textIndex++] = literalMask[i];
- }
- state.cursor = 0;
- woStatus |= WOS_CHANGED | WOS_NO_AUTO_CLEAR;
- }
-
- void UIW_FORMATTED_STRING::DeleteKey()
- {
- int column = ExpandedColumn();
- // ## Borland bug: large model code generation problem on following line:
- // state.text[state.cursor] = literalMask[column];
- char literalChar = literalMask[column];
- state.text[state.cursor] = literalChar;
- woStatus |= WOS_CHANGED | WOS_NO_AUTO_CLEAR;
- }
-
- int UIW_FORMATTED_STRING::Expand(char *destText)
- {
- char *src = state.text;
- int column = maskLen - 1;
- for (int i = 0; i < maskLen; i++)
- {
- if (src - state.text == state.cursor)
- column = i;
- if ( editMask[i] == 'L' )
- *destText++ = literalMask[i];
- else
- *destText++ = *src++;
- }
- *destText = 0;
- return column;
- }
-
- int UIW_FORMATTED_STRING::ExpandedColumn()
- {
- char *src = state.text;
- int column = maskLen - 1;
- for (int i = 0; i < maskLen; i++)
- {
- if (src - state.text == state.cursor)
- column = i;
- if (editMask[i] != 'L')
- src++;
- }
- return column;
- }
-
- void UIW_FORMATTED_STRING::FixText()
- {
- int textLen = TextLength();
- if (FlagSet(woStatus, WOS_UNANSWERED))
- memset(state.text, '\0', textLen + 1);
- int copyLen = strlen(state.text);
- int t = 0;
- for (int i = 0; i < maskLen; i++)
- {
- if (editMask[i] != 'L')
- {
- int textValue = ValidateMask(editMask[i], state.text[t]);
- if (t >= copyLen || !textValue)
- state.text[t] = literalMask[i];
- else
- state.text[t] = textValue;
- t++;
- }
- }
- state.text[textLen] = '\0';
- }
-
- void UIW_FORMATTED_STRING::PasteBlock()
- {
- if (pasteBuffer && !state.isMarked)
- {
- int textIndex = 0;
- int p = 0;
- for (int i = 0; i < maskLen && p < pasteLength; i++)
- {
- if (editMask[i] != 'L')
- {
- int textValue;
- do
- {
- textValue = ValidateMask(editMask[i], pasteBuffer[p]);
- p++;
- } while (!textValue && p < pasteLength);
- if (textValue)
- state.text[textIndex++] = textValue;
- }
- }
- state.text[textIndex] = '\0';
- FixText();
- state.cursor = 0;
- woStatus |= WOS_CHANGED | WOS_NO_AUTO_CLEAR;
- }
- }
-
- void UIW_FORMATTED_STRING::Redisplay(UI_REGION ®ion, short width, char *dText)
- {
- short cellHeight = display->TextHeight("W");
- short cellWidth = display->TextWidth("W");
- if ( !display->isText || (woStatus & WOS_UNANSWERED) )
- display->Rectangle(screenID, region, lastPalette, 0, TRUE);
- int text_len = strlen(dText);
- int leading = CalcLeading(width, dText);
- text_len = Min(text_len, width - leading);
- int trailing = width - text_len - leading;
- int bottom = region.top + display->TextHeight("W") - 1;
- if (bottom <= region.bottom && (woStatus & WOS_UNANSWERED) == 0)
- {
- if (!display->isText) // Center text vertically.
- {
- int vertRoom = region.bottom + 1 - region.top - cellHeight;
- region.top += (vertRoom + 1) / 2;
- region.bottom += (vertRoom + 1) / 2;
- }
- if (leading && display->isText)
- display->Rectangle(screenID, region.left, region.top,
- region.left + leading - 1, region.bottom, lastPalette, 0, TRUE);
- display->Text(screenID,
- region.left + leading * cellWidth,
- region.top, dText, lastPalette, text_len, FALSE);
- if ( trailing && display->isText )
- {
- display->Rectangle(screenID,
- region.left + leading + text_len, region.top,
- region.left + leading + text_len + trailing - 1,
- region.bottom, lastPalette, 0, TRUE);
- }
- if (state.isMarked)
- display->Text(screenID, region.left, region.top,
- NULL, _xorPalette, width, TRUE, TRUE);
- }
- }
-
- void UIW_FORMATTED_STRING::RegularKey(USHORT key)
- {
- int textValue = ValidateMask(editMask[ExpandedColumn()], key);
- if (textValue)
- {
- if (FlagSet(woFlags, WOF_AUTO_CLEAR) && !FlagSet(woStatus, WOS_NO_AUTO_CLEAR))
- {
- int textIndex = 0;
- for (int i = 0; state.text[textIndex] && i < maskLen; i++)
- {
- if (editMask[i] != 'L')
- state.text[textIndex++] = literalMask[i];
- }
- state.cursor = 0;
- }
- state.text[state.cursor] = textValue;
- if (state.text[state.cursor + 1])
- state.cursor++;
- woStatus |= WOS_CHANGED | WOS_NO_AUTO_CLEAR;
- }
- }
-
- void UIW_FORMATTED_STRING::SetCursor(int column, int width)
- {
- char expandedText[40];
- Expand(expandedText);
- int leading = 0;
- int textLen = strlen(expandedText);
- if (woFlags & WOF_JUSTIFY_CENTER)
- leading = Min((fieldWidth - textLen) / 2, width);
- else if (woFlags & WOF_JUSTIFY_RIGHT)
- leading = Min(fieldWidth - textLen, width);
- column -= leading;
- column = Min(column, maskLen);
- int match = 0;
- for (int i = 0; i < column; i++)
- {
- if (editMask[i] != 'L')
- match++;
- }
- state.cursor = match;
- }
-
- int UIW_FORMATTED_STRING::TextLength()
- {
- int textLen = 0;
- for (int i = 0; i < maskLen; i++)
- {
- if (editMask[i] != 'L')
- textLen++;
- }
- return textLen;
- }
-
- void UIW_FORMATTED_STRING::UpdateCursor(UI_REGION ®ion, int width,
- char *dText, int cursorColumn)
- {
- short cellWidth = display->TextWidth("W");
- int leading = CalcLeading(width, dText);
- if ( FlagSet(woStatus, WOS_CURRENT) &&
- !FlagSet(woAdvancedStatus, WOAS_TOO_SMALL) &&
- !FlagSet(woFlags, WOF_VIEW_ONLY) &&
- (leading + cursorColumn < width) )
- {
- int trueColumn = region.left +
- (leading + cursorColumn) * cellWidth;
- if (trueColumn >= 0 && trueColumn < display->columns &&
- region.top >= 0 && region.top < display->lines )
- {
- eventManager->DevicePosition(E_CURSOR, trueColumn, region.top);
- eventManager->DeviceState(E_CURSOR, DC_OVERTYPE);
- }
- }
- }
-
- int UIW_FORMATTED_STRING::ValidateMask(int editValue, int textValue)
- {
- int isAlpha = (textValue == ' ' || isalpha(textValue));
- int isDigit = isdigit(textValue);
- if (isupper(editValue))
- textValue = toupper(textValue);
- editValue = toupper(editValue);
- if ((editValue == 'X' && textValue >= ' ' && textValue <= '~') ||
- (editValue == 'N' && isDigit) ||
- (editValue == 'A' && isAlpha) ||
- (editValue == 'C' && (isDigit || isAlpha)))
- return (textValue);
- else
- return (0);
- }
-
- #ifdef ZIL_LOAD
- UIW_FORMATTED_STRING::UIW_FORMATTED_STRING(const char *name, UI_STORAGE *file, USHORT loadFlags) :
- UI_WINDOW_OBJECT(name, file, loadFlags | L_SUB_LEVEL),
- fieldWidth(relative.right - relative.left + 1)
- {
- windowID[0] = ID_FORMATTED_STRING;
-
- if (!file)
- file = _storage;
- file->Load(&editMask);
- file->Load(&literalMask);
- file->Load(&state.text);
- maskLen = strlen(editMask);
- if (!FlagSet(loadFlags, L_SUB_LEVEL) && FlagSet(file->stStatus, STS_TEMPORARY))
- delete file;
- }
- #endif
-
- #ifdef ZIL_STORE
- void UIW_FORMATTED_STRING::Store(const char *name, UI_STORAGE *file, USHORT storeFlags)
- {
- UI_WINDOW_OBJECT::Store(name, file, storeFlags | S_SUB_LEVEL);
- file->Store(editMask);
- file->Store(literalMask);
- file->Store(state.text);
- if (!FlagSet(storeFlags, S_SUB_LEVEL))
- file->ObjectSize(name, search);
- }
- #endif
-
-