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:
@@ -1,5 +1,6 @@
|
||||
#include "StdAfx.h"
|
||||
#include "GrpDIB.h"
|
||||
#include <utf8.h>
|
||||
|
||||
CGraphicDib::CGraphicDib()
|
||||
{
|
||||
@@ -74,10 +75,17 @@ void CGraphicDib::SetBkMode(int iBkMode)
|
||||
::SetBkMode(m_hDC, iBkMode);
|
||||
}
|
||||
|
||||
void CGraphicDib::TextOut(int ix, int iy, const char * c_szText)
|
||||
void CGraphicDib::TextOut(int ix, int iy, const char* c_szText)
|
||||
{
|
||||
::SetBkColor(m_hDC, 0);
|
||||
::TextOut(m_hDC, ix, iy, c_szText, strlen(c_szText));
|
||||
::SetBkColor(m_hDC, 0);
|
||||
|
||||
if (!c_szText || !*c_szText)
|
||||
return;
|
||||
|
||||
std::wstring wText = Utf8ToWide(c_szText);
|
||||
|
||||
if (!wText.empty())
|
||||
::TextOutW(m_hDC, ix, iy, wText.c_str(), (int)wText.length());
|
||||
}
|
||||
|
||||
void CGraphicDib::Put(HDC hDC, int x, int y)
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
#include "GrpDevice.h"
|
||||
#include "EterBase/Stl.h"
|
||||
#include "EterBase/Debug.h"
|
||||
|
||||
#include <intrin.h>
|
||||
#include <utf8.h>
|
||||
|
||||
bool CPU_HAS_SSE2 = false;
|
||||
bool GRAPHICS_CAPS_CAN_NOT_DRAW_LINE = false;
|
||||
@@ -48,9 +50,16 @@ void CGraphicDevice::RegisterWarningString(UINT uiMsg, const char * c_szString)
|
||||
|
||||
void CGraphicDevice::__WarningMessage(HWND hWnd, UINT uiMsg)
|
||||
{
|
||||
if (m_kMap_strWarningMessage.end() == m_kMap_strWarningMessage.find(uiMsg))
|
||||
auto it = m_kMap_strWarningMessage.find(uiMsg);
|
||||
if (it == m_kMap_strWarningMessage.end())
|
||||
return;
|
||||
MessageBox(hWnd, m_kMap_strWarningMessage[uiMsg].c_str(), "Warning", MB_OK|MB_TOPMOST);
|
||||
|
||||
const std::string& msgUtf8 = it->second;
|
||||
|
||||
std::wstring wMsg = Utf8ToWide(msgUtf8);
|
||||
std::wstring wCaption = L"Warning"; // static wide literal is fine
|
||||
|
||||
MessageBoxW(hWnd, wMsg.c_str(), wCaption.c_str(), MB_OK | MB_TOPMOST);
|
||||
}
|
||||
|
||||
void CGraphicDevice::MoveWebBrowserRect(const RECT& c_rcWebPage)
|
||||
@@ -148,9 +157,9 @@ LPDIRECT3DVERTEXDECLARATION9 CGraphicDevice::CreatePNTStreamVertexShader()
|
||||
|
||||
if (ms_lpd3dDevice->CreateVertexDeclaration(pShaderDecl, &dwShader) != D3D_OK)
|
||||
{
|
||||
char szError[1024];
|
||||
sprintf(szError, "Failed to create CreatePNTStreamVertexShader");
|
||||
MessageBox(NULL, szError, "Vertex Shader Error", MB_ICONSTOP);
|
||||
wchar_t szError[1024];
|
||||
swprintf(szError, L"Failed to create CreatePNTStreamVertexShader");
|
||||
MessageBoxW(NULL, szError, L"Vertex Shader Error", MB_ICONSTOP);
|
||||
}
|
||||
|
||||
return dwShader;
|
||||
@@ -172,9 +181,9 @@ LPDIRECT3DVERTEXDECLARATION9 CGraphicDevice::CreatePNT2StreamVertexShader()
|
||||
|
||||
if (ms_lpd3dDevice->CreateVertexDeclaration(pShaderDecl, &dwShader) != D3D_OK)
|
||||
{
|
||||
char szError[1024];
|
||||
sprintf(szError, "Failed to create CreatePNT2StreamVertexShader");
|
||||
MessageBox(NULL, szError, "Vertex Shader Error", MB_ICONSTOP);
|
||||
wchar_t szError[1024];
|
||||
swprintf(szError, L"Failed to create CreatePNT2StreamVertexShader");
|
||||
MessageBoxW(NULL, szError, L"Vertex Shader Error", MB_ICONSTOP);
|
||||
}
|
||||
|
||||
return dwShader;
|
||||
@@ -194,9 +203,9 @@ LPDIRECT3DVERTEXDECLARATION9 CGraphicDevice::CreatePTStreamVertexShader()
|
||||
|
||||
if (ms_lpd3dDevice->CreateVertexDeclaration(pShaderDecl, &dwShader) != D3D_OK)
|
||||
{
|
||||
char szError[1024];
|
||||
sprintf(szError, "Failed to create CreatePTStreamVertexShader");
|
||||
MessageBox(NULL, szError, "Vertex Shader Error", MB_ICONSTOP);
|
||||
wchar_t szError[1024];
|
||||
swprintf(szError, L"Failed to create CreatePTStreamVertexShader");
|
||||
MessageBoxW(NULL, szError, L"Vertex Shader Error", MB_ICONSTOP);
|
||||
}
|
||||
|
||||
return dwShader;
|
||||
@@ -221,9 +230,9 @@ LPDIRECT3DVERTEXDECLARATION9 CGraphicDevice::CreateDoublePNTStreamVertexShader()
|
||||
|
||||
if (ms_lpd3dDevice->CreateVertexDeclaration(pShaderDecl, &dwShader) != D3D_OK)
|
||||
{
|
||||
char szError[1024];
|
||||
sprintf(szError, "Failed to create CreateDoublePNTStreamVertexShader");
|
||||
MessageBox(NULL, szError, "Vertex Shader Error", MB_ICONSTOP);
|
||||
wchar_t szError[1024];
|
||||
swprintf(szError, L"Failed to create CreateDoublePNTStreamVertexShader");
|
||||
MessageBoxW(NULL, szError, L"Vertex Shader Error", MB_ICONSTOP);
|
||||
}
|
||||
|
||||
return dwShader;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "EterBase/Stl.h"
|
||||
|
||||
#include "Util.h"
|
||||
#include <utf8.h>
|
||||
|
||||
CGraphicFontTexture::CGraphicFontTexture()
|
||||
{
|
||||
@@ -69,75 +70,74 @@ void CGraphicFontTexture::DestroyDeviceObjects()
|
||||
bool CGraphicFontTexture::Create(const char* c_szFontName, int fontSize, bool bItalic)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
strncpy(m_fontName, c_szFontName, sizeof(m_fontName)-1);
|
||||
m_fontSize = fontSize;
|
||||
m_bItalic = bItalic;
|
||||
|
||||
// UTF-8 -> UTF-16 for font name
|
||||
std::wstring wFontName = Utf8ToWide(c_szFontName ? c_szFontName : "");
|
||||
wcsncpy_s(m_fontName, wFontName.c_str(), _TRUNCATE);
|
||||
|
||||
m_fontSize = fontSize;
|
||||
m_bItalic = bItalic;
|
||||
|
||||
m_x = 0;
|
||||
m_y = 0;
|
||||
m_step = 0;
|
||||
|
||||
DWORD width = 256,height = 256;
|
||||
DWORD width = 256, height = 256;
|
||||
if (GetMaxTextureWidth() > 512)
|
||||
width = 512;
|
||||
if (GetMaxTextureHeight() > 512)
|
||||
height = 512;
|
||||
|
||||
|
||||
if (!m_dib.Create(ms_hDC, width, height))
|
||||
return false;
|
||||
|
||||
HDC hDC = m_dib.GetDCHandle();
|
||||
|
||||
m_hFont = GetFont(GetDefaultCodePage());
|
||||
m_hFont = GetFont();
|
||||
|
||||
m_hFontOld=(HFONT)SelectObject(hDC, m_hFont);
|
||||
m_hFontOld = (HFONT)SelectObject(hDC, m_hFont);
|
||||
SetTextColor(hDC, RGB(255, 255, 255));
|
||||
SetBkColor(hDC, 0);
|
||||
SetBkColor(hDC, 0);
|
||||
|
||||
if (!AppendTexture())
|
||||
return false;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HFONT CGraphicFontTexture::GetFont(WORD codePage)
|
||||
HFONT CGraphicFontTexture::GetFont()
|
||||
{
|
||||
HFONT hFont = NULL;
|
||||
TFontMap::iterator i = m_fontMap.find(codePage);
|
||||
HFONT hFont = nullptr;
|
||||
|
||||
if(i != m_fontMap.end())
|
||||
{
|
||||
hFont = i->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGFONT logFont;
|
||||
// For Unicode, codePage should NOT affect font selection anymore
|
||||
static const WORD kUnicodeFontKey = 0;
|
||||
|
||||
memset(&logFont, 0, sizeof(LOGFONT));
|
||||
TFontMap::iterator it = m_fontMap.find(kUnicodeFontKey);
|
||||
if (it != m_fontMap.end())
|
||||
return it->second;
|
||||
|
||||
logFont.lfHeight = m_fontSize;
|
||||
logFont.lfEscapement = 0;
|
||||
logFont.lfOrientation = 0;
|
||||
logFont.lfWeight = FW_NORMAL;
|
||||
logFont.lfItalic = (BYTE) m_bItalic;
|
||||
logFont.lfUnderline = FALSE;
|
||||
logFont.lfStrikeOut = FALSE;
|
||||
logFont.lfCharSet = GetCharsetFromCodePage(codePage);
|
||||
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
||||
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||
logFont.lfQuality = ANTIALIASED_QUALITY;
|
||||
logFont.lfPitchAndFamily = DEFAULT_PITCH;
|
||||
//Tracenf("font: %s", GetFontFaceFromCodePage(codePage));
|
||||
strcpy(logFont.lfFaceName, m_fontName); //GetFontFaceFromCodePage(codePage));
|
||||
//strcpy(logFont.lfFaceName, GetFontFaceFromCodePage(codePage));
|
||||
LOGFONTW logFont{};
|
||||
|
||||
hFont = CreateFontIndirect(&logFont);
|
||||
logFont.lfHeight = m_fontSize;
|
||||
logFont.lfEscapement = 0;
|
||||
logFont.lfOrientation = 0;
|
||||
logFont.lfWeight = FW_NORMAL;
|
||||
logFont.lfItalic = (BYTE)m_bItalic;
|
||||
logFont.lfUnderline = FALSE;
|
||||
logFont.lfStrikeOut = FALSE;
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
||||
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||
logFont.lfQuality = ANTIALIASED_QUALITY;
|
||||
logFont.lfPitchAndFamily = DEFAULT_PITCH;
|
||||
|
||||
m_fontMap.insert(TFontMap::value_type(codePage, hFont));
|
||||
}
|
||||
// Copy Unicode font face name safely
|
||||
wcsncpy_s(logFont.lfFaceName, m_fontName, _TRUNCATE);
|
||||
|
||||
hFont = CreateFontIndirectW(&logFont);
|
||||
|
||||
if (hFont)
|
||||
m_fontMap.insert(TFontMap::value_type(kUnicodeFontKey, hFont));
|
||||
|
||||
return hFont;
|
||||
}
|
||||
@@ -189,9 +189,9 @@ bool CGraphicFontTexture::UpdateTexture()
|
||||
return true;
|
||||
}
|
||||
|
||||
CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::GetCharacterInfomation(WORD codePage, wchar_t keyValue)
|
||||
CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::GetCharacterInfomation(wchar_t keyValue)
|
||||
{
|
||||
TCharacterKey code(codePage, keyValue);
|
||||
TCharacterKey code = keyValue;
|
||||
|
||||
TCharacterInfomationMap::iterator f = m_charInfoMap.find(code);
|
||||
|
||||
@@ -201,22 +201,20 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::GetCharacterInfo
|
||||
}
|
||||
else
|
||||
{
|
||||
return &f->second;
|
||||
return &f->second;
|
||||
}
|
||||
}
|
||||
|
||||
CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterInfomation(TCharacterKey code)
|
||||
CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterInfomation(TCharacterKey keyValue)
|
||||
{
|
||||
HDC hDC = m_dib.GetDCHandle();
|
||||
SelectObject(hDC, GetFont(code.first));
|
||||
|
||||
wchar_t keyValue = code.second;
|
||||
SelectObject(hDC, GetFont());
|
||||
|
||||
if (keyValue == 0x08)
|
||||
keyValue = L' '; // 탭은 공백으로 바꾼다 (아랍 출력시 탭 사용: NAME:\tTEXT -> TEXT\t:NAME 로 전환됨 )
|
||||
keyValue = L' '; // 탭은 공백으로 바꾼다 (아랍 출력시 탭 사용: NAME:\tTEXT -> TEXT\t:NAME 로 전환됨 )
|
||||
|
||||
ABCFLOAT stABC;
|
||||
SIZE size;
|
||||
ABCFLOAT stABC;
|
||||
SIZE size;
|
||||
|
||||
if (!GetTextExtentPoint32W(hDC, &keyValue, 1, &size) || !GetCharABCWidthsFloatW(hDC, keyValue, keyValue, &stABC))
|
||||
return NULL;
|
||||
@@ -254,21 +252,20 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterI
|
||||
}
|
||||
|
||||
TextOutW(hDC, m_x, m_y, &keyValue, 1);
|
||||
|
||||
|
||||
int nChrX;
|
||||
int nChrY;
|
||||
int nChrWidth = size.cx;
|
||||
int nChrHeight = size.cy;
|
||||
int nDIBWidth = m_dib.GetWidth();
|
||||
|
||||
|
||||
DWORD*pdwDIBData=(DWORD*)m_dib.GetPointer();
|
||||
DWORD*pdwDIBData=(DWORD*)m_dib.GetPointer();
|
||||
DWORD*pdwDIBBase=pdwDIBData+nDIBWidth*m_y+m_x;
|
||||
DWORD*pdwDIBRow;
|
||||
|
||||
|
||||
pdwDIBRow=pdwDIBBase;
|
||||
for (nChrY=0; nChrY<nChrHeight; ++nChrY, pdwDIBRow+=nDIBWidth)
|
||||
{
|
||||
{
|
||||
for (nChrX=0; nChrX<nChrWidth; ++nChrX)
|
||||
{
|
||||
pdwDIBRow[nChrX]=(pdwDIBRow[nChrX]&0xff) ? 0xffff : 0;
|
||||
@@ -278,7 +275,7 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterI
|
||||
float rhwidth = 1.0f / float(width);
|
||||
float rhheight = 1.0f / float(height);
|
||||
|
||||
TCharacterInfomation& rNewCharInfo = m_charInfoMap[code];
|
||||
TCharacterInfomation& rNewCharInfo = m_charInfoMap[keyValue];
|
||||
|
||||
rNewCharInfo.index = static_cast<short>(m_pFontTextureVector.size() - 1);
|
||||
rNewCharInfo.width = size.cx;
|
||||
@@ -292,7 +289,7 @@ CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterI
|
||||
m_x += size.cx;
|
||||
|
||||
if (m_step < size.cy)
|
||||
m_step = size.cy;
|
||||
m_step = size.cy;
|
||||
|
||||
m_isDirty = true;
|
||||
|
||||
|
||||
@@ -9,73 +9,73 @@
|
||||
|
||||
class CGraphicFontTexture : public CGraphicTexture
|
||||
{
|
||||
public:
|
||||
typedef std::pair<WORD,wchar_t> TCharacterKey;
|
||||
public:
|
||||
typedef wchar_t TCharacterKey;
|
||||
|
||||
typedef struct SCharacterInfomation
|
||||
{
|
||||
short index;
|
||||
short width;
|
||||
short height;
|
||||
float left;
|
||||
float top;
|
||||
float right;
|
||||
float bottom;
|
||||
float advance;
|
||||
} TCharacterInfomation;
|
||||
typedef struct SCharacterInfomation
|
||||
{
|
||||
short index;
|
||||
short width;
|
||||
short height;
|
||||
float left;
|
||||
float top;
|
||||
float right;
|
||||
float bottom;
|
||||
float advance;
|
||||
} TCharacterInfomation;
|
||||
|
||||
typedef std::vector<TCharacterInfomation*> TPCharacterInfomationVector;
|
||||
typedef std::vector<TCharacterInfomation*> TPCharacterInfomationVector;
|
||||
|
||||
public:
|
||||
CGraphicFontTexture();
|
||||
virtual ~CGraphicFontTexture();
|
||||
public:
|
||||
CGraphicFontTexture();
|
||||
virtual ~CGraphicFontTexture();
|
||||
|
||||
void Destroy();
|
||||
bool Create(const char* c_szFontName, int fontSize, bool bItalic);
|
||||
void Destroy();
|
||||
bool Create(const char* c_szFontName, int fontSize, bool bItalic);
|
||||
|
||||
bool CreateDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
bool CreateDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
|
||||
bool CheckTextureIndex(DWORD dwTexture);
|
||||
void SelectTexture(DWORD dwTexture);
|
||||
bool CheckTextureIndex(DWORD dwTexture);
|
||||
void SelectTexture(DWORD dwTexture);
|
||||
|
||||
bool UpdateTexture();
|
||||
bool UpdateTexture();
|
||||
|
||||
TCharacterInfomation* GetCharacterInfomation(WORD codePage, wchar_t keyValue);
|
||||
TCharacterInfomation* UpdateCharacterInfomation(TCharacterKey code);
|
||||
TCharacterInfomation* GetCharacterInfomation(wchar_t keyValue);
|
||||
TCharacterInfomation* UpdateCharacterInfomation(TCharacterKey keyValue);
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
protected:
|
||||
void Initialize();
|
||||
protected:
|
||||
void Initialize();
|
||||
|
||||
bool AppendTexture();
|
||||
bool AppendTexture();
|
||||
|
||||
HFONT GetFont(WORD codePage);
|
||||
HFONT GetFont();
|
||||
|
||||
protected:
|
||||
typedef std::vector<CGraphicImageTexture*> TGraphicImageTexturePointerVector;
|
||||
typedef std::map<TCharacterKey, TCharacterInfomation> TCharacterInfomationMap;
|
||||
typedef std::map<WORD, HFONT> TFontMap;
|
||||
protected:
|
||||
typedef std::vector<CGraphicImageTexture*> TGraphicImageTexturePointerVector;
|
||||
typedef std::map<TCharacterKey, TCharacterInfomation> TCharacterInfomationMap;
|
||||
typedef std::map<WORD, HFONT> TFontMap;
|
||||
|
||||
protected:
|
||||
CGraphicDib m_dib;
|
||||
protected:
|
||||
CGraphicDib m_dib;
|
||||
|
||||
HFONT m_hFontOld;
|
||||
HFONT m_hFont;
|
||||
HFONT m_hFontOld;
|
||||
HFONT m_hFont;
|
||||
|
||||
TGraphicImageTexturePointerVector m_pFontTextureVector;
|
||||
TGraphicImageTexturePointerVector m_pFontTextureVector;
|
||||
|
||||
TCharacterInfomationMap m_charInfoMap;
|
||||
TCharacterInfomationMap m_charInfoMap;
|
||||
|
||||
TFontMap m_fontMap;
|
||||
TFontMap m_fontMap;
|
||||
|
||||
int m_x;
|
||||
int m_y;
|
||||
int m_step;
|
||||
bool m_isDirty;
|
||||
int m_x;
|
||||
int m_y;
|
||||
int m_step;
|
||||
bool m_isDirty;
|
||||
|
||||
TCHAR m_fontName[LF_FACESIZE];
|
||||
LONG m_fontSize;
|
||||
bool m_bItalic;
|
||||
TCHAR m_fontName[LF_FACESIZE];
|
||||
LONG m_fontSize;
|
||||
bool m_bItalic;
|
||||
};
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "GrpD3DXBuffer.h"
|
||||
#include "StateManager.h"
|
||||
|
||||
#include <utf8.h>
|
||||
|
||||
CPixelShader::CPixelShader()
|
||||
{
|
||||
Initialize();
|
||||
@@ -29,23 +31,46 @@ void CPixelShader::Destroy()
|
||||
|
||||
bool CPixelShader::CreateFromDiskFile(const char* c_szFileName)
|
||||
{
|
||||
Destroy();
|
||||
Destroy();
|
||||
|
||||
LPD3DXBUFFER lpd3dxShaderBuffer;
|
||||
LPD3DXBUFFER lpd3dxErrorBuffer;
|
||||
|
||||
if (FAILED(
|
||||
D3DXAssembleShaderFromFile(c_szFileName, 0, NULL, 0, &lpd3dxShaderBuffer, &lpd3dxErrorBuffer)
|
||||
))
|
||||
return false;
|
||||
if (!c_szFileName || !*c_szFileName)
|
||||
return false;
|
||||
|
||||
CDirect3DXBuffer shaderBuffer(lpd3dxShaderBuffer);
|
||||
CDirect3DXBuffer errorBuffer(lpd3dxErrorBuffer);
|
||||
// UTF-8 -> UTF-16 for D3DX
|
||||
std::wstring wFileName = Utf8ToWide(c_szFileName);
|
||||
|
||||
if (FAILED(ms_lpd3dDevice->CreatePixelShader((DWORD*)shaderBuffer.GetPointer(), &m_handle)))
|
||||
return false;
|
||||
LPD3DXBUFFER lpd3dxShaderBuffer = nullptr;
|
||||
LPD3DXBUFFER lpd3dxErrorBuffer = nullptr;
|
||||
|
||||
return true;
|
||||
HRESULT hr = D3DXAssembleShaderFromFileW(
|
||||
wFileName.c_str(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
0,
|
||||
&lpd3dxShaderBuffer,
|
||||
&lpd3dxErrorBuffer
|
||||
);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Log compiler error text (it is ANSI/ASCII)
|
||||
if (lpd3dxErrorBuffer)
|
||||
{
|
||||
const char* err = (const char*)lpd3dxErrorBuffer->GetBufferPointer();
|
||||
TraceError("Shader compile error: %s", err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CDirect3DXBuffer shaderBuffer(lpd3dxShaderBuffer);
|
||||
CDirect3DXBuffer errorBuffer(lpd3dxErrorBuffer);
|
||||
|
||||
if (FAILED(ms_lpd3dDevice->CreatePixelShader(
|
||||
(DWORD*)shaderBuffer.GetPointer(),
|
||||
&m_handle)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPixelShader::Set()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "StateManager.h"
|
||||
|
||||
#include <comdef.h>
|
||||
#include <utf8.h>
|
||||
|
||||
DWORD CScreen::ms_diffuseColor = 0xffffffff;
|
||||
DWORD CScreen::ms_clearColor = 0L;
|
||||
@@ -669,8 +670,11 @@ BOOL CScreen::RestoreDevice()
|
||||
if (FAILED(hrReset))
|
||||
{
|
||||
_com_error err(hrReset);
|
||||
LPCTSTR errMsg = err.ErrorMessage();
|
||||
TraceError(errMsg);
|
||||
LPCWSTR errMsgW = err.ErrorMessage(); // wide string
|
||||
|
||||
std::string errUtf8 = WideToUtf8(errMsgW);
|
||||
TraceError("%s", errUtf8.c_str());
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@ class CGraphicTextInstance
|
||||
HORIZONTAL_ALIGN_CENTER = 0x02,
|
||||
HORIZONTAL_ALIGN_RIGHT = 0x03,
|
||||
};
|
||||
|
||||
enum EVerticalAlign
|
||||
{
|
||||
VERTICAL_ALIGN_TOP = 0x10,
|
||||
@@ -23,6 +24,13 @@ class CGraphicTextInstance
|
||||
VERTICAL_ALIGN_BOTTOM = 0x30
|
||||
};
|
||||
|
||||
enum class ETextDirection : unsigned char
|
||||
{
|
||||
Auto = 0,
|
||||
LTR = 1,
|
||||
RTL = 2,
|
||||
};
|
||||
|
||||
public:
|
||||
static void Hyperlink_UpdateMousePos(int x, int y);
|
||||
static int Hyperlink_GetText(char* buf, int len);
|
||||
@@ -65,14 +73,24 @@ class CGraphicTextInstance
|
||||
const std::string& GetValueStringReference();
|
||||
WORD GetTextLineCount();
|
||||
|
||||
void SetTextDirection(ETextDirection dir);
|
||||
ETextDirection GetTextDirection() const { return m_direction; }
|
||||
bool IsRTL() const
|
||||
{
|
||||
// For AUTO mode, use computed result from BiDi analysis
|
||||
if (m_direction == ETextDirection::Auto)
|
||||
return m_computedRTL;
|
||||
// For explicit direction, derive from m_direction
|
||||
return (m_direction == ETextDirection::RTL);
|
||||
}
|
||||
|
||||
int PixelPositionToCharacterPosition(int iPixelPosition);
|
||||
int GetHorizontalAlign();
|
||||
|
||||
protected:
|
||||
void __Initialize();
|
||||
int __DrawCharacter(CGraphicFontTexture * pFontTexture, WORD codePage, wchar_t text, DWORD dwColor);
|
||||
int __DrawCharacter(CGraphicFontTexture * pFontTexture, wchar_t text, DWORD dwColor);
|
||||
void __GetTextPos(DWORD index, float* x, float* y);
|
||||
int __GetTextTag(const wchar_t * src, int maxLen, int & tagLen, std::wstring & extraInfo);
|
||||
|
||||
protected:
|
||||
struct SHyperlink
|
||||
@@ -112,11 +130,15 @@ class CGraphicTextInstance
|
||||
private:
|
||||
bool m_isUpdate;
|
||||
bool m_isUpdateFontTexture;
|
||||
|
||||
bool m_computedRTL; // Result of BiDi analysis (used when m_direction == Auto)
|
||||
|
||||
CGraphicText::TRef m_roText;
|
||||
CGraphicFontTexture::TPCharacterInfomationVector m_pCharInfoVector;
|
||||
std::vector<DWORD> m_dwColorInfoVector;
|
||||
std::vector<SHyperlink> m_hyperlinkVector;
|
||||
std::vector<int> m_logicalToVisualPos; // Maps logical cursor pos (UTF-16 with tags) to visual pos (rendered chars)
|
||||
std::vector<int> m_visualToLogicalPos; // Reverse mapping: visual pos -> logical pos
|
||||
ETextDirection m_direction = ETextDirection::Auto; // Will be overwritten by __Initialize()
|
||||
|
||||
public:
|
||||
static void CreateSystem(UINT uCapacity);
|
||||
@@ -125,10 +147,8 @@ class CGraphicTextInstance
|
||||
static CGraphicTextInstance* New();
|
||||
static void Delete(CGraphicTextInstance* pkInst);
|
||||
|
||||
static CDynamicPool<CGraphicTextInstance> ms_kPool;
|
||||
static CDynamicPool<CGraphicTextInstance> ms_kPool;
|
||||
};
|
||||
|
||||
extern const char* FindToken(const char* begin, const char* end);
|
||||
extern int ReadToken(const char* token);
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "GrpD3DXBuffer.h"
|
||||
#include "StateManager.h"
|
||||
|
||||
#include <utf8.h>
|
||||
|
||||
CVertexShader::CVertexShader()
|
||||
{
|
||||
Initialize();
|
||||
@@ -29,21 +31,44 @@ void CVertexShader::Destroy()
|
||||
|
||||
bool CVertexShader::CreateFromDiskFile(const char* c_szFileName, const DWORD* c_pdwVertexDecl)
|
||||
{
|
||||
Destroy();
|
||||
Destroy();
|
||||
|
||||
LPD3DXBUFFER lpd3dxShaderBuffer;
|
||||
LPD3DXBUFFER lpd3dxErrorBuffer;
|
||||
|
||||
if (FAILED(
|
||||
D3DXAssembleShaderFromFile(c_szFileName, 0, NULL, 0, &lpd3dxShaderBuffer, &lpd3dxErrorBuffer)
|
||||
)) return false;
|
||||
if (!c_szFileName || !*c_szFileName)
|
||||
return false;
|
||||
|
||||
if (FAILED(
|
||||
ms_lpd3dDevice->CreateVertexShader((const DWORD*)lpd3dxShaderBuffer->GetBufferPointer(), &m_handle)
|
||||
))
|
||||
return false;
|
||||
// UTF-8 → UTF-16 for D3DX
|
||||
std::wstring wFileName = Utf8ToWide(c_szFileName);
|
||||
|
||||
return true;
|
||||
LPD3DXBUFFER lpd3dxShaderBuffer = nullptr;
|
||||
LPD3DXBUFFER lpd3dxErrorBuffer = nullptr;
|
||||
|
||||
HRESULT hr = D3DXAssembleShaderFromFileW(
|
||||
wFileName.c_str(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
0,
|
||||
&lpd3dxShaderBuffer,
|
||||
&lpd3dxErrorBuffer
|
||||
);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (lpd3dxErrorBuffer)
|
||||
{
|
||||
const char* err = (const char*)lpd3dxErrorBuffer->GetBufferPointer();
|
||||
TraceError("Vertex shader compile error: %s", err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(
|
||||
ms_lpd3dDevice->CreateVertexShader(
|
||||
(const DWORD*)lpd3dxShaderBuffer->GetBufferPointer(),
|
||||
&m_handle
|
||||
)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CVertexShader::Set()
|
||||
|
||||
1185
src/EterLib/IME.cpp
1185
src/EterLib/IME.cpp
File diff suppressed because it is too large
Load Diff
@@ -6,203 +6,237 @@
|
||||
|
||||
#include "DIMM.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class IIMEEventSink
|
||||
{
|
||||
public:
|
||||
virtual bool OnWM_CHAR( WPARAM wParam, LPARAM lParam ) = 0;
|
||||
virtual void OnUpdate() = 0;
|
||||
public:
|
||||
virtual bool OnWM_CHAR( WPARAM wParam, LPARAM lParam ) = 0;
|
||||
virtual void OnUpdate() = 0;
|
||||
|
||||
virtual void OnChangeCodePage() = 0;
|
||||
virtual void OnOpenCandidateList() = 0;
|
||||
virtual void OnCloseCandidateList() = 0;
|
||||
|
||||
virtual void OnOpenCandidateList() = 0;
|
||||
virtual void OnCloseCandidateList() = 0;
|
||||
|
||||
virtual void OnOpenReadingWnd() = 0;
|
||||
virtual void OnCloseReadingWnd() = 0;
|
||||
virtual void OnOpenReadingWnd() = 0;
|
||||
virtual void OnCloseReadingWnd() = 0;
|
||||
};
|
||||
|
||||
class CIME
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
IMEREADING_MAXLEN = 128,
|
||||
IMESTR_MAXLEN = 1024,
|
||||
IMECANDIDATE_MAXLEN = 32768,
|
||||
MAX_CANDLIST = 10,
|
||||
MAX_CANDIDATE_LENGTH = 256
|
||||
};
|
||||
public:
|
||||
enum
|
||||
{
|
||||
IMEREADING_MAXLEN = 128,
|
||||
IMESTR_MAXLEN = 1024,
|
||||
IMECANDIDATE_MAXLEN = 32768,
|
||||
MAX_CANDLIST = 10,
|
||||
MAX_CANDIDATE_LENGTH = 256
|
||||
};
|
||||
|
||||
public:
|
||||
CIME();
|
||||
virtual ~CIME();
|
||||
public:
|
||||
CIME();
|
||||
virtual ~CIME();
|
||||
|
||||
bool Initialize(HWND hWnd);
|
||||
void Uninitialize(void);
|
||||
bool Initialize(HWND hWnd);
|
||||
void Uninitialize(void);
|
||||
|
||||
static void Clear();
|
||||
static void Clear();
|
||||
|
||||
void SetMax(int iMax);
|
||||
void SetUserMax(int iMax);
|
||||
void SetText(const char* c_szText, int len);
|
||||
int GetText(std::string & rstrText, bool addCodePage=false);
|
||||
const char* GetCodePageText();
|
||||
int GetCodePage();
|
||||
void SetMax(int iMax);
|
||||
void SetUserMax(int iMax);
|
||||
static void SetText(const char* c_szText, int len);
|
||||
int GetText(std::string & rstrText);
|
||||
|
||||
// Candidate List
|
||||
int GetCandidateCount();
|
||||
int GetCandidatePageCount();
|
||||
int GetCandidate(DWORD index, std::string & rstrText);
|
||||
int GetCandidateSelection();
|
||||
// Candidate List
|
||||
int GetCandidateCount();
|
||||
int GetCandidatePageCount();
|
||||
int GetCandidate(DWORD index, std::string & rstrText);
|
||||
int GetCandidateSelection();
|
||||
|
||||
// Reading Information
|
||||
int GetReading(std::string & rstrText);
|
||||
int GetReadingError();
|
||||
// Reading Information
|
||||
int GetReading(std::string & rstrText);
|
||||
int GetReadingError();
|
||||
|
||||
void SetInputMode(DWORD dwMode);
|
||||
DWORD GetInputMode();
|
||||
void SetInputMode(DWORD dwMode);
|
||||
DWORD GetInputMode();
|
||||
|
||||
bool IsIMEEnabled();
|
||||
void EnableIME(bool bEnable=true);
|
||||
void DisableIME();
|
||||
bool IsIMEEnabled();
|
||||
void EnableIME(bool bEnable=true);
|
||||
void DisableIME();
|
||||
|
||||
void EnableCaptureInput();
|
||||
void DisableCaptureInput();
|
||||
bool IsCaptureEnabled();
|
||||
void EnableCaptureInput();
|
||||
void DisableCaptureInput();
|
||||
bool IsCaptureEnabled();
|
||||
|
||||
void SetNumberMode();
|
||||
void SetStringMode();
|
||||
bool __IsWritable(wchar_t key);
|
||||
void AddExceptKey(wchar_t key);
|
||||
void ClearExceptKey();
|
||||
void SetNumberMode();
|
||||
void SetStringMode();
|
||||
bool __IsWritable(wchar_t key);
|
||||
void AddExceptKey(wchar_t key);
|
||||
void ClearExceptKey();
|
||||
|
||||
void PasteTextFromClipBoard();
|
||||
void EnablePaste(bool bFlag);
|
||||
void PasteString(const char * str);
|
||||
static void FinalizeString(bool bSend = false);
|
||||
void PasteTextFromClipBoard();
|
||||
void EnablePaste(bool bFlag);
|
||||
void PasteString(const char * str);
|
||||
static void FinalizeString(bool bSend = false);
|
||||
|
||||
void UseDefaultIME();
|
||||
void SelectAll();
|
||||
void DeleteSelection();
|
||||
void CopySelectionToClipboard(HWND hWnd);
|
||||
void CutSelectionToClipboard(HWND hWnd);
|
||||
|
||||
static int GetCurPos();
|
||||
static int GetCompLen();
|
||||
static int GetULBegin();
|
||||
static int GetULEnd();
|
||||
void UseDefaultIME();
|
||||
|
||||
static void CloseCandidateList();
|
||||
static void CloseReadingInformation();
|
||||
static void ChangeInputLanguage();
|
||||
static void ChangeInputLanguageWorker();
|
||||
static int GetCurPos();
|
||||
static int GetCompLen();
|
||||
static int GetULBegin();
|
||||
static int GetULEnd();
|
||||
|
||||
LRESULT WMInputLanguage(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WMStartComposition(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WMComposition(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WMEndComposition(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WMNotify(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WMChar(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
|
||||
static int GetSelBegin();
|
||||
static int GetSelEnd();
|
||||
static void ClearSelection();
|
||||
|
||||
protected:
|
||||
void IncCurPos();
|
||||
void DecCurPos();
|
||||
void SetCurPos(int offset);
|
||||
void DelCurPos();
|
||||
static void CloseCandidateList();
|
||||
static void CloseReadingInformation();
|
||||
static void ChangeInputLanguage();
|
||||
static void ChangeInputLanguageWorker();
|
||||
|
||||
protected:
|
||||
static void CheckInputLocale();
|
||||
static void CheckToggleState();
|
||||
static void SetSupportLevel( DWORD dwImeLevel );
|
||||
LRESULT WMInputLanguage(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WMStartComposition(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WMComposition(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WMEndComposition(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WMNotify(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WMChar(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void InsertString(wchar_t* szString, int iSize);
|
||||
public:
|
||||
struct SUndoState
|
||||
{
|
||||
std::wstring text;
|
||||
int curpos = 0;
|
||||
int lastpos = 0;
|
||||
int selbegin = 0;
|
||||
int selend = 0;
|
||||
};
|
||||
|
||||
void OnChar(wchar_t c);
|
||||
static void PushUndoState();
|
||||
static void Undo();
|
||||
static void Redo();
|
||||
static void ClearUndoRedo();
|
||||
|
||||
UINT GetCodePageFromLang( LANGID langid );
|
||||
void ResultProcess(HIMC hImc);
|
||||
void CompositionProcessBuilding(HIMC hImc);
|
||||
void CompositionProcess(HIMC hImc);
|
||||
void AttributeProcess(HIMC hImc);
|
||||
void CandidateProcess(HIMC hImc);
|
||||
void ReadingProcess(HIMC hImc);
|
||||
static bool CanUndo();
|
||||
static bool CanRedo();
|
||||
|
||||
bool IsMax(const wchar_t* wInput, int len);
|
||||
private:
|
||||
static void RestoreState(const SUndoState& st);
|
||||
|
||||
DWORD GetImeId(UINT uIndex = 0);
|
||||
bool GetReadingWindowOrientation();
|
||||
static void SetupImeApi();
|
||||
private:
|
||||
static std::vector<SUndoState> ms_undo;
|
||||
static std::vector<SUndoState> ms_redo;
|
||||
static const size_t MAX_UNDO = 64;
|
||||
|
||||
static INPUTCONTEXT* (WINAPI * _ImmLockIMC)( HIMC );
|
||||
static BOOL (WINAPI * _ImmUnlockIMC)( HIMC );
|
||||
static LPVOID (WINAPI * _ImmLockIMCC)( HIMCC );
|
||||
static BOOL (WINAPI * _ImmUnlockIMCC)( HIMCC );
|
||||
protected:
|
||||
void IncCurPos();
|
||||
void DecCurPos();
|
||||
void SetCurPos(int offset);
|
||||
void DelCurPos();
|
||||
|
||||
static UINT (WINAPI * _GetReadingString)( HIMC, UINT, LPWSTR, PINT, BOOL*, PUINT );
|
||||
static BOOL (WINAPI * _ShowReadingWindow)( HIMC, BOOL );
|
||||
protected:
|
||||
static void CheckInputLocale();
|
||||
static void CheckToggleState();
|
||||
static void SetSupportLevel( DWORD dwImeLevel );
|
||||
|
||||
protected:
|
||||
HIMC m_hOrgIMC;
|
||||
int m_max;
|
||||
int m_userMax;
|
||||
void InsertString(wchar_t* szString, int iSize);
|
||||
|
||||
BOOL m_bOnlyNumberMode;
|
||||
void OnChar(wchar_t c);
|
||||
|
||||
std::vector<wchar_t> m_exceptKey;
|
||||
void ResultProcess(HIMC hImc);
|
||||
void CompositionProcessBuilding(HIMC hImc);
|
||||
void CompositionProcess(HIMC hImc);
|
||||
void AttributeProcess(HIMC hImc);
|
||||
void CandidateProcess(HIMC hImc);
|
||||
void ReadingProcess(HIMC hImc);
|
||||
|
||||
bool m_bEnablePaste;
|
||||
bool m_bUseDefaultIME;
|
||||
bool IsMax(const wchar_t* wInput, int len);
|
||||
|
||||
DWORD GetImeId(UINT uIndex = 0);
|
||||
bool GetReadingWindowOrientation();
|
||||
static void SetupImeApi();
|
||||
|
||||
static INPUTCONTEXT* (WINAPI * _ImmLockIMC)( HIMC );
|
||||
static BOOL (WINAPI * _ImmUnlockIMC)( HIMC );
|
||||
static LPVOID (WINAPI * _ImmLockIMCC)( HIMCC );
|
||||
static BOOL (WINAPI * _ImmUnlockIMCC)( HIMCC );
|
||||
|
||||
static UINT (WINAPI * _GetReadingString)( HIMC, UINT, LPWSTR, PINT, BOOL*, PUINT );
|
||||
static BOOL (WINAPI * _ShowReadingWindow)( HIMC, BOOL );
|
||||
|
||||
protected:
|
||||
HIMC m_hOrgIMC;
|
||||
int m_max;
|
||||
int m_userMax;
|
||||
|
||||
BOOL m_bOnlyNumberMode;
|
||||
|
||||
std::vector<wchar_t> m_exceptKey;
|
||||
|
||||
bool m_bEnablePaste;
|
||||
bool m_bUseDefaultIME;
|
||||
|
||||
|
||||
public:
|
||||
static bool ms_bInitialized;
|
||||
static bool ms_bDisableIMECompletely;
|
||||
static bool ms_bUILessMode;
|
||||
static bool ms_bImeEnabled;
|
||||
static bool ms_bCaptureInput;
|
||||
static bool ms_bChineseIME;
|
||||
static bool ms_bUseIMMCandidate;
|
||||
public:
|
||||
static bool ms_bInitialized;
|
||||
static bool ms_bDisableIMECompletely;
|
||||
static bool ms_bUILessMode;
|
||||
static bool ms_bImeEnabled;
|
||||
static bool ms_bCaptureInput;
|
||||
static bool ms_bChineseIME;
|
||||
static bool ms_bUseIMMCandidate;
|
||||
|
||||
static HWND ms_hWnd;
|
||||
static HKL ms_hklCurrent;
|
||||
static char ms_szKeyboardLayout[KL_NAMELENGTH+1];
|
||||
static OSVERSIONINFOA ms_stOSVI;
|
||||
static HWND ms_hWnd;
|
||||
static HKL ms_hklCurrent;
|
||||
static wchar_t ms_szKeyboardLayout[KL_NAMELENGTH+1];
|
||||
static OSVERSIONINFOW ms_stOSVI;
|
||||
|
||||
static HINSTANCE ms_hImm32Dll;
|
||||
static HINSTANCE ms_hCurrentImeDll;
|
||||
static DWORD ms_dwImeState;
|
||||
static HINSTANCE ms_hImm32Dll;
|
||||
static HINSTANCE ms_hCurrentImeDll;
|
||||
static DWORD ms_dwImeState;
|
||||
|
||||
static DWORD ms_adwId[2];
|
||||
static DWORD ms_adwId[2];
|
||||
|
||||
// IME Level
|
||||
static DWORD ms_dwIMELevel;
|
||||
static DWORD ms_dwIMELevelSaved;
|
||||
// IME Level
|
||||
static DWORD ms_dwIMELevel;
|
||||
static DWORD ms_dwIMELevelSaved;
|
||||
|
||||
// Candidate List
|
||||
static bool ms_bCandidateList;
|
||||
static DWORD ms_dwCandidateCount;
|
||||
static bool ms_bVerticalCandidate;
|
||||
static int ms_iCandListIndexBase;
|
||||
static WCHAR ms_wszCandidate[CIME::MAX_CANDLIST][MAX_CANDIDATE_LENGTH];
|
||||
static DWORD ms_dwCandidateSelection;
|
||||
static DWORD ms_dwCandidatePageSize;
|
||||
// Candidate List
|
||||
static bool ms_bCandidateList;
|
||||
static DWORD ms_dwCandidateCount;
|
||||
static bool ms_bVerticalCandidate;
|
||||
static int ms_iCandListIndexBase;
|
||||
static WCHAR ms_wszCandidate[CIME::MAX_CANDLIST][MAX_CANDIDATE_LENGTH];
|
||||
static DWORD ms_dwCandidateSelection;
|
||||
static DWORD ms_dwCandidatePageSize;
|
||||
|
||||
// Reading Information
|
||||
static bool ms_bReadingInformation;
|
||||
static int ms_iReadingError;
|
||||
static bool ms_bHorizontalReading;
|
||||
static std::vector<wchar_t> ms_wstrReading;
|
||||
// Reading Information
|
||||
static bool ms_bReadingInformation;
|
||||
static int ms_iReadingError;
|
||||
static bool ms_bHorizontalReading;
|
||||
static std::vector<wchar_t> ms_wstrReading;
|
||||
|
||||
// Indicator
|
||||
static wchar_t* ms_wszCurrentIndicator;
|
||||
// Indicator
|
||||
static wchar_t* ms_wszCurrentIndicator;
|
||||
|
||||
static IIMEEventSink* ms_pEvent;
|
||||
static IIMEEventSink* ms_pEvent;
|
||||
|
||||
wchar_t m_wszComposition[IMESTR_MAXLEN];
|
||||
static wchar_t m_wText[IMESTR_MAXLEN];
|
||||
wchar_t m_wszComposition[IMESTR_MAXLEN];
|
||||
static wchar_t m_wText[IMESTR_MAXLEN];
|
||||
|
||||
static int ms_compLen;
|
||||
static int ms_curpos;
|
||||
static int ms_lastpos;
|
||||
static int ms_ulbegin;
|
||||
static int ms_ulend;
|
||||
static int ms_compLen;
|
||||
static int ms_curpos;
|
||||
static int ms_lastpos;
|
||||
static int ms_ulbegin;
|
||||
static int ms_ulend;
|
||||
|
||||
static UINT ms_uOutputCodePage;
|
||||
static UINT ms_uInputCodePage;
|
||||
static int ms_selbegin;
|
||||
static int ms_selend;
|
||||
static int ms_compCaret;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "MsWindow.h"
|
||||
|
||||
#include <windowsx.h>
|
||||
#include <utf8.h>
|
||||
|
||||
CMSWindow::TWindowClassSet CMSWindow::ms_stWCSet;
|
||||
HINSTANCE CMSWindow::ms_hInstance = NULL;
|
||||
@@ -61,27 +62,32 @@ void CMSWindow::Destroy()
|
||||
|
||||
bool CMSWindow::Create(const char* c_szName, int brush, DWORD cs, DWORD ws, HICON hIcon, int iCursorResource)
|
||||
{
|
||||
//assert(ms_hInstance != NULL);
|
||||
Destroy();
|
||||
|
||||
const char* c_szClassName = RegisterWindowClass(cs, brush, MSWindowProcedure, hIcon, iCursorResource);
|
||||
|
||||
m_hWnd = CreateWindow(
|
||||
c_szClassName,
|
||||
c_szName,
|
||||
ws,
|
||||
0, 0, 0, 0,
|
||||
NULL,
|
||||
NULL,
|
||||
ms_hInstance,
|
||||
NULL);
|
||||
const wchar_t* wClassName =
|
||||
RegisterWindowClass(cs, brush, MSWindowProcedure, hIcon, iCursorResource);
|
||||
|
||||
if (!wClassName)
|
||||
return false;
|
||||
|
||||
// Window title is UTF-8 → convert
|
||||
std::wstring wWindowName = Utf8ToWide(c_szName ? c_szName : "");
|
||||
|
||||
m_hWnd = CreateWindowW(
|
||||
wClassName, // already wide
|
||||
wWindowName.c_str(), // wide
|
||||
ws,
|
||||
0, 0, 0, 0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
ms_hInstance,
|
||||
nullptr
|
||||
);
|
||||
|
||||
if (!m_hWnd)
|
||||
return false;
|
||||
|
||||
SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||
//DestroyWindow(ImmGetDefaultIMEWnd(m_hWnd));
|
||||
|
||||
SetWindowLongPtrW(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -197,7 +203,11 @@ void CMSWindow::AdjustSize(int width, int height)
|
||||
|
||||
void CMSWindow::SetText(const char* c_szText)
|
||||
{
|
||||
SetWindowText(m_hWnd, c_szText);
|
||||
if (!m_hWnd)
|
||||
return;
|
||||
|
||||
std::wstring wText = Utf8ToWide(c_szText ? c_szText : "");
|
||||
SetWindowTextW(m_hWnd, wText.c_str());
|
||||
}
|
||||
|
||||
void CMSWindow::SetSize(int width, int height)
|
||||
@@ -205,37 +215,41 @@ void CMSWindow::SetSize(int width, int height)
|
||||
SetWindowPos(m_hWnd, NULL, 0, 0, width, height, SWP_NOZORDER|SWP_NOMOVE);
|
||||
}
|
||||
|
||||
const char * CMSWindow::RegisterWindowClass(DWORD style, int brush, WNDPROC pfnWndProc, HICON hIcon, int iCursorResource)
|
||||
const wchar_t* CMSWindow::RegisterWindowClass(DWORD style, int brush, WNDPROC pfnWndProc, HICON hIcon, int iCursorResource)
|
||||
{
|
||||
char szClassName[1024];
|
||||
sprintf(szClassName, "eter - s%x:b%x:p:%x", style, brush, (DWORD) pfnWndProc);
|
||||
wchar_t szClassName[1024];
|
||||
swprintf_s(
|
||||
szClassName,
|
||||
L"eter - s%x:b%x:p:%p",
|
||||
style,
|
||||
brush,
|
||||
pfnWndProc
|
||||
);
|
||||
|
||||
TWindowClassSet::iterator f = ms_stWCSet.find((char*) szClassName);
|
||||
// Use a set of std::wstring (NOT char*)
|
||||
TWindowClassSet::iterator it = ms_stWCSet.find(szClassName);
|
||||
if (it != ms_stWCSet.end())
|
||||
return it->c_str();
|
||||
|
||||
if (f != ms_stWCSet.end())
|
||||
return *f;
|
||||
// Persist the string
|
||||
std::wstring staticClassName = szClassName;
|
||||
ms_stWCSet.insert(staticClassName);
|
||||
|
||||
const char* c_szStaticClassName = stl_static_string(szClassName).c_str();
|
||||
WNDCLASSW wc{};
|
||||
wc.style = style;
|
||||
wc.lpfnWndProc = pfnWndProc;
|
||||
wc.hCursor = LoadCursor(ms_hInstance, MAKEINTRESOURCE(iCursorResource));
|
||||
wc.hIcon = hIcon ? hIcon : LoadIcon(ms_hInstance, IDI_APPLICATION);
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(brush);
|
||||
wc.hInstance = ms_hInstance;
|
||||
wc.lpszClassName = staticClassName.c_str();
|
||||
wc.lpszMenuName = nullptr;
|
||||
|
||||
ms_stWCSet.insert((char * const) c_szStaticClassName);
|
||||
|
||||
WNDCLASS wc;
|
||||
if (!RegisterClassW(&wc))
|
||||
return nullptr;
|
||||
|
||||
wc.style = 0;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.lpfnWndProc = pfnWndProc;
|
||||
wc.hCursor = LoadCursor(ms_hInstance, MAKEINTRESOURCE(iCursorResource));
|
||||
wc.hIcon = hIcon ? hIcon : LoadIcon(ms_hInstance, IDI_APPLICATION);
|
||||
wc.hbrBackground = (HBRUSH) GetStockObject(brush);
|
||||
wc.hInstance = ms_hInstance;
|
||||
wc.lpszClassName = c_szStaticClassName;
|
||||
wc.lpszMenuName = "";
|
||||
|
||||
if (!RegisterClass(&wc))
|
||||
return "";
|
||||
|
||||
return c_szStaticClassName;
|
||||
// Return pointer stable inside the set
|
||||
return ms_stWCSet.find(staticClassName)->c_str();
|
||||
}
|
||||
|
||||
CMSWindow::CMSWindow()
|
||||
|
||||
@@ -42,10 +42,10 @@ class CMSWindow
|
||||
virtual void OnSize(WPARAM wParam, LPARAM lParam);
|
||||
|
||||
protected:
|
||||
const char* RegisterWindowClass(DWORD style, int brush, WNDPROC pfnWndProc, HICON hIcon=NULL, int iCursorResource=32512);
|
||||
const wchar_t* RegisterWindowClass(DWORD style, int brush, WNDPROC pfnWndProc, HICON hIcon=NULL, int iCursorResource=32512);
|
||||
|
||||
protected:
|
||||
typedef std::set<char*, stl_sz_less> TWindowClassSet;
|
||||
typedef std::set<std::wstring> TWindowClassSet;
|
||||
|
||||
protected:
|
||||
HWND m_hWnd;
|
||||
|
||||
@@ -2,38 +2,30 @@
|
||||
#include "TextBar.h"
|
||||
#include "EterLib/Util.h"
|
||||
|
||||
#include <utf8.h>
|
||||
|
||||
void CTextBar::__SetFont(int fontSize, bool isBold)
|
||||
{
|
||||
int iCodePage = GetDefaultCodePage();
|
||||
LOGFONTW logFont{};
|
||||
|
||||
LOGFONT logFont;
|
||||
logFont.lfHeight = fontSize;
|
||||
logFont.lfEscapement = 0;
|
||||
logFont.lfOrientation = 0;
|
||||
logFont.lfWeight = isBold ? FW_BOLD : FW_NORMAL;
|
||||
logFont.lfItalic = FALSE;
|
||||
logFont.lfUnderline = FALSE;
|
||||
logFont.lfStrikeOut = FALSE;
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
||||
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||
logFont.lfQuality = ANTIALIASED_QUALITY;
|
||||
logFont.lfPitchAndFamily = DEFAULT_PITCH;
|
||||
wcscpy_s(logFont.lfFaceName, LF_FACESIZE, L"Tahoma");
|
||||
|
||||
memset(&logFont, 0, sizeof(LOGFONT));
|
||||
|
||||
logFont.lfHeight = fontSize;
|
||||
logFont.lfEscapement = 0;
|
||||
logFont.lfOrientation = 0;
|
||||
|
||||
if (isBold)
|
||||
logFont.lfWeight = FW_BOLD;
|
||||
else
|
||||
logFont.lfWeight = FW_NORMAL;
|
||||
|
||||
logFont.lfItalic = FALSE;
|
||||
logFont.lfUnderline = FALSE;
|
||||
logFont.lfStrikeOut = FALSE;
|
||||
logFont.lfCharSet = GetCharsetFromCodePage(iCodePage);
|
||||
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
||||
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||
logFont.lfQuality = ANTIALIASED_QUALITY;
|
||||
logFont.lfPitchAndFamily = DEFAULT_PITCH;
|
||||
strcpy(logFont.lfFaceName, GetFontFaceFromCodePage(iCodePage));
|
||||
m_hFont = CreateFontIndirect(&logFont);
|
||||
|
||||
|
||||
HDC hdc = m_dib.GetDCHandle();
|
||||
m_hOldFont = (HFONT)SelectObject(hdc, m_hFont);
|
||||
|
||||
}
|
||||
|
||||
void CTextBar::SetTextColor(int r, int g, int b)
|
||||
@@ -41,11 +33,24 @@ void CTextBar::SetTextColor(int r, int g, int b)
|
||||
HDC hDC = m_dib.GetDCHandle();
|
||||
::SetTextColor(hDC, RGB(r, g, b));
|
||||
}
|
||||
|
||||
void CTextBar::GetTextExtent(const char * c_szText, SIZE* p_size)
|
||||
|
||||
void CTextBar::GetTextExtent(const char* c_szText, SIZE* p_size)
|
||||
{
|
||||
if (!c_szText || !p_size)
|
||||
{
|
||||
if (p_size)
|
||||
{
|
||||
p_size->cx = 0;
|
||||
p_size->cy = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
HDC hDC = m_dib.GetDCHandle();
|
||||
GetTextExtentPoint32(hDC, c_szText, strlen(c_szText), p_size);
|
||||
|
||||
// UTF-8 → UTF-16
|
||||
std::wstring wText = Utf8ToWide(c_szText);
|
||||
GetTextExtentPoint32W(hDC, wText.c_str(), static_cast<int>(wText.length()), p_size);
|
||||
}
|
||||
|
||||
void CTextBar::TextOut(int ix, int iy, const char * c_szText)
|
||||
@@ -63,10 +68,9 @@ void CTextBar::OnCreate()
|
||||
|
||||
CTextBar::CTextBar(int fontSize, bool isBold)
|
||||
{
|
||||
m_hOldFont = NULL;
|
||||
m_hOldFont = NULL;
|
||||
m_fontSize = fontSize;
|
||||
m_isBold = isBold;
|
||||
|
||||
}
|
||||
|
||||
CTextBar::~CTextBar()
|
||||
|
||||
@@ -57,16 +57,24 @@ std::wstring GetTextTagOutputString(const wchar_t * src, int src_len)
|
||||
|
||||
if (tag == TEXT_TAG_PLAIN || tag == TEXT_TAG_TAG)
|
||||
{
|
||||
if (hyperlinkStep == 0)
|
||||
// Show normal text (step 0) AND hyperlink visible text (step 2)
|
||||
if (hyperlinkStep == 0 || hyperlinkStep == 2)
|
||||
{
|
||||
++output_len;
|
||||
dst += src[i];
|
||||
}
|
||||
}
|
||||
else if (tag == TEXT_TAG_HYPERLINK_START)
|
||||
hyperlinkStep = 1;
|
||||
hyperlinkStep = 1; // Start metadata (hidden)
|
||||
else if (tag == TEXT_TAG_HYPERLINK_END)
|
||||
hyperlinkStep = 0;
|
||||
{
|
||||
// First |h: end metadata, start visible (1 -> 2)
|
||||
// Second |h: end visible (2 -> 0)
|
||||
if (hyperlinkStep == 1)
|
||||
hyperlinkStep = 2;
|
||||
else if (hyperlinkStep == 2)
|
||||
hyperlinkStep = 0;
|
||||
}
|
||||
|
||||
i += len;
|
||||
}
|
||||
@@ -98,7 +106,8 @@ int GetTextTagInternalPosFromRenderPos(const wchar_t * src, int src_len, int off
|
||||
}
|
||||
else if (tag == TEXT_TAG_PLAIN || tag == TEXT_TAG_TAG)
|
||||
{
|
||||
if (hyperlinkStep == 0)
|
||||
// Show normal text (step 0) AND hyperlink visible text (step 2)
|
||||
if (hyperlinkStep == 0 || hyperlinkStep == 2)
|
||||
{
|
||||
if (!color_tag)
|
||||
internal_offset = i;
|
||||
@@ -111,9 +120,16 @@ int GetTextTagInternalPosFromRenderPos(const wchar_t * src, int src_len, int off
|
||||
}
|
||||
}
|
||||
else if (tag == TEXT_TAG_HYPERLINK_START)
|
||||
hyperlinkStep = 1;
|
||||
hyperlinkStep = 1; // Start metadata (hidden)
|
||||
else if (tag == TEXT_TAG_HYPERLINK_END)
|
||||
hyperlinkStep = 0;
|
||||
{
|
||||
// First |h: end metadata, start visible (1 -> 2)
|
||||
// Second |h: end visible (2 -> 0)
|
||||
if (hyperlinkStep == 1)
|
||||
hyperlinkStep = 2;
|
||||
else if (hyperlinkStep == 2)
|
||||
hyperlinkStep = 0;
|
||||
}
|
||||
|
||||
i += len;
|
||||
}
|
||||
|
||||
@@ -133,252 +133,3 @@ D3DXCOLOR TokenToColor(CTokenVector & rVector)
|
||||
atof(rVector[2].c_str()),
|
||||
atof(rVector[3].c_str()));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::string gs_fontFace="";
|
||||
static DWORD gs_codePage=0;
|
||||
|
||||
int CALLBACK EnumFontFamExProc(CONST LOGFONT* plogFont, CONST TEXTMETRIC* /*textMetric*/, DWORD /*dwWord*/, LPARAM lParam)
|
||||
{
|
||||
return stricmp((const char*)lParam, plogFont->lfFaceName);
|
||||
}
|
||||
|
||||
int GetCharsetFromCodePage(WORD codePage)
|
||||
{
|
||||
switch( codePage )
|
||||
{
|
||||
case CP_932:
|
||||
return SHIFTJIS_CHARSET;
|
||||
case CP_949:
|
||||
return HANGUL_CHARSET;
|
||||
case CP_936:
|
||||
return GB2312_CHARSET;
|
||||
case CP_950:
|
||||
return CHINESEBIG5_CHARSET;
|
||||
case CP_1253:
|
||||
return GREEK_CHARSET;
|
||||
case CP_1254:
|
||||
return TURKISH_CHARSET;
|
||||
case CP_1255:
|
||||
return HEBREW_CHARSET;
|
||||
case CP_1256:
|
||||
return ARABIC_CHARSET;
|
||||
case CP_1257:
|
||||
return BALTIC_CHARSET;
|
||||
case CP_1258:
|
||||
return VIETNAMESE_CHARSET;
|
||||
case CP_874:
|
||||
return THAI_CHARSET;
|
||||
case CP_1250:
|
||||
return EASTEUROPE_CHARSET;
|
||||
case CP_1251:
|
||||
return RUSSIAN_CHARSET;
|
||||
default:
|
||||
return DEFAULT_CHARSET;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char* GetFontFaceFromCodePageNT(WORD codePage)
|
||||
{
|
||||
switch( codePage )
|
||||
{
|
||||
case CP_932:
|
||||
return "MS PGothic";
|
||||
case CP_949:
|
||||
return "GulimChe";
|
||||
case CP_936:
|
||||
return "SimSun";
|
||||
case CP_950:
|
||||
return "MingLiU";
|
||||
case CP_874:
|
||||
return "Tahoma";
|
||||
case CP_1252:
|
||||
return "Arial";
|
||||
case CP_1256:
|
||||
return "Tahoma";
|
||||
case CP_1258:
|
||||
return "Tahoma";
|
||||
case CP_65001:
|
||||
return "Arial";
|
||||
default:
|
||||
return "Arial";
|
||||
}
|
||||
}
|
||||
const char* GetFontFaceFromCodePage9x(WORD codePage)
|
||||
{
|
||||
switch( codePage )
|
||||
{
|
||||
case CP_932:
|
||||
return "굃굍 굊긕긘긞긏";
|
||||
case CP_949:
|
||||
return "굴림체";
|
||||
case CP_936:
|
||||
return "芥竟";
|
||||
case CP_950:
|
||||
return "꾄ⁿ톱";
|
||||
case CP_874:
|
||||
return "Tahoma";
|
||||
case CP_1252:
|
||||
return "Arial";
|
||||
case CP_1256:
|
||||
return "Tahoma";
|
||||
case CP_1258:
|
||||
return "Tahoma";
|
||||
case CP_65001:
|
||||
return "Arial";
|
||||
default:
|
||||
return "Arial";
|
||||
}
|
||||
}
|
||||
|
||||
DWORD GetDefaultCodePage()
|
||||
{
|
||||
return gs_codePage;
|
||||
}
|
||||
|
||||
const char * GetDefaultFontFace()
|
||||
{
|
||||
return gs_fontFace.c_str();
|
||||
}
|
||||
|
||||
const char* GetFontFaceFromCodePage(WORD codePage)
|
||||
{
|
||||
LOGFONTA logFont = {};
|
||||
logFont.lfCharSet = GetCharsetFromCodePage(codePage);
|
||||
|
||||
const char* fontFace = GetFontFaceFromCodePage9x(codePage);
|
||||
|
||||
HDC hDC = GetDC(NULL);
|
||||
|
||||
if(EnumFontFamiliesEx(hDC, &logFont, EnumFontFamExProc, (LPARAM)fontFace, 0) == 0)
|
||||
{
|
||||
ReleaseDC(NULL, hDC);
|
||||
return fontFace;
|
||||
}
|
||||
|
||||
fontFace = GetFontFaceFromCodePageNT(codePage);
|
||||
|
||||
if(EnumFontFamiliesEx(hDC, &logFont, EnumFontFamExProc, (LPARAM)fontFace, 0) == 0)
|
||||
{
|
||||
ReleaseDC(NULL, hDC);
|
||||
return fontFace;
|
||||
}
|
||||
|
||||
ReleaseDC(NULL, hDC);
|
||||
|
||||
return GetDefaultFontFace();
|
||||
}
|
||||
|
||||
void SetDefaultFontFace(const char* fontFace)
|
||||
{
|
||||
gs_fontFace=fontFace;
|
||||
}
|
||||
|
||||
bool SetDefaultCodePage(DWORD codePage)
|
||||
{
|
||||
gs_codePage=codePage;
|
||||
|
||||
std::string fontFace=GetFontFaceFromCodePage(codePage);
|
||||
if (fontFace.empty())
|
||||
return false;
|
||||
|
||||
SetDefaultFontFace(fontFace.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int __base64_get( const int c )
|
||||
{
|
||||
if( 'A' <= c && c <= 'Z' )
|
||||
return c-'A';
|
||||
if( 'a' <= c && c <= 'z' )
|
||||
return c - 'a' + 26;
|
||||
if( '0' <= c && c <= '9' )
|
||||
return c - '0' + 52;
|
||||
if( c == '+' )
|
||||
return 62;
|
||||
if( c == '/' )
|
||||
return 63;
|
||||
if( c == '=' ) // end of line
|
||||
return -1;
|
||||
return -2; // non value;
|
||||
}
|
||||
|
||||
void __strcat1(char * str,int i)
|
||||
{
|
||||
char result[2];
|
||||
result[0] = i;
|
||||
result[1] = NULL;
|
||||
strcat(str,result);
|
||||
}
|
||||
|
||||
void base64_decode(const char * str,char * resultStr)
|
||||
{
|
||||
int nCount=0, i=0, r, result;
|
||||
int length = strlen(str);
|
||||
char szDest[5]="";
|
||||
|
||||
strcpy(resultStr,"");
|
||||
while(nCount < length)
|
||||
{
|
||||
i=0;
|
||||
strcpy(szDest, "");
|
||||
while(nCount<length && i<4) // 4개의 바이트를 얻는다.
|
||||
{
|
||||
r = str[nCount++];
|
||||
result = __base64_get(r);
|
||||
if(result!=-2)
|
||||
{
|
||||
if(result!=-1)
|
||||
szDest[i++] = result;
|
||||
else szDest[i++] = '@'; // It's end (64번은 디코딩시 사용되지 않기 때문)
|
||||
}
|
||||
}
|
||||
|
||||
if(i==4) // 4개의 소스를 모두 얻어냈다. 디코드 시작
|
||||
{
|
||||
if( nCount+3 >= length ) // 데이터의 끝에 도달했다.
|
||||
{
|
||||
if( szDest[1] == '@' )
|
||||
{
|
||||
__strcat1(resultStr,(szDest[0]<<2));
|
||||
break;
|
||||
}// exit while loop
|
||||
else
|
||||
__strcat1(resultStr,(szDest[0]<<2 | szDest[1]>>4)); // 1 Byte
|
||||
if( szDest[2] == '@' )
|
||||
{
|
||||
__strcat1(resultStr,(szDest[1]<<4));
|
||||
break;
|
||||
}
|
||||
else
|
||||
__strcat1(resultStr,(szDest[1]<<4 | szDest[2]>>2)); // 2 Byte
|
||||
if( szDest[3] == '@' )
|
||||
{
|
||||
__strcat1(resultStr,(szDest[2]<<6));
|
||||
break;
|
||||
}
|
||||
else
|
||||
__strcat1(resultStr,(szDest[2]<<6 | szDest[3])); // 3 Byte
|
||||
}
|
||||
else
|
||||
{
|
||||
__strcat1(resultStr,(szDest[0]<<2 | szDest[1]>>4)); // 1 Byte
|
||||
__strcat1(resultStr,(szDest[1]<<4 | szDest[2]>>2)); // 2 Byte
|
||||
__strcat1(resultStr,(szDest[2]<<6 | szDest[3])); // 3 Byte
|
||||
}
|
||||
}
|
||||
|
||||
}// end of while
|
||||
|
||||
for (i = 0; i < strlen(resultStr); i++)
|
||||
{
|
||||
char c = resultStr[i];
|
||||
int xx = i + 5;
|
||||
resultStr[i] = char(c ^ xx);
|
||||
}
|
||||
// E
|
||||
}
|
||||
|
||||
@@ -96,18 +96,5 @@ extern D3DXCOLOR TokenToColor(CTokenVector & rVector);
|
||||
|
||||
#define GOTO_CHILD_NODE(TextFileLoader, Index) CTextFileLoader::CGotoChild Child(TextFileLoader, Index);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern int CALLBACK EnumFontFamExProc(CONST LOGFONT* plogFont, CONST TEXTMETRIC* textMetric, DWORD dwWord, LPARAM lParam);
|
||||
extern int GetCharsetFromCodePage(WORD codePage);
|
||||
extern const char* GetFontFaceFromCodePageNT(WORD codePage);
|
||||
extern const char* GetFontFaceFromCodePage9x(WORD codePage);
|
||||
extern DWORD GetDefaultCodePage();
|
||||
extern const char * GetDefaultFontFace();
|
||||
extern const char* GetFontFaceFromCodePage(WORD codePage);
|
||||
extern void SetDefaultFontFace(const char* fontFace);
|
||||
extern bool SetDefaultCodePage(DWORD codePage);
|
||||
extern void base64_decode(const char * str,char * resultStr);
|
||||
|
||||
extern DWORD GetMaxTextureWidth();
|
||||
extern DWORD GetMaxTextureHeight();
|
||||
@@ -3,34 +3,48 @@
|
||||
|
||||
using namespace script;
|
||||
|
||||
#define ishan(ch) (((ch) & 0xE0) > 0x90)
|
||||
#define isnhspace(ch) (!ishan(ch) && isspace(ch))
|
||||
static const char* Utf8Next(const char* p, const char* end)
|
||||
{
|
||||
if (!p || p >= end) return end;
|
||||
unsigned char c = (unsigned char)*p;
|
||||
if (c < 0x80) return p + 1;
|
||||
if ((c >> 5) == 0x6) return (p + 2 <= end) ? p + 2 : end;
|
||||
if ((c >> 4) == 0xE) return (p + 3 <= end) ? p + 3 : end;
|
||||
if ((c >> 3) == 0x1E) return (p + 4 <= end) ? p + 4 : end;
|
||||
// invalid lead byte -> move 1 to avoid infinite loops
|
||||
return p + 1;
|
||||
}
|
||||
|
||||
|
||||
extern DWORD GetDefaultCodePage();
|
||||
static const char* Utf8Prev(const char* base, const char* p)
|
||||
{
|
||||
if (!base || !p || p <= base) return base;
|
||||
const char* q = p - 1;
|
||||
// move back over continuation bytes 10xxxxxx
|
||||
while (q > base && (((unsigned char)*q & 0xC0) == 0x80))
|
||||
--q;
|
||||
return q;
|
||||
}
|
||||
|
||||
const char* LocaleString_FindChar(const char* base, int len, char test)
|
||||
{
|
||||
if (!base)
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
DWORD codePage = GetDefaultCodePage();
|
||||
|
||||
int pos = 0;
|
||||
while (pos < len)
|
||||
{
|
||||
const char* cur = base + pos;
|
||||
const char* next = CharNextExA(codePage, cur, 0);
|
||||
int cur_len = next - cur;
|
||||
const char* next = Utf8Next(cur, base + len);
|
||||
int cur_len = int(next - cur);
|
||||
|
||||
if (cur_len > 1)
|
||||
{
|
||||
pos += cur_len;
|
||||
}
|
||||
else if (1 == cur_len)
|
||||
else if (cur_len == 1)
|
||||
{
|
||||
if (*cur == test)
|
||||
return cur;
|
||||
|
||||
++pos;
|
||||
}
|
||||
else
|
||||
@@ -38,36 +52,31 @@ const char* LocaleString_FindChar(const char* base, int len, char test)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int LocaleString_RightTrim(char* base, int len)
|
||||
{
|
||||
DWORD codePage = GetDefaultCodePage();
|
||||
|
||||
int pos = len;
|
||||
|
||||
|
||||
while (pos > 0)
|
||||
{
|
||||
char* cur = base + pos;
|
||||
char* prev = CharPrevExA(codePage, base, cur , 0);
|
||||
|
||||
int prev_len = cur - prev;
|
||||
char* prev = (char*)Utf8Prev(base, cur);
|
||||
|
||||
int prev_len = int(cur - prev);
|
||||
if (prev_len != 1)
|
||||
break;
|
||||
|
||||
if (!isspace((unsigned char) *prev) && *prev != '\n' && *prev != '\r')
|
||||
break;
|
||||
|
||||
|
||||
if (!isspace((unsigned char)*prev) && *prev != '\n' && *prev != '\r')
|
||||
break;
|
||||
|
||||
*prev = '\0';
|
||||
|
||||
pos -= prev_len;
|
||||
}
|
||||
|
||||
if (pos > 0)
|
||||
return pos;
|
||||
|
||||
return 0;
|
||||
return (pos > 0) ? pos : 0;
|
||||
}
|
||||
|
||||
void LocaleString_RightTrim(char* base)
|
||||
@@ -75,52 +84,10 @@ void LocaleString_RightTrim(char* base)
|
||||
LocaleString_RightTrim(base, strlen(base));
|
||||
}
|
||||
|
||||
void OLD_rtrim(char* base)
|
||||
{
|
||||
if (!base)
|
||||
return;
|
||||
|
||||
DWORD codePage = GetDefaultCodePage();
|
||||
|
||||
if (949 == codePage || 936 == codePage)
|
||||
{
|
||||
char* end = base + strlen(base) - 1;
|
||||
|
||||
while (end != base)
|
||||
{
|
||||
if (!isnhspace((unsigned char) *end) && *end != '\n' && *end != '\r' || (end!=base && *((unsigned char*)end-1)>0xa0))
|
||||
break;
|
||||
|
||||
*end = '\0';
|
||||
|
||||
end = CharPrevExA(codePage, base, end, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char* end = base + strlen(base);
|
||||
|
||||
while (end != base)
|
||||
{
|
||||
char* prev = CharPrevExA(codePage, base, end, 0);
|
||||
|
||||
int prev_len = end - prev;
|
||||
if (prev_len != 1)
|
||||
break;
|
||||
|
||||
if (!isspace((unsigned char) *prev) && *prev != '\n' && *prev != '\r')
|
||||
break;
|
||||
|
||||
*prev = '\0';
|
||||
|
||||
end = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* LocaleString_Skip(DWORD codePage, const char* cur)
|
||||
const char* LocaleString_Skip(const char* cur)
|
||||
{
|
||||
int loopCount = 0;
|
||||
const char* end = cur + strlen(cur);
|
||||
|
||||
while (*cur)
|
||||
{
|
||||
@@ -130,44 +97,42 @@ const char* LocaleString_Skip(DWORD codePage, const char* cur)
|
||||
break;
|
||||
}
|
||||
|
||||
const char* next = CharNextExA(codePage, cur, 0);
|
||||
int cur_len = next - cur;
|
||||
const char* next = Utf8Next(cur, end);
|
||||
int cur_len = int(next - cur);
|
||||
|
||||
if (cur_len > 1)
|
||||
{
|
||||
cur = next;
|
||||
}
|
||||
else if (1 == cur_len)
|
||||
else if (cur_len == 1)
|
||||
{
|
||||
if (!isspace((unsigned char) *cur) && *cur != '\n' && *cur != '\r')
|
||||
if (!isspace((unsigned char)*cur) && *cur != '\n' && *cur != '\r')
|
||||
return cur;
|
||||
++cur;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
bool Group::GetArg(const char *c_arg_base, int arg_len, TArgList & argList)
|
||||
{
|
||||
char szName[32 + 1];
|
||||
char szValue[64 + 1];
|
||||
char szName[32 + 1];
|
||||
char szValue[64 + 1];
|
||||
|
||||
int iNameLen = 0;
|
||||
int iValueLen = 0;
|
||||
int iNameLen = 0;
|
||||
int iValueLen = 0;
|
||||
int iCharLen = 0;
|
||||
|
||||
int pos = 0;
|
||||
|
||||
bool isValue = false;
|
||||
bool isValue = false;
|
||||
|
||||
DWORD codePage = GetDefaultCodePage();
|
||||
|
||||
while (pos < arg_len)
|
||||
{
|
||||
while (pos < arg_len)
|
||||
{
|
||||
const char* end = c_arg_base + arg_len;
|
||||
const char* cur = c_arg_base + pos;
|
||||
const char* next = CharNextExA(codePage, cur, 0);
|
||||
const char* next = Utf8Next(cur, end);
|
||||
|
||||
iCharLen = next - cur;
|
||||
|
||||
if (iCharLen > 1)
|
||||
@@ -180,7 +145,7 @@ bool Group::GetArg(const char *c_arg_base, int arg_len, TArgList & argList)
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(szValue+iValueLen, cur, iCharLen);
|
||||
memcpy(szValue+iValueLen, cur, iCharLen);
|
||||
iValueLen += iCharLen;
|
||||
szValue[iValueLen] = '\0';
|
||||
}
|
||||
@@ -191,7 +156,7 @@ bool Group::GetArg(const char *c_arg_base, int arg_len, TArgList & argList)
|
||||
TraceError("argument name overflow: must be shorter than 32 letters");
|
||||
return false;
|
||||
}
|
||||
memcpy(szName+iNameLen, cur, iCharLen);
|
||||
memcpy(szName+iNameLen, cur, iCharLen);
|
||||
iNameLen += iCharLen;
|
||||
szName[iNameLen] = '\0';
|
||||
}
|
||||
@@ -220,11 +185,9 @@ bool Group::GetArg(const char *c_arg_base, int arg_len, TArgList & argList)
|
||||
{
|
||||
isValue = true;
|
||||
}
|
||||
// 값이 아니고, 이름이 시작되지 않았을 경우 빈칸은 건너 뛴다.
|
||||
else if (!isValue && iNameLen == 0 && isspace((unsigned char) c))
|
||||
{
|
||||
}
|
||||
// 엔터는 건너 뛴다
|
||||
else if (c == '\r' || c == '\n')
|
||||
{
|
||||
}
|
||||
@@ -238,9 +201,9 @@ bool Group::GetArg(const char *c_arg_base, int arg_len, TArgList & argList)
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(szValue+iValueLen, cur, iCharLen);
|
||||
memcpy(szValue+iValueLen, cur, iCharLen);
|
||||
iValueLen += iCharLen;
|
||||
szValue[iValueLen] = '\0';
|
||||
szValue[iValueLen] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -249,10 +212,10 @@ bool Group::GetArg(const char *c_arg_base, int arg_len, TArgList & argList)
|
||||
TraceError("argument name overflow: must be shorter than 32 letters");
|
||||
return false;
|
||||
}
|
||||
memcpy(szName+iNameLen, cur, iCharLen);
|
||||
memcpy(szName+iNameLen, cur, iCharLen);
|
||||
iNameLen += iCharLen;
|
||||
szName[iNameLen] = '\0';
|
||||
}
|
||||
szName[iNameLen] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -261,122 +224,128 @@ bool Group::GetArg(const char *c_arg_base, int arg_len, TArgList & argList)
|
||||
}
|
||||
|
||||
pos += iCharLen;
|
||||
}
|
||||
}
|
||||
|
||||
if (iNameLen != 0 && iValueLen != 0)
|
||||
{
|
||||
if (iNameLen != 0 && iValueLen != 0)
|
||||
{
|
||||
iNameLen = LocaleString_RightTrim(szName, iNameLen);
|
||||
iValueLen = LocaleString_RightTrim(szValue, iValueLen);
|
||||
argList.push_back(TArg(szName, szValue));
|
||||
}
|
||||
argList.push_back(TArg(szName, szValue));
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Group::Create(const std::string & stSource)
|
||||
bool Group::Create(const std::string& stSource)
|
||||
{
|
||||
m_cmdList.clear();
|
||||
|
||||
if (stSource.empty())
|
||||
return false;
|
||||
|
||||
const char *str_base = stSource.c_str();
|
||||
if (!str_base || !*str_base)
|
||||
{
|
||||
TraceError("Source file has no content");
|
||||
return false;
|
||||
}
|
||||
int str_len = stSource.length();
|
||||
int str_pos = 0;
|
||||
|
||||
DWORD codePage = GetDefaultCodePage();
|
||||
const char* str_base = stSource.c_str();
|
||||
if (!str_base || !*str_base)
|
||||
{
|
||||
TraceError("Source file has no content");
|
||||
return false;
|
||||
}
|
||||
|
||||
char box_data[1024 + 1];
|
||||
const int str_len = (int)stSource.size();
|
||||
int str_pos = 0;
|
||||
|
||||
char box_data[1024 + 1];
|
||||
|
||||
static std::string stLetter;
|
||||
|
||||
while (str_pos < str_len)
|
||||
{
|
||||
TCmd cmd;
|
||||
|
||||
while (str_pos < str_len)
|
||||
{
|
||||
TCmd cmd;
|
||||
|
||||
const char* word = str_base + str_pos;
|
||||
const char* word_next = CharNextExA(codePage, word, 0);
|
||||
|
||||
int word_len = word_next - word;
|
||||
|
||||
const char* end = str_base + str_len;
|
||||
|
||||
const char* word_next = Utf8Next(word, end);
|
||||
if (!word_next || word_next <= word)
|
||||
{
|
||||
// Invalid UTF-8 sequence or broken helper -> advance 1 byte to avoid infinite loop
|
||||
word_next = word + 1;
|
||||
}
|
||||
|
||||
const int word_len = (int)(word_next - word);
|
||||
|
||||
if (word_len > 1)
|
||||
{
|
||||
str_pos += word_len;
|
||||
|
||||
{
|
||||
stLetter.assign(word, word_next);
|
||||
|
||||
cmd.name.assign("LETTER");
|
||||
cmd.argList.push_back(TArg("value", stLetter));
|
||||
|
||||
m_cmdList.push_back(cmd);
|
||||
}
|
||||
|
||||
stLetter.assign(word, word_next);
|
||||
cmd.name.assign("LETTER");
|
||||
cmd.argList.push_back(TArg("value", stLetter));
|
||||
m_cmdList.push_back(cmd);
|
||||
}
|
||||
else if (word_len == 1)
|
||||
{
|
||||
const char cur = *word;
|
||||
|
||||
if ('[' == cur)
|
||||
if (cur == '[')
|
||||
{
|
||||
++str_pos;
|
||||
|
||||
const char* box_begin = str_base + str_pos;
|
||||
const char* box_end = LocaleString_FindChar(box_begin, str_len - str_pos, ']');
|
||||
const char* box_end = LocaleString_FindChar(box_begin, str_len - str_pos, ']');
|
||||
if (!box_end)
|
||||
{
|
||||
TraceError(" !! PARSING ERROR - Syntax Error : %s\n", box_begin);
|
||||
return false;
|
||||
}
|
||||
str_pos += box_end - box_begin + 1;
|
||||
|
||||
|
||||
str_pos += (int)(box_end - box_begin) + 1;
|
||||
|
||||
int data_len = 0;
|
||||
{
|
||||
const char* data_begin = LocaleString_Skip(codePage, box_begin);
|
||||
const char* data_begin = LocaleString_Skip(box_begin);
|
||||
const char* data_end = box_end;
|
||||
data_len = data_end - data_begin;
|
||||
|
||||
data_len = (int)(data_end - data_begin);
|
||||
if (data_len >= 1024)
|
||||
{
|
||||
TraceError(" !! PARSING ERROR - Buffer Overflow : %d, %s\n", data_len, str_base);
|
||||
return false;
|
||||
}
|
||||
memcpy(box_data, data_begin, data_len);
|
||||
|
||||
memcpy(box_data, data_begin, (size_t)data_len);
|
||||
box_data[data_len] = '\0';
|
||||
|
||||
data_len = LocaleString_RightTrim(box_data, data_len); // 오른쪽 빈칸 자르기
|
||||
data_len = LocaleString_RightTrim(box_data, data_len);
|
||||
}
|
||||
|
||||
{
|
||||
const char* space = LocaleString_FindChar(box_data, data_len, ' ');
|
||||
if (space) // 인자가 있음
|
||||
if (space)
|
||||
{
|
||||
int name_len = space - box_data;
|
||||
const int name_len = (int)(space - box_data);
|
||||
cmd.name.assign(box_data, name_len);
|
||||
|
||||
const char* space_next = CharNextExA(codePage, space, 0);
|
||||
const char* arg = LocaleString_Skip(codePage, space_next);
|
||||
|
||||
int arg_len = data_len - (arg - box_data);
|
||||
|
||||
const char* data_end = box_data + data_len;
|
||||
|
||||
const char* space_next = Utf8Next(space, data_end);
|
||||
if (!space_next || space_next <= space)
|
||||
space_next = space + 1;
|
||||
|
||||
const char* arg = LocaleString_Skip(space_next);
|
||||
|
||||
const int arg_len = (int)(data_len - (arg - box_data));
|
||||
if (!GetArg(arg, arg_len, cmd.argList))
|
||||
{
|
||||
TraceError(" !! PARSING ERROR - Unknown Arguments : %d, %s\n", arg_len, arg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else // 인자가 없으므로 모든 스트링이 명령어다.
|
||||
else
|
||||
{
|
||||
cmd.name.assign(box_data);
|
||||
cmd.argList.clear();
|
||||
}
|
||||
|
||||
|
||||
m_cmdList.push_back(cmd);
|
||||
}
|
||||
}
|
||||
@@ -387,51 +356,49 @@ bool Group::Create(const std::string & stSource)
|
||||
else
|
||||
{
|
||||
++str_pos;
|
||||
|
||||
{
|
||||
stLetter.assign(1, cur);
|
||||
cmd.name.assign("LETTER");
|
||||
cmd.argList.push_back(TArg("value", stLetter));
|
||||
m_cmdList.push_back(cmd);
|
||||
}
|
||||
|
||||
stLetter.assign(1, cur);
|
||||
cmd.name.assign("LETTER");
|
||||
cmd.argList.push_back(TArg("value", stLetter));
|
||||
m_cmdList.push_back(cmd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Group::GetCmd(TCmd & cmd)
|
||||
{
|
||||
if (m_cmdList.empty())
|
||||
return false;
|
||||
if (m_cmdList.empty())
|
||||
return false;
|
||||
|
||||
cmd = m_cmdList.front();
|
||||
m_cmdList.pop_front();
|
||||
return true;
|
||||
cmd = m_cmdList.front();
|
||||
m_cmdList.pop_front();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Group::ReadCmd(TCmd & cmd)
|
||||
{
|
||||
if (m_cmdList.empty())
|
||||
return false;
|
||||
if (m_cmdList.empty())
|
||||
return false;
|
||||
|
||||
cmd = m_cmdList.front();
|
||||
return true;
|
||||
cmd = m_cmdList.front();
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string & Group::GetError()
|
||||
{
|
||||
return m_stError;
|
||||
return m_stError;
|
||||
}
|
||||
|
||||
void Group::SetError(const char * c_pszError)
|
||||
{
|
||||
m_stError.assign(c_pszError);
|
||||
m_stError.assign(c_pszError);
|
||||
}
|
||||
|
||||
Group::Group()
|
||||
|
||||
@@ -6,89 +6,69 @@
|
||||
|
||||
namespace script
|
||||
{
|
||||
typedef struct SArgumet
|
||||
{
|
||||
SArgumet(const std::string& c_stName, const std::string& c_stValue)
|
||||
{
|
||||
strName = c_stName;
|
||||
strValue = c_stValue;
|
||||
}
|
||||
typedef struct SArgumet
|
||||
{
|
||||
SArgumet(const std::string& c_stName, const std::string& c_stValue)
|
||||
{
|
||||
strName = c_stName;
|
||||
strValue = c_stValue;
|
||||
}
|
||||
|
||||
SArgumet(const SArgumet& c_arg)
|
||||
{
|
||||
strName = c_arg.strName;
|
||||
strValue = c_arg.strValue;
|
||||
}
|
||||
}
|
||||
|
||||
void operator=(const SArgumet& c_arg)
|
||||
{
|
||||
strName = c_arg.strName;
|
||||
strValue = c_arg.strValue;
|
||||
}
|
||||
std::string strName;
|
||||
std::string strValue;
|
||||
} TArg;
|
||||
|
||||
typedef std::list<TArg> TArgList;
|
||||
|
||||
typedef struct SCmd
|
||||
{
|
||||
std::string name;
|
||||
TArgList argList;
|
||||
}
|
||||
|
||||
SCmd()
|
||||
{}
|
||||
std::string strName;
|
||||
std::string strValue;
|
||||
} TArg;
|
||||
|
||||
typedef std::list<TArg> TArgList;
|
||||
|
||||
typedef struct SCmd
|
||||
{
|
||||
std::string name;
|
||||
TArgList argList;
|
||||
|
||||
SCmd() {}
|
||||
SCmd(const SCmd& c_cmd)
|
||||
{
|
||||
name = c_cmd.name;
|
||||
argList = c_cmd.argList;
|
||||
}
|
||||
|
||||
void operator=(const SCmd& c_cmd)
|
||||
{
|
||||
name = c_cmd.name;
|
||||
argList = c_cmd.argList;
|
||||
}
|
||||
} TCmd;
|
||||
|
||||
class Group
|
||||
{
|
||||
} TCmd;
|
||||
|
||||
class Group
|
||||
{
|
||||
public:
|
||||
Group();
|
||||
~Group();
|
||||
|
||||
|
||||
public:
|
||||
/** 스트링으로 부터 스크립트 그룹을 만든다.
|
||||
*
|
||||
* 실패하면 GetError 메소드로 확인할 수 있다.
|
||||
*
|
||||
* @param stSource 이 스트링으로 부터 그룹이 만들어 진다.
|
||||
* @return 성공시 true, 실패하면 false
|
||||
*/
|
||||
bool Create(const std::string & stSource);
|
||||
|
||||
/** 명령어를 받는 메소드
|
||||
*
|
||||
* @param cmd 성공시에 이 구조체로 명령어가 복사 된다.
|
||||
* @return 명령어가 남아 있다면 true, 없다면 false
|
||||
*/
|
||||
bool GetCmd(TCmd & cmd);
|
||||
bool Create(const std::string & stSource);
|
||||
bool GetCmd(TCmd & cmd);
|
||||
bool ReadCmd(TCmd & cmd);
|
||||
std::string & GetError();
|
||||
|
||||
/*
|
||||
명령어를 가져오되 꺼내지는 않는다.
|
||||
*/
|
||||
bool ReadCmd(TCmd & cmd);
|
||||
|
||||
/** 에러를 출력 받는 메소드
|
||||
*
|
||||
* @return stError 이 곳으로 에러가 출력 된다.
|
||||
*/
|
||||
std::string & GetError();
|
||||
|
||||
private:
|
||||
void SetError(const char *str);
|
||||
bool GetArg(const char * c_atr_base, int arg_len, TArgList & argList);
|
||||
|
||||
std::string m_stError;
|
||||
std::list<TCmd> m_cmdList;
|
||||
};
|
||||
}
|
||||
void SetError(const char *str);
|
||||
bool GetArg(const char * c_atr_base, int arg_len, TArgList & argList);
|
||||
|
||||
std::string m_stError;
|
||||
std::list<TCmd> m_cmdList;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user