/* * CRTDLL wide-char functions * * Copyright 1999 Alexandre Julliard * * TODO: * These functions are really necessary only if sizeof(WCHAR) != sizeof(wchar_t), * otherwise we could use the libc functions directly. */ #include "config.h" #include #include #include #ifdef HAVE_WCTYPE_H #include #endif #include "windef.h" #include "crtdll.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(crtdll); /********************************************************************* * CRTDLL__wcsdup (CRTDLL.320) */ LPWSTR __cdecl CRTDLL__wcsdup( LPCWSTR str ) { LPWSTR ret = NULL; if (str) { int size = (CRTDLL_wcslen(str) + 1) * sizeof(WCHAR); ret = CRTDLL_malloc( size ); if (ret) memcpy( ret, str, size ); } return ret; } /********************************************************************* * CRTDLL__wcsicmp (CRTDLL.321) */ INT __cdecl CRTDLL__wcsicmp( LPCWSTR str1, LPCWSTR str2 ) { while (*str1 && (CRTDLL_towupper(*str1) == CRTDLL_towupper(*str2))) { str1++; str2++; } return CRTDLL_towupper(*str1) - CRTDLL_towupper(*str2); } /********************************************************************* * CRTDLL__wcsicoll (CRTDLL.322) */ INT __cdecl CRTDLL__wcsicoll( LPCWSTR str1, LPCWSTR str2 ) { /* FIXME: handle collates */ return CRTDLL__wcsicmp( str1, str2 ); } /********************************************************************* * CRTDLL__wcslwr (CRTDLL.323) */ LPWSTR __cdecl CRTDLL__wcslwr( LPWSTR str ) { LPWSTR ret = str; for ( ; *str; str++) *str = CRTDLL_towlower(*str); return ret; } /********************************************************************* * CRTDLL__wcsnicmp (CRTDLL.324) */ INT __cdecl CRTDLL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n ) { if (!n) return 0; while ((--n > 0) && *str1 && (CRTDLL_towupper(*str1) == CRTDLL_towupper(*str2))) { str1++; str2++; } return CRTDLL_towupper(*str1) - CRTDLL_towupper(*str2); } /********************************************************************* * CRTDLL__wcsnset (CRTDLL.325) */ LPWSTR __cdecl CRTDLL__wcsnset( LPWSTR str, WCHAR c, INT n ) { LPWSTR ret = str; while ((n-- > 0) && *str) *str++ = c; return ret; } /********************************************************************* * CRTDLL__wcsrev (CRTDLL.326) */ LPWSTR __cdecl CRTDLL__wcsrev( LPWSTR str ) { LPWSTR ret = str; LPWSTR end = str + CRTDLL_wcslen(str) - 1; while (end > str) { WCHAR t = *end; *end-- = *str; *str++ = t; } return ret; } /********************************************************************* * CRTDLL__wcsset (CRTDLL.327) */ LPWSTR __cdecl CRTDLL__wcsset( LPWSTR str, WCHAR c ) { LPWSTR ret = str; while (*str) *str++ = c; return ret; } /********************************************************************* * CRTDLL__wcsupr (CRTDLL.328) */ LPWSTR __cdecl CRTDLL__wcsupr( LPWSTR str ) { LPWSTR ret = str; for ( ; *str; str++) *str = CRTDLL_towupper(*str); return ret; } /********************************************************************* * CRTDLL_towlower (CRTDLL.493) */ WCHAR __cdecl CRTDLL_towlower( WCHAR ch ) { #ifdef HAVE_WCTYPE_H ch = (WCHAR)towlower( (wchar_t)ch ); #else if (!HIBYTE(ch)) ch = (WCHAR)tolower( LOBYTE(ch) ); /* FIXME */ #endif return ch; } /********************************************************************* * CRTDLL_towupper (CRTDLL.494) */ WCHAR __cdecl CRTDLL_towupper( WCHAR ch ) { #ifdef HAVE_WCTYPE_H ch = (WCHAR)towupper( (wchar_t)ch ); #else if (!HIBYTE(ch)) ch = (WCHAR)toupper( LOBYTE(ch) ); /* FIXME */ #endif return ch; } /*********************************************************************** * CRTDLL_wcscat (CRTDLL.503) */ LPWSTR __cdecl CRTDLL_wcscat( LPWSTR dst, LPCWSTR src ) { LPWSTR p = dst; while (*p) p++; while ((*p++ = *src++)); return dst; } /********************************************************************* * CRTDLL_wcschr (CRTDLL.504) */ LPWSTR __cdecl CRTDLL_wcschr( LPCWSTR str, WCHAR ch ) { while (*str) { if (*str == ch) return (LPWSTR)str; str++; } return NULL; } /********************************************************************* * CRTDLL_wcscmp (CRTDLL.505) */ INT __cdecl CRTDLL_wcscmp( LPCWSTR str1, LPCWSTR str2 ) { while (*str1 && (*str1 == *str2)) { str1++; str2++; } return (INT)(*str1 - *str2); } /********************************************************************* * CRTDLL_wcscoll (CRTDLL.506) */ DWORD __cdecl CRTDLL_wcscoll( LPCWSTR str1, LPCWSTR str2 ) { /* FIXME: handle collates */ return CRTDLL_wcscmp( str1, str2 ); } /*********************************************************************** * CRTDLL_wcscpy (CRTDLL.507) */ LPWSTR __cdecl CRTDLL_wcscpy( LPWSTR dst, LPCWSTR src ) { LPWSTR p = dst; while ((*p++ = *src++)); return dst; } /********************************************************************* * CRTDLL_wcscspn (CRTDLL.508) */ INT __cdecl CRTDLL_wcscspn( LPCWSTR str, LPCWSTR reject ) { LPCWSTR start = str; while (*str) { LPCWSTR p = reject; while (*p && (*p != *str)) p++; if (*p) break; str++; } return str - start; } /*********************************************************************** * CRTDLL_wcslen (CRTDLL.510) */ INT __cdecl CRTDLL_wcslen( LPCWSTR str ) { LPCWSTR s = str; while (*s) s++; return s - str; } /********************************************************************* * CRTDLL_wcsncat (CRTDLL.511) */ LPWSTR __cdecl CRTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT n ) { LPWSTR ret = s1; while (*s1) s1++; while (n-- > 0) if (!(*s1++ = *s2++)) return ret; *s1 = 0; return ret; } /********************************************************************* * CRTDLL_wcsncmp (CRTDLL.512) */ INT __cdecl CRTDLL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n ) { if (!n) return 0; while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; } return (INT)(*str1 - *str2); } /********************************************************************* * CRTDLL_wcsncpy (CRTDLL.513) */ LPWSTR __cdecl CRTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT n ) { LPWSTR ret = s1; while (n-- > 0) if (!(*s1++ = *s2++)) break; while (n-- > 0) *s1++ = 0; return ret; } /********************************************************************* * CRTDLL_wcspbrk (CRTDLL.514) */ LPWSTR __cdecl CRTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept ) { LPCWSTR p; while (*str) { for (p = accept; *p; p++) if (*p == *str) return (LPWSTR)str; str++; } return NULL; } /********************************************************************* * CRTDLL_wcsrchr (CRTDLL.515) */ LPWSTR __cdecl CRTDLL_wcsrchr( LPWSTR str, WCHAR ch ) { LPWSTR last = NULL; while (*str) { if (*str == ch) last = str; str++; } return last; } /********************************************************************* * CRTDLL_wcsspn (CRTDLL.516) */ INT __cdecl CRTDLL_wcsspn( LPCWSTR str, LPCWSTR accept ) { LPCWSTR start = str; while (*str) { LPCWSTR p = accept; while (*p && (*p != *str)) p++; if (!*p) break; str++; } return str - start; } /********************************************************************* * CRTDLL_wcsstr (CRTDLL.517) */ LPWSTR __cdecl CRTDLL_wcsstr( LPCWSTR str, LPCWSTR sub ) { while (*str) { LPCWSTR p1 = str, p2 = sub; while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; } if (!*p2) return (LPWSTR)str; str++; } return NULL; } /********************************************************************* * CRTDLL_wcstok (CRTDLL.519) */ LPWSTR __cdecl CRTDLL_wcstok( LPWSTR str, LPCWSTR delim ) { static LPWSTR next = NULL; LPWSTR ret; if (!str) if (!(str = next)) return NULL; while (*str && CRTDLL_wcschr( delim, *str )) str++; if (!*str) return NULL; ret = str++; while (*str && !CRTDLL_wcschr( delim, *str )) str++; if (*str) *str++ = 0; next = str; return ret; } /********************************************************************* * CRTDLL_wcstombs (CRTDLL.521) * * FIXME: the reason I do not use wcstombs is that it seems to fail * for any latin-1 valid character. Not good. */ INT __cdecl CRTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT n ) { int copied=0; while ((n>0) && *src) { int ret; /* FIXME: could potentially overflow if we ever have MB of 2 bytes*/ ret = wctomb(dst,(wchar_t)*src); if (ret<0) { /* FIXME: sadly, some versions of glibc do not like latin characters * as UNICODE chars for some reason (like german umlauts). Just * copy those anyway. MM 991106 */ *dst=*src; ret = 1; } dst += ret; n -= ret; copied += ret; src++; } return copied; } /********************************************************************* * CRTDLL_wctomb (CRTDLL.524) */ INT __cdecl CRTDLL_wctomb( LPSTR dst, WCHAR ch ) { return wctomb( dst, (wchar_t)ch ); } /********************************************************************* * CRTDLL_iswalnum (CRTDLL.405) */ INT __cdecl CRTDLL_iswalnum( WCHAR wc ) { #ifdef HAVE_WCTYPE_H #undef iswalnum return iswalnum(wc); #else return isalnum( LOBYTE(wc) ); /* FIXME */ #endif } /********************************************************************* * CRTDLL_iswalpha (CRTDLL.406) */ INT __cdecl CRTDLL_iswalpha( WCHAR wc ) { #ifdef HAVE_WCTYPE_H #undef iswalpha return iswalpha(wc); #else return isalpha( LOBYTE(wc) ); /* FIXME */ #endif } /********************************************************************* * CRTDLL_iswcntrl (CRTDLL.408) */ INT __cdecl CRTDLL_iswcntrl( WCHAR wc ) { #ifdef HAVE_WCTYPE_H #undef iswcntrl return iswcntrl(wc); #else return iscntrl( LOBYTE(wc) ); /* FIXME */ #endif } /********************************************************************* * CRTDLL_iswdigit (CRTDLL.410) */ INT __cdecl CRTDLL_iswdigit( WCHAR wc ) { #ifdef HAVE_WCTYPE_H #undef iswdigit return iswdigit(wc); #else return isdigit( LOBYTE(wc) ); /* FIXME */ #endif } /********************************************************************* * CRTDLL_iswgraph (CRTDLL.411) */ INT __cdecl CRTDLL_iswgraph( WCHAR wc ) { #ifdef HAVE_WCTYPE_H #undef iswgraph return iswgraph(wc); #else return isgraph( LOBYTE(wc) ); /* FIXME */ #endif } /********************************************************************* * CRTDLL_iswlower (CRTDLL.412) */ INT __cdecl CRTDLL_iswlower( WCHAR wc ) { #ifdef HAVE_WCTYPE_H #undef iswlower return iswlower(wc); #else return islower( LOBYTE(wc) ); /* FIXME */ #endif } /********************************************************************* * CRTDLL_iswprint (CRTDLL.413) */ INT __cdecl CRTDLL_iswprint( WCHAR wc ) { #ifdef HAVE_WCTYPE_H #undef iswprint return iswprint(wc); #else return isprint( LOBYTE(wc) ); /* FIXME */ #endif } /********************************************************************* * CRTDLL_iswpunct (CRTDLL.414) */ INT __cdecl CRTDLL_iswpunct( WCHAR wc ) { #ifdef HAVE_WCTYPE_H #undef iswpunct return iswpunct(wc); #else return ispunct( LOBYTE(wc) ); /* FIXME */ #endif } /********************************************************************* * CRTDLL_iswspace (CRTDLL.415) */ INT __cdecl CRTDLL_iswspace( WCHAR wc ) { #ifdef HAVE_WCTYPE_H #undef iswspace return iswspace(wc); #else return isspace( LOBYTE(wc) ); /* FIXME */ #endif } /********************************************************************* * CRTDLL_iswupper (CRTDLL.416) */ INT __cdecl CRTDLL_iswupper( WCHAR wc ) { #ifdef HAVE_WCTYPE_H #undef iswupper return iswupper(wc); #else return isupper( LOBYTE(wc) ); /* FIXME */ #endif } /********************************************************************* * CRTDLL_iswxdigit (CRTDLL.417) */ INT __cdecl CRTDLL_iswxdigit( WCHAR wc ) { #ifdef HAVE_WCTYPE_H #undef iswxdigit return iswxdigit(wc); #else return isxdigit( LOBYTE(wc) ); /* FIXME */ #endif } /********************************************************************* * CRTDLL_iswctype (CRTDLL.409) */ INT __cdecl CRTDLL_iswctype( WCHAR wc, WCHAR wct ) { INT res = 0; if (wct & 0x0001) res |= CRTDLL_iswupper(wc); if (wct & 0x0002) res |= CRTDLL_iswlower(wc); if (wct & 0x0004) res |= CRTDLL_iswdigit(wc); if (wct & 0x0008) res |= CRTDLL_iswspace(wc); if (wct & 0x0010) res |= CRTDLL_iswpunct(wc); if (wct & 0x0020) res |= CRTDLL_iswcntrl(wc); if (wct & 0x0080) res |= CRTDLL_iswxdigit(wc); if (wct & 0x0100) res |= CRTDLL_iswalpha(wc); if (wct & 0x0040) FIXME(": iswctype(%04hx,_BLANK|...) requested\n",wc); if (wct & 0x8000) FIXME(": iswctype(%04hx,_LEADBYTE|...) requested\n",wc); return res; }