Make sure only *W functions from Win32 API are called.
After this commit, SolveSpace always uses UTF-8 strings internally (represented as char* and std::string) on every OS, for everything: UI labels, paths and user input. OS X always uses UTF-8; on Windows, strings are converted at boundary; and on Linux/BSD/etc SolveSpace refuses to start unless the current locale is UTF-8. This will negatively affect literally no one. This commit does not bring forth any user-visible improvement yet; in order to correctly handle Unicode in filenames, it is still necessary to change the fopen calls to _wfopen on Windows.
This commit is contained in:
parent
5c9c32cfc7
commit
97a9b4743e
|
@ -35,7 +35,9 @@ if(WIN32)
|
||||||
-D_WIN32_IE=_WIN32_WINNT
|
-D_WIN32_IE=_WIN32_WINNT
|
||||||
-DISOLATION_AWARE_ENABLED=1
|
-DISOLATION_AWARE_ENABLED=1
|
||||||
-DWIN32=1
|
-DWIN32=1
|
||||||
-DWIN32_LEAN_AND_MEAN=1)
|
-DWIN32_LEAN_AND_MEAN=1
|
||||||
|
-DUNICODE
|
||||||
|
-D_UNICODE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MINGW)
|
if(MINGW)
|
||||||
|
|
|
@ -1470,7 +1470,21 @@ void ExitNow(void) {
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
/* If we don't call this, gtk_init will set the C standard library
|
/* It would in principle be possible to judiciously use
|
||||||
|
Glib::filename_{from,to}_utf8, but it's not really worth
|
||||||
|
the effort.
|
||||||
|
The setlocale() call is necessary for Glib::get_charset()
|
||||||
|
to detect the system character set; otherwise it thinks
|
||||||
|
it is always ANSI_X3.4-1968.
|
||||||
|
We set it back to C after all. */
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
if(!Glib::get_charset()) {
|
||||||
|
std::cerr << "Sorry, only UTF-8 locales are supported." << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
setlocale(LC_ALL, "C");
|
||||||
|
|
||||||
|
/* If we don't do this, gtk_init will set the C standard library
|
||||||
locale, and printf will format floats using ",". We will then
|
locale, and printf will format floats using ",". We will then
|
||||||
fail to parse these. Also, many text window lines will become
|
fail to parse these. Also, many text window lines will become
|
||||||
ambiguous. */
|
ambiguous. */
|
||||||
|
@ -1500,7 +1514,8 @@ int main(int argc, char** argv) {
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
SS.OpenFile(argv[1]);
|
/* Make sure the argument is valid UTF-8. */
|
||||||
|
SS.OpenFile(Glib::ustring(argv[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
main.run(*GW);
|
main.run(*GW);
|
||||||
|
|
|
@ -107,6 +107,13 @@ typedef UCHAR uint8_t;
|
||||||
typedef CHAR int8_t;
|
typedef CHAR int8_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
std::string Narrow(const wchar_t *s);
|
||||||
|
std::wstring Widen(const char *s);
|
||||||
|
std::string Narrow(const std::wstring &s);
|
||||||
|
std::wstring Widen(const std::string &s);
|
||||||
|
#endif
|
||||||
|
|
||||||
inline double Random(double vmax) {
|
inline double Random(double vmax) {
|
||||||
return (vmax*rand()) / RAND_MAX;
|
return (vmax*rand()) / RAND_MAX;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,9 +90,9 @@ static LRESULT CALLBACK MessageProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||||
col = 0;
|
col = 0;
|
||||||
row++;
|
row++;
|
||||||
} else {
|
} else {
|
||||||
TextOut(hdc, col*SS.TW.CHAR_WIDTH + 10,
|
TextOutW(hdc, col*SS.TW.CHAR_WIDTH + 10,
|
||||||
row*SS.TW.LINE_HEIGHT + 10,
|
row*SS.TW.LINE_HEIGHT + 10,
|
||||||
&(MessageString[i]), 1);
|
Widen(&(MessageString[i])).c_str(), 1);
|
||||||
col++;
|
col++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,11 +107,11 @@ static LRESULT CALLBACK MessageProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND CreateWindowClient(DWORD exStyle, const char *className, const char *windowName,
|
HWND CreateWindowClient(DWORD exStyle, const wchar_t *className, const wchar_t *windowName,
|
||||||
DWORD style, int x, int y, int width, int height, HWND parent,
|
DWORD style, int x, int y, int width, int height, HWND parent,
|
||||||
HMENU menu, HINSTANCE instance, void *param)
|
HMENU menu, HINSTANCE instance, void *param)
|
||||||
{
|
{
|
||||||
HWND h = CreateWindowEx(exStyle, className, windowName, style, x, y,
|
HWND h = CreateWindowExW(exStyle, className, windowName, style, x, y,
|
||||||
width, height, parent, menu, instance, param);
|
width, height, parent, menu, instance, param);
|
||||||
|
|
||||||
RECT r;
|
RECT r;
|
||||||
|
@ -128,16 +128,15 @@ void SolveSpace::DoMessageBox(const char *str, int rows, int cols, bool error)
|
||||||
{
|
{
|
||||||
EnableWindow(GraphicsWnd, false);
|
EnableWindow(GraphicsWnd, false);
|
||||||
EnableWindow(TextWnd, false);
|
EnableWindow(TextWnd, false);
|
||||||
//HWND h = GetForegroundWindow();
|
|
||||||
|
|
||||||
// Register the window class for our dialog.
|
// Register the window class for our dialog.
|
||||||
WNDCLASSEX wc = {};
|
WNDCLASSEX wc = {};
|
||||||
wc.cbSize = sizeof(wc);
|
wc.cbSize = sizeof(wc);
|
||||||
wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC;
|
wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC;
|
||||||
wc.lpfnWndProc = (WNDPROC)MessageProc;
|
wc.lpfnWndProc = (WNDPROC)MessageProc;
|
||||||
wc.hInstance = Instance;
|
wc.hInstance = Instance;
|
||||||
wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
|
wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
|
||||||
wc.lpszClassName = "MessageWnd";
|
wc.lpszClassName = L"MessageWnd";
|
||||||
wc.lpszMenuName = NULL;
|
wc.lpszMenuName = NULL;
|
||||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
wc.hIcon = (HICON)LoadImage(Instance, MAKEINTRESOURCE(4000),
|
wc.hIcon = (HICON)LoadImage(Instance, MAKEINTRESOURCE(4000),
|
||||||
|
@ -153,11 +152,11 @@ void SolveSpace::DoMessageBox(const char *str, int rows, int cols, bool error)
|
||||||
const char *title = error ? "SolveSpace - Error" : "SolveSpace - Message";
|
const char *title = error ? "SolveSpace - Error" : "SolveSpace - Message";
|
||||||
int width = cols*SS.TW.CHAR_WIDTH + 20,
|
int width = cols*SS.TW.CHAR_WIDTH + 20,
|
||||||
height = rows*SS.TW.LINE_HEIGHT + 60;
|
height = rows*SS.TW.LINE_HEIGHT + 60;
|
||||||
MessageWnd = CreateWindowClient(0, "MessageWnd", title,
|
MessageWnd = CreateWindowClient(0, L"MessageWnd", Widen(title).c_str(),
|
||||||
WS_OVERLAPPED | WS_SYSMENU,
|
WS_OVERLAPPED | WS_SYSMENU,
|
||||||
r.left + 100, r.top + 100, width, height, NULL, NULL, Instance, NULL);
|
r.left + 100, r.top + 100, width, height, NULL, NULL, Instance, NULL);
|
||||||
|
|
||||||
OkButton = CreateWindowEx(0, WC_BUTTON, "OK",
|
OkButton = CreateWindowExW(0, WC_BUTTON, L"OK",
|
||||||
WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS | WS_VISIBLE | BS_DEFPUSHBUTTON,
|
WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS | WS_VISIBLE | BS_DEFPUSHBUTTON,
|
||||||
(width - 70)/2, rows*SS.TW.LINE_HEIGHT + 20,
|
(width - 70)/2, rows*SS.TW.LINE_HEIGHT + 20,
|
||||||
70, 25, MessageWnd, NULL, Instance, NULL);
|
70, 25, MessageWnd, NULL, Instance, NULL);
|
||||||
|
@ -196,15 +195,15 @@ void SolveSpace::AddContextMenuItem(const char *label, int id)
|
||||||
if(!ContextMenu) ContextMenu = CreatePopupMenu();
|
if(!ContextMenu) ContextMenu = CreatePopupMenu();
|
||||||
|
|
||||||
if(id == CONTEXT_SUBMENU) {
|
if(id == CONTEXT_SUBMENU) {
|
||||||
AppendMenu(ContextMenu, MF_STRING | MF_POPUP,
|
AppendMenuW(ContextMenu, MF_STRING | MF_POPUP,
|
||||||
(UINT_PTR)ContextSubmenu, label);
|
(UINT_PTR)ContextSubmenu, Widen(label).c_str());
|
||||||
ContextSubmenu = NULL;
|
ContextSubmenu = NULL;
|
||||||
} else {
|
} else {
|
||||||
HMENU m = ContextSubmenu ? ContextSubmenu : ContextMenu;
|
HMENU m = ContextSubmenu ? ContextSubmenu : ContextMenu;
|
||||||
if(id == CONTEXT_SEPARATOR) {
|
if(id == CONTEXT_SEPARATOR) {
|
||||||
AppendMenu(m, MF_SEPARATOR, 0, "");
|
AppendMenuW(m, MF_SEPARATOR, 0, L"");
|
||||||
} else {
|
} else {
|
||||||
AppendMenu(m, MF_STRING, id, label);
|
AppendMenuW(m, MF_STRING, id, Widen(label).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,7 +270,7 @@ void SolveSpace::GetTextWindowSize(int *w, int *h)
|
||||||
}
|
}
|
||||||
|
|
||||||
void SolveSpace::OpenWebsite(const char *url) {
|
void SolveSpace::OpenWebsite(const char *url) {
|
||||||
ShellExecute(GraphicsWnd, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
ShellExecuteW(GraphicsWnd, L"open", Widen(url).c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SolveSpace::ExitNow(void) {
|
void SolveSpace::ExitNow(void) {
|
||||||
|
@ -292,12 +291,13 @@ inline int CLAMP(int v, int a, int b) {
|
||||||
static HKEY GetRegistryKey()
|
static HKEY GetRegistryKey()
|
||||||
{
|
{
|
||||||
HKEY Software;
|
HKEY Software;
|
||||||
if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &Software) != ERROR_SUCCESS)
|
if(RegOpenKeyExW(HKEY_CURRENT_USER, L"Software", 0,
|
||||||
|
KEY_ALL_ACCESS, &Software) != ERROR_SUCCESS)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
HKEY SolveSpace;
|
HKEY SolveSpace;
|
||||||
if(RegCreateKeyEx(Software, "SolveSpace", 0, NULL, 0,
|
if(RegCreateKeyExW(Software, L"SolveSpace", 0, NULL, 0,
|
||||||
KEY_ALL_ACCESS, NULL, &SolveSpace, NULL) != ERROR_SUCCESS)
|
KEY_ALL_ACCESS, NULL, &SolveSpace, NULL) != ERROR_SUCCESS)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
RegCloseKey(Software);
|
RegCloseKey(Software);
|
||||||
|
@ -308,8 +308,8 @@ static HKEY GetRegistryKey()
|
||||||
void SolveSpace::CnfFreezeInt(uint32_t val, const std::string &name)
|
void SolveSpace::CnfFreezeInt(uint32_t val, const std::string &name)
|
||||||
{
|
{
|
||||||
HKEY SolveSpace = GetRegistryKey();
|
HKEY SolveSpace = GetRegistryKey();
|
||||||
RegSetValueEx(SolveSpace, &name[0], 0,
|
RegSetValueExW(SolveSpace, &Widen(name)[0], 0,
|
||||||
REG_DWORD, (const BYTE*) &val, sizeof(DWORD));
|
REG_DWORD, (const BYTE*) &val, sizeof(DWORD));
|
||||||
RegCloseKey(SolveSpace);
|
RegCloseKey(SolveSpace);
|
||||||
}
|
}
|
||||||
void SolveSpace::CnfFreezeFloat(float val, const std::string &name)
|
void SolveSpace::CnfFreezeFloat(float val, const std::string &name)
|
||||||
|
@ -317,15 +317,16 @@ void SolveSpace::CnfFreezeFloat(float val, const std::string &name)
|
||||||
static_assert(sizeof(float) == sizeof(DWORD),
|
static_assert(sizeof(float) == sizeof(DWORD),
|
||||||
"sizes of float and DWORD must match");
|
"sizes of float and DWORD must match");
|
||||||
HKEY SolveSpace = GetRegistryKey();
|
HKEY SolveSpace = GetRegistryKey();
|
||||||
RegSetValueEx(SolveSpace, &name[0], 0,
|
RegSetValueExW(SolveSpace, &Widen(name)[0], 0,
|
||||||
REG_DWORD, (const BYTE*) &val, sizeof(DWORD));
|
REG_DWORD, (const BYTE*) &val, sizeof(DWORD));
|
||||||
RegCloseKey(SolveSpace);
|
RegCloseKey(SolveSpace);
|
||||||
}
|
}
|
||||||
void SolveSpace::CnfFreezeString(const std::string &str, const std::string &name)
|
void SolveSpace::CnfFreezeString(const std::string &str, const std::string &name)
|
||||||
{
|
{
|
||||||
HKEY SolveSpace = GetRegistryKey();
|
HKEY SolveSpace = GetRegistryKey();
|
||||||
RegSetValueEx(SolveSpace, &name[0], 0,
|
std::wstring strW = Widen(str);
|
||||||
REG_SZ, (const BYTE*) &str[0], str.length() + 1);
|
RegSetValueExW(SolveSpace, &Widen(name)[0], 0,
|
||||||
|
REG_SZ, (const BYTE*) &strW[0], (strW.length() + 1) * 2);
|
||||||
RegCloseKey(SolveSpace);
|
RegCloseKey(SolveSpace);
|
||||||
}
|
}
|
||||||
static void FreezeWindowPos(HWND hwnd, const std::string &name)
|
static void FreezeWindowPos(HWND hwnd, const std::string &name)
|
||||||
|
@ -344,7 +345,8 @@ uint32_t SolveSpace::CnfThawInt(uint32_t val, const std::string &name)
|
||||||
{
|
{
|
||||||
HKEY SolveSpace = GetRegistryKey();
|
HKEY SolveSpace = GetRegistryKey();
|
||||||
DWORD type, newval, len = sizeof(DWORD);
|
DWORD type, newval, len = sizeof(DWORD);
|
||||||
LONG result = RegQueryValueEx(SolveSpace, &name[0], NULL, &type, (BYTE*) &newval, &len);
|
LONG result = RegQueryValueEx(SolveSpace, &Widen(name)[0], NULL,
|
||||||
|
&type, (BYTE*) &newval, &len);
|
||||||
RegCloseKey(SolveSpace);
|
RegCloseKey(SolveSpace);
|
||||||
|
|
||||||
if(result == ERROR_SUCCESS && type == REG_DWORD)
|
if(result == ERROR_SUCCESS && type == REG_DWORD)
|
||||||
|
@ -357,7 +359,8 @@ float SolveSpace::CnfThawFloat(float val, const std::string &name)
|
||||||
HKEY SolveSpace = GetRegistryKey();
|
HKEY SolveSpace = GetRegistryKey();
|
||||||
DWORD type, len = sizeof(DWORD);
|
DWORD type, len = sizeof(DWORD);
|
||||||
float newval;
|
float newval;
|
||||||
LONG result = RegQueryValueEx(SolveSpace, &name[0], NULL, &type, (BYTE*) &newval, &len);
|
LONG result = RegQueryValueExW(SolveSpace, &Widen(name)[0], NULL,
|
||||||
|
&type, (BYTE*) &newval, &len);
|
||||||
RegCloseKey(SolveSpace);
|
RegCloseKey(SolveSpace);
|
||||||
|
|
||||||
if(result == ERROR_SUCCESS && type == REG_DWORD)
|
if(result == ERROR_SUCCESS && type == REG_DWORD)
|
||||||
|
@ -369,22 +372,22 @@ std::string SolveSpace::CnfThawString(const std::string &val, const std::string
|
||||||
{
|
{
|
||||||
HKEY SolveSpace = GetRegistryKey();
|
HKEY SolveSpace = GetRegistryKey();
|
||||||
DWORD type, len;
|
DWORD type, len;
|
||||||
if(RegQueryValueEx(SolveSpace, &name[0], NULL,
|
if(RegQueryValueExW(SolveSpace, &Widen(name)[0], NULL,
|
||||||
&type, NULL, &len) != ERROR_SUCCESS || type != REG_SZ) {
|
&type, NULL, &len) != ERROR_SUCCESS || type != REG_SZ) {
|
||||||
RegCloseKey(SolveSpace);
|
RegCloseKey(SolveSpace);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string newval;
|
std::wstring newval;
|
||||||
newval.resize(len - 1);
|
newval.resize(len / 2 - 1);
|
||||||
if(RegQueryValueEx(SolveSpace, &name[0], NULL,
|
if(RegQueryValueExW(SolveSpace, &Widen(name)[0], NULL,
|
||||||
NULL, (BYTE*) &newval[0], &len) != ERROR_SUCCESS) {
|
NULL, (BYTE*) &newval[0], &len) != ERROR_SUCCESS) {
|
||||||
RegCloseKey(SolveSpace);
|
RegCloseKey(SolveSpace);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegCloseKey(SolveSpace);
|
RegCloseKey(SolveSpace);
|
||||||
return newval;
|
return Narrow(newval);
|
||||||
}
|
}
|
||||||
static void ThawWindowPos(HWND hwnd, const std::string &name)
|
static void ThawWindowPos(HWND hwnd, const std::string &name)
|
||||||
{
|
{
|
||||||
|
@ -414,9 +417,9 @@ static void ThawWindowPos(HWND hwnd, const std::string &name)
|
||||||
|
|
||||||
void SolveSpace::SetCurrentFilename(const std::string &filename) {
|
void SolveSpace::SetCurrentFilename(const std::string &filename) {
|
||||||
if(!filename.empty()) {
|
if(!filename.empty()) {
|
||||||
SetWindowText(GraphicsWnd, ("SolveSpace - " + filename).c_str());
|
SetWindowTextW(GraphicsWnd, Widen("SolveSpace - " + filename).c_str());
|
||||||
} else {
|
} else {
|
||||||
SetWindowText(GraphicsWnd, "SolveSpace - (not yet saved)");
|
SetWindowTextW(GraphicsWnd, L"SolveSpace - (not yet saved)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,13 +625,19 @@ LRESULT CALLBACK TextWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string EditControlText(HWND hwnd)
|
||||||
|
{
|
||||||
|
std::wstring result;
|
||||||
|
result.resize(GetWindowTextLength(hwnd));
|
||||||
|
GetWindowTextW(hwnd, &result[0], result.length() + 1);
|
||||||
|
return Narrow(result);
|
||||||
|
}
|
||||||
|
|
||||||
static bool ProcessKeyDown(WPARAM wParam)
|
static bool ProcessKeyDown(WPARAM wParam)
|
||||||
{
|
{
|
||||||
if(GraphicsEditControlIsVisible() && wParam != VK_ESCAPE) {
|
if(GraphicsEditControlIsVisible() && wParam != VK_ESCAPE) {
|
||||||
if(wParam == VK_RETURN) {
|
if(wParam == VK_RETURN) {
|
||||||
char s[1024] = {};
|
SS.GW.EditControlDone(EditControlText(GraphicsEditControl).c_str());
|
||||||
SendMessage(GraphicsEditControl, WM_GETTEXT, 900, (LPARAM)s);
|
|
||||||
SS.GW.EditControlDone(s);
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -636,9 +645,7 @@ static bool ProcessKeyDown(WPARAM wParam)
|
||||||
}
|
}
|
||||||
if(TextEditControlIsVisible() && wParam != VK_ESCAPE) {
|
if(TextEditControlIsVisible() && wParam != VK_ESCAPE) {
|
||||||
if(wParam == VK_RETURN) {
|
if(wParam == VK_RETURN) {
|
||||||
char s[1024] = {};
|
SS.TW.EditControlDone(EditControlText(TextEditControl).c_str());
|
||||||
SendMessage(TextEditControl, WM_GETTEXT, 900, (LPARAM)s);
|
|
||||||
SS.TW.EditControlDone(s);
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -796,12 +803,12 @@ void SolveSpace::InvalidateText(void)
|
||||||
InvalidateRect(TextWnd, NULL, false);
|
InvalidateRect(TextWnd, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ShowEditControl(HWND h, int x, int y, char *s) {
|
static void ShowEditControl(HWND h, int x, int y, const std::wstring &s) {
|
||||||
MoveWindow(h, x, y, EDIT_WIDTH, EDIT_HEIGHT, true);
|
MoveWindow(h, x, y, EDIT_WIDTH, EDIT_HEIGHT, true);
|
||||||
ShowWindow(h, SW_SHOW);
|
ShowWindow(h, SW_SHOW);
|
||||||
if(s) {
|
if(!s.empty()) {
|
||||||
SendMessage(h, WM_SETTEXT, 0, (LPARAM)s);
|
SendMessage(h, WM_SETTEXT, 0, (LPARAM)s.c_str());
|
||||||
SendMessage(h, EM_SETSEL, 0, strlen(s));
|
SendMessage(h, EM_SETSEL, 0, s.length());
|
||||||
SetFocus(h);
|
SetFocus(h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -809,7 +816,7 @@ void SolveSpace::ShowTextEditControl(int x, int y, char *s)
|
||||||
{
|
{
|
||||||
if(GraphicsEditControlIsVisible()) return;
|
if(GraphicsEditControlIsVisible()) return;
|
||||||
|
|
||||||
ShowEditControl(TextEditControl, x, y, s);
|
ShowEditControl(TextEditControl, x, y, Widen(s));
|
||||||
}
|
}
|
||||||
void SolveSpace::HideTextEditControl(void)
|
void SolveSpace::HideTextEditControl(void)
|
||||||
{
|
{
|
||||||
|
@ -832,7 +839,7 @@ void SolveSpace::ShowGraphicsEditControl(int x, int y, char *s)
|
||||||
// top left corner
|
// top left corner
|
||||||
y -= 20;
|
y -= 20;
|
||||||
|
|
||||||
ShowEditControl(GraphicsEditControl, x, y, s);
|
ShowEditControl(GraphicsEditControl, x, y, Widen(s));
|
||||||
}
|
}
|
||||||
void SolveSpace::HideGraphicsEditControl(void)
|
void SolveSpace::HideGraphicsEditControl(void)
|
||||||
{
|
{
|
||||||
|
@ -958,67 +965,63 @@ LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Common dialog routines, to open or save a file.
|
// Common dialog routines, to open or save a file.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool SolveSpace::GetOpenFile(std::string &filename,
|
static size_t strlen2(const char *p) {
|
||||||
const char *defExtension, const char *selPattern)
|
const char *s = p;
|
||||||
{
|
while(*p || (!*p && *(p+1))) p++;
|
||||||
// UNC paths may be arbitrarily long.
|
return p - s + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool OpenSaveFile(bool isOpen, std::string &filename,
|
||||||
|
const char *defExtension, const char *selPattern) {
|
||||||
|
// UNC paths may be as long as 32767 characters.
|
||||||
// Unfortunately, the Get*FileName API does not provide any way to use it
|
// Unfortunately, the Get*FileName API does not provide any way to use it
|
||||||
// except with a preallocated buffer of fixed size, so we use something
|
// except with a preallocated buffer of fixed size, so we use something
|
||||||
// reasonably large.
|
// reasonably large.
|
||||||
char filenameC[0xFFFF] = {};
|
const int len = 32768;
|
||||||
strncpy(filenameC, filename.c_str(), sizeof(filenameC) - 1);
|
wchar_t filenameC[len] = {};
|
||||||
|
wcsncpy(filenameC, Widen(filename).c_str(), len - 1);
|
||||||
|
|
||||||
|
std::wstring selPatternW = Widen(std::string(selPattern, strlen2(selPattern)));
|
||||||
|
std::wstring defExtensionW = Widen(defExtension);
|
||||||
|
|
||||||
OPENFILENAME ofn = {};
|
OPENFILENAME ofn = {};
|
||||||
ofn.lStructSize = sizeof(ofn);
|
ofn.lStructSize = sizeof(ofn);
|
||||||
ofn.hInstance = Instance;
|
ofn.hInstance = Instance;
|
||||||
ofn.hwndOwner = GraphicsWnd;
|
ofn.hwndOwner = GraphicsWnd;
|
||||||
ofn.lpstrFilter = selPattern;
|
ofn.lpstrFilter = selPatternW.c_str();
|
||||||
ofn.lpstrDefExt = defExtension;
|
ofn.lpstrDefExt = defExtensionW.c_str();
|
||||||
ofn.lpstrFile = filenameC;
|
ofn.lpstrFile = filenameC;
|
||||||
ofn.nMaxFile = sizeof(filenameC);
|
ofn.nMaxFile = len;
|
||||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||||
|
|
||||||
EnableWindow(GraphicsWnd, false);
|
EnableWindow(GraphicsWnd, false);
|
||||||
EnableWindow(TextWnd, false);
|
EnableWindow(TextWnd, false);
|
||||||
|
|
||||||
BOOL r = GetOpenFileName(&ofn);
|
BOOL r;
|
||||||
|
if(isOpen) {
|
||||||
|
r = GetOpenFileNameW(&ofn);
|
||||||
|
} else {
|
||||||
|
r = GetSaveFileNameW(&ofn);
|
||||||
|
}
|
||||||
|
|
||||||
EnableWindow(TextWnd, true);
|
EnableWindow(TextWnd, true);
|
||||||
EnableWindow(GraphicsWnd, true);
|
EnableWindow(GraphicsWnd, true);
|
||||||
SetForegroundWindow(GraphicsWnd);
|
SetForegroundWindow(GraphicsWnd);
|
||||||
|
|
||||||
if(r) filename = filenameC;
|
if(r) filename = Narrow(filenameC);
|
||||||
return r ? true : false;
|
return r ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SolveSpace::GetOpenFile(std::string &filename,
|
||||||
|
const char *defExtension, const char *selPattern)
|
||||||
|
{
|
||||||
|
return OpenSaveFile(true, filename, defExtension, selPattern);
|
||||||
|
}
|
||||||
|
|
||||||
bool SolveSpace::GetSaveFile(std::string &filename,
|
bool SolveSpace::GetSaveFile(std::string &filename,
|
||||||
const char *defExtension, const char *selPattern)
|
const char *defExtension, const char *selPattern)
|
||||||
{
|
{
|
||||||
// See GetOpenFile
|
return OpenSaveFile(false, filename, defExtension, selPattern);
|
||||||
char filenameC[0xFFFF] = {};
|
|
||||||
strncpy(filenameC, filename.c_str(), sizeof(filenameC) - 1);
|
|
||||||
|
|
||||||
OPENFILENAME ofn = {};
|
|
||||||
ofn.lStructSize = sizeof(ofn);
|
|
||||||
ofn.hInstance = Instance;
|
|
||||||
ofn.hwndOwner = GraphicsWnd;
|
|
||||||
ofn.lpstrFilter = selPattern;
|
|
||||||
ofn.lpstrDefExt = defExtension;
|
|
||||||
ofn.lpstrFile = filenameC;
|
|
||||||
ofn.nMaxFile = sizeof(filenameC);
|
|
||||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
|
|
||||||
|
|
||||||
EnableWindow(GraphicsWnd, false);
|
|
||||||
EnableWindow(TextWnd, false);
|
|
||||||
|
|
||||||
BOOL r = GetSaveFileName(&ofn);
|
|
||||||
|
|
||||||
EnableWindow(TextWnd, true);
|
|
||||||
EnableWindow(GraphicsWnd, true);
|
|
||||||
SetForegroundWindow(GraphicsWnd);
|
|
||||||
|
|
||||||
if(r) filename = filenameC;
|
|
||||||
return r ? true : false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SolveSpace::SaveFileYesNoCancel(void)
|
int SolveSpace::SaveFileYesNoCancel(void)
|
||||||
|
@ -1026,9 +1029,9 @@ int SolveSpace::SaveFileYesNoCancel(void)
|
||||||
EnableWindow(GraphicsWnd, false);
|
EnableWindow(GraphicsWnd, false);
|
||||||
EnableWindow(TextWnd, false);
|
EnableWindow(TextWnd, false);
|
||||||
|
|
||||||
int r = MessageBox(GraphicsWnd,
|
int r = MessageBoxW(GraphicsWnd,
|
||||||
"The program has changed since it was last saved.\r\n\r\n"
|
L"The program has changed since it was last saved.\r\n\r\n"
|
||||||
"Do you want to save the changes?", "SolveSpace",
|
L"Do you want to save the changes?", L"SolveSpace",
|
||||||
MB_YESNOCANCEL | MB_ICONWARNING);
|
MB_YESNOCANCEL | MB_ICONWARNING);
|
||||||
|
|
||||||
EnableWindow(TextWnd, true);
|
EnableWindow(TextWnd, true);
|
||||||
|
@ -1050,9 +1053,9 @@ int SolveSpace::LoadAutosaveYesNo(void)
|
||||||
EnableWindow(GraphicsWnd, false);
|
EnableWindow(GraphicsWnd, false);
|
||||||
EnableWindow(TextWnd, false);
|
EnableWindow(TextWnd, false);
|
||||||
|
|
||||||
int r = MessageBox(GraphicsWnd,
|
int r = MessageBoxW(GraphicsWnd,
|
||||||
"An autosave file is availible for this project.\r\n\r\n"
|
L"An autosave file is availible for this project.\r\n\r\n"
|
||||||
"Do you want to load the autosave file instead?", "SolveSpace",
|
L"Do you want to load the autosave file instead?", L"SolveSpace",
|
||||||
MB_YESNO | MB_ICONWARNING);
|
MB_YESNO | MB_ICONWARNING);
|
||||||
|
|
||||||
EnableWindow(TextWnd, true);
|
EnableWindow(TextWnd, true);
|
||||||
|
@ -1069,18 +1072,18 @@ int SolveSpace::LoadAutosaveYesNo(void)
|
||||||
|
|
||||||
void SolveSpace::LoadAllFontFiles(void)
|
void SolveSpace::LoadAllFontFiles(void)
|
||||||
{
|
{
|
||||||
std::string fontsDir(MAX_PATH, '\0');
|
std::wstring fontsDir(MAX_PATH, '\0');
|
||||||
fontsDir.resize(GetWindowsDirectory(&fontsDir[0], fontsDir.length()));
|
fontsDir.resize(GetWindowsDirectoryW(&fontsDir[0], fontsDir.length()));
|
||||||
fontsDir += "\\fonts\\";
|
fontsDir += L"\\fonts\\";
|
||||||
|
|
||||||
WIN32_FIND_DATA wfd;
|
WIN32_FIND_DATA wfd;
|
||||||
HANDLE h = FindFirstFile((fontsDir + "*.ttf").c_str(), &wfd);
|
HANDLE h = FindFirstFileW((fontsDir + L"*.ttf").c_str(), &wfd);
|
||||||
while(h != INVALID_HANDLE_VALUE) {
|
while(h != INVALID_HANDLE_VALUE) {
|
||||||
TtfFont tf = {};
|
TtfFont tf = {};
|
||||||
tf.fontFile = fontsDir + wfd.cFileName;
|
tf.fontFile = Narrow(fontsDir) + Narrow(wfd.cFileName);
|
||||||
SS.fonts.l.Add(&tf);
|
SS.fonts.l.Add(&tf);
|
||||||
|
|
||||||
if(!FindNextFile(h, &wfd)) break;
|
if(!FindNextFileW(h, &wfd)) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1128,11 +1131,11 @@ static void DoRecent(HMENU m, int base)
|
||||||
int i, c = 0;
|
int i, c = 0;
|
||||||
for(i = 0; i < MAX_RECENT; i++) {
|
for(i = 0; i < MAX_RECENT; i++) {
|
||||||
if(!RecentFile[i].empty()) {
|
if(!RecentFile[i].empty()) {
|
||||||
AppendMenu(m, MF_STRING, base + i, RecentFile[i].c_str());
|
AppendMenuW(m, MF_STRING, base + i, Widen(RecentFile[i]).c_str());
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(c == 0) AppendMenu(m, MF_STRING | MF_GRAYED, 0, "(no recent files)");
|
if(c == 0) AppendMenuW(m, MF_STRING | MF_GRAYED, 0, L"(no recent files)");
|
||||||
}
|
}
|
||||||
void SolveSpace::RefreshRecentMenus(void)
|
void SolveSpace::RefreshRecentMenus(void)
|
||||||
{
|
{
|
||||||
|
@ -1160,23 +1163,23 @@ HMENU CreateGraphicsWindowMenus(void)
|
||||||
|
|
||||||
if(SS.GW.menu[i].level == 0) {
|
if(SS.GW.menu[i].level == 0) {
|
||||||
m = CreateMenu();
|
m = CreateMenu();
|
||||||
AppendMenu(top, MF_STRING | MF_POPUP, (UINT_PTR)m, label);
|
AppendMenuW(top, MF_STRING | MF_POPUP, (UINT_PTR)m, Widen(label).c_str());
|
||||||
if(subMenu >= (int)arraylen(SubMenus)) oops();
|
if(subMenu >= (int)arraylen(SubMenus)) oops();
|
||||||
SubMenus[subMenu] = m;
|
SubMenus[subMenu] = m;
|
||||||
subMenu++;
|
subMenu++;
|
||||||
} else if(SS.GW.menu[i].level == 1) {
|
} else if(SS.GW.menu[i].level == 1) {
|
||||||
if(SS.GW.menu[i].id == GraphicsWindow::MNU_OPEN_RECENT) {
|
if(SS.GW.menu[i].id == GraphicsWindow::MNU_OPEN_RECENT) {
|
||||||
RecentOpenMenu = CreateMenu();
|
RecentOpenMenu = CreateMenu();
|
||||||
AppendMenu(m, MF_STRING | MF_POPUP,
|
AppendMenuW(m, MF_STRING | MF_POPUP,
|
||||||
(UINT_PTR)RecentOpenMenu, label);
|
(UINT_PTR)RecentOpenMenu, Widen(label).c_str());
|
||||||
} else if(SS.GW.menu[i].id == GraphicsWindow::MNU_GROUP_RECENT) {
|
} else if(SS.GW.menu[i].id == GraphicsWindow::MNU_GROUP_RECENT) {
|
||||||
RecentImportMenu = CreateMenu();
|
RecentImportMenu = CreateMenu();
|
||||||
AppendMenu(m, MF_STRING | MF_POPUP,
|
AppendMenuW(m, MF_STRING | MF_POPUP,
|
||||||
(UINT_PTR)RecentImportMenu, label);
|
(UINT_PTR)RecentImportMenu, Widen(label).c_str());
|
||||||
} else if(SS.GW.menu[i].label) {
|
} else if(SS.GW.menu[i].label) {
|
||||||
AppendMenu(m, MF_STRING, SS.GW.menu[i].id, label);
|
AppendMenuW(m, MF_STRING, SS.GW.menu[i].id, Widen(label).c_str());
|
||||||
} else {
|
} else {
|
||||||
AppendMenu(m, MF_SEPARATOR, SS.GW.menu[i].id, "");
|
AppendMenuW(m, MF_SEPARATOR, SS.GW.menu[i].id, L"");
|
||||||
}
|
}
|
||||||
} else oops();
|
} else oops();
|
||||||
}
|
}
|
||||||
|
@ -1196,7 +1199,7 @@ static void CreateMainWindows(void)
|
||||||
CS_DBLCLKS;
|
CS_DBLCLKS;
|
||||||
wc.lpfnWndProc = (WNDPROC)GraphicsWndProc;
|
wc.lpfnWndProc = (WNDPROC)GraphicsWndProc;
|
||||||
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
||||||
wc.lpszClassName = "GraphicsWnd";
|
wc.lpszClassName = L"GraphicsWnd";
|
||||||
wc.lpszMenuName = NULL;
|
wc.lpszMenuName = NULL;
|
||||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
wc.hIcon = (HICON)LoadImage(Instance, MAKEINTRESOURCE(4000),
|
wc.hIcon = (HICON)LoadImage(Instance, MAKEINTRESOURCE(4000),
|
||||||
|
@ -1206,14 +1209,14 @@ static void CreateMainWindows(void)
|
||||||
if(!RegisterClassEx(&wc)) oops();
|
if(!RegisterClassEx(&wc)) oops();
|
||||||
|
|
||||||
HMENU top = CreateGraphicsWindowMenus();
|
HMENU top = CreateGraphicsWindowMenus();
|
||||||
GraphicsWnd = CreateWindowEx(0, "GraphicsWnd",
|
GraphicsWnd = CreateWindowExW(0, L"GraphicsWnd",
|
||||||
"SolveSpace (not yet saved)",
|
L"SolveSpace (not yet saved)",
|
||||||
WS_OVERLAPPED | WS_THICKFRAME | WS_CLIPCHILDREN | WS_MAXIMIZEBOX |
|
WS_OVERLAPPED | WS_THICKFRAME | WS_CLIPCHILDREN | WS_MAXIMIZEBOX |
|
||||||
WS_MINIMIZEBOX | WS_SYSMENU | WS_SIZEBOX | WS_CLIPSIBLINGS,
|
WS_MINIMIZEBOX | WS_SYSMENU | WS_SIZEBOX | WS_CLIPSIBLINGS,
|
||||||
50, 50, 900, 600, NULL, top, Instance, NULL);
|
50, 50, 900, 600, NULL, top, Instance, NULL);
|
||||||
if(!GraphicsWnd) oops();
|
if(!GraphicsWnd) oops();
|
||||||
|
|
||||||
GraphicsEditControl = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, "",
|
GraphicsEditControl = CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDIT, L"",
|
||||||
WS_CHILD | ES_AUTOHSCROLL | WS_TABSTOP | WS_CLIPSIBLINGS,
|
WS_CHILD | ES_AUTOHSCROLL | WS_TABSTOP | WS_CLIPSIBLINGS,
|
||||||
50, 50, 100, 21, GraphicsWnd, NULL, Instance, NULL);
|
50, 50, 100, 21, GraphicsWnd, NULL, Instance, NULL);
|
||||||
SendMessage(GraphicsEditControl, WM_SETFONT, (WPARAM)FixedFont, true);
|
SendMessage(GraphicsEditControl, WM_SETFONT, (WPARAM)FixedFont, true);
|
||||||
|
@ -1223,24 +1226,24 @@ static void CreateMainWindows(void)
|
||||||
wc.style &= ~CS_DBLCLKS;
|
wc.style &= ~CS_DBLCLKS;
|
||||||
wc.lpfnWndProc = (WNDPROC)TextWndProc;
|
wc.lpfnWndProc = (WNDPROC)TextWndProc;
|
||||||
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||||
wc.lpszClassName = "TextWnd";
|
wc.lpszClassName = L"TextWnd";
|
||||||
wc.hCursor = NULL;
|
wc.hCursor = NULL;
|
||||||
if(!RegisterClassEx(&wc)) oops();
|
if(!RegisterClassEx(&wc)) oops();
|
||||||
|
|
||||||
// We get the desired Alt+Tab behaviour by specifying that the text
|
// We get the desired Alt+Tab behaviour by specifying that the text
|
||||||
// window is a child of the graphics window.
|
// window is a child of the graphics window.
|
||||||
TextWnd = CreateWindowEx(0,
|
TextWnd = CreateWindowExW(0,
|
||||||
"TextWnd", "SolveSpace - Browser", WS_THICKFRAME | WS_CLIPCHILDREN,
|
L"TextWnd", L"SolveSpace - Browser", WS_THICKFRAME | WS_CLIPCHILDREN,
|
||||||
650, 500, 420, 300, GraphicsWnd, (HMENU)NULL, Instance, NULL);
|
650, 500, 420, 300, GraphicsWnd, (HMENU)NULL, Instance, NULL);
|
||||||
if(!TextWnd) oops();
|
if(!TextWnd) oops();
|
||||||
|
|
||||||
TextWndScrollBar = CreateWindowEx(0, WC_SCROLLBAR, "", WS_CHILD |
|
TextWndScrollBar = CreateWindowExW(0, WC_SCROLLBAR, L"", WS_CHILD |
|
||||||
SBS_VERT | SBS_LEFTALIGN | WS_VISIBLE | WS_CLIPSIBLINGS,
|
SBS_VERT | SBS_LEFTALIGN | WS_VISIBLE | WS_CLIPSIBLINGS,
|
||||||
200, 100, 100, 100, TextWnd, NULL, Instance, NULL);
|
200, 100, 100, 100, TextWnd, NULL, Instance, NULL);
|
||||||
// Force the scrollbar to get resized to the window,
|
// Force the scrollbar to get resized to the window,
|
||||||
TextWndProc(TextWnd, WM_SIZE, 0, 0);
|
TextWndProc(TextWnd, WM_SIZE, 0, 0);
|
||||||
|
|
||||||
TextEditControl = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, "",
|
TextEditControl = CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDIT, L"",
|
||||||
WS_CHILD | ES_AUTOHSCROLL | WS_TABSTOP | WS_CLIPSIBLINGS,
|
WS_CHILD | ES_AUTOHSCROLL | WS_TABSTOP | WS_CLIPSIBLINGS,
|
||||||
50, 50, 100, 21, TextWnd, NULL, Instance, NULL);
|
50, 50, 100, 21, TextWnd, NULL, Instance, NULL);
|
||||||
SendMessage(TextEditControl, WM_SETFONT, (WPARAM)FixedFont, true);
|
SendMessage(TextEditControl, WM_SETFONT, (WPARAM)FixedFont, true);
|
||||||
|
@ -1304,10 +1307,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||||
InitCommonControls();
|
InitCommonControls();
|
||||||
|
|
||||||
// A monospaced font
|
// A monospaced font
|
||||||
FixedFont = CreateFont(SS.TW.CHAR_HEIGHT, SS.TW.CHAR_WIDTH, 0, 0,
|
FixedFont = CreateFontW(SS.TW.CHAR_HEIGHT, SS.TW.CHAR_WIDTH, 0, 0,
|
||||||
FW_REGULAR, false,
|
FW_REGULAR, false,
|
||||||
false, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
|
false, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
|
||||||
DEFAULT_QUALITY, FF_DONTCARE, "Lucida Console");
|
DEFAULT_QUALITY, FF_DONTCARE, L"Lucida Console");
|
||||||
if(!FixedFont)
|
if(!FixedFont)
|
||||||
FixedFont = (HFONT)GetStockObject(SYSTEM_FONT);
|
FixedFont = (HFONT)GetStockObject(SYSTEM_FONT);
|
||||||
|
|
||||||
|
@ -1331,23 +1334,29 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||||
// Create the heaps for all dynamic memory (AllocTemporary, MemAlloc)
|
// Create the heaps for all dynamic memory (AllocTemporary, MemAlloc)
|
||||||
InitHeaps();
|
InitHeaps();
|
||||||
|
|
||||||
|
// Pull out the Unicode command line.
|
||||||
|
int argc;
|
||||||
|
LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||||
|
|
||||||
// A filename may have been specified on the command line; if so, then
|
// A filename may have been specified on the command line; if so, then
|
||||||
// strip any quotation marks, and make it absolute.
|
// strip any quotation marks, and make it absolute.
|
||||||
std::string filename = lpCmdLine;
|
std::wstring filenameRel, filename;
|
||||||
size_t pos;
|
if(argc >= 2) {
|
||||||
pos = filename.find_last_not_of("\"");
|
filenameRel = argv[1];
|
||||||
if(pos != std::string::npos)
|
if(filenameRel[0] == L'\"' && filenameRel[filenameRel.length() - 1] == L'\"') {
|
||||||
filename.erase(pos + 1);
|
filenameRel.erase(0, 1);
|
||||||
pos = filename.find_first_not_of(" \"");
|
filenameRel.erase(filenameRel.length() - 1, 1);
|
||||||
if(pos != std::string::npos)
|
}
|
||||||
filename.erase(0, pos);
|
|
||||||
if(!filename.empty())
|
DWORD len = GetFullPathNameW(&filenameRel[0], 0, NULL, NULL);
|
||||||
filename = GetAbsoluteFilename(filename);
|
filename.resize(len - 1);
|
||||||
|
GetFullPathNameW(&filenameRel[0], len, &filename[0], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SPACEWARE
|
#ifdef HAVE_SPACEWARE
|
||||||
// Initialize the SpaceBall, if present. Test if the driver is running
|
// Initialize the SpaceBall, if present. Test if the driver is running
|
||||||
// first, to avoid a long timeout if it's not.
|
// first, to avoid a long timeout if it's not.
|
||||||
HWND swdc = FindWindow("SpaceWare Driver Class", NULL);
|
HWND swdc = FindWindowW(L"SpaceWare Driver Class", NULL);
|
||||||
if(swdc != NULL) {
|
if(swdc != NULL) {
|
||||||
SiOpenData sod;
|
SiOpenData sod;
|
||||||
SiInitialize();
|
SiInitialize();
|
||||||
|
@ -1361,7 +1370,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||||
// Call in to the platform-independent code, and let them do their init
|
// Call in to the platform-independent code, and let them do their init
|
||||||
SS.Init();
|
SS.Init();
|
||||||
if(!filename.empty())
|
if(!filename.empty())
|
||||||
SS.OpenFile(filename);
|
SS.OpenFile(Narrow(filename));
|
||||||
|
|
||||||
// And now it's the message loop. All calls in to the rest of the code
|
// And now it's the message loop. All calls in to the rest of the code
|
||||||
// will be from the wndprocs.
|
// will be from the wndprocs.
|
||||||
|
|
|
@ -19,7 +19,52 @@ void dbp(const char *str, ...)
|
||||||
_vsnprintf(buf, sizeof(buf), str, f);
|
_vsnprintf(buf, sizeof(buf), str, f);
|
||||||
va_end(f);
|
va_end(f);
|
||||||
|
|
||||||
OutputDebugString(buf);
|
// The native version of OutputDebugString, unlike most others,
|
||||||
|
// is OutputDebugStringA.
|
||||||
|
OutputDebugStringA(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Narrow(const wchar_t *in)
|
||||||
|
{
|
||||||
|
std::string out;
|
||||||
|
DWORD len = WideCharToMultiByte(CP_UTF8, 0, in, -1, NULL, 0, NULL, NULL);
|
||||||
|
out.resize(len - 1);
|
||||||
|
if(!WideCharToMultiByte(CP_UTF8, 0, in, -1, &out[0], len, NULL, NULL))
|
||||||
|
oops();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Narrow(const std::wstring &in)
|
||||||
|
{
|
||||||
|
if(in == L"") return "";
|
||||||
|
|
||||||
|
std::string out;
|
||||||
|
out.resize(WideCharToMultiByte(CP_UTF8, 0, &in[0], in.length(), NULL, 0, NULL, NULL));
|
||||||
|
if(!WideCharToMultiByte(CP_UTF8, 0, &in[0], in.length(),
|
||||||
|
&out[0], out.length(), NULL, NULL))
|
||||||
|
oops();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring Widen(const char *in)
|
||||||
|
{
|
||||||
|
std::wstring out;
|
||||||
|
DWORD len = MultiByteToWideChar(CP_UTF8, 0, in, -1, NULL, 0);
|
||||||
|
out.resize(len - 1);
|
||||||
|
if(!MultiByteToWideChar(CP_UTF8, 0, in, -1, &out[0], len))
|
||||||
|
oops();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring Widen(const std::string &in)
|
||||||
|
{
|
||||||
|
if(in == "") return L"";
|
||||||
|
|
||||||
|
std::wstring out;
|
||||||
|
out.resize(MultiByteToWideChar(CP_UTF8, 0, &in[0], in.length(), NULL, 0));
|
||||||
|
if(!MultiByteToWideChar(CP_UTF8, 0, &in[0], in.length(), &out[0], out.length()))
|
||||||
|
oops();
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue
Block a user