home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / S12409.ZIP / NLSINFO.C < prev    next >
C/C++ Source or Header  |  1989-09-15  |  15KB  |  503 lines

  1. /*
  2.  *
  3.  *  SCCSID: @(#)nlsinfo.c -- display localization information
  4.  * 
  5.  *  This program displays most of the NLS (national language
  6.  *  support) features of OS/2. It uses the Family API services
  7.  *  DosGetCntryInfo(), DosGetCollate(), and DosGetCp() to obtain 
  8.  *  various locale-dependent information. 
  9.  *  
  10.  *  In addition to the information returned by these three FAPI
  11.  *  services, this program also has created a table of information
  12.  *  based on DOS and OS/2 user documentation to give more 
  13.  *  information about the localized environment. For example, see 
  14.  *  the COUNTRYNAME table. This table can easily become outdated,
  15.  *  as the table is not in the operating system; refer to MS-DOS 
  16.  *  and OS/2 user documentation for the latest information. 
  17.  *  
  18.  *  The compile instructions for this program are:
  19.  *  
  20.  *      cl /Lp /Fb /W3 nlsinfo.c
  21.  *  
  22.  *  which will result in a dual-mode NLSINFO.EXE file which can 
  23.  *  be run in DOS (3.3 or above) real mode or OS/2 protect mode.
  24.  *  
  25.  *  The runtime command line usage of this program is:
  26.  *  
  27.  *      nlsinfo <countrycode> <codepage>
  28.  * 
  29.  *  where <countrycode> is a valid country code and <codepage>
  30.  *  is a valid codepage. If these values are both omitted, the
  31.  *  program uses the default values of 0 for each, which uses
  32.  *  the current country and codepage information for the current
  33.  *  process. See the batch files NLSTEST.CMD and NLSTEST.BAT for 
  34.  *  examples of how to invoke NLSINFO.EXE.
  35.  *
  36.  *  [Remember, when using DOS, the program NLSFUNC must be running
  37.  *  if you want to obtain NLS-related information for any country 
  38.  *  but the current (default) one. No similar precaution is 
  39.  *  required when running OS/2.]
  40.  *
  41.  *  Copyright (C) 1988 Microsoft Corporation 
  42.  *
  43.  *  This software is provided for demonstration purposes only.
  44.  *  Microsoft makes no warranty, either express or implied as
  45.  *  to its usability in any given situation.
  46.  *
  47.  */
  48.  
  49. /* ------------------------------------------------------------------------ */
  50.  
  51. /* include files */
  52.  
  53. #define INCL_DOS
  54. #define INCL_DOSNLS
  55. #include <os2.h>
  56.  
  57. #include <stdio.h>
  58. #include <stdlib.h>
  59.  
  60. /* ------------------------------------------------------------------------ */
  61.  
  62. /* hard-coded country ASCIIZ names (not accessable from an OS/2 API) */
  63.  
  64. typedef struct {
  65.     USHORT usCountry;                                   /* the country code */
  66.     USHORT usCodepagePrimary;         /* country's default/primary codepage */
  67.     USHORT usCodepageSecondary;      /* country's backup/secondary codepage */
  68.     PSZ pszName;                                        /* the country name */
  69. } COUNTRYNAME;
  70.  
  71. /*
  72.  * 
  73.  * NOTE: Many of the countries in this list (especially the far and 
  74.  *       middle eastern Europe countries) are not supported in the 
  75.  *       USA domestic releases of OS/2 and DOS. They are listed 
  76.  *       because some localized versions of DOS 4.0 and OS/2 may 
  77.  *       support these countries. Refer to the OS/2 documentation 
  78.  *       for a list of the supported countries.
  79.  *
  80.  *       In this table, a value of 9999 is used internally to 
  81.  *       this program as an invalid country; this value does not 
  82.  *       have this special significance by OS/2 or DOS.
  83.  *
  84.  */
  85.  
  86. COUNTRYNAME vctrynm[] =
  87. {
  88.     {   0, 437, 850, "United States"             },    
  89.     {   1, 437, 850, "United States"             },    
  90.     {   2, 863, 850, "Canada (French)"           },
  91.     {   3, 850, 437, "Latin America"             },
  92.     {  31, 437, 850, "Netherlands"               },
  93.     {  32, 850, 437, "Belgium"                   },
  94.     {  33, 437, 850, "France"                    },
  95.     {  34, 850, 437, "Spain"                     },
  96.     {  39, 437, 850, "Italy"                     },
  97.     {  41, 850, 437, "Switzerland"               },
  98.     {  44, 437, 850, "United Kingdom"            },
  99.     {  45, 850, 865, "Denmark"                   },
  100.     {  46, 437, 850, "Sweden"                    },
  101.     {  47, 850, 865, "Norway"                    },
  102.     {  49, 437, 850, "Germany"                   },
  103.     {  61, 437, 850, "Australia"                 },
  104.     {  81, 932, 437, "Japan"                     },
  105.     {  82, 934, 437, "Korea"                     },
  106.     {  86, 936, 437, "Peoples Republic of China" },
  107.     {  88, 938, 437, "Taiwan"                    },
  108.     { 351, 850, 860, "Portugal"                  },
  109.     { 358, 850, 437, "Finland"                   },
  110.     { 785, 864, 850, "Saudi Arabia"              },
  111.     { 972, 862, 850, "Israel"                    },
  112.     {9999, 000, 000, "Unknown"                   }
  113. };
  114.  
  115. #define iMAXCOUNTRYNAME (sizeof(vctrynm) / sizeof(COUNTRYNAME))
  116. #define iINVALID_COUNTRYNAME 9999        /* invalid country name/code */
  117.  
  118. /* ------------------------------------------------------------------------ */
  119.  
  120. /* function prototypes */
  121.  
  122. int main(int argc, char *argv[]);
  123. void DisplayCountryInfo(COUNTRYINFO ctryi);
  124. void TestErrorCode(USHORT usError, char *pszApiName);
  125. void DisplayCollateInfo(CHAR acCollate[], USHORT usSize);
  126. void ValidateCountryCode(USHORT usCountry);
  127. void ValidateCodepage(USHORT usCodepage);
  128. COUNTRYNAME FindCountryName(USHORT usCountry);
  129. void DisplayCountryName(USHORT usCountry);
  130.  
  131. /* ------------------------------------------------------------------------ */
  132.  
  133. /*
  134.  *
  135.  * main()
  136.  *
  137.  * The main program.
  138.  *
  139.  */
  140.  
  141. int main(int argc, char *argv[])
  142. {
  143.  
  144.     USHORT usErrorCode;       /* generic OS/2 API return code */
  145.     COUNTRYCODE ctryc;        /* DosGetCntryInfo() input buffer */
  146.     COUNTRYINFO ctryi;        /* DosGetCntryInfo() output buffer */
  147.     USHORT usCtryI;           /* sizeof the COUNTRYINFO structure */
  148.     CHAR acCollateTbl[256];   /* collating table buffer */
  149.     USHORT usCollateTblSize;  /* size of collating table buffer */
  150.     USHORT rgusCpList[50];    /* the codepage table */
  151.     USHORT cbCpList;          /* the size of the codepage table (bytes) */
  152.     USHORT usActiveCp;        /* the active codepage */
  153.     int i;                    /* loop index (for codepage table) */
  154.  
  155.     /* specify the country/codepage to use */
  156.     if (argc == 3)
  157.     {
  158.         /* user entered country and codepage on command line */
  159.         ctryc.country = atoi(argv[1]);
  160.         ctryc.codepage = atoi(argv[2]);
  161.         ValidateCountryCode(ctryc.country);
  162.         ValidateCodepage(ctryc.codepage);
  163.     }
  164.     else if (argc == 1)
  165.     {
  166.         /* user didn't enter anything; silently assume defaults */
  167.         ctryc.country = 0;                       /* use the default country */
  168.         ctryc.codepage = 0;                     /* use the current codepage */
  169.     }
  170.     else
  171.     {
  172.         /* user is confused; give them help then terminate */
  173.         printf("usage: nlsinfo <countrycode> <codepage>\n");
  174.         exit(1);
  175.     }
  176.  
  177.     printf("\n\n%s NLS information for codepage %d and country %d.\n\n",
  178.         (_osmajor < 10 ? "DOS" : "OS/2"), ctryc.codepage, ctryc.country);
  179.  
  180.     /* get the current codepage */
  181.     usErrorCode = DosGetCp(sizeof(rgusCpList), rgusCpList, &cbCpList);
  182.     TestErrorCode(usErrorCode, "DosGetCp");
  183.  
  184.     /* get/validate the active codepage */
  185.     usActiveCp = rgusCpList[0];
  186.     printf("Active codepage:     %d\n", usActiveCp);
  187.     ValidateCodepage(usActiveCp);
  188.  
  189.     printf("Prepared codepages:  ");
  190.     /* loop through each codepage, a word at a time */
  191.     for (i = 0; i < (cbCpList/2); i++)
  192.     {
  193.         printf("%d  ", rgusCpList[i]);
  194.         ValidateCodepage(rgusCpList[i]);
  195.     }
  196.     printf("\n\n");
  197.  
  198.     /* get/display country information */
  199.     usErrorCode = DosGetCtryInfo(sizeof(COUNTRYINFO), &ctryc, &ctryi, &usCtryI);
  200.     TestErrorCode(usErrorCode, "DosGetCtryInfo");
  201.     DisplayCountryName(ctryi.country);          /* get/display country name */
  202.     DisplayCountryInfo(ctryi);
  203.  
  204.     /* get/display collating table information */
  205.     usErrorCode = DosGetCollate(sizeof(acCollateTbl), &ctryc, acCollateTbl,
  206.         &usCollateTblSize);
  207.     TestErrorCode(usErrorCode, "DosGetCollate");
  208.     DisplayCollateInfo(acCollateTbl, usCollateTblSize);
  209.  
  210.     /* get/display dbcs table information */
  211.  
  212.     /* get/display codepage information */
  213.  
  214.     exit(0);
  215.     return (0);
  216.  
  217. } /* main */
  218.  
  219. /* ------------------------------------------------------------------------ */
  220.  
  221. /*
  222.  *
  223.  * DisplayCountryInfo()
  224.  *
  225.  * Displays information obtained from the DosGetCtryInfo API.
  226.  *
  227.  */
  228.  
  229. void DisplayCountryInfo(COUNTRYINFO ctryi)
  230. {
  231.  
  232.     /* display the country information */
  233.     printf("Country code:        %03d\n", ctryi.country);
  234.  
  235.     printf("Date separator:      %s\n",   ctryi.szDateSeparator);
  236.  
  237.     switch (ctryi.fsDateFmt)
  238.     {
  239.         case DATEFMT_MM_DD_YY:
  240.             printf("Date format:         MM%sDD%sYY\n",
  241.                    ctryi.szDateSeparator, ctryi.szDateSeparator,
  242.                    ctryi.szDateSeparator);
  243.             break;
  244.  
  245.         case DATEFMT_DD_MM_YY:
  246.             printf("Date format:         DD%sMM%sYY\n",
  247.                    ctryi.szDateSeparator, ctryi.szDateSeparator,
  248.                    ctryi.szDateSeparator);
  249.             break;
  250.  
  251.         case DATEFMT_YY_MM_DD:
  252.             printf("Date format:         YY%sMM%sDD\n",
  253.                    ctryi.szDateSeparator, ctryi.szDateSeparator,
  254.                    ctryi.szDateSeparator);
  255.             break;
  256.     }
  257.  
  258.     printf("Time separator:      %s\n",   ctryi.szTimeSeparator);
  259.  
  260.     printf("Clock type:          %s\n",
  261.          (ctryi.fsTimeFmt == 0x0001 ? "12 hour clock" : "24 hour clock"));
  262.  
  263.     printf("Currency symbol:     %s\n",   ctryi.szCurrency);
  264.  
  265.     printf("Currency places:     %d\n",   ctryi.cDecimalPlace);
  266.  
  267. /*
  268.  * 
  269.  * NOTE: The following switch statement needs to be modified to 
  270.  *       support the CURRENCY_FOLLOW and CURRENCY_SPACE naming 
  271.  *       conventions as defined in BSEDOS.H. It works as it is, 
  272.  *       but would be better if using the provided #definitions.
  273.  *
  274.  */
  275.     switch (ctryi.fsCurrencyFmt)
  276.     {
  277.         case 0:
  278.             printf("Currency rule:       currency symbol precedes the value\n");
  279.             printf("Currency rule:       no spaces between symbol and value\n");
  280.             break;
  281.  
  282.         case 1:
  283.             printf("Currency rule:       currency symbol follows the value\n");
  284.             printf("Currency rule:       no spaces between symbol and value\n");
  285.             break;
  286.  
  287.         case 2:
  288.             printf("Currency rule:       currency symbol precedes the value\n");
  289.             printf("Currency rule:       one space between symbol and value\n");
  290.             break;
  291.  
  292.         case 3:
  293.             printf("Currency rule:       currency symbol follows the value\n");
  294.             printf("Currency rule:       one space between symbol and value\n");
  295.             break;
  296.  
  297.         case CURRENCY_DECIMAL:
  298.             printf("Currency rule:       currency symbol replaces decimal separator\n");
  299.             break;
  300.     }
  301.  
  302.     printf("Decimal separator:   %s\n",   ctryi.szDecimal);
  303.  
  304.     printf("Thousands separator: %s\n",   ctryi.szThousandsSeparator);
  305.  
  306.     printf("Data separator:      %s\n",   ctryi.szDataSeparator);
  307.  
  308. } /* DisplayCountryInfo */
  309.  
  310. /* ------------------------------------------------------------------------ */
  311.  
  312. /*
  313.  *
  314.  * DisplayCollateInfo()
  315.  *
  316.  * Displays information obtained from the DosGetCollate API.
  317.  *
  318.  */
  319.  
  320. void DisplayCollateInfo(CHAR acCollate[], USHORT usSize)
  321. {
  322.  
  323.     register int i;
  324.  
  325.     printf("\nCollating table has %d characters:\n\n", usSize);
  326.     for (i = 0; i < usSize; i++)
  327.     {
  328.         printf("%4d%s", acCollate[i],
  329.             (i % 8 == 7 || i == usSize - 1) ? "\n" : ", "); /* see K&R p48 */
  330.     }
  331.  
  332. } /* DisplayCollateInfo */
  333.  
  334. /* ------------------------------------------------------------------------ */
  335.  
  336. /*
  337.  *
  338.  * DisplayCountryName()
  339.  *
  340.  * Displays information obtained from our hard-coded table.
  341.  *
  342.  */
  343.  
  344. void DisplayCountryName(USHORT usCountry)
  345. {
  346.  
  347.     COUNTRYNAME ctrynm;
  348.  
  349.     /* display the country name from our lookup table */
  350.     ctrynm = FindCountryName(usCountry);
  351.     if (usCountry == iINVALID_COUNTRYNAME)
  352.     {
  353.         printf("This country's name is unknown!\n");
  354.     }
  355.     else
  356.     {
  357.         printf("Country name:        %s\n", ctrynm.pszName);
  358.         printf("Primary codepage:    %03d\n", ctrynm.usCodepagePrimary);
  359.         printf("Secondary codepage:  %03d\n", ctrynm.usCodepageSecondary);
  360.     }
  361.  
  362. } /* DisplayCountryName */
  363.  
  364. /* ------------------------------------------------------------------------ */
  365.  
  366. /*
  367.  *
  368.  * FindCountryName()
  369.  *
  370.  * Find the country name/mnemonic from our hard-coded table.
  371.  *
  372.  */
  373.  
  374. COUNTRYNAME FindCountryName(USHORT usCountry)
  375. {
  376.     register int i;
  377.  
  378.     /* this lookup algorithm is unefficient... */
  379.     for (i = 0; i < iMAXCOUNTRYNAME; i++)
  380.     {
  381.         if (usCountry == vctrynm[i].usCountry)
  382.         {
  383.             return (vctrynm[i]);
  384.         }
  385.     }
  386.  
  387.     return (vctrynm[iINVALID_COUNTRYNAME]);
  388.  
  389. } /* FindCountryName */
  390.  
  391. /* ------------------------------------------------------------------------ */
  392.  
  393. /*
  394.  *
  395.  * ValidateCountryCode()
  396.  *
  397.  * Verifies that the given country code is a valid one.
  398.  *
  399.  */
  400.  
  401. void ValidateCountryCode(USHORT usCountry)
  402. {
  403.  
  404.     switch (usCountry)
  405.     {
  406.         case   0: /* this is only here since 0 means default */
  407.         case   1:
  408.         case   2:
  409.         case   3:
  410.         case  31:
  411.         case  32:
  412.         case  33:
  413.         case  34:
  414.         case  39:
  415.         case  41:
  416.         case  44:
  417.         case  45:
  418.         case  46:
  419.         case  47:
  420.         case  49:
  421.         case  61:
  422.         case  81:
  423.         case  82:
  424.         case  86:
  425.         case  88:
  426.         case 351:
  427.         case 358:
  428.         case 785:
  429.         case 972:
  430.             /* these are all known country codes */
  431.             return;
  432.             break;
  433.  
  434.         default:
  435.             printf("Error, invalid country code %d\n", usCountry);
  436.             exit(1);
  437.             break;
  438.     }
  439.  
  440. } /* ValidateCountryCode */
  441.  
  442. /* ------------------------------------------------------------------------ */
  443.  
  444. /*
  445.  *
  446.  * ValidateCodepage()
  447.  *
  448.  * Verifies that the given codepage is a valid one.
  449.  *
  450.  */
  451.  
  452. void ValidateCodepage(USHORT usCodepage)
  453. {
  454.  
  455.     switch (usCodepage)
  456.     {
  457.         case   0: /* this is only here since 0 means default */
  458.         case 437:
  459.         case 850:
  460.         case 860:
  461.         case 862:
  462.         case 863:
  463.         case 864:
  464.         case 865:
  465.         case 932:
  466.         case 934:
  467.         case 936:
  468.         case 938:
  469.             /* these are all known codepages */
  470.             return;
  471.             break;
  472.  
  473.         default:
  474.             printf("Error, invalid codepage %d\n", usCodepage);
  475.             exit(1);
  476.             break;
  477.     }
  478.  
  479. } /* ValidateCodepage */
  480.  
  481. /* ------------------------------------------------------------------------ */
  482.  
  483. /*
  484.  *
  485.  * TestErrorCode()
  486.  *
  487.  * Tests an OS/2 API return code, and terminates if nonzero/unsuccessful.
  488.  *
  489.  */
  490.  
  491. void TestErrorCode(USHORT usError, char *pszApiName)
  492. {
  493.  
  494.     if (usError != 0)
  495.     {
  496.         printf("  %s failed with code %d!\n", pszApiName, usError);
  497.         exit(1);
  498.     }
  499.  
  500. } /* TestErrorCode */
  501.  
  502. /* ------------------------------------------------------------------------ */
  503.