Adds support for utf paths on Windows.
Not all file formats/calls are supported yet. It will be expended. Please from now on use BLI_fopen, BLI_* for file manipulations. For non-windows systems BLI_fopen just calls fopen. For Windows, the utf-8 string is translated to utf-16 string in order to call UTF version of the function.
This commit is contained in:
@@ -281,6 +281,10 @@ elseif(WIN32)
|
||||
${WINTAB_INC}
|
||||
)
|
||||
|
||||
list(APPEND INC
|
||||
../utfconv
|
||||
)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_DisplayManagerWin32.cpp
|
||||
intern/GHOST_SystemWin32.cpp
|
||||
|
@@ -110,6 +110,7 @@ else:
|
||||
|
||||
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
|
||||
incs = env['BF_WINTAB_INC'] + ' ' + incs
|
||||
incs += ' ../utfconv'
|
||||
|
||||
if window_system in ('win32-vc', 'win64-vc'):
|
||||
env.BlenderLib ('bf_intern_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15]) #, cc_compileflags=env['CCFLAGS'].append('/WX') )
|
||||
|
@@ -34,6 +34,9 @@
|
||||
#include "GHOST_DropTargetWin32.h"
|
||||
#include <ShellApi.h>
|
||||
|
||||
#include "utf_winfunc.h"
|
||||
#include "utfconv.h"
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
// utility
|
||||
void printLastError(void);
|
||||
@@ -267,20 +270,12 @@ void * GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject * pDataObject)
|
||||
{
|
||||
if ( ::DragQueryFileW ( hdrop, nfile, fpath, MAX_PATH ) > 0 )
|
||||
{
|
||||
if ( !WideCharToANSI(fpath, temp_path) )
|
||||
if ( !(temp_path = alloc_utf_8_from_16(fpath, 0)) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Just ignore paths that could not be converted verbatim.
|
||||
if (strpbrk(temp_path, "?"))
|
||||
{
|
||||
#ifdef GHOST_DEBUG
|
||||
::printf("\ndiscarding path that contains illegal characters: %s", temp_path);
|
||||
#endif // GHOST_DEBUG
|
||||
::free(temp_path);
|
||||
temp_path = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
strArray->strings[nvalid] = (GHOST_TUns8*) temp_path;
|
||||
strArray->count = nvalid+1;
|
||||
nvalid++;
|
||||
@@ -309,7 +304,7 @@ void * GHOST_DropTargetWin32::getDropDataAsString(IDataObject * pDataObject)
|
||||
if(pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
|
||||
{
|
||||
LPCWSTR wstr = (LPCWSTR)::GlobalLock(stgmed.hGlobal);
|
||||
if ( !WideCharToANSI(wstr, tmp_string) )
|
||||
if ( !(tmp_string = alloc_utf_8_from_16((wchar_t*)wstr, 0)) )
|
||||
{
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
return NULL;
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#define _WIN32_IE 0x0501
|
||||
#endif
|
||||
#include <shlobj.h>
|
||||
#include "utfconv.h"
|
||||
|
||||
#if defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
|
||||
@@ -70,11 +71,14 @@ GHOST_SystemPathsWin32::~GHOST_SystemPathsWin32()
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsWin32::getSystemDir() const
|
||||
{
|
||||
static char knownpath[MAX_PATH];
|
||||
HRESULT hResult = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath);
|
||||
static char knownpath[MAX_PATH*3] = {0}; /* 1 utf-16 might translante into 3 utf-8. 2 utf-16 translates into 4 utf-8*/
|
||||
wchar_t knownpath_16[MAX_PATH];
|
||||
|
||||
HRESULT hResult = SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath_16);
|
||||
|
||||
if (hResult == S_OK)
|
||||
{
|
||||
conv_utf_16_to_8(knownpath_16,knownpath,MAX_PATH*3);
|
||||
return (GHOST_TUns8*)knownpath;
|
||||
}
|
||||
|
||||
@@ -83,11 +87,14 @@ const GHOST_TUns8* GHOST_SystemPathsWin32::getSystemDir() const
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsWin32::getUserDir() const
|
||||
{
|
||||
static char knownpath[MAX_PATH];
|
||||
HRESULT hResult = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath);
|
||||
static char knownpath[MAX_PATH*3] = {0};
|
||||
wchar_t knownpath_16[MAX_PATH];
|
||||
|
||||
HRESULT hResult = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath_16);
|
||||
|
||||
if (hResult == S_OK)
|
||||
{
|
||||
conv_utf_16_to_8(knownpath_16,knownpath,MAX_PATH*3);
|
||||
return (GHOST_TUns8*)knownpath;
|
||||
}
|
||||
|
||||
@@ -96,8 +103,11 @@ const GHOST_TUns8* GHOST_SystemPathsWin32::getUserDir() const
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsWin32::getBinaryDir() const
|
||||
{
|
||||
static char fullname[MAX_PATH];
|
||||
if(GetModuleFileName(0, fullname, MAX_PATH)) {
|
||||
static char fullname[MAX_PATH*3] = {0};
|
||||
wchar_t fullname_16[MAX_PATH*3];
|
||||
|
||||
if(GetModuleFileNameW(0, fullname_16, MAX_PATH)) {
|
||||
conv_utf_16_to_8(fullname_16,fullname,MAX_PATH*3);
|
||||
return (GHOST_TUns8*)fullname;
|
||||
}
|
||||
|
||||
@@ -107,5 +117,7 @@ const GHOST_TUns8* GHOST_SystemPathsWin32::getBinaryDir() const
|
||||
void GHOST_SystemPathsWin32::addToSystemRecentFiles(const char* filename) const
|
||||
{
|
||||
/* SHARD_PATH resolves to SHARD_PATHA for non-UNICODE build */
|
||||
SHAddToRecentDocs(SHARD_PATH,filename);
|
||||
UTF16_ENCODE(filename)
|
||||
SHAddToRecentDocs(SHARD_PATHW,filename_16);
|
||||
UTF16_UN_ENCODE(filename)
|
||||
}
|
||||
|
@@ -60,6 +60,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "utfconv.h"
|
||||
|
||||
#include "GHOST_DisplayManagerWin32.h"
|
||||
#include "GHOST_EventButton.h"
|
||||
#include "GHOST_EventCursor.h"
|
||||
@@ -292,8 +294,8 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
|
||||
}
|
||||
|
||||
// Process all the events waiting for us
|
||||
while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0) {
|
||||
::DispatchMessage(&msg);
|
||||
while (::PeekMessageW(&msg, 0, 0, 0, PM_REMOVE) != 0) {
|
||||
::DispatchMessageW(&msg);
|
||||
anyProcessed = true;
|
||||
}
|
||||
} while (waitForEvent && !anyProcessed);
|
||||
@@ -394,7 +396,7 @@ GHOST_TSuccess GHOST_SystemWin32::init()
|
||||
}
|
||||
|
||||
if (success) {
|
||||
WNDCLASS wc;
|
||||
WNDCLASSW wc;
|
||||
wc.style= CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc= s_wndProc;
|
||||
wc.cbClsExtra= 0;
|
||||
@@ -408,10 +410,10 @@ GHOST_TSuccess GHOST_SystemWin32::init()
|
||||
wc.hCursor = ::LoadCursor(0, IDC_ARROW);
|
||||
wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH);
|
||||
wc.lpszMenuName = 0;
|
||||
wc.lpszClassName= GHOST_WindowWin32::getWindowClassName();
|
||||
wc.lpszClassName= L"GHOST_WindowClass";
|
||||
|
||||
// Use RegisterClassEx for setting small icon
|
||||
if (::RegisterClass(&wc) == 0) {
|
||||
if (::RegisterClassW(&wc) == 0) {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
@@ -719,15 +721,17 @@ GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP
|
||||
char utf8_char[6] = {0};
|
||||
char ascii = 0;
|
||||
|
||||
wchar_t utf16[2]={0};
|
||||
wchar_t utf16[3]={0};
|
||||
BYTE state[256] ={0};
|
||||
GetKeyboardState(state);
|
||||
int r;
|
||||
GetKeyboardState((PBYTE)state);
|
||||
|
||||
if(ToUnicodeEx(vk, 0, state, utf16, 2, 0, system->m_keylayout))
|
||||
WideCharToMultiByte(CP_UTF8, 0,
|
||||
(wchar_t*)utf16, 1,
|
||||
(LPSTR) utf8_char, 5,
|
||||
NULL,NULL); else *utf8_char = 0;
|
||||
if(r = ToUnicodeEx(vk, 0, state, utf16, 2, 0, system->m_keylayout))
|
||||
|
||||
if((r>0 && r<3)){utf16[r]=0;
|
||||
|
||||
conv_utf_16_to_8(utf16,utf8_char,6);}
|
||||
else if (r==-1) utf8_char[0] = '\0';
|
||||
|
||||
|
||||
|
||||
@@ -1189,8 +1193,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
* DefWindowProc returns.
|
||||
*/
|
||||
break;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Other events
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WM_GETTEXT:
|
||||
@@ -1239,17 +1242,17 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
}
|
||||
|
||||
if (!eventHandled)
|
||||
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
lResult = ::DefWindowProcW(hwnd, msg, wParam, lParam);
|
||||
|
||||
return lResult;
|
||||
}
|
||||
|
||||
GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const
|
||||
{
|
||||
wchar_t *buffer;
|
||||
char *temp_buff;
|
||||
|
||||
if ( IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL) ) {
|
||||
wchar_t *buffer;
|
||||
size_t len = 0;
|
||||
HANDLE hData = GetClipboardData( CF_UNICODETEXT );
|
||||
if (hData == NULL) {
|
||||
@@ -1262,9 +1265,32 @@ GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, NULL, 0, NULL, NULL);
|
||||
temp_buff = (char*) malloc(len);
|
||||
WideCharToMultiByte(CP_UTF8, 0, buffer, -1, temp_buff, len, NULL, NULL);
|
||||
temp_buff = alloc_utf_8_from_16(buffer,0);
|
||||
|
||||
/* Buffer mustn't be accessed after CloseClipboard
|
||||
it would like accessing free-d memory */
|
||||
GlobalUnlock( hData );
|
||||
CloseClipboard();
|
||||
|
||||
return (GHOST_TUns8*)temp_buff;
|
||||
} else if ( IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL) ) {
|
||||
char *buffer;
|
||||
size_t len = 0;
|
||||
HANDLE hData = GetClipboardData( CF_TEXT );
|
||||
if (hData == NULL) {
|
||||
CloseClipboard();
|
||||
return NULL;
|
||||
}
|
||||
buffer = (char*)GlobalLock( hData );
|
||||
if (!buffer) {
|
||||
CloseClipboard();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = strlen(buffer);
|
||||
temp_buff = (char*) malloc(len+1);
|
||||
strncpy(temp_buff, buffer, len);
|
||||
temp_buff[len] = '\0';
|
||||
|
||||
/* Buffer mustn't be accessed after CloseClipboard
|
||||
it would like accessing free-d memory */
|
||||
@@ -1281,20 +1307,19 @@ void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const
|
||||
{
|
||||
if(selection) {return;} // for copying the selection, used on X11
|
||||
|
||||
if (OpenClipboard(NULL)) {
|
||||
if(OpenClipboard(NULL)) {
|
||||
HLOCAL clipbuffer;
|
||||
wchar_t *data;
|
||||
|
||||
if (buffer) {
|
||||
size_t len = count_utf_16_from_8(buffer);
|
||||
EmptyClipboard();
|
||||
|
||||
int wlen = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, NULL, 0);
|
||||
|
||||
clipbuffer = LocalAlloc(LMEM_FIXED, wlen * sizeof(wchar_t));
|
||||
clipbuffer = LocalAlloc(LMEM_FIXED,sizeof(wchar_t) * len);
|
||||
data = (wchar_t*)GlobalLock(clipbuffer);
|
||||
|
||||
MultiByteToWideChar(CP_UTF8, 0, buffer, -1, data, wlen);
|
||||
|
||||
|
||||
conv_utf_8_to_16(buffer, data, len);
|
||||
|
||||
LocalUnlock(clipbuffer);
|
||||
SetClipboardData(CF_UNICODETEXT,clipbuffer);
|
||||
}
|
||||
|
@@ -41,6 +41,8 @@
|
||||
#include "GHOST_WindowWin32.h"
|
||||
#include "GHOST_SystemWin32.h"
|
||||
#include "GHOST_DropTargetWin32.h"
|
||||
#include "utfconv.h"
|
||||
#include "utf_winfunc.h"
|
||||
|
||||
// Need glew for some defines
|
||||
#include <GL/glew.h>
|
||||
@@ -64,7 +66,7 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
LPCSTR GHOST_WindowWin32::s_windowClassName = "GHOST_WindowClass";
|
||||
wchar_t* GHOST_WindowWin32::s_windowClassName = L"GHOST_WindowClass";
|
||||
const int GHOST_WindowWin32::s_maxTitleLength = 128;
|
||||
HGLRC GHOST_WindowWin32::s_firsthGLRc = NULL;
|
||||
HDC GHOST_WindowWin32::s_firstHDC = NULL;
|
||||
@@ -234,9 +236,10 @@ GHOST_WindowWin32::GHOST_WindowWin32(
|
||||
height = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
m_hWnd = ::CreateWindow(
|
||||
wchar_t * title_16 = alloc_utf16_from_8((char*)(const char*)title,0);
|
||||
m_hWnd = ::CreateWindowW(
|
||||
s_windowClassName, // pointer to registered class name
|
||||
title, // pointer to window name
|
||||
title_16, // pointer to window name
|
||||
wintype, // window style
|
||||
left, // horizontal position of window
|
||||
top, // vertical position of window
|
||||
@@ -246,11 +249,13 @@ GHOST_WindowWin32::GHOST_WindowWin32(
|
||||
0, // handle to menu or child-window identifier
|
||||
::GetModuleHandle(0), // handle to application instance
|
||||
0); // pointer to window-creation data
|
||||
free(title_16);
|
||||
}
|
||||
else {
|
||||
m_hWnd = ::CreateWindow(
|
||||
wchar_t * title_16 = alloc_utf16_from_8((char*)(const char*)title,0);
|
||||
m_hWnd = ::CreateWindowW(
|
||||
s_windowClassName, // pointer to registered class name
|
||||
title, // pointer to window name
|
||||
title_16, // pointer to window name
|
||||
WS_POPUP | WS_MAXIMIZE, // window style
|
||||
left, // horizontal position of window
|
||||
top, // vertical position of window
|
||||
@@ -260,6 +265,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(
|
||||
0, // handle to menu or child-window identifier
|
||||
::GetModuleHandle(0), // handle to application instance
|
||||
0); // pointer to window-creation data
|
||||
free(title_16);
|
||||
}
|
||||
if (m_hWnd) {
|
||||
// Register this window as a droptarget. Requires m_hWnd to be valid.
|
||||
@@ -433,13 +439,15 @@ HWND GHOST_WindowWin32::getHWND() const
|
||||
|
||||
void GHOST_WindowWin32::setTitle(const STR_String& title)
|
||||
{
|
||||
::SetWindowText(m_hWnd, title);
|
||||
wchar_t * title_16 = alloc_utf16_from_8((char*)(const char*)title, 0);
|
||||
::SetWindowTextW(m_hWnd, (wchar_t*)title_16);
|
||||
free(title_16);
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowWin32::getTitle(STR_String& title) const
|
||||
{
|
||||
char buf[s_maxTitleLength];
|
||||
char buf[s_maxTitleLength];/*CHANGE + never used yet*/
|
||||
::GetWindowText(m_hWnd, buf, s_maxTitleLength);
|
||||
STR_String temp (buf);
|
||||
title = buf;
|
||||
|
@@ -236,7 +236,7 @@ public:
|
||||
* Returns the name of the window class.
|
||||
* @return The name of the window class.
|
||||
*/
|
||||
static LPCSTR getWindowClassName() { return s_windowClassName; }
|
||||
static wchar_t* getWindowClassName() { return s_windowClassName; }
|
||||
|
||||
/**
|
||||
* Register a mouse click event (should be called
|
||||
@@ -351,7 +351,7 @@ protected:
|
||||
/** ITaskbarList3 structure for progress bar*/
|
||||
ITaskbarList3 * m_Bar;
|
||||
|
||||
static LPCSTR s_windowClassName;
|
||||
static wchar_t* s_windowClassName;
|
||||
static const int s_maxTitleLength;
|
||||
|
||||
/** WinTab dll handle */
|
||||
|
Reference in New Issue
Block a user