Full Unicode patch with RTL Support & BiDi logic.

This commit is well documented, so no need to tell you my life story.

Full Unicode patch with RTL Support & BiDi logic.

Removed the legacy codePage, normalised to UTF8 (65001).

It also comes with:

CTRL + A : select text (highlighted)
CTRL + C : copy
CTRL + V : paste
CTRL + X : cut
CTRL + Y : redo
CTRL + Z : undo
This commit is contained in:
rtw1x1
2025-12-26 12:32:43 +00:00
parent d37607baa1
commit a955c50744
86 changed files with 4076 additions and 3839 deletions

View File

@@ -5,24 +5,43 @@
#include <io.h>
#include <assert.h>
#include <sys/stat.h>
#include <utf8.h>
#include "Utils.h"
#include "filedir.h"
char korean_tolower(const char c);
const char * CreateTempFileName(const char * c_pszPrefix)
const char* CreateTempFileName(const char* c_pszPrefix)
{
char szTempPath[MAX_PATH + 1];
static char szTempName[MAX_PATH + 1];
static std::string s_utf8TempName; // safe static storage
GetTempPath(MAX_PATH, szTempPath);
wchar_t wTempPath[MAX_PATH + 1]{};
wchar_t wTempName[MAX_PATH + 1]{};
GetTempFileName(szTempPath, // directory for temp files
c_pszPrefix ? c_pszPrefix : "etb", // temp file name prefix
c_pszPrefix ? true : false, // create unique name
szTempName); // buffer for name
// Get temp directory
if (!GetTempPathW(MAX_PATH, wTempPath))
return "";
return (szTempName);
// Prefix must be wide
wchar_t wPrefix[4] = L"etb";
if (c_pszPrefix && *c_pszPrefix)
{
std::wstring wp = Utf8ToWide(c_pszPrefix);
wcsncpy_s(wPrefix, wp.c_str(), 3);
}
// Create temp file name
if (!GetTempFileNameW(
wTempPath,
wPrefix,
0, // unique number generated by system
wTempName))
return "";
// Convert result to UTF-8 for engine
s_utf8TempName = WideToUtf8(wTempName);
return s_utf8TempName.c_str();
}
void GetFilePathNameExtension(const char * c_szFile, int len, std::string * pstPath, std::string * pstName, std::string * pstExt)
@@ -41,10 +60,10 @@ void GetFilePathNameExtension(const char * c_szFile, int len, std::string * pstP
if (ext == len && c == '.')
{
ext = pos;
ext = pos;
break;
}
if (c == '/' || c == '\\')
break;
}
@@ -83,7 +102,7 @@ void GetFileExtension(const char* c_szFile, int len, std::string* pstExt)
char c=c_szFile[pos];
if (ext==len && c=='.')
{
ext=pos;
ext=pos;
break;
}
@@ -91,7 +110,7 @@ void GetFileExtension(const char* c_szFile, int len, std::string* pstExt)
else if (c=='\\') break;
}
++ext;
++ext;
if (len>ext)
pstExt->append(c_szFile+ext, len-ext);
}
@@ -110,7 +129,7 @@ void GetFileNameParts(const char* c_szFile, int len, char* pszPath, char* pszNam
char c=c_szFile[pos];
if (ext==len && c=='.')
{
ext=pos;
ext=pos;
break;
}
@@ -127,7 +146,7 @@ void GetFileNameParts(const char* c_szFile, int len, char* pszPath, char* pszNam
else if (c=='\\') break;
}
if (pos)
if (pos)
{
++pos;
for (int i = 0; i < pos; ++i)
@@ -147,7 +166,7 @@ void GetFileNameParts(const char* c_szFile, int len, char* pszPath, char* pszNam
pszName[count] = '\0';
}
++ext;
++ext;
if (len > ext)
{
int count = 0;
@@ -163,10 +182,10 @@ void GetOldIndexingName(char * szName, int Index)
{
int dec, sign;
char Temp[512];
strcpy(Temp, _ecvt(Index, 256, &dec, &sign));
Temp[dec] = '\0';
strcat(szName, Temp);
}
@@ -423,38 +442,40 @@ bool IsGlobalFileName(const char * c_szFileName)
return strchr(c_szFileName, ':') != NULL;
}
void MyCreateDirectory(const char* path)
void MyCreateDirectory(const char* pathUtf8)
{
if (!path || !*path)
if (!pathUtf8 || !*pathUtf8)
return;
char * dir;
const char * p;
// Skip drive letter (C:\)
const char* path = pathUtf8;
if (strlen(path) >= 3 && path[1] == ':')
path += 3;
if (strlen(path) >= 3)
{
if (*(path + 1) == ':') // C:, D: 같은 경우를 체크
path += 3;
}
size_t len = strlen(pathUtf8) + 1;
char* dirUtf8 = new char[len];
p = path;
int len = strlen(path) + 1;
dir = new char[len];
const char* p = path;
while (*p)
{
if (*p == '/' || *p == '\\')
{
memset(dir, 0, len);
strncpy(dir, path, p - path);
CreateDirectory(dir, NULL);
}
memset(dirUtf8, 0, len);
strncpy(dirUtf8, pathUtf8, p - path + (path - pathUtf8));
// UTF-8 → UTF-16 for WinAPI
std::wstring wDir = Utf8ToWide(dirUtf8);
CreateDirectoryW(wDir.c_str(), nullptr);
}
++p;
}
delete [] dir;
// Create final directory too
std::wstring wFinal = Utf8ToWide(pathUtf8);
CreateDirectoryW(wFinal.c_str(), nullptr);
delete[] dirUtf8;
}
class CDirRemover : public CDir
@@ -484,22 +505,31 @@ class CDirRemover : public CDir
ms_strDirectoryDeque.push_back(strWorkingFolder);
return true;
}
bool OnFile(const char* c_szPathName, const char* c_szFileName)
{
std::string strFullPathName;
strFullPathName = c_szPathName;
strFullPathName += c_szFileName;
_chmod(strFullPathName.c_str(), _S_IWRITE);
DeleteFile(strFullPathName.c_str());
strFullPathName += c_szFileName;
std::wstring wFullPath = Utf8ToWide(strFullPathName);
// Make writable (use wide version)
_wchmod(wFullPath.c_str(), _S_IWRITE);
// Delete (use wide WinAPI)
DeleteFileW(wFullPath.c_str());
return true;
}
static void RemoveAllDirectory()
{
for (std::deque<std::string>::iterator itor = ms_strDirectoryDeque.begin(); itor != ms_strDirectoryDeque.end(); ++itor)
for (std::deque<std::string>::iterator itor = ms_strDirectoryDeque.begin();
itor != ms_strDirectoryDeque.end(); ++itor)
{
const std::string & c_rstrDirectory = *itor;
RemoveDirectory(c_rstrDirectory.c_str());
const std::string& dirUtf8 = *itor;
std::wstring wDir = Utf8ToWide(dirUtf8);
RemoveDirectoryW(wDir.c_str());
}
ms_strDirectoryDeque.clear();
@@ -511,14 +541,19 @@ class CDirRemover : public CDir
std::deque<std::string> CDirRemover::ms_strDirectoryDeque;
void RemoveAllDirectory(const char * c_szDirectoryName)
void RemoveAllDirectory(const char* c_szDirectoryName)
{
{
CDirRemover remover;
remover.Create("*.*", c_szDirectoryName);
CDirRemover::RemoveAllDirectory();
}
RemoveDirectory(c_szDirectoryName);
if (c_szDirectoryName && *c_szDirectoryName)
{
std::wstring wDir = Utf8ToWide(c_szDirectoryName);
RemoveDirectoryW(wDir.c_str());
}
}
void StringExceptCharacter(std::string * pstrString, const char * c_szCharacter)
@@ -573,14 +608,15 @@ bool SplitLine(const char * c_szLine, const char * c_szDelimeter, std::vector<st
return true;
}
void GetExcutedFileName(std::string & r_str)
void GetExcutedFileName(std::string& r_str)
{
char szPath[MAX_PATH+1];
wchar_t wPath[MAX_PATH + 1]{};
GetModuleFileName(NULL, szPath, MAX_PATH);
szPath[MAX_PATH] = '\0';
GetModuleFileNameW(nullptr, wPath, MAX_PATH);
wPath[MAX_PATH] = L'\0';
r_str = szPath;
// Convert UTF-16 → UTF-8 for engine use
r_str = WideToUtf8(wPath);
}
const char * _getf(const char* c_szFormat, ...)