iconv: outsource code into it's own file
authorPhil Sutter <phil@nwl.cc>
Sat, 3 Oct 2009 18:01:33 +0000 (20:01 +0200)
committerPhil Sutter <phil@nwl.cc>
Sun, 4 Oct 2009 01:41:45 +0000 (03:41 +0200)
While testing, I found two already existing bugs:
* the variable 'a' passed to iconv_convert() needs to be passed by
  reference in order to allow for the desired side effect.
* Somehow the trailing junk after an iconv_conversion to a shorter
  string messes things up (and gets printed!). I couldn't exactly find
  out why this happens, but setting (*p) = 0; solves this problem.

configure.ac.in
src/Makefile.am
src/conky.c
src/core.c
src/core.h
src/iconv_tools.c [new file with mode: 0644]
src/iconv_tools.h [new file with mode: 0644]

index 924727f..bdfcbe3 100644 (file)
@@ -568,6 +568,7 @@ if test "$am_cv_func_iconv" != yes; then
 else
   conky_LIBS="$conky_LIBS $LIBICONV"
 fi
+AM_CONDITIONAL(BUILD_ICONV, test "$am_cv_func_iconv" = yes)
 
 dnl
 dnl Xext Double-buffering Extension
index e2e3090..ac6f1b8 100644 (file)
@@ -80,6 +80,7 @@ lua = llua.c llua.h
 nvidia = nvidia.c nvidia.h
 imlib2 = imlib2.c imlib2.h
 apcupsd = apcupsd.c apcupsd.h
+iconv = iconv_tools.c iconv_tools.h
 
 # make sure the files from above are always included in the distfile
 EXTRA_DIST = $(audacious) $(bmpx) $(ibm) $(mpd) $(moc) $(xmms2) $(linux) \
@@ -155,6 +156,9 @@ endif
 if BUILD_APCUPSD
 optional_sources += $(apcupsd)
 endif
+if BUILD_ICONV
+optional_sources += $(iconv)
+endif
 
 # linux takes the standard to the max
 if BUILD_LINUX
index 1a5aeaf..812d191 100644 (file)
@@ -80,6 +80,9 @@
 #include "fonts.h"
 #endif
 #include "fs.h"
+#ifdef HAVE_ICONV
+#include "iconv_tools.h"
+#endif
 #include "logging.h"
 #include "mixer.h"
 #include "mail.h"
@@ -983,7 +986,6 @@ static void generate_text_internal(char *p, int p_max_size,
 #ifdef HAVE_ICONV
        char buff_in[p_max_size];
        buff_in[0] = 0;
-       set_iconv_converting(0);
 #endif /* HAVE_ICONV */
 
        p[0] = 0;
@@ -2841,12 +2843,10 @@ static void generate_text_internal(char *p, int p_max_size,
 
 #ifdef HAVE_ICONV
                        OBJ(iconv_start) {
-                               set_iconv_converting(1);
-                               set_iconv_selected(obj->a);
+                               do_iconv_start(obj);
                        }
                        OBJ(iconv_stop) {
-                               set_iconv_converting(0);
-                               set_iconv_selected(0);
+                               do_iconv_stop();
                        }
 #endif /* HAVE_ICONV */
 
@@ -3209,7 +3209,7 @@ static void generate_text_internal(char *p, int p_max_size,
                        size_t a = strlen(p);
 
 #ifdef HAVE_ICONV
-                       iconv_convert(a, buff_in, p, p_max_size);
+                       iconv_convert(&a, buff_in, p, p_max_size);
 #endif /* HAVE_ICONV */
                        if (obj->type != OBJ_text && obj->type != OBJ_execp && obj->type != OBJ_execpi
                                        && obj->type != OBJ_lua && obj->type != OBJ_lua_parse) {
@@ -3217,6 +3217,7 @@ static void generate_text_internal(char *p, int p_max_size,
                        }
                        p += a;
                        p_max_size -= a;
+                       (*p) = 0;
                }
                obj = obj->next;
        }
index 208c6de..14a0f6c 100644 (file)
@@ -39,6 +39,9 @@
 #include "fonts.h"
 #endif
 #include "fs.h"
+#ifdef HAVE_ICONV
+#include "iconv_tools.h"
+#endif
 #include "logging.h"
 #include "mixer.h"
 #include "mail.h"
 #include "timeinfo.h"
 #include "top.h"
 
+#ifdef NCURSES
+#include <ncurses.h>
+#endif
+
 /* check for OS and include appropriate headers */
 #if defined(__linux__)
 #include "linux.h"
@@ -65,107 +72,6 @@ void update_entropy(void);
 #include <string.h>
 #include <ctype.h>
 
-#ifdef HAVE_ICONV
-#include <iconv.h>
-
-#ifdef NCURSES
-#include <ncurses.h>
-#endif
-
-#define ICONV_CODEPAGE_LENGTH 20
-
-int register_iconv(iconv_t *new_iconv);
-
-long iconv_selected;
-long iconv_count = 0;
-char iconv_converting;
-static iconv_t **iconv_cd = 0;
-
-char is_iconv_converting(void)
-{
-       return iconv_converting;
-}
-
-void set_iconv_converting(char i)
-{
-       iconv_converting = i;
-}
-
-long get_iconv_selected(void)
-{
-       return iconv_selected;
-}
-
-void set_iconv_selected(long i)
-{
-       iconv_selected = i;
-}
-
-int register_iconv(iconv_t *new_iconv)
-{
-       iconv_cd = realloc(iconv_cd, sizeof(iconv_t *) * (iconv_count + 1));
-       if (!iconv_cd) {
-               CRIT_ERR(NULL, NULL, "Out of memory");
-       }
-       iconv_cd[iconv_count] = malloc(sizeof(iconv_t));
-       if (!iconv_cd[iconv_count]) {
-               CRIT_ERR(NULL, NULL, "Out of memory");
-       }
-       memcpy(iconv_cd[iconv_count], new_iconv, sizeof(iconv_t));
-       iconv_count++;
-       return iconv_count;
-}
-
-void free_iconv(void)
-{
-       if (iconv_cd) {
-               long i;
-
-               for (i = 0; i < iconv_count; i++) {
-                       if (iconv_cd[i]) {
-                               iconv_close(*iconv_cd[i]);
-                               free(iconv_cd[i]);
-                       }
-               }
-               free(iconv_cd);
-       }
-       iconv_cd = 0;
-}
-
-void iconv_convert(size_t a, char *buff_in, char *p, size_t p_max_size)
-{
-       if (a > 0 && is_iconv_converting() && get_iconv_selected() > 0
-                       && (iconv_cd[iconv_selected - 1] != (iconv_t) (-1))) {
-               int bytes;
-               size_t dummy1, dummy2;
-#ifdef __FreeBSD__
-               const char *ptr = buff_in;
-#else
-               char *ptr = buff_in;
-#endif
-               char *outptr = p;
-
-               dummy1 = dummy2 = a;
-
-               strncpy(buff_in, p, p_max_size);
-
-               iconv(*iconv_cd[iconv_selected - 1], NULL, NULL, NULL, NULL);
-               while (dummy1 > 0) {
-                       bytes = iconv(*iconv_cd[iconv_selected - 1], &ptr, &dummy1,
-                                       &outptr, &dummy2);
-                       if (bytes == -1) {
-                               NORM_ERR("Iconv codeset conversion failed");
-                               break;
-                       }
-               }
-
-               /* It is nessecary when we are converting from multibyte to
-                * singlebyte codepage */
-               a = outptr - p;
-       }
-}
-#endif /* HAVE_ICONV */
-
 /* strip a leading /dev/ if any, following symlinks first
  *
  * BEWARE: this function returns a pointer to static content
@@ -1364,29 +1270,9 @@ struct text_object *construct_text_object(const char *s, const char *arg, long
                scan_tztime(obj, arg);
 #ifdef HAVE_ICONV
        END OBJ_ARG(iconv_start, 0, "Iconv requires arguments")
-               char iconv_from[ICONV_CODEPAGE_LENGTH];
-               char iconv_to[ICONV_CODEPAGE_LENGTH];
-
-               if (is_iconv_converting()) {
-                       CRIT_ERR(obj, free_at_crash, "You must stop your last iconv conversion before "
-                               "starting another");
-               }
-               if (sscanf(arg, "%s %s", iconv_from, iconv_to) != 2) {
-                       CRIT_ERR(obj, free_at_crash, "Invalid arguments for iconv_start");
-               } else {
-                       iconv_t new_iconv;
-
-                       new_iconv = iconv_open(iconv_to, iconv_from);
-                       if (new_iconv == (iconv_t) (-1)) {
-                               NORM_ERR("Can't convert from %s to %s.", iconv_from, iconv_to);
-                       } else {
-                               obj->a = register_iconv(&new_iconv);
-                               set_iconv_converting(1);
-                       }
-               }
+               init_iconv_start(obj, free_at_crash, arg);
        END OBJ(iconv_stop, 0)
-               set_iconv_converting(0);
-
+               init_iconv_stop();
 #endif
        END OBJ(totaldown, &update_net_stats)
                if (arg) {
index c6078c9..1d1c140 100644 (file)
@@ -46,10 +46,4 @@ void free_text_objects(struct text_object *root, int internal);
 void scan_mixer_bar(const char *arg, int *a, int *w, int *h);
 #endif /* X11 */
 
-#ifdef HAVE_ICONV
-void set_iconv_converting(char i);
-void set_iconv_selected(long i);
-void iconv_convert(size_t a, char *buff_in, char *p, size_t p_max_size);
-#endif /* HAVE_ICONV */
-
 #endif /* _CONKY_CORE_H_ */
diff --git a/src/iconv_tools.c b/src/iconv_tools.c
new file mode 100644 (file)
index 0000000..0c4912b
--- /dev/null
@@ -0,0 +1,152 @@
+/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
+ * vim: ts=4 sw=4 noet ai cindent syntax=c
+ *
+ * Conky, a system monitor, based on torsmo
+ *
+ * Any original torsmo code is licensed under the BSD license
+ *
+ * All code written since the fork of torsmo is licensed under the GPL
+ *
+ * Please see COPYING for details
+ *
+ * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
+ * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
+ *     (see AUTHORS)
+ * All rights reserved.
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+#include "logging.h"
+#include "text_object.h"
+#include <iconv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define ICONV_CODEPAGE_LENGTH 20
+
+static long iconv_selected;
+static long iconv_count = 0;
+static char iconv_converting = 0;
+static iconv_t **iconv_cd = 0;
+
+int register_iconv(iconv_t *new_iconv)
+{
+       iconv_cd = realloc(iconv_cd, sizeof(iconv_t *) * (iconv_count + 1));
+       if (!iconv_cd) {
+               CRIT_ERR(NULL, NULL, "Out of memory");
+       }
+       iconv_cd[iconv_count] = malloc(sizeof(iconv_t));
+       if (!iconv_cd[iconv_count]) {
+               CRIT_ERR(NULL, NULL, "Out of memory");
+       }
+       memcpy(iconv_cd[iconv_count], new_iconv, sizeof(iconv_t));
+       iconv_count++;
+       return iconv_count;
+}
+
+void free_iconv(void)
+{
+       long i;
+
+       if (!iconv_cd)
+               return;
+
+       for (i = 0; i < iconv_count; i++) {
+               if (iconv_cd[i]) {
+                       iconv_close(*iconv_cd[i]);
+                       free(iconv_cd[i]);
+               }
+       }
+       free(iconv_cd);
+       iconv_cd = 0;
+}
+
+void iconv_convert(size_t *a, char *buff_in, char *p, size_t p_max_size)
+{
+       if (*a > 0 && iconv_converting && iconv_selected > 0
+                       && (iconv_cd[iconv_selected - 1] != (iconv_t) (-1))) {
+               int bytes;
+               size_t dummy1, dummy2;
+#ifdef __FreeBSD__
+               const char *ptr = buff_in;
+#else
+               char *ptr = buff_in;
+#endif
+               char *outptr = p;
+
+               dummy1 = dummy2 = *a;
+
+               strncpy(buff_in, p, p_max_size);
+
+               iconv(*iconv_cd[iconv_selected - 1], NULL, NULL, NULL, NULL);
+               while (dummy1 > 0) {
+                       bytes = iconv(*iconv_cd[iconv_selected - 1], &ptr, &dummy1,
+                                       &outptr, &dummy2);
+                       if (bytes == -1) {
+                               NORM_ERR("Iconv codeset conversion failed");
+                               break;
+                       }
+               }
+
+               /* It is nessecary when we are converting from multibyte to
+                * singlebyte codepage */
+               //a = outptr - p;
+               //(*a) = *a - dummy2;
+               (*a) = outptr - p;
+       }
+}
+
+void init_iconv_start(struct text_object *obj, void *free_at_crash, const char *arg)
+{
+       char iconv_from[ICONV_CODEPAGE_LENGTH];
+       char iconv_to[ICONV_CODEPAGE_LENGTH];
+
+       if (iconv_converting) {
+               CRIT_ERR(obj, free_at_crash, "You must stop your last iconv conversion before "
+                               "starting another");
+       }
+       if (sscanf(arg, "%s %s", iconv_from, iconv_to) != 2) {
+               CRIT_ERR(obj, free_at_crash, "Invalid arguments for iconv_start");
+       } else {
+               iconv_t new_iconv;
+
+               new_iconv = iconv_open(iconv_to, iconv_from);
+               if (new_iconv == (iconv_t) (-1)) {
+                       NORM_ERR("Can't convert from %s to %s.", iconv_from, iconv_to);
+               } else {
+                       obj->a = register_iconv(&new_iconv);
+                       iconv_converting = 1;
+               }
+       }
+}
+
+void init_iconv_stop(void)
+{
+       iconv_converting = 0;
+}
+
+void do_iconv_start(struct text_object *obj)
+{
+       iconv_converting = 1;
+       iconv_selected = obj->a;
+}
+
+void do_iconv_stop(void)
+{
+       iconv_converting = 0;
+       iconv_selected = 0;
+}
diff --git a/src/iconv_tools.h b/src/iconv_tools.h
new file mode 100644 (file)
index 0000000..73a1467
--- /dev/null
@@ -0,0 +1,41 @@
+/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
+ * vim: ts=4 sw=4 noet ai cindent syntax=c
+ *
+ * Conky, a system monitor, based on torsmo
+ *
+ * Any original torsmo code is licensed under the BSD license
+ *
+ * All code written since the fork of torsmo is licensed under the GPL
+ *
+ * Please see COPYING for details
+ *
+ * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
+ * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
+ *     (see AUTHORS)
+ * All rights reserved.
+ *
+ * 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _ICONV_TOOLS_H
+#define _ICONV_TOOLS_H
+
+void free_iconv(void);
+void iconv_convert(size_t *, char *, char *, size_t);
+void init_iconv_start(struct text_object *, void *, const char *);
+void init_iconv_stop(void);
+void do_iconv_start(struct text_object *);
+void do_iconv_stop(void);
+
+#endif /* _ICONV_TOOLS_H */