home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / xwctomb.c < prev    next >
C/C++ Source or Header  |  1998-06-16  |  8KB  |  317 lines

  1. /***
  2. *xwctomb.c - Convert wide character to multibyte character, with locale.
  3. *
  4. *       Copyright (c) 1995-1996, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       Convert a wide character into the equivalent multibyte character.
  8. *
  9. *Revision History:
  10. *       12-XX-95  PJP   Created from wctomb.c December 1995 by P.J. Plauger
  11. *       04-18-96  GJF   Updated for current locale locking. Also, reformatted
  12. *                       and made several cosmetic changes.
  13. *       09-26-96  GJF   Made _Getcvt() and wcsrtombs() multithread safe.
  14. *
  15. *******************************************************************************/
  16.  
  17.  
  18. #include <cruntime.h>
  19. #include <stdlib.h>
  20. #include <mtdll.h>
  21. #include <errno.h>
  22. #include <limits.h>             /* for MB_LEN_MAX */
  23. #include <string.h>             /* for memcpy */
  24. #include <stdio.h>              /* for EOF */
  25. #include <xlocinfo.h>           /* for _Cvtvec, _Wcrtomb */
  26. #ifdef _WIN32
  27. #include <locale.h>
  28. #include <setlocal.h>
  29. #endif  /* _WIN32 */
  30.  
  31. #ifndef _MT
  32. #define __Wcrtomb_lk    _Wcrtomb
  33. #endif
  34.  
  35. /***
  36. *int _Wcrtomb() - Convert wide character to multibyte character.
  37. *
  38. *Purpose:
  39. *       Convert a wide character into the equivalent multi-byte character,
  40. *       according to the specified LC_CTYPE category, or the current locale.
  41. *       [ANSI].
  42. *
  43. *       NOTE:  Currently, the C libraries support the "C" locale only.
  44. *              Non-C locale support now available under _INTL switch.
  45. *Entry:
  46. *       char *s             = pointer to multibyte character
  47. *       wchar_t wchar       = source wide character
  48. *       mbstate_t *pst      = pointer to state (not used)
  49. *       const _Cvtvec *ploc = pointer to locale info
  50. *
  51. *Exit:
  52. *       Returns:
  53. *      -1 (if error) or number of bytes comprising converted mbc
  54. *
  55. *Exceptions:
  56. *
  57. *******************************************************************************/
  58.  
  59. #ifdef _MT
  60. _CRTIMP2 int __cdecl __Wcrtomb_lk
  61.         (
  62.         char *s,
  63.         wchar_t wchar,
  64.         mbstate_t *,
  65.         const _Cvtvec *ploc
  66.         );
  67.  
  68. _CRTIMP2 int __cdecl _Wcrtomb
  69.         (
  70.         char *s,
  71.         wchar_t wchar,
  72.         mbstate_t *pst,
  73.         const _Cvtvec *ploc
  74.         )
  75. {
  76.         int retval;
  77.         int local_lock_flag;
  78.  
  79.         _lock_locale( local_lock_flag )
  80.         retval = __Wcrtomb_lk(s, wchar, 0, ploc);
  81.         _unlock_locale( local_lock_flag )
  82.         return retval;
  83. }
  84. #endif  /* _MT */
  85.  
  86. #ifdef _MT
  87. _CRTIMP2 int __cdecl __Wcrtomb_lk
  88. #else  /* _MT */
  89. _CRTIMP2 int __cdecl _Wcrtomb
  90. #endif  /* _MT */
  91.         (
  92.         char *s,
  93.         wchar_t wchar,
  94.         mbstate_t *pst,
  95.         const _Cvtvec *ploc
  96.         )
  97. {
  98. #ifdef _WIN32
  99.         LCID handle;
  100.         UINT codepage;
  101.  
  102.         if (ploc == 0)
  103.         {
  104.             handle = __lc_handle[LC_CTYPE];
  105.             codepage = __lc_codepage;
  106.         }
  107.         else
  108.         {
  109.             handle = ploc->_Hand;
  110.             codepage = ploc->_Page;
  111.         }
  112.  
  113.         if ( handle == _CLOCALEHANDLE )
  114.         {
  115.             if ( wchar > 255 )  /* validate high byte */
  116.             {
  117.                 errno = EILSEQ;
  118.                 return -1;
  119.             }
  120.  
  121.             *s = (char) wchar;
  122.             return sizeof(char);
  123.         } else {
  124.             int size;
  125.             BOOL defused = 0;
  126.  
  127.             if ( ((size = WideCharToMultiByte(codepage,
  128.                                               WC_COMPOSITECHECK | WC_SEPCHARS,
  129.                                               &wchar, 
  130.                                               1,
  131.                                               s, 
  132.                                               MB_CUR_MAX, 
  133.                                               NULL, 
  134.                                               &defused)) == 0) || 
  135.                  (defused) )
  136.             {
  137.                 errno = EILSEQ;
  138.                 return -1;
  139.             }
  140.  
  141.             return size;
  142.         }
  143.  
  144. #else  /* _WIN32 */
  145.  
  146.         if ( wchar > 255 )  /* validate high byte */
  147.         {
  148.             errno = EILSEQ;
  149.             return -1;
  150.         }
  151.  
  152.         *s = (char) wchar;
  153.         return sizeof(char);
  154.  
  155. #endif  /* _WIN32 */
  156. }
  157.  
  158.  
  159. /***
  160. *_Cvtvec _Getcvt() - get conversion info for current locale
  161. *
  162. *Purpose:
  163. *
  164. *Entry:
  165. *
  166. *Exit:
  167. *
  168. *Exceptions:
  169. *
  170. *******************************************************************************/
  171.  
  172. _CRTIMP2 _Cvtvec __cdecl _Getcvt()
  173. {
  174.         _Cvtvec cvt;
  175. #ifdef  _MT
  176.         int local_lock_flag;
  177. #endif
  178.  
  179.         _lock_locale( local_lock_flag )
  180.         cvt._Hand = __lc_handle[LC_CTYPE];
  181.         cvt._Page = __lc_codepage;
  182.         _unlock_locale( local_lock_flag )
  183.  
  184.         return (cvt);
  185. }
  186.  
  187.  
  188. /***
  189. *size_t wcrtomb(s, wchar, pst) - translate wchar_t to multibyte, restartably
  190. *
  191. *Purpose:
  192. *
  193. *Entry:
  194. *
  195. *Exit:
  196. *
  197. *Exceptions:
  198. *
  199. *******************************************************************************/
  200.  
  201. _CRTIMP2 size_t __cdecl wcrtomb(
  202.         char *s, 
  203.         wchar_t wchar, 
  204.         mbstate_t *pst
  205.         )
  206. {
  207.         return (s == 0 ? 1 : _Wcrtomb(s, wchar, 0, 0));
  208. }
  209.  
  210.  
  211. /***
  212. *size_t wcsrtombs(s, pwcs, n, pst) - translate wide char string to multibyte 
  213. *       string
  214. *
  215. *Purpose:
  216. *
  217. *Entry:
  218. *
  219. *Exit:
  220. *
  221. *Exceptions:
  222. *
  223. *******************************************************************************/
  224.  
  225. _CRTIMP2 size_t __cdecl wcsrtombs(
  226.         char *s, 
  227.         const wchar_t **pwcs, 
  228.         size_t n, 
  229.         mbstate_t *pst
  230.         )
  231. {
  232.         char buf[MB_LEN_MAX];
  233.         int i;
  234.         size_t nc = 0;
  235.         const wchar_t *wcs = *pwcs;
  236. #ifdef  _MT
  237.         int local_lock_flag;
  238. #endif
  239.  
  240.         _lock_locale( local_lock_flag )
  241.  
  242.         if (s == 0)
  243.             for (; ; nc += i, ++wcs)
  244.             {   /* translate but don't store */
  245.                 if ((i = __Wcrtomb_lk(buf, *wcs, 0, 0)) <= 0) {
  246.                     _unlock_locale( local_lock_flag )
  247.                     return ((size_t)-1);
  248.                 }
  249.                 else if (buf[i - 1] == '\0') {
  250.                     _unlock_locale( local_lock_flag )
  251.                     return (nc + i - 1);
  252.                 }
  253.             }
  254.  
  255.         for (; 0 < n; nc += i, ++wcs, s += i, n -= i)
  256.         {   /* translate and store */
  257.             char *t;
  258.  
  259.             if (n < MB_CUR_MAX)
  260.                 t = buf;
  261.             else
  262.                 t = s;
  263.  
  264.             if ((i = __Wcrtomb_lk(t, *wcs, 0, 0)) <= 0)
  265.             {   /* encountered invalid sequence */
  266.                 nc = (size_t)-1;
  267.                 break;
  268.             }
  269.  
  270.             if (s == t)
  271.                 ;
  272.             else if (n < i)
  273.                 break;  /* won't all fit */
  274.             else
  275.                 memcpy(s, buf, i);
  276.  
  277.             if (s[i - 1] == '\0')
  278.             {   /* encountered terminating null */
  279.                 *pwcs = 0;
  280.                 _unlock_locale( local_lock_flag )
  281.                 return (nc + i - 1);
  282.             }
  283.         }
  284.  
  285.         _unlock_locale( local_lock_flag )
  286.  
  287.         *pwcs = wcs;
  288.         return (nc);
  289. }
  290.  
  291.  
  292. /***
  293. *int wctob(wchar) - translate wint_t to one-byte multibyte
  294. *
  295. *Purpose:
  296. *
  297. *Entry:
  298. *
  299. *Exit:
  300. *
  301. *Exceptions:
  302. *
  303. *******************************************************************************/
  304.  
  305. _CRTIMP2 int __cdecl wctob(
  306.         wint_t wchar
  307.         )
  308. {  
  309.         if (wchar == WEOF)
  310.             return (EOF);
  311.         else
  312.         {   /* check for one-byte translation */
  313.             char buf[MB_LEN_MAX];
  314.             return (_Wcrtomb(buf, wchar, 0, 0) == 1 ? buf[0] : EOF);
  315.         }
  316. }
  317.