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:
Alexander Kuznetsov
2012-03-20 02:17:37 +00:00
parent deea1f38b1
commit f11a6d3a84
66 changed files with 1012 additions and 175 deletions

View File

@@ -281,6 +281,10 @@ elseif(WIN32)
${WINTAB_INC}
)
list(APPEND INC
../utfconv
)
list(APPEND SRC
intern/GHOST_DisplayManagerWin32.cpp
intern/GHOST_SystemWin32.cpp

View File

@@ -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') )

View File

@@ -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;

View File

@@ -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)
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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 */