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

  1. /***
  2. *initctyp.c - contains __init_ctype
  3. *
  4. *       Copyright (c) 1991-1998, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       Contains the locale-category initialization function: __init_ctype().
  8. *
  9. *       Each initialization function sets up locale-specific information
  10. *       for their category, for use by functions which are affected by
  11. *       their locale category.
  12. *
  13. *       *** For internal use by setlocale() only ***
  14. *
  15. *******************************************************************************/
  16.  
  17. #include <stdlib.h>
  18. #include <windows.h>
  19. #include <locale.h>
  20. #include <setlocal.h>
  21. #include <ctype.h>
  22. #include <malloc.h>
  23. #include <limits.h>
  24. #include <awint.h>
  25. #include <dbgint.h>
  26.  
  27. #define _CTABSIZE   257     /* size of ctype tables */
  28.  
  29. /***
  30. *int __init_ctype() - initialization for LC_CTYPE locale category.
  31. *
  32. *Purpose:
  33. *       In non-C locales, preread ctype tables for chars and wide-chars.
  34. *       Old tables are freed when new tables are fully established, else
  35. *       the old tables remain intact (as if original state unaltered).
  36. *       The leadbyte table is implemented as the high bit in ctype1.
  37. *
  38. *       In the C locale, ctype tables are freed, and pointers point to
  39. *       the static ctype table.
  40. *
  41. *       Tables contain 257 entries: -1 to 256.
  42. *       Table pointers point to entry 0 (to allow index -1).
  43. *
  44. *Entry:
  45. *       None.
  46. *
  47. *Exit:
  48. *       0 success
  49. *       1 fail
  50. *
  51. *Exceptions:
  52. *
  53. *******************************************************************************/
  54.  
  55. int __cdecl __init_ctype (
  56.         void
  57.         )
  58. {
  59.         /* non-C locale table for char's    */
  60.         static unsigned short *ctype1 = NULL;   /* keep around until next time */
  61.         unsigned short *newctype1;          /* temp new table */
  62.  
  63.         /* non-C locale table for wchar_t's */
  64.         static unsigned short *wctype1 = NULL;  /* keep around until next time */
  65.         unsigned short *newwctype1;         /* temp new table */
  66.  
  67.         unsigned char *cbuffer = NULL;      /* char working buffer */
  68.         wchar_t *wbuffer = NULL;            /* wchar_t working buffer */
  69.  
  70.         int i;                              /* general purpose counter */
  71.         unsigned char *cp;                  /* char pointer */
  72.         wchar_t *wcp;                       /* wide char pointer */
  73.         CPINFO lpCPInfo;                    /* struct for use with GetCPInfo */
  74.  
  75.         /* allocate and set up buffers before destroying old ones */
  76.         /* codepage will be restored by setlocale if error */
  77.  
  78.  
  79.         if (__lc_handle[LC_CTYPE] != _CLOCALEHANDLE)
  80.         {
  81.             if (__lc_codepage == 0)
  82.             { /* code page was not specified */
  83.                 if ( __getlocaleinfo( LC_INT_TYPE,
  84.                                       MAKELCID(__lc_id[LC_CTYPE].wLanguage, SORT_DEFAULT),
  85.                                       LOCALE_IDEFAULTANSICODEPAGE,
  86.                                       (char **)&__lc_codepage ) )
  87.                     goto error_cleanup;
  88.             }
  89.  
  90.             /* allocate new buffers for tables */
  91.             newctype1 = (unsigned short *)
  92.                 _malloc_crt(_CTABSIZE * sizeof(unsigned short));
  93.             newwctype1 = (unsigned short *)
  94.                 _malloc_crt(_CTABSIZE * sizeof(unsigned short));
  95.             cbuffer = (unsigned char *)
  96.                 _malloc_crt (_CTABSIZE * sizeof(char));
  97.             wbuffer = (wchar_t *)
  98.                 _malloc_crt (_CTABSIZE * sizeof(wchar_t));
  99.  
  100.             if (!newctype1 || !newwctype1 || !cbuffer || !wbuffer)
  101.                 goto error_cleanup;
  102.  
  103.             /* construct string composed of first 256 chars in sequence */
  104.             for (cp=cbuffer, i=0; i<_CTABSIZE-1; i++)
  105.                 *cp++ = (unsigned char)i;
  106.  
  107.             if (GetCPInfo( __lc_codepage, &lpCPInfo) == FALSE)
  108.                 goto error_cleanup;
  109.  
  110.             if (lpCPInfo.MaxCharSize > MB_LEN_MAX)
  111.                 goto error_cleanup;
  112.  
  113.             __mb_cur_max = (unsigned short) lpCPInfo.MaxCharSize;
  114.  
  115.             /* zero out leadbytes so GetStringType doesn't interpret as multi-byte chars */
  116.             if (__mb_cur_max > 1)
  117.             {
  118.                 for (cp = (unsigned char *)lpCPInfo.LeadByte; cp[0] && cp[1]; cp += 2)
  119.                 {
  120.                     for (i = cp[0]; i <= cp[1]; i++)
  121.                         cbuffer[i] = 0;
  122.                 }
  123.             }
  124.  
  125.             /* convert to newctype1 table - ignore invalid char errors */
  126.             if ( __crtGetStringTypeA( CT_CTYPE1,
  127.                                       cbuffer,
  128.                                       _CTABSIZE-1,
  129.                                       newctype1+1,
  130.                                       0,
  131.                                       0,
  132.                                       FALSE ) == FALSE )
  133.                 goto error_cleanup;
  134.             *newctype1 = 0; /* entry for EOF */
  135.  
  136.             /* construct wide char string composed of first 256 chars in sequence */
  137.             for (wcp=wbuffer, i=0; i<_CTABSIZE-1; i++)
  138.                 *wcp++ = (wchar_t)i;
  139.  
  140.             /* convert to newwctype1 table */
  141.             if ( __crtGetStringTypeW( CT_CTYPE1,
  142.                                       wbuffer,
  143.                                       _CTABSIZE-1,
  144.                                       newwctype1+1,
  145.                                       0,
  146.                                       0 ) == FALSE )
  147.                 goto error_cleanup;
  148.             *newwctype1 = 0;    /* entry for EOF */
  149.  
  150.             /* ignore DefaultChar */
  151.  
  152.             /* mark lead-byte entries in newctype1 table */
  153.             if (__mb_cur_max > 1)
  154.             {
  155.                 for (cp = (unsigned char *)lpCPInfo.LeadByte; cp[0] && cp[1]; cp += 2)
  156.                 {
  157.                     for (i = cp[0]; i <= cp[1]; i++)
  158.                         newctype1[i+1] = _LEADBYTE;
  159.                 }
  160.             }
  161.  
  162.             /* set pointers to point to entry 0 of tables */
  163.             _pctype = newctype1 + 1;
  164.             _pwctype = newwctype1 + 1;
  165.  
  166.             /* free old tables */
  167.             if (ctype1)
  168.                 _free_crt (ctype1);
  169.             ctype1 = newctype1;
  170.  
  171.             if (wctype1)
  172.                 _free_crt (wctype1);
  173.             wctype1 = newwctype1;
  174.  
  175.             /* cleanup and return success */
  176.             _free_crt (cbuffer);
  177.             _free_crt (wbuffer);
  178.             return 0;
  179.  
  180. error_cleanup:
  181.             _free_crt (newctype1);
  182.             _free_crt (newwctype1);
  183.             _free_crt (cbuffer);
  184.             _free_crt (wbuffer);
  185.             return 1;
  186.  
  187.         } else {
  188.  
  189.             /* set pointers to static C-locale table */
  190.             _pctype = _ctype + 1;
  191.             _pwctype = _ctype + 1;
  192.  
  193.             /* free dynamic locale-specific tables */
  194.             _free_crt (ctype1);
  195.             _free_crt (wctype1);
  196.             ctype1 = NULL;
  197.             wctype1 = NULL;
  198.  
  199.             return 0;
  200.         }
  201. }
  202.