Merge pull request #113 from tesselode/fix-multi-targets
[wdl/wdl-ol.git] / WDL / win32_utf8.c
blob24d4d1a8c2177200e51c20ef0f11f1def8d9e567
1 #if defined(_WIN32) && !defined(WDL_WIN32_UTF8_NO_UI_IMPL)
2 #include <shlobj.h>
3 #include <commctrl.h>
4 #endif
6 #include "win32_utf8.h"
7 #include "wdltypes.h"
8 #include "wdlutf8.h"
10 #ifdef _WIN32
12 #if !defined(WDL_NO_SUPPORT_UTF8)
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
19 #ifndef WDL_UTF8_MAXFNLEN
20 #define WDL_UTF8_MAXFNLEN 2048
21 #endif
23 #define MBTOWIDE(symbase, src) \
24 int symbase##_size; \
25 WCHAR symbase##_buf[1024]; \
26 WCHAR *symbase = (symbase##_size=MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,src,-1,NULL,0)) >= 1000 ? (WCHAR *)malloc(symbase##_size * sizeof(WCHAR) + 10) : symbase##_buf; \
27 int symbase##_ok = symbase ? (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,src,-1,symbase,symbase##_size < 1 ? 1024 : symbase##_size)) : 0
29 #define MBTOWIDE_FREE(symbase) if (symbase != symbase##_buf) free(symbase)
32 #define WIDETOMB_ALLOC(symbase, length) \
33 WCHAR symbase##_buf[1024]; \
34 size_t symbase##_size = sizeof(symbase##_buf); \
35 WCHAR *symbase = (length) > 1000 ? (WCHAR *)malloc(symbase##_size = (sizeof(WCHAR)*(length) + 10)) : symbase##_buf
37 #define WIDETOMB_FREE(symbase) if (symbase != symbase##_buf) free(symbase)
39 BOOL WDL_HasUTF8(const char *_str)
41 return WDL_DetectUTF8(_str) > 0;
44 #ifdef AND_IS_NOT_WIN9X
45 #undef AND_IS_NOT_WIN9X
46 #endif
47 #ifdef IS_NOT_WIN9X_AND
48 #undef IS_NOT_WIN9X_AND
49 #endif
51 #ifdef WDL_SUPPORT_WIN9X
52 #define IS_NOT_WIN9X_AND (GetVersion() < 0x80000000) &&
53 #define AND_IS_NOT_WIN9X && (GetVersion() < 0x80000000)
54 #else
55 #define AND_IS_NOT_WIN9X
56 #define IS_NOT_WIN9X_AND
57 #endif
59 static ATOM s_combobox_atom;
60 #define WDL_UTF8_OLDPROCPROP "WDLUTF8OldProc"
62 int GetWindowTextUTF8(HWND hWnd, LPTSTR lpString, int nMaxCount)
64 if (!lpString) return 0;
65 if (nMaxCount>0 AND_IS_NOT_WIN9X)
67 int alloc_size=nMaxCount;
69 // if a hooked combo box, and has an edit child, ask it directly
70 if (s_combobox_atom && s_combobox_atom == GetClassWord(hWnd,GCW_ATOM) && GetProp(hWnd,WDL_UTF8_OLDPROCPROP))
72 HWND h2=FindWindowEx(hWnd,NULL,"Edit",NULL);
73 if (h2) hWnd=h2;
74 else
76 // get via selection
77 int sel = (int) SendMessage(hWnd,CB_GETCURSEL,0,0);
78 if (sel>=0)
80 int len = (int) SendMessage(hWnd,CB_GETLBTEXTLEN,sel,0);
81 char *p = lpString;
82 if (len > nMaxCount-1)
84 p = (char*)calloc(len+1,1);
85 len = nMaxCount-1;
87 lpString[0]=0;
88 if (p)
90 SendMessage(hWnd,CB_GETLBTEXT,sel,(LPARAM)p);
91 if (p!=lpString)
93 memcpy(lpString,p,len);
94 lpString[len]=0;
95 free(p);
97 return len;
103 // prevent large values of nMaxCount from allocating memory unless the underlying text is big too
104 if (alloc_size > 512)
106 int l=GetWindowTextLengthW(hWnd);
107 if (l>=0 && l < 512) alloc_size=1000;
111 WIDETOMB_ALLOC(wbuf, alloc_size);
112 if (wbuf)
114 lpString[0]=0;
115 if (GetWindowTextW(hWnd,wbuf,(int) (wbuf_size/sizeof(WCHAR))))
117 if (!WideCharToMultiByte(CP_UTF8,0,wbuf,-1,lpString,nMaxCount,NULL,NULL))
118 lpString[nMaxCount-1]=0;
121 WIDETOMB_FREE(wbuf);
123 return (int)strlen(lpString);
127 return GetWindowTextA(hWnd,lpString,nMaxCount);
130 UINT GetDlgItemTextUTF8(HWND hDlg, int nIDDlgItem, LPTSTR lpString, int nMaxCount)
132 HWND h = GetDlgItem(hDlg,nIDDlgItem);
133 if (h) return GetWindowTextUTF8(h,lpString,nMaxCount);
134 return 0;
138 BOOL SetDlgItemTextUTF8(HWND hDlg, int nIDDlgItem, LPCTSTR lpString)
140 HWND h = GetDlgItem(hDlg,nIDDlgItem);
141 if (!h) return FALSE;
143 if (WDL_HasUTF8(lpString) AND_IS_NOT_WIN9X)
145 MBTOWIDE(wbuf,lpString);
146 if (wbuf_ok)
148 BOOL rv = SetWindowTextW(h, wbuf);
149 MBTOWIDE_FREE(wbuf);
150 return rv;
153 MBTOWIDE_FREE(wbuf);
156 return SetWindowTextA(h, lpString);
160 static LRESULT WINAPI __forceUnicodeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
162 if (uMsg == WM_SETTEXT && lParam)
164 MBTOWIDE(wbuf,(const char *)lParam);
165 if (wbuf_ok)
167 LRESULT rv = DefWindowProcW(hwnd, uMsg, wParam, (LPARAM)wbuf);
168 MBTOWIDE_FREE(wbuf);
169 return rv;
171 MBTOWIDE_FREE(wbuf);
173 return DefWindowProc(hwnd, uMsg, wParam, lParam);
176 BOOL SetWindowTextUTF8(HWND hwnd, LPCTSTR str)
178 if (WDL_HasUTF8(str) AND_IS_NOT_WIN9X)
180 DWORD pid;
181 if (GetWindowThreadProcessId(hwnd,&pid) == GetCurrentThreadId() &&
182 pid == GetCurrentProcessId() &&
183 !(GetWindowLong(hwnd,GWL_STYLE)&WS_CHILD))
185 LPARAM tmp = SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LPARAM)__forceUnicodeWndProc);
186 BOOL rv = SetWindowTextA(hwnd, str);
187 SetWindowLongPtr(hwnd, GWLP_WNDPROC, tmp);
188 return rv;
190 else
192 MBTOWIDE(wbuf,str);
193 if (wbuf_ok)
195 BOOL rv = SetWindowTextW(hwnd, wbuf);
196 MBTOWIDE_FREE(wbuf);
197 return rv;
200 MBTOWIDE_FREE(wbuf);
204 return SetWindowTextA(hwnd,str);
207 int MessageBoxUTF8(HWND hwnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT fl)
209 if ((WDL_HasUTF8(lpText)||WDL_HasUTF8(lpCaption)) AND_IS_NOT_WIN9X)
211 MBTOWIDE(wbuf,lpText);
212 if (wbuf_ok)
214 MBTOWIDE(wcap,lpCaption?lpCaption:"");
215 if (wcap_ok)
217 int ret=MessageBoxW(hwnd,wbuf,lpCaption?wcap:NULL,fl);
218 MBTOWIDE_FREE(wcap);
219 MBTOWIDE_FREE(wbuf);
220 return ret;
222 MBTOWIDE_FREE(wbuf);
225 return MessageBoxA(hwnd,lpText,lpCaption,fl);
228 UINT DragQueryFileUTF8(HDROP hDrop, UINT idx, char *buf, UINT bufsz)
230 if (buf && bufsz && idx!=-1 AND_IS_NOT_WIN9X)
232 const UINT reqsz = DragQueryFileW(hDrop,idx,NULL,0);
233 WIDETOMB_ALLOC(wbuf, reqsz+32);
234 if (wbuf)
236 UINT rv=DragQueryFileW(hDrop,idx,wbuf,(int)(wbuf_size/sizeof(WCHAR)));
237 if (rv)
239 if (!WideCharToMultiByte(CP_UTF8,0,wbuf,-1,buf,bufsz,NULL,NULL))
240 buf[bufsz-1]=0;
242 WIDETOMB_FREE(wbuf);
243 return rv;
246 return DragQueryFileA(hDrop,idx,buf,bufsz);
250 WCHAR *WDL_UTF8ToWC(const char *buf, BOOL doublenull, int minsize, DWORD *sizeout)
252 if (doublenull)
254 int sz=1;
255 const char *p = (const char *)buf;
256 WCHAR *pout,*ret;
258 while (*p)
260 int a=MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,p,-1,NULL,0);
261 int sp=(int)strlen(p)+1;
262 if (a < sp)a=sp; // in case it needs to be ansi mapped
263 sz+=a;
264 p+=sp;
266 if (sz < minsize) sz=minsize;
268 pout = (WCHAR *) malloc(sizeof(WCHAR)*(sz+4));
269 if (!pout) return NULL;
271 ret=pout;
272 p = (const char *)buf;
273 while (*p)
275 int a;
276 *pout=0;
277 a = MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,p,-1,pout,(int) (sz-(pout-ret)));
278 if (!a)
280 pout[0]=0;
281 a=MultiByteToWideChar(CP_ACP,MB_ERR_INVALID_CHARS,p,-1,pout,(int) (sz-(pout-ret)));
283 pout += a;
284 p+=strlen(p)+1;
286 *pout=0;
287 pout[1]=0;
288 if (sizeout) *sizeout=sz;
289 return ret;
291 else
293 int srclen = (int)strlen(buf)+1;
294 int size=MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,buf,srclen,NULL,0);
295 if (size < srclen)size=srclen; // for ansi code page
296 if (size<minsize)size=minsize;
299 WCHAR *outbuf = (WCHAR *)malloc(sizeof(WCHAR)*(size+128));
300 if (!outbuf) return NULL;
302 *outbuf=0;
303 if (srclen>1)
305 int a=MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,buf,srclen,outbuf, size);
306 if (!a)
308 outbuf[0]=0;
309 a=MultiByteToWideChar(CP_ACP,MB_ERR_INVALID_CHARS,buf,srclen,outbuf,size);
312 if (sizeout) *sizeout = size;
313 return outbuf;
318 #ifndef WDL_WIN32_UTF8_NO_UI_IMPL
319 static BOOL GetOpenSaveFileNameUTF8(LPOPENFILENAME lpofn, BOOL save)
322 OPENFILENAMEW tmp={sizeof(tmp),lpofn->hwndOwner,lpofn->hInstance,};
323 BOOL ret;
325 // allocate, convert input
326 if (lpofn->lpstrFilter) tmp.lpstrFilter = WDL_UTF8ToWC(lpofn->lpstrFilter,TRUE,0,0);
327 tmp.nFilterIndex = lpofn->nFilterIndex ;
329 if (lpofn->lpstrFile) tmp.lpstrFile = WDL_UTF8ToWC(lpofn->lpstrFile,FALSE,lpofn->nMaxFile,&tmp.nMaxFile);
330 if (lpofn->lpstrFileTitle) tmp.lpstrFileTitle = WDL_UTF8ToWC(lpofn->lpstrFileTitle,FALSE,lpofn->nMaxFileTitle,&tmp.nMaxFileTitle);
331 if (lpofn->lpstrInitialDir) tmp.lpstrInitialDir = WDL_UTF8ToWC(lpofn->lpstrInitialDir,0,0,0);
332 if (lpofn->lpstrTitle) tmp.lpstrTitle = WDL_UTF8ToWC(lpofn->lpstrTitle,0,0,0);
333 if (lpofn->lpstrDefExt) tmp.lpstrDefExt = WDL_UTF8ToWC(lpofn->lpstrDefExt,0,0,0);
334 tmp.Flags = lpofn->Flags;
335 tmp.lCustData = lpofn->lCustData;
336 tmp.lpfnHook = lpofn->lpfnHook;
337 tmp.lpTemplateName = (const WCHAR *)lpofn->lpTemplateName ;
339 ret=save ? GetSaveFileNameW(&tmp) : GetOpenFileNameW(&tmp);
341 // free, convert output
342 if (ret && lpofn->lpstrFile && tmp.lpstrFile)
344 if ((tmp.Flags & OFN_ALLOWMULTISELECT) && tmp.lpstrFile[wcslen(tmp.lpstrFile)+1])
346 char *op = lpofn->lpstrFile;
347 WCHAR *ip = tmp.lpstrFile;
348 while (*ip)
350 const int bcount = WideCharToMultiByte(CP_UTF8,0,ip,-1,NULL,0,NULL,NULL);
352 const int maxout=lpofn->nMaxFile - 2 - (int)(op - lpofn->lpstrFile);
353 if (maxout < 2+bcount) break;
354 op += WideCharToMultiByte(CP_UTF8,0,ip,-1,op,maxout,NULL,NULL);
355 ip += wcslen(ip)+1;
357 *op=0;
359 else
361 int len = WideCharToMultiByte(CP_UTF8,0,tmp.lpstrFile,-1,lpofn->lpstrFile,lpofn->nMaxFile-1,NULL,NULL);
362 if (len == 0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER) len = lpofn->nMaxFile-2;
363 lpofn->lpstrFile[len]=0;
364 if (!len)
366 lpofn->lpstrFile[len+1]=0;
367 ret=0;
370 // convert
373 lpofn->nFileOffset = tmp.nFileOffset ;
374 lpofn->nFileExtension = tmp.nFileExtension;
375 lpofn->lCustData = tmp.lCustData;
377 free((WCHAR *)tmp.lpstrFilter);
378 free((WCHAR *)tmp.lpstrFile);
379 free((WCHAR *)tmp.lpstrFileTitle);
380 free((WCHAR *)tmp.lpstrInitialDir);
381 free((WCHAR *)tmp.lpstrTitle);
382 free((WCHAR *)tmp.lpstrDefExt );
384 lpofn->nFilterIndex = tmp.nFilterIndex ;
385 return ret;
388 BOOL GetOpenFileNameUTF8(LPOPENFILENAME lpofn)
390 #ifdef WDL_SUPPORT_WIN9X
391 if (GetVersion()&0x80000000) return GetOpenFileNameA(lpofn);
392 #endif
393 return GetOpenSaveFileNameUTF8(lpofn,FALSE);
396 BOOL GetSaveFileNameUTF8(LPOPENFILENAME lpofn)
398 #ifdef WDL_SUPPORT_WIN9X
399 if (GetVersion()&0x80000000) return GetSaveFileNameA(lpofn);
400 #endif
401 return GetOpenSaveFileNameUTF8(lpofn,TRUE);
404 BOOL SHGetSpecialFolderPathUTF8(HWND hwndOwner, LPTSTR lpszPath, int pszPathLen, int csidl, BOOL create)
406 if (lpszPath AND_IS_NOT_WIN9X)
408 WCHAR tmp[4096];
409 if (SHGetSpecialFolderPathW(hwndOwner,tmp,csidl,create))
411 return WideCharToMultiByte(CP_UTF8,0,tmp,-1,lpszPath,pszPathLen,NULL,NULL) > 0;
414 return SHGetSpecialFolderPathA(hwndOwner,lpszPath,csidl,create);
418 #if _MSC_VER > 1700 && defined(_WIN64)
419 BOOL SHGetPathFromIDListUTF8(const struct _ITEMIDLIST __unaligned *pidl, LPSTR pszPath, int pszPathLen)
420 #else
421 BOOL SHGetPathFromIDListUTF8(const struct _ITEMIDLIST *pidl, LPSTR pszPath, int pszPathLen)
422 #endif
424 if (pszPath AND_IS_NOT_WIN9X)
426 const int alloc_sz = pszPathLen < 4096 ? 4096 : pszPathLen;
427 WIDETOMB_ALLOC(wfn,alloc_sz);
428 if (wfn)
430 BOOL b = FALSE;
431 if (SHGetPathFromIDListW(pidl,wfn))
433 b = WideCharToMultiByte(CP_UTF8,0,wfn,-1,pszPath,pszPathLen,NULL,NULL) > 0;
435 WIDETOMB_FREE(wfn);
436 return b;
439 return SHGetPathFromIDListA(pidl,pszPath);
442 struct _ITEMIDLIST *SHBrowseForFolderUTF8(struct _browseinfoA *bi)
444 if (bi && (WDL_HasUTF8(bi->pszDisplayName) || WDL_HasUTF8(bi->lpszTitle)) AND_IS_NOT_WIN9X)
446 MBTOWIDE(wfn,bi->pszDisplayName);
447 if (wfn_ok)
449 MBTOWIDE(wtxt,bi->lpszTitle);
450 if (wtxt_ok)
452 BROWSEINFOW biw ={ bi->hwndOwner,bi->pidlRoot,wfn,wtxt,bi->ulFlags,bi->lpfn,(LPARAM)bi->lParam,bi->iImage };
453 LPITEMIDLIST idlist = SHBrowseForFolderW(&biw);
454 MBTOWIDE_FREE(wfn);
455 MBTOWIDE_FREE(wtxt);
456 return (struct _ITEMIDLIST *) idlist;
458 MBTOWIDE_FREE(wtxt);
460 MBTOWIDE_FREE(wfn);
462 return (struct _ITEMIDLIST *)SHBrowseForFolderA(bi);
465 int WDL_UTF8_SendBFFM_SETSEL(HWND hwnd, const char *str)
467 if (IS_NOT_WIN9X_AND WDL_HasUTF8(str))
469 MBTOWIDE(wc, str);
470 if (wc_ok)
472 int r=(int)SendMessage(hwnd, BFFM_SETSELECTIONW, 1, (LPARAM)wc);
473 MBTOWIDE_FREE(wc);
474 return r;
476 MBTOWIDE_FREE(wc);
478 return (int) SendMessage(hwnd, BFFM_SETSELECTIONA, 1, (LPARAM)str);
481 #endif
483 BOOL SetCurrentDirectoryUTF8(LPCTSTR path)
485 if (WDL_HasUTF8(path) AND_IS_NOT_WIN9X)
487 MBTOWIDE(wbuf,path);
488 if (wbuf_ok)
490 BOOL rv=SetCurrentDirectoryW(wbuf);
491 MBTOWIDE_FREE(wbuf);
492 return rv;
494 MBTOWIDE_FREE(wbuf);
496 return SetCurrentDirectoryA(path);
499 BOOL RemoveDirectoryUTF8(LPCTSTR path)
501 if (WDL_HasUTF8(path) AND_IS_NOT_WIN9X)
503 MBTOWIDE(wbuf,path);
504 if (wbuf_ok)
506 BOOL rv=RemoveDirectoryW(wbuf);
507 MBTOWIDE_FREE(wbuf);
508 return rv;
510 MBTOWIDE_FREE(wbuf);
512 return RemoveDirectoryA(path);
515 HINSTANCE LoadLibraryUTF8(LPCTSTR path)
517 if (WDL_HasUTF8(path) AND_IS_NOT_WIN9X)
519 MBTOWIDE(wbuf,path);
520 if (wbuf_ok)
522 HINSTANCE rv=LoadLibraryW(wbuf);
523 if (rv)
525 MBTOWIDE_FREE(wbuf);
526 return rv;
529 MBTOWIDE_FREE(wbuf);
531 return LoadLibraryA(path);
534 BOOL CreateDirectoryUTF8(LPCTSTR path, LPSECURITY_ATTRIBUTES attr)
536 if (WDL_HasUTF8(path) AND_IS_NOT_WIN9X)
538 MBTOWIDE(wbuf,path);
539 if (wbuf_ok)
541 BOOL rv=CreateDirectoryW(wbuf,attr);
542 MBTOWIDE_FREE(wbuf);
543 return rv;
545 MBTOWIDE_FREE(wbuf);
547 return CreateDirectoryA(path,attr);
550 BOOL DeleteFileUTF8(LPCTSTR path)
552 if (WDL_HasUTF8(path) AND_IS_NOT_WIN9X)
554 MBTOWIDE(wbuf,path);
555 if (wbuf_ok)
557 BOOL rv=DeleteFileW(wbuf);
558 MBTOWIDE_FREE(wbuf);
559 return rv;
561 MBTOWIDE_FREE(wbuf);
563 return DeleteFileA(path);
566 BOOL MoveFileUTF8(LPCTSTR existfn, LPCTSTR newfn)
568 if ((WDL_HasUTF8(existfn)||WDL_HasUTF8(newfn)) AND_IS_NOT_WIN9X)
570 MBTOWIDE(wbuf,existfn);
571 if (wbuf_ok)
573 MBTOWIDE(wbuf2,newfn);
574 if (wbuf2_ok)
576 int rv=MoveFileW(wbuf,wbuf2);
577 MBTOWIDE_FREE(wbuf2);
578 MBTOWIDE_FREE(wbuf);
579 return rv;
581 MBTOWIDE_FREE(wbuf2);
583 MBTOWIDE_FREE(wbuf);
585 return MoveFileA(existfn,newfn);
588 BOOL CopyFileUTF8(LPCTSTR existfn, LPCTSTR newfn, BOOL fie)
590 if ((WDL_HasUTF8(existfn)||WDL_HasUTF8(newfn)) AND_IS_NOT_WIN9X)
592 MBTOWIDE(wbuf,existfn);
593 if (wbuf_ok)
595 MBTOWIDE(wbuf2,newfn);
596 if (wbuf2_ok)
598 int rv=CopyFileW(wbuf,wbuf2,fie);
599 MBTOWIDE_FREE(wbuf2);
600 MBTOWIDE_FREE(wbuf);
601 return rv;
603 MBTOWIDE_FREE(wbuf2);
605 MBTOWIDE_FREE(wbuf);
607 return CopyFileA(existfn,newfn,fie);
611 DWORD GetModuleFileNameUTF8(HMODULE hModule, LPTSTR lpBuffer, DWORD nBufferLength)
613 if (lpBuffer && nBufferLength > 1 AND_IS_NOT_WIN9X)
616 WCHAR wbuf[WDL_UTF8_MAXFNLEN];
617 wbuf[0]=0;
618 if (GetModuleFileNameW(hModule,wbuf,WDL_UTF8_MAXFNLEN) && wbuf[0])
620 int rv=WideCharToMultiByte(CP_UTF8,0,wbuf,-1,lpBuffer,nBufferLength,NULL,NULL);
621 if (rv) return rv;
624 return GetModuleFileNameA(hModule,lpBuffer,nBufferLength);
628 DWORD GetCurrentDirectoryUTF8(DWORD nBufferLength, LPTSTR lpBuffer)
630 if (lpBuffer && nBufferLength > 1 AND_IS_NOT_WIN9X)
633 WCHAR wbuf[WDL_UTF8_MAXFNLEN];
634 wbuf[0]=0;
635 if (GetCurrentDirectoryW(WDL_UTF8_MAXFNLEN,wbuf) && wbuf[0])
637 int rv=WideCharToMultiByte(CP_UTF8,0,wbuf,-1,lpBuffer,nBufferLength,NULL,NULL);
638 if (rv) return rv;
641 return GetCurrentDirectoryA(nBufferLength,lpBuffer);
644 HANDLE CreateFileUTF8(LPCTSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)
646 if (WDL_HasUTF8(lpFileName) AND_IS_NOT_WIN9X)
648 HANDLE h = INVALID_HANDLE_VALUE;
650 MBTOWIDE(wstr, lpFileName);
651 if (wstr_ok) h = CreateFileW(wstr,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile);
652 MBTOWIDE_FREE(wstr);
654 if (h != INVALID_HANDLE_VALUE) return h;
656 return CreateFileA(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile);
660 int DrawTextUTF8(HDC hdc, LPCTSTR str, int nc, LPRECT lpRect, UINT format)
662 if (WDL_HasUTF8(str) AND_IS_NOT_WIN9X)
664 if (nc<0) nc=(int)strlen(str);
667 MBTOWIDE(wstr, str);
668 if (wstr_ok)
670 int rv=DrawTextW(hdc,wstr,-1,lpRect,format);;
671 MBTOWIDE_FREE(wstr);
672 return rv;
674 MBTOWIDE_FREE(wstr);
678 return DrawTextA(hdc,str,nc,lpRect,format);
682 BOOL InsertMenuUTF8(HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, LPCTSTR str)
684 if (!(uFlags&(MF_BITMAP|MF_SEPARATOR)) && str && WDL_HasUTF8(str) AND_IS_NOT_WIN9X)
686 MBTOWIDE(wbuf,str);
687 if (wbuf_ok)
689 BOOL rv=InsertMenuW(hMenu,uPosition,uFlags,uIDNewItem,wbuf);
690 MBTOWIDE_FREE(wbuf);
691 return rv;
694 return InsertMenuA(hMenu,uPosition,uFlags,uIDNewItem,str);
697 BOOL InsertMenuItemUTF8( HMENU hMenu,UINT uItem, BOOL fByPosition, LPMENUITEMINFO lpmii)
699 if (!lpmii) return FALSE;
700 if ((lpmii->fMask & MIIM_TYPE) && (lpmii->fType&(MFT_SEPARATOR|MFT_STRING|MFT_BITMAP)) == MFT_STRING && lpmii->dwTypeData && WDL_HasUTF8(lpmii->dwTypeData) AND_IS_NOT_WIN9X)
702 BOOL rv;
703 MENUITEMINFOW tmp = *(MENUITEMINFOW*)lpmii;
704 MBTOWIDE(wbuf,lpmii->dwTypeData);
705 if (wbuf_ok)
708 tmp.cbSize=sizeof(tmp);
709 tmp.dwTypeData = wbuf;
710 rv=InsertMenuItemW(hMenu,uItem,fByPosition,&tmp);
712 MBTOWIDE_FREE(wbuf);
713 return rv;
715 MBTOWIDE_FREE(wbuf);
717 return InsertMenuItemA(hMenu,uItem,fByPosition,lpmii);
719 BOOL SetMenuItemInfoUTF8( HMENU hMenu,UINT uItem, BOOL fByPosition, LPMENUITEMINFO lpmii)
721 if (!lpmii) return FALSE;
722 if ((lpmii->fMask & MIIM_TYPE) && (lpmii->fType&(MFT_SEPARATOR|MFT_STRING|MFT_BITMAP)) == MFT_STRING && lpmii->dwTypeData && WDL_HasUTF8(lpmii->dwTypeData) AND_IS_NOT_WIN9X)
724 BOOL rv;
725 MENUITEMINFOW tmp = *(MENUITEMINFOW*)lpmii;
726 MBTOWIDE(wbuf,lpmii->dwTypeData);
727 if (wbuf_ok)
729 tmp.cbSize=sizeof(tmp);
730 tmp.dwTypeData = wbuf;
731 rv=SetMenuItemInfoW(hMenu,uItem,fByPosition,&tmp);
733 MBTOWIDE_FREE(wbuf);
734 return rv;
736 MBTOWIDE_FREE(wbuf);
738 return SetMenuItemInfoA(hMenu,uItem,fByPosition,lpmii);
741 BOOL GetMenuItemInfoUTF8( HMENU hMenu,UINT uItem, BOOL fByPosition, LPMENUITEMINFO lpmii)
743 if (!lpmii) return FALSE;
744 if ((lpmii->fMask & MIIM_TYPE) && lpmii->dwTypeData && lpmii->cch AND_IS_NOT_WIN9X)
746 MENUITEMINFOW tmp = *(MENUITEMINFOW*)lpmii;
747 WIDETOMB_ALLOC(wbuf,lpmii->cch);
749 if (wbuf)
751 BOOL rv;
752 char *otd=lpmii->dwTypeData;
753 int osz=lpmii->cbSize;
754 tmp.cbSize=sizeof(tmp);
755 tmp.dwTypeData = wbuf;
756 tmp.cch = (UINT)(wbuf_size/sizeof(WCHAR));
757 rv=GetMenuItemInfoW(hMenu,uItem,fByPosition,&tmp);
759 if (rv && (tmp.fType&(MFT_SEPARATOR|MFT_STRING|MFT_BITMAP)) == MFT_STRING)
761 if (!WideCharToMultiByte(CP_UTF8,0,wbuf,-1,lpmii->dwTypeData,lpmii->cch,NULL,NULL))
763 lpmii->dwTypeData[lpmii->cch-1]=0;
766 *lpmii = *(MENUITEMINFO*)&tmp; // copy results
767 lpmii->cbSize=osz; // restore old stuff
768 lpmii->dwTypeData = otd;
770 else rv=0;
772 WIDETOMB_FREE(wbuf);
773 if (rv)return rv;
776 return GetMenuItemInfoA(hMenu,uItem,fByPosition,lpmii);
780 FILE *fopenUTF8(const char *filename, const char *mode)
782 if (WDL_HasUTF8(filename) AND_IS_NOT_WIN9X)
784 MBTOWIDE(wbuf,filename);
785 if (wbuf_ok)
787 FILE *rv;
788 WCHAR tb[32];
789 tb[0]=0;
790 MultiByteToWideChar(CP_UTF8,0,mode,-1,tb,32);
791 rv=tb[0] ? _wfopen(wbuf,tb) : NULL;
792 MBTOWIDE_FREE(wbuf);
793 if (rv) return rv;
796 return fopen(filename,mode);
799 int statUTF8(const char *filename, struct stat *buffer)
801 if (WDL_HasUTF8(filename) AND_IS_NOT_WIN9X)
803 MBTOWIDE(wbuf,filename);
804 if (wbuf_ok)
806 int rv=_wstat(wbuf,(struct _stat*)buffer);
807 MBTOWIDE_FREE(wbuf);
808 if (!rv) return rv;
810 else
812 MBTOWIDE_FREE(wbuf);
815 return stat(filename,buffer);
818 LPSTR GetCommandParametersUTF8()
820 char *buf;
821 int szneeded;
822 LPWSTR w=GetCommandLineW();
823 if (!w) return NULL;
824 szneeded = WideCharToMultiByte(CP_UTF8,0,w,-1,NULL,0,NULL,NULL);
825 if (szneeded<1) return NULL;
826 buf = (char *)malloc(szneeded+10);
827 if (!buf) return NULL;
828 if (WideCharToMultiByte(CP_UTF8,0,w,-1,buf,szneeded+9,NULL,NULL)<1) return NULL;
829 while (*buf == ' ') buf++;
830 if (*buf == '\"')
832 buf++;
833 while (*buf && *buf != '\"') buf++;
835 else
837 while (*buf && *buf != ' ') buf++;
839 if (*buf) buf++;
840 while (*buf == ' ') buf++;
841 if (*buf) return buf;
843 return NULL;
846 int GetKeyNameTextUTF8(LONG lParam, LPTSTR lpString, int nMaxCount)
848 if (!lpString) return 0;
849 if (nMaxCount>0 AND_IS_NOT_WIN9X)
851 WIDETOMB_ALLOC(wbuf, nMaxCount);
852 if (wbuf)
854 const int v = GetKeyNameTextW(lParam,wbuf,(int) (wbuf_size/sizeof(WCHAR)));
856 if (v)
858 lpString[0]=0;
859 if (!WideCharToMultiByte(CP_UTF8,0,wbuf,-1,lpString,nMaxCount,NULL,NULL))
860 lpString[nMaxCount-1]=0;
862 WIDETOMB_FREE(wbuf);
864 return v ? (int)strlen(lpString) : 0;
867 return GetKeyNameTextA(lParam,lpString,nMaxCount);
870 HINSTANCE ShellExecuteUTF8(HWND hwnd, LPCTSTR lpOp, LPCTSTR lpFile, LPCTSTR lpParm, LPCTSTR lpDir, INT nShowCmd)
872 if (IS_NOT_WIN9X_AND (WDL_HasUTF8(lpOp)||WDL_HasUTF8(lpFile)||WDL_HasUTF8(lpParm)||WDL_HasUTF8(lpDir)))
874 DWORD sz;
875 WCHAR *p1=lpOp ? WDL_UTF8ToWC(lpOp,0,0,&sz) : NULL;
876 WCHAR *p2=lpFile ? WDL_UTF8ToWC(lpFile,0,0,&sz) : NULL;
877 WCHAR *p3=lpParm ? WDL_UTF8ToWC(lpParm,0,0,&sz) : NULL;
878 WCHAR *p4=lpDir ? WDL_UTF8ToWC(lpDir,0,0,&sz) : NULL;
879 HINSTANCE rv= p2 ? ShellExecuteW(hwnd,p1,p2,p3,p4,nShowCmd) : NULL;
880 free(p1);
881 free(p2);
882 free(p3);
883 free(p4);
884 return rv;
886 return ShellExecuteA(hwnd,lpOp,lpFile,lpParm,lpDir,nShowCmd);
889 BOOL GetUserNameUTF8(LPTSTR lpString, LPDWORD nMaxCount)
891 if (IS_NOT_WIN9X_AND lpString && nMaxCount)
893 WIDETOMB_ALLOC(wtmp,*nMaxCount);
894 if (wtmp)
896 DWORD sz=(DWORD)(wtmp_size/sizeof(WCHAR));
897 BOOL r = GetUserNameW(wtmp, &sz);
898 if (r && (!*nMaxCount || (!WideCharToMultiByte(CP_UTF8,0,wtmp,-1,lpString,*nMaxCount,NULL,NULL) && GetLastError()==ERROR_INSUFFICIENT_BUFFER)))
900 if (*nMaxCount>0) lpString[*nMaxCount-1]=0;
901 *nMaxCount=(int)wcslen(wtmp)+1;
902 r=FALSE;
904 else
906 *nMaxCount=sz;
908 WIDETOMB_FREE(wtmp);
909 return r;
912 return GetUserNameA(lpString, nMaxCount);
915 BOOL GetComputerNameUTF8(LPTSTR lpString, LPDWORD nMaxCount)
917 if (IS_NOT_WIN9X_AND lpString && nMaxCount)
919 WIDETOMB_ALLOC(wtmp,*nMaxCount);
920 if (wtmp)
922 DWORD sz=(DWORD)(wtmp_size/sizeof(WCHAR));
923 BOOL r = GetComputerNameW(wtmp, &sz);
924 if (r && (!*nMaxCount || (!WideCharToMultiByte(CP_UTF8,0,wtmp,-1,lpString,*nMaxCount,NULL,NULL) && GetLastError()==ERROR_INSUFFICIENT_BUFFER)))
926 if (*nMaxCount>0) lpString[*nMaxCount-1]=0;
927 *nMaxCount=(int)wcslen(wtmp)+1;
928 r=FALSE;
930 else
932 *nMaxCount=sz;
934 WIDETOMB_FREE(wtmp);
935 return r;
938 return GetComputerNameA(lpString, nMaxCount);
941 #define MBTOWIDE_NULLOK(symbase, src) \
942 int symbase##_size; \
943 WCHAR symbase##_buf[256]; \
944 WCHAR *symbase = (src)==NULL ? NULL : ((symbase##_size=MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,src,-1,NULL,0)) >= 248 ? (WCHAR *)malloc(symbase##_size * sizeof(WCHAR) + 10) : symbase##_buf); \
945 int symbase##_ok = symbase ? (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,src,-1,symbase,symbase##_size < 1 ? 256 : symbase##_size)) : (src)==NULL
948 // these only bother using Wide versions if the filename has wide chars
949 // (for now)
950 #define PROFILESTR_COMMON \
951 if (IS_NOT_WIN9X_AND fnStr && WDL_HasUTF8(fnStr)) \
953 MBTOWIDE(wfn,fnStr); \
954 MBTOWIDE_NULLOK(wapp,appStr); \
955 MBTOWIDE_NULLOK(wkey,keyStr); \
956 if (wfn_ok && wapp_ok && wkey_ok) {
958 #define PROFILESTR_COMMON_END \
959 MBTOWIDE_FREE(wfn); \
960 MBTOWIDE_FREE(wapp); \
961 MBTOWIDE_FREE(wkey); \
962 return rv; \
965 UINT GetPrivateProfileIntUTF8(LPCTSTR appStr, LPCTSTR keyStr, INT def, LPCTSTR fnStr)
967 PROFILESTR_COMMON
969 const UINT rv = GetPrivateProfileIntW(wapp,wkey,def,wfn);
971 PROFILESTR_COMMON_END
972 return GetPrivateProfileIntA(appStr,keyStr,def,fnStr);
975 DWORD GetPrivateProfileStringUTF8(LPCTSTR appStr, LPCTSTR keyStr, LPCTSTR defStr, LPTSTR retStr, DWORD nSize, LPCTSTR fnStr)
977 PROFILESTR_COMMON
978 MBTOWIDE_NULLOK(wdef, defStr);
980 WIDETOMB_ALLOC(buf, nSize);
982 DWORD rv = GetPrivateProfileStringW(wapp,wkey,wdef,buf,(DWORD) (buf_size / sizeof(WCHAR)),wfn);
984 const DWORD nullsz = (!wapp || !wkey) ? 2 : 1;
985 if (nSize<=nullsz)
987 memset(retStr,0,nSize);
988 rv=0;
990 else
992 // rv does not include null character(s)
993 if (rv>0) rv = WideCharToMultiByte(CP_UTF8,0,buf,rv,retStr,nSize-nullsz,NULL,NULL);
994 if (rv > nSize-nullsz) rv=nSize-nullsz;
995 memset(retStr + rv,0,nullsz);
998 WIDETOMB_FREE(buf);
999 PROFILESTR_COMMON_END
1000 return GetPrivateProfileStringA(appStr,keyStr,defStr,retStr,nSize,fnStr);
1003 BOOL WritePrivateProfileStringUTF8(LPCTSTR appStr, LPCTSTR keyStr, LPCTSTR str, LPCTSTR fnStr)
1005 PROFILESTR_COMMON
1006 MBTOWIDE_NULLOK(wval, str);
1008 const BOOL rv = WritePrivateProfileStringW(wapp,wkey,wval,wfn);
1010 MBTOWIDE_FREE(wval);
1012 PROFILESTR_COMMON_END
1013 return WritePrivateProfileStringA(appStr,keyStr,str,fnStr);
1016 BOOL GetPrivateProfileStructUTF8(LPCTSTR appStr, LPCTSTR keyStr, LPVOID pStruct, UINT uSize, LPCTSTR fnStr)
1018 PROFILESTR_COMMON
1020 const BOOL rv = GetPrivateProfileStructW(wapp,wkey,pStruct,uSize,wfn);
1022 PROFILESTR_COMMON_END
1023 return GetPrivateProfileStructA(appStr,keyStr,pStruct,uSize,fnStr);
1026 BOOL WritePrivateProfileStructUTF8(LPCTSTR appStr, LPCTSTR keyStr, LPVOID pStruct, UINT uSize, LPCTSTR fnStr)
1028 PROFILESTR_COMMON
1030 const BOOL rv = WritePrivateProfileStructW(wapp,wkey,pStruct,uSize,wfn);
1032 PROFILESTR_COMMON_END
1033 return WritePrivateProfileStructA(appStr,keyStr,pStruct,uSize,fnStr);
1037 #undef PROFILESTR_COMMON
1038 #undef PROFILESTR_COMMON_END
1041 BOOL CreateProcessUTF8(LPCTSTR lpApplicationName,
1042 LPTSTR lpCommandLine,
1043 LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes,
1044 BOOL bInheritHandles,
1045 DWORD dwCreationFlags, LPVOID lpEnvironment, // pointer to new environment block
1046 LPCTSTR lpCurrentDirectory,
1047 LPSTARTUPINFO lpStartupInfo,
1048 LPPROCESS_INFORMATION lpProcessInformation )
1050 // special case ver
1051 if (IS_NOT_WIN9X_AND (
1052 WDL_HasUTF8(lpApplicationName) ||
1053 WDL_HasUTF8(lpCommandLine) ||
1054 WDL_HasUTF8(lpCurrentDirectory)
1058 MBTOWIDE_NULLOK(appn, lpApplicationName);
1059 MBTOWIDE_NULLOK(cmdl, lpCommandLine);
1060 MBTOWIDE_NULLOK(curd, lpCurrentDirectory);
1062 if (appn_ok && cmdl_ok && curd_ok)
1064 BOOL rv;
1065 WCHAR *free1=NULL, *free2=NULL;
1066 char *save1=NULL, *save2=NULL;
1068 if (lpStartupInfo && lpStartupInfo->cb >= sizeof(STARTUPINFO))
1070 if (lpStartupInfo->lpDesktop)
1071 lpStartupInfo->lpDesktop = (char *) (free1 = WDL_UTF8ToWC(save1 = lpStartupInfo->lpDesktop,FALSE,0,NULL));
1072 if (lpStartupInfo->lpTitle)
1073 lpStartupInfo->lpTitle = (char*) (free2 = WDL_UTF8ToWC(save2 = lpStartupInfo->lpTitle,FALSE,0,NULL));
1076 rv=CreateProcessW(appn,cmdl,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,
1077 lpEnvironment,curd,(STARTUPINFOW*)lpStartupInfo,lpProcessInformation);
1079 if (lpStartupInfo && lpStartupInfo->cb >= sizeof(STARTUPINFO))
1081 lpStartupInfo->lpDesktop = save1;
1082 lpStartupInfo->lpTitle = save2;
1083 free(free1);
1084 free(free2);
1087 MBTOWIDE_FREE(appn);
1088 MBTOWIDE_FREE(cmdl);
1089 MBTOWIDE_FREE(curd);
1090 return rv;
1092 MBTOWIDE_FREE(appn);
1093 MBTOWIDE_FREE(cmdl);
1094 MBTOWIDE_FREE(curd);
1097 return CreateProcessA(lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation);
1101 #if (defined(WDL_WIN32_UTF8_IMPL_NOTSTATIC) || defined(WDL_WIN32_UTF8_IMPL_STATICHOOKS)) && !defined(WDL_WIN32_UTF8_NO_UI_IMPL)
1103 static LRESULT WINAPI cb_newProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1105 WNDPROC oldproc = (WNDPROC)GetProp(hwnd,WDL_UTF8_OLDPROCPROP);
1106 if (!oldproc) return 0;
1108 if (msg==WM_NCDESTROY)
1110 SetWindowLongPtr(hwnd, GWLP_WNDPROC,(INT_PTR)oldproc);
1111 RemoveProp(hwnd,WDL_UTF8_OLDPROCPROP);
1112 RemoveProp(hwnd,WDL_UTF8_OLDPROCPROP "W");
1114 else if (msg == CB_ADDSTRING || msg == CB_INSERTSTRING || msg == LB_ADDSTRING || msg == LB_INSERTSTRING)
1116 char *str=(char*)lParam;
1117 if (lParam && WDL_HasUTF8(str))
1119 MBTOWIDE(wbuf,str);
1120 if (wbuf_ok)
1122 WNDPROC oldprocW = (WNDPROC)GetProp(hwnd,WDL_UTF8_OLDPROCPROP "W");
1123 LRESULT rv=CallWindowProcW(oldprocW ? oldprocW : oldproc,hwnd,msg,wParam,(LPARAM)wbuf);
1124 MBTOWIDE_FREE(wbuf);
1125 return rv;
1128 MBTOWIDE_FREE(wbuf);
1131 else if ((msg == CB_GETLBTEXT || msg == LB_GETTEXT) && lParam)
1133 WNDPROC oldprocW = (WNDPROC)GetProp(hwnd,WDL_UTF8_OLDPROCPROP "W");
1134 LRESULT l = CallWindowProcW(oldprocW ? oldprocW : oldproc,hwnd,msg == CB_GETLBTEXT ? CB_GETLBTEXTLEN : LB_GETTEXTLEN,wParam,0);
1136 if (l != CB_ERR)
1138 WIDETOMB_ALLOC(tmp,l+1);
1139 if (tmp)
1141 LRESULT rv=CallWindowProcW(oldprocW ? oldprocW : oldproc,hwnd,msg,wParam,(LPARAM)tmp);
1142 if (rv>=0)
1144 *(char *)lParam=0;
1145 rv=WideCharToMultiByte(CP_UTF8,0,tmp,-1,(char *)lParam,((int)l)*4 + 32,NULL,NULL);
1146 if (rv>0) rv--;
1148 WIDETOMB_FREE(tmp);
1150 return rv;
1154 else if (msg == CB_GETLBTEXTLEN || msg == LB_GETTEXTLEN)
1156 WNDPROC oldprocW = (WNDPROC)GetProp(hwnd,WDL_UTF8_OLDPROCPROP "W");
1157 return CallWindowProcW(oldprocW ? oldprocW : oldproc,hwnd,msg,wParam,lParam) * 4 + 32; // make sure caller allocates a lot extra
1160 return CallWindowProc(oldproc,hwnd,msg,wParam,lParam);
1163 void WDL_UTF8_HookComboBox(HWND h)
1165 if (!h||
1166 #ifdef WDL_SUPPORT_WIN9X
1167 GetVersion()>=0x80000000||
1168 #endif
1169 GetProp(h,WDL_UTF8_OLDPROCPROP)) return;
1170 SetProp(h,WDL_UTF8_OLDPROCPROP "W",(HANDLE)GetWindowLongPtrW(h,GWLP_WNDPROC));
1171 SetProp(h,WDL_UTF8_OLDPROCPROP,(HANDLE)SetWindowLongPtr(h,GWLP_WNDPROC,(INT_PTR)cb_newProc));
1173 if (!s_combobox_atom) s_combobox_atom = (ATOM)GetClassWord(h,GCW_ATOM);
1176 void WDL_UTF8_HookListBox(HWND h)
1178 WDL_UTF8_HookComboBox(h);
1181 static LRESULT WINAPI tc_newProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1183 WNDPROC oldproc = (WNDPROC)GetProp(hwnd,WDL_UTF8_OLDPROCPROP);
1184 if (!oldproc) return 0;
1186 if (msg==WM_NCDESTROY)
1188 SetWindowLongPtr(hwnd, GWLP_WNDPROC,(INT_PTR)oldproc);
1189 RemoveProp(hwnd,WDL_UTF8_OLDPROCPROP);
1191 else if (msg == TCM_INSERTITEMA)
1193 LPTCITEM pItem = (LPTCITEM) lParam;
1194 char *str;
1195 if (pItem && (str=pItem->pszText) && (pItem->mask&TCIF_TEXT) && WDL_HasUTF8(str))
1197 MBTOWIDE(wbuf,str);
1198 if (wbuf_ok)
1200 LRESULT rv;
1201 pItem->pszText=(char*)wbuf; // set new buffer
1202 rv=CallWindowProc(oldproc,hwnd,TCM_INSERTITEMW,wParam,lParam);
1203 pItem->pszText = str; // restore old pointer
1204 MBTOWIDE_FREE(wbuf);
1205 return rv;
1208 MBTOWIDE_FREE(wbuf);
1213 return CallWindowProc(oldproc,hwnd,msg,wParam,lParam);
1217 static LRESULT WINAPI tv_newProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1219 WNDPROC oldproc = (WNDPROC)GetProp(hwnd,WDL_UTF8_OLDPROCPROP);
1220 if (!oldproc) return 0;
1222 if (msg==WM_NCDESTROY)
1224 SetWindowLongPtr(hwnd, GWLP_WNDPROC,(INT_PTR)oldproc);
1225 RemoveProp(hwnd,WDL_UTF8_OLDPROCPROP);
1227 else if (msg == TVM_INSERTITEMA || msg == TVM_SETITEMA)
1229 LPTVITEM pItem = msg == TVM_INSERTITEMA ? &((LPTVINSERTSTRUCT)lParam)->item : (LPTVITEM) lParam;
1230 char *str;
1231 if (pItem && (str=pItem->pszText) && (pItem->mask&TVIF_TEXT) && WDL_HasUTF8(str))
1233 MBTOWIDE(wbuf,str);
1234 if (wbuf_ok)
1236 LRESULT rv;
1237 pItem->pszText=(char*)wbuf; // set new buffer
1238 rv=CallWindowProc(oldproc,hwnd,msg == TVM_INSERTITEMA ? TVM_INSERTITEMW : TVM_SETITEMW,wParam,lParam);
1239 pItem->pszText = str; // restore old pointer
1240 MBTOWIDE_FREE(wbuf);
1241 return rv;
1244 MBTOWIDE_FREE(wbuf);
1247 else if (msg==TVM_GETITEMA)
1249 LPTVITEM pItem = (LPTVITEM) lParam;
1250 char *obuf;
1251 if (pItem && (pItem->mask & TVIF_TEXT) && (obuf=pItem->pszText) && pItem->cchTextMax > 3)
1253 WIDETOMB_ALLOC(wbuf,pItem->cchTextMax);
1254 if (wbuf)
1256 LRESULT rv;
1257 int oldsz=pItem->cchTextMax;
1258 *wbuf=0;
1259 *obuf=0;
1260 pItem->cchTextMax=(int) (wbuf_size/sizeof(WCHAR));
1261 pItem->pszText = (char *)wbuf;
1262 rv=CallWindowProc(oldproc,hwnd,TVM_GETITEMW,wParam,lParam);
1264 if (!WideCharToMultiByte(CP_UTF8,0,wbuf,-1,obuf,oldsz,NULL,NULL))
1265 obuf[oldsz-1]=0;
1267 pItem->cchTextMax=oldsz;
1268 pItem->pszText=obuf;
1269 WIDETOMB_FREE(wbuf);
1271 if (obuf[0]) return rv;
1276 return CallWindowProc(oldproc,hwnd,msg,wParam,lParam);
1279 static LRESULT WINAPI lv_newProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1281 WNDPROC oldproc = (WNDPROC)GetProp(hwnd,WDL_UTF8_OLDPROCPROP);
1282 if (!oldproc) return 0;
1284 if (msg==WM_NCDESTROY)
1286 SetWindowLongPtr(hwnd, GWLP_WNDPROC,(INT_PTR)oldproc);
1287 RemoveProp(hwnd,WDL_UTF8_OLDPROCPROP);
1289 else if (msg == LVM_INSERTCOLUMNA || msg==LVM_SETCOLUMNA)
1291 LPLVCOLUMNA pCol = (LPLVCOLUMNA) lParam;
1292 char *str;
1293 if (pCol && (str=pCol->pszText) && (pCol->mask & LVCF_TEXT) && WDL_HasUTF8(str))
1295 MBTOWIDE(wbuf,str);
1296 if (wbuf_ok)
1298 LRESULT rv;
1299 pCol->pszText=(char*)wbuf; // set new buffer
1300 rv=CallWindowProc(oldproc,hwnd,msg==LVM_INSERTCOLUMNA?LVM_INSERTCOLUMNW:LVM_SETCOLUMNW,wParam,lParam);
1301 pCol->pszText = str; // restore old pointer
1302 MBTOWIDE_FREE(wbuf);
1303 return rv;
1308 else if (msg == LVM_INSERTITEMA || msg == LVM_SETITEMA || msg == LVM_SETITEMTEXTA)
1310 LPLVITEMA pItem = (LPLVITEMA) lParam;
1311 char *str;
1312 if (pItem && (str=pItem->pszText) && (msg==LVM_SETITEMTEXTA || (pItem->mask&LVIF_TEXT)) && WDL_HasUTF8(str))
1314 MBTOWIDE(wbuf,str);
1315 if (wbuf_ok)
1317 LRESULT rv;
1318 pItem->pszText=(char*)wbuf; // set new buffer
1319 rv=CallWindowProc(oldproc,hwnd,msg == LVM_INSERTITEMA ? LVM_INSERTITEMW : msg == LVM_SETITEMA ? LVM_SETITEMW : LVM_SETITEMTEXTW,wParam,lParam);
1320 pItem->pszText = str; // restore old pointer
1321 MBTOWIDE_FREE(wbuf);
1322 return rv;
1325 MBTOWIDE_FREE(wbuf);
1328 else if (msg==LVM_GETITEMA||msg==LVM_GETITEMTEXTA)
1330 LPLVITEMA pItem = (LPLVITEMA) lParam;
1331 char *obuf;
1332 if (pItem && (msg == LVM_GETITEMTEXTA || (pItem->mask & LVIF_TEXT)) && (obuf=pItem->pszText) && pItem->cchTextMax > 3)
1334 WIDETOMB_ALLOC(wbuf,pItem->cchTextMax);
1335 if (wbuf)
1337 LRESULT rv;
1338 int oldsz=pItem->cchTextMax;
1339 *wbuf=0;
1340 *obuf=0;
1341 pItem->cchTextMax=(int) (wbuf_size/sizeof(WCHAR));
1342 pItem->pszText = (char *)wbuf;
1343 rv=CallWindowProc(oldproc,hwnd,msg==LVM_GETITEMTEXTA ? LVM_GETITEMTEXTW : LVM_GETITEMW,wParam,lParam);
1345 if (!WideCharToMultiByte(CP_UTF8,0,wbuf,-1,obuf,oldsz,NULL,NULL))
1346 obuf[oldsz-1]=0;
1348 pItem->cchTextMax=oldsz;
1349 pItem->pszText=obuf;
1350 WIDETOMB_FREE(wbuf);
1352 if (obuf[0]) return rv;
1357 return CallWindowProc(oldproc,hwnd,msg,wParam,lParam);
1360 void WDL_UTF8_HookListView(HWND h)
1362 if (!h||
1363 #ifdef WDL_SUPPORT_WIN9X
1364 GetVersion()>=0x80000000||
1365 #endif
1366 GetProp(h,WDL_UTF8_OLDPROCPROP)) return;
1367 SetProp(h,WDL_UTF8_OLDPROCPROP,(HANDLE)SetWindowLongPtr(h,GWLP_WNDPROC,(INT_PTR)lv_newProc));
1370 void WDL_UTF8_HookTreeView(HWND h)
1372 if (!h||
1373 #ifdef WDL_SUPPORT_WIN9X
1374 GetVersion()>=0x80000000||
1375 #endif
1376 GetProp(h,WDL_UTF8_OLDPROCPROP)) return;
1378 SetProp(h,WDL_UTF8_OLDPROCPROP,(HANDLE)SetWindowLongPtr(h,GWLP_WNDPROC,(INT_PTR)tv_newProc));
1381 void WDL_UTF8_HookTabCtrl(HWND h)
1383 if (!h||
1384 #ifdef WDL_SUPPORT_WIN9X
1385 GetVersion()>=0x80000000||
1386 #endif
1387 GetProp(h,WDL_UTF8_OLDPROCPROP)) return;
1389 SetProp(h,WDL_UTF8_OLDPROCPROP,(HANDLE)SetWindowLongPtr(h,GWLP_WNDPROC,(INT_PTR)tc_newProc));
1392 void WDL_UTF8_ListViewConvertDispInfoToW(void *_di)
1394 NMLVDISPINFO *di = (NMLVDISPINFO *)_di;
1395 if (di && (di->item.mask & LVIF_TEXT) && di->item.pszText && di->item.cchTextMax>0)
1397 char tmp_buf[1024], *tmp=tmp_buf;
1398 char *src = di->item.pszText;
1400 if (strlen(src) < 1024) strcpy(tmp,src);
1401 else tmp = strdup(src);
1403 if (!MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,tmp,-1,(LPWSTR)di->item.pszText,di->item.cchTextMax))
1405 if (GetLastError()==ERROR_INSUFFICIENT_BUFFER)
1407 ((WCHAR *)di->item.pszText)[di->item.cchTextMax-1] = 0;
1409 else
1411 if (!MultiByteToWideChar(CP_ACP,MB_ERR_INVALID_CHARS,tmp,-1,(LPWSTR)di->item.pszText,di->item.cchTextMax))
1412 ((WCHAR *)di->item.pszText)[di->item.cchTextMax-1] = 0;
1416 if (tmp!=tmp_buf) free(tmp);
1421 #endif
1423 #ifdef __cplusplus
1425 #endif
1427 #endif
1429 #endif //_WIN32