home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / gd201.zip / gd-2.0.1 / gdkanji.c < prev    next >
C/C++ Source or Header  |  2001-04-03  |  12KB  |  627 lines

  1.  
  2. /* gdkanji.c (Kanji code converter)                            */
  3. /*                 written by Masahito Yamaga (ma@yama-ga.com) */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include "gd.h"
  9. #include "gdhelpers.h"
  10.  
  11. #include <stdarg.h>
  12. #if defined(HAVE_ICONV_H) || defined(HAVE_ICONV)
  13. #include <iconv.h>
  14. #ifdef HAVE_ERRNO_H
  15. #include <errno.h>
  16. #endif
  17. #endif
  18.  
  19. #if defined(HAVE_ICONV_H) && !defined(HAVE_ICONV)
  20. #define HAVE_ICONV 1
  21. #endif
  22.  
  23. #define LIBNAME "any2eucjp()"
  24.  
  25. #if defined(__MSC__) || defined(__BORLANDC__) || defined(__TURBOC__) || defined(_Windows) || defined(MSDOS)
  26. #ifndef SJISPRE
  27. #define SJISPRE 1
  28. #endif
  29. #endif
  30.  
  31. #ifdef TRUE
  32. #undef TRUE
  33. #endif
  34. #ifdef FALSE
  35. #undef FALSE
  36. #endif
  37.  
  38. #define TRUE  1
  39. #define FALSE 0
  40.  
  41. #define NEW 1
  42. #define OLD 2
  43. #define ESCI 3
  44. #define NEC 4
  45. #define EUC 5
  46. #define SJIS 6
  47. #define EUCORSJIS 7
  48. #define ASCII 8
  49.  
  50. #define NEWJISSTR "JIS7"
  51. #define OLDJISSTR "jis"
  52. #define EUCSTR    "eucJP"
  53. #define SJISSTR   "SJIS"
  54.  
  55. #define ESC 27
  56. #define SS2 142
  57.  
  58. static void
  59. debug (const char *format,...)
  60. {
  61. #ifdef DEBUG
  62.   va_list args;
  63.  
  64.   va_start (args, format);
  65.   fprintf (stdout, "%s: ", LIBNAME);
  66.   vfprintf (stdout, format, args);
  67.   fprintf (stdout, "\n");
  68.   va_end (args);
  69. #endif
  70. }
  71.  
  72. static void
  73. error (const char *format,...)
  74. {
  75.   va_list args;
  76.  
  77.   va_start (args, format);
  78.   fprintf (stderr, "%s: ", LIBNAME);
  79.   vfprintf (stderr, format, args);
  80.   fprintf (stderr, "\n");
  81.   va_end (args);
  82. }
  83.  
  84. /* DetectKanjiCode() derived from DetectCodeType() by Ken Lunde. */
  85.  
  86. static int
  87. DetectKanjiCode (unsigned char *str)
  88. {
  89.   static int whatcode = ASCII;
  90.   int oldcode = ASCII;
  91.   int c, i;
  92.   char *lang = NULL;
  93.  
  94.   c = '\1';
  95.   i = 0;
  96.  
  97.   if (whatcode != EUCORSJIS && whatcode != ASCII)
  98.     {
  99.       oldcode = whatcode;
  100.       whatcode = ASCII;
  101.     }
  102.  
  103.   while ((whatcode == EUCORSJIS || whatcode == ASCII) && c != '\0')
  104.     {
  105.       if ((c = str[i++]) != '\0')
  106.     {
  107.       if (c == ESC)
  108.         {
  109.           c = str[i++];
  110.           if (c == '$')
  111.         {
  112.           c = str[i++];
  113.           if (c == 'B')
  114.             whatcode = NEW;
  115.           else if (c == '@')
  116.             whatcode = OLD;
  117.         }
  118.           else if (c == '(')
  119.         {
  120.           c = str[i++];
  121.           if (c == 'I')
  122.             whatcode = ESCI;
  123.         }
  124.           else if (c == 'K')
  125.         whatcode = NEC;
  126.         }
  127.       else if ((c >= 129 && c <= 141) || (c >= 143 && c <= 159))
  128.         whatcode = SJIS;
  129.       else if (c == SS2)
  130.         {
  131.           c = str[i++];
  132.           if ((c >= 64 && c <= 126) || (c >= 128 && c <= 160) || (c >= 224 && c <= 252))
  133.         whatcode = SJIS;
  134.           else if (c >= 161 && c <= 223)
  135.         whatcode = EUCORSJIS;
  136.         }
  137.       else if (c >= 161 && c <= 223)
  138.         {
  139.           c = str[i++];
  140.           if (c >= 240 && c <= 254)
  141.         whatcode = EUC;
  142.           else if (c >= 161 && c <= 223)
  143.         whatcode = EUCORSJIS;
  144.           else if (c >= 224 && c <= 239)
  145.         {
  146.           whatcode = EUCORSJIS;
  147.           while (c >= 64 && c != '\0' && whatcode == EUCORSJIS)
  148.             {
  149.               if (c >= 129)
  150.             {
  151.               if (c <= 141 || (c >= 143 && c <= 159))
  152.                 whatcode = SJIS;
  153.               else if (c >= 253 && c <= 254)
  154.                 whatcode = EUC;
  155.             }
  156.               c = str[i++];
  157.             }
  158.         }
  159.           else if (c <= 159)
  160.         whatcode = SJIS;
  161.         }
  162.       else if (c >= 240 && c <= 254)
  163.         whatcode = EUC;
  164.       else if (c >= 224 && c <= 239)
  165.         {
  166.           c = str[i++];
  167.           if ((c >= 64 && c <= 126) || (c >= 128 && c <= 160))
  168.         whatcode = SJIS;
  169.           else if (c >= 253 && c <= 254)
  170.         whatcode = EUC;
  171.           else if (c >= 161 && c <= 252)
  172.         whatcode = EUCORSJIS;
  173.         }
  174.     }
  175.     }
  176.  
  177. #ifdef DEBUG
  178.   if (whatcode == ASCII)
  179.     debug ("Kanji code not included.");
  180.   else if (whatcode == EUCORSJIS)
  181.     debug ("Kanji code not detected.");
  182.   else
  183.     debug ("Kanji code detected at %d byte.", i);
  184. #endif
  185.  
  186.   if (whatcode == EUCORSJIS && oldcode != ASCII)
  187.     whatcode = oldcode;
  188.  
  189.   if (whatcode == EUCORSJIS)
  190.     {
  191.       if (getenv ("LC_ALL"))
  192.     lang = getenv ("LC_ALL");
  193.       else if (getenv ("LC_CTYPE"))
  194.     lang = getenv ("LC_CTYPE");
  195.       else if (getenv ("LANG"))
  196.     lang = getenv ("LANG");
  197.  
  198.       if (lang)
  199.     {
  200.       if (strcmp (lang, "ja_JP.SJIS") == 0 ||
  201. #ifdef hpux
  202.           strcmp (lang, "japanese") == 0 ||
  203. #endif
  204.           strcmp (lang, "ja_JP.mscode") == 0 ||
  205.           strcmp (lang, "ja_JP.PCK") == 0)
  206.         whatcode = SJIS;
  207.       else if (strncmp (lang, "ja", 2) == 0)
  208. #ifdef SJISPRE
  209.         whatcode = SJIS;
  210. #else
  211.         whatcode = EUC;
  212. #endif
  213.     }
  214.     }
  215.  
  216.   if (whatcode == EUCORSJIS)
  217. #ifdef SJISPRE
  218.     whatcode = SJIS;
  219. #else
  220.     whatcode = EUC;
  221. #endif
  222.  
  223.   return whatcode;
  224. }
  225.  
  226. /* SJIStoJIS() is sjis2jis() by Ken Lunde. */
  227.  
  228. static void
  229. SJIStoJIS (int *p1, int *p2)
  230. {
  231.   register unsigned char c1 = *p1;
  232.   register unsigned char c2 = *p2;
  233.   register int adjust = c2 < 159;
  234.   register int rowOffset = c1 < 160 ? 112 : 176;
  235.   register int cellOffset = adjust ? (31 + (c2 > 127)) : 126;
  236.  
  237.   *p1 = ((c1 - rowOffset) << 1) - adjust;
  238.   *p2 -= cellOffset;
  239. }
  240.  
  241. /* han2zen() was derived from han2zen() written by Ken Lunde. */
  242.  
  243. #define IS_DAKU(c) ((c >= 182 && c <= 196) || (c >= 202 && c <= 206) || (c == 179))
  244. #define IS_HANDAKU(c) (c >= 202 && c <= 206)
  245.  
  246. static void
  247. han2zen (int *p1, int *p2)
  248. {
  249.   int c = *p1;
  250.   int daku = FALSE;
  251.   int handaku = FALSE;
  252.   int mtable[][2] =
  253.   {
  254.     {129, 66},
  255.     {129, 117},
  256.     {129, 118},
  257.     {129, 65},
  258.     {129, 69},
  259.     {131, 146},
  260.     {131, 64},
  261.     {131, 66},
  262.     {131, 68},
  263.     {131, 70},
  264.     {131, 72},
  265.     {131, 131},
  266.     {131, 133},
  267.     {131, 135},
  268.     {131, 98},
  269.     {129, 91},
  270.     {131, 65},
  271.     {131, 67},
  272.     {131, 69},
  273.     {131, 71},
  274.     {131, 73},
  275.     {131, 74},
  276.     {131, 76},
  277.     {131, 78},
  278.     {131, 80},
  279.     {131, 82},
  280.     {131, 84},
  281.     {131, 86},
  282.     {131, 88},
  283.     {131, 90},
  284.     {131, 92},
  285.     {131, 94},
  286.     {131, 96},
  287.     {131, 99},
  288.     {131, 101},
  289.     {131, 103},
  290.     {131, 105},
  291.     {131, 106},
  292.     {131, 107},
  293.     {131, 108},
  294.     {131, 109},
  295.     {131, 110},
  296.     {131, 113},
  297.     {131, 116},
  298.     {131, 119},
  299.     {131, 122},
  300.     {131, 125},
  301.     {131, 126},
  302.     {131, 128},
  303.     {131, 129},
  304.     {131, 130},
  305.     {131, 132},
  306.     {131, 134},
  307.     {131, 136},
  308.     {131, 137},
  309.     {131, 138},
  310.     {131, 139},
  311.     {131, 140},
  312.     {131, 141},
  313.     {131, 143},
  314.     {131, 147},
  315.     {129, 74},
  316.     {129, 75}
  317.   };
  318.  
  319.   if (*p2 == 222 && IS_DAKU (*p1))
  320.     daku = TRUE;        /* Daku-ten */
  321.   else if (*p2 == 223 && IS_HANDAKU (*p1))
  322.     handaku = TRUE;        /* Han-daku-ten */
  323.  
  324.   *p1 = mtable[c - 161][0];
  325.   *p2 = mtable[c - 161][1];
  326.  
  327.   if (daku)
  328.     {
  329.       if ((*p2 >= 74 && *p2 <= 103) || (*p2 >= 110 && *p2 <= 122))
  330.     (*p2)++;
  331.       else if (*p2 == 131 && *p2 == 69)
  332.     *p2 = 148;
  333.     }
  334.   else if (handaku && *p2 >= 110 && *p2 <= 122)
  335.     (*p2) += 2;
  336. }
  337.  
  338. /* Recast strcpy to handle unsigned chars used below. */
  339. #define ustrcpy(A,B) (strcpy((char*)(A),(const char*)(B)))
  340.  
  341. static void
  342. do_convert (unsigned char *to, unsigned char *from, const char *code)
  343. {
  344. #ifdef HAVE_ICONV
  345.   iconv_t cd;
  346.   size_t from_len, to_len;
  347.  
  348.   if ((cd = iconv_open (EUCSTR, code)) == (iconv_t) - 1)
  349.     {
  350.       error ("iconv_open() error");
  351. #ifdef HAVE_ERRNO_H
  352.       if (errno == EINVAL)
  353.     error ("invalid code specification: \"%s\" or \"%s\"",
  354.            EUCSTR, code);
  355. #endif
  356.       strcpy ((char *) to, (const char *) from);
  357.       return;
  358.     }
  359.  
  360.   from_len = strlen ((const char *) from) + 1;
  361.   to_len = BUFSIZ;
  362.  
  363.   if (iconv (cd, (const char **) &from, &from_len,
  364.          (char **) &to, &to_len) == -1)
  365.     {
  366. #ifdef HAVE_ERRNO_H
  367.       if (errno == EINVAL)
  368.     error ("invalid end of input string");
  369.       else if (errno == EILSEQ)
  370.     error ("invalid code in input string");
  371.       else if (errno == E2BIG)
  372.     error ("output buffer overflow at do_convert()");
  373.       else
  374. #endif
  375.     error ("something happen");
  376.       strcpy ((char *) to, (const char *) from);
  377.       return;
  378.     }
  379.  
  380.   if (iconv_close (cd) != 0)
  381.     {
  382.       error ("iconv_close() error");
  383.     }
  384. #else
  385.   int p1, p2, i, j;
  386.   int jisx0208 = FALSE;
  387.   int hankaku = FALSE;
  388.  
  389.   j = 0;
  390.   if (strcmp (code, NEWJISSTR) == 0 || strcmp (code, OLDJISSTR) == 0)
  391.     {
  392.       for (i = 0; from[i] != '\0' && j < BUFSIZ; i++)
  393.     {
  394.       if (from[i] == ESC)
  395.         {
  396.           i++;
  397.           if (from[i] == '$')
  398.         {
  399.           jisx0208 = TRUE;
  400.           hankaku = FALSE;
  401.           i++;
  402.         }
  403.           else if (from[i] == '(')
  404.         {
  405.           jisx0208 = FALSE;
  406.           i++;
  407.           if (from[i] == 'I')    /* Hankaku Kana */
  408.             hankaku = TRUE;
  409.           else
  410.             hankaku = FALSE;
  411.         }
  412.         }
  413.       else
  414.         {
  415.           if (jisx0208)
  416.         to[j++] = from[i] + 128;
  417.           else if (hankaku)
  418.         {
  419.           to[j++] = SS2;
  420.           to[j++] = from[i] + 128;
  421.         }
  422.           else
  423.         to[j++] = from[i];
  424.         }
  425.     }
  426.     }
  427.   else if (strcmp (code, SJISSTR) == 0)
  428.     {
  429.       for (i = 0; from[i] != '\0' && j < BUFSIZ; i++)
  430.     {
  431.       p1 = from[i];
  432.       if (p1 < 127)
  433.         to[j++] = p1;
  434.       else if ((p1 >= 161) && (p1 <= 223))
  435.         {            /* Hankaku Kana */
  436.           to[j++] = SS2;
  437.           to[j++] = p1;
  438.         }
  439.       else
  440.         {
  441.           p2 = from[++i];
  442.           SJIStoJIS (&p1, &p2);
  443.           to[j++] = p1 + 128;
  444.           to[j++] = p2 + 128;
  445.         }
  446.     }
  447.     }
  448.   else
  449.     {
  450.       error ("invalid code specification: \"%s\"", code);
  451.       return;
  452.     }
  453.  
  454.   if (j >= BUFSIZ)
  455.     {
  456.       error ("output buffer overflow at do_convert()");
  457.       ustrcpy (to, from);
  458.     }
  459.   else
  460.     to[j] = '\0';
  461. #endif /* HAVE_ICONV */
  462. }
  463.  
  464. static int
  465. do_check_and_conv (unsigned char *to, unsigned char *from)
  466. {
  467.   static unsigned char tmp[BUFSIZ];
  468.   int p1, p2, i, j;
  469.   int kanji = TRUE;
  470.  
  471.   switch (DetectKanjiCode (from))
  472.     {
  473.     case NEW:
  474.       debug ("Kanji code is New JIS.");
  475.       do_convert (tmp, from, NEWJISSTR);
  476.       break;
  477.     case OLD:
  478.       debug ("Kanji code is Old JIS.");
  479.       do_convert (tmp, from, OLDJISSTR);
  480.       break;
  481.     case ESCI:
  482.       debug ("This string includes Hankaku-Kana (jisx0201) escape sequence [ESC] + ( + I.");
  483.       do_convert (tmp, from, NEWJISSTR);
  484.       break;
  485.     case NEC:
  486.       debug ("Kanji code is NEC Kanji.");
  487.       error ("cannot convert NEC Kanji.");
  488.       ustrcpy (tmp, from);
  489.       kanji = FALSE;
  490.       break;
  491.     case EUC:
  492.       debug ("Kanji code is EUC.");
  493.       ustrcpy (tmp, from);
  494.       break;
  495.     case SJIS:
  496.       debug ("Kanji code is SJIS.");
  497.       do_convert (tmp, from, SJISSTR);
  498.       break;
  499.     case EUCORSJIS:
  500.       debug ("Kanji code is EUC or SJIS.");
  501.       ustrcpy (tmp, from);
  502.       kanji = FALSE;
  503.       break;
  504.     case ASCII:
  505.       debug ("This is ASCII string.");
  506.       ustrcpy (tmp, from);
  507.       kanji = FALSE;
  508.       break;
  509.     default:
  510.       debug ("This string includes unknown code.");
  511.       ustrcpy (tmp, from);
  512.       kanji = FALSE;
  513.       break;
  514.     }
  515.  
  516.   /* Hankaku Kana ---> Zenkaku Kana */
  517.   if (kanji)
  518.     {
  519.       j = 0;
  520.       for (i = 0; tmp[i] != '\0' && j < BUFSIZ; i++)
  521.     {
  522.       if (tmp[i] == SS2)
  523.         {
  524.           p1 = tmp[++i];
  525.           if (tmp[i + 1] == SS2)
  526.         {
  527.           p2 = tmp[i + 2];
  528.           if (p2 == 222 || p2 == 223)
  529.             i += 2;
  530.           else
  531.             p2 = 0;
  532.         }
  533.           else
  534.         p2 = 0;
  535.           han2zen (&p1, &p2);
  536.           SJIStoJIS (&p1, &p2);
  537.           to[j++] = p1 + 128;
  538.           to[j++] = p2 + 128;
  539.         }
  540.       else
  541.         to[j++] = tmp[i];
  542.     }
  543.  
  544.       if (j >= BUFSIZ)
  545.     {
  546.       error ("output buffer overflow at Hankaku --> Zenkaku");
  547.       ustrcpy (to, tmp);
  548.     }
  549.       else
  550.     to[j] = '\0';
  551.     }
  552.   else
  553.     ustrcpy (to, tmp);
  554.  
  555.   return kanji;
  556. }
  557.  
  558. int
  559. any2eucjp (unsigned char *dest, unsigned char *src, unsigned int dest_max)
  560. {
  561.   static unsigned char tmp_dest[BUFSIZ];
  562.   int ret;
  563.  
  564.   if (strlen ((const char *) src) >= BUFSIZ)
  565.     {
  566.       error ("input string too large");
  567.       return -1;
  568.     }
  569.   if (dest_max > BUFSIZ)
  570.     {
  571.       error ("invalid maximum size of destination\nit should be less than %d.", BUFSIZ);
  572.       return -1;
  573.     }
  574.   ret = do_check_and_conv (tmp_dest, src);
  575.   if (strlen ((const char *) tmp_dest) >= dest_max)
  576.     {
  577.       error ("output buffer overflow");
  578.       ustrcpy (dest, src);
  579.       return -1;
  580.     }
  581.   ustrcpy (dest, tmp_dest);
  582.   return ret;
  583. }
  584.  
  585. #if 0
  586. unsigned int
  587. strwidth (unsigned char *s)
  588. {
  589.   unsigned char *t;
  590.   unsigned int i;
  591.  
  592.   t = (unsigned char *) gdMalloc (BUFSIZ);
  593.   any2eucjp (t, s, BUFSIZ);
  594.   i = strlen (t);
  595.   gdFree (t);
  596.   return i;
  597. }
  598.  
  599. #ifdef DEBUG
  600. int
  601. main ()
  602. {
  603.   unsigned char input[BUFSIZ];
  604.   unsigned char *output;
  605.   unsigned char *str;
  606.   int c, i = 0;
  607.  
  608.   while ((c = fgetc (stdin)) != '\n' && i < BUFSIZ)
  609.     input[i++] = c;
  610.   input[i] = '\0';
  611.  
  612.   printf ("input : %d bytes\n", strlen ((const char *) input));
  613.   printf ("output: %d bytes\n", strwidth (input));
  614.  
  615.   output = (unsigned char *) gdMalloc (BUFSIZ);
  616.   any2eucjp (output, input, BUFSIZ);
  617.   str = output;
  618.   while (*str != '\0')
  619.     putchar (*(str++));
  620.   putchar ('\n');
  621.   gdFree (output);
  622.  
  623.   return 0;
  624. }
  625. #endif
  626. #endif
  627.