home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 11.ddi / OWLSRC.PAK / FILEDOC.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  16.1 KB  |  611 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1993 by Borland International
  3. //   source\owl\filedoc.cpp
  4. //   Implements classes TFileDocument, TFileInStream, TFileOutStream, TFileBuf
  5. //----------------------------------------------------------------------------
  6. #pragma hdrignore SECTION
  7. #include <owl\owlpch.h>
  8. #include <owl\filedoc.h>
  9.  
  10. #if !defined(SECTION) || SECTION == 1
  11.  
  12. //
  13. //  class TFileBuf
  14. //  ----- --------
  15. //
  16. class _OWLCLASS_RTL TFileBuf : public streambuf {
  17.   public:
  18.     enum { shDefault = shReadWrite };  // default file sharing
  19.  
  20.     TFileBuf(int fhdl, int omode, streampos seekpos);
  21.    ~TFileBuf() {}
  22.  
  23.     virtual int overflow(int = EOF);
  24.     virtual int underflow();
  25.     virtual int sync();
  26.     virtual streampos  seekoff(streamoff, ios::seek_dir, int);
  27.  
  28.     int       xfd;       // the file descriptor, EOF if closed
  29.     int       mode;      // the opened mode
  30.     streampos last_seek;
  31.     char      lahead[2]; // current input char if unbuffered
  32. };
  33.  
  34. //
  35. //  class TFileStreamBase
  36. //  ----- ---------------
  37. //
  38. class _OWLCLASS_RTL TFileStreamBase : virtual public ios {
  39.   public:
  40.     TFileStreamBase(int fhdl, int omode, streampos seekpos);
  41.    ~TFileStreamBase() {}
  42.     TFileBuf buf;
  43. };
  44.  
  45. //
  46. //  class TFileInStream
  47. //  ----- -------------
  48. //
  49. class _OWLCLASS_RTL TFileInStream : public TFileStreamBase, public TInStream {
  50.   public:
  51.     TFileInStream(TFileDocument& doc, HFILE fhdl, int omode, streampos seekpos)
  52.                : TInStream (doc,0,omode), TFileStreamBase(fhdl,omode,seekpos){}
  53.    ~TFileInStream();
  54. };
  55.  
  56. //
  57. //  class TFileOutStream
  58. //  ----- --------------
  59. //
  60. class _OWLCLASS_RTL TFileOutStream : public TFileStreamBase, public TOutStream {
  61.   public:
  62.     TFileOutStream(TFileDocument& doc, HFILE fhdl, int omode, streampos seekpos)
  63.               : TOutStream (doc,0,omode), TFileStreamBase(fhdl,omode,seekpos){}
  64.    ~TFileOutStream();
  65. };
  66.  
  67. //
  68. //  class TFileDocument
  69. //  ----- -------------
  70. //
  71.  
  72. HFILE
  73. TFileDocument::OpenThisFile(int omode, LPCSTR name, streampos* pseekpos){
  74.   int how;
  75.   HFILE fhdl;
  76.   BOOL exists = FALSE;
  77.   int share = omode & shMask;
  78.  
  79.   if (share < shCompat)
  80.     share = (omode & ofWrite) ? shRead : shReadWrite;
  81.  
  82.   how = ((unsigned)(share-shCompat)) >> 5;
  83.  
  84.   if (omode & ofWrite) {
  85.     if (!(omode & (ofAtEnd | ofAppend | ofRead)))
  86.       omode |= ofTruncate; // output implies truncate unless in, app, or ate
  87.  
  88.     if (omode & ofRead)
  89.       how |= OF_READWRITE;
  90.     else
  91.       how |= OF_WRITE;
  92.     if (!((omode & ofNoCreate) && !(omode & ofTruncate))) {
  93.       if (!((omode & ofTruncate) && !(omode & (ofNoCreate | ofNoReplace)))) {
  94.         if ((fhdl=::_lopen(name,OF_READ|OF_SHARE_COMPAT))   !=HFILE_ERROR
  95.         ||  (fhdl=::_lopen(name,OF_READ|OF_SHARE_DENY_NONE))!=HFILE_ERROR) {
  96.           ::_lclose(fhdl);
  97.           exists = TRUE;
  98.           }
  99.         }
  100.       if (!(exists && !(omode & (ofNoCreate | ofNoReplace)))) {
  101.         if ((exists && (omode & ofNoReplace))
  102.         || (!exists && (omode & ofNoCreate)) )
  103.             return 0;
  104.         if ((fhdl = _lcreat(name, 0)) == HFILE_ERROR)
  105.             return HFILE_ERROR;
  106.         ::_lclose(fhdl);   // close in order to open with share mode
  107.         }
  108.       }
  109.     }
  110.   else if (omode & ofRead)
  111.     how |= OF_READ;
  112.   else
  113.     return HFILE_ERROR;   // must specfify in, out, or in/out
  114.  
  115.   if ((fhdl = ::_lopen(name, how)) != HFILE_ERROR) {
  116.     if ((*pseekpos = ::_llseek(fhdl, 0L, (omode & (ofAtEnd|ofAppend))
  117.                              ? SEEK_END : SEEK_SET)) == long(HFILE_ERROR)) {
  118.       ::_lclose(fhdl);
  119.       return HFILE_ERROR;
  120.     }
  121.   }
  122. #if defined(__WIN32__)
  123.   FileLength = GetFileSize((HANDLE)fhdl, 0);
  124.   InfoPresent = GetFileTime((HANDLE)fhdl, &FileCreateTime, &FileAccessTime,
  125.                             &FileUpdateTime);
  126. #else
  127.   FileLength = filelength(fhdl);
  128.   getftime(fhdl, (struct ftime*)&FileTime);
  129.   InfoPresent = TRUE;
  130. #endif
  131.   NotifyViews(vnDocOpened,omode);
  132.   return fhdl;
  133. }
  134.  
  135. void
  136. TFileDocument::CloseThisFile(HFILE fhdl, int omode)
  137. {
  138.   if (!IS_PREV_OPEN(omode)) {
  139.     ::_lclose(fhdl);
  140.     NotifyViews(vnDocClosed, omode);
  141.   }
  142. }
  143.  
  144. BOOL
  145. TFileDocument::Open(int omode, LPCSTR path)
  146. {
  147.   long seekpos;
  148.   if (FHdl != HFILE_ERROR)
  149.     return FALSE;    // if already open at document level
  150.   if (path)
  151.     SetDocPath(path);
  152.   if (omode != 0)
  153.     SetOpenMode(omode);
  154.   if ((FHdl = OpenThisFile(GetOpenMode(),GetDocPath(),&seekpos)) == HFILE_ERROR)
  155.     return FALSE;
  156.   return TRUE;
  157. }
  158.  
  159. BOOL
  160. TFileDocument::Open(HFILE fhdl)
  161. {
  162.   SetOpenMode(PREV_OPEN | ofReadWrite);  // can we determine open mode?
  163.   SetDocPath(0); // can we get path name?
  164.   FHdl = fhdl;
  165.   return TRUE;
  166. }
  167.  
  168. BOOL
  169. TFileDocument::Close()
  170. {
  171.   if (!TDocument::Close())     // close all children first
  172.     return FALSE;
  173.   if (FHdl != HFILE_ERROR) {   // if open at document level
  174.     if (TDocument::IsOpen())   // cannot close document if streams open
  175.       return FALSE;       // ?should we close streams here?
  176.     CloseThisFile(FHdl, GetOpenMode());
  177.     FHdl = HFILE_ERROR;
  178.   }
  179.   return TRUE;
  180. }
  181.  
  182. BOOL
  183. TFileDocument::Commit(BOOL force)
  184. {
  185.   if (!TDocument::Commit(force))      // flush views and child docs
  186.     return FALSE;
  187.   SetDirty(FALSE);
  188.   return TRUE;
  189. }
  190.  
  191. BOOL
  192. TFileDocument::Revert(BOOL clear)
  193. {
  194.   if (!TDocument::Revert(clear))
  195.     return FALSE;
  196.   SetDirty(FALSE);
  197.   return TRUE;
  198. }
  199.  
  200. static char* PropNames[] = {
  201.   "Create Time",   // CreateTime 
  202.   "Modify Time",   // ModifyTime
  203.   "Access Time",   // AccessTime
  204.   "Storage Size",  // StorageSize
  205.   "File Handle",   // FileHandle
  206. };
  207.  
  208. static int PropFlags[] = {
  209.   pfGetBinary|pfGetText,   // CreateTime 
  210.   pfGetBinary|pfGetText,   // ModifyTime
  211.   pfGetBinary|pfGetText,   // AccessTime
  212.   pfGetBinary|pfGetText,   // StorageSize
  213.   pfGetBinary,             // FileHandle
  214. };
  215.  
  216. const char*
  217. TFileDocument::PropertyName(int index)
  218. {
  219.   if (index <= PrevProperty)
  220.     return TDocument::PropertyName(index);
  221.   else if (index < NextProperty)
  222.     return PropNames[index-PrevProperty-1];
  223.   else
  224.     return 0;
  225. }
  226.  
  227. int
  228. TFileDocument::PropertyFlags(int index)
  229. {
  230.   if (index <= PrevProperty)
  231.     return TDocument::PropertyFlags(index);
  232.   else if (index < NextProperty)
  233.     return PropFlags[index-PrevProperty-1];
  234.   else
  235.     return 0;
  236. }
  237.  
  238. int
  239. TFileDocument::FindProperty(const char far* name)
  240. {
  241.   int i;
  242.   for (i=0; i < NextProperty-PrevProperty-1; i++)
  243.     if (strcmp(PropNames[i], name) == 0)
  244.       return i+PrevProperty+1;
  245.   return TDocument::FindProperty(name);
  246. }
  247.  
  248. int
  249. TFileDocument::GetProperty(int prop, void far* dest, int textlen)
  250. {
  251.   switch(prop)
  252.   {
  253.     case FileHandle:
  254.       if (textlen)
  255.         return 0;
  256.       *(HFILE FAR*)dest = FHdl;
  257.       return sizeof(FHdl);
  258.     default:
  259.       if (InfoPresent) {
  260.         switch(prop)
  261.         {
  262.           case StorageSize:
  263.             if (!textlen) {
  264.               *(unsigned long FAR*)dest = FileLength;
  265.               return sizeof(FileLength);
  266.             } else {
  267.               char buf[10];
  268.               int len = wsprintf(buf, "%ld", FileLength);
  269.               if (textlen > len)
  270.                 textlen = len;
  271.               memcpy(dest, buf, textlen);
  272.               *((char far*)dest + textlen) = 0;
  273.               return len;
  274.             }
  275. #if defined(__WIN32__)
  276.           case CreateTime:
  277.             return FormatFileTime(&FileCreateTime, dest, textlen);
  278.           case ModifyTime:
  279.             return FormatFileTime(&FileUpdateTime, dest, textlen);
  280.           case AccessTime:
  281.             return FormatFileTime(&FileAccessTime, dest, textlen);
  282. #else  // DOS file system
  283.           case CreateTime:
  284.           case ModifyTime:
  285.           case AccessTime:
  286.           {
  287.             struct date  propdate;
  288.             struct time  proptime;
  289.             propdate.da_year = ((struct ftime*)&FileTime)->ft_year+1980;
  290.             propdate.da_mon  = ((struct ftime*)&FileTime)->ft_month;
  291.             propdate.da_day  = ((struct ftime*)&FileTime)->ft_day;
  292.             proptime.ti_hour = ((struct ftime*)&FileTime)->ft_hour;
  293.             proptime.ti_min  = ((struct ftime*)&FileTime)->ft_min;
  294.             proptime.ti_sec  = ((struct ftime*)&FileTime)->ft_tsec*2;
  295.             proptime.ti_hund = 0;
  296.             return FormatDateTime(propdate, proptime, dest, textlen);
  297.           }
  298. #endif
  299.         }
  300.       }
  301.       return TDocument::GetProperty(prop, dest, textlen);
  302.   }
  303. }
  304.  
  305. BOOL
  306. TFileDocument::SetProperty(int prop, const void far* src)
  307. {
  308.   // file properties currently not settable
  309.   return TDocument::SetProperty(prop, src);
  310. }
  311.  
  312. TInStream*
  313. TFileDocument::InStream(int omode, LPCSTR /* strmId */) 
  314. {
  315.   HFILE fhdl;
  316.   streampos seekpos;
  317.   if (omode == ofParent)
  318.     omode = GetOpenMode();
  319.   if (!(omode & ofRead))
  320.     return 0;
  321.   if ((fhdl = FHdl) == HFILE_ERROR) {   // if file not open at document level
  322.     if ((fhdl=OpenThisFile (omode, GetDocPath(), &seekpos)) == HFILE_ERROR)
  323.       return 0;
  324.   } else {
  325.     omode = GetOpenMode() ? (GetOpenMode() & ~ofBinary) | (omode & ofBinary)
  326.                           : omode;
  327.     omode |= PREV_OPEN;
  328.   }
  329.   return new TFileInStream(*this, fhdl, omode, seekpos);
  330. }
  331.  
  332. TOutStream*
  333. TFileDocument::OutStream(int omode, LPCSTR /* strmId */)
  334. {
  335.   HFILE fhdl;
  336.   streampos seekpos;
  337.   if (omode == ofParent)
  338.     omode = GetOpenMode();
  339.   if (!(omode & ofWrite))
  340.     return 0;
  341.   if ((fhdl = FHdl) == HFILE_ERROR) {   // if file not open at document level
  342.     if ((fhdl=OpenThisFile (omode, GetDocPath(), &seekpos)) == HFILE_ERROR)
  343.       return 0;
  344.   } else {
  345.     omode = GetOpenMode() ? (GetOpenMode() & ~ofBinary) | (omode & ofBinary)
  346.                           : omode;
  347.     omode |= PREV_OPEN;
  348.   }
  349.   return new TFileOutStream(*this, fhdl, omode, seekpos);
  350. }
  351.  
  352. TFileInStream::~TFileInStream()
  353. {
  354.   ((TFileDocument&)Doc).CloseThisFile(buf.xfd, GetOpenMode());
  355. }
  356.  
  357. TFileOutStream::~TFileOutStream()
  358. {
  359.   if (buf.out_waiting())
  360.     buf.overflow(EOF);
  361.   ((TFileDocument&)Doc).CloseThisFile(buf.xfd, GetOpenMode());
  362. }
  363.  
  364. //
  365. //  class TFileBuf
  366. //  ----- --------
  367. //
  368. const int B_size = 516; // natural size for a file buffer, plus 4 for putback
  369.  
  370. // make a TFileBuf attached to an open fd
  371.  
  372. TFileBuf::TFileBuf(int fhdl, int omode, long seekpos)
  373. {
  374.   xfd = fhdl;     // assumed to be valid
  375.   mode = omode;   // this may not represent the actual mode opened previously
  376.   last_seek = seekpos;
  377.   char* p = new char[B_size];
  378.   if (p) {
  379.     setb(p, p+B_size, 1);   // ~streambuf() will delete buffer
  380.     setp(p+4, p+4);
  381.     setg(p, p+4, p+4);
  382.   }
  383. }
  384.  
  385. // Seek file to position.
  386. // We take a simple approach, and don't check for small position changes
  387. // within the current buffer.
  388.  
  389. streampos TFileBuf::seekoff(streamoff off, ios::seek_dir dir, int /* mode ignored */)
  390. {
  391.   long loff = off;
  392.   int count = out_waiting();
  393.   if (out_waiting()) {       // flush the output
  394.     if (sync() == EOF)
  395.         return EOF;
  396.   } else if (dir == ios::cur)
  397.     if ((count = in_avail()) != 0) {
  398.       loff -= count;
  399.  
  400.       //  if we're in text mode, need to allow for newlines
  401.       //  in the buffer
  402.       if ((mode & ofBinary) == 0) {
  403.         char *tptr = gptr();
  404.         while (tptr != egptr())
  405.           if (*tptr++ == '\n')
  406.             loff--;
  407.       }
  408.     }
  409.   int w = (dir==ios::beg) ? SEEK_SET : ((dir==ios::cur) ? SEEK_CUR:SEEK_END);
  410.   last_seek = ::_llseek(xfd, loff, w);
  411.   if (!unbuffered() && base()) {      // set up get and put areas
  412.     int pb = (blen() > 8) ? 4 : 1;  // putback area size
  413.     char *b = base();
  414.     setp(b+pb, b+pb);
  415.     setg(b, b+pb, b+pb);
  416.   }
  417.   return (last_seek == long(HFILE_ERROR)) ? EOF : last_seek;
  418. }
  419.  
  420. int TFileBuf::sync()
  421. {
  422.   int count = out_waiting();
  423.   if (count) {
  424.     char* curp;
  425.     char* srcp = pbase();
  426.     char* endp = srcp + count;
  427.  
  428.     // convert LF's to CR/LF if text mode
  429.     if ((mode & ofBinary) == 0) {
  430.       for (curp = srcp; curp < endp; curp++) {
  431.         if (*curp == '\n') {
  432.           *curp = '\r';
  433.           count = (int)(curp - srcp) + 1;
  434.           if (::_lwrite(xfd, srcp, count) != count)
  435.             return EOF;
  436.           *(srcp = curp) = '\n';
  437.         }
  438.       }
  439.       count = (int)(curp - srcp);  // write what remains in the buffer below
  440.     }
  441.     if (::_lwrite(xfd, srcp, count) != count)
  442.       return EOF;
  443.  
  444.     // reset get and put areas
  445.     int pb = (blen() > 8) ? 4 : 1;  // putback area size
  446.     char *b = base();
  447.     setp(b+pb, b+blen());
  448.     setg(b, b+pb, b+pb);
  449.   } else if (in_avail()) {
  450.     last_seek = ::_llseek(xfd, long(-in_avail()), SEEK_CUR);
  451.     setg(eback(), gptr(), gptr());
  452.     setp(gptr(), gptr());
  453.     if (last_seek == long(HFILE_ERROR))
  454.       return EOF;
  455.   }
  456.   return 0;
  457. }
  458.  
  459. int TFileBuf::underflow()
  460. {
  461.   if ((mode & (ofRead | ofWrite)) == ofWrite)
  462.     return EOF;
  463.  
  464.   if (in_avail())    // no action needed
  465.     return (unsigned char) *gptr();
  466.  
  467.   int c;  // the return value
  468.   int count;  // input character count
  469.  
  470.   if (!unbuffered() && base()) {     // this is buffered
  471.     if (sync() != 0)
  472.       return EOF;
  473.  
  474.     // find buffer data
  475.     int pb = (blen() > 8) ? 4 : 1;  // putback area size
  476.     char* begp = base() + pb;
  477.  
  478.     // read in a new buffer
  479.     count = ::_lread(xfd, begp, blen()-pb);
  480.     if (count == HFILE_ERROR)
  481.       return EOF;
  482.  
  483.     // remove CR's if text mode
  484.     if ((mode & ofBinary) == 0) {
  485.       char* endp = begp + count;
  486.       char* dstp = 0;
  487.       char* srcp = 0; // initialized only to prevent compiler warning
  488.       char* curp;
  489.  
  490.       for (curp = begp;  curp < endp; curp++) {
  491.         if (*curp == '\r') {
  492.           if (dstp) {
  493.             memcpy(dstp, srcp, (int)(curp - srcp));
  494.             dstp += (int)(curp - srcp);
  495.           }
  496.           else
  497.             dstp = curp;
  498.           srcp = curp + 1;
  499.         }
  500.       }
  501.       if (dstp) {
  502.         endp = dstp + (int)(curp - srcp);
  503.         if (curp != srcp)
  504.           memcpy(dstp, srcp, (int)(curp - srcp));
  505.       }
  506.       count = (int)(endp - begp);
  507.     }
  508.     // set up get and put areas
  509.     setg(base(), begp, begp + count);
  510.     setp(begp, begp);
  511.  
  512.     if (count)
  513.       c = (unsigned char) *gptr();
  514.   } else {     // this is not buffered
  515.     for (;;) {
  516.       count = ::_lread(xfd, lahead, 1);
  517.       if (count == HFILE_ERROR) {
  518.         c = EOF;
  519.         setg(0, 0, 0);
  520.       } else {
  521.         c = (unsigned char)lahead[0];
  522.         if ((mode & ofBinary) == 0  && c == '\r')
  523.           continue;
  524.         setg(lahead, lahead, lahead+1);
  525.       }
  526.       break;
  527.     }
  528.   }
  529.   if (!count)
  530.     c = EOF;    // end of file
  531.   return c;
  532. }
  533.  
  534. // always flush
  535.  
  536. int TFileBuf::overflow(int c)
  537. {
  538.   if ((mode & (ofRead | ofWrite)) == ofRead)
  539.     return EOF;
  540.  
  541.   if (unbuffered() || !base()) {
  542.     if (c != EOF) {
  543.       int count;
  544.       char b[2];
  545.       if (c == '\n' && (mode & ofBinary) == 0) {
  546.         b[0] = '\r';
  547.         b[1] = (char)c;
  548.         count = 2;
  549.       } else {
  550.         b[0] = (char)c;
  551.         count = 1;
  552.       }
  553.       if (::_lwrite(xfd, b, count) != count)
  554.         return EOF;
  555.     }
  556.   } else {   // now we know this is buffered and state is not bad
  557.  
  558.     // resets get and put areas
  559.     if (sync() != 0)
  560.       return EOF;
  561.  
  562.     // reset get and put areas
  563.     int pb = (blen() > 8) ? 4 : 1;  // putback area size
  564.     char *b = base();
  565.     setp(b+pb, b+blen());
  566.     setg(b, b+pb, b+pb);
  567.  
  568.     if (c != EOF) {
  569.       sputc(c);
  570.       gbump(1);       // pptr and gptr must be the same
  571.     }
  572.   }
  573.   return 1;
  574. }
  575.  
  576. //
  577. //  class TFileStreamBase
  578. //  ----- ---------------
  579. //
  580.  
  581. TFileStreamBase::TFileStreamBase(int fhdl, int omode, streampos seekpos)
  582.                 : buf(fhdl, omode, seekpos)
  583. {
  584.   ios::init(&buf);
  585. }
  586.  
  587. #endif
  588.  
  589. #if !defined(SECTION) || SECTION == 2
  590.  
  591. IMPLEMENT_STREAMABLE1(TFileDocument, TDocument);
  592.  
  593. void*
  594. TFileDocument::Streamer::Read(ipstream& is, uint32 /*version*/) const
  595. {
  596.   TFileDocument* o = GetObject();
  597.   o->FHdl = HFILE_ERROR;    // initialize to closed file
  598.   o->InfoPresent = FALSE;
  599.   ReadBaseObject((TDocument*)o, is);
  600.   return o;
  601. }
  602.  
  603. void
  604. TFileDocument::Streamer::Write(opstream& os) const
  605. {
  606.   //  assumed that document is committed at this point
  607.   WriteBaseObject((TDocument*)GetObject(), os);
  608. }
  609.  
  610. #endif
  611.