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

  1. /***
  2. *w_map.c - W version of LCMapString.
  3. *
  4. *       Copyright (c) 1993-1997, Microsoft Corporation.  All rights reserved.
  5. *
  6. *Purpose:
  7. *       Use either LCMapStringA or LCMapStringW depending on which is available
  8. *
  9. *******************************************************************************/
  10.  
  11. #include <cruntime.h>
  12. #include <internal.h>
  13. #include <stdlib.h>
  14. #include <setlocal.h>
  15. #include <awint.h>
  16. #include <dbgint.h>
  17.  
  18. #define USE_W   1
  19. #define USE_A   2
  20.  
  21. /***
  22. *int __cdecl wcsncnt - count wide characters in a string, up to n.
  23. *
  24. *Purpose:
  25. *       Internal local support function. Counts characters in string before
  26. *       null. If null not found in n chars, then return n.
  27. *
  28. *Entry:
  29. *       const wchar_t *string   - start of string
  30. *       int n                - byte count
  31. *
  32. *Exit:
  33. *       returns number of wide characaters from start of string to
  34. *       null (exclusive), up to n.
  35. *
  36. *Exceptions:
  37. *
  38. *******************************************************************************/
  39.  
  40. static int __cdecl wcsncnt (
  41.         const wchar_t *string,
  42.         int cnt
  43.         )
  44. {
  45.         int n = cnt;
  46.         wchar_t *cp = (wchar_t *)string;
  47.  
  48.         while (n-- && *cp)
  49.             cp++;
  50.  
  51.         if (!*cp)
  52.             return cp - string;
  53.         return cnt;
  54. }
  55.  
  56. /***
  57. *int __cdecl __crtLCMapStringW - Get type information about a wide string.
  58. *
  59. *Purpose:
  60. *       Internal support function. Assumes info in wide string format. Tries
  61. *       to use NLS API call LCMapStringW if available and uses LCMapStringA
  62. *       if it must. If neither are available it fails and returns 0.
  63. *
  64. *Entry:
  65. *       LCID     Locale      - locale context for the comparison.
  66. *       DWORD    dwMapFlags  - see NT\Chicago docs
  67. *       LPCWSTR  lpSrcStr    - pointer to string to be mapped
  68. *       int      cchSrc      - wide char (word) count of input string
  69. *                              (including NULL if any)
  70. *                              (-1 if NULL terminated)
  71. *       LPWSTR   lpDestStr   - pointer to memory to store mapping
  72. *       int      cchDest     - wide char (word) count of buffer (including NULL)
  73. *       int      code_page   - for MB/WC conversion. If 0, use __lc_codepage
  74. *
  75. *       NOTE:    if LCMAP_SORTKEY is specified, then cchDest refers to number
  76. *                of BYTES, not number of wide chars. The return string will be
  77. *                a series of bytes with a NULL byte terminator.
  78. *
  79. *Exit:
  80. *       Success: if LCMAP_SORKEY:
  81. *                   number of bytes written to lpDestStr (including NULL byte
  82. *                   terminator)
  83. *               else
  84. *                   number of wide characters written to lpDestStr (including
  85. *                   NULL)
  86. *       Failure: 0
  87. *
  88. *Exceptions:
  89. *
  90. *******************************************************************************/
  91.  
  92. int __cdecl __crtLCMapStringW(
  93.         LCID     Locale,
  94.         DWORD    dwMapFlags,
  95.         LPCWSTR  lpSrcStr,
  96.         int      cchSrc,
  97.         LPWSTR   lpDestStr,
  98.         int      cchDest,
  99.         int      code_page
  100.         )
  101. {
  102.         static int f_use = 0;
  103.  
  104.         /*
  105.          * Look for unstubbed 'preferred' flavor. Otherwise use available flavor.
  106.          * Must actually call the function to ensure it's not a stub.
  107.          */
  108.  
  109.         if (0 == f_use) {
  110.             if (0 != LCMapStringW(0, LCMAP_LOWERCASE, L"\0", 1, NULL, 0))
  111.                 f_use = USE_W;
  112.             else if (0 != LCMapStringA(0, LCMAP_LOWERCASE, "\0", 1, NULL, 0))
  113.                 f_use = USE_A;
  114.             else
  115.                 return 0;
  116.         }
  117.  
  118.         /*
  119.          * LCMapString will map past NULL. Must find NULL if in string
  120.          * before cchSrc wide characters.
  121.          */
  122.         if (cchSrc > 0)
  123.             cchSrc = wcsncnt(lpSrcStr, cchSrc);
  124.  
  125.         /* Use "W" version */
  126.  
  127.         if (USE_W == f_use) {
  128.             return LCMapStringW( Locale, dwMapFlags, lpSrcStr, cchSrc,
  129.                                  lpDestStr, cchDest );
  130.         }
  131.  
  132.         /* Use "A" version */
  133.  
  134.         if (USE_A == f_use) {
  135.  
  136.             int retval;
  137.             int inbuff_size;
  138.             int outbuff_size;
  139.             unsigned char *inbuffer;
  140.             unsigned char *outbuffer;
  141.  
  142.             /*
  143.              * Convert string and return the requested information. Note that
  144.              * we are converting to a multibyte string so there is not a
  145.              * one-to-one correspondence between number of wide chars in the
  146.              * input string and the number of *bytes* in the buffer. However,
  147.              * there had *better be* a one-to-one correspondence between the
  148.              * number of wide characters and the number of multibyte characters
  149.              * (enforced by WC_SEPCHARS) in the buffer or the resulting mapped
  150.              * string will be worthless to the user.
  151.              *
  152.              */
  153.  
  154.             /*
  155.              * Use __lc_codepage for conversion if code_page not specified
  156.              */
  157.  
  158.             if (0 == code_page)
  159.                 code_page = __lc_codepage;
  160.  
  161.             /* find out how big a buffer we need (includes NULL if any) */
  162.             if ( 0 == (inbuff_size = WideCharToMultiByte( code_page,
  163.                                                           WC_COMPOSITECHECK |
  164.                                                             WC_SEPCHARS,
  165.                                                           lpSrcStr,
  166.                                                           cchSrc,
  167.                                                           NULL,
  168.                                                           0,
  169.                                                           NULL,
  170.                                                           NULL )) )
  171.                 return 0;
  172.  
  173.             /* allocate enough space for chars */
  174.             __try {
  175.                 inbuffer = (unsigned char *)_alloca( inbuff_size * sizeof(char) );
  176.             }
  177.             __except(EXCEPTION_EXECUTE_HANDLER) {
  178.                 inbuffer = NULL;
  179.             }
  180.  
  181.             if ( inbuffer == NULL )
  182.                 return 0;
  183.  
  184.             /* do the conversion */
  185.             if ( 0 ==  WideCharToMultiByte( code_page,
  186.                                             WC_COMPOSITECHECK | WC_SEPCHARS,
  187.                                             lpSrcStr,
  188.                                             cchSrc,
  189.                                             inbuffer,
  190.                                             inbuff_size,
  191.                                             NULL,
  192.                                             NULL ) )
  193.                 return 0;
  194.  
  195.             /* get size required for string mapping */
  196.             if ( 0 == (outbuff_size = LCMapStringA( Locale,
  197.                                                     dwMapFlags,
  198.                                                     inbuffer,
  199.                                                     inbuff_size,
  200.                                                     NULL,
  201.                                                     0 )) )
  202.                 return 0;
  203.  
  204.             /* allocate enough space for chars and NULL */
  205.             __try {
  206.                 outbuffer = (unsigned char *)_alloca( outbuff_size * sizeof(char) );
  207.             }
  208.             __except(EXCEPTION_EXECUTE_HANDLER) {
  209.                 outbuffer = NULL;
  210.             }
  211.  
  212.             if ( outbuffer == NULL )
  213.                 return 0;
  214.  
  215.             /* do string mapping */
  216.             if ( 0 == LCMapStringA( Locale,
  217.                                     dwMapFlags,
  218.                                     inbuffer,
  219.                                     inbuff_size,
  220.                                     outbuffer,
  221.                                     outbuff_size ) )
  222.                 return 0;
  223.  
  224.             if (dwMapFlags & LCMAP_SORTKEY) {
  225.  
  226.                 /* outbuff_size > cchDest is allowed */
  227.                 retval = outbuff_size;
  228.  
  229.                 if (0 != cchDest)
  230.                     /* SORTKEY returns BYTES, just copy */
  231.                     strncpy( (char *)lpDestStr,
  232.                              (char *)outbuffer,
  233.                              cchDest < outbuff_size ? cchDest : outbuff_size );
  234.             }
  235.             else {
  236.                 if (0 == cchDest) {
  237.                     /* get size required */
  238.                     if ( 0 == (retval = MultiByteToWideChar( code_page,
  239.                                                              MB_PRECOMPOSED,
  240.                                                              outbuffer,
  241.                                                              outbuff_size,
  242.                                                              NULL,
  243.                                                              0 )) )
  244.                         return 0;
  245.                 }
  246.                 else {
  247.                     /* convert mapping */
  248.                     if ( 0 == (retval = MultiByteToWideChar( code_page,
  249.                                                              MB_PRECOMPOSED,
  250.                                                              outbuffer,
  251.                                                              outbuff_size,
  252.                                                              lpDestStr,
  253.                                                              cchDest )) )
  254.                         return 0;
  255.                 }
  256.             }
  257.  
  258.             return retval;
  259.         }
  260.         else   /* f_use is neither USE_A nor USE_W */
  261.             return 0;
  262. }
  263.