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

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