This is OATextFieldCell.m in view mode; [Download] [Up]
// OATextFieldCell:TextFieldCell // // COPYRIGHT 1994 BY M. ONYSCHUK AND ASSOCIATES INC. // ALL RIGHTS RESERVED. #import "OATextFieldCell.h" #import "OATextFieldFormatter.h" #import <appkit/Font.h> #import <appkit/Text.h> #import <appkit/color.h> #import <appkit/NXCType.h> #import <appkit/publicWraps.h> #import <defaults/defaults.h> #include <libc.h> #define CLASS_VERSION 1 #define DF_NAME "OATextField" #define DF_COLOR_OPTIONAL "OptionalFieldColor" #define COLOR_OPTIONAL "0.53 0.66 1.0" #define DF_COLOR_MANDATORY "MandatoryFieldColor" #define COLOR_MANDATORY "1.0 0.6 0.6" #define DF_FONT "Font" #define FONT "Courier 12.0" @interface OATextFieldCell (Private) // Factory methods + (OATextFieldCell *)currentCell; + setCurrentCell:(OATextFieldCell *)aCell; // Instance methods - (void)_setBackgroundColorFromDefaultsDatabase; - (void)_setFontFromDefaultsDatabase; - (void)_setStringValueByRemovingWhitespace; - (void)_setStringValueFromCaseMapping; @end @implementation OATextFieldCell (Private) // Factory methods static OATextFieldCell *currentCell = nil; + (OATextFieldCell *)currentCell { return currentCell; } + setCurrentCell:(OATextFieldCell *)aCell { currentCell = aCell; return self; } // Instance methods static NXColor colorFromRGBString(const char *aString) { if (aString) { float r, g, b; sscanf(aString, "%f %f %f", &r, &g, &b); return NXConvertRGBAToColor(r, g, b, NX_NOALPHA); } else { return NX_COLORCLEAR; } } static Font * fontFromFontString(const char *aString) { if (aString) { char name[80]; float size; if (sscanf(aString, "%[^ \t]%f", name, &size) == 2) { return[Font newFont:name size:size]; } else { return nil; } } else { return nil; } } - (void)_setBackgroundColorFromDefaultsDatabase { const char *value = [self stringValue]; unsigned int length = (value) ? strlen(value) : 0; // if the field is empty, and the defaults database // specifies a color for the mandatory flag setting, then // set the background color to the color specified... if (length == 0) { const char *df; if ([self isMandatory]) { df = NXGetDefaultValue(DF_NAME, DF_COLOR_MANDATORY); } else { df = NXGetDefaultValue(DF_NAME, DF_COLOR_OPTIONAL); } if (df) { [self setBackgroundColor:colorFromRGBString(df)]; } } } - (void)_setFontFromDefaultsDatabase { const char *df; if ((df = NXGetDefaultValue(DF_NAME, DF_FONT)) != NULL) { Font *font; if ((font = fontFromFontString(df)) != nil) { [self setFont:font]; } } } - (void)_setStringValueByRemovingWhitespace { const char *value = [self stringValue]; unsigned int length = (value) ? strlen(value) : 0; if (isSettingValue) { return; } isSettingValue = YES; if (length > 0) { int i, j; char *copy = NXCopyStringBufferFromZone(value, [self zone]); if (removeLeadingWhitespace) { for (i = 0; NXIsSpace(copy[i]); i++) { } if (i > 0) { for (j = 0; i < length; i++, j++) { copy[j] = copy[i]; } copy[j] = copy[i]; } } if (removeTrailingWhitespace) { for (j = strlen(copy); j && NXIsSpace(copy[j-1]); j--) { } copy[j] = '\0'; } [self setStringValueNoCopy:copy]; } isSettingValue = NO; } - (void)_setStringValueFromCaseMapping { const char *value = [self stringValue]; unsigned int length = (value) ? strlen(value) : 0; if (isSettingValue) { return; } isSettingValue = YES; if (length > 0) { switch (caseMapping) { case MAP_TO_UPPER: { int index = length; char *copy = NXCopyStringBufferFromZone(value,[self zone]); while (index--) { copy[index] = NXToUpper(copy[index]); } [self setStringValueNoCopy:copy]; } break; case MAP_TO_LOWER: { int index = length; char *copy = NXCopyStringBufferFromZone(value,[self zone]); while (index--) { copy[index] = NXToLower(copy[index]); } [self setStringValueNoCopy:copy]; } break; case MAP_TO_PROPER: { int index = length; char *copy = NXCopyStringBufferFromZone(value,[self zone]); while (index--) { if ((index == 0) || NXIsSpace(copy[index - 1])) { copy[index] = NXToUpper(copy[index]); } else { copy[index] = NXToLower(copy[index]); } } [self setStringValueNoCopy:copy]; } break; case MAP_TO_STUDLY: { // YeAH! StUDlY CapS int index = length; char *copy = NXCopyStringBufferFromZone(value,[self zone]); while (index--) { if (random()&01) { copy[index] = NXToUpper(copy[index]); } else { copy[index] = NXToLower(copy[index]); } } [self setStringValueNoCopy:copy]; } break; case MAP_TO_NONE: break; } } isSettingValue = NO; } @end @implementation OATextFieldCell + initialize // Initializes the receiver, sets the class version, and registers // several default values. { static NXDefaultsVector defaults = { {DF_COLOR_OPTIONAL, NULL}, {DF_COLOR_MANDATORY, NULL}, {DF_FONT, NULL}, {NULL} }; NXRegisterDefaults(DF_NAME, defaults); [self setVersion:CLASS_VERSION]; return self; } // Instance methods static char emptyText[1] = {'\0'}; static char outputText[80] = {'\0'}; char * OAFilterFun(id textObj, unsigned char *inputText, int *inputLength, int position) { OATextFieldCell *cell = [OATextFieldCell currentCell]; OACharacterFiltering filtering = [cell characterFiltering]; const char *exceptions = [cell filteringExceptions]; BOOL checksMaximumLength = [cell doesCheckMaximumLength]; int maximumLength = [cell maximumLength]; OATextFieldFormatter *formatter = [cell textFieldFormatter]; if (inputText == NULL) { // if the input is NULL, then return... *inputLength = 0; return emptyText; } if (NXIsCntrl(inputText[0])) { outputText[0] = inputText[0]; outputText[1] = '\0'; return outputText; } if (checksMaximumLength && (position >= maximumLength)) { // if the imput is too long then beep and return... NXBeep(); *inputLength = 0; return emptyText; } if ((filtering == ALLOW_ALL) || (filtering == ALLOW_LETTERS && NXIsAlpha(inputText[0])) || (filtering == ALLOW_NUMBERS && NXIsDigit(inputText[0])) || (filtering == ALLOW_ALPHANUMERIC && NXIsAlNum(inputText[0])) || (exceptions && index(exceptions, inputText[0]))) { // if the input passes filter presets, then if the // cell has a custom formatter, apply it here... if (formatter) { const char *formatterOutput; [formatter filterSubstring:inputText ofSize:*inputLength at:position]; formatterOutput = [formatter output]; if (formatterOutput) { *inputLength = strlen(formatterOutput); return formatterOutput; } else { *inputLength = 0; return emptyText; } } else { strncpy(outputText, inputText, *inputLength); return outputText; } } else { // Beep to signal an input error... NXBeep(); *inputLength = 0; return emptyText; } } - initTextCell:(const char *)stringValue { [super initTextCell:stringValue]; oldTextFilter = (NXTextFilterFunc)nil; [self _setStringValueFromCaseMapping]; [self _setStringValueByRemovingWhitespace]; [self _setFontFromDefaultsDatabase]; [self _setBackgroundColorFromDefaultsDatabase]; return self; } - free { if (filteringExceptions) { NXZoneFree([self zone], filteringExceptions); filteringExceptions = NULL; } return[super free]; } - select:(const NXRect *)aRect inView:controlView editor:textObj delegate:anObject start:(int)selStart length:(int)selLength { [self setBackgroundColor:NX_COLORWHITE]; [super select:aRect inView:controlView editor:textObj delegate:anObject start:selStart length:selLength]; oldTextFilter = [textObj textFilter]; [textObj setTextFilter:(NXTextFilterFunc)OAFilterFun]; [OATextFieldCell setCurrentCell:self]; return self; } - (BOOL)isEntryAcceptable:(const char *)value { unsigned int length = (value) ? strlen(value) : 0; int ivalue = atoi(value); // perform field length check... if ((length == 0) && [self isNullable]) { return YES; } if ([self doesCheckMinimumLength] && (length < [self minimumLength])) { NXBeep(); return NO; } else { goto BEGIN_CHECK_VALUES; // GOTO } if ([self doesCheckMaximumLength] && (length > [self maximumLength])) { NXBeep(); return NO; } BEGIN_CHECK_VALUES: // begin value check... if ([self doesCheckMinimumValue] && (ivalue < [self minimumValue])) { NXBeep(); return NO; } if ([self doesCheckMaximumValue] && (ivalue > [self maximumValue])) { NXBeep(); return NO; } // after preliminary checks, perform custom formatting and // validation defined by the formatter... if (formatter) { if ([formatter formatString:[self stringValue]] == YES) { // this is a bit bass-ackwards by my reasoning, but it is // the way the text delegate indicates that an error in input // has occurred... NXBeep(); return NO; } else { [self setStringValue:[formatter output]]; return YES; } } return YES; } - edit:(const NXRect *)aRect inView:controlView editor:textObj delegate:anObject event:(NXEvent *)theEvent { [self setBackgroundColor:NX_COLORWHITE]; [super edit:aRect inView:controlView editor:textObj delegate:anObject event:theEvent]; oldTextFilter = [textObj textFilter]; [textObj setTextFilter:(NXTextFilterFunc)OAFilterFun]; [OATextFieldCell setCurrentCell:self]; return self; } - endEditing:anObject { [self _setStringValueFromCaseMapping]; [self _setStringValueByRemovingWhitespace]; [self _setBackgroundColorFromDefaultsDatabase]; [anObject setTextFilter:(NXTextFilterFunc)oldTextFilter]; [OATextFieldCell setCurrentCell:nil]; return [super endEditing:anObject]; } - (OACaseMapping)caseMapping { return caseMapping; } - setCaseMapping:(OACaseMapping)aValue { caseMapping = aValue; [self _setStringValueFromCaseMapping]; return self; } - (OACharacterFiltering)characterFiltering { return characterFiltering; } - setCharacterFiltering:(OACharacterFiltering)aValue { characterFiltering = aValue; return self; } - (const char *)filteringExceptions { return filteringExceptions; } - setFilteringExceptions:(const char *)aValue { NXZone *z = [self zone]; if (filteringExceptions) { NXZoneFree(z, filteringExceptions); } filteringExceptions = (aValue) ? NXCopyStringBufferFromZone(aValue,z) : NULL; return self; } - (BOOL)doesRemoveLeadingWhitespace { return removeLeadingWhitespace; } - setRemovesLeadingWhitespace:(BOOL)aValue { removeLeadingWhitespace = aValue; [self _setStringValueByRemovingWhitespace]; return self; } - (BOOL)doesRemoveTrailingWhitespace { return removeTrailingWhitespace; } - setRemovesTrailingWhitespace:(BOOL)aValue { removeTrailingWhitespace = aValue; [self _setStringValueByRemovingWhitespace]; return self; } - (int)minimumLength { return minimumLength; } - setMinimumLength:(int)aValue { minimumLength = aValue; return self; } - (BOOL)doesCheckMinimumLength { return checkMinimumLength; } - setChecksMinimumLength:(BOOL)aValue { checkMinimumLength = aValue; return self; } - (int)maximumLength { return maximumLength; } - setMaximumLength:(int)aValue { maximumLength = aValue; return self; } - (BOOL)doesCheckMaximumLength { return checkMaximumLength; } - setChecksMaximumLength:(BOOL)aValue { checkMaximumLength = aValue; return self; } - (BOOL)isNullable { return isNullable; } - setNullable:(BOOL)aValue { isNullable = aValue; return self; } - (BOOL)isMandatory { return isMandatory; } - setMandatory:(BOOL)aValue { isMandatory = aValue; [self _setBackgroundColorFromDefaultsDatabase]; return self; } - (int)minimumValue { return minimumValue; } - setMinimumValue:(int)aValue { minimumValue = aValue; return self; } - (BOOL)doesCheckMinimumValue { return checkMinimumValue; } - setChecksMinimumValue:(BOOL)aValue { checkMinimumValue = aValue; return self; } - (int)maximumValue { return maximumValue; } - setMaximumValue:(int)aValue { maximumValue = aValue; return self; } - (BOOL)doesCheckMaximumValue { return checkMaximumValue; } - setChecksMaximumValue:(BOOL)aValue { checkMaximumValue = aValue; return self; } - (OATextFieldFormatter *)textFieldFormatter { return formatter; } - setTextFieldFormatter:(OATextFieldFormatter *)aValue { return [self setTextFieldFormatterNoCopy:[aValue copy]]; } - setTextFieldFormatterNoCopy:(OATextFieldFormatter *)aValue { if (formatter != aValue) { [formatter free]; } formatter = aValue; [formatter setTextFieldCell:self]; return self; } - read:(NXTypedStream *)aStream { [super read:aStream]; NXReadType(aStream,@encode(OACaseMapping), &caseMapping); NXReadType(aStream,@encode(OACharacterFiltering), &characterFiltering); NXReadType(aStream,@encode(char*), &filteringExceptions); NXReadType(aStream,@encode(BOOL), &removeLeadingWhitespace); NXReadType(aStream,@encode(BOOL), &removeTrailingWhitespace); NXReadType(aStream,@encode(int), &minimumLength); NXReadType(aStream,@encode(int), &maximumLength); NXReadType(aStream,@encode(BOOL), &checkMinimumLength); NXReadType(aStream,@encode(BOOL), &checkMaximumLength); NXReadType(aStream,@encode(BOOL), &isNullable); NXReadType(aStream,@encode(BOOL), &isMandatory); NXReadType(aStream,@encode(int), &minimumValue); NXReadType(aStream,@encode(int), &maximumValue); NXReadType(aStream,@encode(BOOL), &checkMinimumValue); NXReadType(aStream,@encode(BOOL), &checkMaximumValue); formatter = NXReadObject(aStream); return self; } - write:(NXTypedStream *)aStream { [super write:aStream]; NXWriteType(aStream,@encode(OACaseMapping), &caseMapping); NXWriteType(aStream,@encode(OACharacterFiltering), &characterFiltering); NXWriteType(aStream,@encode(char*), &filteringExceptions); NXWriteType(aStream,@encode(BOOL), &removeLeadingWhitespace); NXWriteType(aStream,@encode(BOOL), &removeTrailingWhitespace); NXWriteType(aStream,@encode(int), &minimumLength); NXWriteType(aStream,@encode(int), &maximumLength); NXWriteType(aStream,@encode(BOOL), &checkMinimumLength); NXWriteType(aStream,@encode(BOOL), &checkMaximumLength); NXWriteType(aStream,@encode(BOOL), &isNullable); NXWriteType(aStream,@encode(BOOL), &isMandatory); NXWriteType(aStream,@encode(int), &minimumValue); NXWriteType(aStream,@encode(int), &maximumValue); NXWriteType(aStream,@encode(BOOL), &checkMinimumValue); NXWriteType(aStream,@encode(BOOL), &checkMaximumValue); NXWriteObject(aStream,formatter); return self; } - copyFromZone:(NXZone *)aZone { OATextFieldCell *copy = [super copyFromZone:aZone]; copy->filteringExceptions = (filteringExceptions) ? NXCopyStringBufferFromZone(filteringExceptions, aZone) : NULL; copy->formatter = [formatter copyFromZone:aZone]; return copy; } - awake { id ret = [super awake]; [self _setStringValueFromCaseMapping]; [self _setStringValueByRemovingWhitespace]; [self _setFontFromDefaultsDatabase]; [self _setBackgroundColorFromDefaultsDatabase]; [self setTextFieldFormatterNoCopy:formatter]; return ret; } - awakeFromNib { return [self awake]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.