| Current Path : /var/www/html/prashantkr/TurboC/TCWIN45/SOURCE/OWL/ |
| Current File : /var/www/html/prashantkr/TurboC/TCWIN45/SOURCE/OWL/FILEDOC.CPP |
//----------------------------------------------------------------------------
// ObjectWindows
// (C) Copyright 1993, 1994 by Borland International, All Rights Reserved
//
// 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, const char far* 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(BI_PLAT_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, const char far* 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(BI_PLAT_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, const char far* /*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, const char far* /*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*/)
{
long loff = off;
if (out_waiting()) { // flush the output
if (sync() == EOF)
return EOF;
}
else if (dir == ios::cur) {
int count = in_avail();
if (count != 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 = 0; // 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