🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
2.4 KiB

  1. #ifndef WIN_MAIN_UTF8_H
  2. #define WIN_MAIN_UTF8_H
  3. /* For Windows systems this provides a way to get UTF-8 encoded argv strings,
  4. * and also overrides fopen to accept UTF-8 filenames. Working with wmain
  5. * directly complicates cross-platform compatibility, while normal main() in
  6. * Windows uses the current codepage (which has limited availability of
  7. * characters).
  8. *
  9. * For MinGW, you must link with -municode
  10. */
  11. #ifdef _WIN32
  12. #define WIN32_LEAN_AND_MEAN
  13. #include <windows.h>
  14. #include <shellapi.h>
  15. static FILE *my_fopen(const char *fname, const char *mode)
  16. {
  17. WCHAR *wname=NULL, *wmode=NULL;
  18. int namelen, modelen;
  19. FILE *file = NULL;
  20. errno_t err;
  21. namelen = MultiByteToWideChar(CP_UTF8, 0, fname, -1, NULL, 0);
  22. modelen = MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
  23. if(namelen <= 0 || modelen <= 0)
  24. {
  25. fprintf(stderr, "Failed to convert UTF-8 fname \"%s\", mode \"%s\"\n", fname, mode);
  26. return NULL;
  27. }
  28. wname = (WCHAR*)calloc(sizeof(WCHAR), namelen+modelen);
  29. wmode = wname + namelen;
  30. MultiByteToWideChar(CP_UTF8, 0, fname, -1, wname, namelen);
  31. MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, modelen);
  32. err = _wfopen_s(&file, wname, wmode);
  33. if(err)
  34. {
  35. errno = err;
  36. file = NULL;
  37. }
  38. free(wname);
  39. return file;
  40. }
  41. #define fopen my_fopen
  42. static char **arglist;
  43. static void cleanup_arglist(void)
  44. {
  45. free(arglist);
  46. }
  47. static void GetUnicodeArgs(int *argc, char ***argv)
  48. {
  49. size_t total;
  50. wchar_t **args;
  51. int nargs, i;
  52. args = CommandLineToArgvW(GetCommandLineW(), &nargs);
  53. if(!args)
  54. {
  55. fprintf(stderr, "Failed to get command line args: %ld\n", GetLastError());
  56. exit(EXIT_FAILURE);
  57. }
  58. total = sizeof(**argv) * nargs;
  59. for(i = 0;i < nargs;i++)
  60. total += WideCharToMultiByte(CP_UTF8, 0, args[i], -1, NULL, 0, NULL, NULL);
  61. atexit(cleanup_arglist);
  62. arglist = *argv = (char**)calloc(1, total);
  63. (*argv)[0] = (char*)(*argv + nargs);
  64. for(i = 0;i < nargs-1;i++)
  65. {
  66. int len = WideCharToMultiByte(CP_UTF8, 0, args[i], -1, (*argv)[i], 65535, NULL, NULL);
  67. (*argv)[i+1] = (*argv)[i] + len;
  68. }
  69. WideCharToMultiByte(CP_UTF8, 0, args[i], -1, (*argv)[i], 65535, NULL, NULL);
  70. *argc = nargs;
  71. LocalFree(args);
  72. }
  73. #define GET_UNICODE_ARGS(argc, argv) GetUnicodeArgs(argc, argv)
  74. #else
  75. /* Do nothing. */
  76. #define GET_UNICODE_ARGS(argc, argv)
  77. #endif
  78. #endif /* WIN_MAIN_UTF8_H */