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

  1. /***
  2. *w_str.c - W version of GetStringType.
  3. *
  4. *       Copyright (c) 1993-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       Use either GetStringTypeA or GetStringTypeW depending on which is
  8. *       unstubbed.
  9. *
  10. *******************************************************************************/
  11.  
  12. #include <cruntime.h>
  13. #include <internal.h>
  14. #include <stdlib.h>
  15. #include <setlocal.h>
  16. #include <locale.h>
  17. #include <awint.h>
  18. #include <dbgint.h>
  19.  
  20. #define USE_W   1
  21. #define USE_A   2
  22.  
  23. /***
  24. *int __cdecl __crtGetStringTypeW - Get type information about a wide string.
  25. *
  26. *Purpose:
  27. *       Internal support function. Assumes info in wide string format. Tries
  28. *       to use NLS API call GetStringTypeW if available and uses GetStringTypeA
  29. *       if it must. If neither are available it fails and returns FALSE.
  30. *
  31. *Entry:
  32. *       DWORD    dwInfoType  - see NT\Chicago docs
  33. *       LPCWSTR  lpSrcStr    - wide string for which character types are
  34. *                              requested
  35. *       int      cchSrc      - wide char (word) count of lpSrcStr (including
  36. *                              NULL if any)
  37. *       LPWORD   lpCharType  - array to receive character type information
  38. *                              (must be same size as lpSrcStr)
  39. *       int      code_page   - for MB/WC conversion. If 0, use __lc_codepage
  40. *       int      lcid        - for A call, specify LCID, If 0, use
  41. *                              __lc_handle[LC_CTYPE].
  42. *
  43. *Exit:
  44. *       Success: TRUE
  45. *       Failure: FALSE
  46. *
  47. *Exceptions:
  48. *
  49. *******************************************************************************/
  50.  
  51. BOOL __cdecl __crtGetStringTypeW(
  52.         DWORD    dwInfoType,
  53.         LPCWSTR  lpSrcStr,
  54.         int      cchSrc,
  55.         LPWORD   lpCharType,
  56.         int      code_page,
  57.         int      lcid
  58.         )
  59. {
  60.         static int f_use = 0;
  61.  
  62.         /*
  63.          * Look for unstubbed 'preferred' flavor. Otherwise use available flavor.
  64.          * Must actually call the function to ensure it's not a stub.
  65.          */
  66.  
  67.         if (0 == f_use)
  68.         {
  69.             unsigned short dummy;
  70.  
  71.             if (0 != GetStringTypeW(CT_CTYPE1, L"\0", 1, &dummy))
  72.                 f_use = USE_W;
  73.  
  74.             else if (0 != GetStringTypeA(0, CT_CTYPE1, "\0", 1, &dummy))
  75.                 f_use = USE_A;
  76.  
  77.             else
  78.                 return FALSE;
  79.         }
  80.  
  81.         /* Use "W" version */
  82.  
  83.         if (USE_W == f_use)
  84.         {
  85.             return GetStringTypeW(dwInfoType, lpSrcStr, cchSrc, lpCharType);
  86.         }
  87.  
  88.         /* Use "A" version */
  89.  
  90.         if (USE_A == f_use)
  91.         {
  92.             int buff_size;
  93.             BOOL retbool;
  94.             unsigned char *buffer;
  95.             WORD * pwCharInfo;
  96.  
  97.             /*
  98.              * Convert string and return the requested information. Note that
  99.              * we are converting to a multibyte string so there is not a
  100.              * one-to-one correspondence between number of wide chars in the
  101.              * input string and the number of *bytes* in the buffer. However,
  102.              * there had *better be* a one-to-one correspondence between the
  103.              * number of wide characters and the number of WORDs in the
  104.              * return buffer.
  105.              */
  106.  
  107.             /*
  108.              * Use __lc_codepage for conversion if code_page not specified
  109.              */
  110.  
  111.             if (0 == code_page)
  112.                 code_page = __lc_codepage;
  113.  
  114.             /* find out how big a buffer we need */
  115.             if ( 0 == (buff_size = WideCharToMultiByte( code_page,
  116.                                                         WC_COMPOSITECHECK |
  117.                                                             WC_SEPCHARS,
  118.                                                         lpSrcStr,
  119.                                                         cchSrc,
  120.                                                         NULL,
  121.                                                         0,
  122.                                                         NULL,
  123.                                                         NULL )) )
  124.                 return FALSE;
  125.  
  126.             /* allocate enough space for chars */
  127.             __try {
  128.                 buffer = (unsigned char *)_alloca( sizeof(char) * buff_size );
  129.                 (void)memset( buffer, 0, sizeof(char) * buff_size );
  130.             }
  131.             __except( EXCEPTION_EXECUTE_HANDLER ) {
  132.                 buffer = NULL;
  133.             }
  134.  
  135.             if ( buffer == NULL )
  136.                 return FALSE;
  137.  
  138.             /* do the conversion */
  139.             if ( 0 == WideCharToMultiByte( code_page,
  140.                                            WC_COMPOSITECHECK | WC_SEPCHARS,
  141.                                            lpSrcStr,
  142.                                            cchSrc,
  143.                                            buffer,
  144.                                            buff_size,
  145.                                            NULL,
  146.                                            NULL ) )
  147.                 return FALSE;
  148.  
  149.             /* allocate enough space for result (+1 for sanity check) */
  150.             __try {
  151.                 pwCharInfo = (WORD *)_alloca( sizeof(WORD) * (buff_size + 1) );
  152.             }
  153.             __except( EXCEPTION_EXECUTE_HANDLER ) {
  154.                 pwCharInfo = NULL;
  155.             }
  156.  
  157.             if ( pwCharInfo == NULL )
  158.                 return FALSE;
  159.  
  160.             /* do we use default lcid */
  161.             if (0 == lcid)
  162.                 lcid = __lc_handle[LC_CTYPE];
  163.  
  164.             /* set to known value */
  165.             pwCharInfo[cchSrc - 1] = pwCharInfo[cchSrc] = 0xFFFF;
  166.  
  167.             /* obtain result */
  168.             retbool = GetStringTypeA( lcid, dwInfoType, buffer, buff_size,
  169.                                       pwCharInfo );
  170.  
  171.             /*
  172.              * GetStringTypeA does not reveal how many WORDs have been
  173.              * modifed - to be safe we use another buffer and then
  174.              * verify that EXACTLY cchSrc WORDs were modified. Note that
  175.              * not all multibyte LCID/codepage combos are guaranteed to work.
  176.              */
  177.  
  178.             if (pwCharInfo[cchSrc - 1] == 0xFFFF || pwCharInfo[cchSrc] != 0xFFFF)
  179.                 return FALSE;
  180.  
  181.             memmove(lpCharType, pwCharInfo, cchSrc * sizeof(WORD));
  182.  
  183.             return retbool;
  184.         }
  185.         else   /* f_use is neither USE_A nor USE_W */
  186.             return FALSE;
  187. }
  188.