#include "ET++.ph" #ifdef __GNUG__ #pragma implementation #endif #include "Data.h" #include "Class.h" #include "OrdColl.h" #include "MemBuf.h" #include "Bitmap.h" #include "String.h" #include "Converter.h" #include "TypeMatcher.h" #include "CType.h" #include "ET_stdio.h" extern Converter *gEtConverter; extern TypeMatcher *gEtMatcher; const Symbol cDocCreatorUndef("__UNKNOWN__"), cDocTypeUndef("UNDEF"), cDocTypeAscii("ASCII"), cDocTypeET("ET++OIO"); //cDocTypeCHeader("CHEADER"); extern SmartBitmap gFileIcon; // bitmap images for file icons OrdCollection *gConverters; static OrdCollection *gTypes; void PrepareTypes() { SafeDelete(gTypes); gTypes= new OrdCollection; } void EndTypes(Data *data) { if (data && gTypes) data->CheckTypes(gTypes); SafeDelete(gTypes); } //---- Data -------------------------------------------------------------------- NewMetaImpl(Data,RefCounted, (TP(name), T(creator), T(type), T(bits), T(flags), T(uniqueid), T(sizehint), T(modtime), TP(classtype), TP(typematcher))); Data::Data(const char *n) { name= strsave(n ? n : "???"); classtype= 0; type= cDocTypeUndef; creator= cDocCreatorUndef; typematcher= 0; bits= flags= 0; uniqueid= 0; sizehint= -1; modtime= 0; } Data::~Data() { SafeDelete(name); } void Data::UpdateBit(u_long b, bool val) { if (val) SETBIT(bits, b); else CLRBIT(bits, b); SETBIT(flags, b); } Class *Data::GetClassType() { UpdateFields(eDataDeepType); return classtype; } bool Data::IsWritable() { UpdateFields(eDataWrite); return TESTBIT(bits, eDataWrite); } bool Data::IsReadable() { UpdateFields(eDataRead); return TESTBIT(bits, eDataRead); } bool Data::IsExecutable() { UpdateFields(eDataExec); return TESTBIT(bits, eDataExec); } bool Data::IsETFormat() { if (classtype) return TRUE; UpdateFields(eDataDeepType); if (type == cDocTypeET) return TRUE; if (typematcher && typematcher->GetType() == cDocTypeET) return TRUE; return FALSE; } bool Data::IsAscii() { UpdateFields(eDataType); if (typematcher) return typematcher->ascii; return Type() == cDocTypeAscii; } bool Data::IsValid() { UpdateFields(eDataValid); return TESTBIT(bits, eDataValid); } bool Data::IsUntitled() { UpdateFields(eDataNew); return TESTBIT(bits, eDataNew); } bool Data::HasContents() { UpdateFields(eDataType); return type == cDocTypeDirectory; } u_long Data::ModifiedAt() { UpdateFields(eDataTime); return modtime; } long Data::SizeHint() { UpdateFields(eDataSize); return sizehint; } const Symbol &Data::Type() { UpdateFields(eDataDeepType); return type; } void Data::SetType(const Symbol &t) { type= t; SETBIT(flags, eDataDeepType); } const Symbol &Data::Creator() { UpdateFields(eDataCreator); return creator; } void Data::SetCreator(const Symbol &crea) { creator= crea; SETBIT(flags, eDataCreator); } const char *Data::FullName() { return name; } const char *Data::ShortName() { return FullName(); } u_long Data::UniqueId() { UpdateFields(eDataId); return uniqueid; } const char *Data::AsString() { return ShortName(); } int Data::Compare(Object *op) { return StrCmp(ShortName(), Guard(op,Data)->ShortName(), -1, gStdEncoding->SortMap()); } u_long Data::Hash() { return strhash(FullName()); } bool Data::IsEqual(Object *other) { return other != 0 && IsA() == other->IsA() && strcmp(FullName(), ((Data*)other)->FullName()) == 0; } StreamBuf *Data::GetStreamBuf(bool) { AbstractMethod("GetStreamBuf"); return 0; } StreamBuf *Data::GetStreamBufForReading() { StreamBuf *sb= GetStreamBuf(FALSE); if (sb) sb->seek(0); return sb; } StreamBuf *Data::GetStreamBufForWriting() { return GetStreamBuf(TRUE); } void Data::StartUpdate() { } void Data::EndUpdate(bool, bool) { } Object *Data::AsObject(Class *want) { if (gTypes) { // AsObject used in test mode (ala CanPaste) if (want) gTypes->AddFirst(want); return 0; } // AsObject used in normal mode (ala PasteData) return MakeObject(want); } Object *Data::MakeObject(Class *want) { Converter *converter= Converter::FindConverter(this, want); if (converter && converter->CanConvert(this, want)) return converter->Convert(this, want); return 0; } bool Data::CanConvert(Class *want) { if (gTypes) { if (want) gTypes->AddFirst(want); return FALSE; } return Converter::FindConverter(this, want) != 0; } bool Data::CheckTypes(OrdCollection *typelist) { if (typelist) { Iter next(typelist); Class *cl; SafeDelete(gConverters); gConverters= new OrdCollection; while (cl= (Class*) next()) Converter::FindConverter(this, cl, gConverters); if (gConverters->Size() <= 0) SafeDelete(gConverters); } if (gConverters && gConverters->Size() > 0) return TRUE; return FALSE; } Bitmap *Data::GetBitmap() { UpdateFields(eDataType); if (typematcher) return typematcher->GetBitmap(); return gFileIcon; } SeqCollection *Data::GetContents() { return 0; } bool Data::HasParent() { Data *d= GetParent(); bool b= (d != 0); SafeDelete(d); return b; } Data *Data::GetParent() { return 0; } OStream& Data::PrintOn(OStream &s) { RefCounted::PrintOn(s); s.PrintString(name); return s << bits SP << flags SP << creator SP << type SP << sizehint SP << modtime SP << uniqueid SP << (long)(classtype) SP << (long)(typematcher) SP; } IStream& Data::ReadFrom(IStream &s) { long ct, tm; RefCounted::ReadFrom(s); SafeDelete(name); s.ReadString(&name); s >> bits >> flags >> creator >> type >> sizehint >> modtime >> uniqueid >> ct >> tm; classtype= (Class*) ct; typematcher= (TypeMatcher*) tm; return s; } u_long Data::UpdateFields(u_long f) { if (!TESTBIT(flags, f)) { switch (f) { case eDataType: case eDataDeepType: case eDataCreator: typematcher= TypeMatcher::MatchByContents(this); if (typematcher && type == cDocTypeUndef) type= typematcher->GetType(); SETBIT(flags, eDataType); SETBIT(flags, eDataDeepType); SETBIT(flags, eDataCreator); break; } } return 0; } //---- MemoryData -------------------------------------------------------------- NewMetaImpl(MemoryData,Data, (TV(data,sizehint))); MemoryData::MemoryData(byte *d, int l, const Symbol &t, bool copy, bool dd) : Data("MemoryData") { type= t; sizehint= l; dodelete= dd; if (copy) { data= new byte[sizehint]; MemCpy(data, d, (u_int)sizehint); } else data= d; SETBIT(flags, eDataType); SETBIT(flags, eDataDeepType); UpdateBit(eDataRead, TRUE); } MemoryData::~MemoryData() { if (dodelete) SafeDelete(data); } StreamBuf *MemoryData::GetStreamBuf(bool forwriting) { if (forwriting) { fprintf(stderr, "MemoryData::GetStreamBuf: no support for writing\n"); return 0; } return new StreamBuf((int)sizehint, (char*) data, (int)sizehint, FALSE); } OStream& MemoryData::PrintOn(OStream &s) { Data::PrintOn(s); return s.PrintString(data, (int)sizehint); } IStream& MemoryData::ReadFrom(IStream &s) { Data::ReadFrom(s); SafeDelete(data); return s.ReadString(&data, (int*) &sizehint); } //---- StreamBufData ----------------------------------------------------------- NewMetaImpl0(StreamBufData,Data); StreamBufData::StreamBufData(StreamBuf *s, const Symbol &t) : Data("StreamBufData") { sb= s; type= t; SETBIT(flags, eDataType); SETBIT(flags, eDataDeepType); if (sb) sizehint= sb->tell(); else sizehint= -1; } StreamBuf *StreamBufData::GetStreamBuf(bool) { return sb; } //---- ObjectData -------------------------------------------------------------- NewMetaImpl(ObjectData,Data, (TP(object))); ObjectData::ObjectData(Object *op) : Data("ObjectData") { object= op; typematcher= gEtMatcher; type= cDocTypeET; if (object) classtype= object->IsA(); SETBIT(flags, eDataType); SETBIT(flags, eDataDeepType); SETBIT(flags, eDataCreator); UpdateBit(eDataRead, TRUE); } ObjectData::~ObjectData() { SafeDelete(object); } Object *ObjectData::MakeObject(Class *want) { if (GetClassType()->isKindOf(want)) return object->DeepClone(); Converter *converter= Converter::FindConverter(this, want); if (converter) return converter->Convert(this, want); return 0; } bool ObjectData::CanConvert(Class *want) { if (gTypes) return Data::CanConvert(want); if (GetClassType()->isKindOf(want)) return TRUE; if (Converter::FindConverter(this, want)) return TRUE; return FALSE; } OStream& ObjectData::PrintOn(OStream &s) { Data::PrintOn(s); return s << object; } IStream& ObjectData::ReadFrom(IStream &s) { Data::ReadFrom(s); return s >> object; }