1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2024-12-25 04:06:03 +00:00

iconv: outsource code into it's own file

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.
This commit is contained in:
Phil Sutter 2009-10-03 20:01:33 +02:00
parent adf9d23927
commit 1e893ec6e3
7 changed files with 214 additions and 135 deletions

View File

@ -568,6 +568,7 @@ if test "$am_cv_func_iconv" != yes; then
else else
conky_LIBS="$conky_LIBS $LIBICONV" conky_LIBS="$conky_LIBS $LIBICONV"
fi fi
AM_CONDITIONAL(BUILD_ICONV, test "$am_cv_func_iconv" = yes)
dnl dnl
dnl Xext Double-buffering Extension dnl Xext Double-buffering Extension

View File

@ -80,6 +80,7 @@ lua = llua.c llua.h
nvidia = nvidia.c nvidia.h nvidia = nvidia.c nvidia.h
imlib2 = imlib2.c imlib2.h imlib2 = imlib2.c imlib2.h
apcupsd = apcupsd.c apcupsd.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 # make sure the files from above are always included in the distfile
EXTRA_DIST = $(audacious) $(bmpx) $(ibm) $(mpd) $(moc) $(xmms2) $(linux) \ EXTRA_DIST = $(audacious) $(bmpx) $(ibm) $(mpd) $(moc) $(xmms2) $(linux) \
@ -155,6 +156,9 @@ endif
if BUILD_APCUPSD if BUILD_APCUPSD
optional_sources += $(apcupsd) optional_sources += $(apcupsd)
endif endif
if BUILD_ICONV
optional_sources += $(iconv)
endif
# linux takes the standard to the max # linux takes the standard to the max
if BUILD_LINUX if BUILD_LINUX

View File

@ -80,6 +80,9 @@
#include "fonts.h" #include "fonts.h"
#endif #endif
#include "fs.h" #include "fs.h"
#ifdef HAVE_ICONV
#include "iconv_tools.h"
#endif
#include "logging.h" #include "logging.h"
#include "mixer.h" #include "mixer.h"
#include "mail.h" #include "mail.h"
@ -983,7 +986,6 @@ static void generate_text_internal(char *p, int p_max_size,
#ifdef HAVE_ICONV #ifdef HAVE_ICONV
char buff_in[p_max_size]; char buff_in[p_max_size];
buff_in[0] = 0; buff_in[0] = 0;
set_iconv_converting(0);
#endif /* HAVE_ICONV */ #endif /* HAVE_ICONV */
p[0] = 0; p[0] = 0;
@ -2841,12 +2843,10 @@ static void generate_text_internal(char *p, int p_max_size,
#ifdef HAVE_ICONV #ifdef HAVE_ICONV
OBJ(iconv_start) { OBJ(iconv_start) {
set_iconv_converting(1); do_iconv_start(obj);
set_iconv_selected(obj->a);
} }
OBJ(iconv_stop) { OBJ(iconv_stop) {
set_iconv_converting(0); do_iconv_stop();
set_iconv_selected(0);
} }
#endif /* HAVE_ICONV */ #endif /* HAVE_ICONV */
@ -3209,7 +3209,7 @@ static void generate_text_internal(char *p, int p_max_size,
size_t a = strlen(p); size_t a = strlen(p);
#ifdef HAVE_ICONV #ifdef HAVE_ICONV
iconv_convert(a, buff_in, p, p_max_size); iconv_convert(&a, buff_in, p, p_max_size);
#endif /* HAVE_ICONV */ #endif /* HAVE_ICONV */
if (obj->type != OBJ_text && obj->type != OBJ_execp && obj->type != OBJ_execpi if (obj->type != OBJ_text && obj->type != OBJ_execp && obj->type != OBJ_execpi
&& obj->type != OBJ_lua && obj->type != OBJ_lua_parse) { && 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 += a;
p_max_size -= a; p_max_size -= a;
(*p) = 0;
} }
obj = obj->next; obj = obj->next;
} }

View File

@ -39,6 +39,9 @@
#include "fonts.h" #include "fonts.h"
#endif #endif
#include "fs.h" #include "fs.h"
#ifdef HAVE_ICONV
#include "iconv_tools.h"
#endif
#include "logging.h" #include "logging.h"
#include "mixer.h" #include "mixer.h"
#include "mail.h" #include "mail.h"
@ -50,6 +53,10 @@
#include "timeinfo.h" #include "timeinfo.h"
#include "top.h" #include "top.h"
#ifdef NCURSES
#include <ncurses.h>
#endif
/* check for OS and include appropriate headers */ /* check for OS and include appropriate headers */
#if defined(__linux__) #if defined(__linux__)
#include "linux.h" #include "linux.h"
@ -65,107 +72,6 @@ void update_entropy(void);
#include <string.h> #include <string.h>
#include <ctype.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 /* strip a leading /dev/ if any, following symlinks first
* *
* BEWARE: this function returns a pointer to static content * 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); scan_tztime(obj, arg);
#ifdef HAVE_ICONV #ifdef HAVE_ICONV
END OBJ_ARG(iconv_start, 0, "Iconv requires arguments") END OBJ_ARG(iconv_start, 0, "Iconv requires arguments")
char iconv_from[ICONV_CODEPAGE_LENGTH]; init_iconv_start(obj, free_at_crash, arg);
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);
}
}
END OBJ(iconv_stop, 0) END OBJ(iconv_stop, 0)
set_iconv_converting(0); init_iconv_stop();
#endif #endif
END OBJ(totaldown, &update_net_stats) END OBJ(totaldown, &update_net_stats)
if (arg) { if (arg) {

View 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); void scan_mixer_bar(const char *arg, int *a, int *w, int *h);
#endif /* X11 */ #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_ */ #endif /* _CONKY_CORE_H_ */

152
src/iconv_tools.c Normal file
View File

@ -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;
}

41
src/iconv_tools.h Normal file
View File

@ -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 */