home *** CD-ROM | disk | FTP | other *** search
- //----------------------------------------------------------------------------
- // ObjectWindows - (C) Copyright 1993 by Borland International
- // source\owl\filedoc.cpp
- // Implements classes TFileDocument, TFileInStream, TFileOutStream, TFileBuf
- //----------------------------------------------------------------------------
- #pragma hdrignore SECTION
- #include <owl\owlpch.h>
- #include <owl\filedoc.h>
-
- #if !defined(SECTION) || SECTION == 1
-
- //
- // class TFileBuf
- // ----- --------
- //
- class _OWLCLASS_RTL TFileBuf : public streambuf {
- public:
- enum { shDefault = shReadWrite }; // default file sharing
-
- TFileBuf(int fhdl, int omode, streampos seekpos);
- ~TFileBuf() {}
-
- virtual int overflow(int = EOF);
- virtual int underflow();
- virtual int sync();
- virtual streampos seekoff(streamoff, ios::seek_dir, int);
-
- int xfd; // the file descriptor, EOF if closed
- int mode; // the opened mode
- streampos last_seek;
- char lahead[2]; // current input char if unbuffered
- };
-
- //
- // class TFileStreamBase
- // ----- ---------------
- //
- class _OWLCLASS_RTL TFileStreamBase : virtual public ios {
- public:
- TFileStreamBase(int fhdl, int omode, streampos seekpos);
- ~TFileStreamBase() {}
- TFileBuf buf;
- };
-
- //
- // class TFileInStream
- // ----- -------------
- //
- class _OWLCLASS_RTL TFileInStream : public TFileStreamBase, public TInStream {
- public:
- TFileInStream(TFileDocument& doc, HFILE fhdl, int omode, streampos seekpos)
- : TInStream (doc,0,omode), TFileStreamBase(fhdl,omode,seekpos){}
- ~TFileInStream();
- };
-
- //
- // class TFileOutStream
- // ----- --------------
- //
- class _OWLCLASS_RTL TFileOutStream : public TFileStreamBase, public TOutStream {
- public:
- TFileOutStream(TFileDocument& doc, HFILE fhdl, int omode, streampos seekpos)
- : TOutStream (doc,0,omode), TFileStreamBase(fhdl,omode,seekpos){}
- ~TFileOutStream();
- };
-
- //
- // class TFileDocument
- // ----- -------------
- //
-
- HFILE
- TFileDocument::OpenThisFile(int omode, LPCSTR name, streampos* pseekpos){
- int how;
- HFILE fhdl;
- BOOL exists = FALSE;
- int share = omode & shMask;
-
- if (share < shCompat)
- share = (omode & ofWrite) ? shRead : shReadWrite;
-
- how = ((unsigned)(share-shCompat)) >> 5;
-
- if (omode & ofWrite) {
- if (!(omode & (ofAtEnd | ofAppend | ofRead)))
- omode |= ofTruncate; // output implies truncate unless in, app, or ate
-
- if (omode & ofRead)
- how |= OF_READWRITE;
- else
- how |= OF_WRITE;
- if (!((omode & ofNoCreate) && !(omode & ofTruncate))) {
- if (!((omode & ofTruncate) && !(omode & (ofNoCreate | ofNoReplace)))) {
- if ((fhdl=::_lopen(name,OF_READ|OF_SHARE_COMPAT)) !=HFILE_ERROR
- || (fhdl=::_lopen(name,OF_READ|OF_SHARE_DENY_NONE))!=HFILE_ERROR) {
- ::_lclose(fhdl);
- exists = TRUE;
- }
- }
- if (!(exists && !(omode & (ofNoCreate | ofNoReplace)))) {
- if ((exists && (omode & ofNoReplace))
- || (!exists && (omode & ofNoCreate)) )
- return 0;
- if ((fhdl = _lcreat(name, 0)) == HFILE_ERROR)
- return HFILE_ERROR;
- ::_lclose(fhdl); // close in order to open with share mode
- }
- }
- }
- else if (omode & ofRead)
- how |= OF_READ;
- else
- return HFILE_ERROR; // must specfify in, out, or in/out
-
- if ((fhdl = ::_lopen(name, how)) != HFILE_ERROR) {
- if ((*pseekpos = ::_llseek(fhdl, 0L, (omode & (ofAtEnd|ofAppend))
- ? SEEK_END : SEEK_SET)) == long(HFILE_ERROR)) {
- ::_lclose(fhdl);
- return HFILE_ERROR;
- }
- }
- #if defined(__WIN32__)
- FileLength = GetFileSize((HANDLE)fhdl, 0);
- InfoPresent = GetFileTime((HANDLE)fhdl, &FileCreateTime, &FileAccessTime,
- &FileUpdateTime);
- #else
- FileLength = filelength(fhdl);
- getftime(fhdl, (struct ftime*)&FileTime);
- InfoPresent = TRUE;
- #endif
- NotifyViews(vnDocOpened,omode);
- return fhdl;
- }
-
- void
- TFileDocument::CloseThisFile(HFILE fhdl, int omode)
- {
- if (!IS_PREV_OPEN(omode)) {
- ::_lclose(fhdl);
- NotifyViews(vnDocClosed, omode);
- }
- }
-
- BOOL
- TFileDocument::Open(int omode, LPCSTR path)
- {
- long seekpos;
- if (FHdl != HFILE_ERROR)
- return FALSE; // if already open at document level
- if (path)
- SetDocPath(path);
- if (omode != 0)
- SetOpenMode(omode);
- if ((FHdl = OpenThisFile(GetOpenMode(),GetDocPath(),&seekpos)) == HFILE_ERROR)
- return FALSE;
- return TRUE;
- }
-
- BOOL
- TFileDocument::Open(HFILE fhdl)
- {
- SetOpenMode(PREV_OPEN | ofReadWrite); // can we determine open mode?
- SetDocPath(0); // can we get path name?
- FHdl = fhdl;
- return TRUE;
- }
-
- BOOL
- TFileDocument::Close()
- {
- if (!TDocument::Close()) // close all children first
- return FALSE;
- if (FHdl != HFILE_ERROR) { // if open at document level
- if (TDocument::IsOpen()) // cannot close document if streams open
- return FALSE; // ?should we close streams here?
- CloseThisFile(FHdl, GetOpenMode());
- FHdl = HFILE_ERROR;
- }
- return TRUE;
- }
-
- BOOL
- TFileDocument::Commit(BOOL force)
- {
- if (!TDocument::Commit(force)) // flush views and child docs
- return FALSE;
- SetDirty(FALSE);
- return TRUE;
- }
-
- BOOL
- TFileDocument::Revert(BOOL clear)
- {
- if (!TDocument::Revert(clear))
- return FALSE;
- SetDirty(FALSE);
- return TRUE;
- }
-
- static char* PropNames[] = {
- "Create Time", // CreateTime
- "Modify Time", // ModifyTime
- "Access Time", // AccessTime
- "Storage Size", // StorageSize
- "File Handle", // FileHandle
- };
-
- static int PropFlags[] = {
- pfGetBinary|pfGetText, // CreateTime
- pfGetBinary|pfGetText, // ModifyTime
- pfGetBinary|pfGetText, // AccessTime
- pfGetBinary|pfGetText, // StorageSize
- pfGetBinary, // FileHandle
- };
-
- const char*
- TFileDocument::PropertyName(int index)
- {
- if (index <= PrevProperty)
- return TDocument::PropertyName(index);
- else if (index < NextProperty)
- return PropNames[index-PrevProperty-1];
- else
- return 0;
- }
-
- int
- TFileDocument::PropertyFlags(int index)
- {
- if (index <= PrevProperty)
- return TDocument::PropertyFlags(index);
- else if (index < NextProperty)
- return PropFlags[index-PrevProperty-1];
- else
- return 0;
- }
-
- int
- TFileDocument::FindProperty(const char far* name)
- {
- int i;
- for (i=0; i < NextProperty-PrevProperty-1; i++)
- if (strcmp(PropNames[i], name) == 0)
- return i+PrevProperty+1;
- return TDocument::FindProperty(name);
- }
-
- int
- TFileDocument::GetProperty(int prop, void far* dest, int textlen)
- {
- switch(prop)
- {
- case FileHandle:
- if (textlen)
- return 0;
- *(HFILE FAR*)dest = FHdl;
- return sizeof(FHdl);
- default:
- if (InfoPresent) {
- switch(prop)
- {
- case StorageSize:
- if (!textlen) {
- *(unsigned long FAR*)dest = FileLength;
- return sizeof(FileLength);
- } else {
- char buf[10];
- int len = wsprintf(buf, "%ld", FileLength);
- if (textlen > len)
- textlen = len;
- memcpy(dest, buf, textlen);
- *((char far*)dest + textlen) = 0;
- return len;
- }
- #if defined(__WIN32__)
- case CreateTime:
- return FormatFileTime(&FileCreateTime, dest, textlen);
- case ModifyTime:
- return FormatFileTime(&FileUpdateTime, dest, textlen);
- case AccessTime:
- return FormatFileTime(&FileAccessTime, dest, textlen);
- #else // DOS file system
- case CreateTime:
- case ModifyTime:
- case AccessTime:
- {
- struct date propdate;
- struct time proptime;
- propdate.da_year = ((struct ftime*)&FileTime)->ft_year+1980;
- propdate.da_mon = ((struct ftime*)&FileTime)->ft_month;
- propdate.da_day = ((struct ftime*)&FileTime)->ft_day;
- proptime.ti_hour = ((struct ftime*)&FileTime)->ft_hour;
- proptime.ti_min = ((struct ftime*)&FileTime)->ft_min;
- proptime.ti_sec = ((struct ftime*)&FileTime)->ft_tsec*2;
- proptime.ti_hund = 0;
- return FormatDateTime(propdate, proptime, dest, textlen);
- }
- #endif
- }
- }
- return TDocument::GetProperty(prop, dest, textlen);
- }
- }
-
- BOOL
- TFileDocument::SetProperty(int prop, const void far* src)
- {
- // file properties currently not settable
- return TDocument::SetProperty(prop, src);
- }
-
- TInStream*
- TFileDocument::InStream(int omode, LPCSTR /* strmId */)
- {
- HFILE fhdl;
- streampos seekpos;
- if (omode == ofParent)
- omode = GetOpenMode();
- if (!(omode & ofRead))
- return 0;
- if ((fhdl = FHdl) == HFILE_ERROR) { // if file not open at document level
- if ((fhdl=OpenThisFile (omode, GetDocPath(), &seekpos)) == HFILE_ERROR)
- return 0;
- } else {
- omode = GetOpenMode() ? (GetOpenMode() & ~ofBinary) | (omode & ofBinary)
- : omode;
- omode |= PREV_OPEN;
- }
- return new TFileInStream(*this, fhdl, omode, seekpos);
- }
-
- TOutStream*
- TFileDocument::OutStream(int omode, LPCSTR /* strmId */)
- {
- HFILE fhdl;
- streampos seekpos;
- if (omode == ofParent)
- omode = GetOpenMode();
- if (!(omode & ofWrite))
- return 0;
- if ((fhdl = FHdl) == HFILE_ERROR) { // if file not open at document level
- if ((fhdl=OpenThisFile (omode, GetDocPath(), &seekpos)) == HFILE_ERROR)
- return 0;
- } else {
- omode = GetOpenMode() ? (GetOpenMode() & ~ofBinary) | (omode & ofBinary)
- : omode;
- omode |= PREV_OPEN;
- }
- return new TFileOutStream(*this, fhdl, omode, seekpos);
- }
-
- TFileInStream::~TFileInStream()
- {
- ((TFileDocument&)Doc).CloseThisFile(buf.xfd, GetOpenMode());
- }
-
- TFileOutStream::~TFileOutStream()
- {
- if (buf.out_waiting())
- buf.overflow(EOF);
- ((TFileDocument&)Doc).CloseThisFile(buf.xfd, GetOpenMode());
- }
-
- //
- // class TFileBuf
- // ----- --------
- //
- const int B_size = 516; // natural size for a file buffer, plus 4 for putback
-
- // make a TFileBuf attached to an open fd
-
- TFileBuf::TFileBuf(int fhdl, int omode, long seekpos)
- {
- xfd = fhdl; // assumed to be valid
- mode = omode; // this may not represent the actual mode opened previously
- last_seek = seekpos;
- char* p = new char[B_size];
- if (p) {
- setb(p, p+B_size, 1); // ~streambuf() will delete buffer
- setp(p+4, p+4);
- setg(p, p+4, p+4);
- }
- }
-
- // Seek file to position.
- // We take a simple approach, and don't check for small position changes
- // within the current buffer.
-
- streampos TFileBuf::seekoff(streamoff off, ios::seek_dir dir, int /* mode ignored */)
- {
- long loff = off;
- int count = out_waiting();
- if (out_waiting()) { // flush the output
- if (sync() == EOF)
- return EOF;
- } else if (dir == ios::cur)
- if ((count = in_avail()) != 0) {
- loff -= count;
-
- // if we're in text mode, need to allow for newlines
- // in the buffer
- if ((mode & ofBinary) == 0) {
- char *tptr = gptr();
- while (tptr != egptr())
- if (*tptr++ == '\n')
- loff--;
- }
- }
- int w = (dir==ios::beg) ? SEEK_SET : ((dir==ios::cur) ? SEEK_CUR:SEEK_END);
- last_seek = ::_llseek(xfd, loff, w);
- if (!unbuffered() && base()) { // set up get and put areas
- int pb = (blen() > 8) ? 4 : 1; // putback area size
- char *b = base();
- setp(b+pb, b+pb);
- setg(b, b+pb, b+pb);
- }
- return (last_seek == long(HFILE_ERROR)) ? EOF : last_seek;
- }
-
- int TFileBuf::sync()
- {
- int count = out_waiting();
- if (count) {
- char* curp;
- char* srcp = pbase();
- char* endp = srcp + count;
-
- // convert LF's to CR/LF if text mode
- if ((mode & ofBinary) == 0) {
- for (curp = srcp; curp < endp; curp++) {
- if (*curp == '\n') {
- *curp = '\r';
- count = (int)(curp - srcp) + 1;
- if (::_lwrite(xfd, srcp, count) != count)
- return EOF;
- *(srcp = curp) = '\n';
- }
- }
- count = (int)(curp - srcp); // write what remains in the buffer below
- }
- if (::_lwrite(xfd, srcp, count) != count)
- return EOF;
-
- // reset get and put areas
- int pb = (blen() > 8) ? 4 : 1; // putback area size
- char *b = base();
- setp(b+pb, b+blen());
- setg(b, b+pb, b+pb);
- } else if (in_avail()) {
- last_seek = ::_llseek(xfd, long(-in_avail()), SEEK_CUR);
- setg(eback(), gptr(), gptr());
- setp(gptr(), gptr());
- if (last_seek == long(HFILE_ERROR))
- return EOF;
- }
- return 0;
- }
-
- int TFileBuf::underflow()
- {
- if ((mode & (ofRead | ofWrite)) == ofWrite)
- return EOF;
-
- if (in_avail()) // no action needed
- return (unsigned char) *gptr();
-
- int c; // the return value
- int count; // input character count
-
- if (!unbuffered() && base()) { // this is buffered
- if (sync() != 0)
- return EOF;
-
- // find buffer data
- int pb = (blen() > 8) ? 4 : 1; // putback area size
- char* begp = base() + pb;
-
- // read in a new buffer
- count = ::_lread(xfd, begp, blen()-pb);
- if (count == HFILE_ERROR)
- return EOF;
-
- // remove CR's if text mode
- if ((mode & ofBinary) == 0) {
- char* endp = begp + count;
- char* dstp = 0;
- char* srcp = 0; // initialized only to prevent compiler warning
- char* curp;
-
- for (curp = begp; curp < endp; curp++) {
- if (*curp == '\r') {
- if (dstp) {
- memcpy(dstp, srcp, (int)(curp - srcp));
- dstp += (int)(curp - srcp);
- }
- else
- dstp = curp;
- srcp = curp + 1;
- }
- }
- if (dstp) {
- endp = dstp + (int)(curp - srcp);
- if (curp != srcp)
- memcpy(dstp, srcp, (int)(curp - srcp));
- }
- count = (int)(endp - begp);
- }
- // set up get and put areas
- setg(base(), begp, begp + count);
- setp(begp, begp);
-
- if (count)
- c = (unsigned char) *gptr();
- } else { // this is not buffered
- for (;;) {
- count = ::_lread(xfd, lahead, 1);
- if (count == HFILE_ERROR) {
- c = EOF;
- setg(0, 0, 0);
- } else {
- c = (unsigned char)lahead[0];
- if ((mode & ofBinary) == 0 && c == '\r')
- continue;
- setg(lahead, lahead, lahead+1);
- }
- break;
- }
- }
- if (!count)
- c = EOF; // end of file
- return c;
- }
-
- // always flush
-
- int TFileBuf::overflow(int c)
- {
- if ((mode & (ofRead | ofWrite)) == ofRead)
- return EOF;
-
- if (unbuffered() || !base()) {
- if (c != EOF) {
- int count;
- char b[2];
- if (c == '\n' && (mode & ofBinary) == 0) {
- b[0] = '\r';
- b[1] = (char)c;
- count = 2;
- } else {
- b[0] = (char)c;
- count = 1;
- }
- if (::_lwrite(xfd, b, count) != count)
- return EOF;
- }
- } else { // now we know this is buffered and state is not bad
-
- // resets get and put areas
- if (sync() != 0)
- return EOF;
-
- // reset get and put areas
- int pb = (blen() > 8) ? 4 : 1; // putback area size
- char *b = base();
- setp(b+pb, b+blen());
- setg(b, b+pb, b+pb);
-
- if (c != EOF) {
- sputc(c);
- gbump(1); // pptr and gptr must be the same
- }
- }
- return 1;
- }
-
- //
- // class TFileStreamBase
- // ----- ---------------
- //
-
- TFileStreamBase::TFileStreamBase(int fhdl, int omode, streampos seekpos)
- : buf(fhdl, omode, seekpos)
- {
- ios::init(&buf);
- }
-
- #endif
-
- #if !defined(SECTION) || SECTION == 2
-
- IMPLEMENT_STREAMABLE1(TFileDocument, TDocument);
-
- void*
- TFileDocument::Streamer::Read(ipstream& is, uint32 /*version*/) const
- {
- TFileDocument* o = GetObject();
- o->FHdl = HFILE_ERROR; // initialize to closed file
- o->InfoPresent = FALSE;
- ReadBaseObject((TDocument*)o, is);
- return o;
- }
-
- void
- TFileDocument::Streamer::Write(opstream& os) const
- {
- // assumed that document is committed at this point
- WriteBaseObject((TDocument*)GetObject(), os);
- }
-
- #endif
-