/* * msvcrt.dll wide-char functions * * Copyright 1999 Alexandre Julliard * Copyright 2000 Jon Griffiths */ #include #include #include "msvcrt.h" #include "winnls.h" #include "wine/unicode.h" #include "msvcrt/stdio.h" #include "msvcrt/stdlib.h" #include "msvcrt/string.h" #include "msvcrt/wctype.h" DEFAULT_DEBUG_CHANNEL(msvcrt); /* INTERNAL: MSVCRT_malloc() based wstrndup */ WCHAR* msvcrt_wstrndup(LPCWSTR buf, unsigned int size) { WCHAR* ret; unsigned int len = strlenW(buf), max_len; max_len = size <= len? size : len + 1; ret = MSVCRT_malloc(max_len * sizeof (WCHAR)); if (ret) { memcpy(ret,buf,max_len * sizeof (WCHAR)); ret[max_len] = 0; } return ret; } /********************************************************************* * _wcsdup (MSVCRT.@) */ WCHAR* _wcsdup( const WCHAR* str ) { WCHAR* ret = NULL; if (str) { int size = (strlenW(str) + 1) * sizeof(WCHAR); ret = MSVCRT_malloc( size ); if (ret) memcpy( ret, str, size ); } return ret; } /********************************************************************* * _wcsicoll (MSVCRT.@) */ INT _wcsicoll( const WCHAR* str1, const WCHAR* str2 ) { /* FIXME: handle collates */ return strcmpiW( str1, str2 ); } /********************************************************************* * _wcsnset (MSVCRT.@) */ WCHAR* _wcsnset( WCHAR* str, WCHAR c, MSVCRT_size_t n ) { WCHAR* ret = str; while ((n-- > 0) && *str) *str++ = c; return ret; } /********************************************************************* * _wcsrev (MSVCRT.@) */ WCHAR* _wcsrev( WCHAR* str ) { WCHAR* ret = str; WCHAR* end = str + strlenW(str) - 1; while (end > str) { WCHAR t = *end; *end-- = *str; *str++ = t; } return ret; } /********************************************************************* * _wcsset (MSVCRT.@) */ WCHAR* _wcsset( WCHAR* str, WCHAR c ) { WCHAR* ret = str; while (*str) *str++ = c; return ret; } /********************************************************************* * _vsnwprintf (MSVCRT.@) */ int _vsnwprintf(WCHAR *str, unsigned int len, const WCHAR *format, va_list valist) { /* If you fix a bug in this function, fix it in ntdll/wcstring.c also! */ unsigned int written = 0; const WCHAR *iter = format; char bufa[256], fmtbufa[64], *fmta; TRACE("(%d,%s)\n",len,debugstr_w(format)); while (*iter) { while (*iter && *iter != (WCHAR)L'%') { if (written++ >= len) return -1; *str++ = *iter++; } if (*iter == (WCHAR)L'%') { fmta = fmtbufa; *fmta++ = *iter++; while (*iter == (WCHAR)L'0' || *iter == (WCHAR)L'+' || *iter == (WCHAR)L'-' || *iter == (WCHAR)L' ' || *iter == (WCHAR)L'0' || *iter == (WCHAR)L'*' || *iter == (WCHAR)L'#') { if (*iter == (WCHAR)L'*') { char *buffiter = bufa; int fieldlen = va_arg(valist, int); sprintf(buffiter, "%d", fieldlen); while (*buffiter) *fmta++ = *buffiter++; } else *fmta++ = *iter; iter++; } while (isdigit(*iter)) *fmta++ = *iter++; if (*iter == (WCHAR)L'.') { *fmta++ = *iter++; if (*iter == (WCHAR)L'*') { char *buffiter = bufa; int fieldlen = va_arg(valist, int); sprintf(buffiter, "%d", fieldlen); while (*buffiter) *fmta++ = *buffiter++; } else while (isdigit(*iter)) *fmta++ = *iter++; } if (*iter == (WCHAR)L'h' || *iter == (WCHAR)L'l') { *fmta++ = *iter++; *fmta++ = *iter++; } switch (*iter) { case (WCHAR)L's': { static const WCHAR none[] = { '(', 'n', 'u', 'l', 'l', ')', 0 }; const WCHAR *wstr = va_arg(valist, const WCHAR *); const WCHAR *striter = wstr ? wstr : none; while (*striter) { if (written++ >= len) return -1; *str++ = *striter++; } iter++; break; } case (WCHAR)L'c': if (written++ >= len) return -1; *str++ = (WCHAR)va_arg(valist, int); iter++; break; default: { /* For non wc types, use system sprintf and append to wide char output */ /* FIXME: for unrecognised types, should ignore % when printing */ char *bufaiter = bufa; if (*iter == (WCHAR)L'p') sprintf(bufaiter, "%08lX", va_arg(valist, long)); else { *fmta++ = *iter; *fmta = '\0'; sprintf(bufaiter, fmtbufa, va_arg(valist, void *)); } while (*bufaiter) { if (written++ >= len) return -1; *str++ = *bufaiter++; } iter++; break; } } } } if (written >= len) return -1; *str++ = (WCHAR)L'\0'; return (int)written; } /********************************************************************* * vswprintf (MSVCRT.@) */ int MSVCRT_vswprintf( WCHAR* str, const WCHAR* format, va_list args ) { return _vsnwprintf( str, INT_MAX, format, args ); } /********************************************************************* * wcscoll (MSVCRT.@) */ int MSVCRT_wcscoll( const WCHAR* str1, const WCHAR* str2 ) { /* FIXME: handle collates */ return strcmpW( str1, str2 ); } /********************************************************************* * wcspbrk (MSVCRT.@) */ WCHAR* MSVCRT_wcspbrk( const WCHAR* str, const WCHAR* accept ) { const WCHAR* p; while (*str) { for (p = accept; *p; p++) if (*p == *str) return (WCHAR*)str; str++; } return NULL; } /********************************************************************* * wctomb (MSVCRT.@) */ INT MSVCRT_wctomb( char *dst, WCHAR ch ) { return WideCharToMultiByte( CP_ACP, 0, &ch, 1, dst, 6, NULL, NULL ); } /********************************************************************* * iswalnum (MSVCRT.@) */ INT MSVCRT_iswalnum( WCHAR wc ) { return get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT|C1_LOWER|C1_UPPER); } /********************************************************************* * iswalpha (MSVCRT.@) */ INT MSVCRT_iswalpha( WCHAR wc ) { return get_char_typeW(wc) & (C1_ALPHA|C1_LOWER|C1_UPPER); } /********************************************************************* * iswcntrl (MSVCRT.@) */ INT MSVCRT_iswcntrl( WCHAR wc ) { return get_char_typeW(wc) & C1_CNTRL; } /********************************************************************* * iswdigit (MSVCRT.@) */ INT MSVCRT_iswdigit( WCHAR wc ) { return get_char_typeW(wc) & C1_DIGIT; } /********************************************************************* * iswgraph (MSVCRT.@) */ INT MSVCRT_iswgraph( WCHAR wc ) { return get_char_typeW(wc) & (C1_ALPHA|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER); } /********************************************************************* * iswlower (MSVCRT.@) */ INT MSVCRT_iswlower( WCHAR wc ) { return get_char_typeW(wc) & C1_LOWER; } /********************************************************************* * iswprint (MSVCRT.@) */ INT MSVCRT_iswprint( WCHAR wc ) { return get_char_typeW(wc) & (C1_ALPHA|C1_BLANK|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER); } /********************************************************************* * iswpunct (MSVCRT.@) */ INT MSVCRT_iswpunct( WCHAR wc ) { return get_char_typeW(wc) & C1_PUNCT; } /********************************************************************* * iswspace (MSVCRT.@) */ INT MSVCRT_iswspace( WCHAR wc ) { return get_char_typeW(wc) & C1_SPACE; } /********************************************************************* * iswupper (MSVCRT.@) */ INT MSVCRT_iswupper( WCHAR wc ) { return get_char_typeW(wc) & C1_UPPER; } /********************************************************************* * iswxdigit (MSVCRT.@) */ INT MSVCRT_iswxdigit( WCHAR wc ) { return get_char_typeW(wc) & C1_XDIGIT; } /********************************************************************* * _itow (MSVCRT.@) */ WCHAR* _itow(int value,WCHAR* out,int base) { char buf[64]; _itoa(value, buf, base); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buf, -1, out, 128); return out; } /********************************************************************* * _ltow (MSVCRT.@) */ WCHAR* _ltow(long value,WCHAR* out,int base) { char buf[128]; _ltoa(value, buf, base); MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buf, -1, out, 128); return out; } /********************************************************************* * _ultow (MSVCRT.@) */ WCHAR* _ultow(unsigned long value,WCHAR* out,int base) { char buf[128]; _ultoa(value, buf, base); MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buf, -1, out, 128); return out; }