double update_interval;
void *global_cpu = NULL;
+int argc_copy;
+char** argv_copy;
/* prototypes for internally used functions */
static void signal_handler(int);
static void generate_text_internal(char *, int, struct text_object,
struct information *);
static int extract_variable_text_internal(struct text_object *,
- const char *, char);
+ const char *);
static void print_version(void)
{
#ifdef TCP_PORT_MONITOR
" * portmon\n"
#endif /* TCP_PORT_MONITOR */
+#ifdef HAVE_CURL
+ " * Curl\n"
+#endif /* HAVE_CURL */
#ifdef RSS
" * RSS\n"
#endif /* RSS */
#ifdef WEATHER
- " * Weather (METAR)\n"
+ " * Weather (NOAA)\n"
+#ifdef XOAP
+ " * Weather (XOAP)\n"
+#endif /* XOAP */
#endif /* WEATHER */
#ifdef HAVE_IWLIB
" * wireless\n"
#ifdef X11
-static void X11_destroy_window(void);
static void X11_create_window(void);
static void X11_initialisation(void);
char *current_config;
/* set to 1 if you want all text to be in uppercase */
-static unsigned int stuff_in_upper_case;
+static unsigned int stuff_in_uppercase;
/* Run how many times? */
static unsigned long total_run_times;
char *overwrite_file = NULL; FILE *overwrite_fpointer = NULL;
char *append_file = NULL; FILE *append_fpointer = NULL;
+/* xoap suffix for weather from weather.com */
+#ifdef WEATHER
+static char *xoap = NULL;
+#endif /* WEATHER */
+
#ifdef X11
static int show_graph_scale;
{
iconv_cd = realloc(iconv_cd, sizeof(iconv_t *) * (iconv_count + 1));
if (!iconv_cd) {
- CRIT_ERR("Out of memory");
+ CRIT_ERR(NULL, NULL, "Out of memory");
}
iconv_cd[iconv_count] = malloc(sizeof(iconv_t));
if (!iconv_cd[iconv_count]) {
- CRIT_ERR("Out of memory");
+ CRIT_ERR(NULL, NULL, "Out of memory");
}
memcpy(iconv_cd[iconv_count], new_iconv, sizeof(iconv_t));
iconv_count++;
return ret;
}
+#define SECRIT_MULTILINE_CHAR '\x02'
+
#ifdef X11
+
static inline int calc_text_width(const char *s, int l)
{
- if ((output_methods & TO_X) == 0)
+ if ((output_methods & TO_X) == 0) {
return 0;
+ }
#ifdef XFT
if (use_xft) {
XGlyphInfo gi;
static char *text_buffer;
-#ifdef X11
-static unsigned int special_index; /* used when drawing */
-#endif /* X11 */
-
/* quite boring functions */
-static inline void for_each_line(char *b, void f(char *))
+static inline void for_each_line(char *b, int f(char *, int))
{
char *ps, *pe;
+ int special_index = 0; /* specials index */
for (ps = b, pe = b; *pe; pe++) {
if (*pe == '\n') {
*pe = '\0';
- f(ps);
+ special_index = f(ps, special_index);
*pe = '\n';
ps = pe + 1;
}
}
if (ps < pe) {
- f(ps);
+ f(ps, special_index);
}
}
case OBJ_eve:
break;
#endif
+#ifdef HAVE_CURL
+ case OBJ_curl:
+ free(data.curl.uri);
+ break;
+#endif
#ifdef RSS
case OBJ_rss:
free(data.rss.uri);
#endif
#ifdef HAVE_LUA
case OBJ_lua:
+ case OBJ_lua_parse:
case OBJ_lua_bar:
#ifdef X11
case OBJ_lua_graph:
free(data.execi.buffer);
break;
case OBJ_texeci:
+ if (data.texeci.p_timed_thread) timed_thread_destroy(data.texeci.p_timed_thread, &data.texeci.p_timed_thread);
free(data.texeci.cmd);
free(data.texeci.buffer);
break;
free(info.x11.desktop.name);
info.x11.desktop.name = NULL;
}
+ if(info.x11.desktop.all_names) {
+ free(info.x11.desktop.all_names);
+ info.x11.desktop.all_names = NULL;
+ }
break;
#endif /* X11 */
}
return 1;
}
+long current_text_color;
+
/* construct_text_object() creates a new text_object */
static struct text_object *construct_text_object(const char *s,
- const char *arg, long line, char allow_threaded, void **ifblock_opaque)
+ const char *arg, long line, void **ifblock_opaque, void *free_at_crash)
{
// struct text_object *obj = new_text_object();
struct text_object *obj = new_text_object_internal();
#define OBJ_IF(a, n) if (strcmp(s, #a) == 0) { \
obj->type = OBJ_##a; need_mask |= (1ULL << n); \
obj_be_ifblock_if(ifblock_opaque, obj); {
-#define OBJ_THREAD(a, n) if (strcmp(s, #a) == 0 && allow_threaded) { \
- obj->type = OBJ_##a; need_mask |= (1ULL << n); {
#define END } } else
#define SIZE_DEFAULTS(arg) { \
}
obj->data.read_tcp.port = htons(obj->data.read_tcp.port);
if(obj->data.read_tcp.port < 1 || obj->data.read_tcp.port > 65535) {
- CRIT_ERR("read_tcp: Needs \"(host) port\" as argument(s)");
+ CRIT_ERR(obj, free_at_crash, "read_tcp: Needs \"(host) port\" as argument(s)");
}
}else{
- CRIT_ERR("read_tcp: Needs \"(host) port\" as argument(s)");
+ CRIT_ERR(obj, free_at_crash, "read_tcp: Needs \"(host) port\" as argument(s)");
}
#if defined(__linux__)
END OBJ(voltage_mv, 0)
#ifdef HAVE_IWLIB
END OBJ(wireless_essid, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
END OBJ(wireless_mode, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
END OBJ(wireless_bitrate, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
END OBJ(wireless_ap, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
END OBJ(wireless_link_qual, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
END OBJ(wireless_link_qual_max, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
END OBJ(wireless_link_qual_perc, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
END OBJ(wireless_link_bar, INFO_NET)
SIZE_DEFAULTS(bar);
if (arg) {
arg = scan_bar(arg, &obj->a, &obj->b);
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
#endif /* HAVE_IWLIB */
if (arg)
obj->data.s = strndup(dev_name(arg), text_buffer_size);
else
- CRIT_ERR("disk_protect needs an argument");
+ CRIT_ERR(obj, free_at_crash, "disk_protect needs an argument");
END OBJ(i8k_version, INFO_I8K)
END OBJ(i8k_bios, INFO_I8K)
END OBJ(i8k_serial, INFO_I8K)
END OBJ(ibm_fan, 0)
END OBJ(ibm_temps, 0)
if (!arg) {
- CRIT_ERR("ibm_temps: needs an argument");
+ CRIT_ERR(obj, free_at_crash, "ibm_temps: needs an argument");
}
if (!isdigit(arg[0]) || strlen(arg) >= 2 || atoi(&arg[0]) >= 8) {
obj->data.sensor = 0;
END OBJ_IF(if_gw, INFO_GW)
END OBJ(ioscheduler, 0)
if (!arg) {
- CRIT_ERR("get_ioscheduler needs an argument (e.g. hda)");
+ CRIT_ERR(obj, free_at_crash, "get_ioscheduler needs an argument (e.g. hda)");
obj->data.s = 0;
} else
obj->data.s = strndup(dev_name(arg), text_buffer_size);
#if defined(__OpenBSD__)
END OBJ(obsd_sensors_temp, 0)
if (!arg) {
- CRIT_ERR("obsd_sensors_temp: needs an argument");
+ CRIT_ERR(obj, free_at_crash, "obsd_sensors_temp: needs an argument");
}
if (!isdigit(arg[0]) || atoi(&arg[0]) < 0
|| atoi(&arg[0]) > OBSD_MAX_SENSORS - 1) {
obj->data.sensor = atoi(&arg[0]);
END OBJ(obsd_sensors_fan, 0)
if (!arg) {
- CRIT_ERR("obsd_sensors_fan: needs 2 arguments (device and sensor "
+ CRIT_ERR(obj, free_at_crash, "obsd_sensors_fan: needs 2 arguments (device and sensor "
"number)");
}
if (!isdigit(arg[0]) || atoi(&arg[0]) < 0
obj->data.sensor = atoi(&arg[0]);
END OBJ(obsd_sensors_volt, 0)
if (!arg) {
- CRIT_ERR("obsd_sensors_volt: needs 2 arguments (device and sensor "
+ CRIT_ERR(obj, free_at_crash, "obsd_sensors_volt: needs 2 arguments (device and sensor "
"number)");
}
if (!isdigit(arg[0]) || atoi(&arg[0]) < 0
#ifdef X11
if (output_methods & TO_X) {
obj->data.l = arg ? get_x11_color(arg) : default_fg_color;
+ current_text_color = obj->data.l;
}
#endif /* X11 */
END OBJ(color0, 0)
obj->data.l = color0;
+ current_text_color = obj->data.l;
END OBJ(color1, 0)
obj->data.l = color1;
+ current_text_color = obj->data.l;
END OBJ(color2, 0)
obj->data.l = color2;
+ current_text_color = obj->data.l;
END OBJ(color3, 0)
obj->data.l = color3;
+ current_text_color = obj->data.l;
END OBJ(color4, 0)
obj->data.l = color4;
+ current_text_color = obj->data.l;
END OBJ(color5, 0)
obj->data.l = color5;
+ current_text_color = obj->data.l;
END OBJ(color6, 0)
obj->data.l = color6;
+ current_text_color = obj->data.l;
END OBJ(color7, 0)
obj->data.l = color7;
+ current_text_color = obj->data.l;
END OBJ(color8, 0)
obj->data.l = color8;
+ current_text_color = obj->data.l;
END OBJ(color9, 0)
obj->data.l = color9;
+ current_text_color = obj->data.l;
#ifdef X11
END OBJ(font, 0)
obj->data.s = scan_font(arg);
END OBJ(conky_build_arch, 0)
END OBJ(downspeed, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
END OBJ(downspeedf, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
#ifdef X11
// default to DEFAULTNETDEV
buf = strndup(buf ? buf : DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
#endif /* X11 */
END OBJ(else, 0)
obj->data.execi.cmd = strndup(arg + n, text_buffer_size);
obj->data.execi.buffer = malloc(text_buffer_size);
}
- END OBJ_THREAD(texeci, 0)
+ END OBJ(texeci, 0)
int n;
if (!arg || sscanf(arg, "%f %n", &obj->data.texeci.interval, &n) <= 0) {
}
} else OBJ(addr, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
#if defined(__linux__)
END OBJ(addrs, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
#endif /* __linux__ */
if (arg) {
obj->data.s = strndup(arg, text_buffer_size);
}else{
- CRIT_ERR("lines needs a argument");
+ CRIT_ERR(obj, free_at_crash, "lines needs a argument");
}
END OBJ(words, 0)
if (arg) {
obj->data.s = strndup(arg, text_buffer_size);
}else{
- CRIT_ERR("words needs a argument");
+ CRIT_ERR(obj, free_at_crash, "words needs a argument");
}
END OBJ(loadavg, INFO_LOADAVG)
int a = 1, b = 2, c = 3, r = 3;
obj->data.ifblock.s = strndup(arg, text_buffer_size);
obj->sub = malloc(sizeof(struct text_object));
extract_variable_text_internal(obj->sub,
- obj->data.ifblock.s, 0);
+ obj->data.ifblock.s);
}
END OBJ_IF(if_match, 0)
if (!arg) {
obj->data.ifblock.s = strndup(arg, text_buffer_size);
obj->sub = malloc(sizeof(struct text_object));
extract_variable_text_internal(obj->sub,
- obj->data.ifblock.s, 0);
+ obj->data.ifblock.s);
}
END OBJ_IF(if_existing, 0)
if (!arg) {
#ifdef HAVE_ICONV
END OBJ(iconv_start, 0)
if (iconv_converting) {
- CRIT_ERR("You must stop your last iconv conversion before "
+ CRIT_ERR(obj, free_at_crash, "You must stop your last iconv conversion before "
"starting another");
}
if (arg) {
char iconv_to[CODEPAGE_LENGTH];
if (sscanf(arg, "%s %s", iconv_from, iconv_to) != 2) {
- CRIT_ERR("Invalid arguments for iconv_start");
+ CRIT_ERR(obj, free_at_crash, "Invalid arguments for iconv_start");
} else {
iconv_t new_iconv;
}
}
} else {
- CRIT_ERR("Iconv requires arguments");
+ CRIT_ERR(obj, free_at_crash, "Iconv requires arguments");
}
END OBJ(iconv_stop, 0)
iconv_converting = 0;
#endif
END OBJ(totaldown, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
END OBJ(totalup, INFO_NET)
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
END OBJ(updates, 0)
END OBJ_IF(if_updatenr, 0)
obj->data.ifblock.i = arg ? atoi(arg) : 0;
- if(obj->data.ifblock.i == 0) CRIT_ERR("if_updatenr needs a number above 0 as argument");
+ if(obj->data.ifblock.i == 0) CRIT_ERR(obj, free_at_crash, "if_updatenr needs a number above 0 as argument");
updatereset = obj->data.ifblock.i > updatereset ? obj->data.ifblock.i : updatereset;
END OBJ(alignr, 0)
obj->data.i = arg ? atoi(arg) : 0;
obj->data.i = arg ? atoi(arg) : 0;
END OBJ(upspeed, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
END OBJ(upspeedf, INFO_NET)
if (arg) {
- obj->data.net = get_net_stat(arg);
+ obj->data.net = get_net_stat(arg, obj, free_at_crash);
} else {
// default to DEFAULTNETDEV
char *buf = strndup(DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
}
// default to DEFAULTNETDEV
buf = strndup(buf ? buf : DEFAULTNETDEV, text_buffer_size);
- obj->data.net = get_net_stat(buf);
+ obj->data.net = get_net_stat(buf, obj, free_at_crash);
free(buf);
#endif
END OBJ(uptime_short, INFO_UPTIME)
END OBJ(apm_battery_life, 0)
END OBJ(apm_battery_time, 0)
#endif /* __FreeBSD__ */
- END OBJ_THREAD(imap_unseen, 0)
+ END OBJ(imap_unseen, 0)
if (arg) {
// proccss
obj->data.mail = parse_mail_args(IMAP_TYPE, arg);
} else {
obj->char_b = 1;
}
- END OBJ_THREAD(imap_messages, 0)
+ END OBJ(imap_messages, 0)
if (arg) {
// proccss
obj->data.mail = parse_mail_args(IMAP_TYPE, arg);
} else {
obj->char_b = 1;
}
- END OBJ_THREAD(pop3_unseen, 0)
+ END OBJ(pop3_unseen, 0)
if (arg) {
// proccss
obj->data.mail = parse_mail_args(POP3_TYPE, arg);
} else {
obj->char_b = 1;
}
- END OBJ_THREAD(pop3_used, 0)
+ END OBJ(pop3_used, 0)
if (arg) {
// proccss
obj->data.mail = parse_mail_args(POP3_TYPE, arg);
if (info.audacious.max_title_len > 0) {
info.audacious.max_title_len++;
} else {
- CRIT_ERR("audacious_title: invalid length argument");
+ CRIT_ERR(obj, free_at_crash, "audacious_title: invalid length argument");
}
}
END OBJ(audacious_length, INFO_AUDACIOUS)
init_eve();
} else {
- CRIT_ERR("eve needs arguments: <userid> <apikey> <characterid>");
+ CRIT_ERR(obj, free_at_crash, "eve needs arguments: <userid> <apikey> <characterid>");
+ }
+#endif
+#ifdef HAVE_CURL
+ END OBJ(curl, 0)
+ if (arg) {
+ int argc;
+ float interval;
+ char *uri = (char *) malloc(128 * sizeof(char));
+
+ argc = sscanf(arg, "%127s %f", uri, &interval);
+ if (argc == 2) {
+ obj->data.curl.uri = uri;
+ obj->data.curl.interval = interval > 0 ? interval * 60 : 15*60;
+ } else {
+ ERR("wrong number of arguments for $curl");
+ }
+ } else {
+ CRIT_ERR(obj, free_at_crash, "curl needs arguments: <uri> <interval in minutes>");
}
#endif
#ifdef RSS
END OBJ(rss, 0)
if (arg) {
- int argc, delay, act_par;
+ float interval;
+ int argc, act_par;
unsigned int nrspaces = 0;
char *uri = (char *) malloc(128 * sizeof(char));
char *action = (char *) malloc(64 * sizeof(char));
- argc = sscanf(arg, "%127s %d %63s %d %u", uri, &delay, action,
+ argc = sscanf(arg, "%127s %f %63s %d %u", uri, &interval, action,
&act_par, &nrspaces);
- obj->data.rss.uri = uri;
- obj->data.rss.delay = delay;
- obj->data.rss.action = action;
- obj->data.rss.act_par = act_par;
- obj->data.rss.nrspaces = nrspaces;
-
- init_rss_info();
+ if (argc == 5) {
+ obj->data.rss.uri = uri;
+ obj->data.rss.interval = interval > 0 ? interval * 60 : 15*60;
+ obj->data.rss.action = action;
+ obj->data.rss.act_par = act_par;
+ obj->data.rss.nrspaces = nrspaces;
+ } else {
+ ERR("wrong number of arguments for $rss");
+ }
} else {
- CRIT_ERR("rss needs arguments: <uri> <delay in minutes> <action> "
+ CRIT_ERR(obj, free_at_crash, "rss needs arguments: <uri> <interval in minutes> <action> "
"[act_par] [spaces in front]");
}
#endif
#ifdef WEATHER
- END OBJ_THREAD(weather, 0)
+ END OBJ(weather, 0)
if (arg) {
- int argc, interval;
- char *icao = (char *) malloc(5 * sizeof(char));
+ int argc;
+ float interval;
+ char *locID = (char *) malloc(9 * sizeof(char));
char *uri = (char *) malloc(128 * sizeof(char));
char *data_type = (char *) malloc(32 * sizeof(char));
char *tmp_p;
- argc = sscanf(arg, "%119s %4s %31s %d", uri, icao, data_type, &interval);
+ argc = sscanf(arg, "%119s %8s %31s %f", uri, locID, data_type, &interval);
- //icao MUST BE upper-case
- tmp_p = icao;
- while (*tmp_p) {
- *tmp_p = toupper(*tmp_p);
- tmp_p++;
- }
+ if (argc >= 3) {
+ /* locID MUST BE upper-case */
+ tmp_p = locID;
+ while (*tmp_p) {
+ *tmp_p = toupper(*tmp_p);
+ tmp_p++;
+ }
+
+ /* Construct complete uri */
+ if (strstr(uri, "xoap.weather.com")) {
+ if(xoap != NULL) {
+ strcat(uri, locID);
+ strcat(uri, xoap);
+ } else {
+ free(uri);
+ uri = NULL;
+ }
+ } else if (strstr(uri, "weather.noaa.gov")) {
+ strcat(uri, locID);
+ strcat(uri, ".TXT");
+ } else if (!strstr(uri, "localhost") && !strstr(uri, "127.0.0.1")) {
+ CRIT_ERR(obj, free_at_crash, \
+ "could not recognize the weather uri");
+ }
+ obj->data.weather.uri = uri;
+ obj->data.weather.data_type = data_type;
- strcat(uri, icao);
- strcat(uri, ".TXT");
- obj->data.weather.uri = uri;
+ /* Limit the data retrieval interval to half hour min */
+ if (interval < 30) {
+ interval = 30;
+ }
- obj->data.weather.data_type = data_type;
+ /* Convert to seconds */
+ obj->data.weather.interval = interval * 60;
+ free(locID);
- // The data retrieval interval is limited to half an hour
- if (interval < 30) {
- interval = 30;
+ DBGP("weather: fetching %s from %s every %d seconds", \
+ data_type, uri, obj->data.weather.interval);
+ } else {
+ ERR("wrong number of arguments for $weather");
}
- obj->data.weather.interval = interval * 60; // convert to seconds
- free(icao);
} else {
- CRIT_ERR("weather needs arguments: <uri> <icao> <data_type> [interval in minutes]");
+ CRIT_ERR(obj, free_at_crash, "weather needs arguments: <uri> <locID> <data_type> [interval in minutes]");
}
#endif
#ifdef HAVE_LUA
if (arg) {
obj->data.s = strndup(arg, text_buffer_size);
} else {
- CRIT_ERR("lua needs arguments: <function name> [function parameters]");
+ CRIT_ERR(obj, free_at_crash, "lua needs arguments: <function name> [function parameters]");
}
END OBJ(lua_parse, 0)
if (arg) {
obj->data.s = strndup(arg, text_buffer_size);
} else {
- CRIT_ERR("lua_parse needs arguments: <function name> [function parameters]");
+ CRIT_ERR(obj, free_at_crash, "lua_parse needs arguments: <function name> [function parameters]");
}
END OBJ(lua_bar, 0)
SIZE_DEFAULTS(bar);
if(arg) {
obj->data.s = strndup(arg, text_buffer_size);
} else {
- CRIT_ERR("lua_bar needs arguments: <height>,<width> <function name> [function parameters]");
+ CRIT_ERR(obj, free_at_crash, "lua_bar needs arguments: <height>,<width> <function name> [function parameters]");
}
} else {
- CRIT_ERR("lua_bar needs arguments: <height>,<width> <function name> [function parameters]");
+ CRIT_ERR(obj, free_at_crash, "lua_bar needs arguments: <height>,<width> <function name> [function parameters]");
}
#ifdef X11
END OBJ(lua_graph, 0)
if (buf) {
obj->data.s = buf;
} else {
- CRIT_ERR("lua_graph needs arguments: <function name> [height],[width] [gradient colour 1] [gradient colour 2] [scale] [-t] [-l]");
+ CRIT_ERR(obj, free_at_crash, "lua_graph needs arguments: <function name> [height],[width] [gradient colour 1] [gradient colour 2] [scale] [-t] [-l]");
}
} else {
- CRIT_ERR("lua_graph needs arguments: <function name> [height],[width] [gradient colour 1] [gradient colour 2] [scale] [-t] [-l]");
+ CRIT_ERR(obj, free_at_crash, "lua_graph needs arguments: <function name> [height],[width] [gradient colour 1] [gradient colour 2] [scale] [-t] [-l]");
}
END OBJ(lua_gauge, 0)
SIZE_DEFAULTS(gauge);
if (arg) {
obj->data.s = strndup(arg, text_buffer_size);
} else {
- CRIT_ERR("lua_gauge needs arguments: <height>,<width> <function name> [function parameters]");
+ CRIT_ERR(obj, free_at_crash, "lua_gauge needs arguments: <height>,<width> <function name> [function parameters]");
}
} else {
- CRIT_ERR("lua_gauge needs arguments: <height>,<width> <function name> [function parameters]");
+ CRIT_ERR(obj, free_at_crash, "lua_gauge needs arguments: <height>,<width> <function name> [function parameters]");
}
#endif /* X11 */
#endif /* HAVE_LUA */
END OBJ(blink, 0)
if(arg) {
obj->sub = malloc(sizeof(struct text_object));
- extract_variable_text_internal(obj->sub, arg, 0);
+ extract_variable_text_internal(obj->sub, arg);
}else{
- CRIT_ERR("blink needs a argument");
+ CRIT_ERR(obj, free_at_crash, "blink needs a argument");
}
END OBJ(to_bytes, 0)
if(arg) {
obj->sub = malloc(sizeof(struct text_object));
- extract_variable_text_internal(obj->sub, arg, 0);
+ extract_variable_text_internal(obj->sub, arg);
}else{
- CRIT_ERR("to_bytes needs a argument");
+ CRIT_ERR(obj, free_at_crash, "to_bytes needs a argument");
}
END OBJ(scroll, 0)
- int n1, n2;
+ int n1 = 0, n2 = 0;
+ obj->data.scroll.resetcolor = current_text_color;
obj->data.scroll.step = 1;
if (arg && sscanf(arg, "%u %n", &obj->data.scroll.show, &n1) > 0) {
- if (sscanf(arg + n1, "%u %n", &obj->data.scroll.step, &n2) > 0)
+ sscanf(arg + n1, "%u %n", &obj->data.scroll.step, &n2);
+ if (*(arg + n1 + n2)) {
n1 += n2;
- obj->data.scroll.text = strndup(arg + n1, text_buffer_size);
+ } else {
+ obj->data.scroll.step = 1;
+ }
+ obj->data.scroll.text = malloc(strlen(arg + n1) + obj->data.scroll.show + 1);
+ for(n2 = 0; (unsigned int) n2 < obj->data.scroll.show; n2++) {
+ obj->data.scroll.text[n2] = ' ';
+ }
+ obj->data.scroll.text[n2] = 0;
+ strcat(obj->data.scroll.text, arg + n1);
obj->data.scroll.start = 0;
obj->sub = malloc(sizeof(struct text_object));
extract_variable_text_internal(obj->sub,
- obj->data.scroll.text, 0);
+ obj->data.scroll.text);
} else {
- CRIT_ERR("scroll needs arguments: <length> [<step>] <text>");
+ CRIT_ERR(obj, free_at_crash, "scroll needs arguments: <length> [<step>] <text>");
}
END OBJ(combine, 0)
if(arg) {
obj->data.combine.right[endvar[1] - startvar[1]] = 0;
obj->sub = malloc(sizeof(struct text_object));
- extract_variable_text_internal(obj->sub, obj->data.combine.left, 0);
+ extract_variable_text_internal(obj->sub, obj->data.combine.left);
obj->sub->sub = malloc(sizeof(struct text_object));
- extract_variable_text_internal(obj->sub->sub, obj->data.combine.right, 0);
+ extract_variable_text_internal(obj->sub->sub, obj->data.combine.right);
} else {
- CRIT_ERR("combine needs arguments: <text1> <text2>");
+ CRIT_ERR(obj, free_at_crash, "combine needs arguments: <text1> <text2>");
}
} else {
- CRIT_ERR("combine needs arguments: <text1> <text2>");
+ CRIT_ERR(obj, free_at_crash, "combine needs arguments: <text1> <text2>");
}
#ifdef NVIDIA
END OBJ(nvidia, 0)
if (!arg) {
- CRIT_ERR("nvidia needs an argument\n");
+ CRIT_ERR(obj, free_at_crash, "nvidia needs an argument\n");
} else if (set_nvidia_type(&obj->data.nvidia, arg)) {
- CRIT_ERR("nvidia: invalid argument"
+ CRIT_ERR(obj, free_at_crash, "nvidia: invalid argument"
" specified: '%s'\n", arg);
}
#endif /* NVIDIA */
char host[64];
int port;
if (sscanf(arg, "%63s %d", host, &port) != 2) {
- CRIT_ERR("apcupsd needs arguments: <host> <port>");
+ CRIT_ERR(obj, free_at_crash, "apcupsd needs arguments: <host> <port>");
} else {
info.apcupsd.port = htons(port);
strncpy(info.apcupsd.host, host, sizeof(info.apcupsd.host));
}
} else {
- CRIT_ERR("apcupsd needs arguments: <host> <port>");
+ CRIT_ERR(obj, free_at_crash, "apcupsd needs arguments: <host> <port>");
}
END OBJ(apcupsd_name, INFO_APCUPSD)
END OBJ(apcupsd_model, INFO_APCUPSD)
*(p - 1) = '\0';
} else {
// we ran into the end of string without finding a closing }, bark
- CRIT_ERR("cannot find a closing '}' in template expansion");
+ CRIT_ERR(NULL, NULL, "cannot find a closing '}' in template expansion");
}
} else {
templ = p + 1;
return folded;
}
-static int extract_variable_text_internal(struct text_object *retval, const char *const_p, char allow_threaded)
+static int extract_variable_text_internal(struct text_object *retval, const char *const_p)
{
struct text_object *obj;
char *p, *s, *orig_p;
}
obj = construct_text_object(buf, arg,
- line, allow_threaded,
- &ifblock_opaque);
+ line, &ifblock_opaque, orig_p);
if (obj != NULL) {
append_object(retval, obj);
}
text_buffer = 0;
}
- extract_variable_text_internal(&global_root_object, p, 1);
+ extract_variable_text_internal(&global_root_object, p);
}
void parse_conky_vars(struct text_object *root, char *txt, char *p, struct information *cur)
{
- extract_variable_text_internal(root, txt, 0);
+ extract_variable_text_internal(root, txt);
generate_text_internal(p, max_user_text, *root, cur);
return;
}
return barnum;
}
+/* substitutes all occurrences of '\n' with SECRIT_MULTILINE_CHAR, which allows
+ * multiline objects like $exec work with $align[rc] and friends
+ */
+void substitute_newlines(char *p, long l)
+{
+ char *s = p;
+ if (l < 0) return;
+ while (p && *p && p < s + l) {
+ if (*p == '\n') {
+ /* only substitute if it's not the last newline */
+ *p = SECRIT_MULTILINE_CHAR;
+ }
+ p++;
+ }
+}
+
static void generate_text_internal(char *p, int p_max_size,
struct text_object root, struct information *cur)
{
p[0] = 0;
obj = root.next;
while (obj && p_max_size > 0) {
- needed = 0; // reset for top stuff
+ needed = 0; /* reset for top stuff */
/* IFBLOCK jumping algorithm
*
if (obj->data.cpu_index > info.cpu_count) {
ERR("obj->data.cpu_index %i info.cpu_count %i",
obj->data.cpu_index, info.cpu_count);
- CRIT_ERR("attempting to use more CPUs than you have!");
+ CRIT_ERR(NULL, NULL, "attempting to use more CPUs than you have!");
}
percent_print(p, p_max_size,
round_to_int(cur->cpu_usage[obj->data.cpu_index] * 100.0));
}
#if defined(__linux__)
OBJ(addrs) {
- if(NULL != obj->data.net->addrs && strlen(obj->data.net->addrs) > 2)
- {
+ if (NULL != obj->data.net->addrs && strlen(obj->data.net->addrs) > 2) {
obj->data.net->addrs[strlen(obj->data.net->addrs) - 2] = 0; /* remove ", " from end of string */
strcpy(p, obj->data.net->addrs);
+ } else {
+ strcpy(p, "0.0.0.0");
}
- else
- strcpy(p, "0.0.0.0");
- }
+ }
#endif /* __linux__ */
#if defined(IMLIB2) && defined(X11)
OBJ(image) {
if (!obj->data.texeci.p_timed_thread) {
ERR("Error creating texeci timed thread");
}
- timed_thread_register(obj->data.texeci.p_timed_thread,
- &obj->data.texeci.p_timed_thread);
+ /*
+ * note that we don't register this thread with the
+ * timed_thread list, because we destroy it manually
+ */
if (timed_thread_run(obj->data.texeci.p_timed_thread)) {
ERR("Error running texeci timed thread");
}
snprintf(p, p_max_size, "%s", skill);
}
#endif
+#ifdef HAVE_CURL
+ OBJ(curl) {
+ if (obj->data.curl.uri != NULL) {
+ ccurl_process_info(p, p_max_size, obj->data.curl.uri, obj->data.curl.interval);
+ } else {
+ ERR("error processing Curl data");
+ }
+ }
+#endif
#ifdef RSS
OBJ(rss) {
- PRSS *data = get_rss_info(obj->data.rss.uri,
- obj->data.rss.delay);
- char *str;
-
- if (data == NULL) {
- snprintf(p, p_max_size, "prss: Error reading RSS data\n");
+ if (obj->data.rss.uri != NULL) {
+ rss_process_info(p, p_max_size, obj->data.rss.uri, obj->data.rss.action, obj->data.rss.act_par, obj->data.rss.interval, obj->data.rss.nrspaces);
} else {
- if (strcmp(obj->data.rss.action, "feed_title") == EQUAL) {
- str = data->title;
- // remove trailing new line if one exists
- if (str[strlen(str) - 1] == '\n') {
- str[strlen(str) - 1] = 0;
- }
- snprintf(p, p_max_size, "%s", str);
- } else if (strcmp(obj->data.rss.action, "item_title") == EQUAL) {
- if (obj->data.rss.act_par < data->item_count) {
- str = data->items[obj->data.rss.act_par].title;
- // remove trailing new line if one exists
- if (str[strlen(str) - 1] == '\n') {
- str[strlen(str) - 1] = 0;
- }
- snprintf(p, p_max_size, "%s", str);
- }
- } else if (strcmp(obj->data.rss.action, "item_desc") == EQUAL) {
- if (obj->data.rss.act_par < data->item_count) {
- str =
- data->items[obj->data.rss.act_par].description;
- // remove trailing new line if one exists
- if (str[strlen(str) - 1] == '\n') {
- str[strlen(str) - 1] = 0;
- }
- snprintf(p, p_max_size, "%s", str);
- }
- } else if (strcmp(obj->data.rss.action, "item_titles") == EQUAL) {
- if (data->item_count > 0) {
- int itmp;
- int show;
- //'tmpspaces' is a string with spaces too be placed in front of each title
- char *tmpspaces = malloc(obj->data.rss.nrspaces + 1);
- memset(tmpspaces, ' ', obj->data.rss.nrspaces);
- tmpspaces[obj->data.rss.nrspaces]=0;
-
- p[0] = 0;
-
- if (obj->data.rss.act_par > data->item_count) {
- show = data->item_count;
- } else {
- show = obj->data.rss.act_par;
- }
- for (itmp = 0; itmp < show; itmp++) {
- PRSS_Item *item = &data->items[itmp];
-
- str = item->title;
- if (str) {
- // don't add new line before first item
- if (itmp > 0) {
- strncat(p, "\n", p_max_size);
- }
- /* remove trailing new line if one exists,
- * we have our own */
- if (str[strlen(str) - 1] == '\n') {
- str[strlen(str) - 1] = 0;
- }
- strncat(p, tmpspaces, p_max_size);
- strncat(p, str, p_max_size);
- }
- }
- free(tmpspaces);
- }
- }
+ ERR("error processing RSS data");
}
}
#endif
#ifdef WEATHER
OBJ(weather) {
- process_weather_info(p, p_max_size, obj->data.weather.uri, obj->data.weather.data_type, obj->data.weather.interval);
+ if (obj->data.weather.uri != NULL) {
+ weather_process_info(p, p_max_size, obj->data.weather.uri, obj->data.weather.data_type, obj->data.weather.interval);
+ } else {
+ ERR("error processing weather data, check that you have a valid XOAP key if using XOAP.");
+ }
}
#endif
#ifdef HAVE_LUA
char *str = llua_getstring(obj->data.s);
if (str) {
evaluate(str, p);
+ free(str);
}
}
OBJ(lua_bar) {
}
}
#ifdef X11
+#define NOT_IN_X "Not running in X"
OBJ(monitor) {
- snprintf(p, p_max_size, "%d", cur->x11.monitor.current);
+ if(x_initialised != YES) {
+ strncpy(p, NOT_IN_X, p_max_size);
+ }else{
+ snprintf(p, p_max_size, "%d", cur->x11.monitor.current);
+ }
}
OBJ(monitor_number) {
- snprintf(p, p_max_size, "%d", cur->x11.monitor.number);
+ if(x_initialised != YES) {
+ strncpy(p, NOT_IN_X, p_max_size);
+ }else{
+ snprintf(p, p_max_size, "%d", cur->x11.monitor.number);
+ }
}
OBJ(desktop) {
- snprintf(p, p_max_size, "%d", cur->x11.desktop.current);
+ if(x_initialised != YES) {
+ strncpy(p, NOT_IN_X, p_max_size);
+ }else{
+ snprintf(p, p_max_size, "%d", cur->x11.desktop.current);
+ }
}
OBJ(desktop_number) {
- snprintf(p, p_max_size, "%d", cur->x11.desktop.number);
+ if(x_initialised != YES) {
+ strncpy(p, NOT_IN_X, p_max_size);
+ }else{
+ snprintf(p, p_max_size, "%d", cur->x11.desktop.number);
+ }
}
OBJ(desktop_name) {
- if(cur->x11.desktop.name != NULL) {
- strncpy(p, cur->x11.desktop.name, p_max_size);
- }
+ if(x_initialised != YES) {
+ strncpy(p, NOT_IN_X, p_max_size);
+ }else if(cur->x11.desktop.name != NULL) {
+ strncpy(p, cur->x11.desktop.name, p_max_size);
+ }
}
#endif /* X11 */
OBJ(to_bytes) {
char buf[max_user_text];
long long bytes;
- char unit[16]; //16 because we can also have long names (like mega-bytes)
+ char unit[16]; // 16 because we can also have long names (like mega-bytes)
generate_text_internal(buf, max_user_text, *obj->sub, cur);
if(sscanf(buf, "%lli%s", &bytes, unit) == 2 && strlen(unit) < 16){
snprintf(p, p_max_size, "%s", buf);
}
OBJ(scroll) {
- unsigned int j;
- char *tmp, buf[max_user_text];
+ unsigned int j, colorchanges = 0, frontcolorchanges = 0, visibcolorchanges = 0, strend;
+ char *pwithcolors;
+ char buf[max_user_text];
generate_text_internal(buf, max_user_text,
*obj->sub, cur);
-
- if (strlen(buf) <= obj->data.scroll.show) {
- snprintf(p, p_max_size, "%s", buf);
- break;
- }
-#define LINESEPARATOR '|'
- //place all the lines behind each other with LINESEPARATOR between them
for(j = 0; buf[j] != 0; j++) {
- if(buf[j]=='\n') {
+ switch(buf[j]) {
+ case '\n': //place all the lines behind each other with LINESEPARATOR between them
+#define LINESEPARATOR '|'
buf[j]=LINESEPARATOR;
+ break;
+ case SPECIAL_CHAR:
+ colorchanges++;
+ break;
}
}
- //scroll the output obj->data.scroll.start places by copying that many chars from
- //the front of the string to tmp, scrolling the rest to the front and placing tmp
- //at the back of the string
- tmp = calloc(obj->data.scroll.start + 1, sizeof(char));
- strncpy(tmp, buf, obj->data.scroll.start); tmp[obj->data.scroll.start] = 0;
- for(j = obj->data.scroll.start; buf[j] != 0; j++){
- buf[j - obj->data.scroll.start] = buf[j];
- }
- strcpy(&buf[j - obj->data.scroll.start], tmp);
- free(tmp);
- //only show the requested number of chars
- if(obj->data.scroll.show < j) {
- buf[obj->data.scroll.show] = 0;
- }
- //next time, scroll a place more or reset scrolling if we are at the end
+ //no scrolling necessary if the length of the text to scroll is too short
+ if (strlen(buf) - colorchanges <= obj->data.scroll.show) {
+ snprintf(p, p_max_size, "%s", buf);
+ break;
+ }
+ //make sure a colorchange at the front is not part of the string we are going to show
+ while(*(buf + obj->data.scroll.start) == SPECIAL_CHAR) {
+ obj->data.scroll.start++;
+ }
+ //place all chars that should be visible in p, including colorchanges
+ for(j=0; j < obj->data.scroll.show + visibcolorchanges; j++) {
+ p[j] = *(buf + obj->data.scroll.start + j);
+ if(p[j] == SPECIAL_CHAR) {
+ visibcolorchanges++;
+ }
+ //if there is still room fill it with spaces
+ if( ! p[j]) break;
+ }
+ for(; j < obj->data.scroll.show + visibcolorchanges; j++) {
+ p[j] = ' ';
+ }
+ p[j] = 0;
+ //count colorchanges in front of the visible part and place that many colorchanges in front of the visible part
+ for(j = 0; j < obj->data.scroll.start; j++) {
+ if(buf[j] == SPECIAL_CHAR) frontcolorchanges++;
+ }
+ pwithcolors=malloc(strlen(p) + 1 + colorchanges - visibcolorchanges);
+ for(j = 0; j < frontcolorchanges; j++) {
+ pwithcolors[j] = SPECIAL_CHAR;
+ }
+ pwithcolors[j] = 0;
+ strcat(pwithcolors,p);
+ strend = strlen(pwithcolors);
+ //and place the colorchanges not in front or in the visible part behind the visible part
+ for(j = 0; j < colorchanges - frontcolorchanges - visibcolorchanges; j++) {
+ pwithcolors[strend + j] = SPECIAL_CHAR;
+ }
+ pwithcolors[strend + j] = 0;
+ strcpy(p, pwithcolors);
+ free(pwithcolors);
+ //scroll
obj->data.scroll.start += obj->data.scroll.step;
- if(obj->data.scroll.start >= j){
+ if(buf[obj->data.scroll.start] == 0){
obj->data.scroll.start = 0;
}
- snprintf(p, p_max_size, "%s", buf);
+#ifdef X11
+ //reset color when scroll is finished
+ new_fg(p + strlen(p), obj->data.scroll.resetcolor);
+#endif
}
OBJ(combine) {
char buf[2][max_user_text];
}
strcat(p, "\n");
#ifdef HAVE_OPENMP
- #pragma omp parallel for
+ #pragma omp parallel for schedule(dynamic,10)
#endif /* HAVE_OPENMP */
for(i=0; i<2; i++) if(current[i]) current[i]=current[i]->next;
}
#ifdef HAVE_OPENMP
- #pragma omp parallel for
+ #pragma omp parallel for schedule(dynamic,10)
#endif /* HAVE_OPENMP */
for(i=0; i<2; i++) {
while(ll_rows[i] != NULL) {
a = outptr - p;
}
#endif /* HAVE_ICONV */
+ if (obj->type != OBJ_text) {
+ substitute_newlines(p, a - 2);
+ }
p += a;
p_max_size -= a;
}
generate_text_internal(p, max_user_text, global_root_object, cur);
- if (stuff_in_upper_case) {
+ if (stuff_in_uppercase) {
char *tmp_p;
tmp_p = text_buffer;
}
last_update_time = current_update_time;
total_updates++;
- // free(p);
}
static inline int get_string_width(const char *s)
return strlen(s);
}
-static inline int get_string_width_special(char *s)
-{
#ifdef X11
+static int get_string_width_special(char *s, int special_index)
+{
char *p, *final;
int idx = 1;
int width = 0;
long i;
if ((output_methods & TO_X) == 0) {
-#endif
return (s) ? strlen(s) : 0;
-#ifdef X11
}
if (!s) {
width += specials[special_index + idx].width;
}
idx++;
+ } else if (*p == SECRIT_MULTILINE_CHAR) {
+ *p = 0;
+ break;
} else {
p++;
}
}
free(final);
return width;
-#endif /* X11 */
}
-#ifdef X11
-static void text_size_updater(char *s);
+static int text_size_updater(char *s, int special_index);
int last_font_height;
static void update_text_area(void)
{
text_width = minimum_width;
text_height = 0;
- special_index = 0;
last_font_height = font_height();
for_each_line(text_buffer, text_size_updater);
text_width += 1;
#ifdef X11
static long current_color;
-static void text_size_updater(char *s)
+static int text_size_updater(char *s, int special_index)
{
int w = 0;
char *p;
if ((output_methods & TO_X) == 0)
- return;
+ return 0;
/* get string widths and skip specials */
p = s;
while (*p) {
special_index++;
s = p + 1;
+ } else if (*p == SECRIT_MULTILINE_CHAR) {
+ int lw;
+ *p = '\0';
+ lw = get_string_width(s);
+ *p = SECRIT_MULTILINE_CHAR;
+ s = p + 1;
+ w = lw > w ? lw : w;
+ text_height += last_font_height;
}
p++;
}
text_height += last_font_height;
last_font_height = font_height();
+ return special_index;
}
static inline void set_foreground_color(long c)
memcpy(tmpstring1, s, text_buffer_size);
}
-static void draw_line(char *s)
-{
#ifdef X11
- char *p;
+int draw_each_line_inner(char *s, int special_index, int last_special_applied)
+{
+ int font_h = font_height();
int cur_y_add = 0;
- int font_h;
- char *tmp_str;
+ char *recurse = 0;
+ char *p = s;
+ int last_special_needed = -1;
+ int orig_special_index = special_index;
- if ((output_methods & TO_X) == 0) {
-#endif /* X11 */
- draw_string(s);
- return;
-#ifdef X11
- }
cur_x = text_start_x;
cur_y += font_ascent();
- font_h = font_height();
- /* find specials and draw stuff */
- p = s;
while (*p) {
- if (*p == SPECIAL_CHAR) {
- int w = 0;
-
- /* draw string before special */
+ if (*p == SECRIT_MULTILINE_CHAR) {
+ /* special newline marker for multiline objects */
+ recurse = p + 1;
*p = '\0';
- draw_string(s);
- *p = SPECIAL_CHAR;
- s = p + 1;
+ break;
+ }
+ if (*p == SPECIAL_CHAR || last_special_applied > -1) {
+ int w = 0;
+ /* draw string before special, unless we're dealing multiline
+ * specials */
+ if (last_special_applied > -1) {
+ special_index = last_special_applied;
+ } else {
+ *p = '\0';
+ draw_string(s);
+ *p = SPECIAL_CHAR;
+ s = p + 1;
+ }
/* draw special */
switch (specials[special_index].type) {
case HORIZONTAL_LINE:
char *tmp_hour_str;
char *tmp_min_str;
char *tmp_sec_str;
+ char *tmp_str;
unsigned short int timeunits;
if (seconds != 0) {
timeunits = seconds / 86400; seconds %= 86400;
if (show_graph_scale && (specials[special_index].show_scale == 1)) {
int tmp_x = cur_x;
int tmp_y = cur_y;
+ char *tmp_str;
cur_x += font_ascent() / 2;
cur_y += font_h / 2;
tmp_str = (char *)
case OFFSET:
w += specials[special_index].arg;
+ last_special_needed = special_index;
break;
case VOFFSET:
if (specials[special_index].arg >= 0) {
cur_x = (int) specials[special_index].arg;
}
+ last_special_needed = special_index;
break;
case TAB:
step = 10;
}
w = step - (cur_x - text_start_x - start) % step;
+ last_special_needed = special_index;
break;
}
/* TODO: add back in "+ window.border_inner_margin" to the end of
* this line? */
int pos_x = text_start_x + text_width -
- get_string_width_special(s);
+ get_string_width_special(s, special_index);
/* printf("pos_x %i text_start_x %i text_width %i cur_x %i "
"get_string_width(p) %i gap_x %i "
if (pos_x > specials[special_index].arg && pos_x > cur_x) {
cur_x = pos_x - specials[special_index].arg;
}
+ last_special_needed = special_index;
break;
}
case ALIGNC:
{
- int pos_x = (text_width) / 2 - get_string_width_special(s) /
- 2 - (cur_x - text_start_x);
+ int pos_x = (text_width) / 2 - get_string_width_special(s,
+ special_index) / 2 - (cur_x -
+ text_start_x);
/* int pos_x = text_start_x + text_width / 2 -
get_string_width_special(s) / 2; */
if (pos_x > specials[special_index].arg) {
w = pos_x - specials[special_index].arg;
}
+ last_special_needed = special_index;
break;
}
}
cur_x += w;
- special_index++;
+ if (special_index != last_special_applied) {
+ special_index++;
+ } else {
+ special_index = orig_special_index;
+ last_special_applied = -1;
+ }
}
-
p++;
}
- if (cur_y_add > 0) {
- cur_y += cur_y_add;
- }
+ cur_y += cur_y_add;
draw_string(s);
cur_y += font_descent();
+ if (recurse && *recurse) {
+ special_index = draw_each_line_inner(recurse, special_index, last_special_needed);
+ *(recurse - 1) = SECRIT_MULTILINE_CHAR;
+ }
+ return special_index;
+}
+#endif /* X11 */
+static int draw_line(char *s, int special_index)
+{
+#ifdef X11
+ if ((output_methods & TO_X) == 0) {
+#endif /* X11 */
+ draw_string(s);
+ //'special_index - special_index' instead of 0 otherwise gcc complains about not using special_index when build without X11
+ return special_index - special_index;
+#ifdef X11
+ }
+
+ /* find specials and draw stuff */
+ return draw_each_line_inner(s, special_index, -1);
#endif /* X11 */
}
}
/* draw text */
- special_index = 0;
}
setup_fonts();
#endif /* X11 */
#ifdef SIGNAL_BLOCKING
/* block signals. we will inspect for pending signals later */
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
- CRIT_ERR("unable to sigprocmask()");
+ CRIT_ERR(NULL, NULL, "unable to sigprocmask()");
}
#endif
break;
}
+ case PropertyNotify:
+ {
+ if ( ev.xproperty.state == PropertyNewValue ) {
+ get_x11_desktop_info( ev.xproperty.display, ev.xproperty.atom );
+ }
+ break;
+ }
+
#ifdef OWN_WINDOW
case ReparentNotify:
/* set background to ParentRelative for all parents */
#ifdef SIGNAL_BLOCKING
/* unblock signals of interest and let handler fly */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
- CRIT_ERR("unable to sigprocmask()");
+ CRIT_ERR(NULL, NULL, "unable to sigprocmask()");
}
#endif
g_signal_pending = 0;
}
- clean_up();
+ clean_up(NULL, NULL);
#ifdef HAVE_SYS_INOTIFY_H
if (inotify_fd != -1) {
}
static void load_config_file(const char *);
+#ifdef X11
static void load_config_file_x11(const char *);
+#endif /* X11 */
+void initialisation(int argc, char** argv);
/* reload the config file */
static void reload_config(void)
{
- timed_thread_destroy_registered_threads();
-
- if (info.cpu_usage) {
- free(info.cpu_usage);
- info.cpu_usage = NULL;
- }
-
- if (info.mail) {
- free(info.mail);
- }
-
-#ifdef X11
- free_fonts();
-#endif /* X11 */
-
-#ifdef TCP_PORT_MONITOR
- tcp_portmon_clear();
-#endif
-
-#ifdef RSS
- free_rss_info();
-#endif
-#ifdef WEATHER
- free_weather_info();
-#endif
-#ifdef HAVE_LUA
- llua_close();
-#endif /* HAVE_LUA */
-
-#ifdef X11
- X11_destroy_window();
-#endif /* X11 */
-
- if (current_config) {
- clear_fs_stats();
- load_config_file(current_config);
- load_config_file_x11(current_config);
-
- /* re-init specials array */
- if ((specials = realloc((void *) specials,
- sizeof(struct special_t) * max_specials)) == 0) {
- ERR("failed to realloc specials array");
- }
-
-#ifdef X11
- if (output_methods & TO_X) {
- X11_initialisation();
- }
-#endif /* X11 */
- extract_variable_text(global_text);
- free(global_text);
- global_text = NULL;
- if (tmpstring1) {
- free(tmpstring1);
- }
- tmpstring1 = malloc(text_buffer_size);
- memset(tmpstring1, 0, text_buffer_size);
- if (tmpstring2) {
- free(tmpstring2);
- }
- tmpstring2 = malloc(text_buffer_size);
- memset(tmpstring2, 0, text_buffer_size);
- if (text_buffer) {
- free(text_buffer);
- }
- text_buffer = malloc(max_user_text);
- memset(text_buffer, 0, max_user_text);
-#ifdef X11
- X11_create_window();
-#endif /* X11 */
- update_text();
- }
+ char *current_config_copy = strdup(current_config);
+ clean_up(NULL, NULL);
+ current_config = current_config_copy;
+ initialisation(argc_copy, argv_copy);
}
-void clean_up(void)
+void clean_up(void *memtofree1, void* memtofree2)
{
int i;
+ if(memtofree1) {
+ free(memtofree1);
+ }
+ if(memtofree2) {
+ free(memtofree2);
+ }
timed_thread_destroy_registered_threads();
if (info.cpu_usage) {
}
#ifdef X11
if (x_initialised == YES) {
+ destroy_window();
free_fonts();
if(x11_stuff.region) {
XDestroyRegion(x11_stuff.region);
x11_stuff.region = NULL;
}
- destroy_window();
XClearWindow(display, RootWindow(display, screen));
XCloseDisplay(display);
+ display = NULL;
+ if(info.x11.desktop.all_names) {
+ free(info.x11.desktop.all_names);
+ info.x11.desktop.all_names = NULL;
+ }
+ if (info.x11.desktop.name) {
+ free(info.x11.desktop.name);
+ info.x11.desktop.name = NULL;
+ }
+ x_initialised = NO;
}else{
free(fonts); //in set_default_configurations a font is set but not loaded
+ font_count = -1;
}
#endif /* X11 */
#ifdef TCP_PORT_MONITOR
tcp_portmon_clear();
#endif
+#ifdef HAVE_CURL
+ ccurl_free_info();
+#endif
#ifdef RSS
- free_rss_info();
+ rss_free_info();
#endif
#ifdef WEATHER
- free_weather_info();
+ weather_free_info();
#endif
#ifdef HAVE_LUA
llua_close();
clear_net_stats();
clear_diskio_stats();
- if(global_cpu != NULL) free(global_cpu);
+ if(global_cpu != NULL) {
+ free(global_cpu);
+ global_cpu = NULL;
+ }
}
static int string_to_bool(const char *s)
color7 = default_fg_color;
color8 = default_fg_color;
color9 = default_fg_color;
+ current_text_color = default_fg_color;
}
#endif /* X11 */
info.x11.monitor.current = 0;
info.x11.desktop.current = 1;
info.x11.desktop.number = 1;
+ info.x11.desktop.nitems = 0;
+ info.x11.desktop.all_names = NULL;
info.x11.desktop.name = NULL;
#endif /* X11 */
no_buffers = 1;
update_interval = 3.0;
info.music_player_interval = 1.0;
- stuff_in_upper_case = 0;
+ stuff_in_uppercase = 0;
info.users.number = 1;
#ifdef TCP_PORT_MONITOR
#endif /* DEBUG */
}
-static void X11_destroy_window(void)
-{
- /* this function only exists for the sake of consistency */
- if (output_methods & TO_X) {
-#ifdef HAVE_XDAMAGE
- XDamageDestroy(display, x11_stuff.damage);
- XFixesDestroyRegion(display, x11_stuff.region2);
- XFixesDestroyRegion(display, x11_stuff.part);
- if (x11_stuff.region) {
- XDestroyRegion(x11_stuff.region);
- }
- x11_stuff.region = NULL;
-#endif /* HAVE_XDAMAGE */
- destroy_window();
- }
- x_initialised = NO;
-}
-
static char **xargv = 0;
static int xargc = 0;
CONF2("out_to_x") {
/* don't listen if X is already initialised or
* if we already know we don't want it */
- if(x_initialised == NO) {
+ if(x_initialised != YES) {
if (string_to_bool(value)) {
output_methods &= TO_X;
} else {
output_methods &= ~TO_X;
x_initialised = NEVER;
- free(fonts); //in set_default_configurations a font is set but not loaded
}
}
}
}
}
CONF("uppercase") {
- stuff_in_upper_case = string_to_bool(value);
+ stuff_in_uppercase = string_to_bool(value);
}
CONF("max_specials") {
if (value) {
}
fclose(fp);
if (strlen(global_text) < 1) {
- CRIT_ERR("no text supplied in configuration; exiting");
+ CRIT_ERR(NULL, NULL, "no text supplied in configuration; exiting");
}
global_text_lines = line + 1;
return;
info.music_player_interval = update_interval;
}
if (!global_text) { // didn't supply any text
- CRIT_ERR("missing text block in configuration; exiting");
+ CRIT_ERR(NULL, NULL, "missing text block in configuration; exiting");
}
}
+#ifdef X11
static void load_config_file_x11(const char *f)
{
int line = 0;
continue;
}
-#ifdef X11
CONF2("color0") {
X11_initialisation();
if (x_initialised == YES) {
}
#endif
CONF("text") {
- //initialize X11 if nothing X11-related is mentioned before TEXT (and if X11 is the default outputmethod)
+ /* initialize X11 if nothing X11-related is mentioned before TEXT (and if X11 is the default outputmethod) */
if(output_methods & TO_X) {
X11_initialisation();
}
}
-#endif /* X11 */
#undef CONF
#undef CONF2
#undef CONF3
fclose(fp);
}
+#endif /* X11 */
+
+#if defined(WEATHER) && defined(XOAP)
+/*
+ * TODO: make the xoap keys file readable from the config file
+ * make the keys directly readable from the config file
+ * make the xoap keys file giveable as a command line option
+ */
+static void load_xoap_keys(void)
+{
+ FILE *fp;
+ char *par = (char *) malloc(11 * sizeof(char));
+ char *key = (char *) malloc(17 * sizeof(char));
+
+ xoap = (char *) malloc(64 * sizeof(char));
+ to_real_path(xoap, XOAP_FILE);
+ fp = fopen(xoap, "r");
+ if (fp != NULL) {
+ if( fscanf(fp, "%10s %16s", par, key) == 2 ) {
+ strcpy(xoap, "?cc=*&link=xoap&prod=xoap&par=");
+ strcat(xoap, par);
+ strcat(xoap, "&key=");
+ strcat(xoap, key);
+ strcat(xoap, "&unit=m");
+ } else {
+ free(xoap);
+ xoap = NULL;
+ }
+ fclose(fp);
+ } else {
+ free(xoap);
+ xoap = NULL;
+ }
+ free(par);
+ free(key);
+}
+#endif /* WEATHER && XOAP */
static void print_help(const char *prog_name) {
printf("Usage: %s [OPTION]...\n"
{ 0, 0, 0, 0 }
};
-int main(int argc, char **argv)
-{
-#ifdef X11
- char *s, *temp;
- unsigned int x;
-#endif
+void initialisation(int argc, char **argv) {
struct sigaction act, oact;
- g_signal_pending = 0;
- max_user_text = MAX_USER_TEXT_DEFAULT;
- current_config = 0;
- memset(&info, 0, sizeof(info));
- memset(template, 0, sizeof(template));
- clear_net_stats();
-
-#ifdef TCP_PORT_MONITOR
- /* set default connection limit */
- tcp_portmon_set_max_connections(0);
-#endif
-
- /* handle command line parameters that don't change configs */
-#ifdef X11
- if (((s = getenv("LC_ALL")) && *s) || ((s = getenv("LC_CTYPE")) && *s)
- || ((s = getenv("LANG")) && *s)) {
- temp = (char *) malloc((strlen(s) + 1) * sizeof(char));
- if (temp == NULL) {
- ERR("malloc failed");
- }
- for (x = 0; x < strlen(s); x++) {
- temp[x] = tolower(s[x]);
- }
- temp[x] = 0;
- if (strstr(temp, "utf-8") || strstr(temp, "utf8")) {
- utf8_mode = 1;
- }
-
- free(temp);
- }
- if (!setlocale(LC_CTYPE, "")) {
- ERR("Can't set the specified locale!\nCheck LANG, LC_CTYPE, LC_ALL.");
- }
-#endif /* X11 */
- while (1) {
- int c = getopt_long(argc, argv, getopt_string, longopts, NULL);
-
- if (c == -1) {
- break;
- }
-
- switch (c) {
- case 'v':
- case 'V':
- print_version();
- case 'c':
- if (current_config) {
- free(current_config);
- }
- current_config = strndup(optarg, max_user_text);
- break;
- case 'q':
- freopen("/dev/null", "w", stderr);
- break;
- case 'h':
- print_help(argv[0]);
- return 0;
-#ifdef CONFIG_OUTPUT
- case 'C':
- print_defconfig();
- return 0;
-#endif
-#ifdef X11
- case 'w':
- window.window = strtol(optarg, 0, 0);
- break;
-#endif /* X11 */
-
- case '?':
- exit(EXIT_FAILURE);
- }
- }
-
- /* check if specified config file is valid */
- if (current_config) {
- struct stat sb;
- if (stat(current_config, &sb) ||
- (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode))) {
- ERR("invalid configuration file '%s'\n", current_config);
- free(current_config);
- current_config = 0;
- }
- }
-
- /* load current_config, CONFIG_FILE or SYSTEM_CONFIG_FILE */
-
- if (!current_config) {
- /* load default config file */
- char buf[DEFAULT_TEXT_BUFFER_SIZE];
- FILE *fp;
-
- /* Try to use personal config file first */
- to_real_path(buf, CONFIG_FILE);
- if (buf[0] && (fp = fopen(buf, "r"))) {
- current_config = strndup(buf, max_user_text);
- fclose(fp);
- }
-
- /* Try to use system config file if personal config not readable */
- if (!current_config && (fp = fopen(SYSTEM_CONFIG_FILE, "r"))) {
- current_config = strndup(SYSTEM_CONFIG_FILE, max_user_text);
- fclose(fp);
- }
-
- /* No readable config found */
- if (!current_config) {
-#ifdef CONFIG_OUTPUT
- current_config = strdup("==builtin==");
- ERR("no readable personal or system-wide config file found,"
- " using builtin default");
-#else
- CRIT_ERR("no readable personal or system-wide config file found");
-#endif /* ! CONF_OUTPUT */
- }
- }
-#ifdef HAVE_SYS_INOTIFY_H
- inotify_fd = inotify_init();
-#endif /* HAVE_SYS_INOTIFY_H */
-
load_config_file(current_config);
/* init specials array */
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
if ((kd = kvm_open("/dev/null", "/dev/null", "/dev/null", O_RDONLY,
"kvm_open")) == NULL) {
- CRIT_ERR("cannot read kvm");
+ CRIT_ERR(NULL, NULL, "cannot read kvm");
}
#endif
fprintf(stderr, PACKAGE_NAME": forked to background, pid is %d\n",
pid);
fflush(stderr);
- return 0;
+ exit(EXIT_SUCCESS);
}
}
ERR("error setting signal handler: %s", strerror(errno));
}
+}
+
+int main(int argc, char **argv)
+{
+#ifdef X11
+ char *s, *temp;
+ unsigned int x;
+#endif
+
+ argc_copy = argc;
+ argv_copy = argv;
+ g_signal_pending = 0;
+ max_user_text = MAX_USER_TEXT_DEFAULT;
+ current_config = 0;
+ memset(&info, 0, sizeof(info));
+ memset(template, 0, sizeof(template));
+ clear_net_stats();
+
+#ifdef TCP_PORT_MONITOR
+ /* set default connection limit */
+ tcp_portmon_set_max_connections(0);
+#endif
+
+ /* handle command line parameters that don't change configs */
+#ifdef X11
+ if (((s = getenv("LC_ALL")) && *s) || ((s = getenv("LC_CTYPE")) && *s)
+ || ((s = getenv("LANG")) && *s)) {
+ temp = (char *) malloc((strlen(s) + 1) * sizeof(char));
+ if (temp == NULL) {
+ ERR("malloc failed");
+ }
+ for (x = 0; x < strlen(s); x++) {
+ temp[x] = tolower(s[x]);
+ }
+ temp[x] = 0;
+ if (strstr(temp, "utf-8") || strstr(temp, "utf8")) {
+ utf8_mode = 1;
+ }
+
+ free(temp);
+ }
+ if (!setlocale(LC_CTYPE, "")) {
+ ERR("Can't set the specified locale!\nCheck LANG, LC_CTYPE, LC_ALL.");
+ }
+#endif /* X11 */
+ while (1) {
+ int c = getopt_long(argc, argv, getopt_string, longopts, NULL);
+
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'v':
+ case 'V':
+ print_version();
+ case 'c':
+ if (current_config) {
+ free(current_config);
+ }
+ current_config = strndup(optarg, max_user_text);
+ break;
+ case 'q':
+ freopen("/dev/null", "w", stderr);
+ break;
+ case 'h':
+ print_help(argv[0]);
+ return 0;
+#ifdef CONFIG_OUTPUT
+ case 'C':
+ print_defconfig();
+ return 0;
+#endif
+#ifdef X11
+ case 'w':
+ window.window = strtol(optarg, 0, 0);
+ break;
+#endif /* X11 */
+
+ case '?':
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* check if specified config file is valid */
+ if (current_config) {
+ struct stat sb;
+ if (stat(current_config, &sb) ||
+ (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode))) {
+ ERR("invalid configuration file '%s'\n", current_config);
+ free(current_config);
+ current_config = 0;
+ }
+ }
+
+ /* load current_config, CONFIG_FILE or SYSTEM_CONFIG_FILE */
+
+ if (!current_config) {
+ /* load default config file */
+ char buf[DEFAULT_TEXT_BUFFER_SIZE];
+ FILE *fp;
+
+ /* Try to use personal config file first */
+ to_real_path(buf, CONFIG_FILE);
+ if (buf[0] && (fp = fopen(buf, "r"))) {
+ current_config = strndup(buf, max_user_text);
+ fclose(fp);
+ }
+
+ /* Try to use system config file if personal config not readable */
+ if (!current_config && (fp = fopen(SYSTEM_CONFIG_FILE, "r"))) {
+ current_config = strndup(SYSTEM_CONFIG_FILE, max_user_text);
+ fclose(fp);
+ }
+
+ /* No readable config found */
+ if (!current_config) {
+#ifdef CONFIG_OUTPUT
+ current_config = strdup("==builtin==");
+ ERR("no readable personal or system-wide config file found,"
+ " using builtin default");
+#else
+ CRIT_ERR(NULL, NULL, "no readable personal or system-wide config file found");
+#endif /* ! CONF_OUTPUT */
+ }
+ }
+
+#if defined(WEATHER) && defined(XOAP)
+ /* Load xoap keys, if existing */
+ load_xoap_keys();
+#endif /* WEATHER && XOAP */
+
+#ifdef HAVE_SYS_INOTIFY_H
+ inotify_fd = inotify_init();
+#endif /* HAVE_SYS_INOTIFY_H */
+
+ initialisation(argc, argv);
+
main_loop();
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
* and do any signal processing there, NOT here. */
g_signal_pending = sig;
}
+