This is MORegexTextCellInspector.m in view mode; [Download] [Up]
// MORegexTextCellInspector.m // // by Mike Ferris // Part of MOKit - MORegexPalette // Copyright 1993, all rights reserved. // ABOUT MOKit // by Mike Ferris (mike@lorax.com) // // MOKit is a collection of useful and general objects. Permission is // granted by the author to use MOKit in your own programs in any way // you see fit. All other rights pertaining to the kit are reserved by the // author including the right to sell these objects as objects, as part // of a LIBRARY, or as SOURCE CODE. In plain English, I wish to retain // rights to these objects as objects, but allow the use of the objects // as pieces in a fully functional program. Permission is also granted to // redistribute the source code of MOKit for FREE as long as this copyright // notice is left intact and unchanged. NO WARRANTY is expressed or implied. // The author will under no circumstances be held responsible for ANY // consequences from the use of these objects. Since you don't have to pay // for them, and full source is provided, I think this is perfectly fair. #import "MORegexTextCellInspector.h" #import "MOKit/MORegexTextCell.h" #import "MOKit/MOString.h" #import <objc/objc-runtime.h> #define CLASS_VERSION 0 #define CLASS_NAME "MORegexTextCellInspector" #define ADD_TAG 0 #define CHANGE_TAG 1 #define REMOVE_TAG 2 #define BG_NONE_TAG 0 #define BG_BLACK_TAG 1 #define BG_DKGRAY_TAG 2 #define BG_LTGRAY_TAG 3 #define BG_WHITE_TAG 4 #define TG_BLACK_TAG 0 #define TG_DKGRAY_TAG 1 #define TG_LTGRAY_TAG 2 #define TG_WHITE_TAG 3 #define ALIGN_LEFT_TAG 0 #define ALIGN_CENTER_TAG 1 #define ALIGN_RIGHT_TAG 2 #define BORDER_NONE_TAG 0 #define BORDER_LINE_TAG 1 #define BORDER_BEZEL_TAG 2 #define EDITABLE_CB_TAG 0 #define SELECTABLE_CB_TAG 1 #define SCROLLABLE_CB_TAG 2 #define BUNDLE_TYPE "bundle" #define MOREGEXTEXTCELL_CLASS_NAME "MORegexTextCell" #define NIB_TYPE "nib" #define NIB_NAME "MORegexTextCellInspector" @interface MORegexTextCellInspector(Private) + (Class)MO_loadClassBundle:(const char *)className; @end @implementation MORegexTextCellInspector static id MORegexTextCellClass; + (Class)MO_loadClassBundle:(const char *)className // Finds the bundle of the same name as the class, grabs it and loads the // class from it and returns the named class. { char pathBuff[MAXPATHLEN+1]; id classBundle = nil; Class class = nil; // Load the bundle if ((class = objc_lookUpClass(className)) == nil) { // class is not already loaded... load it. // Look for the bundle in the main bundle first, // else try in this class's bundle. if (![[NXBundle mainBundle] getPath:pathBuff forResource:className ofType:BUNDLE_TYPE]) { if (![[NXBundle bundleForClass:[self class]] getPath:pathBuff forResource:className ofType:BUNDLE_TYPE]) { NXLogError("[%s loadClassBundle] failed to " "find %s class bundle.", [self name], className); return nil; } } classBundle = [[NXBundle allocFromZone:[self zone]] initForDirectory:pathBuff]; if (!classBundle) { NXLogError("[%s loadClassBundle] failed to " "create bundle for class %s.", [self name], className); return nil; } if ((class = [classBundle classNamed:className]) == nil) { NXLogError("[%s loadClassBundle] failed to " "load %s class from bundle.", [self name], className); return nil; } } return class; } + initialize // Set the version. { if (self == objc_lookUpClass(CLASS_NAME)) { [self setVersion:CLASS_VERSION]; // Load the MORegexTextCell class if necessary MORegexTextCellClass = [self MO_loadClassBundle:MOREGEXTEXTCELL_CLASS_NAME]; } return self; } - init // Load our nib file. { char buf[MAXPATHLEN+1]; id bundle; [super init]; // load our nib file. bundle = [NXBundle bundleForClass:[self class]]; [bundle getPath:buf forResource:NIB_NAME ofType:NIB_TYPE]; [NXApp loadNibFile:buf owner:self withNames:NO fromZone:[self zone]]; [patternText setDelegate:self]; [patternText setCharFilter:NXFieldFilter]; [patternText setFont:[Font userFixedPitchFontOfSize:0 matrix:NX_FLIPPEDMATRIX]]; return self; } - (int)browserSelectedRow // Return the row that is selected in the patternBrowser or -1 if none is. { return [[patternBrowser matrixInColumn:0] selectedRow]; } - (const char *)getPatternText { static char *text=NULL; if (text) NX_FREE(text); NX_MALLOC(text, char, [patternText byteLength]+1); [patternText getSubstring:text start:0 length:[patternText textLength]+1]; return text; } - enablePatternButtons // Enables or disables the add, change, remove buttons as appropriate for // the current state of the inspector. { if ([self browserSelectedRow] == -1) { [[patternButtonMatrix cellAt:0 :CHANGE_TAG] setEnabled:NO]; [[patternButtonMatrix cellAt:0 :REMOVE_TAG] setEnabled:NO]; } else { [[patternButtonMatrix cellAt:0 :CHANGE_TAG] setEnabled:YES]; [[patternButtonMatrix cellAt:0 :REMOVE_TAG] setEnabled:YES]; } if (strlen([self getPatternText])>0) { [[patternButtonMatrix cellAt:0 :ADD_TAG] setEnabled:YES]; } else { [[patternButtonMatrix cellAt:0 :ADD_TAG] setEnabled:NO]; [[patternButtonMatrix cellAt:0 :CHANGE_TAG] setEnabled:NO]; } return self; } - browserAction:sender // Copies the string of the currently selected pattern to the pattern text // field for editing. { int row = [self browserSelectedRow]; // put the text of the selected row's pattern in the patternField. if (row >= 0) { [patternText setText:[object regexStrAt:row]]; } else { [patternText setText:""]; } [patternText sizeToFit]; [patternText setSel:0 :[patternText textLength]]; [self enablePatternButtons]; return self; } - patternButtonAction:sender // Adds the text of patternField to the cell's patterns, or changes the pattern // currently selected in the patternBrowser to the text in patternField, or // removes the pattern in the selected row of the patternBrowser from the // cell's patterns. { int tag = [[sender selectedCell] tag]; const char *pattern = [self getPatternText]; char *pcpy; int row = [self browserSelectedRow]; id matrix = [patternBrowser matrixInColumn:0]; NX_MALLOC(pcpy, char, strlen(pattern)+1); strcpy(pcpy, pattern); if (tag==ADD_TAG) { // add the string in patternField to the object's patterns. if ((!pattern) || (!*pattern) || (![MORegexTextCellClass isValidRegex:pattern])) { NXRunAlertPanel("Regexp Error", "'%s' is not a valid regular " "expression.", "OK", NULL, NULL, pattern); NX_FREE(pcpy); return self; } [object addRegexStr:pattern]; } else if (tag==CHANGE_TAG) { // change the pattern at the index of the selected row in the // browser to the string in patternField. id string = [[object regexStrList] objectAt:row]; if ((!pattern) || (!*pattern) || (![MORegexTextCellClass isValidRegex:pattern])) { NXRunAlertPanel("Regexp Error", "'%s' is not a valid regular " "expression.", "OK", NULL, NULL, pattern); NX_FREE(pcpy); return self; } [string setStringValue:pattern]; } else if (tag==REMOVE_TAG) { // remove the pattern at the index of the selected row in the browser. [object removeRegexStrAt:row]; NX_FREE(pcpy); pcpy = NULL; pattern = [[matrix cellAt:((row==0)?1:row-1) :0] stringValue]; if (pattern) { NX_MALLOC(pcpy, char, strlen(pattern)+1); strcpy(pcpy, pattern); } } [patternBrowser reloadColumn:0]; if (pcpy) { char *buff; NX_MALLOC(buff, char, strlen(pcpy)+2); sprintf(buff, "/%s", pcpy); [patternBrowser setPath:buff]; NX_FREE(buff); } NX_FREE(pcpy); [self browserAction:patternBrowser]; [self enablePatternButtons]; [self touch:self]; return self; } - optionsCheckboxAction:sender { id selCell = [sender selectedCell]; int selTag = [selCell tag]; if (selTag == EDITABLE_CB_TAG) { id selectableCB = [optionsCheckboxMatrix cellAt:SELECTABLE_CB_TAG:0]; if ([selCell state]) { [selectableCB setState:YES]; [selectableCB setEnabled:NO]; } else { [selectableCB setEnabled:YES]; } } [optionsCheckboxMatrix display]; if ([[optionsCheckboxMatrix cellAt:EDITABLE_CB_TAG:0] state]) { [object setEditable:YES]; } else { [object setEditable:NO]; if ([[optionsCheckboxMatrix cellAt:SELECTABLE_CB_TAG:0] state]) { [object setSelectable:YES]; } else { [object setSelectable:NO]; } } [object setScrollable:[[optionsCheckboxMatrix cellAt:0:SCROLLABLE_CB_TAG] state]]; return self; } - ok:sender // set the text field-ish stuff and the allowEmptyString attribute. // The patternButtonAction takes care of the regex stuff. The // optionCheckboxAction takes care of editable, selectable, scrollable. { int bgTag = [backgroundGrayMatrix selectedTag]; int tgTag = [textGrayMatrix selectedTag]; int alTag = [alignmentMatrix selectedTag]; int boTag = [borderMatrix selectedTag]; if (bgTag == BG_NONE_TAG) { [object setBackgroundGray:-1.0]; } else if (bgTag == BG_BLACK_TAG) { [object setBackgroundGray:NX_BLACK]; } else if (bgTag == BG_DKGRAY_TAG) { [object setBackgroundGray:NX_DKGRAY]; } else if (bgTag == BG_LTGRAY_TAG) { [object setBackgroundGray:NX_LTGRAY]; } else { [object setBackgroundGray:NX_WHITE]; } if (tgTag == TG_BLACK_TAG) { [object setTextGray:NX_BLACK]; } else if (tgTag == TG_DKGRAY_TAG) { [object setTextGray:NX_DKGRAY]; } else if (tgTag == TG_LTGRAY_TAG) { [object setTextGray:NX_LTGRAY]; } else { [object setTextGray:NX_WHITE]; } if (alTag == ALIGN_LEFT_TAG) { [object setAlignment:NX_LEFTALIGNED]; } else if (alTag == ALIGN_CENTER_TAG) { [object setAlignment:NX_CENTERED]; } else { [object setAlignment:NX_RIGHTALIGNED]; } if (boTag == BORDER_NONE_TAG) { [object setBordered:NO]; [object setBezeled:NO]; } else if (boTag == BORDER_LINE_TAG) { [object setBordered:YES]; } else { [object setBezeled:YES]; } [object setTag:[tagForm intValueAt:0]]; [object setAllowEmptyString:[allowEmptyStringButton state]]; return [super ok:sender]; } - revert:sender // fill in the inspector with the attributes of "object" { id matrix; float bg = [object backgroundGray], tg = [object textGray]; int alignment = [object alignment]; BOOL isBordered = [object isBordered], isBezeled = [object isBezeled]; if (bg < 0) { [backgroundGrayMatrix selectCellAt:0:BG_NONE_TAG]; } else if ((bg >= 0) && (bg < .2)) { [backgroundGrayMatrix selectCellAt:0:BG_BLACK_TAG]; } else if ((bg >= .2) && (bg < .45)) { [backgroundGrayMatrix selectCellAt:0:BG_DKGRAY_TAG]; } else if ((bg >= .45) && (bg < .8)) { [backgroundGrayMatrix selectCellAt:0:BG_LTGRAY_TAG]; } else if (bg >= .8) { [backgroundGrayMatrix selectCellAt:0:BG_WHITE_TAG]; } [backgroundGrayMatrix display]; if (tg < .2) { [textGrayMatrix selectCellAt:0:TG_BLACK_TAG]; } else if ((tg >= .2) && (tg < .45)) { [textGrayMatrix selectCellAt:0:TG_DKGRAY_TAG]; } else if ((tg >= .45) && (tg < .8)) { [textGrayMatrix selectCellAt:0:TG_LTGRAY_TAG]; } else if (tg >= .8) { [textGrayMatrix selectCellAt:0:TG_WHITE_TAG]; } [textGrayMatrix display]; if (alignment == NX_LEFTALIGNED) { [alignmentMatrix selectCellAt:0:ALIGN_LEFT_TAG]; } else if (alignment == NX_CENTERED) { [alignmentMatrix selectCellAt:0:ALIGN_CENTER_TAG]; } else { [alignmentMatrix selectCellAt:0:ALIGN_RIGHT_TAG]; } [alignmentMatrix display]; if (isBezeled) { [borderMatrix selectCellAt:0:BORDER_BEZEL_TAG]; } else if (isBordered) { [borderMatrix selectCellAt:0:BORDER_LINE_TAG]; } else { [borderMatrix selectCellAt:0:BORDER_NONE_TAG]; } [optionsCheckboxMatrix setState:[object isEditable] at:EDITABLE_CB_TAG:0]; [optionsCheckboxMatrix setState:[object isSelectable] at:SELECTABLE_CB_TAG:0]; [optionsCheckboxMatrix setState:[object isScrollable] at:SCROLLABLE_CB_TAG:0]; [allowEmptyStringButton setState:[object doesAllowEmptyString]]; [tagForm setIntValue:[object tag] at:0]; // browser [patternBrowser loadColumnZero]; matrix = [patternBrowser matrixInColumn:0]; if ([matrix cellCount] > 0) { const char *pattern = [[matrix cellAt:0:0] stringValue]; char *buff; NX_MALLOC(buff, char, strlen(pattern)+2); sprintf(buff, "/%s", pattern); [patternBrowser setPath:buff]; NX_FREE(buff); } [self browserAction:patternBrowser]; [self enablePatternButtons]; [patternButtonMatrix display]; return [super revert:sender]; } - (BOOL)wantsButtons // Our inspector does not have OK or Revert buttons. { return NO; } - (int)browser:sender fillMatrix:matrix inColumn:(int)column // Fill the browser with the pattern strings from the cell. { int i, c = [object regexStrCount]; for (i=0; i<c; i++) { [matrix renewRows:i+1 cols:1]; [[matrix cellAt:i :0] setStringValue:[object regexStrAt:i]]; [[matrix cellAt:i :0] setLoaded:YES]; [[matrix cellAt:i :0] setLeaf:YES]; } return i; } - textDidGetKeys:sender isEmpty:(BOOL)flag // Having text in the patternField affects what buttons to enable. { if (sender==patternText) { [self enablePatternButtons]; [patternButtonMatrix display]; } return self; } - textDidChange:sender; // The patternField shouldn't be passed on. { if (sender==patternText) { return self; } else { return [super textDidChange:sender]; } } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.