split off specials from conky.c
authorPhil Sutter <phil@nwl.cc>
Sun, 22 Feb 2009 16:53:30 +0000 (17:53 +0100)
committerPhil Sutter <phil@nwl.cc>
Sun, 22 Feb 2009 18:04:33 +0000 (19:04 +0100)
As a side effect, font and colour specific stuff got outsourced, too.
This is because the apropriate functions are used by conky.c as well as
specials.c, so they should be kept on their own.

In the long term I hope for positive impact on the X11 integration mess.
(Take e.g. the mass of X11 ifdefs cluttering conky.c.) Though this
commit contains no optimisations in this direction, just plain
outsourcing, to ensure minimised (intended: none) changes to conky's
interface behaviour.

src/Makefile.am
src/colours.c [new file with mode: 0644]
src/colours.h [new file with mode: 0644]
src/conky.c
src/conky.h
src/fonts.c [new file with mode: 0644]
src/fonts.h [new file with mode: 0644]
src/specials.c [new file with mode: 0644]
src/specials.h [new file with mode: 0644]

index 568b621..4957766 100644 (file)
@@ -92,7 +92,7 @@ port_monitors = libtcp-portmon.h libtcp-portmon.c \
 endif
 
 if BUILD_X11
-x11 = x11.c
+x11 = x11.c fonts.c
 endif
 
 if BUILD_HDDTEMP
@@ -116,6 +116,8 @@ conky_SOURCES =             \
        $(config_cookie)        \
        $(audacious)            \
        $(bmpx)                 \
+       colours.c               \
+       colours.h               \
        common.c                \
        conky.c                 \
        conky.h                 \
@@ -142,6 +144,8 @@ conky_SOURCES =             \
        $(x11)                  \
        $(xmms2)                \
        $(ibm)                  \
+       specials.c              \
+       specials.h              \
        tailhead.c              \
        tailhead.h              \
        temphelper.c            \
@@ -161,7 +165,11 @@ EXTRA_DIST =                       \
        audacious.c             \
        audacious.h             \
        bmpx.c                  \
+       colours.c               \
+       colours.h               \
        common.h                \
+       fonts.c                 \
+       fonts.h                 \
        freebsd.c               \
        freebsd.h               \
        fs.h                    \
@@ -186,6 +194,8 @@ EXTRA_DIST =                        \
        openbsd.c               \
        openbsd.h               \
        solaris.c               \
+       specials.c              \
+       specials.h              \
        tailhead.c              \
        tailhead.h              \
        top.h                   \
diff --git a/src/colours.c b/src/colours.c
new file mode 100644 (file)
index 0000000..6909293
--- /dev/null
@@ -0,0 +1,183 @@
+/* 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-2008 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 "conky.h"
+#include "logging.h"
+#include "x11.h"
+
+/* precalculated: 31/255, and 63/255 */
+#define CONST_8_TO_5_BITS 0.12156862745098
+#define CONST_8_TO_6_BITS 0.247058823529412
+
+static short colour_depth = 0;
+static long redmask, greenmask, bluemask;
+
+static void set_up_gradient(void)
+{
+       int i;
+#ifdef X11
+       if (output_methods & TO_X) {
+               colour_depth = DisplayPlanes(display, screen);
+       } else
+#endif /* X11 */
+       {
+               colour_depth = 16;
+       }
+       if (colour_depth != 24 && colour_depth != 16) {
+               ERR("using non-standard colour depth, gradients may look like a "
+                       "lolly-pop");
+       }
+
+       redmask = 0;
+       greenmask = 0;
+       bluemask = 0;
+       for (i = (colour_depth / 3) - 1; i >= 0; i--) {
+               redmask |= 1 << i;
+               greenmask |= 1 << i;
+               bluemask |= 1 << i;
+       }
+       if (colour_depth % 3 == 1) {
+               greenmask |= 1 << (colour_depth / 3);
+       }
+       redmask = redmask << (2 * colour_depth / 3 + colour_depth % 3);
+       greenmask = greenmask << (colour_depth / 3);
+}
+
+/* adjust color values depending on color depth */
+unsigned int adjust_colors(unsigned int color)
+{
+       double r, g, b;
+
+       if (colour_depth == 0) {
+               set_up_gradient();
+       }
+       if (colour_depth == 16) {
+               r = (color & 0xff0000) >> 16;
+               g = (color & 0xff00) >> 8;
+               b =  color & 0xff;
+               color  = (int) (r * CONST_8_TO_5_BITS) << 11;
+               color |= (int) (g * CONST_8_TO_6_BITS) << 5;
+               color |= (int) (b * CONST_8_TO_5_BITS);
+       }
+       return color;
+}
+
+/* this function returns the next colour between two colours for a gradient */
+unsigned long do_gradient(unsigned long first_colour,
+               unsigned long last_colour)
+{
+       int tmp_color = 0;
+       int red1, green1, blue1;                                // first colour
+       int red2, green2, blue2;                                // second colour
+       int red3 = 0, green3 = 0, blue3 = 0;    // difference
+       short redshift = (2 * colour_depth / 3 + colour_depth % 3);
+       short greenshift = (colour_depth / 3);
+
+       red1 = (first_colour & redmask) >> redshift;
+       green1 = (first_colour & greenmask) >> greenshift;
+       blue1 = first_colour & bluemask;
+       red2 = (last_colour & redmask) >> redshift;
+       green2 = (last_colour & greenmask) >> greenshift;
+       blue2 = last_colour & bluemask;
+       if (red1 > red2) {
+               red3 = -1;
+       }
+       if (red1 < red2) {
+               red3 = 1;
+       }
+       if (green1 > green2) {
+               green3 = -1;
+       }
+       if (green1 < green2) {
+               green3 = 1;
+       }
+       if (blue1 > blue2) {
+               blue3 = -1;
+       }
+       if (blue1 < blue2) {
+               blue3 = 1;
+       }
+       red1 += red3;
+       green1 += green3;
+       blue1 += blue3;
+       if (red1 < 0) {
+               red1 = 0;
+       }
+       if (green1 < 0) {
+               green1 = 0;
+       }
+       if (blue1 < 0) {
+               blue1 = 0;
+       }
+       if (red1 > bluemask) {
+               red1 = bluemask;
+       }
+       if (green1 > bluemask) {
+               green1 = bluemask;
+       }
+       if (blue1 > bluemask) {
+               blue1 = bluemask;
+       }
+       tmp_color = (red1 << redshift) | (green1 << greenshift) | blue1;
+       return tmp_color;
+}
+
+/* this function returns the max diff for a gradient */
+unsigned long gradient_max(unsigned long first_colour,
+               unsigned long last_colour)
+{
+       int red1, green1, blue1;                                // first colour
+       int red2, green2, blue2;                                // second colour
+       int red3 = 0, green3 = 0, blue3 = 0;                    // difference
+       long redshift, greenshift;
+       int max;
+
+       if (colour_depth == 0) {
+               set_up_gradient();
+       }
+       redshift = (2 * colour_depth / 3 + colour_depth % 3);
+       greenshift = (colour_depth / 3);
+
+       red1 = (first_colour & redmask) >> redshift;
+       green1 = (first_colour & greenmask) >> greenshift;
+       blue1 = first_colour & bluemask;
+       red2 = (last_colour & redmask) >> redshift;
+       green2 = (last_colour & greenmask) >> greenshift;
+       blue2 = last_colour & bluemask;
+       red3 = abs(red1 - red2);
+       green3 = abs(green1 - green2);
+       blue3 = abs(blue1 - blue2);
+       max = red3;
+
+       if (green3 > max) {
+               max = green3;
+       }
+       if (blue3 > max) {
+               max = blue3;
+       }
+       return max;
+}
+
diff --git a/src/colours.h b/src/colours.h
new file mode 100644 (file)
index 0000000..b83ccd4
--- /dev/null
@@ -0,0 +1,34 @@
+/* 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-2008 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 _COLOURS_H
+#define _COLOURS_H
+
+unsigned int adjust_colors(unsigned int);
+unsigned long do_gradient(unsigned long, unsigned long);
+unsigned long gradient_max(unsigned long, unsigned long);
+
+#endif /* _COLOURS_H */
index 03a26da..3bd678e 100644 (file)
 /* local headers */
 #include "algebra.h"
 #include "build.h"
+#include "colours.h"
 #include "diskio.h"
+#include "fonts.h"
 #include "fs.h"
 #include "logging.h"
 #include "mixer.h"
 #include "mail.h"
 #include "mboxscan.h"
+#include "specials.h"
 #include "temphelper.h"
 #include "tailhead.h"
 #include "top.h"
@@ -126,17 +129,8 @@ enum {
        RIGHT_SPACER
 } use_spacer;
 int top_cpu, top_mem, top_time;
-#define TO_X 1
-#define TO_STDOUT 2
-#define TO_STDERR 4
-#define OVERWRITE_FILE 8
-#define APPEND_FILE 16
-static int output_methods;
-enum {
-       NO = 0,
-       YES = 1,
-       NEVER = 2
-} x_initialised = NO;
+int output_methods;
+enum x_initialiser_state x_initialised = NO;
 static volatile int g_signal_pending;
 /* Update interval */
 double update_interval;
@@ -239,178 +233,6 @@ enum alignment {
        NONE
 };
 
-/* for fonts */
-struct font_list {
-
-       char name[DEFAULT_TEXT_BUFFER_SIZE];
-       int num;
-       XFontStruct *font;
-
-#ifdef XFT
-       XftFont *xftfont;
-       int font_alpha;
-#endif
-};
-
-static int selected_font = 0;
-static int font_count = -1;
-struct font_list *fonts = NULL;
-
-#ifdef XFT
-
-#define font_height() (use_xft ? (fonts[selected_font].xftfont->ascent + \
-       fonts[selected_font].xftfont->descent) \
-       : (fonts[selected_font].font->max_bounds.ascent + \
-       fonts[selected_font].font->max_bounds.descent))
-#define font_ascent() (use_xft ? fonts[selected_font].xftfont->ascent \
-       : fonts[selected_font].font->max_bounds.ascent)
-#define font_descent() (use_xft ? fonts[selected_font].xftfont->descent \
-       : fonts[selected_font].font->max_bounds.descent)
-
-#else
-
-#define font_height() (fonts[selected_font].font->max_bounds.ascent + \
-       fonts[selected_font].font->max_bounds.descent)
-#define font_ascent() fonts[selected_font].font->max_bounds.ascent
-#define font_descent() fonts[selected_font].font->max_bounds.descent
-
-#endif
-
-#define MAX_FONTS 64 // hmm, no particular reason, just makes sense.
-
-static void set_font(void);
-
-int addfont(const char *data_in)
-{
-       if ((output_methods & TO_X) == 0)
-               return 0;
-       if (font_count > MAX_FONTS) {
-               CRIT_ERR("you don't need that many fonts, sorry.");
-       }
-       font_count++;
-       if (font_count == 0) {
-               if (fonts != NULL) {
-                       free(fonts);
-               }
-               if ((fonts = (struct font_list *) malloc(sizeof(struct font_list)))
-                               == NULL) {
-                       CRIT_ERR("malloc");
-               }
-               memset(fonts, 0, sizeof(struct font_list));
-       }
-       fonts = realloc(fonts, (sizeof(struct font_list) * (font_count + 1)));
-       memset(&fonts[font_count], 0, sizeof(struct font_list));
-       if (fonts == NULL) {
-               CRIT_ERR("realloc in addfont");
-       }
-       // must account for null terminator
-       if (strlen(data_in) < DEFAULT_TEXT_BUFFER_SIZE) {
-               strncpy(fonts[font_count].name, data_in, DEFAULT_TEXT_BUFFER_SIZE);
-#ifdef XFT
-               fonts[font_count].font_alpha = 0xffff;
-#endif
-       } else {
-               CRIT_ERR("Oops...looks like something overflowed in addfont().");
-       }
-       return font_count;
-}
-
-void set_first_font(const char *data_in)
-{
-       if ((output_methods & TO_X) == 0)
-               return;
-       if (font_count < 0) {
-               if ((fonts = (struct font_list *) malloc(sizeof(struct font_list)))
-                               == NULL) {
-                       CRIT_ERR("malloc");
-               }
-               memset(fonts, 0, sizeof(struct font_list));
-               font_count++;
-       }
-       if (strlen(data_in) > 1) {
-               strncpy(fonts[0].name, data_in, DEFAULT_TEXT_BUFFER_SIZE);
-#ifdef XFT
-               fonts[0].font_alpha = 0xffff;
-#endif
-       }
-}
-
-void free_fonts(void)
-{
-       int i;
-
-       if ((output_methods & TO_X) == 0)
-               return;
-       for (i = 0; i <= font_count; i++) {
-#ifdef XFT
-               if (use_xft) {
-                       XftFontClose(display, fonts[i].xftfont);
-                       fonts[i].xftfont = 0;
-               } else
-#endif
-               {
-                       XFreeFont(display, fonts[i].font);
-                       fonts[i].font = 0;
-               }
-       }
-       free(fonts);
-       fonts = 0;
-       font_count = -1;
-       selected_font = 0;
-}
-
-static void load_fonts(void)
-{
-       int i;
-
-       if ((output_methods & TO_X) == 0)
-               return;
-       for (i = 0; i <= font_count; i++) {
-#ifdef XFT
-               /* load Xft font */
-               if (use_xft && fonts[i].xftfont) {
-                       continue;
-               } else if (use_xft) {
-                       /* if (fonts[i].xftfont != NULL && selected_font == 0) {
-                               XftFontClose(display, fonts[i].xftfont);
-                       } */
-                       fonts[i].xftfont = XftFontOpenName(display, screen,
-                                       fonts[i].name);
-                       if (fonts[i].xftfont != NULL) {
-                               continue;
-                       }
-
-                       ERR("can't load Xft font '%s'", fonts[i].name);
-                       if ((fonts[i].xftfont = XftFontOpenName(display, screen,
-                                       "courier-12")) != NULL) {
-                               continue;
-                       }
-
-                       ERR("can't load Xft font '%s'", "courier-12");
-
-                       if ((fonts[i].font = XLoadQueryFont(display, "fixed")) == NULL) {
-                               CRIT_ERR("can't load font '%s'", "fixed");
-                       }
-                       use_xft = 0;
-
-                       continue;
-               }
-#endif
-               /* load normal font */
-               /* if (fonts[i].font != NULL) {
-                       XFreeFont(display, fonts[i].font);
-               } */
-
-               if (fonts[i].font || (fonts[i].font = XLoadQueryFont(display, fonts[i].name)) == NULL) {
-                       ERR("can't load font '%s'", fonts[i].name);
-                       if ((fonts[i].font = XLoadQueryFont(display, "fixed")) == NULL) {
-                               CRIT_ERR("can't load font '%s'", "fixed");
-                               printf("loaded fixed?\n");
-                       }
-               }
-       }
-}
-
 #endif /* X11 */
 
 /* struct that has all info to be shared between
@@ -480,9 +302,6 @@ static long color0, color1, color2, color3, color4, color5, color6, color7,
 
 static char *template[10];
 
-/* maximum number of special things, e.g. fonts, offsets, aligns, etc. */
-static unsigned int max_specials = MAX_SPECIALS_DEFAULT;
-
 /* maximum size of config TEXT buffer, i.e. below TEXT line. */
 static unsigned int max_user_text = MAX_USER_TEXT_DEFAULT;
 
@@ -595,68 +414,10 @@ static inline int calc_text_width(const char *s, int l)
 
 static char *text_buffer;
 
-/* special stuff in text_buffer */
-
-#define SPECIAL_CHAR '\x01'
-
-enum special_types {
-       HORIZONTAL_LINE,
-       STIPPLED_HR,
-       BAR,
-       FG,
-       BG,
-       OUTLINE,
-       ALIGNR,
-       ALIGNC,
-       GRAPH,
-       OFFSET,
-       VOFFSET,
-       FONT,
-       GOTO,
-       TAB,
-};
-
-struct special_t {
-       int type;
-       short height;
-       short width;
-       long arg;
-       double *graph;
-       double graph_scale;
-       short show_scale;
-       int graph_width;
-       int scaled;
-       unsigned long first_colour;     // for graph gradient
-       unsigned long last_colour;
-       short font_added;
-};
-
-/* create specials array on heap instead of stack with introduction of
- * max_specials */
-static struct special_t *specials = NULL;
-
-static unsigned int special_count;
-
 #ifdef X11
 static unsigned int special_index;     /* used when drawing */
 #endif /* X11 */
 
-/* why 256? cause an array of more then 256 doubles seems excessive,
- * and who needs that kind of precision anyway? */
-#define MAX_GRAPH_DEPTH 256
-
-static struct special_t *new_special(char *buf, enum special_types t)
-{
-       if (special_count >= max_specials) {
-               CRIT_ERR("too many special things in text");
-       }
-
-       buf[0] = SPECIAL_CHAR;
-       buf[1] = '\0';
-       specials[special_count].type = t;
-       return &specials[special_count++];
-}
-
 #ifndef HAVE_MEMRCHR
 void *memrchr(const void *buffer, char c, size_t n)
 {
@@ -671,321 +432,6 @@ void *memrchr(const void *buffer, char c, size_t n)
 }
 #endif
 
-static void new_bar(char *buf, int w, int h, int usage)
-{
-       struct special_t *s = new_special(buf, BAR);
-
-       s->arg = (usage > 255) ? 255 : ((usage < 0) ? 0 : usage);
-       s->width = w;
-       s->height = h;
-}
-
-static const char *scan_bar(const char *args, int *w, int *h)
-{
-       /* zero width means all space that is available */
-       *w = 0;
-       *h = 6;
-       /* bar's argument is either height or height,width */
-       if (args) {
-               int n = 0;
-
-               if (sscanf(args, "%d,%d %n", h, w, &n) <= 1) {
-                       sscanf(args, "%d %n", h, &n);
-               }
-               args += n;
-       }
-
-       return args;
-}
-
-static char *scan_font(const char *args)
-{
-       if (args && *args) {
-               return strndup(args, DEFAULT_TEXT_BUFFER_SIZE);
-       }
-
-       return NULL;
-}
-
-#ifdef X11
-static void new_font(char *buf, char *args)
-{
-       if ((output_methods & TO_X) == 0)
-               return;
-       if (args) {
-               struct special_t *s = new_special(buf, FONT);
-
-               if (s->font_added > font_count || !s->font_added || (strncmp(args, fonts[s->font_added].name, DEFAULT_TEXT_BUFFER_SIZE) != EQUAL) ) {
-                       int tmp = selected_font;
-
-                       selected_font = s->font_added = addfont(args);
-                       load_fonts();
-                       selected_font = tmp;
-               }
-       } else {
-               struct special_t *s = new_special(buf, FONT);
-               int tmp = selected_font;
-
-               selected_font = s->font_added = 0;
-               selected_font = tmp;
-       }
-}
-#endif
-void graph_append(struct special_t *graph, double f, char showaslog)
-{
-       int i;
-
-       if (showaslog) {
-#ifdef MATH
-               f = log10(f + 1);
-#endif
-       }
-       
-       if (!graph->scaled && f > graph->graph_scale) {
-               f = graph->graph_scale;
-       }
-
-/* Already happens in new_graph
-       if (graph->scaled) {
-               graph->graph_scale = 1;
-       }
-*/
-       graph->graph[0] = f;    /* add new data */
-       /* shift all the data by 1 */
-       for (i = graph->graph_width - 1; i > 0; i--) {
-               graph->graph[i] = graph->graph[i - 1];
-               if (graph->scaled && graph->graph[i] > graph->graph_scale) {
-                       /* check if we need to update the scale */
-                       graph->graph_scale = graph->graph[i];
-               }
-       }
-}
-
-short colour_depth = 0;
-void set_up_gradient(void);
-
-/* precalculated: 31/255, and 63/255 */
-#define CONST_8_TO_5_BITS 0.12156862745098
-#define CONST_8_TO_6_BITS 0.247058823529412
-
-/* adjust color values depending on color depth */
-static unsigned int adjust_colors(unsigned int color)
-{
-       double r, g, b;
-
-       if (colour_depth == 0) {
-               set_up_gradient();
-       }
-       if (colour_depth == 16) {
-               r = (color & 0xff0000) >> 16;
-               g = (color & 0xff00) >> 8;
-               b =  color & 0xff;
-               color  = (int) (r * CONST_8_TO_5_BITS) << 11;
-               color |= (int) (g * CONST_8_TO_6_BITS) << 5;
-               color |= (int) (b * CONST_8_TO_5_BITS);
-       }
-       return color;
-}
-
-static void new_graph(char *buf, int w, int h, unsigned int first_colour,
-               unsigned int second_colour, double i, int scale, int append, char showaslog)
-{
-       struct special_t *s = new_special(buf, GRAPH);
-
-       s->width = w;
-       if (s->graph == NULL) {
-               if (s->width > 0 && s->width < MAX_GRAPH_DEPTH) {
-                       // subtract 2 for the box
-                       s->graph_width = s->width /* - 2 */;
-               } else {
-                       s->graph_width = MAX_GRAPH_DEPTH - 2;
-               }
-               s->graph = malloc(s->graph_width * sizeof(double));
-               memset(s->graph, 0, s->graph_width * sizeof(double));
-               s->graph_scale = 100;
-       }
-       s->height = h;
-       s->first_colour = adjust_colors(first_colour);
-       s->last_colour = adjust_colors(second_colour);
-       if (scale != 0) {
-               s->scaled = 0;
-               s->graph_scale = scale;
-               s->show_scale = 0;
-       } else {
-               s->scaled = 1;
-               s->graph_scale = 1;
-               s->show_scale = 1;
-       }
-       /* if (s->width) {
-               s->graph_width = s->width - 2;  // subtract 2 for rectangle around
-       } */
-       if (showaslog) {
-#ifdef MATH
-               s->graph_scale = log10(s->graph_scale + 1);
-#endif
-       }
-       if (append) {
-               graph_append(s, i, showaslog);
-       }
-}
-
-//don't use spaces in LOGGRAPH or NORMGRAPH if you change them
-#define LOGGRAPH "log"
-#define NORMGRAPH "normal"
-
-static char *scan_graph(const char *args, int *w, int *h,
-               unsigned int *first_colour, unsigned int *last_colour,
-               unsigned int *scale, char *showaslog)
-{
-       const char *nographtype;
-       char buf[64];
-       buf[0] = 0;
-
-       /* zero width means all space that is available */
-       *w = 0;
-       *h = 25;
-       *first_colour = 0;
-       *last_colour = 0;
-       *scale = 0;
-       if (args) {
-               //set showaslog and place the rest of the args in nographtype
-               if(strcasecmp(args, LOGGRAPH) == EQUAL) {
-                       *showaslog = TRUE;
-                       return NULL;
-               }else if(strcasecmp(args, NORMGRAPH) == EQUAL) {
-                       *showaslog = FALSE;
-                       return NULL;
-               }else if(strncasecmp(args, LOGGRAPH" ", strlen(LOGGRAPH) + 1 ) == EQUAL) {
-                       *showaslog = TRUE;
-                       nographtype = &args[strlen(LOGGRAPH) + 1];
-               }else if(strncasecmp(args, NORMGRAPH" ", strlen(NORMGRAPH) + 1 ) == EQUAL) {
-                       *showaslog = FALSE;
-                       nographtype = &args[strlen(NORMGRAPH) + 1];
-               }else{
-                       *showaslog = FALSE;
-                       nographtype = args;
-               }
-               DBGP("printing graph as %s, other args are: %s", (*showaslog ? "log" : "normal"), nographtype);
-               //check the rest of the args
-               if (sscanf(nographtype, "%d,%d %x %x %u", h, w, first_colour, last_colour, scale) == 5) {
-                       return NULL;
-               }
-               *scale = 0;
-               if (sscanf(nographtype, "%d,%d %x %x", h, w, first_colour, last_colour) == 4) {
-                       return NULL;
-               }
-               if (sscanf(nographtype, "%63s %d,%d %x %x %u", buf, h, w, first_colour, last_colour, scale) == 6) {
-                       return strndup(buf, text_buffer_size);
-               }
-               *scale = 0;
-               if (sscanf(nographtype, "%63s %d,%d %x %x", buf, h, w, first_colour, last_colour) == 5) {
-                       return strndup(buf, text_buffer_size);
-               }
-               buf[0] = '\0';
-               *h = 25;
-               *w = 0;
-               if (sscanf(nographtype, "%x %x %u", first_colour, last_colour, scale) == 3) {
-                       return NULL;
-               }
-               *scale = 0;
-               if (sscanf(nographtype, "%x %x", first_colour, last_colour) == 2) {
-                       return NULL;
-               }
-               if (sscanf(nographtype, "%63s %x %x %u", buf, first_colour, last_colour, scale) == 4) {
-                       return strndup(buf, text_buffer_size);
-               }
-               *scale = 0;
-               if (sscanf(nographtype, "%63s %x %x", buf, first_colour, last_colour) == 3) {
-                       return strndup(buf, text_buffer_size);
-               }
-               buf[0] = '\0';
-               *first_colour = 0;
-               *last_colour = 0;
-               if (sscanf(nographtype, "%d,%d %u", h, w, scale) == 3) {
-                       return NULL;
-               }
-               *scale = 0;
-               if (sscanf(nographtype, "%d,%d", h, w) == 2) {
-                       return NULL;
-               }
-               if (sscanf(nographtype, "%63s %d,%d %u", buf, h, w, scale) < 4) {
-                       *scale = 0;
-                       //TODO: check the return value and throw an error?
-                       sscanf(nographtype, "%63s %d,%d", buf, h, w);
-               }
-
-               return strndup(buf, text_buffer_size);
-       }
-
-       if (buf[0] == '\0') {
-               return NULL;
-       } else {
-               return strndup(buf, text_buffer_size);
-       }
-}
-
-static inline void new_hr(char *buf, int a)
-{
-       new_special(buf, HORIZONTAL_LINE)->height = a;
-}
-
-static inline void new_stippled_hr(char *buf, int a, int b)
-{
-       struct special_t *s = new_special(buf, STIPPLED_HR);
-
-       s->height = b;
-       s->arg = a;
-}
-
-static inline void new_fg(char *buf, long c)
-{
-       new_special(buf, FG)->arg = c;
-}
-
-static inline void new_bg(char *buf, long c)
-{
-       new_special(buf, BG)->arg = c;
-}
-
-static inline void new_outline(char *buf, long c)
-{
-       new_special(buf, OUTLINE)->arg = c;
-}
-
-static inline void new_offset(char *buf, long c)
-{
-       new_special(buf, OFFSET)->arg = c;
-}
-
-static inline void new_voffset(char *buf, long c)
-{
-       new_special(buf, VOFFSET)->arg = c;
-}
-
-static inline void new_alignr(char *buf, long c)
-{
-       new_special(buf, ALIGNR)->arg = c;
-}
-
-// A postive offset pushes the text further left
-static inline void new_alignc(char *buf, long c)
-{
-       new_special(buf, ALIGNC)->arg = c;
-}
-
-static inline void new_goto(char *buf, long c)
-{
-       new_special(buf, GOTO)->arg = c;
-}
-
-static inline void new_tab(char *buf, int a, int b)
-{
-       struct special_t *s = new_special(buf, TAB);
-
-       s->width = a;
-       s->arg = b;
-}
-
 /* quite boring functions */
 
 static inline void for_each_line(char *b, void f(char *))
@@ -5400,27 +4846,6 @@ static void generate_text(void)
        // free(p);
 }
 
-#ifdef X11
-static void set_font(void)
-{
-       if ((output_methods & TO_X) == 0)
-               return;
-#ifdef XFT
-       if (use_xft) {
-               if (window.xftdraw != NULL) {
-                       XftDrawDestroy(window.xftdraw);
-               }
-               window.xftdraw = XftDrawCreate(display, window.drawable,
-                       DefaultVisual(display, screen), DefaultColormap(display, screen));
-       } else
-#endif
-       {
-               XSetFont(display, window.gc, fonts[selected_font].font->fid);
-       }
-}
-
-#endif /* X11 */
-
 static inline int get_string_width(const char *s)
 {
 #ifdef X11
@@ -5766,135 +5191,6 @@ static void draw_string(const char *s)
        memcpy(tmpstring1, s, text_buffer_size);
 }
 
-long redmask, greenmask, bluemask;
-
-void set_up_gradient(void)
-{
-       int i;
-#ifdef X11
-       if (output_methods & TO_X) {
-               colour_depth = DisplayPlanes(display, screen);
-       } else
-#endif /* X11 */
-       {
-               colour_depth = 16;
-       }
-       if (colour_depth != 24 && colour_depth != 16) {
-               ERR("using non-standard colour depth, gradients may look like a "
-                       "lolly-pop");
-       }
-
-       redmask = 0;
-       greenmask = 0;
-       bluemask = 0;
-       for (i = (colour_depth / 3) - 1; i >= 0; i--) {
-               redmask |= 1 << i;
-               greenmask |= 1 << i;
-               bluemask |= 1 << i;
-       }
-       if (colour_depth % 3 == 1) {
-               greenmask |= 1 << (colour_depth / 3);
-       }
-       redmask = redmask << (2 * colour_depth / 3 + colour_depth % 3);
-       greenmask = greenmask << (colour_depth / 3);
-}
-
-/* this function returns the next colour between two colours for a gradient */
-unsigned long do_gradient(unsigned long first_colour,
-               unsigned long last_colour)
-{
-       int tmp_color = 0;
-       int red1, green1, blue1;                                // first colour
-       int red2, green2, blue2;                                // second colour
-       int red3 = 0, green3 = 0, blue3 = 0;    // difference
-       short redshift = (2 * colour_depth / 3 + colour_depth % 3);
-       short greenshift = (colour_depth / 3);
-
-       red1 = (first_colour & redmask) >> redshift;
-       green1 = (first_colour & greenmask) >> greenshift;
-       blue1 = first_colour & bluemask;
-       red2 = (last_colour & redmask) >> redshift;
-       green2 = (last_colour & greenmask) >> greenshift;
-       blue2 = last_colour & bluemask;
-       if (red1 > red2) {
-               red3 = -1;
-       }
-       if (red1 < red2) {
-               red3 = 1;
-       }
-       if (green1 > green2) {
-               green3 = -1;
-       }
-       if (green1 < green2) {
-               green3 = 1;
-       }
-       if (blue1 > blue2) {
-               blue3 = -1;
-       }
-       if (blue1 < blue2) {
-               blue3 = 1;
-       }
-       red1 += red3;
-       green1 += green3;
-       blue1 += blue3;
-       if (red1 < 0) {
-               red1 = 0;
-       }
-       if (green1 < 0) {
-               green1 = 0;
-       }
-       if (blue1 < 0) {
-               blue1 = 0;
-       }
-       if (red1 > bluemask) {
-               red1 = bluemask;
-       }
-       if (green1 > bluemask) {
-               green1 = bluemask;
-       }
-       if (blue1 > bluemask) {
-               blue1 = bluemask;
-       }
-       tmp_color = (red1 << redshift) | (green1 << greenshift) | blue1;
-       return tmp_color;
-}
-
-/* this function returns the max diff for a gradient */
-unsigned long gradient_max(unsigned long first_colour,
-               unsigned long last_colour)
-{
-       int red1, green1, blue1;                                // first colour
-       int red2, green2, blue2;                                // second colour
-       int red3 = 0, green3 = 0, blue3 = 0;                    // difference
-       long redshift, greenshift;
-       int max;
-
-       if (colour_depth == 0) {
-               set_up_gradient();
-       }
-       redshift = (2 * colour_depth / 3 + colour_depth % 3);
-       greenshift = (colour_depth / 3);
-
-       red1 = (first_colour & redmask) >> redshift;
-       green1 = (first_colour & greenmask) >> greenshift;
-       blue1 = first_colour & bluemask;
-       red2 = (last_colour & redmask) >> redshift;
-       green2 = (last_colour & greenmask) >> greenshift;
-       blue2 = last_colour & bluemask;
-       red3 = abs(red1 - red2);
-       green3 = abs(green1 - green2);
-       blue3 = abs(blue1 - blue2);
-       max = red3;
-
-       if (green3 > max) {
-               max = green3;
-       }
-       if (blue3 > max) {
-               max = blue3;
-       }
-       return max;
-}
-
 static void draw_line(char *s)
 {
 #ifdef X11
index 5ff325c..44e426b 100644 (file)
@@ -297,4 +297,17 @@ extern double current_update_time, last_update_time, update_interval;
 int spaced_print(char *, int, const char *, int, ...)
        __attribute__((format(printf, 3, 5)));
 
-#endif
+#define TO_X 1
+#define TO_STDOUT 2
+#define TO_STDERR 4
+#define OVERWRITE_FILE 8
+#define APPEND_FILE 16
+enum x_initialiser_state {
+       NO = 0,
+       YES = 1,
+       NEVER = 2
+};
+extern int output_methods;
+extern enum x_initialiser_state x_initialised;
+
+#endif /* _conky_h_ */
diff --git a/src/fonts.c b/src/fonts.c
new file mode 100644 (file)
index 0000000..52f95cb
--- /dev/null
@@ -0,0 +1,183 @@
+/* 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-2008 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 "conky.h"
+#include "fonts.h"
+#include "logging.h"
+
+int selected_font = 0;
+int font_count = -1;
+struct font_list *fonts = NULL;
+
+void set_font(void)
+{
+       if ((output_methods & TO_X) == 0)
+               return;
+#ifdef XFT
+       if (use_xft) {
+               if (window.xftdraw != NULL) {
+                       XftDrawDestroy(window.xftdraw);
+               }
+               window.xftdraw = XftDrawCreate(display, window.drawable,
+                       DefaultVisual(display, screen), DefaultColormap(display, screen));
+       } else
+#endif
+       {
+               XSetFont(display, window.gc, fonts[selected_font].font->fid);
+       }
+}
+
+int addfont(const char *data_in)
+{
+       if ((output_methods & TO_X) == 0)
+               return 0;
+       if (font_count > MAX_FONTS) {
+               CRIT_ERR("you don't need that many fonts, sorry.");
+       }
+       font_count++;
+       if (font_count == 0) {
+               if (fonts != NULL) {
+                       free(fonts);
+               }
+               if ((fonts = (struct font_list *) malloc(sizeof(struct font_list)))
+                               == NULL) {
+                       CRIT_ERR("malloc");
+               }
+               memset(fonts, 0, sizeof(struct font_list));
+       }
+       fonts = realloc(fonts, (sizeof(struct font_list) * (font_count + 1)));
+       memset(&fonts[font_count], 0, sizeof(struct font_list));
+       if (fonts == NULL) {
+               CRIT_ERR("realloc in addfont");
+       }
+       // must account for null terminator
+       if (strlen(data_in) < DEFAULT_TEXT_BUFFER_SIZE) {
+               strncpy(fonts[font_count].name, data_in, DEFAULT_TEXT_BUFFER_SIZE);
+#ifdef XFT
+               fonts[font_count].font_alpha = 0xffff;
+#endif
+       } else {
+               CRIT_ERR("Oops...looks like something overflowed in addfont().");
+       }
+       return font_count;
+}
+
+void set_first_font(const char *data_in)
+{
+       if ((output_methods & TO_X) == 0)
+               return;
+       if (font_count < 0) {
+               if ((fonts = (struct font_list *) malloc(sizeof(struct font_list)))
+                               == NULL) {
+                       CRIT_ERR("malloc");
+               }
+               memset(fonts, 0, sizeof(struct font_list));
+               font_count++;
+       }
+       if (strlen(data_in) > 1) {
+               strncpy(fonts[0].name, data_in, DEFAULT_TEXT_BUFFER_SIZE);
+#ifdef XFT
+               fonts[0].font_alpha = 0xffff;
+#endif
+       }
+}
+
+void free_fonts(void)
+{
+       int i;
+
+       if ((output_methods & TO_X) == 0)
+               return;
+       for (i = 0; i <= font_count; i++) {
+#ifdef XFT
+               if (use_xft) {
+                       XftFontClose(display, fonts[i].xftfont);
+                       fonts[i].xftfont = 0;
+               } else
+#endif
+               {
+                       XFreeFont(display, fonts[i].font);
+                       fonts[i].font = 0;
+               }
+       }
+       free(fonts);
+       fonts = 0;
+       font_count = -1;
+       selected_font = 0;
+}
+
+void load_fonts(void)
+{
+       int i;
+
+       if ((output_methods & TO_X) == 0)
+               return;
+       for (i = 0; i <= font_count; i++) {
+#ifdef XFT
+               /* load Xft font */
+               if (use_xft && fonts[i].xftfont) {
+                       continue;
+               } else if (use_xft) {
+                       /* if (fonts[i].xftfont != NULL && selected_font == 0) {
+                               XftFontClose(display, fonts[i].xftfont);
+                       } */
+                       fonts[i].xftfont = XftFontOpenName(display, screen,
+                                       fonts[i].name);
+                       if (fonts[i].xftfont != NULL) {
+                               continue;
+                       }
+
+                       ERR("can't load Xft font '%s'", fonts[i].name);
+                       if ((fonts[i].xftfont = XftFontOpenName(display, screen,
+                                       "courier-12")) != NULL) {
+                               continue;
+                       }
+
+                       ERR("can't load Xft font '%s'", "courier-12");
+
+                       if ((fonts[i].font = XLoadQueryFont(display, "fixed")) == NULL) {
+                               CRIT_ERR("can't load font '%s'", "fixed");
+                       }
+                       use_xft = 0;
+
+                       continue;
+               }
+#endif
+               /* load normal font */
+               /* if (fonts[i].font != NULL) {
+                       XFreeFont(display, fonts[i].font);
+               } */
+
+               if (fonts[i].font || (fonts[i].font = XLoadQueryFont(display, fonts[i].name)) == NULL) {
+                       ERR("can't load font '%s'", fonts[i].name);
+                       if ((fonts[i].font = XLoadQueryFont(display, "fixed")) == NULL) {
+                               CRIT_ERR("can't load font '%s'", "fixed");
+                               printf("loaded fixed?\n");
+                       }
+               }
+       }
+}
+
diff --git a/src/fonts.h b/src/fonts.h
new file mode 100644 (file)
index 0000000..22682bd
--- /dev/null
@@ -0,0 +1,78 @@
+/* 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-2008 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 _FONTS_H
+#define _FONTS_H
+
+#include "x11.h"
+
+/* for fonts */
+struct font_list {
+
+       char name[DEFAULT_TEXT_BUFFER_SIZE];
+       int num;
+       XFontStruct *font;
+
+#ifdef XFT
+       XftFont *xftfont;
+       int font_alpha;
+#endif
+};
+
+#ifdef XFT
+
+#define font_height() (use_xft ? (fonts[selected_font].xftfont->ascent + \
+       fonts[selected_font].xftfont->descent) \
+       : (fonts[selected_font].font->max_bounds.ascent + \
+       fonts[selected_font].font->max_bounds.descent))
+#define font_ascent() (use_xft ? fonts[selected_font].xftfont->ascent \
+       : fonts[selected_font].font->max_bounds.ascent)
+#define font_descent() (use_xft ? fonts[selected_font].xftfont->descent \
+       : fonts[selected_font].font->max_bounds.descent)
+
+#else
+
+#define font_height() (fonts[selected_font].font->max_bounds.ascent + \
+       fonts[selected_font].font->max_bounds.descent)
+#define font_ascent() fonts[selected_font].font->max_bounds.ascent
+#define font_descent() fonts[selected_font].font->max_bounds.descent
+
+#endif
+
+#define MAX_FONTS 64 // hmm, no particular reason, just makes sense.
+
+/* direct access to registered fonts (FIXME: bad encapsulation) */
+extern struct font_list *fonts;
+extern int selected_font;
+extern int font_count;
+
+void set_font(void);
+int addfont(const char *);
+void set_first_font(const char *);
+void free_fonts(void);
+void load_fonts(void);
+
+#endif /* _FONTS_H */
diff --git a/src/specials.c b/src/specials.c
new file mode 100644 (file)
index 0000000..1c177d8
--- /dev/null
@@ -0,0 +1,347 @@
+/* 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-2008 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 "conky.h"
+#include "colours.h"
+#include "fonts.h"
+#include "logging.h"
+#include "specials.h"
+#include <math.h>
+
+/* maximum number of special things, e.g. fonts, offsets, aligns, etc. */
+unsigned int max_specials = MAX_SPECIALS_DEFAULT;
+
+/* create specials array on heap instead of stack with introduction of
+ * max_specials */
+struct special_t *specials = NULL;
+
+unsigned int special_count;
+
+/*
+ * Scanning arguments to various special text objects
+ */
+const char *scan_bar(const char *args, int *w, int *h)
+{
+       /* zero width means all space that is available */
+       *w = 0;
+       *h = 6;
+       /* bar's argument is either height or height,width */
+       if (args) {
+               int n = 0;
+
+               if (sscanf(args, "%d,%d %n", h, w, &n) <= 1) {
+                       sscanf(args, "%d %n", h, &n);
+               }
+               args += n;
+       }
+
+       return args;
+}
+
+char *scan_font(const char *args)
+{
+       if (args && *args) {
+               return strndup(args, DEFAULT_TEXT_BUFFER_SIZE);
+       }
+
+       return NULL;
+}
+
+char *scan_graph(const char *args, int *w, int *h,
+                 unsigned int *first_colour, unsigned int *last_colour,
+                 unsigned int *scale, char *showaslog)
+{
+       const char *nographtype;
+       char buf[64];
+       buf[0] = 0;
+
+       /* zero width means all space that is available */
+       *w = 0;
+       *h = 25;
+       *first_colour = 0;
+       *last_colour = 0;
+       *scale = 0;
+       if (args) {
+               //set showaslog and place the rest of the args in nographtype
+               if(strcasecmp(args, LOGGRAPH) == EQUAL) {
+                       *showaslog = TRUE;
+                       return NULL;
+               }else if(strcasecmp(args, NORMGRAPH) == EQUAL) {
+                       *showaslog = FALSE;
+                       return NULL;
+               }else if(strncasecmp(args, LOGGRAPH" ", strlen(LOGGRAPH) + 1 ) == EQUAL) {
+                       *showaslog = TRUE;
+                       nographtype = &args[strlen(LOGGRAPH) + 1];
+               }else if(strncasecmp(args, NORMGRAPH" ", strlen(NORMGRAPH) + 1 ) == EQUAL) {
+                       *showaslog = FALSE;
+                       nographtype = &args[strlen(NORMGRAPH) + 1];
+               }else{
+                       *showaslog = FALSE;
+                       nographtype = args;
+               }
+               DBGP("printing graph as %s, other args are: %s", (*showaslog ? "log" : "normal"), nographtype);
+               //check the rest of the args
+               if (sscanf(nographtype, "%d,%d %x %x %u", h, w, first_colour, last_colour, scale) == 5) {
+                       return NULL;
+               }
+               *scale = 0;
+               if (sscanf(nographtype, "%d,%d %x %x", h, w, first_colour, last_colour) == 4) {
+                       return NULL;
+               }
+               if (sscanf(nographtype, "%63s %d,%d %x %x %u", buf, h, w, first_colour, last_colour, scale) == 6) {
+                       return strndup(buf, text_buffer_size);
+               }
+               *scale = 0;
+               if (sscanf(nographtype, "%63s %d,%d %x %x", buf, h, w, first_colour, last_colour) == 5) {
+                       return strndup(buf, text_buffer_size);
+               }
+               buf[0] = '\0';
+               *h = 25;
+               *w = 0;
+               if (sscanf(nographtype, "%x %x %u", first_colour, last_colour, scale) == 3) {
+                       return NULL;
+               }
+               *scale = 0;
+               if (sscanf(nographtype, "%x %x", first_colour, last_colour) == 2) {
+                       return NULL;
+               }
+               if (sscanf(nographtype, "%63s %x %x %u", buf, first_colour, last_colour, scale) == 4) {
+                       return strndup(buf, text_buffer_size);
+               }
+               *scale = 0;
+               if (sscanf(nographtype, "%63s %x %x", buf, first_colour, last_colour) == 3) {
+                       return strndup(buf, text_buffer_size);
+               }
+               buf[0] = '\0';
+               *first_colour = 0;
+               *last_colour = 0;
+               if (sscanf(nographtype, "%d,%d %u", h, w, scale) == 3) {
+                       return NULL;
+               }
+               *scale = 0;
+               if (sscanf(nographtype, "%d,%d", h, w) == 2) {
+                       return NULL;
+               }
+               if (sscanf(nographtype, "%63s %d,%d %u", buf, h, w, scale) < 4) {
+                       *scale = 0;
+                       //TODO: check the return value and throw an error?
+                       sscanf(nographtype, "%63s %d,%d", buf, h, w);
+               }
+
+               return strndup(buf, text_buffer_size);
+       }
+
+       if (buf[0] == '\0') {
+               return NULL;
+       } else {
+               return strndup(buf, text_buffer_size);
+       }
+}
+
+/*
+ * Printing various special text objects
+ */
+
+static struct special_t *new_special(char *buf, enum special_types t)
+{
+       if (special_count >= max_specials) {
+               CRIT_ERR("too many special things in text");
+       }
+
+       buf[0] = SPECIAL_CHAR;
+       buf[1] = '\0';
+       specials[special_count].type = t;
+       return &specials[special_count++];
+}
+
+void new_bar(char *buf, int w, int h, int usage)
+{
+       struct special_t *s = new_special(buf, BAR);
+
+       s->arg = (usage > 255) ? 255 : ((usage < 0) ? 0 : usage);
+       s->width = w;
+       s->height = h;
+}
+
+#ifdef X11
+void new_font(char *buf, char *args)
+{
+       if ((output_methods & TO_X) == 0)
+               return;
+       if (args) {
+               struct special_t *s = new_special(buf, FONT);
+
+               if (s->font_added > font_count || !s->font_added || (strncmp(args, fonts[s->font_added].name, DEFAULT_TEXT_BUFFER_SIZE) != EQUAL) ) {
+                       int tmp = selected_font;
+
+                       selected_font = s->font_added = addfont(args);
+                       load_fonts();
+                       selected_font = tmp;
+               }
+       } else {
+               struct special_t *s = new_special(buf, FONT);
+               int tmp = selected_font;
+
+               selected_font = s->font_added = 0;
+               selected_font = tmp;
+       }
+}
+#endif
+
+static void graph_append(struct special_t *graph, double f, char showaslog)
+{
+       int i;
+
+       if (showaslog) {
+#ifdef MATH
+               f = log10(f + 1);
+#endif
+       }
+       
+       if (!graph->scaled && f > graph->graph_scale) {
+               f = graph->graph_scale;
+       }
+
+/* Already happens in new_graph
+       if (graph->scaled) {
+               graph->graph_scale = 1;
+       }
+*/
+       graph->graph[0] = f;    /* add new data */
+       /* shift all the data by 1 */
+       for (i = graph->graph_width - 1; i > 0; i--) {
+               graph->graph[i] = graph->graph[i - 1];
+               if (graph->scaled && graph->graph[i] > graph->graph_scale) {
+                       /* check if we need to update the scale */
+                       graph->graph_scale = graph->graph[i];
+               }
+       }
+}
+
+void new_graph(char *buf, int w, int h, unsigned int first_colour,
+               unsigned int second_colour, double i, int scale, int append, char showaslog)
+{
+       struct special_t *s = new_special(buf, GRAPH);
+
+       s->width = w;
+       if (s->graph == NULL) {
+               if (s->width > 0 && s->width < MAX_GRAPH_DEPTH) {
+                       // subtract 2 for the box
+                       s->graph_width = s->width /* - 2 */;
+               } else {
+                       s->graph_width = MAX_GRAPH_DEPTH - 2;
+               }
+               s->graph = malloc(s->graph_width * sizeof(double));
+               memset(s->graph, 0, s->graph_width * sizeof(double));
+               s->graph_scale = 100;
+       }
+       s->height = h;
+       s->first_colour = adjust_colors(first_colour);
+       s->last_colour = adjust_colors(second_colour);
+       if (scale != 0) {
+               s->scaled = 0;
+               s->graph_scale = scale;
+               s->show_scale = 0;
+       } else {
+               s->scaled = 1;
+               s->graph_scale = 1;
+               s->show_scale = 1;
+       }
+       /* if (s->width) {
+               s->graph_width = s->width - 2;  // subtract 2 for rectangle around
+       } */
+       if (showaslog) {
+#ifdef MATH
+               s->graph_scale = log10(s->graph_scale + 1);
+#endif
+       }
+       if (append) {
+               graph_append(s, i, showaslog);
+       }
+}
+
+void new_hr(char *buf, int a)
+{
+       new_special(buf, HORIZONTAL_LINE)->height = a;
+}
+
+void new_stippled_hr(char *buf, int a, int b)
+{
+       struct special_t *s = new_special(buf, STIPPLED_HR);
+
+       s->height = b;
+       s->arg = a;
+}
+
+void new_fg(char *buf, long c)
+{
+       new_special(buf, FG)->arg = c;
+}
+
+void new_bg(char *buf, long c)
+{
+       new_special(buf, BG)->arg = c;
+}
+
+void new_outline(char *buf, long c)
+{
+       new_special(buf, OUTLINE)->arg = c;
+}
+
+void new_offset(char *buf, long c)
+{
+       new_special(buf, OFFSET)->arg = c;
+}
+
+void new_voffset(char *buf, long c)
+{
+       new_special(buf, VOFFSET)->arg = c;
+}
+
+void new_alignr(char *buf, long c)
+{
+       new_special(buf, ALIGNR)->arg = c;
+}
+
+// A postive offset pushes the text further left
+void new_alignc(char *buf, long c)
+{
+       new_special(buf, ALIGNC)->arg = c;
+}
+
+void new_goto(char *buf, long c)
+{
+       new_special(buf, GOTO)->arg = c;
+}
+
+void new_tab(char *buf, int a, int b)
+{
+       struct special_t *s = new_special(buf, TAB);
+
+       s->width = a;
+       s->arg = b;
+}
+
diff --git a/src/specials.h b/src/specials.h
new file mode 100644 (file)
index 0000000..e23a599
--- /dev/null
@@ -0,0 +1,106 @@
+/* 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-2008 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 _SPECIALS_H
+#define _SPECIALS_H
+
+/* special stuff in text_buffer */
+
+#define SPECIAL_CHAR '\x01'
+
+/* why 256? cause an array of more then 256 doubles seems excessive,
+ * and who needs that kind of precision anyway? */
+#define MAX_GRAPH_DEPTH 256
+
+//don't use spaces in LOGGRAPH or NORMGRAPH if you change them
+#define LOGGRAPH "log"
+#define NORMGRAPH "normal"
+
+enum special_types {
+       HORIZONTAL_LINE,
+       STIPPLED_HR,
+       BAR,
+       FG,
+       BG,
+       OUTLINE,
+       ALIGNR,
+       ALIGNC,
+       GRAPH,
+       OFFSET,
+       VOFFSET,
+       FONT,
+       GOTO,
+       TAB,
+};
+
+struct special_t {
+       int type;
+       short height;
+       short width;
+       long arg;
+       double *graph;
+       double graph_scale;
+       short show_scale;
+       int graph_width;
+       int scaled;
+       unsigned long first_colour;     // for graph gradient
+       unsigned long last_colour;
+       short font_added;
+};
+
+/* direct access to the registered specials (FIXME: bad encapsulation) */
+extern struct special_t *specials;
+extern unsigned int special_count;
+
+/* max number of specials allowed (TODO: use linked list instead) */
+extern unsigned int max_specials;
+
+/* scanning special arguments */
+const char *scan_bar(const char *, int *, int *);
+char *scan_font(const char *);
+char *scan_graph(const char *, int *, int *, unsigned int *,
+                 unsigned int *, unsigned int *, char *);
+
+/* printing specials */
+void new_bar(char *, int, int, int);
+#ifdef X11
+void new_font(char *, char *);
+#endif
+void new_graph(char *, int, int, unsigned int,
+               unsigned int, double, int, int, char);
+void new_hr(char *, int);
+void new_stippled_hr(char *, int, int);
+void new_fg(char *, long);
+void new_bg(char *, long);
+void new_outline(char *, long);
+void new_offset(char *, long);
+void new_voffset(char *, long);
+void new_alignr(char *, long);
+void new_alignc(char *, long);
+void new_goto(char *, long);
+void new_tab(char *, int, int);
+
+#endif /* _SPECIALS_H */