| | @@ -1,7 +1,7 @@ |
| 1 | 1 | /* |
| 2 | | -** Copyright (c) 2006 D. Richard Hipp |
| 2 | +** Copyright © 2006 D. Richard Hipp |
| 3 | 3 | ** |
| 4 | 4 | ** This program is free software; you can redistribute it and/or |
| 5 | 5 | ** modify it under the terms of the Simplified BSD License (also |
| 6 | 6 | ** known as the "2-Clause License" or "FreeBSD License".) |
| 7 | 7 | |
| | @@ -32,10 +32,11 @@ |
| 32 | 32 | |
| 33 | 33 | /* |
| 34 | 34 | ** On Windows, include the Platform SDK header file. |
| 35 | 35 | */ |
| 36 | 36 | #ifdef _WIN32 |
| 37 | +# include <direct.h> |
| 37 | 38 | # include <windows.h> |
| 38 | 39 | #endif |
| 39 | 40 | |
| 40 | 41 | /* |
| 41 | 42 | ** The file status information from the most recent stat() call. |
| | @@ -68,12 +69,12 @@ |
| 68 | 69 | }else{ |
| 69 | 70 | return stat(zFilename, buf); |
| 70 | 71 | } |
| 71 | 72 | #else |
| 72 | 73 | int rc = 0; |
| 73 | | - char *zMbcs = fossil_utf8_to_mbcs(zFilename); |
| 74 | | - rc = stat(zMbcs, buf); |
| 74 | + wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename); |
| 75 | + rc = _wstati64(zMbcs, buf); |
| 75 | 76 | fossil_mbcs_free(zMbcs); |
| 76 | 77 | return rc; |
| 77 | 78 | #endif |
| 78 | 79 | } |
| 79 | 80 | |
| | @@ -298,13 +299,17 @@ |
| 298 | 299 | |
| 299 | 300 | /* |
| 300 | 301 | ** Wrapper around the access() system call. |
| 301 | 302 | */ |
| 302 | 303 | int file_access(const char *zFilename, int flags){ |
| 303 | | - char *zMbcs = fossil_utf8_to_mbcs(zFilename); |
| 304 | | - int rc = access(zMbcs, flags); |
| 304 | +#ifdef _WIN32 |
| 305 | + wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename); |
| 306 | + int rc = _waccess(zMbcs, flags); |
| 305 | 307 | fossil_mbcs_free(zMbcs); |
| 308 | +#else |
| 309 | + int rc = access(zFilename, flags); |
| 310 | +#endif |
| 306 | 311 | return rc; |
| 307 | 312 | } |
| 308 | 313 | |
| 309 | 314 | /* |
| 310 | 315 | ** Find an unused filename similar to zBase with zSuffix appended. |
| | @@ -389,13 +394,17 @@ |
| 389 | 394 | |
| 390 | 395 | /* |
| 391 | 396 | ** Delete a file. |
| 392 | 397 | */ |
| 393 | 398 | void file_delete(const char *zFilename){ |
| 394 | | - char *z = fossil_utf8_to_mbcs(zFilename); |
| 395 | | - unlink(z); |
| 399 | +#ifdef _WIN32 |
| 400 | + wchar_t *z = fossil_utf8_to_unicode(zFilename); |
| 401 | + _wunlink(z); |
| 396 | 402 | fossil_mbcs_free(z); |
| 403 | +#else |
| 404 | + unlink(zFilename); |
| 405 | +#endif |
| 397 | 406 | } |
| 398 | 407 | |
| 399 | 408 | /* |
| 400 | 409 | ** Create the directory named in the argument, if it does not already |
| 401 | 410 | ** exist. If forceFlag is 1, delete any prior non-directory object |
| | @@ -410,12 +419,12 @@ |
| 410 | 419 | file_delete(zName); |
| 411 | 420 | } |
| 412 | 421 | if( rc!=1 ){ |
| 413 | 422 | #if defined(_WIN32) |
| 414 | 423 | int rc; |
| 415 | | - char *zMbcs = fossil_utf8_to_mbcs(zName); |
| 416 | | - rc = mkdir(zMbcs); |
| 424 | + wchar_t *zMbcs = fossil_utf8_to_unicode(zName); |
| 425 | + rc = _wmkdir(zMbcs); |
| 417 | 426 | fossil_mbcs_free(zMbcs); |
| 418 | 427 | return rc; |
| 419 | 428 | #else |
| 420 | 429 | return mkdir(zName, 0755); |
| 421 | 430 | #endif |
| | @@ -561,24 +570,24 @@ |
| 561 | 570 | } |
| 562 | 571 | |
| 563 | 572 | /* |
| 564 | 573 | ** Get the current working directory. |
| 565 | 574 | ** |
| 566 | | -** On windows, the name is converted from MBCS to UTF8 and all '\\' |
| 575 | +** On windows, the name is converted from unicode to UTF8 and all '\\' |
| 567 | 576 | ** characters are converted to '/'. No conversions are needed on |
| 568 | 577 | ** unix. |
| 569 | 578 | */ |
| 570 | 579 | void file_getcwd(char *zBuf, int nBuf){ |
| 571 | 580 | #ifdef _WIN32 |
| 572 | 581 | char *zPwdUtf8; |
| 573 | 582 | int nPwd; |
| 574 | 583 | int i; |
| 575 | | - char zPwd[2000]; |
| 576 | | - if( getcwd(zPwd, sizeof(zPwd)-1)==0 ){ |
| 584 | + wchar_t zPwd[2000]; |
| 585 | + if( _wgetcwd(zPwd, sizeof(zPwd)/sizeof(zPwd[0])-1)==0 ){ |
| 577 | 586 | fossil_fatal("cannot find the current working directory."); |
| 578 | 587 | } |
| 579 | | - zPwdUtf8 = fossil_mbcs_to_utf8(zPwd); |
| 588 | + zPwdUtf8 = fossil_unicode_to_utf8(zPwd); |
| 580 | 589 | nPwd = strlen(zPwdUtf8); |
| 581 | 590 | if( nPwd > nBuf-1 ){ |
| 582 | 591 | fossil_fatal("pwd too big: max %d\n", nBuf-1); |
| 583 | 592 | } |
| 584 | 593 | for(i=0; zPwdUtf8[i]; i++) if( zPwdUtf8[i]=='\\' ) zPwdUtf8[i] = '/'; |
| | @@ -928,14 +937,14 @@ |
| 928 | 937 | unsigned int i, j; |
| 929 | 938 | const char *zDir = "."; |
| 930 | 939 | int cnt = 0; |
| 931 | 940 | |
| 932 | 941 | #if defined(_WIN32) |
| 933 | | - char zTmpPath[MAX_PATH]; |
| 942 | + wchar_t zTmpPath[MAX_PATH]; |
| 934 | 943 | |
| 935 | | - if( GetTempPath(sizeof(zTmpPath), zTmpPath) ){ |
| 936 | | - azDirs[0] = zTmpPath; |
| 944 | + if( GetTempPathW(MAX_PATH, zTmpPath) ){ |
| 945 | + azDirs[0] = fossil_unicode_to_utf8(zTmpPath); |
| 937 | 946 | } |
| 938 | 947 | |
| 939 | 948 | azDirs[1] = fossil_getenv("TEMP"); |
| 940 | 949 | azDirs[2] = fossil_getenv("TMP"); |
| 941 | 950 | #endif |
| | @@ -994,11 +1003,10 @@ |
| 994 | 1003 | rc = blob_compare(&onDisk, pContent); |
| 995 | 1004 | blob_reset(&onDisk); |
| 996 | 1005 | return rc==0; |
| 997 | 1006 | } |
| 998 | 1007 | |
| 999 | | - |
| 1000 | 1008 | /************************************************************************** |
| 1001 | 1009 | ** The following routines translate between MBCS and UTF8 on windows. |
| 1002 | 1010 | ** Since everything is always UTF8 on unix, these routines are no-ops |
| 1003 | 1011 | ** there. |
| 1004 | 1012 | */ |
| | @@ -1014,10 +1022,29 @@ |
| 1014 | 1022 | return sqlite3_win32_mbcs_to_utf8(zMbcs); |
| 1015 | 1023 | #else |
| 1016 | 1024 | return (char*)zMbcs; /* No-op on unix */ |
| 1017 | 1025 | #endif |
| 1018 | 1026 | } |
| 1027 | + |
| 1028 | +/* |
| 1029 | +** Translate Unicode to UTF8. Return a pointer to the translated text. |
| 1030 | +** Call fossil_mbcs_free() to deallocate any memory used to store the |
| 1031 | +** returned pointer when done. |
| 1032 | +*/ |
| 1033 | +char *fossil_unicode_to_utf8(const void *zUnicode){ |
| 1034 | +#ifdef _WIN32 |
| 1035 | + int nByte = WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, 0, 0, 0, 0); |
| 1036 | + char *zUtf = sqlite3_malloc( nByte ); |
| 1037 | + if( zUtf==0 ){ |
| 1038 | + return 0; |
| 1039 | + } |
| 1040 | + WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, zUtf, nByte, 0, 0); |
| 1041 | + return zUtf; |
| 1042 | +#else |
| 1043 | + return (char *)zUnicode; /* No-op on unix */ |
| 1044 | +#endif |
| 1045 | +} |
| 1019 | 1046 | |
| 1020 | 1047 | /* |
| 1021 | 1048 | ** Translate UTF8 to MBCS for use in system calls. Return a pointer to the |
| 1022 | 1049 | ** translated text.. Call fossil_mbcs_free() to deallocate any memory |
| 1023 | 1050 | ** used to store the returned pointer when done. |
| | @@ -1028,18 +1055,41 @@ |
| 1028 | 1055 | return sqlite3_win32_utf8_to_mbcs(zUtf8); |
| 1029 | 1056 | #else |
| 1030 | 1057 | return (char*)zUtf8; /* No-op on unix */ |
| 1031 | 1058 | #endif |
| 1032 | 1059 | } |
| 1060 | + |
| 1061 | +/* |
| 1062 | +** Translate UTF8 to unicode for use in system calls. Return a pointer to the |
| 1063 | +** translated text.. Call fossil_mbcs_free() to deallocate any memory |
| 1064 | +** used to store the returned pointer when done. |
| 1065 | +*/ |
| 1066 | +void *fossil_utf8_to_unicode(const char *zUtf8){ |
| 1067 | +#ifdef _WIN32 |
| 1068 | + int nByte = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0); |
| 1069 | + wchar_t *zUnicode = sqlite3_malloc( nByte * 2 ); |
| 1070 | + if( zUnicode==0 ){ |
| 1071 | + return 0; |
| 1072 | + } |
| 1073 | + MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte); |
| 1074 | + return zUnicode; |
| 1075 | +#else |
| 1076 | + return (void *)zUtf8; /* No-op on unix */ |
| 1077 | +#endif |
| 1078 | +} |
| 1033 | 1079 | |
| 1034 | 1080 | /* |
| 1035 | 1081 | ** Return the value of an environment variable as UTF8. |
| 1036 | 1082 | */ |
| 1037 | 1083 | char *fossil_getenv(const char *zName){ |
| 1038 | | - char *zValue = getenv(zName); |
| 1039 | 1084 | #ifdef _WIN32 |
| 1040 | | - if( zValue ) zValue = fossil_mbcs_to_utf8(zValue); |
| 1085 | + wchar_t *uName = fossil_utf8_to_unicode(zName); |
| 1086 | + void *zValue = _wgetenv(uName); |
| 1087 | + fossil_mbcs_free(uName); |
| 1088 | + if( zValue ) zValue = fossil_unicode_to_utf8(zValue); |
| 1089 | +#else |
| 1090 | + char *zValue = getenv(zName); |
| 1041 | 1091 | #endif |
| 1042 | 1092 | return zValue; |
| 1043 | 1093 | } |
| 1044 | 1094 | |
| 1045 | 1095 | /* |
| | @@ -1085,11 +1135,11 @@ |
| 1085 | 1135 | |
| 1086 | 1136 | /* |
| 1087 | 1137 | ** Translate MBCS to UTF8. Return a pointer. Call fossil_mbcs_free() |
| 1088 | 1138 | ** to deallocate any memory used to store the returned pointer when done. |
| 1089 | 1139 | */ |
| 1090 | | -void fossil_mbcs_free(char *zOld){ |
| 1140 | +void fossil_mbcs_free(void *zOld){ |
| 1091 | 1141 | #ifdef _WIN32 |
| 1092 | 1142 | extern void sqlite3_free(void*); |
| 1093 | 1143 | sqlite3_free(zOld); |
| 1094 | 1144 | #else |
| 1095 | 1145 | /* No-op on unix */ |
| | @@ -1098,10 +1148,16 @@ |
| 1098 | 1148 | |
| 1099 | 1149 | /* |
| 1100 | 1150 | ** Like fopen() but always takes a UTF8 argument. |
| 1101 | 1151 | */ |
| 1102 | 1152 | FILE *fossil_fopen(const char *zName, const char *zMode){ |
| 1103 | | - char *zMbcs = fossil_utf8_to_mbcs(zName); |
| 1104 | | - FILE *f = fopen(zMbcs, zMode); |
| 1105 | | - fossil_mbcs_free(zMbcs); |
| 1153 | +#ifdef _WIN32 |
| 1154 | + wchar_t *uMode = fossil_utf8_to_unicode(zMode); |
| 1155 | + wchar_t *uName = fossil_utf8_to_unicode(zName); |
| 1156 | + FILE *f = _wfopen(uName, uMode); |
| 1157 | + fossil_mbcs_free(uName); |
| 1158 | + fossil_mbcs_free(uMode); |
| 1159 | +#else |
| 1160 | + FILE *f = fopen(zName, zMode); |
| 1161 | +#endif |
| 1106 | 1162 | return f; |
| 1107 | 1163 | } |
| 1108 | 1164 | |