diff --git a/Import/GacUI.cpp b/Import/GacUI.cpp index 3d07ec6b..1e7133c7 100644 --- a/Import/GacUI.cpp +++ b/Import/GacUI.cpp @@ -42340,7 +42340,49 @@ document_operation_visitors::SerializeRunVisitor if(run->text!=L"") { XmlElementWriter writer(parent); - writer.Text(run->text); + auto begin = run->text.Buffer(); + auto reading = begin; + auto last = reading; + while (true) + { + const wchar_t* tag = nullptr; + auto c = *reading; + switch (c) + { + case L'\n': + tag = L"br"; + break; + case L' ': + tag = L"sp"; + break; + case L'\t': + tag = L"tab"; + break; + } + + if (tag || c == 0) + { + if (reading > last) + { + auto end = reading[-1] == L'\r' ? reading - 1 : reading; + if (end > last) + { + writer.Text(run->text.Sub(last - begin, end - last)); + } + last = reading; + } + } + + if (tag) + { + writer.Element(tag); + } + else if (c == 0) + { + break; + } + reading++; + } } } diff --git a/Import/Vlpp.cpp b/Import/Vlpp.cpp index 4ee94122..59d305ed 100644 --- a/Import/Vlpp.cpp +++ b/Import/Vlpp.cpp @@ -459,6 +459,9 @@ FILESYSTEM.CPP #include #pragma comment(lib, "Shlwapi.lib") #elif defined VCZH_GCC +#include +#include +#include #endif namespace vl @@ -499,7 +502,11 @@ FilePath if (fullPath.Length() < 2 || fullPath[1] != L':') { wchar_t buffer[MAX_PATH + 1] = { 0 }; - GetCurrentDirectory(sizeof(buffer) / sizeof(*buffer), buffer); + auto result = GetCurrentDirectory(sizeof(buffer) / sizeof(*buffer), buffer); + if (result > MAX_PATH + 1 || result == 0) + { + throw ArgumentException(L"Failed to call GetCurrentDirectory.", L"vl::filesystem::FilePath::Initialize", L""); + } fullPath = WString(buffer) + L"\\" + fullPath; } { @@ -508,17 +515,56 @@ FilePath { fullPath += L"\\"; } - GetFullPathName(fullPath.Buffer(), sizeof(buffer) / sizeof(*buffer), buffer, NULL); + auto result = GetFullPathName(fullPath.Buffer(), sizeof(buffer) / sizeof(*buffer), buffer, NULL); + if (result > MAX_PATH + 1 || result == 0) + { + throw ArgumentException(L"The path is illegal.", L"vl::filesystem::FilePath::FilePath", L"_filePath"); + } fullPath = buffer; } +#elif defined VCZH_GCC + if (fullPath.Length() == 0) + fullPath = L"/"; - if (fullPath[fullPath.Length() - 1] == Delimiter) + if (fullPath[0] != Delimiter) + { + char buffer[PATH_MAX] = { 0 }; + getcwd(buffer, PATH_MAX); + fullPath = atow(AString(buffer)) + Delimiter + fullPath; + } + + { + collections::List components; + GetPathComponents(fullPath, components); + for(int i = 0; i < components.Count(); i++) + { + if(components[i] == L".") + { + components.RemoveAt(i); + i--; + } + else if(components[i] == L"..") + { + if(i > 0) + { + components.RemoveAt(i); + components.RemoveAt(i - 1); + i -= 2; + } + else + { + throw ArgumentException(L"Illegal path."); + } + } + } + + fullPath = ComponentsToPath(components); + } +#endif + if (fullPath != L"/" && fullPath[fullPath.Length() - 1] == Delimiter) { fullPath = fullPath.Left(fullPath.Length() - 1); } -#elif defined VCZH_GCC - throw 0; -#endif } FilePath::FilePath() @@ -572,7 +618,11 @@ FilePath if (!result) return false; return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0; #elif defined VCZH_GCC - throw 0; + struct stat info; + AString path = wtoa(fullPath); + int result = stat(path.Buffer(), &info); + if(result != 0) return false; + else return S_ISREG(info.st_mode); #endif } @@ -584,7 +634,11 @@ FilePath if (!result) return false; return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; #elif defined VCZH_GCC - throw 0; + struct stat info; + AString path = wtoa(fullPath); + int result = stat(path.Buffer(), &info); + if(result != 0) return false; + else return S_ISDIR(info.st_mode); #endif } @@ -593,7 +647,7 @@ FilePath #if defined VCZH_MSVC return fullPath == L""; #elif defined VCZH_GCC - throw 0; + return fullPath == L"/"; #endif } @@ -620,11 +674,11 @@ FilePath WString FilePath::GetRelativePathFor(const FilePath& _filePath) { -#if defined VCZH_MSVC if (fullPath.Length()==0 || _filePath.fullPath.Length()==0 || fullPath[0] != _filePath.fullPath[0]) { return _filePath.fullPath; } +#if defined VCZH_MSVC wchar_t buffer[MAX_PATH + 1] = { 0 }; PathRelativePathTo( buffer, @@ -635,10 +689,110 @@ FilePath ); return buffer; #elif defined VCZH_GCC - throw 0; + collections::List srcComponents, tgtComponents, resultComponents; + GetPathComponents(IsFolder() ? fullPath : GetFolder().GetFullPath(), srcComponents); + GetPathComponents(_filePath.fullPath, tgtComponents); + + int minLength = srcComponents.Count() <= tgtComponents.Count() ? srcComponents.Count() : tgtComponents.Count(); + int lastCommonComponent = 0; + for(int i = 0; i < minLength; i++) + { + if(srcComponents[i] == tgtComponents[i]) + { + lastCommonComponent = i; + } + else + break; + } + + for(int i = lastCommonComponent + 1; i < srcComponents.Count(); i++) + { + resultComponents.Add(L".."); + } + + for(int i = lastCommonComponent + 1; i < tgtComponents.Count(); i++) + { + resultComponents.Add(tgtComponents[i]); + } + + return ComponentsToPath(resultComponents); #endif } + void FilePath::GetPathComponents(WString path, collections::List& components) + { + WString pathRemaining = path; + WString delimiter = Delimiter; + + components.Clear(); + + while(true) + { + auto index = INVLOC.FindFirst(pathRemaining, delimiter, Locale::None); + if (index.key == -1) + break; + + if(index.key != 0) + components.Add(pathRemaining.Left(index.key)); + else + { +#if defined VCZH_GCC + // Unix absolute path starting with "/" + // components[0] will be L"/" + components.Add(delimiter); +#elif defined VCZH_MSVC + if(pathRemaining.Length() >= 2 && pathRemaining[1] == Delimiter) + { + // Windows UNC Path starting with "\\" + // components[0] will be L"\\" + components.Add(L"\\"); + index.value++; + } +#endif + } + + pathRemaining = pathRemaining.Right(pathRemaining.Length() - (index.key + index.value)); + } + + if(pathRemaining.Length() != 0) + { + components.Add(pathRemaining); + } + } + + WString FilePath::ComponentsToPath(const collections::List& components) + { + WString result; + WString delimiter = Delimiter; + + int i = 0; + +#if defined VCZH_GCC + // For Unix-like OSes, if first component is "/" then take it as absolute path + if(components.Count() > 0 && components[0] == delimiter) + { + result += delimiter; + i++; + } +#elif defined VCZH_MSVC + // For Windows, if first component is "\\" then it is an UNC path + if(components.Count() > 0 && components[0] == L"\\") + { + result += delimiter; + i++; + } +#endif + + for(; i < components.Count(); i++) + { + result += components[i]; + if(i + 1 < components.Count()) + result += delimiter; + } + + return result; + } + /*********************************************************************** File ***********************************************************************/ @@ -776,7 +930,8 @@ File #if defined VCZH_MSVC return DeleteFile(filePath.GetFullPath().Buffer()) != 0; #elif defined VCZH_GCC - throw 0; + AString path = wtoa(filePath.GetFullPath()); + return unlink(path.Buffer()) == 0; #endif } @@ -787,7 +942,9 @@ File WString newFileName = (filePath.GetFolder() / newName).GetFullPath(); return MoveFile(oldFileName.Buffer(), newFileName.Buffer()) != 0; #elif defined VCZH_GCC - throw 0; + AString oldFileName = wtoa(filePath.GetFullPath()); + AString newFileName = wtoa((filePath.GetFolder() / newName).GetFullPath()); + return rename(oldFileName.Buffer(), newFileName.Buffer()) == 0; #endif } @@ -851,7 +1008,33 @@ Folder } return true; #elif defined VCZH_GCC - throw 0; + if (!Exists()) return false; + + DIR *dir; + AString searchPath = wtoa(filePath.GetFullPath()); + + if ((dir = opendir(searchPath.Buffer())) == NULL) + { + return false; + } + + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) + { + WString childName = atow(AString(entry->d_name)); + FilePath childFullPath = filePath / childName; + if (childName != L"." && childName != L".." && childFullPath.IsFolder()) + { + folders.Add(Folder(childFullPath)); + } + } + + if (closedir(dir) != 0) + { + return false; + } + + return true; #endif } @@ -890,7 +1073,32 @@ Folder } return true; #elif defined VCZH_GCC - throw 0; + if (!Exists()) return false; + + DIR *dir; + AString searchPath = wtoa(filePath.GetFullPath()); + + if ((dir = opendir(searchPath.Buffer())) == NULL) + { + return false; + } + + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) + { + FilePath childFullPath = filePath / (atow(AString(entry->d_name))); + if (childFullPath.IsFile()) + { + files.Add(File(childFullPath)); + } + } + + if (closedir(dir) != 0) + { + return false; + } + + return true; #endif } @@ -901,7 +1109,6 @@ Folder bool Folder::Create(bool recursively)const { -#if defined VCZH_MSVC if (recursively) { auto folder = filePath.GetFolder(); @@ -911,17 +1118,19 @@ Folder } else { +#if defined VCZH_MSVC return CreateDirectory(filePath.GetFullPath().Buffer(), NULL) != 0; - } #elif defined VCZH_GCC - throw 0; + AString path = wtoa(filePath.GetFullPath()); + return mkdir(path.Buffer(), 0777) == 0; #endif + } } bool Folder::Delete(bool recursively)const { -#if defined VCZH_MSVC if (!Exists()) return false; + if (recursively) { List folders; @@ -940,9 +1149,11 @@ Folder return Delete(false); } +#if defined VCZH_MSVC return RemoveDirectory(filePath.GetFullPath().Buffer()) != 0; #elif defined VCZH_GCC - throw 0; + AString path = wtoa(filePath.GetFullPath()); + return rmdir(path.Buffer()) == 0; #endif } @@ -953,7 +1164,9 @@ Folder WString newFileName = (filePath.GetFolder() / newName).GetFullPath(); return MoveFile(oldFileName.Buffer(), newFileName.Buffer()) != 0; #elif defined VCZH_GCC - throw 0; + AString oldFileName = wtoa(filePath.GetFullPath()); + AString newFileName = wtoa((filePath.GetFolder() / newName).GetFullPath()); + return rename(oldFileName.Buffer(), newFileName.Buffer()) == 0; #endif } } @@ -3464,9 +3677,7 @@ THREADINGLINUX.CPP ***********************************************************************/ #ifdef VCZH_GCC #include -#include #include -#include #include #include #if defined(__APPLE__) || defined(__APPLE_CC__) diff --git a/Import/Vlpp.h b/Import/Vlpp.h index 3dd486e7..f1c7f351 100644 --- a/Import/Vlpp.h +++ b/Import/Vlpp.h @@ -16143,6 +16143,9 @@ namespace vl WString fullPath; void Initialize(); + + static void GetPathComponents(WString path, collections::List& components); + static WString ComponentsToPath(const collections::List& components); public: #if defined VCZH_MSVC static const wchar_t Delimiter = L'\\'; @@ -16199,6 +16202,7 @@ namespace vl /// The relative path. /// The referencing folder. WString GetRelativePathFor(const FilePath& _filePath); + }; /// Representing a file reference. diff --git a/Tools/GacGen.exe b/Tools/GacGen.exe index 538b62ad..0d9fc033 100644 Binary files a/Tools/GacGen.exe and b/Tools/GacGen.exe differ diff --git a/Tools/ParserGen.exe b/Tools/ParserGen.exe index 9310f4f8..c19b6424 100644 Binary files a/Tools/ParserGen.exe and b/Tools/ParserGen.exe differ diff --git a/Tutorial/GacUI_HelloWorlds/UIRes/MVVM.bin b/Tutorial/GacUI_HelloWorlds/UIRes/MVVM.bin index 02199812..81cdbdb7 100644 Binary files a/Tutorial/GacUI_HelloWorlds/UIRes/MVVM.bin and b/Tutorial/GacUI_HelloWorlds/UIRes/MVVM.bin differ diff --git a/Tutorial/GacUI_Layout/UIRes/RichTextEmbedding.bin b/Tutorial/GacUI_Layout/UIRes/RichTextEmbedding.bin index bc8f7397..8920199b 100644 Binary files a/Tutorial/GacUI_Layout/UIRes/RichTextEmbedding.bin and b/Tutorial/GacUI_Layout/UIRes/RichTextEmbedding.bin differ