home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icuapps / locexp / util / lx_utils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-22  |  21.0 KB  |  859 lines

  1. #include "lx_utils.h"
  2.  
  3. /* Realloc broken on linux????? */
  4. void *my_realloc(void *ptr, size_t old, size_t size)
  5. {
  6.   void *newptr;
  7.  
  8.   newptr = malloc(size);
  9.   if(ptr)
  10.     memcpy(newptr,ptr,old);
  11.   return newptr;
  12. }
  13.  
  14. /******************************************************** derived from ucnv_err.c */
  15. #define ToOffset(a) ((a)<=9?(0x0030+(a)):(0x0030+(a)+7))
  16.  
  17. /*Takes a int32_t and fills in  a UChar* string with that number "radix"-based
  18.  * and padded with "pad" zeroes
  19.  */
  20. static void 
  21.   itou (UChar * buffer, int32_t i, int32_t radix, int32_t pad)
  22. {
  23.   int32_t length = 0;
  24.   int32_t num = 0;
  25.   int8_t digit;
  26.   int32_t j;
  27.   UChar temp;
  28.  
  29.   while (i > radix)
  30.     {
  31.       num = i / radix;
  32.       digit = (int8_t) (i - num * radix);
  33.       buffer[length++] = (UChar) (ToOffset (digit));
  34.       i = num;
  35.     }
  36.  
  37.   buffer[length] = (UChar) (ToOffset (i));
  38.  
  39.   while (length < pad)
  40.     buffer[++length] = (UChar) 0x0030;    /*zero padding */
  41.   buffer[length--] = (UChar) 0x0000;
  42.  
  43.   /*Reverses the string */
  44.   for (j = 0; j < (pad / 2); j++)
  45.     {
  46.       temp = buffer[length - j];
  47.       buffer[length - j] = buffer[j];
  48.       buffer[j] = temp;
  49.     }
  50.  
  51.   return;
  52. }
  53.  
  54. void 
  55. UCNV_FROM_U_CALLBACK_BACKSLASH_ESCAPE_HTML  (UConverter * _this,
  56.                         char **target,
  57.                         const char *targetLimit,
  58.                         const UChar ** source,
  59.                         const UChar * sourceLimit,
  60.                         int32_t *offsets,
  61.                         bool_t flush,
  62.                         UErrorCode * err)
  63. {
  64.   UChar valueString[100];
  65.   int32_t valueStringLength = 0;
  66.   UChar codepoint[100];
  67.   int32_t i = 0;
  68.   /*Makes a bitwise copy of the converter passwd in */
  69.   UConverter myConverter = *_this;
  70.   char myTarget[100];
  71.   char *myTargetAlias = myTarget;
  72.   const UChar *myValueSource = NULL;
  73.   UErrorCode err2 = U_ZERO_ERROR;
  74.  
  75.  
  76.   if (CONVERSION_U_SUCCESS (*err))
  77.     return;
  78.  
  79.   ucnv_reset (&myConverter);
  80.   ucnv_setFromUCallBack (&myConverter,
  81.              (UConverterFromUCallback) UCNV_FROM_U_CALLBACK_STOP,
  82.              &err2);
  83.   if (U_FAILURE (err2))
  84.     {
  85.       *err = err2;
  86.       return;
  87.     }
  88.   u_uastrcpy(codepoint,"<B>\\u");
  89.  
  90.   while (i < _this->invalidUCharLength)
  91.     {
  92.       itou (codepoint + 5, _this->invalidUCharBuffer[i++], 16, 4);
  93.       u_uastrcpy(codepoint+9, "</B>");
  94.       memcpy (valueString + valueStringLength, codepoint, sizeof (UChar) * (5+4+4) );
  95.       valueStringLength += (5+4+4) ;
  96.     }
  97.  
  98.   myValueSource = valueString;
  99.  
  100.   /*converts unicode escape sequence */
  101.   ucnv_fromUnicode (&myConverter,
  102.             &myTargetAlias,
  103.             myTargetAlias + 100,
  104.             &myValueSource,
  105.             myValueSource + (5+4+4),
  106.             NULL,
  107.             TRUE,
  108.             &err2);
  109.  
  110.   if (U_FAILURE (err2))
  111.     {
  112.       UCNV_FROM_U_CALLBACK_SUBSTITUTE (_this,
  113.                        target,
  114.                        targetLimit,
  115.                        source,
  116.                        sourceLimit,
  117.                        offsets,
  118.                        flush,
  119.                        err);
  120.       return;
  121.     }
  122.  
  123.   valueStringLength = myTargetAlias - myTarget;
  124.  
  125.   /*if we have enough space on the output buffer we just copy
  126.    * the subchar there and update the pointer
  127.    */
  128.   if ((targetLimit - *target) >= valueStringLength)
  129.     {
  130.       memcpy (*target, myTarget, valueStringLength);
  131.       *target += valueStringLength;
  132.       *err = U_ZERO_ERROR;
  133.     }
  134.   else
  135.     {
  136.       /*if we don't have enough space on the output buffer
  137.        *we copy as much as we can to it, update that pointer.
  138.        *copy the rest in the internal buffer, and increase the
  139.        *length marker
  140.        */
  141.       memcpy (*target, valueString, (targetLimit - *target));
  142.       memcpy (_this->charErrorBuffer + _this->charErrorBufferLength,
  143.           valueString + (targetLimit - *target),
  144.           valueStringLength - (targetLimit - *target));
  145.       _this->charErrorBufferLength += valueStringLength - (targetLimit - *target);
  146.       *target += (targetLimit - *target);
  147.       *err = U_INDEX_OUTOFBOUNDS_ERROR;
  148.     }
  149.  
  150.   return;
  151. }
  152.  
  153. void 
  154. UCNV_FROM_U_CALLBACK_BACKSLASH_ESCAPE (UConverter * _this,
  155.                   char **target,
  156.                   const char *targetLimit,
  157.                   const UChar ** source,
  158.                   const UChar * sourceLimit,
  159.                   int32_t *offsets,
  160.                   bool_t flush,
  161.                   UErrorCode * err)
  162. {
  163.   UChar valueString[100];
  164.   int32_t valueStringLength = 0;
  165.   UChar codepoint[100];
  166.   int32_t i = 0;
  167.   /*Makes a bitwise copy of the converter passwd in */
  168.   UConverter myConverter = *_this;
  169.   char myTarget[100];
  170.   char *myTargetAlias = myTarget;
  171.   const UChar *myValueSource = NULL;
  172.   UErrorCode err2 = U_ZERO_ERROR;
  173.  
  174.  
  175.   if (CONVERSION_U_SUCCESS (*err))
  176.     return;
  177.  
  178.   ucnv_reset (&myConverter);
  179.   ucnv_setFromUCallBack (&myConverter,
  180.              (UConverterFromUCallback) UCNV_FROM_U_CALLBACK_STOP,
  181.              &err2);
  182.   if (U_FAILURE (err2))
  183.     {
  184.       *err = err2;
  185.       return;
  186.     }
  187.   u_uastrcpy(codepoint,"\\u");
  188.  
  189.   while (i < _this->invalidUCharLength)
  190.     {
  191.       itou (codepoint + 2, _this->invalidUCharBuffer[i++], 16, 4);
  192.       memcpy (valueString + valueStringLength, codepoint, sizeof (UChar) * (2+4) );
  193.       valueStringLength += (2+4) ;
  194.     }
  195.  
  196.   myValueSource = valueString;
  197.  
  198.   /*converts unicode escape sequence */
  199.   ucnv_fromUnicode (&myConverter,
  200.             &myTargetAlias,
  201.             myTargetAlias + 100,
  202.             &myValueSource,
  203.             myValueSource + (2+4),
  204.             NULL,
  205.             TRUE,
  206.             &err2);
  207.  
  208.   if (U_FAILURE (err2))
  209.     {
  210.       UCNV_FROM_U_CALLBACK_SUBSTITUTE (_this,
  211.                        target,
  212.                        targetLimit,
  213.                        source,
  214.                        sourceLimit,
  215.                        offsets,
  216.                        flush,
  217.                        err);
  218.       return;
  219.     }
  220.  
  221.   valueStringLength = myTargetAlias - myTarget;
  222.  
  223.   /*if we have enough space on the output buffer we just copy
  224.    * the subchar there and update the pointer
  225.    */
  226.   if ((targetLimit - *target) >= valueStringLength)
  227.     {
  228.       memcpy (*target, myTarget, valueStringLength);
  229.       *target += valueStringLength;
  230.       *err = U_ZERO_ERROR;
  231.     }
  232.   else
  233.     {
  234.       /*if we don't have enough space on the output buffer
  235.        *we copy as much as we can to it, update that pointer.
  236.        *copy the rest in the internal buffer, and increase the
  237.        *length marker
  238.        */
  239.       memcpy (*target, valueString, (targetLimit - *target));
  240.       memcpy (_this->charErrorBuffer + _this->charErrorBufferLength,
  241.           valueString + (targetLimit - *target),
  242.           valueStringLength - (targetLimit - *target));
  243.       _this->charErrorBufferLength += valueStringLength - (targetLimit - *target);
  244.       *target += (targetLimit - *target);
  245.       *err = U_INDEX_OUTOFBOUNDS_ERROR;
  246.     }
  247.  
  248.   return;
  249. }
  250. /*******************************************************end of borrowed code from ucnv_err.c **/
  251.  
  252.  
  253.  
  254. void doDecodeQueryField(const char *in, char *out, int32_t length)
  255. {
  256.   unsigned int i;
  257.   char *anchor;
  258.  
  259.   anchor = out;
  260.   if(length == -1)
  261.     length = strlen(in);
  262.  
  263.   for(i=0;i<length;i++)
  264.     {
  265.       if(in[i] == '+')
  266.     {
  267.       *(out++) = ' ';
  268.       continue;
  269.     }
  270.       else if(in[i] == '%')
  271.     {
  272.       if(in[i+1] == '%') /* & */
  273.         {
  274.           *(out++) = '%';
  275.           continue;
  276.         }
  277.       if((length-i) < 2)
  278.         {
  279.           break;
  280.         }
  281.       {
  282.         char tmp2[3];
  283.         unsigned int asciiValue;
  284.         tmp2[(unsigned int)0] = in[i+1];
  285.         tmp2[(unsigned int)1] = in[i+2];
  286.         tmp2[(unsigned int)2] = 0;
  287.         
  288.         
  289.         /* & */
  290.         sscanf(tmp2,"%x",&asciiValue);
  291.         
  292.         *(out++) = (unsigned char)asciiValue;
  293.         
  294.         i += 2;
  295.       }
  296.     }
  297.       else
  298.     *(out++) = in[i];
  299.     }
  300.   /* & */
  301.   *(out++) = 0;
  302. }
  303.  
  304. /**
  305.  * Unescape [changes \uXXXX -> U+XXXX, \\ -> U+005C (\)]
  306.  * DOES NOT null terminate.
  307.  * @param chars  target chars. must be big enough.
  308.  * @param src    source chars. 
  309.  * @param origLen # of chars to copy from the source.  If -1, src is assumed to be null terminated
  310.  * @return number of chars copied into 'chars'. 
  311.  */
  312.  
  313. int32_t copyWithUnescaping( UChar* chars, const UChar* src, int32_t origLen)
  314. {
  315.   /* if we wanted to we could do diacrits and junk here. Or whatever. */
  316.   UChar *dst = chars;
  317.  
  318.   if(origLen == -1)
  319.      origLen == u_strlen(src); /* but we don't null terminate still */
  320.  
  321.   while(origLen--)
  322.     {
  323.       if((src[0] == '\\') && (src[1] == 'u'))
  324.     {
  325.       static const int pv[] = { 0x0000, 0x0001, 0x0010, 0x0100, 0x1000 }; /* place value */
  326.       UChar out = 0;
  327.       int32_t max;
  328.       
  329.       src += 2;
  330.       origLen -= 2;
  331.       for(max=4;*src && (max>0);max--)
  332.         {
  333.           char from2 = tolower(*src);
  334.           if((from2 >= '0') && (from2 <= '9'))
  335.         {
  336.           int32_t digitval = 0x0 + from2 - '0';
  337.           out += digitval * pv[max];
  338.           /* printf("** multiplying %c@%d %x*%x\n",from2,max,digitval,pv[max]); */
  339.         }
  340.           else if((from2 >= 'a') && (from2 <= 'f'))
  341.         {
  342.           int32_t digitval = 0xa + from2 - 'a';        
  343.           out += digitval * pv[max];
  344.         }
  345.           src++;
  346.           origLen--;
  347.         }
  348.       src--;
  349.       origLen++;
  350.  
  351.       *(dst++) = out;
  352.     }
  353.       else
  354.     {
  355.       *(dst++) = *src;
  356.     }
  357.     
  358.       src++;
  359.     }
  360.  
  361.   return dst-chars;
  362. }
  363.  
  364. /*
  365.    ===================================== MySortable stuff follows ==========
  366. */
  367.  
  368. /** 
  369.  * Initialize a MySortable with the specified locale. Will reset all fields.
  370.  * TODO: limit displayname to just a part (default -> English -> United States -> California, instead of   .... -> English (United States) -> ... 
  371.  * @param s The MySortable struct to initialize
  372.  * @param locid The Locale that the MySortable should refer to
  373.  * @param inLocale The Locale which the MySortable's display name should be displayed 
  374.  * @param parent   Parent MySortable
  375.  */
  376.  
  377. void initSortable(MySortable *s, const char *locid, const char *inLocale, MySortable *parent)
  378. {
  379.   UErrorCode status = U_ZERO_ERROR;
  380.   int32_t siz;
  381.   s->str = strdup(locid);
  382.  
  383.   /*
  384.    * OLD CODE:
  385.  
  386.      siz = uloc_getDisplayName(s->str,NULL, NULL, 0, &status);
  387.      s->ustr = malloc((siz+1) * sizeof(UChar));
  388.      ((UChar*)(s->ustr)) [0] = 0;
  389.      status = U_ZERO_ERROR;
  390.      uloc_getDisplayName( (s->str) , inLocale, (UChar*)(s->ustr), siz, &status);
  391.   * Now, we want to print the 'most leaf' string.. 
  392.   */
  393.   
  394.   status = U_ZERO_ERROR; /* check for variant */
  395.  
  396.   if( (siz = uloc_getDisplayVariant( s->str, inLocale, NULL, 0, &status)) &&
  397.       (siz > 1) )
  398.     {
  399.       s->ustr = malloc((siz+1) * sizeof(UChar));
  400.       ((UChar*)(s->ustr))[0] = 0;
  401.       status = U_ZERO_ERROR;
  402.       uloc_getDisplayVariant( s->str, inLocale, (UChar*)(s->ustr), siz, &status );
  403.     }
  404.   else
  405.     {
  406.       status = U_ZERO_ERROR;
  407.       if( (siz = uloc_getDisplayCountry( s->str, inLocale, NULL, 0, &status))  &&
  408.       (siz > 1) )
  409.     {
  410.       s->ustr = malloc((siz+1) * sizeof(UChar));
  411.       ((UChar*)(s->ustr))[0] = 0;
  412.       status = U_ZERO_ERROR;
  413.       uloc_getDisplayCountry( s->str, inLocale, (UChar*)(s->ustr), siz, &status );
  414.     }
  415.       else
  416.     {
  417.       status = U_ZERO_ERROR;
  418.       if( ( siz = uloc_getDisplayLanguage( s->str, inLocale, NULL, 0, &status)) &&
  419.           (siz > 1) )
  420.         {
  421.           s->ustr = malloc((siz+1) * sizeof(UChar));
  422.           ((UChar*)(s->ustr))[0] = 0;
  423.           status = U_ZERO_ERROR;
  424.           uloc_getDisplayLanguage( s->str, inLocale, (UChar*)(s->ustr), siz, &status );
  425.         }
  426.       else
  427.         s->ustr = 0;
  428.     }
  429.     }
  430.   
  431.   s->subLocs = 0;
  432.   s->nSubLocs = 0;
  433.   s->parent = parent;
  434.   s->subLocsSize = 0;
  435. }
  436.  
  437.  
  438. /**
  439.  * Add a locale (realloc if necesary) directly to this level.
  440.  * @param root Node to add to
  441.  * @param thisLocale New locale name
  442.  * @param inLocale Locale for string names
  443.  * @param localeCount (return) global count to increment.
  444.  */
  445.  
  446. MySortable *addSubLocaleTo(MySortable *root, const char *thisLocale, const char *inLocale, int32_t *localeCount)
  447. {
  448.   int32_t n;
  449.  
  450.   if( (root->nSubLocs) >= root->subLocsSize)
  451.     {
  452.       if(root->subLocsSize)
  453.     root->subLocsSize *= 2;
  454.       else
  455.     root->subLocsSize = 10;
  456.       
  457.       root->subLocs = 
  458.     my_realloc(root->subLocs,sizeof(MySortable)*(root->nSubLocs), sizeof(MySortable) * (root->subLocsSize));
  459.     }
  460.       
  461.   initSortable(&(root->subLocs[root->nSubLocs]), thisLocale, inLocale, root);
  462.  
  463.   localeCount++;
  464.   
  465.   root->nSubLocs++;
  466.  
  467.   return &(root->subLocs[root->nSubLocs-1]);
  468. }
  469.  
  470. void addLocaleRecursive(MySortable *root, const char *thisLoc, const char *level, const char *inLocale, int32_t *localeCount)
  471. {
  472.   char        curStub[128]; /* current stub (next section to add) */
  473.   const char *curStubLimit; /* ptr to end of the current 'stub' (sublocale section) */
  474.   int32_t     j;
  475.  
  476.   curStubLimit = strchr(level, '_');
  477.   if(!curStubLimit)
  478.     curStubLimit = thisLoc + strlen(thisLoc);
  479.  
  480.   strncpy(curStub, thisLoc, curStubLimit-thisLoc);
  481.   curStub[curStubLimit-thisLoc] = 0;
  482.  
  483.   /* OK, find the stub.. */
  484.   j = findLocaleNonRecursive(root, curStub);
  485.   
  486.   /* advance the root to point to the parent of the next item to search in */
  487.   if(j == -1)
  488.     {
  489.       root = addSubLocaleTo(root, strdup(curStub), inLocale, localeCount);
  490.       *localeCount++;
  491.     }
  492.   else
  493.     {
  494.       root = &(root->subLocs[j]);
  495.     }
  496.  
  497.   if(*curStubLimit) /* We're not at the end yet. CSL points to _. */
  498.     {
  499.       addLocaleRecursive(root, thisLoc, ++curStubLimit, inLocale, localeCount);
  500.     }
  501.   else
  502.     {
  503.       /*
  504.     if *curStubLimit == 0, that means that curStub==thisLoc
  505.     
  506.     therefore, we just added the original locale we were trying
  507.     
  508.     to add. 
  509.       */
  510.     }
  511. }
  512.  
  513. /**
  514.  * create a MySortable tree of locales. 
  515.  * default -> en, ja, de, ... -> en_US, en_CA, .. -> en_US_CALIFORNIA
  516.  * @param inLocale the Locale the tree should be created in
  517.  * @param localeCount [return] total # of items in the tree
  518.  * @return a new MySortable tree, owned by the caller.  Not sorted.
  519.  */
  520.  
  521. MySortable *createLocaleTree(const char *inLocale, int32_t *localeCount)
  522. {
  523.   MySortable *root;
  524.  
  525.   int32_t     nlocs;  /* ICU-specified total locales */
  526.   
  527.   /* temps */
  528.   int32_t     i,j;
  529.  
  530.   root = malloc(sizeof(MySortable));
  531.  
  532.   /* get things rolling... */
  533.   initSortable(root, "default", inLocale, NULL);
  534.   *localeCount = 1;
  535.  
  536.  
  537.   /* load the list of locales from the ICU and process them */
  538.   nlocs = uloc_countAvailable();
  539.   
  540.   for(i=0;i<nlocs;i++)
  541.     {
  542.       const char *thisLoc;
  543.  
  544.       thisLoc = uloc_getAvailable(i);
  545.  
  546.  
  547.       addLocaleRecursive(root, thisLoc, thisLoc, inLocale, localeCount);
  548.  
  549.     }
  550.   
  551.   return root;
  552. }
  553.  
  554.  
  555.  
  556.  
  557. /* Helper function for mySort --------------------------------------------------------*/
  558. int myCompare(const void *aa, const void *bb)
  559. {
  560.   int cmp;
  561.   int minSize;
  562.   const MySortable *a, *b;
  563.  
  564.   a = (const MySortable*) aa;
  565.   b = (const MySortable*) bb;
  566.  
  567.   if(a->keySize == b->keySize)
  568.     return memcmp(a->key,b->key,a->keySize);
  569.   else
  570.     {
  571.       if(a->keySize > b->keySize)
  572.     minSize = b->keySize;
  573.       else
  574.     minSize = a->keySize;
  575.  
  576.       cmp = memcmp(a->key,b->key, minSize);
  577.  
  578.       if(cmp != 0) /* if dissimilar, just return */
  579.     return cmp;
  580.       if(a->keySize == minSize)
  581.     return -1;
  582.       else
  583.     return 1;
  584.     }
  585.  
  586. }
  587.  
  588. /**
  589.  * NON recursive exact match search
  590.  * @param toSort  the list of locales to search
  591.  * @param locale  locale to search for
  592.  * @return index into toSort.subLocs[], or -1 if not found
  593.  */
  594.  
  595. int32_t findLocaleNonRecursive(MySortable *toSort, const char *locale)
  596. {
  597.   int32_t j;
  598.   int32_t numTopLocs = toSort->nSubLocs;
  599.   MySortable *s = toSort->subLocs;
  600.  
  601.   for(j=0;j<numTopLocs;j++)
  602.     {
  603.       if(!strcmp(s[j].str, locale))
  604.     {
  605.       return j;
  606.     }
  607.     }
  608.   
  609.   return -1; /* not found */
  610. }
  611.  
  612. MySortable *findLocale(MySortable *root, const char *locale)
  613. {
  614.   int32_t    n;
  615.   MySortable *found;
  616.  
  617.   if(!root)
  618.     return NULL;
  619.   
  620.   if(!strcmp(root->str,locale))
  621.     {
  622.       return root;
  623.     }
  624.   
  625.   /* Right now very stupid DFS. Let's forget that we actually know that if we're searching for fr_BF that we should look under the fr node. */
  626.   for(n=0;n<root->nSubLocs;n++)
  627.     {
  628.       if(!strcmp(root->subLocs[n].str,locale))
  629.     {
  630.       return &(root->subLocs[n]);
  631.     }
  632.       
  633.       if(found = findLocale(&(root->subLocs[n]),locale)) /* if found at a sublevel */
  634.     return found;
  635.     }
  636.   
  637.   return NULL; /* not found */
  638. }
  639.  
  640. /* Sort an array of sortables --------------------------------------------------------*/
  641. /* terminated with s->str being null */
  642. void mySort(MySortable *s, UErrorCode *status, bool_t recurse)
  643. {
  644.   UCollator *coll;
  645.   MySortable *p;
  646.   int32_t num;
  647.   int32_t n = 0;
  648.  
  649.   num = s->nSubLocs;
  650.  
  651.   if(num <= 1)
  652.     return; /* nothing to do */
  653.  
  654.   *status = U_ZERO_ERROR;
  655.   coll = ucol_open(NULL, status);
  656.   if(U_FAILURE(*status))
  657.     return;
  658.  
  659.   ucol_setStrength(coll, UCOL_PRIMARY);
  660.   /* First, fill in the keys */
  661.   for(p=(s->subLocs);n < num;p++)
  662.     {
  663.       if(recurse)
  664.     mySort(p,status,recurse); /* sub sort */
  665.       
  666.       p->keySize = ucol_getSortKey(coll, p->ustr, -1, p->key, SORTKEYSIZE);
  667.       /*      if(U_FAILURE(*status))
  668.           return; */
  669.       n++;
  670.     }
  671.   
  672.   ucol_close(coll); /* don't need it now */
  673.  
  674.   qsort(s->subLocs, n, sizeof(MySortable), &myCompare);
  675.  
  676. }
  677.  
  678. /* convert from our internal names to a MIME friendly name .. ----------------------------  */
  679. const char *MIMECharsetName(const char *n)
  680. {
  681.   int i;
  682.  
  683. static  struct
  684.   {
  685.     char old[20];
  686.     char new[20];
  687.   } mapping[] = 
  688.     {
  689.       /* NOTA BENE:   the 'mime' standard (or nonstandard) names for encoders
  690.      seems like a useful property. We really should have API for dealing with
  691.      these names.  -srl
  692.       */
  693.  
  694.       { "UTF8",     "utf-8" },
  695.       { "LATIN_1",  "iso-8859-1" },
  696.       { "ISO_2022", "iso-2022" },
  697.       { "ibm-1089", "iso-8859-6" },
  698.       { "ibm-1252", "windows-1252" },
  699.       { "ibm-1386", "gb" },
  700.       { "ibm-813",  "iso-8859-7" },
  701.       { "ibm-912",  "iso-8859-2" },
  702.       { "ibm-913",  "iso-8859-3" }, 
  703.       { "ibm-914",  "iso-8859-4" },
  704.       { "ibm-915",  "iso-8859-5" },
  705.       { "ibm-916",  "iso-8859-8" },
  706.       { "ibm-920",  "iso-8859-9" },
  707.       { "ibm-923",  "iso-8859-15" },
  708.       { "ibm-943",  "shift_jis" },
  709.       { "ibm-949",  "ksc-5601" },
  710.       { "ibm-954",  "euc-jp" },
  711.       { "ibm-964",  "euc-tw" },
  712.       { "ibm-970",  "euc-kr" },
  713.       { "ibm-1361", "ksc" },
  714.       { "ibm-1383", "euc-cn" },
  715.       { "ibm-874",  "windows-874" },
  716.       { "ibm-878",  "koi8-r" },
  717.       { "ibm-1250", "windows-1250" },
  718.       { "ibm-1251", "windows-1251" },
  719.       { "ibm-1252", "windows-1252" },
  720.       { "ibm-1253", "windows-1253" },
  721.       { "ibm-1254", "windows-1254" },
  722.       { "ibm-1255", "windows-1255" },
  723.       { "ibm-1256", "windows-1256" },
  724.       { "ibm-1257", "windows-1257" },
  725.       { "ibm-1258", "windows-1258" },
  726.       { "ibm-1275", "mac" },
  727.       { "ibm-860",  "cp860" },
  728.       { "ibm-861",  "cp861" },
  729.       { "ibm-862",  "cp862" },
  730.       { "ibm-863",  "cp863" },
  731.       { "ibm-864",  "cp864" },
  732.       { "ibm-865",  "cp865" },
  733.       { "ibm-866",  "cp866" },
  734.       { "ibm-867",  "cp867" },
  735.       { "ibm-868",  "cp868" },
  736.       { "ibm-869",  "cp869" },
  737.       { "\0", "\0" }
  738.     };
  739.  
  740.   for(i=0;mapping[i].old[0];i++)
  741.     {
  742.       if(!strcmp(n,mapping[i].old))
  743.     return mapping[i].new;
  744.     }
  745.   return n;
  746. }
  747.  
  748.  
  749. /* Kind of crude. we COULD be more lenient and pass more chars through. But it's only for transport to the next form. So, we don't optimize for URL size but for code simplicity.  [Ultra paranoid method = attempt to convert each char into the target CP, and only escape chars that fail a). said conversion or b). if the conversion generates illegal chars for a URL. Just in case you wondered.
  750.  
  751.  <legal char              -> <legal char>
  752.  <illegal char> -> \uXXXX -> %5cXXXX
  753.  
  754.  The code that displays this stuff only has to worry about being able to output to the target CP. We'll make the browser do the rest. 
  755. */
  756.  
  757. void ucharsToEscapedUrlQuery(char *urlQuery, const UChar *src)
  758. {
  759.   while(*src)
  760.     {
  761.   
  762.       if(  ((*src) > 0x007F)
  763.     || !( isalnum(*src) || (*src==',') || (*src==':') || (*src == '.')))
  764.     {
  765.       *(urlQuery++) = '%';
  766.       *(urlQuery++) = '5';
  767.       *(urlQuery++) = 'C';
  768.       *(urlQuery++) = 'u';
  769.       *(urlQuery++) = ToOffset( ((*src) & 0xF000) >> 12);
  770.       *(urlQuery++) = ToOffset( ((*src) & 0x0F00) >>  8);
  771.       *(urlQuery++) = ToOffset( ((*src) & 0x00F0) >>  4);
  772.       *(urlQuery++) = ToOffset( ((*src) & 0x000F) >>  0);
  773.     }
  774.       else
  775.     *(urlQuery++) = *src;
  776.  
  777.       src++;
  778.     }
  779.   *urlQuery = 0; 
  780. }
  781.  
  782.  
  783. /* date [from udate by Stephen F. Booth] ----------------------------------------------------- */
  784. /* Format the date */
  785. UChar *
  786. date(const UChar *tz,
  787.      UDateFormatStyle style,
  788.      UErrorCode *status)
  789. {
  790.   UChar *s = 0;
  791.   int32_t len = 0;
  792.   UDateFormat *fmt;
  793.  
  794.   fmt = udat_open(style, style, NULL, tz, -1, status);
  795.   len = udat_format(fmt, ucal_getNow(), 0, len, 0, status);
  796.   if(*status == U_BUFFER_OVERFLOW_ERROR) {
  797.     *status = U_ZERO_ERROR;
  798.     s = (UChar*) malloc(sizeof(UChar) * (len+1));
  799.     if(s == 0) goto finish;
  800.     udat_format(fmt, ucal_getNow(), s, len + 1, 0, status);
  801.     if(U_FAILURE(*status)) goto finish;
  802.   }
  803.  
  804.  finish:
  805.   udat_close(fmt);
  806.   return s;
  807. }
  808.  
  809. int32_t unescapeAndDecodeQueryField(UChar *dst, int32_t dstLen, const char *src)
  810. {
  811.   const char *fieldLimit;
  812.   UChar temp[1024];
  813.   char tmpc[1024];
  814.   int32_t len;
  815.  
  816.   /* make fieldLimit point to the end of the field data */
  817.   fieldLimit = strchr(src,'&');
  818.   if(!fieldLimit)
  819.     fieldLimit = src + strlen(src);
  820.  
  821.   /* sanity [safety from buffer overruns]  */
  822.   if( (fieldLimit-src) > dstLen)
  823.     fieldLimit = src + dstLen;
  824.  
  825.   /********************/
  826.  
  827.   /* First off, convert the field into an 8 bit string in the user's codepage */
  828.   doDecodeQueryField(src,tmpc,fieldLimit-src);
  829.  
  830.   /* Now, convert it into Unicode, still escaped.. */
  831.   u_uastrcpy(temp, tmpc);
  832.   
  833.   /* Now, de escape it.. */
  834.   len = u_strlen(temp);
  835.   len = copyWithUnescaping( dst, temp, len);
  836.   dst[len] = 0; /* copy with unescaping DOES NOT terminate the str */
  837.   
  838.   return len;
  839. }
  840.  
  841. /**
  842.  * Replace all instances of 'from' with 'to'.
  843.  * @param str the string to modify. Null terminated
  844.  * @param from the char to look for
  845.  * @param to the char to change it to.
  846.  */
  847.  
  848. void u_replaceChar(UChar *str, UChar from, UChar to)
  849. {
  850.   if(from == 0x0000) /* Don't allow the end condition to change. */
  851.     return;
  852.  
  853.   do
  854.     {
  855.       if(*str == from)
  856.     *str = to;
  857.     } while( *(str++) );
  858. }
  859.