-}
-
-static size_t yaz_write_UTF8(yaz_iconv_t cd, unsigned long x,
- char **outbuf, size_t *outbytesleft,
- int last)
-{
- return yaz_write_UTF8_char(x, outbuf, outbytesleft, &cd->my_errno);
-}
-
-size_t yaz_write_UTF8_char(unsigned long x,
- char **outbuf, size_t *outbytesleft,
- int *error)
-{
- unsigned char *outp = (unsigned char *) *outbuf;
-
- if (x <= 0x7f && *outbytesleft >= 1)
- {
- *outp++ = (unsigned char) x;
- (*outbytesleft)--;
- }
- else if (x <= 0x7ff && *outbytesleft >= 2)
- {
- *outp++ = (unsigned char) ((x >> 6) | 0xc0);
- *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
- (*outbytesleft) -= 2;
- }
- else if (x <= 0xffff && *outbytesleft >= 3)
- {
- *outp++ = (unsigned char) ((x >> 12) | 0xe0);
- *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80);
- *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
- (*outbytesleft) -= 3;
- }
- else if (x <= 0x1fffff && *outbytesleft >= 4)
- {
- *outp++ = (unsigned char) ((x >> 18) | 0xf0);
- *outp++ = (unsigned char) (((x >> 12) & 0x3f) | 0x80);
- *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80);
- *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
- (*outbytesleft) -= 4;
- }
- else if (x <= 0x3ffffff && *outbytesleft >= 5)
- {
- *outp++ = (unsigned char) ((x >> 24) | 0xf8);
- *outp++ = (unsigned char) (((x >> 18) & 0x3f) | 0x80);
- *outp++ = (unsigned char) (((x >> 12) & 0x3f) | 0x80);
- *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80);
- *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
- (*outbytesleft) -= 5;
- }
- else if (*outbytesleft >= 6)
- {
- *outp++ = (unsigned char) ((x >> 30) | 0xfc);
- *outp++ = (unsigned char) (((x >> 24) & 0x3f) | 0x80);
- *outp++ = (unsigned char) (((x >> 18) & 0x3f) | 0x80);
- *outp++ = (unsigned char) (((x >> 12) & 0x3f) | 0x80);
- *outp++ = (unsigned char) (((x >> 6) & 0x3f) | 0x80);
- *outp++ = (unsigned char) ((x & 0x3f) | 0x80);
- (*outbytesleft) -= 6;
- }
- else
- {
- *error = YAZ_ICONV_E2BIG; /* not room for output */
- return (size_t)(-1);
- }
- *outbuf = (char *) outp;
- return 0;
-}
-
-
-static size_t yaz_write_ISO8859_1 (yaz_iconv_t cd, unsigned long x,
- char **outbuf, size_t *outbytesleft,
- int last)
-{
- /* list of two char unicode sequence that, when combined, are
- equivalent to single unicode chars that can be represented in
- ISO-8859-1/Latin-1.
- Regular iconv on Linux at least does not seem to convert these,
- but since MARC-8 to UTF-8 generates these composed sequence
- we get a better chance of a successful MARC-8 -> ISO-8859-1
- conversion */
- unsigned char *outp = (unsigned char *) *outbuf;
-
- if (cd->compose_char)
- {
- int i;
- for (i = 0; latin1_comb[i].x1; i++)
- if (cd->compose_char == latin1_comb[i].x1 && x == latin1_comb[i].x2)
- {
- x = latin1_comb[i].y;
- break;
- }
- if (*outbytesleft < 1)
- { /* no room. Retain compose_char and bail out */
- cd->my_errno = YAZ_ICONV_E2BIG;
- return (size_t)(-1);
- }
- if (!latin1_comb[i].x1)
- { /* not found. Just write compose_char */
- *outp++ = (unsigned char) cd->compose_char;
- (*outbytesleft)--;
- *outbuf = (char *) outp;
- }
- /* compose_char used so reset it. x now holds current char */
- cd->compose_char = 0;
- }
-
- if (!last && x > 32 && x < 127 && cd->compose_char == 0)
- {
- cd->compose_char = x;
- return 0;
- }
- else if (x > 255 || x < 1)
- {
- cd->my_errno = YAZ_ICONV_EILSEQ;
- return (size_t) -1;
- }
- else if (*outbytesleft < 1)
- {
- cd->my_errno = YAZ_ICONV_E2BIG;
- return (size_t)(-1);
- }
- *outp++ = (unsigned char) x;
- (*outbytesleft)--;
- *outbuf = (char *) outp;
- return 0;
-}
-
-
-static size_t yaz_write_UCS4 (yaz_iconv_t cd, unsigned long x,
- char **outbuf, size_t *outbytesleft,
- int last)
-{
- unsigned char *outp = (unsigned char *) *outbuf;
- if (*outbytesleft >= 4)
- {
- *outp++ = (unsigned char) (x>>24);
- *outp++ = (unsigned char) (x>>16);
- *outp++ = (unsigned char) (x>>8);
- *outp++ = (unsigned char) x;
- (*outbytesleft) -= 4;
- }
- else
- {
- cd->my_errno = YAZ_ICONV_E2BIG;
- return (size_t)(-1);
- }
- *outbuf = (char *) outp;
- return 0;
-}
-
-static size_t yaz_write_UCS4LE (yaz_iconv_t cd, unsigned long x,
- char **outbuf, size_t *outbytesleft,
- int last)
-{
- unsigned char *outp = (unsigned char *) *outbuf;
- if (*outbytesleft >= 4)
- {
- *outp++ = (unsigned char) x;
- *outp++ = (unsigned char) (x>>8);
- *outp++ = (unsigned char) (x>>16);
- *outp++ = (unsigned char) (x>>24);
- (*outbytesleft) -= 4;
- }
- else
- {
- cd->my_errno = YAZ_ICONV_E2BIG;
- return (size_t)(-1);
- }
- *outbuf = (char *) outp;
- return 0;
-}
-
-static unsigned long lookup_marc8(yaz_iconv_t cd,
- unsigned long x, int *comb,
- const char **page_chr)
-{
- char utf8_buf[7];
- char *utf8_outbuf = utf8_buf;
- size_t utf8_outbytesleft = sizeof(utf8_buf)-1, r;
-
- r = yaz_write_UTF8(cd, x, &utf8_outbuf, &utf8_outbytesleft, 0);
- if (r == (size_t)(-1))
- {
- cd->my_errno = YAZ_ICONV_EILSEQ;
- return 0;
- }
- else
- {
- unsigned char *inp;
- size_t inbytesleft, no_read_sub = 0;
- unsigned long x;
-
- *utf8_outbuf = '\0';
- inp = (unsigned char *) utf8_buf;
- inbytesleft = strlen(utf8_buf);
-
- x = yaz_marc8r_1_conv(inp, inbytesleft, &no_read_sub, comb);
- if (x)
- {
- *page_chr = "\033(B";
- return x;
- }
- x = yaz_marc8r_2_conv(inp, inbytesleft, &no_read_sub, comb);
- if (x)
- {
- *page_chr = "\033g";
- return x;
- }
- x = yaz_marc8r_3_conv(inp, inbytesleft, &no_read_sub, comb);
- if (x)
- {
- *page_chr = "\033b";
- return x;
- }
- x = yaz_marc8r_4_conv(inp, inbytesleft, &no_read_sub, comb);
- if (x)
- {
- *page_chr = "\033p";
- return x;
- }
- x = yaz_marc8r_5_conv(inp, inbytesleft, &no_read_sub, comb);
- if (x)
- {
- *page_chr = "\033(2";
- return x;
- }
- x = yaz_marc8r_6_conv(inp, inbytesleft, &no_read_sub, comb);
- if (x)
- {
- *page_chr = "\033(N";
- return x;
- }
- x = yaz_marc8r_7_conv(inp, inbytesleft, &no_read_sub, comb);
- if (x)
- {
- *page_chr = "\033(3";
- return x;
- }
- x = yaz_marc8r_8_conv(inp, inbytesleft, &no_read_sub, comb);
- if (x)
- {
- *page_chr = "\033(S";
- return x;
- }
- x = yaz_marc8r_9_conv(inp, inbytesleft, &no_read_sub, comb);
- if (x)
- {
- *page_chr = "\033(1";
- return x;
- }
- cd->my_errno = YAZ_ICONV_EILSEQ;
- return x;
- }
-}
-
-static size_t flush_combos(yaz_iconv_t cd,
- char **outbuf, size_t *outbytesleft)
-{
- unsigned long y = cd->write_marc8_last;
- unsigned char byte, second_half = 0;
- char out_buf[10];
- size_t i, out_no = 0;
-
- if (!y)
- return 0;
-
- byte = (unsigned char )((y>>16) & 0xff);
- if (byte)
- out_buf[out_no++] = byte;
- byte = (unsigned char)((y>>8) & 0xff);
- if (byte)
- out_buf[out_no++] = byte;
- byte = (unsigned char )(y & 0xff);
- if (byte)
- out_buf[out_no++] = byte;
-
- if (out_no + cd->write_marc8_comb_no + 1 > *outbytesleft)
- {
- cd->my_errno = YAZ_ICONV_E2BIG;
- return (size_t) (-1);
- }
-
- for (i = 0; i < cd->write_marc8_comb_no; i++)
- {
- /* all MARC-8 combined characters are simple bytes */
- byte = (unsigned char )(cd->write_marc8_comb_ch[i]);
- if (byte == 0xEB)
- second_half = 0xEC;
- else if (byte == 0xFA)
- second_half = 0xFB;
-
- *(*outbuf)++ = byte;
- (*outbytesleft)--;
- }
- memcpy(*outbuf, out_buf, out_no);
- *outbuf += out_no;
- (*outbytesleft) -= out_no;
- if (second_half)
- {
- *(*outbuf)++ = second_half;
- (*outbytesleft)--;
- }
-
- cd->write_marc8_last = 0;
- cd->write_marc8_comb_no = 0;