home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / NeoIntroTCL3.0 folder / TCL / NeoDemo / Source / CNDImage.cp < prev    next >
Encoding:
Text File  |  1994-09-16  |  11.7 KB  |  404 lines  |  [TEXT/KAHL]

  1. /****
  2.  * CNDImage.cp
  3.  *
  4.  *    Methods for a persistent image type.
  5.  *
  6.  *  Copyright © 1992 NeoLogic Systems.  All rights reserved.
  7.  *
  8.  ****/
  9.  
  10. #include "NeoTypes.h"
  11. #include CNeoStreamH
  12. #include CNeoMetaClassH
  13. #include CNeoNodeH
  14. #include CNeoDatabaseH
  15. #include "CNDImage.h"
  16. #include "CNDCamera.h"
  17.  
  18. #ifndef NeoInherited
  19. #define NeoInherited    CNeoBlob
  20. #endif
  21.  
  22. CNDImage::CNDImage(void)
  23. {
  24.     fExposure = 0;
  25.     fFilm = 0;
  26.     fFocal = 0;
  27.     fFStop = 0;
  28.     fCamera = 0;
  29.     fKeyCount = 0;
  30.     fName[0] = 0;
  31.     fBy[0] = 0;
  32.     fDate[0] = 0;
  33.     fCatalog[0] = 0;
  34. }
  35.  
  36. /*
  37.  * Overriding this virtual method from the parent is an optimization which allows us
  38.  * to avoid calling GetHandleSize().
  39.  */
  40. #pragma segment NeoInfo
  41. long CNDImage::getLength(void) const
  42. {
  43.     return kNDImageLength;
  44. }
  45.  
  46. /*
  47.  * This method returns the amount of file space the object occupies in the file. It
  48.  * differs from the getLength() in that getLength returns the size of the object in
  49.  * memory.
  50.  */
  51. #pragma segment NeoInfo
  52. long CNDImage::getFileLength(void) const
  53. {
  54.     return kNDImageFileLength;
  55. }
  56.  
  57. /* ****************************************************************** */
  58.                         /** I/O Methods **/
  59. /* ****************************************************************** */
  60.  
  61. /*
  62.  * The readObject method is used to read in the permanent data members of the
  63.  * object from the given stream. In most cases, this method operates without concern
  64.  * for the type of stream the data values are coming from. As a result, this method
  65.  * is capable of reading from such diverse sources as the data fork of a file, a
  66.  * resource fork, an AppleEvent, the clipboard, a memory block, and so on.
  67.  *
  68.  * The aTag argument indicates how much information to read from the stream.
  69.  * It is sometimes sufficient to read in a minimum amount of data and have all
  70.  * other data be read in on demand. Other times it is necessary to read all the
  71.  * data immediately as the stream may not be available later.
  72.  *
  73.  * The two tag values that are currently used are kNeoObjectTag and kNeoAllTag.
  74.  *
  75.  * The value kNeoObjectTag means that only those values of immediate interest
  76.  * need to be read from the stream, though implementations of readObject may read
  77.  * in additional data member values if they wish.
  78.  *
  79.  * The value kNeoAllTag indicates that all data member values for this class
  80.  * should be read in to the stream.
  81.  */
  82. #pragma segment NeoRead
  83. void CNDImage::readObject(CNeoStream *aStream, const NeoTag aTag)
  84. {
  85.     short    index;
  86.  
  87.     NeoInherited::readObject(aStream, 'PICT');
  88.  
  89.     fExposure = aStream->readShort(pImageExposure);
  90.     fFilm = aStream->readShort(pImageFilm);
  91.     fFocal = aStream->readShort(pImageFocal);
  92.     fFStop = aStream->readShort(pImageFStop);
  93.     fCamera = aStream->readLong(pImageCamera);
  94.     fKeyCount = aStream->readShort(pImageKeyCount);
  95.     if (fKeyCount) {
  96.         aStream->openList(pImageKeys);
  97.         for (index = 0; index < fKeyCount; index++)
  98.             aStream->readString(fKeys[index], 33);
  99.         aStream->closeList();
  100.         if (index < kKeywords)
  101.             fKeys[index][0] = 0;            // set last key to null
  102.     }
  103.     aStream->readNativeString(fName, sizeof(fName), pName);
  104.     aStream->readNativeString(fBy, sizeof(fBy), pImageBy);
  105.     aStream->readNativeString(fDate, sizeof(fDate), pImageDate);
  106.     aStream->readNativeString(fCatalog, sizeof(fCatalog), pImageCatalog);
  107. }
  108.  
  109. /*
  110.  * The writeObject method is used to write to the permanent data members of the
  111.  * object from the given stream. In most cases, this method operates without concern
  112.  * for the type of stream the data values are coming from. As a result, this method
  113.  * is capable of writing to such diverse sources as the data fork of a file, a
  114.  * resource fork, an AppleEvent, the clipboard, a memory block, and so on.
  115.  *
  116.  * The aTag argument indicates how much information to write to the stream.
  117.  * It is sometimes sufficient to write out only those parts that are dirty. Other
  118.  * times it is necessary to write all the data, as when doing Save As operation
  119.  * or when communicating an object's complete state across and RPC channel.
  120.  *
  121.  * The two tag values that are currently used are kNeoObjectTag and kNeoAllTag.
  122.  *
  123.  * The value kNeoObjectTag means that only those values of immediate interest
  124.  * need to be written to the stream, though implementations of writeObject may
  125.  * write out additional data member values if they wish.
  126.  *
  127.  * The value kNeoAllTag indicates that all data member values for this class
  128.  * should be writen out to the stream.
  129.  */
  130. #pragma segment NeoWrite
  131. void CNDImage::writeObject(CNeoStream *aStream, const NeoTag aTag)
  132. {
  133.     short            index;
  134.     CNDCamera *        camera;
  135.  
  136.     NeoInherited::writeObject(aStream, 'PICT');
  137.  
  138.     aStream->writeShort(fExposure, pImageExposure);
  139.     aStream->writeShort(fFilm, pImageFilm);
  140.     aStream->writeShort(fFocal, pImageFocal);
  141.     aStream->writeShort(fFStop, pImageFStop);
  142.     aStream->writeLong(fCamera, pImageCamera);
  143.     aStream->writeShort(fKeyCount, pImageKeyCount);
  144.     if (fKeyCount) {
  145.         aStream->openList(pImageKeys);
  146.         for (index = 0; index < fKeyCount; index++)
  147.             aStream->writeString(fKeys[index], 33);
  148.         aStream->closeList();
  149.     }
  150.     aStream->writeNativeString(fName, sizeof(fName), pName);
  151.     aStream->writeNativeString(fBy, sizeof(fBy), pImageBy);
  152.     aStream->writeNativeString(fDate, sizeof(fDate), pImageDate);
  153.     aStream->writeNativeString(fCatalog, sizeof(fCatalog), pImageCatalog);
  154.  
  155.     // If they asked for the camera explicitly, then send the camera object
  156.     if (aTag == cCamera) {
  157.         camera = getCamera();
  158.         if (camera) {
  159.             camera->writeObject(aStream, aTag);
  160.             camera->unrefer();
  161.         }
  162.     }
  163. }
  164.  
  165.                         /** Search Methods **/
  166. /*
  167.  * Once an object is made permanent it can continue be treated like any other object,
  168.  * including being disposed of. While disposing of an object involves elliminating a
  169.  * reference to it (and in the process, deleting it from memory), disposing does not
  170.  * affect object's permanent state in the file.
  171.  *
  172.  * Locating a permanent object in a file is very easy. In order to identify the
  173.  * object (or objects) of interest its class and identity must be given. FindByID()
  174.  * is also capable of using the specified class as a base class so that it and all
  175.  * subclasses of the base class is searched to locate the object. If the given
  176.  * identity is ambiguous, then the search may find more than one object. Passing
  177.  * FindByID() an array will allow this function to return a list of all objects
  178.  * found.
  179.  */
  180. #pragma segment NeoSearch
  181. CNDImage *CNDImage::FindByName(CNeoDatabase *aDataBase, const NeoID aClassID, const CNeoString &aName, const Boolean aDeeply, NeoTestFunc1 aFunc, void *aParam, const NeoLockType aLock)
  182. {
  183.     CNeoNameSelect    key(aName);
  184.     CNDImage *        image;
  185.  
  186.     image = (CNDImage *)aDataBase->findObject(aClassID, &key, aDeeply, aFunc, aParam, aLock);
  187.  
  188.     return image;
  189. }
  190.  
  191. /*
  192.  * This function is applied to images that match a given selection criteria.
  193.  * It adds the ID of the image to the specified array.
  194.  */
  195. void *CNDImage::GetImageID(CNeoNode *aNode, const short aIndex, const NeoLockType aLock, void *aParam)
  196. {
  197.     CNDImage *    image;
  198.  
  199.     if (aIndex < 0)
  200.         image = (CNDImage *)aNode;
  201.     else
  202.         NeoFailNil(image = (CNDImage *)aNode->getObject(aIndex));
  203.  
  204.     ((CArray *)aParam)->InsertAtIndex(&(image->fID), ((CArray *)aParam)->numItems +1);
  205.  
  206.     return 0;
  207. }
  208.  
  209. /* Return a keyword select key that matches the specified keyword value.
  210.  */
  211. CNeoKeywordSelect *CNDImage::GetKeywordKey(char *aKeyword)
  212. {
  213.     short                index;
  214.     char                keyword[33];
  215.     CNeoKeywordSelect *    key;
  216.  
  217.     /* Translate the keyword to lower case */
  218.     for (index = 0; aKeyword[index]; index++)
  219.         if (aKeyword[index] >= 'A' &&
  220.             aKeyword[index] <= 'Z')
  221.             keyword[index] = aKeyword[index] +32;
  222.         else
  223.             keyword[index] = aKeyword[index];
  224.     keyword[index] = 0;
  225.  
  226.     NeoFailNil(key = new CNeoKeywordSelect(keyword));
  227.  
  228.     return key;
  229. }
  230.  
  231. /*
  232.  * The getValue method can be used to obtain the value of a data member of an
  233.  * object. The aName argument is a tag which identifies the data member, and aType
  234.  * refers to the format in which the value is to be returned. Finally, aValue is a
  235.  * pointer to a buffer into which the value should be returned.
  236.  */
  237. #pragma segment NeoSearch
  238. OSErr CNDImage::getValue(const NeoTag aName, const NeoTag aType, void *aValue)
  239. {
  240.     OSErr    err    = noErr;
  241.  
  242.     switch (aName) {
  243.     case pImageKeys:
  244.         NeoAssert(aType == kNeoStringType);
  245.         *(keyArrayPtr *)aValue = &fKeys;
  246.         break;
  247.  
  248.     default:
  249.         err = NeoInherited::getValue(aName, aType, aValue);
  250.     }
  251.  
  252.     return err;
  253. }
  254.  
  255. void CNDImage::draw(Rect *aRect)
  256. {
  257.     // Null Method
  258. }
  259.  
  260. CNDCamera *CNDImage::getCamera(void)
  261. {
  262.     CNDCamera *    camera    = nil;
  263.  
  264.     if (fCamera)
  265.         camera = (CNDCamera *)CNeoPersist::FindByID(gNeoDatabase, kNDCameraID, fCamera, FALSE);
  266.  
  267.     return camera;
  268. }
  269.  
  270. void CNDImage::buildKeyWordStr(char *aString)    /* construct single string from keywords array */
  271. {
  272.     int    index;
  273.  
  274.     aString[0] = 0;
  275.  
  276.     if(!fKeyCount)
  277.         return;
  278.  
  279.     for (index = 0; index < fKeyCount; index++) {
  280.         if(index)
  281.             strcat(aString , ", ");        /* separate strings with a comma */
  282.         strcat(aString, fKeys[index]);
  283.     }
  284. }
  285.  
  286.  
  287. /* parse comma delimited keywords string */
  288. void CNDImage::parseKeywords(char *str)
  289. {
  290.     int        i, j, kwIndex = 0;
  291.     char    ch;
  292.  
  293.     for (i = 0; i < kKeywords; i++) {
  294.         if (!str[kwIndex])                        /* don't go past end of valid characters */
  295.             break;
  296.         for (j = 0; j < 32; j++) {
  297.             if (!str[kwIndex])                    /* don't go past end of valid characters */
  298.                 break;
  299.             ch = str[kwIndex++];
  300.             if (ch == ',') {                    /* keys are comma delimited */
  301.                 for (; j >= 0; j--)                /* trim trailing spaces */
  302.                     if (fKeys[i][j -1] != ' ')
  303.                         break;
  304.                 while((str[kwIndex] == ' ') &&
  305.                     str[kwIndex])                  /* trim leading spaces */
  306.                     kwIndex++;
  307.                 break;
  308.             }
  309.             else
  310.                 fKeys[i][j] = ch;
  311.         }
  312.         fKeys[i][j] = 0;                        /* zero terminated string */
  313.     }
  314.     fKeyCount = i;
  315.     if (fKeyCount < kKeywords)
  316.         fKeys[fKeyCount][0] = 0;                /* set last key to null */
  317. }
  318.  
  319. /* *****************************    CNeoKeywordSelect    **************************** */
  320.  
  321. /* ****************************************************************** */
  322.                         /** Instance Methods **/
  323. /* ****************************************************************** */
  324. CNeoKeywordSelect::CNeoKeywordSelect(const char *aKeyword)
  325.     : CNeoTypeSelect(pImageKeys)
  326. {
  327.     setKeyword(aKeyword);
  328. }
  329.  
  330. /*
  331.  * While locating an object based on its fID value is the default way of
  332.  * identifying an object, many other application-specific search criteria can
  333.  * also be used.
  334.  *
  335.  * Compare the order of this object against the given key.
  336.  *
  337.  * This function should return one of the following;
  338.  *    kNeoLow        - if the key refers to an object after the given one,
  339.  *    kNeoExact    - if the key refers to the given object, or
  340.  *    kNeoHigh    - if the key refers to an object before the given one.
  341.  */
  342. #pragma segment NeoSearch
  343. NeoOrder CNeoKeywordSelect::compare(CNeoPersist *aObject, const short aIndex, NeoOrder *aKeyOrder) const
  344. {
  345.     short            index;
  346.     short            j;
  347.     NeoOrder        order;
  348.     keyArrayPtr        value;
  349.     char *            ptr;
  350.     char            word[33];
  351.     CNDImage *        image;
  352.  
  353.     if (fValue[0]) {
  354.         if (aIndex < 0)
  355.             aObject->getValue(fSelectType, kNeoStringType, &value);
  356.         else
  357.             ((CNeoNode *)aObject)->getEntryValue(aIndex, fSelectType, kNeoStringType, &value);
  358.  
  359.         order = kNeoLow;
  360.         ptr = value[0][0];
  361.         for (index = 0; index < kKeywords; index++) {
  362.             /* Translate the keyword to lower case */
  363.             if (ptr[0] == 0)
  364.                 break;
  365.             for (j = 0; ptr[j]; j++)
  366.                 if (ptr[j] >= 'A' &&
  367.                     ptr[j] <= 'Z')
  368.                     word[j] = ptr[j] +32;
  369.                 else
  370.                     word[j] = ptr[j];
  371.             word[j] = 0;
  372.             ptr += 33;
  373.             if (Neostrncmp(word, fValue, 32L) == 0) {
  374.                 order = kNeoExact;
  375.                 break;
  376.             }
  377.         }
  378.  
  379.         if (fOrder != kNeoExact &&
  380.             (fOrder&order))
  381.             order = kNeoExact;
  382.     }
  383.     else
  384.         order = kNeoExact;
  385.  
  386.     *aKeyOrder = order;
  387.  
  388.     return *aKeyOrder;
  389. }
  390.  
  391. /* ****************************************************************** */
  392.                         /** Accessing Methods **/
  393. /* ****************************************************************** */
  394. void CNeoKeywordSelect::getKeyword(char *aKeyword) const
  395. {
  396.     NeoBlockMove(fValue, aKeyword, strlen(fValue) +1);
  397. }
  398.  
  399. void CNeoKeywordSelect::setKeyword(const char *aKeyword)
  400. {
  401.     NeoBlockMove(aKeyword, fValue, strlen(aKeyword) +1);
  402. }
  403.  
  404.