home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tv20os2.zip / src / TResourceFile.cpp < prev    next >
C/C++ Source or Header  |  1999-05-19  |  5KB  |  256 lines

  1. /*
  2.  * TResourceFile.cc
  3.  *
  4.  * Turbo Vision - Version 2.0
  5.  *
  6.  * Copyright (c) 1994 by Borland International
  7.  * All Rights Reserved.
  8.  *
  9.  * Modified by Sergio Sigala <ssigala@globalnet.it>
  10.  */
  11.  
  12. #define Uses_TResourceFile
  13. #define Uses_TResourceItem
  14. #define Uses_fpstream
  15. #define Uses_TCollection
  16. #define Uses_TStringCollection
  17. #define Uses_TResourceCollection
  18. #include <tvision/tv.h>
  19. #include <io.h>
  20.  
  21. /*
  22.  * SS: Warning, this file is non-portable.  It is not used by any of the
  23.  * classes in the library.
  24.  */
  25. const long rStreamMagic = 0x52504246uL; // 'FBPR'
  26.  
  27. struct Count_type
  28. {
  29.     ushort lastCount;
  30.     ushort pageCount;
  31. };
  32.  
  33. struct Info_type
  34. {
  35.     ushort infoType;
  36.     long infoSize;
  37. };
  38.  
  39. struct THeader
  40. {
  41.     ushort signature;
  42.     union
  43.         {
  44.         Count_type count;
  45.         Info_type info;
  46.         };
  47. };
  48.  
  49.  
  50. TResourceFile::TResourceFile( fpstream *aStream ) : TObject()
  51. {
  52.     THeader *header;
  53.     int handle;
  54.     int found;
  55.     int repeat;
  56.     long streamSize;
  57.  
  58.     stream = aStream;
  59.     basePos = stream->tellp();
  60.     handle = stream->rdbuf()->fd();
  61.     streamSize = filelength(handle);
  62.     header = new THeader;
  63.     found = 0;
  64.     do {
  65.        repeat = 0;
  66. //       if (basePos <= (streamSize - sizeof(THeader)))    /* XXX */
  67.        if (basePos <= (streamSize - (long)sizeof(THeader))) /* XXX */
  68.            {
  69.            stream->seekg(basePos, ios::beg);
  70.            stream->readBytes(header, sizeof(THeader));
  71.            if (header->signature == 0x5a4d)
  72.                {
  73.                basePos += ((header->count.pageCount * 512L) -
  74.                           (-header->count.lastCount & 511));
  75.                repeat = 1;
  76.                }
  77.            else if (header->signature == 0x4246)
  78.                {
  79.                if (header->info.infoType == 0x5250)
  80.                    found = 1;
  81.                else
  82.                    {
  83.                    basePos +=
  84.                       header->info.infoSize + 16 - (header->info.infoSize)%16;
  85.                    repeat = 1;
  86.                    }
  87.                }
  88.            }
  89.         } while (repeat);
  90.  
  91.     delete header;
  92.  
  93.     if (found)
  94.     {
  95.         stream->seekg(basePos + sizeof(long) * 2, ios::beg);
  96.         *stream >> indexPos;
  97.         stream->seekg(basePos + indexPos, ios::beg);
  98.         *stream >> index;
  99.     }
  100.     else
  101.     {
  102.         indexPos =  sizeof(long) * 3;
  103.         index = new TResourceCollection(0, 8);
  104.     }
  105. }
  106.  
  107. TResourceFile::~TResourceFile()
  108. {
  109.     flush();
  110.     destroy( (TCollection *)index );
  111.     delete stream;
  112. }
  113.  
  114. short TResourceFile::count()
  115. {
  116.     return index->getCount();
  117. }
  118.  
  119. void TResourceFile::remove( const char *key )
  120. {
  121.     int i;
  122.  
  123.     if (index->search( (char *)key, i))
  124.         {
  125.         index->free(index->at(i));
  126.         modified = True;
  127.         }
  128. }
  129.  
  130. void TResourceFile::flush()
  131. {
  132.     long lenRez;
  133.  
  134.     if (modified == True)
  135.     {
  136.         stream->seekp(basePos + indexPos, ios::beg);
  137.         *stream << index;
  138.         lenRez =  stream->tellp() - basePos -  sizeof(long) * 2;
  139.         stream->seekp(basePos, ios::beg);
  140.         *stream << rStreamMagic;
  141.         *stream << lenRez;
  142.         *stream << indexPos;
  143.         stream->flush();
  144.         modified = False;
  145.     }
  146. }
  147.  
  148. void *TResourceFile::get( const char *key)
  149. {
  150.     int i;
  151.     void *p;
  152.  
  153.     if (! index->search((char *)key, i))
  154.         return  0;
  155.     stream->seekg(basePos + ((TResourceItem*)(index->at(i)))->pos, ios::beg);
  156.     *stream >> p;
  157.     return p;
  158. }
  159.  
  160. const char *TResourceFile::keyAt(short i)
  161. {
  162.     return ((TResourceItem*)(index->at(i)))->key;
  163. }
  164.  
  165. void TResourceFile::put(TStreamable *item, const char *key)
  166. {
  167.     int i;
  168.     TResourceItem  *p;
  169.  
  170.     if (index->search( (char *)key, i))
  171.         p = (TResourceItem*)(index->at(i));
  172.     else
  173.     {
  174.         p = new TResourceItem;
  175.         p->key = newStr(key);
  176.         index->atInsert(i, p);
  177.     }
  178.     p->pos =  indexPos;
  179.     stream->seekp(basePos + indexPos, ios::beg);
  180.     *stream << item;
  181.     indexPos = stream->tellp() - basePos;
  182.     p->size  = indexPos - p->pos;
  183.  
  184.     modified = True;
  185. }
  186.  
  187. void copyStream( fpstream* dest, fpstream* src, long n)
  188. {
  189.     const xferSize=256;
  190.  
  191.     char *xferBuf = new char[xferSize];
  192.     size_t thisMove;
  193.  
  194.     while (n > 0)
  195.     {
  196.         if (n > xferSize)
  197.             thisMove = xferSize;
  198.         else
  199.             thisMove = (int)n;
  200.  
  201.         src->readBytes(xferBuf, thisMove);
  202.         dest->writeBytes(xferBuf, thisMove);
  203.         n -= thisMove;
  204.     }
  205.  
  206.     delete xferBuf;
  207. }
  208.  
  209. struct SwitchInfo
  210. {
  211.     fpstream* sourceStream;
  212.     fpstream* destStream;
  213.     long oldBasePos;
  214.     long newBasePos;
  215. };
  216.  
  217. void doCopyResource(void* item, void* arg)
  218. {
  219.   SwitchInfo* si = (SwitchInfo*)arg;
  220.  
  221.   si->sourceStream->seekg(si->oldBasePos + ((TResourceItem*)item)->pos);
  222.   ((TResourceItem*)item)->pos = si->destStream->tellp() - si->newBasePos;
  223.  
  224.   copyStream( si->destStream, si->sourceStream, ((TResourceItem*)item)->size);
  225. }
  226.  
  227. fpstream* TResourceFile::switchTo( fpstream *aStream, Boolean pack )
  228. {
  229.   SwitchInfo args;
  230.  
  231.   args.newBasePos = aStream->tellp();
  232.   args.oldBasePos = basePos;
  233.  
  234.   if (pack)
  235.   {
  236.        args.sourceStream = stream;
  237.      args.destStream = aStream;
  238.     aStream->seekp( args.newBasePos + sizeof(long)*3);
  239.     index->forEach(doCopyResource, &args);
  240.     indexPos = aStream->tellp() - args.newBasePos;
  241.   }
  242.   else
  243.   {
  244.     stream->seekg(basePos);
  245.      copyStream(aStream, stream, indexPos);
  246.   }
  247.  
  248.   modified = True;
  249.   basePos = args.newBasePos;
  250.  
  251.   fpstream* oldStream = stream;
  252.   stream = aStream;
  253.  
  254.   return oldStream;
  255. }
  256.