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

  1. /***
  2. *initmon.c - contains __init_monetary
  3. *
  4. *       Copyright (c) 1991-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       Contains the locale-category initialization function: __init_monetary().
  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 <malloc.h>
  22. #include <limits.h>
  23. #include <dbgint.h>
  24.  
  25. static int __cdecl _get_lc_lconv(struct lconv *l);
  26. static void __cdecl _free_lc_lconv(struct lconv *l);
  27.  
  28. /* Pointer to non-C locale lconv */
  29. static struct lconv *__lconv_intl = NULL;
  30.  
  31. /*
  32.  *  Note that __lconv_c is used when the monetary category is in the C locale
  33.  *  but the numeric category may not necessarily be in the C locale.
  34.  */
  35.  
  36.  
  37. /***
  38. *int __init_monetary() - initialization for LC_MONETARY locale category.
  39. *
  40. *Purpose:
  41. *       In non-C locales, read the localized monetary strings into
  42. *       __lconv_intl, and also copy the numeric strings from __lconv into
  43. *       __lconv_intl.  Set __lconv to point to __lconv_intl.  The old
  44. *       __lconv_intl is not freed until the new one is fully established.
  45. *
  46. *       In the C locale, the monetary fields in lconv are filled with
  47. *       contain C locale values.  Any allocated __lconv_intl fields are freed.
  48. *
  49. *       At startup, __lconv points to a static lconv structure containing
  50. *       C locale strings.  This structure is never used again if
  51. *       __init_monetary is called.
  52. *
  53. *Entry:
  54. *       None.
  55. *
  56. *Exit:
  57. *       0 success
  58. *       1 fail
  59. *
  60. *Exceptions:
  61. *
  62. *******************************************************************************/
  63.  
  64. int __cdecl __init_monetary (
  65.         void
  66.         )
  67. {
  68.         struct lconv *lc;
  69.  
  70.         if (__lc_handle[LC_MONETARY] != _CLOCALEHANDLE) {
  71.  
  72.                 /* Allocate structure filled with NULL pointers */
  73.                 if ((lc = (struct lconv *)
  74.                         _calloc_crt (1, sizeof(struct lconv))) == NULL)
  75.                         return 1;
  76.  
  77.                 if (_get_lc_lconv (lc)) {
  78.                         _free_lc_lconv (lc);
  79.                         _free_crt (lc);
  80.                         return 1;
  81.                 }
  82.  
  83.                 /* Copy numeric locale fields */
  84.                 lc->decimal_point = __lconv->decimal_point;
  85.                 lc->thousands_sep = __lconv->thousands_sep;
  86.                 lc->grouping = __lconv->grouping;
  87.  
  88.                 __lconv = lc;                   /* point to new one */
  89.                 _free_lc_lconv (__lconv_intl);  /* free the old one */
  90.                 _free_crt (__lconv_intl);
  91.                 __lconv_intl = lc;
  92.                 return 0;
  93.  
  94.         } else {
  95.                 /*
  96.                  *  Copy numeric locale fields (not necessarily C locale)
  97.                  *  to static structure.  Note that __lconv_c numeric locale
  98.                  *  fields may contain non-C locale information, but
  99.                  *  monetary locale fields always contain C locale info.
  100.                  */
  101.                 __lconv_c.decimal_point = __lconv->decimal_point;
  102.                 __lconv_c.thousands_sep = __lconv->thousands_sep;
  103.                 __lconv_c.grouping = __lconv->grouping;
  104.  
  105.                 __lconv = &__lconv_c;           /* point to new one */
  106.  
  107.                 _free_lc_lconv (__lconv_intl);  /* free the old one */
  108.                 _free_crt (__lconv_intl);
  109.                 __lconv_intl = NULL;
  110.                 return 0;
  111.         }
  112. }
  113.  
  114. static void fix_grouping(
  115.         char *grouping
  116.         )
  117. {
  118.         /*
  119.          * ANSI specifies that the fields should contain "\3" [\3\0] to indicate
  120.          * thousands groupings (100,000,000.00 for example).
  121.          * NT uses "3;0"; ASCII 3 instead of value 3 and the ';' is extra.
  122.          * So here we convert the NT version to the ANSI version.
  123.          */
  124.  
  125.         while (*grouping)
  126.         {
  127.             /* convert '3' to '\3' */
  128.             if (*grouping >= '0' && *grouping <= '9')
  129.             {
  130.                 *grouping = *grouping - '0';
  131.                 grouping++;
  132.             }
  133.  
  134.             /* remove ';' */
  135.             else if (*grouping == ';')
  136.             {
  137.                 char *tmp = grouping;
  138.  
  139.                 do
  140.                     *tmp = *(tmp+1);
  141.                 while (*++tmp);
  142.             }
  143.  
  144.             /* unknown (illegal) character, ignore */
  145.             else
  146.                 grouping++;
  147.         }
  148. }
  149.  
  150. /*
  151.  *  Get the lconv fields.
  152.  */
  153. static int __cdecl _get_lc_lconv (
  154.         struct lconv *l
  155.         )
  156. {
  157.         int ret = 0;
  158.  
  159.         /* Currency is country--not language--dependent.  NT work-around. */
  160.         LCID ctryid=MAKELCID(__lc_id[LC_MONETARY].wCountry, SORT_DEFAULT);
  161.  
  162.         if (l == NULL)
  163.                 return -1;
  164.  
  165.         ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SINTLSYMBOL, (void *)&l->int_curr_symbol);
  166.         ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SCURRENCY, (void *)&l->currency_symbol);
  167.         ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SMONDECIMALSEP, (void *)&l->mon_decimal_point);
  168.         ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SMONTHOUSANDSEP, (void *)&l->mon_thousands_sep);
  169.         ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SMONGROUPING, (void *)&l->mon_grouping);
  170.         fix_grouping(l->mon_grouping);
  171.  
  172.         ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SPOSITIVESIGN, (void *)&l->positive_sign);
  173.         ret |= __getlocaleinfo(LC_STR_TYPE, ctryid, LOCALE_SNEGATIVESIGN, (void *)&l->negative_sign);
  174.  
  175.         ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_IINTLCURRDIGITS, (void *)&l->int_frac_digits);
  176.         ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_ICURRDIGITS, (void *)&l->frac_digits);
  177.         ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_IPOSSYMPRECEDES, (void *)&l->p_cs_precedes);
  178.         ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_IPOSSEPBYSPACE, (void *)&l->p_sep_by_space);
  179.         ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_INEGSYMPRECEDES, (void *)&l->n_cs_precedes);
  180.         ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_INEGSEPBYSPACE, (void *)&l->n_sep_by_space);
  181.         ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_IPOSSIGNPOSN, (void *)&l->p_sign_posn);
  182.         ret |= __getlocaleinfo(LC_INT_TYPE, ctryid, LOCALE_INEGSIGNPOSN, (void *)&l->n_sign_posn);
  183.  
  184.         return ret;
  185. }
  186.  
  187. /*
  188.  *  Free the lconv strings.
  189.  *  Numeric values do not need to be freed.
  190.  */
  191. static void __cdecl _free_lc_lconv (
  192.         struct lconv *l
  193.         )
  194. {
  195.         if (l == NULL)
  196.                 return;
  197.  
  198.         if (l->int_curr_symbol != __lconv_static_null)
  199.         {
  200.                 _free_crt (l->int_curr_symbol);
  201.                 _free_crt (l->currency_symbol);
  202.                 _free_crt (l->mon_decimal_point);
  203.                 _free_crt (l->mon_thousands_sep);
  204.                 _free_crt (l->mon_grouping);
  205.                 _free_crt (l->positive_sign);
  206.                 _free_crt (l->negative_sign);
  207.         }
  208.         /* Don't need to make these pointers NULL */
  209. }
  210.