From defed109c22cf0e3570fcc2686645ccef8228dfc Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 5 May 2017 13:55:47 +0000 Subject: On Windows, use Tcl_WinTCharToUtf() in stead of Tcl_NewUnicodeObj(), since Tcl_WinTCharToUtf() works correctly when TCL_UTF_MAX==6 while Tcl_NewUnicodeObj() doesn't. All changes taken over from androwish. Thanks to Christian Werner! And ... on the go ... fixed a few memory leaks correctly detected by Christian. --- win/tkWinClipboard.c | 2 +- win/tkWinDialog.c | 52 ++++++++++++++++++++++++++++++++++++++++++++-------- win/tkWinInit.c | 7 ++++++- win/tkWinSend.c | 42 ++++++++++++++++++++++++++++++++++-------- win/tkWinSendCom.c | 25 ++++++++++++++++++++----- win/tkWinTest.c | 5 ++++- 6 files changed, 109 insertions(+), 24 deletions(-) diff --git a/win/tkWinClipboard.c b/win/tkWinClipboard.c index 929070b..03c0cde 100644 --- a/win/tkWinClipboard.c +++ b/win/tkWinClipboard.c @@ -331,7 +331,7 @@ TkWinClipboardRender( #ifdef UNICODE Tcl_DStringInit(&ds); - Tcl_UtfToUniCharDString(rawText, -1, &ds); + Tcl_WinUtfToTChar(rawText, -1, &ds); ckfree(rawText); handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, (unsigned) Tcl_DStringLength(&ds) + 2); diff --git a/win/tkWinDialog.c b/win/tkWinDialog.c index a7d8c7d..635b9a3 100644 --- a/win/tkWinDialog.c +++ b/win/tkWinDialog.c @@ -1379,17 +1379,27 @@ static int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr, goto vamoose; if (optsPtr->extObj != NULL) { - wstr = Tcl_GetUnicode(optsPtr->extObj); + Tcl_DString ds; + const char *src; + + src = Tcl_GetString(optsPtr->extObj); + wstr = (LPWSTR) Tcl_WinUtfToTChar(src, optsPtr->extObj->length, &ds); if (wstr[0] == L'.') ++wstr; hr = fdlgIf->lpVtbl->SetDefaultExtension(fdlgIf, wstr); + Tcl_DStringFree(&ds); if (FAILED(hr)) goto vamoose; } if (optsPtr->titleObj != NULL) { - hr = fdlgIf->lpVtbl->SetTitle(fdlgIf, - Tcl_GetUnicode(optsPtr->titleObj)); + Tcl_DString ds; + const char *src; + + src = Tcl_GetString(optsPtr->titleObj); + wstr = (LPWSTR) Tcl_WinUtfToTChar(src, optsPtr->titleObj->length, &ds); + hr = fdlgIf->lpVtbl->SetTitle(fdlgIf, wstr); + Tcl_DStringFree(&ds); if (FAILED(hr)) goto vamoose; } @@ -1464,12 +1474,14 @@ static int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr, SIGDN_FILESYSPATH, &wstr); if (SUCCEEDED(hr)) { Tcl_DString fnds; + ConvertExternalFilename(wstr, &fnds); CoTaskMemFree(wstr); Tcl_ListObjAppendElement( interp, multiObj, Tcl_NewStringObj(Tcl_DStringValue(&fnds), Tcl_DStringLength(&fnds))); + Tcl_DStringFree(&fnds); } itemIf->lpVtbl->Release(itemIf); if (FAILED(hr)) @@ -1490,10 +1502,12 @@ static int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr, &wstr); if (SUCCEEDED(hr)) { Tcl_DString fnds; + ConvertExternalFilename(wstr, &fnds); resultObj = Tcl_NewStringObj(Tcl_DStringValue(&fnds), Tcl_DStringLength(&fnds)); CoTaskMemFree(wstr); + Tcl_DStringFree(&fnds); } resultIf->lpVtbl->Release(resultIf); } @@ -1501,13 +1515,20 @@ static int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr, if (SUCCEEDED(hr)) { if (filterPtr && optsPtr->typeVariableObj) { UINT ftix; + hr = fdlgIf->lpVtbl->GetFileTypeIndex(fdlgIf, &ftix); if (SUCCEEDED(hr)) { /* Note ftix is a 1-based index */ if (ftix > 0 && ftix <= nfilters) { + Tcl_DString ftds; + Tcl_Obj *ftobj; + + Tcl_WinTCharToUtf(filterPtr[ftix-1].pszName, -1, &ftds); + ftobj = Tcl_NewStringObj(Tcl_DStringValue(&ftds), + Tcl_DStringLength(&ftds)); Tcl_ObjSetVar2(interp, optsPtr->typeVariableObj, NULL, - Tcl_NewUnicodeObj(filterPtr[ftix-1].pszName, -1), - TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); + ftobj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG); + Tcl_DStringFree(&ftds); } } } @@ -2786,6 +2807,9 @@ Tk_MessageBoxObjCmd( }; ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tcl_DString titleBuf, tmpBuf; + WCHAR *titlePtr, *tmpPtr; + const char *src; defaultBtn = -1; detailObj = NULL; @@ -2896,7 +2920,9 @@ Tk_MessageBoxObjCmd( : Tcl_NewUnicodeObj(NULL, 0); Tcl_IncrRefCount(tmpObj); if (detailObj) { - Tcl_AppendUnicodeToObj(tmpObj, L"\n\n", 2); + const Tcl_UniChar twoNL[] = { '\n', '\n' }; + + Tcl_AppendUnicodeToObj(tmpObj, twoNL, 2); Tcl_AppendObjToObj(tmpObj, detailObj); } @@ -2915,8 +2941,18 @@ Tk_MessageBoxObjCmd( tsdPtr->hBigIcon = TkWinGetIcon(parent, ICON_BIG); tsdPtr->hMsgBoxHook = SetWindowsHookEx(WH_CBT, MsgBoxCBTProc, NULL, GetCurrentThreadId()); - winCode = MessageBox(hWnd, Tcl_GetUnicode(tmpObj), - titleObj ? Tcl_GetUnicode(titleObj) : L"", flags); + src = Tcl_GetString(tmpObj); + tmpPtr = Tcl_WinUtfToTChar(src, tmpObj->length, &tmpBuf); + if (titleObj != NULL) { + src = Tcl_GetString(titleObj); + titlePtr = Tcl_WinUtfToTChar(src, titleObj->length, &titleBuf); + } else { + titlePtr = L""; + Tcl_DStringInit(&titleBuf); + } + winCode = MessageBox(hWnd, tmpPtr, titlePtr, flags); + Tcl_DStringFree(&titleBuf); + Tcl_DStringFree(&tmpBuf); UnhookWindowsHookEx(tsdPtr->hMsgBoxHook); (void) Tcl_SetServiceMode(oldMode); diff --git a/win/tkWinInit.c b/win/tkWinInit.c index b1b2d6b..4c18399 100644 --- a/win/tkWinInit.c +++ b/win/tkWinInit.c @@ -181,6 +181,9 @@ TkWin32ErrorObj( LPTSTR lpBuffer = NULL, p = NULL; TCHAR sBuffer[30]; Tcl_Obj* errPtr = NULL; +#ifdef _UNICODE + Tcl_DString ds; +#endif FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD)hrError, @@ -196,7 +199,9 @@ TkWin32ErrorObj( } #ifdef _UNICODE - errPtr = Tcl_NewUnicodeObj(lpBuffer, (int)wcslen(lpBuffer)); + Tcl_WinTCharToUtf(lpBuffer, (int)wcslen(lpBuffer) * sizeof (WCHAR), &ds); + errPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); #else errPtr = Tcl_NewStringObj(lpBuffer, (int)strlen(lpBuffer)); #endif /* _UNICODE */ diff --git a/win/tkWinSend.c b/win/tkWinSend.c index 6c4731a..c999c0b 100644 --- a/win/tkWinSend.c +++ b/win/tkWinSend.c @@ -252,8 +252,14 @@ TkGetInterpNames( LPOLESTR p = olestr + wcslen(oleszStub); if (*p) { + Tcl_DString ds; + + Tcl_WinTCharToUtf(p + 1, -1, &ds); result = Tcl_ListObjAppendElement(interp, - objList, Tcl_NewUnicodeObj(p + 1, -1)); + objList, + Tcl_NewStringObj(Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds))); + Tcl_DStringFree(&ds); } } @@ -614,7 +620,7 @@ BuildMoniker( Tcl_DString dString; Tcl_DStringInit(&dString); - Tcl_UtfToUniCharDString(name, -1, &dString); + Tcl_WinUtfToTChar(name, -1, &dString); hr = CreateFileMoniker((LPOLESTR)Tcl_DStringValue(&dString), &pmkItem); Tcl_DStringFree(&dString); if (SUCCEEDED(hr)) { @@ -740,6 +746,8 @@ Send( HRESULT hr = S_OK, ehr = S_OK; Tcl_Obj *cmd = NULL; DISPID dispid; + Tcl_DString ds; + const char *src; cmd = Tcl_ConcatObj(objc, objv); @@ -753,7 +761,10 @@ Send( memset(&ei, 0, sizeof(ei)); vCmd.vt = VT_BSTR; - vCmd.bstrVal = SysAllocString(Tcl_GetUnicode(cmd)); + src = Tcl_GetString(cmd); + Tcl_WinUtfToTChar(src, cmd->length, &ds); + vCmd.bstrVal = SysAllocString((WCHAR *) Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); dp.cArgs = 1; dp.rgvarg = &vCmd; @@ -774,7 +785,9 @@ Send( ehr = VariantChangeType(&vResult, &vResult, 0, VT_BSTR); if (SUCCEEDED(ehr)) { - Tcl_SetObjResult(interp, Tcl_NewUnicodeObj(vResult.bstrVal, -1)); + Tcl_WinTCharToUtf(vResult.bstrVal, (int) SysStringLen(vResult.bstrVal) * + sizeof (WCHAR), &ds); + Tcl_DStringResult(interp, &ds); } /* @@ -785,8 +798,11 @@ Send( if (hr == DISP_E_EXCEPTION && ei.bstrSource != NULL) { Tcl_Obj *opError, *opErrorCode, *opErrorInfo; - - opError = Tcl_NewUnicodeObj(ei.bstrSource, -1); + Tcl_WinTCharToUtf(ei.bstrSource, (int) SysStringLen(ei.bstrSource) * + sizeof (WCHAR), &ds); + opError = Tcl_NewStringObj(Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); Tcl_ListObjIndex(interp, opError, 0, &opErrorCode); Tcl_SetObjErrorCode(interp, opErrorCode); Tcl_ListObjIndex(interp, opError, 1, &opErrorInfo); @@ -833,6 +849,8 @@ TkWinSend_SetExcepInfo( ICreateErrorInfo *pCEI; IErrorInfo *pEI, **ppEI = &pEI; HRESULT hr; + Tcl_DString ds; + const char *src; if (!pExcepInfo) { return; @@ -851,8 +869,16 @@ TkWinSend_SetExcepInfo( Tcl_ListObjAppendElement(interp, opErrorCode, opErrorInfo); /* TODO: Handle failure to append */ - pExcepInfo->bstrDescription = SysAllocString(Tcl_GetUnicode(opError)); - pExcepInfo->bstrSource = SysAllocString(Tcl_GetUnicode(opErrorCode)); + src = Tcl_GetString(opError); + Tcl_WinUtfToTChar(src, opError->length, &ds); + pExcepInfo->bstrDescription = + SysAllocString((WCHAR *) Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); + src = Tcl_GetString(opErrorCode); + Tcl_WinUtfToTChar(src, opErrorCode->length, &ds); + pExcepInfo->bstrSource = + SysAllocString((WCHAR *) Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); Tcl_DecrRefCount(opErrorCode); pExcepInfo->scode = E_FAIL; diff --git a/win/tkWinSendCom.c b/win/tkWinSendCom.c index 83dd56b..9e5b7a0 100644 --- a/win/tkWinSendCom.c +++ b/win/tkWinSendCom.c @@ -370,6 +370,7 @@ Async( { HRESULT hr = S_OK; VARIANT vCmd; + Tcl_DString ds; VariantInit(&vCmd); @@ -382,9 +383,13 @@ Async( } if (SUCCEEDED(hr) && obj->interp) { - Tcl_Obj *scriptPtr = Tcl_NewUnicodeObj(vCmd.bstrVal, - (int) SysStringLen(vCmd.bstrVal)); + Tcl_Obj *scriptPtr; + Tcl_WinTCharToUtf(vCmd.bstrVal, (int) SysStringLen(vCmd.bstrVal) * + sizeof (WCHAR), &ds); + scriptPtr = + Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); TkWinSend_QueueCommand(obj->interp, scriptPtr); } @@ -424,6 +429,7 @@ Send( VARIANT v; register Tcl_Interp *interp = obj->interp; Tcl_Obj *scriptPtr; + Tcl_DString ds; if (interp == NULL) { return S_OK; @@ -434,17 +440,26 @@ Send( return hr; } - scriptPtr = Tcl_NewUnicodeObj(v.bstrVal, (int) SysStringLen(v.bstrVal)); + Tcl_WinTCharToUtf(v.bstrVal, (int) SysStringLen(v.bstrVal) * + sizeof (WCHAR), &ds); + scriptPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); Tcl_Preserve(interp); Tcl_IncrRefCount(scriptPtr); result = Tcl_EvalObjEx(interp, scriptPtr, TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL); Tcl_DecrRefCount(scriptPtr); if (pvResult != NULL) { + Tcl_Obj *obj; + const char *src; + VariantInit(pvResult); pvResult->vt = VT_BSTR; - pvResult->bstrVal = SysAllocString(Tcl_GetUnicode( - Tcl_GetObjResult(interp))); + obj = Tcl_GetObjResult(interp); + src = Tcl_GetString(obj); + Tcl_WinUtfToTChar(src, obj->length, &ds); + pvResult->bstrVal = SysAllocString((WCHAR *) Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); } if (result == TCL_ERROR) { hr = DISP_E_EXCEPTION; diff --git a/win/tkWinTest.c b/win/tkWinTest.c index d824ee4..6e79df3 100644 --- a/win/tkWinTest.c +++ b/win/tkWinTest.c @@ -515,6 +515,7 @@ TestgetwindowinfoObjCmd( Tcl_Obj *childrenObj = NULL; TCHAR buf[512]; int cch, cchBuf = 256; + Tcl_DString ds; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "hwnd"); @@ -542,7 +543,9 @@ TestgetwindowinfoObjCmd( Tcl_NewLongObj(GetWindowLongA(INT2PTR(hwnd), GWL_ID))); cch = GetWindowText(INT2PTR(hwnd), (LPTSTR)buf, cchBuf); - textObj = Tcl_NewUnicodeObj((LPCWSTR)buf, cch); + Tcl_WinTCharToUtf(buf, cch * sizeof (WCHAR), &ds); + textObj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("text", 4), textObj); Tcl_DictObjPut(interp, dictObj, Tcl_NewStringObj("parent", 6), -- cgit v0.12