home *** CD-ROM | disk | FTP | other *** search
- /*
- StoreManager.m - Copyright (c) 1992 NeXT Computer, Inc.
-
- You may freely copy, distribute and reuse the code in this example.
- NeXT Computer, Inc. disclaims any warranty of any kind, expressed or implied,
- as to its fitness for any particular use.
- */
-
- #import <appkit/appkit.h>
- #import <sys/param.h>
- #import <bsd/libc.h>
- #import <objc/NXBundle.h>
- #import <store/IXStoreBlock.h>
- #import "DataWrapper.h"
- #import "StoreManager.h"
-
- @interface StoreManager(Private)
-
- - loadNib;
- - (int)browser:sender fillMatrix:matrix inColumn:(int)column;
- - browserClick:sender;
- - setBrowser:anObject;
- - windowWillClose:sender;
- - clearText;
- - appendToText:(const char *)aString;
-
- @end
-
- @implementation StoreManager(Private)
- - loadNib
- {
- char buf[MAXPATHLEN+1];
- NXBundle *aBundle = [NXBundle bundleForClass:[self class]];
-
- if ([aBundle getPath:buf forResource:"StoreManager" ofType:"nib"]) {
- if ([NXApp loadNibFile:buf owner:self
- withNames:NO fromZone:[NXApp zone]]) {
- [win makeKeyAndOrderFront:self];
- [win setDelegate:self];
- return self;
- }
- }
-
- return nil;
- }
-
- - (int)browser:sender fillMatrix:matrix inColumn:(int)column
- {
- int row;
- id cell;
- char str[512]&C@ int cnt = [blocks count];
-
- for (row=0; row < cnt; row++) {
- int theValue;
- DataWrapper *aWrapper;
- unsigned int blockNum;
-
- blockNum = (unsigned int) [[blocks objectAt:row] value];
- aWrapper = (DataWrapper *)
- IXReadObjectFromStore(storeFile, blockNum, [NXApp zone]);
- [storeFile closeBlock:blockNum]; // not required for single context
- theValue = [aWrapper value];
- [aWrapper free];
-
- cell = [matrix cellAt:row :0];
- if (cell == nil) {
- [matrix insertRowAt:row];
- cell = [matrix cellAt:row :0];
- }
-
- sprintf(str, "%8d\t%8d\t%s",
- [[blocks objectAt:row] value],
- theValue,
- [[blocks objectAt:row] key]);
- [cell setStringValue:str];
- [cell setLoaded:YES];
- [cell setLeaf:YES];
- }
-
- return row;
- }
-
- - browserClick:sender
- {
- int row;
- const char *str;
- int block, value;
- const char *key;
-
- str = [[[browser matrixInColumn:0] selectedCell] stringValue];
- row = [[browser matrixInColumn:0] selectedRow];
- sscanf(str, "%8d\t%8d", &block, &value);
- /*
- * the key starts at the first char after the first two tabs
- */
- key = [[blocks objectAt:row] key];
-
- [[keyForm cellAt:0 :0] setStringValue:key];
- [[keyForm cellAt:1 :0] setIntValue:value];
-
- return self;
- }
-
- - setBrowser:anObject
- {
- [anObject setTarget:self];
- [anObject setAction:@selector(browserClick:)];
- [anObject setDoubleAction:@selector(browserClick:)];
- browser = anObject;
- return self;
- }
-
- - windowWillClose:sender
- {
- [self free];
- [win setDelegate:nil];
- return (id) 1;
- }
-
- - clearText
- {
- [text setText:""];
- [text display];
- return self;
- }
-
- - appendToText:(const char *)aString
- {
- int currentLength = [text textLength];
- [text setSel:currentLength :currentLength];
- [text replaceSel:aString];
- [text scrollSelToVisible];
-
- return self;
- }
- @end
-
- @implementation StoreManager
-
- - init
- {
- [super init];
- blocks = [[List alloc] init];
- return self;
- }
-
- - add:sender
- {
- unsigned int newBlock;
- DataWrapper *aWrapper = [[DataWrapper alloc] init];
-
- /*
- * get the values from the keyForm
- */
- [aWrapper setKey:[[keyForm cellAt:0 :0] stringValue]];
- [aWrapper setValue:[[keyForm cellAt:1 :0] intValue]];
-
- /*
- * get a new object and store it -- also update the list object
- * initial size doesn't matter; size will be adjusted &CAeeded when
- * the wrapper is archived
- */
- if ([storeFile createBlock:&newBlock ofSize:1]) {
- IXWriteRootObjectToStore(storeFile, newBlock, aWrapper);
- [storeFile closeBlock:newBlock];
-
- /*
- * we will reuse aWrapper as an auxilliary.
- * also store the list of blocks.
- */
- [aWrapper setValue:newBlock];
- [blocks addObject:aWrapper];
- IXWriteRootObjectToStore(storeFile, 1, blocks);
- [win setDocEdited:YES];
- [browser loadColumnZero];
- } else {
- NXRunAlertPanel([NXApp appName],
- "Add operation failed", "OK", NULL, NULL);
- return nil;
- }
-
- [keyForm selectTextAt:0 :0];
- return self;
- }
-
- - delete:sender
- {
- unsigned int num = [[browser matrixInColumn:0] selectedRow];
- DataWrapper *aWrapper = [blocks objectAt:num];
-
- if (!aWrapper) {
- NXRunAlertPanel([NXApp appName],
- "You must select a row to delete", "OK", NULL, NULL);
- return nil;
- }
-
- [blocks removeObjectAt:num];
- [storeFile freeBlock:(unsigned int)[aWrapper value]];
- IXWriteRootObjectToStore(storeFile, 1, blocks);
- [aWrapper free];
- [browser loadColumnZero];
- return self;
- }
-
- /*
- * Verify the first twenty blocks...
- */
- - verify:sender
- {
- BOOL found;
- unsigned int size;
- unsigned int i, cnt;
- char buffer[512];
-
- [self clearText];
- [self appendToText:"VERIFYING FIRST TWENTY ENTRIES\n"];
- for (i = 0; i < 20; i++) {
- NX_DURING
- if (size = [storeFile sizeOfBlock:i]) {
- /*
- * block exists... does it exist in blocks?
- */
- int count = [blocks count];
- for (cnt=0, found = NO; cnt < count; cnt++) {
- if ([[blocks objectAt:cnt] value] == i) {
- /* block found */
- found = YES;
- sprintf(buffer,
- "Block %u exists - found in list; size:%u\n", i, size);
- [self appendToText:buffer];
- break;
- }
- }
-
- if (found == NO) {
- DataWrapper *aWrapper;
- if (i == 1) {
- /* This is the boot block */
- sprintf(buffer,
- "Block 1 is the boot block; size:%u\n", size);
- [self appendToText:buffer];
- } else {
- aWrapper = (DataWrapper *)
- IXReadObjectFromStore(storeFile, i, [NXApp zone]);
- [storeFile closeBlock:i];
- sprintf(buffer,
- "Block %u exists - not in list; key=\"%s\" value=%d size:%u\n",
- i, [aWrapper key], [aWrapper value], size);
- [self appendToText:buffer];
- [aWrapper free];
- }
- }
- }&CB_HANDLER
- /*
- * If this were a multi-threaded application we should check
- * the exception code, to see if indeed the block does not exist.
- * Since it is single-threaded, it only raises the exception if
- * the block does not exist...
- */
- sprintf(buffer, "Block %u does not exist *****\n", i);
- [self appendToText:buffer];
- NX_ENDHANDLER
- }
-
- return self;
- }
-
- - refresh:sender
- {
- [browser loadColumnZero];
- return self;
- }
-
- - replace:sender
- {
- const char *str;
- int block, value;
- DataWrapper *aWrapper = [[DataWrapper alloc] init];
-
- str = [[[browser matrixInColumn:0] selectedCell] stringValue];
- if (!str) {
- NXRunAlertPanel([NXApp appName],
- "You must select a row to replace", "OK", NULL, NULL);
- return nil;
- }
-
- sscanf(str, "%8d\t%8d", &block, &value);
-
- [aWrapper setKey:[[keyForm cellAt:0 :0] stringValue]];
- [aWrapper setValue:[[keyForm cellAt:1 :0] intValue]];
-
- IXWriteRootObjectToStore(storeFile, (unsigned int)block, aWrapper);
- [storeFile closeBlock:block];
-
- [[blocks objectAt:[[browser matrixInColumn:0] selectedRow]]
- setKey:[aWrapper key]];
- [aWrapper free];
-
- /*
- * also write the list of blocks...
- */
- IXWriteRootObjectToStore(storeFile, 1, blocks);
- [browser loadColumnZero];
- return self;
- }
-
- - new:sender
- {
- unsigned int blockHandle;
-
- /*
- * force it to create a storeFile
- */
- [self saveAs:self];
- if (!storeFile) {
- NXRunAlertPanel([NXApp appName],
- "Cannot create a new IXStoreFile", "OK", NULL, NULL);
- return nil;
- }
-
- /*
- * the first block that we allocate is always block 1, and we use this as
- * our boot block. In this case, it is a bare bones example, and we will
- * use the boot block to store the list blocks which enumerate the blocks
- * we have allocated so far. The list is kept consistent with the store.
- */
- if (![storeFile createBlock:&blockHandle ofSize:1]) {
- /* could not get a handle */
- NXRunAlertPanel([NXApp appName],
- "Cannot create the boot block", "OK", NULL, NULL);
- [storeFile free];
- return nil;
- }
-
- /*
- * At this point, we don't care to do anything else... we have opened
- * a store, allocated block 1 (which we will use as our boot block),
- * and we have created a List (not yet associated with the boot block).
- */
-
- if (![self loadNib]) {
- NXRunAlertPanel([NXApp appName],
- "Cannot load the store file", "OK", NULL, NULL);
- return nil;
- }
-
- [win setTitle:[storeFile filename]];
- &C7owser loadColumnZero];
- return self;
- }
-
- char *storeFileTypes[] = { "store", 0 };
-
- - open:sender
- {
- id openPanel = [OpenPanel new];
-
- if ([openPanel runModalForTypes:storeFileTypes]) {
- storeFile = [[IXStoreFile alloc]
- initFromFile:[openPanel filename] forWriting:YES];
- if (!storeFile) {
- NXRunAlertPanel([NXApp appName],
- "Cannot open the IXStoreFile", "OK", NULL, NULL);
- return [self free];
- }
- }
-
- /*
- * load the blocks list from the boot block
- */
- blocks = (List *) IXReadObjectFromStore(storeFile, 1, [NXApp zone]);
-
- [self loadNib];
- [win setTitle:[storeFile filename]];
- [browser loadColumnZero];
- return self;
- }
-
- - saveAs:sender
- {
- id savePanel = [SavePanel new];
-
- [savePanel setRequiredFileType:"store"];
- if (![savePanel runModalForDirectory:"." file:"testfile.store"]) {
- NXRunAlertPanel([NXApp appName],
- "You must save to create a new IXStoreFile", "OK", NULL, NULL);
- return nil;
- }
-
- storeFile = [[IXStoreFile alloc] initWithFile:[savePanel filename]];
- return self;
- }
-
- - free
- {
- [blocks free];
- [storeFile commitTransaction];
- [storeFile free];
- return [super free];
- }
-
- @end
-
-