/* $Id: otherconv.c,v 1.27 2006/05/09 20:51:21 rousseau Exp $ */ /******************************************************************************* * otherconv.c * A module of J-Pilot http://jpilot.org * * Copyright (C) 2004 by Amit Aronovitch * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ******************************************************************************/ /* * General charset conversion library (using gconv) * Convert Palm <-> Unix: * Palm : Any - according to the "other-pda-charset" setup option. * Unix : UTF-8 */ #include "config.h" #include #ifdef ENABLE_GTK2 #include #include #include #include /* To speed up compilation use these instead of glib.h #include #include */ #include "prefs.h" #include "otherconv.h" #include "log.h" static GIConv glob_topda = NULL; static GIConv glob_frompda = NULL; #define HOST_CS "UTF-8" /* You can't do #ifndef __FUNCTION__ */ #if !defined(__GNUC__) && !defined(__IBMC__) #define __FUNCTION__ "" #endif /* * strnlen is not ANSI. * To avoid messing with conflicting declarations, I just implement my own version. * (this is easy & portable might not be very efficient) -- Amit Aronovitch */ size_t oc_strnlen(const char *s, size_t maxlen) { const char *p,*endp; endp = s+maxlen; for (p=s;pmessage : "last char truncated", buf); if (err != NULL) g_error_free(err); else g_free(outbuf); /* convert the head, skip the problematic char, convert the tail */ c = tmp_buf[bytes_read]; tmp_buf[bytes_read] = '\0'; head = (char *)g_convert_with_iconv((gchar *)tmp_buf, oc_strnlen(tmp_buf, buf_len), glob_frompda, &bytes_read, NULL, NULL); tmp_buf[bytes_read] = c; call_depth++; tail = other_to_UTF(tmp_buf + bytes_read +1, buf_len - bytes_read - 1); call_depth--; outbuf_len = strlen(head) +4 + strlen(tail)+1; outbuf = g_malloc(outbuf_len); g_snprintf(outbuf, outbuf_len, "%s\\%02X%s", head, (unsigned char)c, tail); g_free(head); g_free(tail); } #ifdef OTHERCONV_DEBUG jp_logf(JP_LOG_DEBUG, "%s:%s converted to [%s]\n", __FILE__, __FUNCTION__, outbuf); #endif /* * Note: outbuf was allocated by glib, so should be freed with g_free * To be 100% safe, I should have done strncpy to a new malloc-allocated string. * (at least under an 'if (!g_mem_is_system_malloc())' test) * * However, unless you replace the default GMemVTable, freeing with C free should be fine * so I decided this is not worth the overhead -- Amit Aronovitch */ return outbuf; } /* * Conversion to pda encoding using g_iconv */ void UTF_to_other(char *const buf, int buf_len) { gsize inleft,outleft; gchar *inptr, *outptr; size_t rc; char *errstr; char buf_out[1000], *buf_out_ptr = NULL; #ifdef OTHERCONV_DEBUG jp_logf(JP_LOG_DEBUG, "%s:%s reset iconv state...\n", __FILE__, __FUNCTION__); #endif rc = g_iconv(glob_topda, NULL, NULL, NULL, NULL); #ifdef OTHERCONV_DEBUG jp_logf(JP_LOG_DEBUG, "%s:%s converting [%s]\n", __FILE__, __FUNCTION__, buf); #endif inleft = oc_strnlen(buf,buf_len); outleft = buf_len-1; inptr = buf; if (buf_len > sizeof(buf_out)) { buf_out_ptr = malloc(buf_len); if (NULL == buf_out_ptr) { jp_logf(JP_LOG_WARN, "no more memory"); return; } outptr = buf_out_ptr; } else outptr = buf_out; rc = g_iconv(glob_topda, &inptr, &inleft, &outptr, &outleft); *outptr = 0; if (rc<0) { switch (errno) { case EILSEQ: errstr = "iconv: unconvertable sequence at place %d\n"; break; case EINVAL: errstr = "iconv: incomplete UTF-8 sequence at place %d\n"; break; case E2BIG: errstr = "iconv: buffer filled. stopped at place %d\n"; break; default: errstr = "iconv: unexpected error at place %d\n"; } jp_logf(JP_LOG_WARN, errstr, inptr - buf); } if (buf_out_ptr) { g_strlcpy(buf, buf_out_ptr, buf_len); free(buf_out_ptr); } else g_strlcpy(buf, buf_out, buf_len); #ifdef OTHERCONV_DEBUG jp_logf(JP_LOG_DEBUG, "%s:%s converted to [%s]\n", __FILE__, __FUNCTION__, buf); #endif } #else char *other_to_UTF(const char *buf, int buf_len) { return strdup(buf); } void UTF_to_other(char *const buf, int buf_len) { } #endif