home *** CD-ROM | disk | FTP | other *** search
- /* Controller.m:
- * You may freely copy, distribute, and reuse the code in this example.
- * NeXT disclaims any warranty of any kind, expressed or implied, as to its
- * fitness for any particular use.
- *
- *
- */
-
- #import <pwd.h>
- #import <sys/param.h>
- #import <indexing/IXRecordManager.h>
- #import <indexing/IXPostingList.h>
- #import <indexing/protocols.h>
- #import <btree/protocols.h>
- #import <btree/IXPostingSet.h>
- #import <store/IXStoreFile.h>
- #import <architecture/byte_order.h>
-
- #import "Controller.h"
- #import "DataRecord.h"
-
- #define STRINGLEN(A) (strlen((A)) + 1)
-
- @implementation Controller
-
- - free
- {
- [recMan free];
- if (postingList != nil)
- postingList = [[postingList freeObjects] free];
-
- return [super free];
- }
-
- /*
- * Commits any pending transactions to disk.
- */
- - commit
- {
- [[recMan store] commitTransaction];
- return self;
- }
-
- /* TARGET ACTION METHODS */
-
- - clear:sender
- {
- [idField setStringValue:""];
- [dataForm setStringValue:"" at:0];
- [dataForm setStringValue:"" at:1];
- return self;
- }
-
- /*
- * Adds a new record to the database. A DataRecord is created and initialized
- * from the fields in the dataForm.
- */
- - addARecord:sender
- {
- id newRec;
- const char *stringInput;
- const char *numberInput;
-
- /* create and setup the new record */
- /* We don't allow empty input, since those records can't be retrieved
- * later on
- */
- stringInput = (const char *)[dataForm stringValueAt:0];
- numberInput = (const char *)[dataForm stringValueAt:1];
- if ( (strcmp(stringInput, "") == 0) || (strcmp(numberInput, "") == 0) ){
- NXRunAlertPanel("Error", "You must supply a string.", NULL, NULL, NULL);
- return self;
- }
- newRec = [[DataRecord alloc] init];
- [newRec setAString:[dataForm stringValueAt:0]];
- [newRec setAnInt:[dataForm intValueAt:1]];
- /* add it in */
- [idField setIntValue:[recMan addRecord:newRec]];
- [newRec free];
- [self commit];
- [dataForm selectTextAt:0];
- return self;
- }
-
- /*
- * Delete the current record from the database.
- */
- - deleteRecord:sender
- {
- id retval;
- unsigned int aHandle;
-
- aHandle = (unsigned)[idField intValue];
- retval = [recMan removeRecord:aHandle];
- if(retval != nil)
- {
- [self clear:self];
- [self commit];
- }
-
- return self;
- }
-
- /*
- * Changes the data fields of the current record. This is done by creating a
- * new record and replacing the existing one with the new one.
- */
- - editRecord:sender
- {
- id newRec;
-
- /* create and setup the replacement record */
- newRec = [[DataRecord alloc] init];
- [newRec setAString:[dataForm stringValueAt:0]];
- [newRec setAnInt:[dataForm intValueAt:1]];
-
- /* replace it */
- [recMan replaceRecord:[idField intValue] with:newRec];
- [newRec free];
- [self commit];
- return self;
- }
-
-
- /*
- * Searches for records in the database.
- * If the allSwitch is set, we simply pull all records from the record manager.
- * If the allSwitch is not set, we search on each attribute 'anding' the
- * results as we go along.
- */
- - search:sender
- {
- id cur;
- char *searchString;
- IXPostingSet *postingSet;
- unsigned int intfld;
-
- if (postingList != nil)
- postingList = [[postingList freeObjects] free];
-
- if(![allSwitch state])
- {
- postingSet = [[IXPostingSet alloc] init];
-
- /* first search the string attribute */
- searchString = (char *)[searchForm stringValueAt:0];
- if(searchString && *searchString != '\0')
- {
- cur = [recMan cursorForAttributeNamed:DRASTRINGNAME];
- if([cur setKey:searchString andLength:STRINGLEN(searchString)])
- [postingSet formUnionWithPostingsIn:cur];
-
- [cur free]; // must free cursor to avoid leaking.
- }
-
- /* now search the integer attribute */
- searchString = (char *)[searchForm stringValueAt:1];
- if(searchString && *searchString != '\0')
- {
- cur = [recMan cursorForAttributeNamed:DRANINTNAME];
- intfld = atoi(searchString);
-
- /* accumulate results in the IXPostingSet.
- Do a logical AND if there were string matches above,
- otherwise, just do a logical OR.
- */
-
-
- /* Swap if this is a little-endian machine. */
- if ( NXHostByteOrder() == NX_LittleEndian )
- intfld = NXSwapInt(intfld);
-
-
-
- if([cur setKey:(void *)&intfld andLength:sizeof(unsigned int)])
- {
- if([postingSet count] > 0)
- [postingSet formIntersectionWithPostingsIn:cur];
- else
- [postingSet formUnionWithPostingsIn:cur];
- }
-
- [cur free]; // must free cursor to avoid leaking.
- }
-
- [searchForm selectTextAt:0];
- postingList = [[IXPostingList alloc] initWithSource:recMan andPostingsIn:postingSet];
- [postingSet free];
- } else
- postingList = [recMan recordsForClass:[DataRecord class]];
-
- [recBrowser loadColumnZero];
- return self;
- }
-
- - browserHit:sender
- /*
- * Responds to the user selecting a handle in the browser by retrieving
- * the corresponding record and displaying its values in the dataForm.
- */
- {
- int col = [recBrowser selectedColumn];
- id dr, matrix = [recBrowser matrixInColumn:col];
- unsigned int handle;
-
- handle = [[matrix selectedCell] intValue];
- [idField setIntValue:handle];
- if((dr = [recMan readRecord:handle fromZone:[self zone]]) == nil)
- {
- NXRunAlertPanel("Error", "Cannot read record", NULL, NULL, NULL);
- [self clear:self];
- } else
- {
- [dataForm setStringValue:[dr aString] at:0];
- [dataForm setIntValue:[dr anInt] at:1];
- [dr free];
- }
-
- return self;
- }
-
- /* NXBROWSER DELEGATE METHODS */
-
- - (int)browser:sender fillMatrix:matrix inColumn:(int)col
- {
- id cell;
- int i, rows = 0;
-
- if (postingList != nil)
- rows = [postingList count];
-
- for(i = 0; i < rows; i++)
- {
- [matrix insertRowAt:i];
- cell = [matrix cellAt:i :0];
- [cell setIntValue:[postingList handleOfObjectAt:i]];
- [cell setLoaded:YES];
- [cell setLeaf:YES];
- }
-
- return rows;
- }
-
- /* APPLICATION DELEGATE METHODS */
-
- - appDidInit:sender
- {
- struct passwd *pw;
- char path[MAXPATHLEN];
-
- pw = getpwuid(getuid());
- sprintf(path, "%s/%s", pw->pw_dir, DBFILENAME);
- fprintf(stderr, "path %s\n", path);
- [recBrowser acceptArrowKeys:YES andSendActionMessages:YES];
- if(access(path, F_OK) == -1)
- {
- /* create new database */
- recMan = [[IXRecordManager alloc] initWithName:DBNAME inFile:path];
- if (recMan == nil)
- {
- NXRunAlertPanel("Error", "Cannot create database.", NULL, NULL, NULL);
- [NXApp terminate:self];
- }
-
- [recMan addAttributeNamed:DRASTRINGNAME forSelector:@selector(aString)];
- [recMan setComparator:&IXCompareMonocaseStrings andContext:NULL
- forAttributeNamed:DRASTRINGNAME];
-
- [recMan addAttributeNamed:DRANINTNAME forSelector:@selector(anInt)];
- [recMan setComparator:&IXCompareLongs andContext:NULL
- forAttributeNamed:DRANINTNAME];
- } else
- {
- /* open existing database */
- recMan = [[IXRecordManager alloc] initFromName:DBNAME inFile:path forWriting:YES];
- if (recMan == nil)
- {
- NXRunAlertPanel("Error", "Cannot open database.", NULL, NULL, NULL);
- [NXApp terminate:self];
- }
- }
-
- [[recMan store] startTransaction];
- [[recMan store] commitTransaction]; // don't want to leave a transaction pending
- return self;
- }
-
- -appWillTerminate:sender
- {
- [self commit];
- return self;
- }
-
- @end
-