home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / locale.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  10.3 KB  |  598 lines

  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20.  * locale.c
  21.  * --------
  22.  * Implement FE functions to support xp_locale and other locale stuff
  23.  */
  24.  
  25.  
  26. #include <xplocale.h>
  27.  
  28. #include "xfe.h"
  29. #include "felocale.h"
  30. #include "csid.h"
  31.  
  32.  
  33. int16 fe_LocaleCharSetID = CS_LATIN1;
  34.  
  35. char fe_LocaleCharSetName[128] = { 0 };
  36.  
  37. int (*fe_collation_func)(const char *, const char *) = strcoll;
  38.  
  39.  
  40. void
  41. fe_InitCollation(void)
  42. {
  43.     /*
  44.      * Check to see if strcoll() is broken
  45.      */
  46.     if
  47.     (
  48.         ((strcoll("A", "B") < 0) && (strcoll("a", "B") >= 0)) ||
  49.  
  50.         /*
  51.          * Unlikely, but just in case...
  52.          */
  53.         ((strcoll("A", "B") > 0) && (strcoll("a", "B") <= 0)) ||
  54.         (strcoll("A", "B") == 0)
  55.     )
  56.     {
  57.         /*
  58.          * strcoll() is broken, so we use our own routine
  59.          */
  60.         fe_collation_func = strcasecomp;
  61.     }
  62. }
  63.  
  64.  
  65. int
  66. FE_StrColl(const char *s1, const char *s2)
  67. {
  68.     return (*fe_collation_func)(s1, s2);
  69. }
  70.  
  71.  
  72. size_t FE_StrfTime(MWContext *context, char *result, size_t maxsize,
  73.     int format, const struct tm *timeptr)
  74.  
  75. {
  76.     char    *fmt;
  77.  
  78.     switch (format)
  79.     {
  80.     case XP_TIME_FORMAT:
  81.         /* fmt = "%X"; */
  82.         fmt = "%H:%M";
  83.         break;
  84.     case XP_WEEKDAY_TIME_FORMAT:
  85.         /* fmt = "%a %X"; */
  86.         fmt = "%a %H:%M";
  87.         break;
  88.     case XP_DATE_TIME_FORMAT:
  89.         /* fmt = "%x %X"; */
  90.         fmt = "%x %H:%M";
  91.         break;
  92.     case XP_LONG_DATE_TIME_FORMAT:
  93.         fmt = "%c";
  94.         break;
  95.     default:
  96.         fmt = "%c";
  97.         break;
  98.     }
  99.  
  100.     return strftime(result, maxsize, fmt, timeptr);
  101. }
  102.  
  103.  
  104. char *
  105. fe_GetNormalizedLocaleName(void)
  106. {
  107.  
  108. #ifdef _HPUX_SOURCE
  109.  
  110.     int    len;
  111.     char    *locale;
  112.  
  113.     locale = setlocale(LC_CTYPE, NULL);
  114.     if (locale && *locale)
  115.     {
  116.         len = strlen(locale);
  117.     }
  118.     else
  119.     {
  120.         locale = "C";
  121.         len = 1;
  122.     }
  123.  
  124.     if
  125.     (
  126.         (!strncmp(locale, "/\x03:", 3)) &&
  127.         (!strcmp(&locale[len - 2], ";/"))
  128.     )
  129.     {
  130.         locale += 3;
  131.         len -= 5;
  132.     }
  133.  
  134.     locale = strdup(locale);
  135.     if (locale)
  136.     {
  137.         locale[len] = 0;
  138.     }
  139.  
  140.     return locale;
  141.  
  142. #else
  143.  
  144.     char    *locale;
  145.  
  146.     locale = setlocale(LC_CTYPE, NULL);
  147.     if (locale && *locale)
  148.     {
  149.         return strdup(locale);
  150.     }
  151.  
  152.     return strdup("C");
  153.  
  154. #endif
  155.  
  156. }
  157.  
  158.  
  159. unsigned char *
  160. fe_ConvertToLocaleEncoding(int16 charset, unsigned char *str)
  161. {
  162.     CCCDataObject    obj;
  163.     unsigned char    *le_string; /* Locally Encoded STRING */
  164.  
  165.     if ((charset == fe_LocaleCharSetID) || (!str) || (!*str))
  166.     {
  167.         return str;
  168.     }
  169.  
  170.     if (IS_UTF8_CSID(charset)) {
  171.         int32 le_len;
  172.         uint16 *ucs2_chars;
  173.         int32 num_ucs2_chars;
  174.  
  175.         /*
  176.          * Convert utf8 to ucs2
  177.          */
  178.         ucs2_chars = INTL_UTF8ToUCS2(str, &num_ucs2_chars);
  179.  
  180.         /*
  181.          * Convert ucs2 to local encoding
  182.          */
  183.         le_len = INTL_UnicodeToStrLen(fe_LocaleCharSetID, ucs2_chars, 
  184.                                                             num_ucs2_chars);
  185.         le_string = (unsigned char *)XP_ALLOC(le_len+1);
  186.         INTL_UnicodeToStr(fe_LocaleCharSetID, ucs2_chars, num_ucs2_chars,
  187.                     le_string, le_len);
  188.         le_string[le_len] = '\0'; /* null terminate */
  189.         XP_FREE(ucs2_chars);
  190.         return le_string;
  191.     }
  192.  
  193.     obj = INTL_CreateCharCodeConverter();
  194.     if (!obj)
  195.     {
  196.         return str;
  197.     }
  198.     if (INTL_GetCharCodeConverter(charset, fe_LocaleCharSetID, obj))
  199.     {
  200.         le_string = INTL_CallCharCodeConverter(obj, str,
  201.             strlen((char *) str));
  202.         if (!le_string)
  203.         {
  204.             le_string = str;
  205.         }
  206.     }
  207.     else
  208.     {
  209.         le_string = str;
  210.     }
  211.  
  212.     INTL_DestroyCharCodeConverter(obj);
  213.  
  214.     return le_string;
  215. }
  216.  
  217. /*
  218.  * fe_ConvertToXmString - convert text/encoding to XmString/XmFontList
  219.  * 
  220.  * NOTE: if the calling code does not yet set the XmFontList
  221.  * then pass in font==NULL
  222.  */
  223.  
  224. XmString
  225. fe_ConvertToXmString(unsigned char *str, int16 charset, 
  226.                         fe_Font font, XmFontType type, XmFontList *fontList_p)
  227. {
  228.     unsigned char    *loc;
  229.     XmString    xms;
  230.     XmFontList font_list;
  231.     XmFontListEntry    flentry;
  232.  
  233.     /*
  234.      * init default return values
  235.      */
  236.     *fontList_p = NULL;
  237.  
  238.     if ((!IS_UNICODE_CSID(charset)) || (!font)) {
  239.         loc = fe_ConvertToLocaleEncoding(charset, str);
  240.         if (loc)
  241.         {
  242.             xms = XmStringCreate((char *) loc, XmFONTLIST_DEFAULT_TAG);
  243.             if (loc != str)
  244.             {
  245.                 free(loc);
  246.             }
  247.         }
  248.         else
  249.         {
  250.             xms = NULL;
  251.         }
  252.  
  253.         if (font) {
  254.             flentry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG, type, font);
  255.             if (flentry) {
  256.                 font_list = XmFontListAppendEntry(NULL, flentry);
  257.                 if (font_list)
  258.                     *fontList_p = font_list;
  259.                 XmFontListEntryFree(&flentry);
  260.             }
  261.         }
  262.         return xms;
  263.  
  264.     }
  265.     else {
  266.         xms = fe_utf8_to_XmString(font, str, strlen(str), fontList_p);
  267.         return xms;
  268.     }
  269.  
  270.     return xms;
  271. }
  272.  
  273.  
  274. unsigned char *
  275. fe_ConvertFromLocaleEncoding(int16 charset, unsigned char *str)
  276. {
  277.     CCCDataObject    obj;
  278.     unsigned char    *ret;
  279.  
  280.  
  281.     if ((charset == fe_LocaleCharSetID) || (!str) || (!*str))
  282.     {
  283.         return str;
  284.     }
  285.  
  286.     /* handle UTF8 */
  287.     if (IS_UTF8_CSID(charset)) {
  288.         uint16 *ucs2_chars;
  289.         uint32 ucs2_buflen, num_ucs2_chars;
  290.         unsigned char *utf8p;
  291.  
  292.         /*
  293.          * Convert local encoding to ucs2
  294.          */
  295.         ucs2_buflen = INTL_StrToUnicodeLen(fe_LocaleCharSetID, str);
  296.         ucs2_chars = (uint16 *) XP_CALLOC(sizeof(uint16), ucs2_buflen+1);
  297.         num_ucs2_chars = INTL_StrToUnicode(fe_LocaleCharSetID, str,
  298.                                         ucs2_chars, ucs2_buflen);
  299.         utf8p = INTL_UCS2ToUTF8(ucs2_chars, num_ucs2_chars);
  300.         XP_FREE(ucs2_chars);
  301.         return utf8p;
  302.  
  303.     }
  304.  
  305.     obj = INTL_CreateCharCodeConverter();
  306.     if (!obj)
  307.     {
  308.         return str;
  309.     }
  310.     if (INTL_GetCharCodeConverter(fe_LocaleCharSetID, charset, obj))
  311.     {
  312.         ret = INTL_CallCharCodeConverter(obj, str,
  313.             strlen((char *) str));
  314.         if (!ret)
  315.         {
  316.             ret = str;
  317.         }
  318.     }
  319.     else
  320.     {
  321.         ret = str;
  322.     }
  323.  
  324.     INTL_DestroyCharCodeConverter(obj);
  325.  
  326.     return ret;
  327. }
  328.  
  329. /* fe_GetTextSelection() is a direct replacement for XmTextGetSelection --
  330.  * use XtFree() to free the returned string.
  331.  */
  332. char *
  333. fe_GetTextSelection(Widget widget)
  334. {
  335.     char    *loc;
  336.     char    *str;
  337.  
  338.     XP_ASSERT(XmIsText(widget) || XmIsTextField(widget));
  339.  
  340.     loc = NULL;
  341.     if (XmIsText(widget)) {
  342.         loc = XmTextGetSelection(widget);
  343.     }
  344.     else {
  345.         loc = XmTextFieldGetSelection(widget);
  346.     }
  347.     if (!loc)
  348.     {
  349.         return NULL;
  350.     }
  351.     str = (char *) fe_ConvertFromLocaleEncoding(
  352.         INTL_DefaultWinCharSetID(NULL), (unsigned char *) loc);
  353.     if (str == loc)
  354.     {
  355.         str = XtNewString(str);
  356.         if (!str)
  357.         {
  358.             return NULL;
  359.         }
  360.     }
  361.     XtFree(loc);
  362.  
  363.     return str;
  364. }
  365.  
  366.  
  367. /* fe_GetTextField() is a direct replacement for XmTextGetString --
  368.  * use XtFree() to free the returned string.
  369.  */
  370. char *
  371. fe_GetTextField(Widget widget)
  372. {
  373.     char    *loc;
  374.     char    *str;
  375.  
  376.     XP_ASSERT(XmIsText(widget) || XmIsTextField(widget));
  377.  
  378.     loc = NULL;
  379.     XtVaGetValues(widget, XmNvalue, &loc, 0);
  380.     if (!loc)
  381.     {
  382.         return NULL;
  383.     }
  384.     str = (char *) fe_ConvertFromLocaleEncoding(
  385.         INTL_DefaultWinCharSetID(NULL), (unsigned char *) loc);
  386.     if (str == loc)
  387.     {
  388.         str = XtNewString(str);
  389.         if (!str)
  390.         {
  391.             return NULL;
  392.         }
  393.     }
  394.     XtFree(loc);
  395.  
  396.     return str;
  397. }
  398.  
  399.  
  400. void
  401. fe_SetTextField(Widget widget, const char *str)
  402. {
  403.     unsigned char    *loc;
  404.  
  405.     XP_ASSERT(XmIsText(widget) || XmIsTextField(widget));
  406.  
  407.     if ((NULL==str) || ('\0'==*str)) {
  408.         XtVaSetValues(widget, XmNvalue, str, 0);
  409.         return;
  410.     }
  411.  
  412.     loc = fe_ConvertToLocaleEncoding(INTL_DefaultWinCharSetID(NULL),
  413.         (unsigned char *) str);
  414.     XtVaSetValues(widget, XmNvalue, loc, 0);
  415.     if (loc != ((unsigned char *) str))
  416.     {
  417.         XP_FREE(loc);
  418.     }
  419. }
  420.  
  421.  
  422. void
  423. fe_SetTextFieldAndCallBack(Widget widget, const char *str)
  424. {
  425.     unsigned char    *loc = NULL;
  426.  
  427.     XP_ASSERT(XmIsText(widget) || XmIsTextField(widget));
  428.  
  429.     if ((NULL != str) && ('\0' != *str)) {
  430.  
  431.         loc = fe_ConvertToLocaleEncoding(INTL_DefaultWinCharSetID(NULL),
  432.                                          (unsigned char *) str);
  433.     }
  434.  
  435.     /*
  436.      * Warning: on SGI, XtVaSetValues() doesn't run the
  437.      * valueChangedCallback, but XmTextFieldSetString() does.
  438.      */
  439.     if (XmIsText(widget))
  440.         XmTextSetString(widget, (char *) str);
  441.     else if (XmIsTextField(widget))
  442.         XmTextFieldSetString(widget, (char *) str);
  443.  
  444.     if (loc != ((unsigned char *) str))
  445.     {
  446.         XP_FREE(loc);
  447.     }
  448. }
  449.  
  450.  
  451. /*
  452.  * We link statically on AIX to force it to pick up our thread-safe malloc.
  453.  * But AIX has a bug where linking statically results in a broken mbstowcs
  454.  * (and wcstombs) being linked in. So we re-implement these here, so that
  455.  * these are used. See bug # 13574.
  456.  */
  457.  
  458. #ifdef AIXV3
  459.  
  460. size_t
  461. mbstowcs(wchar_t *pwcs, const char *s, size_t n)
  462. {
  463.     int    charlen;
  464.     size_t    inlen;
  465.     size_t    ret;
  466.     wchar_t    wc;
  467.  
  468.     if (!s)
  469.     {
  470.         return 0;
  471.     }
  472.  
  473.     ret = 0;
  474.     inlen = strlen(s) + 1;
  475.  
  476.     while (1)
  477.     {
  478.         wc = 0;
  479.         charlen = mbtowc(&wc, s, inlen);
  480.         if (charlen < 0)
  481.         {
  482.             return -1;
  483.         }
  484.         else if (charlen == 0)
  485.         {
  486.             if (pwcs)
  487.             {
  488.                 if (n > 0)
  489.                 {
  490.                     *pwcs = 0;
  491.                 }
  492.             }
  493.             break;
  494.         }
  495.         else
  496.         {
  497.             if (pwcs)
  498.             {
  499.                 if (n > 0)
  500.                 {
  501.                     *pwcs++ = wc;
  502.                     ret++;
  503.                     n--;
  504.                     if (n == 0)
  505.                     {
  506.                         break;
  507.                     }
  508.                 }
  509.                 else
  510.                 {
  511.                     break;
  512.                 }
  513.             }
  514.             else
  515.             {
  516.                 ret++;
  517.             }
  518.             inlen -= charlen;
  519.             s += charlen;
  520.         }
  521.     }
  522.  
  523.     return ret;
  524. }
  525.  
  526.  
  527. size_t
  528. wcstombs(char *s, const wchar_t *pwcs, size_t n)
  529. {
  530.     char    buf[MB_LEN_MAX];
  531.     int    charlen;
  532.     int    i;
  533.     size_t    ret;
  534.  
  535.     if (!pwcs)
  536.     {
  537.         return 0;
  538.     }
  539.  
  540.     ret = 0;
  541.  
  542.     while (1)
  543.     {
  544.         buf[0] = 0;
  545.         charlen = wctomb(buf, *pwcs);
  546.         if (charlen <= 0)
  547.         {
  548.             return -1;
  549.         }
  550.         else
  551.         {
  552.             if (s)
  553.             {
  554.                 if (n >= charlen)
  555.                 {
  556.                     for (i = 0; i < charlen; i++)
  557.                     {
  558.                         *s++ = buf[i];
  559.                     }
  560.                     if (*pwcs)
  561.                     {
  562.                         ret += charlen;
  563.                     }
  564.                     else
  565.                     {
  566.                         break;
  567.                     }
  568.                     n -= charlen;
  569.                     if (n == 0)
  570.                     {
  571.                         break;
  572.                     }
  573.                 }
  574.                 else
  575.                 {
  576.                     break;
  577.                 }
  578.             }
  579.             else
  580.             {
  581.                 if (*pwcs)
  582.                 {
  583.                     ret += charlen;
  584.                 }
  585.                 else
  586.                 {
  587.                     break;
  588.                 }
  589.             }
  590.             pwcs++;
  591.         }
  592.     }
  593.  
  594.     return ret;
  595. }
  596.  
  597. #endif /* AIXV3 */
  598.