home *** CD-ROM | disk | FTP | other *** search
- /***
- *xwctomb.c - Convert wide character to multibyte character, with locale.
- *
- * Copyright (c) 1995-1996, Microsoft Corporation. All rights reserved.
- *
- *Purpose:
- * Convert a wide character into the equivalent multibyte character.
- *
- *Revision History:
- * 12-XX-95 PJP Created from wctomb.c December 1995 by P.J. Plauger
- * 04-18-96 GJF Updated for current locale locking. Also, reformatted
- * and made several cosmetic changes.
- * 09-26-96 GJF Made _Getcvt() and wcsrtombs() multithread safe.
- *
- *******************************************************************************/
-
-
- #include <cruntime.h>
- #include <stdlib.h>
- #include <mtdll.h>
- #include <errno.h>
- #include <limits.h> /* for MB_LEN_MAX */
- #include <string.h> /* for memcpy */
- #include <stdio.h> /* for EOF */
- #include <xlocinfo.h> /* for _Cvtvec, _Wcrtomb */
- #ifdef _WIN32
- #include <locale.h>
- #include <setlocal.h>
- #endif /* _WIN32 */
-
- #ifndef _MT
- #define __Wcrtomb_lk _Wcrtomb
- #endif
-
- /***
- *int _Wcrtomb() - Convert wide character to multibyte character.
- *
- *Purpose:
- * Convert a wide character into the equivalent multi-byte character,
- * according to the specified LC_CTYPE category, or the current locale.
- * [ANSI].
- *
- * NOTE: Currently, the C libraries support the "C" locale only.
- * Non-C locale support now available under _INTL switch.
- *Entry:
- * char *s = pointer to multibyte character
- * wchar_t wchar = source wide character
- * mbstate_t *pst = pointer to state (not used)
- * const _Cvtvec *ploc = pointer to locale info
- *
- *Exit:
- * Returns:
- * -1 (if error) or number of bytes comprising converted mbc
- *
- *Exceptions:
- *
- *******************************************************************************/
-
- #ifdef _MT
- _CRTIMP2 int __cdecl __Wcrtomb_lk
- (
- char *s,
- wchar_t wchar,
- mbstate_t *,
- const _Cvtvec *ploc
- );
-
- _CRTIMP2 int __cdecl _Wcrtomb
- (
- char *s,
- wchar_t wchar,
- mbstate_t *pst,
- const _Cvtvec *ploc
- )
- {
- int retval;
- int local_lock_flag;
-
- _lock_locale( local_lock_flag )
- retval = __Wcrtomb_lk(s, wchar, 0, ploc);
- _unlock_locale( local_lock_flag )
- return retval;
- }
- #endif /* _MT */
-
- #ifdef _MT
- _CRTIMP2 int __cdecl __Wcrtomb_lk
- #else /* _MT */
- _CRTIMP2 int __cdecl _Wcrtomb
- #endif /* _MT */
- (
- char *s,
- wchar_t wchar,
- mbstate_t *pst,
- const _Cvtvec *ploc
- )
- {
- #ifdef _WIN32
- LCID handle;
- UINT codepage;
-
- if (ploc == 0)
- {
- handle = __lc_handle[LC_CTYPE];
- codepage = __lc_codepage;
- }
- else
- {
- handle = ploc->_Hand;
- codepage = ploc->_Page;
- }
-
- if ( handle == _CLOCALEHANDLE )
- {
- if ( wchar > 255 ) /* validate high byte */
- {
- errno = EILSEQ;
- return -1;
- }
-
- *s = (char) wchar;
- return sizeof(char);
- } else {
- int size;
- BOOL defused = 0;
-
- if ( ((size = WideCharToMultiByte(codepage,
- WC_COMPOSITECHECK | WC_SEPCHARS,
- &wchar,
- 1,
- s,
- MB_CUR_MAX,
- NULL,
- &defused)) == 0) ||
- (defused) )
- {
- errno = EILSEQ;
- return -1;
- }
-
- return size;
- }
-
- #else /* _WIN32 */
-
- if ( wchar > 255 ) /* validate high byte */
- {
- errno = EILSEQ;
- return -1;
- }
-
- *s = (char) wchar;
- return sizeof(char);
-
- #endif /* _WIN32 */
- }
-
-
- /***
- *_Cvtvec _Getcvt() - get conversion info for current locale
- *
- *Purpose:
- *
- *Entry:
- *
- *Exit:
- *
- *Exceptions:
- *
- *******************************************************************************/
-
- _CRTIMP2 _Cvtvec __cdecl _Getcvt()
- {
- _Cvtvec cvt;
- #ifdef _MT
- int local_lock_flag;
- #endif
-
- _lock_locale( local_lock_flag )
- cvt._Hand = __lc_handle[LC_CTYPE];
- cvt._Page = __lc_codepage;
- _unlock_locale( local_lock_flag )
-
- return (cvt);
- }
-
-
- /***
- *size_t wcrtomb(s, wchar, pst) - translate wchar_t to multibyte, restartably
- *
- *Purpose:
- *
- *Entry:
- *
- *Exit:
- *
- *Exceptions:
- *
- *******************************************************************************/
-
- _CRTIMP2 size_t __cdecl wcrtomb(
- char *s,
- wchar_t wchar,
- mbstate_t *pst
- )
- {
- return (s == 0 ? 1 : _Wcrtomb(s, wchar, 0, 0));
- }
-
-
- /***
- *size_t wcsrtombs(s, pwcs, n, pst) - translate wide char string to multibyte
- * string
- *
- *Purpose:
- *
- *Entry:
- *
- *Exit:
- *
- *Exceptions:
- *
- *******************************************************************************/
-
- _CRTIMP2 size_t __cdecl wcsrtombs(
- char *s,
- const wchar_t **pwcs,
- size_t n,
- mbstate_t *pst
- )
- {
- char buf[MB_LEN_MAX];
- int i;
- size_t nc = 0;
- const wchar_t *wcs = *pwcs;
- #ifdef _MT
- int local_lock_flag;
- #endif
-
- _lock_locale( local_lock_flag )
-
- if (s == 0)
- for (; ; nc += i, ++wcs)
- { /* translate but don't store */
- if ((i = __Wcrtomb_lk(buf, *wcs, 0, 0)) <= 0) {
- _unlock_locale( local_lock_flag )
- return ((size_t)-1);
- }
- else if (buf[i - 1] == '\0') {
- _unlock_locale( local_lock_flag )
- return (nc + i - 1);
- }
- }
-
- for (; 0 < n; nc += i, ++wcs, s += i, n -= i)
- { /* translate and store */
- char *t;
-
- if (n < MB_CUR_MAX)
- t = buf;
- else
- t = s;
-
- if ((i = __Wcrtomb_lk(t, *wcs, 0, 0)) <= 0)
- { /* encountered invalid sequence */
- nc = (size_t)-1;
- break;
- }
-
- if (s == t)
- ;
- else if (n < i)
- break; /* won't all fit */
- else
- memcpy(s, buf, i);
-
- if (s[i - 1] == '\0')
- { /* encountered terminating null */
- *pwcs = 0;
- _unlock_locale( local_lock_flag )
- return (nc + i - 1);
- }
- }
-
- _unlock_locale( local_lock_flag )
-
- *pwcs = wcs;
- return (nc);
- }
-
-
- /***
- *int wctob(wchar) - translate wint_t to one-byte multibyte
- *
- *Purpose:
- *
- *Entry:
- *
- *Exit:
- *
- *Exceptions:
- *
- *******************************************************************************/
-
- _CRTIMP2 int __cdecl wctob(
- wint_t wchar
- )
- {
- if (wchar == WEOF)
- return (EOF);
- else
- { /* check for one-byte translation */
- char buf[MB_LEN_MAX];
- return (_Wcrtomb(buf, wchar, 0, 0) == 1 ? buf[0] : EOF);
- }
- }
-