home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.0 / NeXTSTEP3.0.iso / NextDeveloper / Examples / IndexingKit / StoreFile / StoreManager.m < prev   
Text File  |  1992-07-19  |  10KB  |  404 lines

  1. /*
  2. StoreManager.m - Copyright (c) 1992 NeXT Computer, Inc.
  3.  
  4. You may freely copy, distribute and reuse the code in this example.
  5. NeXT Computer, Inc. disclaims any warranty of any kind, expressed or implied, 
  6. as to its fitness for any particular use.
  7. */
  8.  
  9. #import <appkit/appkit.h>
  10. #import <sys/param.h>
  11. #import <bsd/libc.h>
  12. #import <objc/NXBundle.h>
  13. #import <store/IXStoreBlock.h>
  14. #import "DataWrapper.h"
  15. #import "StoreManager.h"
  16.  
  17. @interface StoreManager(Private)
  18.  
  19. - loadNib;
  20. - (int)browser:sender fillMatrix:matrix inColumn:(int)column;
  21. - browserClick:sender;
  22. - setBrowser:anObject;
  23. - windowWillClose:sender;
  24. - clearText;
  25. - appendToText:(const char *)aString;
  26.  
  27. @end
  28.  
  29. @implementation StoreManager(Private)
  30. - loadNib
  31. {
  32.     char buf[MAXPATHLEN+1];
  33.     NXBundle *aBundle = [NXBundle bundleForClass:[self class]];
  34.  
  35.     if ([aBundle getPath:buf forResource:"StoreManager" ofType:"nib"]) {
  36.      if ([NXApp loadNibFile:buf owner:self 
  37.     withNames:NO fromZone:[NXApp zone]]) {
  38.     [win makeKeyAndOrderFront:self];
  39.     [win setDelegate:self];
  40.     return self;
  41.      }
  42.     }
  43.  
  44.     return nil;
  45. }
  46.  
  47. - (int)browser:sender fillMatrix:matrix inColumn:(int)column
  48. {
  49.     int     row;
  50.     id        cell;
  51.     char    str[512]&C@  int        cnt = [blocks count];
  52.  
  53.     for (row=0; row < cnt; row++) {
  54.     int        theValue;
  55.     DataWrapper    *aWrapper;
  56.     unsigned int    blockNum;
  57.     
  58.     blockNum = (unsigned int) [[blocks objectAt:row] value];
  59.     aWrapper = (DataWrapper *) 
  60.         IXReadObjectFromStore(storeFile, blockNum, [NXApp zone]);
  61.     [storeFile closeBlock:blockNum]; // not required for single context
  62.     theValue = [aWrapper value];
  63.     [aWrapper free];
  64.     
  65.     cell = [matrix cellAt:row :0];
  66.     if (cell == nil) {
  67.         [matrix insertRowAt:row];
  68.         cell = [matrix cellAt:row :0];
  69.     }
  70.     
  71.     sprintf(str, "%8d\t%8d\t%s",
  72.         [[blocks objectAt:row] value],
  73.         theValue,
  74.         [[blocks objectAt:row] key]);
  75.     [cell setStringValue:str];
  76.     [cell setLoaded:YES];
  77.     [cell setLeaf:YES];
  78.     }
  79.  
  80.     return row;
  81. }
  82.  
  83. - browserClick:sender
  84. {
  85.     int     row;
  86.     const char *str;
  87.     int        block, value;
  88.     const char    *key;
  89.  
  90.     str = [[[browser matrixInColumn:0] selectedCell] stringValue];
  91.     row = [[browser matrixInColumn:0] selectedRow];
  92.     sscanf(str, "%8d\t%8d", &block, &value);
  93.     /*
  94.     * the key starts at the first char after the first two tabs
  95.     */
  96.     key = [[blocks objectAt:row] key];
  97.  
  98.     [[keyForm cellAt:0 :0] setStringValue:key];
  99.     [[keyForm cellAt:1 :0] setIntValue:value];
  100.  
  101.     return self;
  102. }
  103.  
  104. - setBrowser:anObject
  105. {
  106.     [anObject setTarget:self];
  107.     [anObject setAction:@selector(browserClick:)];
  108.     [anObject setDoubleAction:@selector(browserClick:)];
  109.     browser = anObject;
  110.     return self;
  111. }
  112.  
  113. - windowWillClose:sender
  114. {
  115.     [self free];
  116.     [win setDelegate:nil];
  117.     return (id) 1;
  118. }
  119.  
  120. - clearText
  121. {
  122.     [text setText:""];
  123.     [text display];
  124.     return self;
  125. }
  126.  
  127. - appendToText:(const char *)aString
  128. {
  129.     int currentLength = [text textLength];
  130.     [text setSel:currentLength :currentLength];
  131.     [text replaceSel:aString];
  132.     [text scrollSelToVisible];
  133.  
  134.     return self;
  135. }
  136. @end
  137.  
  138. @implementation StoreManager
  139.  
  140. - init
  141. {
  142.     [super init];
  143.     blocks = [[List alloc] init];
  144.     return self;
  145. }
  146.  
  147. - add:sender
  148. {
  149.     unsigned int    newBlock;
  150.     DataWrapper        *aWrapper = [[DataWrapper alloc] init];
  151.  
  152.     /*
  153.     * get the values from the keyForm
  154.     */
  155.     [aWrapper setKey:[[keyForm cellAt:0 :0] stringValue]];
  156.     [aWrapper setValue:[[keyForm cellAt:1 :0] intValue]];
  157.  
  158.     /*
  159.     * get a new object and store it -- also update the list object
  160.     * initial size doesn't matter; size will be adjusted &CAeeded when
  161.     * the wrapper is archived
  162.     */
  163.     if ([storeFile createBlock:&newBlock ofSize:1]) {
  164.     IXWriteRootObjectToStore(storeFile, newBlock, aWrapper);
  165.     [storeFile closeBlock:newBlock];
  166.     
  167.     /*
  168.      * we will reuse aWrapper as an auxilliary. 
  169.      * also store the list of blocks.
  170.      */
  171.     [aWrapper setValue:newBlock];
  172.     [blocks addObject:aWrapper];
  173.     IXWriteRootObjectToStore(storeFile, 1, blocks);
  174.     [win setDocEdited:YES];
  175.     [browser loadColumnZero];
  176.     } else {
  177.     NXRunAlertPanel([NXApp appName], 
  178.         "Add operation failed", "OK", NULL, NULL);
  179.     return nil;
  180.     }
  181.  
  182.     [keyForm selectTextAt:0 :0];
  183.     return self;
  184. }
  185.  
  186. - delete:sender
  187. {
  188.     unsigned int num = [[browser matrixInColumn:0] selectedRow];
  189.     DataWrapper *aWrapper = [blocks objectAt:num];
  190.  
  191.     if (!aWrapper) {
  192.     NXRunAlertPanel([NXApp appName],
  193.     "You must select a row to delete", "OK", NULL, NULL);
  194.     return nil;
  195.     }
  196.  
  197.     [blocks removeObjectAt:num];
  198.     [storeFile freeBlock:(unsigned int)[aWrapper value]];
  199.     IXWriteRootObjectToStore(storeFile, 1, blocks);
  200.     [aWrapper free];
  201.     [browser loadColumnZero];
  202.     return self;
  203. }
  204.  
  205. /*
  206.  * Verify the first twenty blocks...
  207.  */
  208. - verify:sender
  209. {
  210.     BOOL            found;
  211.     unsigned int        size;
  212.     unsigned int        i, cnt;
  213.     char            buffer[512];
  214.     
  215.     [self clearText];
  216.     [self appendToText:"VERIFYING FIRST TWENTY ENTRIES\n"];
  217.     for (i = 0; i < 20; i++) {
  218.     NX_DURING
  219.     if (size = [storeFile sizeOfBlock:i]) {
  220.         /*
  221.          * block exists... does it exist in blocks?
  222.          */
  223.         int count = [blocks count];
  224.         for (cnt=0, found = NO; cnt < count; cnt++) {
  225.         if ([[blocks objectAt:cnt] value] == i) {
  226.             /* block found */
  227.             found = YES;
  228.             sprintf(buffer,
  229.             "Block %u exists - found in list; size:%u\n", i, size);
  230.             [self appendToText:buffer];
  231.             break;
  232.         }
  233.         }
  234.     
  235.         if (found == NO) {
  236.         DataWrapper *aWrapper;
  237.         if (i == 1) {
  238.             /* This is the boot block */
  239.             sprintf(buffer,
  240.             "Block 1 is the boot block; size:%u\n", size);
  241.             [self appendToText:buffer];
  242.         } else {
  243.             aWrapper = (DataWrapper *) 
  244.             IXReadObjectFromStore(storeFile, i, [NXApp zone]);
  245.             [storeFile closeBlock:i];
  246.             sprintf(buffer, 
  247.             "Block %u exists - not in list; key=\"%s\" value=%d size:%u\n",
  248.             i, [aWrapper key], [aWrapper value], size);
  249.             [self appendToText:buffer];
  250.             [aWrapper free];
  251.         }
  252.         }
  253.     }&CB_HANDLER
  254.         /*
  255.          * If this were a multi-threaded application we should check
  256.          * the exception code, to see if indeed the block does not exist.
  257.          * Since it is single-threaded, it only raises the exception if
  258.          * the block does not exist...
  259.          */
  260.         sprintf(buffer, "Block %u does not exist *****\n", i);
  261.         [self appendToText:buffer];
  262.     NX_ENDHANDLER
  263.     }
  264.     
  265.     return self;
  266. }
  267.  
  268. - refresh:sender
  269. {
  270.     [browser loadColumnZero];
  271.     return self;
  272. }
  273.  
  274. - replace:sender
  275. {
  276.     const char    *str;
  277.     int        block, value;
  278.     DataWrapper    *aWrapper = [[DataWrapper alloc] init];
  279.     
  280.     str = [[[browser matrixInColumn:0] selectedCell] stringValue];
  281.     if (!str) {
  282.     NXRunAlertPanel([NXApp appName],
  283.         "You must select a row to replace", "OK", NULL, NULL);
  284.     return nil;
  285.     }
  286.  
  287.     sscanf(str, "%8d\t%8d", &block, &value);
  288.     
  289.     [aWrapper setKey:[[keyForm cellAt:0 :0] stringValue]];
  290.     [aWrapper setValue:[[keyForm cellAt:1 :0] intValue]];
  291.  
  292.     IXWriteRootObjectToStore(storeFile, (unsigned int)block, aWrapper);
  293.     [storeFile closeBlock:block];
  294.     
  295.     [[blocks objectAt:[[browser matrixInColumn:0] selectedRow]]
  296.     setKey:[aWrapper key]];
  297.     [aWrapper free];
  298.  
  299.     /*
  300.     * also write the list of blocks...
  301.     */
  302.     IXWriteRootObjectToStore(storeFile, 1, blocks);      
  303.     [browser loadColumnZero];
  304.     return self;
  305. }
  306.  
  307. - new:sender
  308. {
  309.     unsigned int    blockHandle;
  310.     
  311.     /*
  312.     * force it to create a storeFile
  313.     */
  314.     [self saveAs:self];
  315.     if (!storeFile) {
  316.     NXRunAlertPanel([NXApp appName],
  317.         "Cannot create a new IXStoreFile", "OK", NULL, NULL);
  318.     return nil;
  319.     }
  320.     
  321.     /*
  322.     * the first block that we allocate is always block 1, and we use this as
  323.     * our boot block. In this case, it is a bare bones example, and we will
  324.     * use the boot block to store the list blocks which enumerate the blocks
  325.     * we have allocated so far. The list is kept consistent with the store.
  326.     */
  327.     if (![storeFile createBlock:&blockHandle ofSize:1]) {
  328.     /* could not get a handle */
  329.     NXRunAlertPanel([NXApp appName],
  330.         "Cannot create the boot block", "OK", NULL, NULL);
  331.     [storeFile free];
  332.     return nil;
  333.     }
  334.     
  335.     /*
  336.     * At this point, we don't care to do anything else... we have opened
  337.     * a store, allocated block 1 (which we will use as our boot block),
  338.     * and we have created a List (not yet associated with the boot block).
  339.     */
  340.     
  341.     if (![self loadNib]) {
  342.     NXRunAlertPanel([NXApp appName],
  343.         "Cannot load the store file", "OK", NULL, NULL);
  344.     return nil;
  345.     }
  346.     
  347.     [win setTitle:[storeFile filename]];
  348.    &C7owser loadColumnZero];
  349.     return self;
  350. }
  351.  
  352. char *storeFileTypes[] = { "store", 0 };
  353.  
  354. - open:sender
  355. {
  356.     id        openPanel = [OpenPanel new];
  357.     
  358.     if ([openPanel runModalForTypes:storeFileTypes]) {
  359.     storeFile = [[IXStoreFile alloc] 
  360.         initFromFile:[openPanel filename] forWriting:YES];
  361.     if (!storeFile) {
  362.         NXRunAlertPanel([NXApp appName],
  363.         "Cannot open the IXStoreFile", "OK", NULL, NULL);
  364.         return [self free];
  365.     }
  366.     }
  367.     
  368.     /*
  369.     * load the blocks list from the boot block
  370.     */
  371.     blocks = (List *) IXReadObjectFromStore(storeFile, 1, [NXApp zone]);
  372.     
  373.     [self loadNib];
  374.     [win setTitle:[storeFile filename]];
  375.     [browser loadColumnZero];
  376.     return self;
  377. }
  378.  
  379. - saveAs:sender
  380. {
  381.     id        savePanel = [SavePanel new];
  382.  
  383.     [savePanel setRequiredFileType:"store"];
  384.     if (![savePanel runModalForDirectory:"." file:"testfile.store"]) {
  385.     NXRunAlertPanel([NXApp appName],
  386.         "You must save to create a new IXStoreFile", "OK", NULL, NULL);
  387.     return nil;
  388.     }
  389.  
  390.     storeFile = [[IXStoreFile alloc] initWithFile:[savePanel filename]];
  391.     return self;
  392. }
  393.  
  394. - free
  395. {
  396.     [blocks free];
  397.     [storeFile commitTransaction];
  398.     [storeFile free];
  399.     return [super free];
  400. }
  401.  
  402. @end
  403.  
  404.