610 lines
13 KiB
C
610 lines
13 KiB
C
/*
|
|
* msvcrt.dll mbcs functions
|
|
*
|
|
* Copyright 1999 Alexandre Julliard
|
|
* Copyright 2000 Jon Griffths
|
|
*
|
|
* FIXME
|
|
* Not currently binary compatible with win32. MSVCRT_mbctype must be
|
|
* populated correctly and the ismb* functions should reference it.
|
|
*/
|
|
|
|
#include "msvcrt.h"
|
|
|
|
#include "msvcrt/stdlib.h"
|
|
#include "msvcrt/string.h"
|
|
|
|
|
|
DEFAULT_DEBUG_CHANNEL(msvcrt);
|
|
|
|
unsigned char MSVCRT_mbctype[257];
|
|
int MSVCRT___mb_cur_max = 1;
|
|
|
|
int MSVCRT_isleadbyte(int);
|
|
char *_strset(char *, int);
|
|
char *_strnset(char *, int, unsigned int);
|
|
extern unsigned int MSVCRT_current_lc_all_cp;
|
|
|
|
|
|
/*********************************************************************
|
|
* __p__mbctype (MSVCRT.@)
|
|
*/
|
|
unsigned char *__p__mbctype(void)
|
|
{
|
|
return MSVCRT_mbctype;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* __p___mb_cur_max(MSVCRT.@)
|
|
*/
|
|
int *__p___mb_cur_max(void)
|
|
{
|
|
return &MSVCRT___mb_cur_max;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbsnextc(MSVCRT.@)
|
|
*/
|
|
unsigned int _mbsnextc(const unsigned char *str)
|
|
{
|
|
if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*str))
|
|
return *str << 8 | str[1];
|
|
return *str; /* ASCII CP or SB char */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbscmp(MSVCRT.@)
|
|
*/
|
|
int _mbscmp(const char *str, const char *cmp)
|
|
{
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
unsigned int strc, cmpc;
|
|
do {
|
|
if(!*str)
|
|
return *cmp ? -1 : 0;
|
|
if(!*cmp)
|
|
return 1;
|
|
strc = _mbsnextc(str);
|
|
cmpc = _mbsnextc(cmp);
|
|
if(strc != cmpc)
|
|
return strc < cmpc ? -1 : 1;
|
|
str +=(strc > 255) ? 2 : 1;
|
|
cmp +=(strc > 255) ? 2 : 1; /* equal, use same increment */
|
|
} while(1);
|
|
}
|
|
return strcmp(str, cmp); /* ASCII CP */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbsicmp(MSVCRT.@)
|
|
*/
|
|
int _mbsicmp(const char *str, const char *cmp)
|
|
{
|
|
/* FIXME: No tolower() for mb strings yet */
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
return _mbscmp(str, cmp);
|
|
return strcasecmp(str, cmp); /* ASCII CP */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbsncmp (MSVCRT.@)
|
|
*/
|
|
int _mbsncmp(const char *str, const char *cmp, unsigned int len)
|
|
{
|
|
if(!len)
|
|
return 0;
|
|
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
unsigned int strc, cmpc;
|
|
while(len--)
|
|
{
|
|
if(!*str)
|
|
return *cmp ? -1 : 0;
|
|
if(!*cmp)
|
|
return 1;
|
|
strc = _mbsnextc(str);
|
|
cmpc = _mbsnextc(cmp);
|
|
if(strc != cmpc)
|
|
return strc < cmpc ? -1 : 1;
|
|
str +=(strc > 255) ? 2 : 1;
|
|
cmp +=(strc > 255) ? 2 : 1; /* Equal, use same increment */
|
|
}
|
|
return 0; /* Matched len chars */
|
|
}
|
|
return strncmp(str, cmp, len); /* ASCII CP */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbsnicmp(MSVCRT.@)
|
|
*
|
|
* Compare two multibyte strings case insensitively to 'len' characters.
|
|
*/
|
|
int _mbsnicmp(const char *str, const char *cmp, unsigned int len)
|
|
{
|
|
/* FIXME: No tolower() for mb strings yet */
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
return _mbsncmp(str, cmp, len);
|
|
return strncasecmp(str, cmp, len); /* ASCII CP */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbsinc(MSVCRT.@)
|
|
*/
|
|
char *_mbsinc(const unsigned char *str)
|
|
{
|
|
if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*str))
|
|
return (char *)str + 2; /* MB char */
|
|
|
|
return (char *)str + 1; /* ASCII CP or SB char */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbsninc(MSVCRT.@)
|
|
*/
|
|
char *_mbsninc(const char *str, unsigned int num)
|
|
{
|
|
if(!str || num < 1)
|
|
return NULL;
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
while(num--)
|
|
str = _mbsinc(str);
|
|
return (char *)str;
|
|
}
|
|
return (char *)str + num; /* ASCII CP */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbslen(MSVCRT.@)
|
|
*/
|
|
int _mbslen(const unsigned char *str)
|
|
{
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
int len = 0;
|
|
while(*str)
|
|
{
|
|
str += MSVCRT_isleadbyte(*str) ? 2 : 1;
|
|
len++;
|
|
}
|
|
return len;
|
|
}
|
|
return strlen(str); /* ASCII CP */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbsrchr(MSVCRT.@)
|
|
*/
|
|
char *_mbsrchr(const char *s,unsigned int x)
|
|
{
|
|
/* FIXME: handle multibyte strings */
|
|
return strrchr(s,x);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* mbtowc(MSVCRT.@)
|
|
*/
|
|
int MSVCRT_mbtowc(WCHAR *dst, const char *str, unsigned int n)
|
|
{
|
|
if(n <= 0 || !str)
|
|
return 0;
|
|
if(!MultiByteToWideChar(CP_ACP, 0, str, n, dst, 1))
|
|
return 0;
|
|
/* return the number of bytes from src that have been used */
|
|
if(!*str)
|
|
return 0;
|
|
if(n >= 2 && MSVCRT_isleadbyte(*str) && str[1])
|
|
return 2;
|
|
return 1;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbccpy(MSVCRT.@)
|
|
*/
|
|
void _mbccpy(char *dest, const unsigned char *src)
|
|
{
|
|
*dest++ = *src;
|
|
if(MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(*src))
|
|
*dest = *++src; /* MB char */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbbtombc(MSVCRT.@)
|
|
*/
|
|
unsigned int _mbbtombc(unsigned int c)
|
|
{
|
|
if(MSVCRT___mb_cur_max > 1 &&
|
|
((c >= 0x20 && c <=0x7e) ||(c >= 0xa1 && c <= 0xdf)))
|
|
{
|
|
/* FIXME: I can't get this function to return anything
|
|
* different to what I pass it...
|
|
*/
|
|
}
|
|
return c; /* ASCII CP or no MB char */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbclen(MSVCRT.@)
|
|
*/
|
|
unsigned int _mbclen(const unsigned char *str)
|
|
{
|
|
return MSVCRT_isleadbyte(*str) ? 2 : 1;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _ismbbkana(MSVCRT.@)
|
|
*/
|
|
int _ismbbkana(unsigned int c)
|
|
{
|
|
/* FIXME: use lc_ctype when supported, not lc_all */
|
|
if(MSVCRT_current_lc_all_cp == 932)
|
|
{
|
|
/* Japanese/Katakana, CP 932 */
|
|
return (c >= 0xa1 && c <= 0xdf);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _ismbchira(MSVCRT.@)
|
|
*/
|
|
int _ismbchira(unsigned int c)
|
|
{
|
|
/* FIXME: use lc_ctype when supported, not lc_all */
|
|
if(MSVCRT_current_lc_all_cp == 932)
|
|
{
|
|
/* Japanese/Hiragana, CP 932 */
|
|
return (c >= 0x829f && c <= 0x82f1);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _ismbckata(MSVCRT.@)
|
|
*/
|
|
int _ismbckata(unsigned int c)
|
|
{
|
|
/* FIXME: use lc_ctype when supported, not lc_all */
|
|
if(MSVCRT_current_lc_all_cp == 932)
|
|
{
|
|
if(c < 256)
|
|
return _ismbbkana(c);
|
|
/* Japanese/Katakana, CP 932 */
|
|
return (c >= 0x8340 && c <= 0x8396 && c != 0x837f);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _ismbblead(MSVCRT.@)
|
|
*/
|
|
int _ismbblead(unsigned int c)
|
|
{
|
|
/* FIXME: should reference MSVCRT_mbctype */
|
|
return MSVCRT___mb_cur_max > 1 && MSVCRT_isleadbyte(c);
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* _ismbbtrail(MSVCRT.@)
|
|
*/
|
|
int _ismbbtrail(unsigned int c)
|
|
{
|
|
/* FIXME: should reference MSVCRT_mbctype */
|
|
return !_ismbblead(c);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _ismbslead(MSVCRT.@)
|
|
*/
|
|
int _ismbslead(const unsigned char *start, const unsigned char *str)
|
|
{
|
|
/* Lead bytes can also be trail bytes if caller messed up
|
|
* iterating through the string...
|
|
*/
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
while(start < str)
|
|
start += MSVCRT_isleadbyte(*str) ? 2 : 1;
|
|
|
|
if(start == str)
|
|
return MSVCRT_isleadbyte(*str);
|
|
}
|
|
return 0; /* Must have been a trail, we skipped it */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _ismbstrail(MSVCRT.@)
|
|
*/
|
|
int _ismbstrail(const char *start, const unsigned char *str)
|
|
{
|
|
/* Must not be a lead, and must be preceeded by one */
|
|
return !_ismbslead(start, str) && MSVCRT_isleadbyte(str[-1]);
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbsdec(MSVCRT.@)
|
|
*/
|
|
char *_mbsdec(const char *start, const char *cur)
|
|
{
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
return (char *)(_ismbstrail(start,cur-1) ? cur - 2 : cur -1);
|
|
|
|
return (char *)cur - 1; /* ASCII CP or SB char */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbsset(MSVCRT.@)
|
|
*/
|
|
char *_mbsset(char *str, unsigned int c)
|
|
{
|
|
char *ret = str;
|
|
|
|
if(MSVCRT___mb_cur_max == 1 || c < 256)
|
|
return _strset(str, c); /* ASCII CP or SB char */
|
|
|
|
c &= 0xffff; /* Strip high bits */
|
|
|
|
while(str[0] && str[1])
|
|
{
|
|
*str++ = c >> 8;
|
|
*str++ = c & 0xff;
|
|
}
|
|
if(str[0])
|
|
str[0] = '\0'; /* FIXME: OK to shorten? */
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbsnset(MSVCRT.@)
|
|
*/
|
|
char *_mbsnset(char *str, unsigned int c, unsigned int len)
|
|
{
|
|
char *ret = str;
|
|
|
|
if(!len)
|
|
return ret;
|
|
|
|
if(MSVCRT___mb_cur_max == 1 || c < 256)
|
|
return _strnset(str, c, len); /* ASCII CP or SB char */
|
|
|
|
c &= 0xffff; /* Strip high bits */
|
|
|
|
while(str[0] && str[1] && len--)
|
|
{
|
|
*str++ = c >> 8;
|
|
*str++ = c & 0xff;
|
|
}
|
|
if(len && str[0])
|
|
str[0] = '\0'; /* FIXME: OK to shorten? */
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbstrlen(MSVCRT.@)
|
|
*/
|
|
MSVCRT_size_t _mbstrlen(const char *str)
|
|
{
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
int len = 0;
|
|
while(*str)
|
|
{
|
|
str += MSVCRT_isleadbyte(*str) ? 2 : 1;
|
|
len++;
|
|
}
|
|
return len;
|
|
}
|
|
return strlen(str); /* ASCII CP */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbsncpy(MSVCRT.@)
|
|
*/
|
|
char *_mbsncpy(char *dst, const char *src, unsigned int len)
|
|
{
|
|
if(!len)
|
|
return dst;
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
char *ret = dst;
|
|
while(src[0] && src[1] && len--)
|
|
{
|
|
*dst++ = *src++;
|
|
*dst++ = *src++;
|
|
}
|
|
if(len--)
|
|
{
|
|
*dst++ = *src++; /* Last char or '\0' */
|
|
while(len--)
|
|
*dst++ = '\0';
|
|
}
|
|
return ret;
|
|
}
|
|
return strncpy(dst, src, len); /* ASCII CP */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbschr(MSVCRT.@)
|
|
*
|
|
* Find a multibyte character in a multibyte string.
|
|
*/
|
|
unsigned char* _mbschr(const unsigned char* str, unsigned int c)
|
|
{
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
unsigned int next;
|
|
while((next = _mbsnextc(str)))
|
|
{
|
|
if(next == c)
|
|
return (char *)str;
|
|
str += next > 255 ? 2 : 1;
|
|
}
|
|
return c ? NULL :(char *)str;
|
|
}
|
|
return strchr(str, c); /* ASCII CP */
|
|
}
|
|
|
|
/*********************************************************************
|
|
* _mbsnccnt(MSVCRT.@)
|
|
*/
|
|
unsigned int _mbsnccnt(const unsigned char *str, unsigned int len)
|
|
{
|
|
int ret = 0;
|
|
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
while(*str && len-- > 0)
|
|
{
|
|
if(MSVCRT_isleadbyte(*str))
|
|
{
|
|
str++;
|
|
len--;
|
|
}
|
|
ret++;
|
|
str++;
|
|
}
|
|
return ret;
|
|
}
|
|
return min(strlen(str), len); /* ASCII CP */
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* _mbsncat(MSVCRT.@)
|
|
*/
|
|
unsigned char* _mbsncat(unsigned char* dst, const unsigned char* src, MSVCRT_size_t len)
|
|
{
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
char *res = dst;
|
|
dst += _mbslen(dst);
|
|
while(*src && len--)
|
|
{
|
|
*dst = *src;
|
|
if(MSVCRT_isleadbyte(*src))
|
|
*++dst = *++src;
|
|
dst++;
|
|
src++;
|
|
}
|
|
*dst++ = '\0';
|
|
return res;
|
|
}
|
|
return strncat(dst, src, len); /* ASCII CP */
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* _ismbcdigit(MSVCRT.@)
|
|
*/
|
|
int _ismbcdigit( unsigned int ch)
|
|
{
|
|
if (ch <0x100)
|
|
return isdigit(ch);
|
|
else
|
|
{
|
|
FIXME("Handle MBC chars\n");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* _mbsnbcmp(MSVCRT.@)
|
|
*/
|
|
int _mbsnbcmp( const unsigned char *str,const unsigned char *cmp, MSVCRT_size_t len )
|
|
{
|
|
if (!len)
|
|
return 0;
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
FIXME("%s %s %d\n",str,cmp,len);
|
|
return 0;
|
|
}
|
|
return strncmp(str,cmp,len);
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* _mbslwr(MSVCRT.@)
|
|
*/
|
|
unsigned char * _mbslwr( unsigned char *string )
|
|
{
|
|
unsigned char *p;
|
|
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
FIXME("%s\n",string);
|
|
return string;
|
|
}
|
|
p = string;
|
|
while (*p)
|
|
{
|
|
*p= tolower(*p);
|
|
p++;
|
|
}
|
|
return string;
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* _mbsnbcpy(MSVCRT.@)
|
|
*/
|
|
unsigned char * _mbsnbcpy(unsigned char *dest,const unsigned char *src,MSVCRT_size_t n)
|
|
{
|
|
if(MSVCRT___mb_cur_max > 1)
|
|
{
|
|
FIXME("%s %d\n",src,n);
|
|
return dest;
|
|
}
|
|
return strncpy(dest, src, n);
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* _mbsspn (MSVCRT.@)
|
|
*/
|
|
MSVCRT_size_t _mbsspn(const unsigned char *string, const unsigned char *set)
|
|
{
|
|
const unsigned char *p, *q;
|
|
|
|
for (p = string; *p; p++)
|
|
{
|
|
if (MSVCRT_isleadbyte(*p))
|
|
{
|
|
for (q = set; *q; q++)
|
|
{
|
|
if (!q[1])
|
|
break;
|
|
if ((*p == *q) && (p[1] == q[1]))
|
|
break;
|
|
q++;
|
|
}
|
|
if (*++p == '\0')
|
|
break;
|
|
}
|
|
else
|
|
for (q = set; *q; q++)
|
|
if (*p == *q)
|
|
break;
|
|
}
|
|
return p - string;
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
* _ismbcspace (MSVCRT.@)
|
|
*/
|
|
int _ismbcspace( unsigned int c)
|
|
{
|
|
|
|
if (c <0x100)
|
|
return isspace(c);
|
|
FIXME("%c\n",c);
|
|
return 0;
|
|
}
|