diff --git a/common/lc_application.cpp b/common/lc_application.cpp index 5118421e..f2d287b0 100644 --- a/common/lc_application.cpp +++ b/common/lc_application.cpp @@ -47,7 +47,7 @@ void lcApplication::AddProject(Project* project) m_ActiveProject = project; } -bool lcApplication::LoadPiecesLibrary(const char* LibPath, const char* SysLibPath) +bool lcApplication::LoadPiecesLibrary(const char* LibPath, const char* LibraryInstallPath, const char* LibraryCachePath) { // Create an empty library. if (m_Library == NULL) @@ -55,19 +55,19 @@ bool lcApplication::LoadPiecesLibrary(const char* LibPath, const char* SysLibPat // Check if the user specified a library path in the command line. if (LibPath != NULL) - if (m_Library->Load(LibPath)) + if (m_Library->Load(LibPath, LibraryCachePath)) return true; // Check for the LEOCAD_LIB environment variable. char* EnvPath = getenv("LEOCAD_LIB"); if (EnvPath != NULL) - if (m_Library->Load(EnvPath)) + if (m_Library->Load(EnvPath, LibraryCachePath)) return true; // Try the executable install path last. - if (SysLibPath != NULL) - if (m_Library->Load(SysLibPath)) + if (LibraryInstallPath != NULL) + if (m_Library->Load(LibraryInstallPath, LibraryCachePath)) return true; lcLoadDefaultColors(); @@ -114,12 +114,11 @@ void lcApplication::ParseStringArgument(int* CurArg, int argc, char* argv[], cha } } -bool lcApplication::Initialize(int argc, char* argv[], const char* SysLibPath) +bool lcApplication::Initialize(int argc, char* argv[], const char* LibraryInstallPath, const char* LibraryCachePath) { // System setup parameters. char* LibPath = NULL; char* GLPath = NULL; - char* LDrawPath = NULL; // Image output options. bool SaveImage = false; @@ -208,7 +207,6 @@ bool lcApplication::Initialize(int argc, char* argv[], const char* SysLibPath) printf(" [options] can be:\n"); printf(" --libgl : Searches for OpenGL libraries in path.\n"); printf(" --libpath : Loads the Pieces Library from path.\n"); - printf(" --convert : Generates Pieces Library from LDraw files.\n"); printf(" -i, --image : Saves a picture in the format specified by ext.\n"); printf(" -w, --width : Sets the picture width.\n"); printf(" -h, --height : Sets the picture height.\n"); @@ -232,7 +230,7 @@ bool lcApplication::Initialize(int argc, char* argv[], const char* SysLibPath) if (!GL_Initialize(GLPath)) return false; - if (!LoadPiecesLibrary(LibPath, SysLibPath)) + if (!LoadPiecesLibrary(LibPath, LibraryInstallPath, LibraryCachePath)) return false; SystemInit(); diff --git a/common/lc_application.h b/common/lc_application.h index d4e6241d..a45b88d8 100644 --- a/common/lc_application.h +++ b/common/lc_application.h @@ -12,11 +12,11 @@ public: lcApplication(); ~lcApplication(); - bool Initialize(int argc, char *argv[], const char* SysLibPath); + bool Initialize(int argc, char *argv[], const char* LibraryInstallPath, const char* LibraryCachePath); void Shutdown(); // Pieces library. - bool LoadPiecesLibrary(const char* LibPath, const char* SysLibPath); + bool LoadPiecesLibrary(const char* LibPath, const char* LibraryInstallPath, const char* LibraryCachePath); lcPiecesLibrary* GetPiecesLibrary() const { return m_Library; diff --git a/common/lc_library.cpp b/common/lc_library.cpp index 796e45ba..3dd619c0 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -5,6 +5,12 @@ #include "pieceinf.h" #include "lc_colors.h" #include "system.h" +#include +#include + +#define LC_LIBRARY_CACHE_VERSION 0x0100 +#define LC_LIBRARY_CACHE_ARCHIVE 0x0001 +#define LC_LIBRARY_CACHE_DIRECTORY 0x0002 lcPiecesLibrary::lcPiecesLibrary() { @@ -41,7 +47,7 @@ PieceInfo* lcPiecesLibrary::CreatePlaceholder(const char* PieceName) return Info; } -bool lcPiecesLibrary::Load(const char* SearchPath) +bool lcPiecesLibrary::Load(const char* SearchPath, const char* CacheFilePath) { char LibraryPath[LC_MAXPATH]; @@ -54,7 +60,7 @@ bool lcPiecesLibrary::Load(const char* SearchPath) strcpy(mLibraryPath, LibraryPath); strcat(LibraryPath, "complete.zip"); - if (OpenArchive(LibraryPath)) + if (OpenArchive(LibraryPath, CacheFilePath)) { lcMemFile ColorFile; @@ -85,7 +91,7 @@ bool lcPiecesLibrary::Load(const char* SearchPath) return true; } -bool lcPiecesLibrary::OpenArchive(const char* FileName) +bool lcPiecesLibrary::OpenArchive(const char* FileName, const char* CacheFilePath) { mZipFile = new lcZipFile(); @@ -151,29 +157,122 @@ bool lcPiecesLibrary::OpenArchive(const char* FileName) } } - lcMemFile PieceFile; + bool CacheValid = false; + struct stat LibraryStat; - for (int PieceInfoIndex = 0; PieceInfoIndex < mPieces.GetSize(); PieceInfoIndex++) + strcpy(mCacheFileName, CacheFilePath); + if (CacheFilePath[0]) + strcat(mCacheFileName, "library.cache"); + + if (stat(FileName, &LibraryStat) == 0) { - PieceInfo* Info = mPieces[PieceInfoIndex]; + lcZipFile CacheFile; - mZipFile->ExtractFile(Info->mZipFileIndex, PieceFile, 256); - PieceFile.Seek(0, SEEK_END); - PieceFile.WriteU8(0); - - char* Src = (char*)PieceFile.mBuffer + 2; - char* Dst = Info->m_strDescription; - - for (;;) + if (CacheFile.OpenRead(mCacheFileName)) { - if (*Src != '\r' && *Src != '\n' && *Src && Dst - Info->m_strDescription < sizeof(Info->m_strDescription) - 1) + lcMemFile VersionFile; + + if (CacheFile.ExtractFile("version", VersionFile)) { - *Dst++ = *Src++; - continue; + lcuint32 CacheVersion; + lcuint32 CacheFlags; + lcuint64 LibrarySize; + lcuint64 LibraryModified; + + if (VersionFile.ReadU32(&CacheVersion, 1) && VersionFile.ReadU32(&CacheFlags, 1) && + VersionFile.ReadU64(&LibrarySize, 1) && VersionFile.ReadU64(&LibraryModified, 1)) + { + if (CacheVersion == LC_LIBRARY_CACHE_VERSION && CacheFlags == LC_LIBRARY_CACHE_ARCHIVE && + LibrarySize == LibraryStat.st_size && LibraryModified == LibraryStat.st_mtime) + CacheValid = true; + } + } + } + + if (CacheValid) + { + lcMemFile IndexFile; + + if (CacheFile.ExtractFile("index", IndexFile)) + { + lcuint32 NumFiles; + + if (IndexFile.ReadU32(&NumFiles, 1) && NumFiles == mPieces.GetSize()) + { + for (int PieceInfoIndex = 0; PieceInfoIndex < mPieces.GetSize(); PieceInfoIndex++) + { + PieceInfo* Info = mPieces[PieceInfoIndex]; + + LC_CASSERT(sizeof(Info->m_strDescription) == 128); + + if (!IndexFile.ReadBuffer(Info->m_strDescription, sizeof(Info->m_strDescription))) + { + CacheValid = false; + break; + } + } + } + else + CacheValid = false; + } + else + CacheValid = false; + } + } + + if (!CacheValid) + { + lcMemFile PieceFile; + + for (int PieceInfoIndex = 0; PieceInfoIndex < mPieces.GetSize(); PieceInfoIndex++) + { + PieceInfo* Info = mPieces[PieceInfoIndex]; + + mZipFile->ExtractFile(Info->mZipFileIndex, PieceFile, 256); + PieceFile.Seek(0, SEEK_END); + PieceFile.WriteU8(0); + + char* Src = (char*)PieceFile.mBuffer + 2; + char* Dst = Info->m_strDescription; + + for (;;) + { + if (*Src != '\r' && *Src != '\n' && *Src && Dst - Info->m_strDescription < sizeof(Info->m_strDescription) - 1) + { + *Dst++ = *Src++; + continue; + } + + *Dst = 0; + break; + } + } + + lcZipFile CacheFile; + + if (CacheFile.OpenWrite(mCacheFileName, false)) + { + lcMemFile VersionFile; + + VersionFile.WriteU32(LC_LIBRARY_CACHE_VERSION); + VersionFile.WriteU32(LC_LIBRARY_CACHE_ARCHIVE); + VersionFile.WriteU64(LibraryStat.st_size); + VersionFile.WriteU64(LibraryStat.st_mtime); + + CacheFile.AddFile("version", VersionFile); + + lcMemFile IndexFile; + + IndexFile.WriteU32(mPieces.GetSize()); + + for (int PieceInfoIndex = 0; PieceInfoIndex < mPieces.GetSize(); PieceInfoIndex++) + { + PieceInfo* Info = mPieces[PieceInfoIndex]; + + IndexFile.WriteBuffer(Info->m_strDescription, sizeof(Info->m_strDescription)); } - *Dst = 0; - break; + CacheFile.AddFile("index", IndexFile); } } diff --git a/common/lc_library.h b/common/lc_library.h index ca4cf49c..9d75fe94 100644 --- a/common/lc_library.h +++ b/common/lc_library.h @@ -84,7 +84,7 @@ public: lcPiecesLibrary(); ~lcPiecesLibrary(); - bool Load(const char* SearchPath); + bool Load(const char* SearchPath, const char* CacheFilePath); PieceInfo* FindPiece(const char* PieceName, bool CreatePlaceholderIfMissing); PieceInfo* CreatePlaceholder(const char* PieceName); @@ -110,7 +110,7 @@ public: char mLibraryPath[LC_MAXPATH]; protected: - bool OpenArchive(const char* FileName); + bool OpenArchive(const char* FileName, const char* CacheFileName); bool OpenDirectory(const char* Path); int FindPrimitiveIndex(const char* Name); bool LoadPrimitive(int PrimitiveIndex); @@ -119,6 +119,8 @@ protected: bool mCategoriesModified; char mCategoriesFile[LC_MAXPATH]; + char mCacheFileName[LC_MAXPATH]; + lcZipFile* mZipFile; }; diff --git a/common/lc_zipfile.cpp b/common/lc_zipfile.cpp index 50da57be..deb72cdc 100644 --- a/common/lc_zipfile.cpp +++ b/common/lc_zipfile.cpp @@ -31,15 +31,22 @@ bool lcZipFile::OpenRead(const char* FilePath) return true; } -bool lcZipFile::OpenWrite(const char* FilePath) +bool lcZipFile::OpenWrite(const char* FilePath, bool Append) { lcDiskFile* File = new lcDiskFile(); mFile = File; - bool Exists = true; - if (!File->Open(FilePath, "r+b") || !Open()) + if (Append) + { + if (!File->Open(FilePath, "r+b") || !Open()) + { + delete File; + mFile = NULL; + return false; + } + } + else { - Exists = false; mNumEntries = 0; mCentralDirSize = 0; mCentralDirOffset = 0; diff --git a/common/lc_zipfile.h b/common/lc_zipfile.h index f977c4ec..ccf8da89 100644 --- a/common/lc_zipfile.h +++ b/common/lc_zipfile.h @@ -49,7 +49,7 @@ public: ~lcZipFile(); bool OpenRead(const char* FilePath); - bool OpenWrite(const char* FilePath); + bool OpenWrite(const char* FilePath, bool Append); void Flush(); bool ExtractFile(int FileIndex, lcMemFile& File, lcuint32 MaxLength = 0xffffffff); diff --git a/win/Leocad.cpp b/win/Leocad.cpp index 07268771..6665f600 100644 --- a/win/Leocad.cpp +++ b/win/Leocad.cpp @@ -5,6 +5,7 @@ #include "CADDoc.h" #include "CADView.h" #include +#include #include #include "project.h" #include "globals.h" @@ -180,16 +181,25 @@ BOOL CCADApp::InitInstance() InitKeyboardShortcuts(); - char app[LC_MAXPATH], *ptr; - GetModuleFileName (NULL, app, LC_MAXPATH); - ptr = strrchr(app,'\\'); + char ApplicationPath[LC_MAXPATH], *ptr; + GetModuleFileName (NULL, ApplicationPath, LC_MAXPATH); + ptr = strrchr(ApplicationPath,'\\'); if (ptr) *(++ptr) = 0; + char CacheFilePath[LC_MAXPATH]; + if (SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, CacheFilePath) == S_OK) + { + PathAppend(CacheFilePath, "LeoCAD\\"); + _mkdir(CacheFilePath); + } + else + CacheFilePath[0] = 0; + g_App = new lcApplication(); main_window = new MainWnd(); - if (!g_App->Initialize(__argc, __targv, app)) + if (!g_App->Initialize(__argc, __targv, ApplicationPath, CacheFilePath)) return false; // Register the application's document templates. Document templates