/* win32-path.c - directory and file functions working on UTF-16
file and path names
Copyright (C) 2007 Michael Sabin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include
#include "newlisp.h"
#include "protos.h"
/*
utf8_to_utf16
Uses the Windows API to convert a UTF-8 string to a UTF-16 string.
Returns a pointer to a WCHAR string, or NULL if there was an error
(like if an invalid utf8 string was provided).
Note that the returned string must be free()ed.
*/
WCHAR * utf8_to_utf16(const char *utf8str)
{
int size = -1;
WCHAR *utf16str = NULL;
size = MultiByteToWideChar(
CP_UTF8,
0, /* no flags=ignore errors if possible */
utf8str,
-1, /* read until NULL character */
NULL,
0 /* just calculate size */
);
if (size == 0) return (NULL);
utf16str = (WCHAR*)allocMemory((size+1) * sizeof(WCHAR));
size = MultiByteToWideChar(
CP_UTF8,
0,
utf8str,
-1,
utf16str,
size
);
if (size == 0)
{
free(utf16str);
return(NULL);
}
else
return(utf16str);
}
/*
utf16_to_utf8ptr
Used in win32_realpath.
Generally wrapped by utf16_to_utf8.
*/
int utf16_to_utf8ptr(const WCHAR *utf16str, char * utf8str, int size)
{
if (size < 1) return(-1);
size = WideCharToMultiByte(
CP_UTF8,
0,
utf16str,
-1,
utf8str,
size,
NULL,
NULL
);
if (size == 0)
return(-1);
else
return(0);
}
/*
utf16_to_utf8
Uses the Windows API to convert a UTF-16 string to a UTF-8 string.
Returns a pointer to a char string, or NULL if there was an error
(like if an invalid utf16 string was provided).
Note that the returned string must be free()ed.
*/
char * utf16_to_utf8(const WCHAR *utf16str)
{
int size = -1;
char *utf8str = NULL;
size = WideCharToMultiByte(
CP_UTF8,
0,
utf16str,
-1,
0,
0,
NULL,
NULL
);
if (size == 0) return (NULL);
utf8str = (char*)allocMemory((size+1) * sizeof(char));
if (utf16_to_utf8ptr(utf16str, utf8str, size) == -1)
{
free(utf8str);
return(NULL);
}
else
return(utf8str);
}
/*
win32_realpath
Identical interface as realpath
for both ANSI and UTF-16 path names on Windows.
Has the following functional differences
* If GetFullPathNameW, first converts the UTF-8 file name to UTF-16 (WCHAR)
* Uses GetFullPathNameA or GetFullPathNameW to receive the char/WCHAR path
* If GetFullPathNameW, converts the UTF-16 WCHAR path back to UTF-8
*/
char *win32_realpath(const char *filepath, char *realpath)
{
#ifdef USE_WIN_UTF16PATH
WCHAR * utf16filepath;
WCHAR utf16realpath[MAX_PATH + 2];
int err;
utf16filepath = utf8_to_utf16(filepath);
err = GetFullPathNameW(utf16filepath, MAX_PATH, utf16realpath, NULL);
free(utf16filepath);
if (err == 0)
return(NULL);
if (utf16_to_utf8ptr(utf16realpath, realpath, MAX_PATH) == -1)
return(NULL);
#else
if(GetFullPathNameA(filepath, MAX_PATH, realpath, NULL) == 0)
return(NULL);
#endif
return (realpath);
}
/*
fileSizeW
Same behavior as fileSize() in nl-filesys.c
but accepts a WCHAR path.
Primarily for use in p_fileInfo()
*/
INT64 fileSizeW(WCHAR * pathName)
{
int handle;
INT64 size;
handle = _wopen(pathName,O_RDONLY | O_BINARY, 0);
size = lseek(handle, 0, SEEK_END);
close(handle);
if(size == -1) size = 0;
return(size);
}
/* ----------------------------------------------------------------------------
Wrappers for wide-character functions.
Same interface as the standard functions.
Adds the following functionality:
* first converts the UTF-8 string to UTF-16
* if there a conversion error, return fail
* calls the wide-character function
---------------------------------------------------------------------------- */
int rename_utf16(const char* a, const char* b)
{
int i;
WCHAR * utf16a;
WCHAR * utf16b;
utf16a = utf8_to_utf16(a);
if (utf16a == NULL) return (-1);
utf16b = utf8_to_utf16(b);
if (utf16b == NULL) return (-1);
i = _wrename(utf16a, utf16b);
free(utf16a);
free(utf16b);
return i;
}
int stat_utf16(const char* a, struct stat* b)
{
int i;
WCHAR * utf16a = utf8_to_utf16(a);
if (utf16a == NULL) return (-1);
i = _wstat(utf16a, (struct _stat*)b);
free(utf16a);
return i;
}
int chdir_utf16(const char* a)
{
int i;
WCHAR * utf16a = utf8_to_utf16(a);
if (utf16a == NULL) return (-1);
i = _wchdir(utf16a);
free(utf16a);
return i;
}
int open_utf16(const char* a, int b, int c)
{
int i;
WCHAR * utf16a = utf8_to_utf16(a);
if (utf16a == NULL) return (-1);
i = _wopen(utf16a, b, c);
free(utf16a);
return i;
}
int mkdir_utf16(const char* a)
{
int i;
WCHAR * utf16a = utf8_to_utf16(a);
if (utf16a == NULL) return (-1);
i = _wmkdir(utf16a);
free(utf16a);
return i;
}
int rmdir_utf16(const char* a)
{
int i;
WCHAR * utf16a = utf8_to_utf16(a);
if (utf16a == NULL) return (-1);
i = _wrmdir(utf16a);
free(utf16a);
return i;
}
int unlink_utf16(const char* a)
{
int i;
WCHAR * utf16a = utf8_to_utf16(a);
if (utf16a == NULL) return (-1);
i = _wunlink(utf16a);
free(utf16a);
return i;
}
_WDIR * opendir_utf16(const char* a)
{
_WDIR * dir;
WCHAR * utf16a = utf8_to_utf16(a);
if (utf16a == NULL) return (NULL);
dir = _wopendir(utf16a);
free(utf16a);
return dir;
}
/* eof */