Gcc complains too much when build without X11 and NCurses
[monky] / src / specials.c
1 /* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
2  *
3  * Conky, a system monitor, based on torsmo
4  *
5  * Any original torsmo code is licensed under the BSD license
6  *
7  * All code written since the fork of torsmo is licensed under the GPL
8  *
9  * Please see COPYING for details
10  *
11  * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
12  * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
13  *      (see AUTHORS)
14  * All rights reserved.
15  *
16  * This program is free software: you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation, either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  * You should have received a copy of the GNU General Public License
26  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
27  *
28  * vim: ts=4 sw=4 noet ai cindent syntax=c
29  *
30  */
31 #include "conky.h"
32 #include "colours.h"
33 #ifdef X11
34 #include "fonts.h"
35 #endif /* X11 */
36 #include "logging.h"
37 #include "specials.h"
38 #include <math.h>
39
40 /* maximum number of special things, e.g. fonts, offsets, aligns, etc. */
41 int max_specials = MAX_SPECIALS_DEFAULT;
42
43 /* create specials array on heap instead of stack with introduction of
44  * max_specials */
45 struct special_t *specials = NULL;
46
47 int special_count;
48
49 int default_bar_width = 0, default_bar_height = 6;
50 #ifdef X11
51 int default_graph_width = 0, default_graph_height = 25;
52 int default_gauge_width = 40, default_gauge_height = 25;
53 #endif /* X11 */
54
55 /*
56  * Scanning arguments to various special text objects
57  */
58
59 #ifdef X11
60 const char *scan_gauge(const char *args, int *w, int *h)
61 {
62         /*width and height*/
63         *w = default_gauge_width;
64         *h = default_gauge_height;
65
66         /* gauge's argument is either height or height,width */
67         if (args) {
68                 int n = 0;
69
70                 if (sscanf(args, "%d,%d %n", h, w, &n) <= 1) {
71                         if (sscanf(args, "%d %n", h, &n) == 2) {
72                                 *w = *h; /*square gauge*/
73                         }
74                 }
75                 args += n;
76         }
77
78         return args;
79 }
80 #endif /* X11 */
81
82 const char *scan_bar(const char *args, int *w, int *h)
83 {
84         /* zero width means all space that is available */
85         *w = default_bar_width;
86         *h = default_bar_height;
87         /* bar's argument is either height or height,width */
88         if (args) {
89                 int n = 0;
90
91                 if (sscanf(args, "%d,%d %n", h, w, &n) <= 1) {
92                         sscanf(args, "%d %n", h, &n);
93                 }
94                 args += n;
95         }
96
97         return args;
98 }
99
100 #ifdef X11
101 char *scan_font(const char *args)
102 {
103         if (args && *args) {
104                 return strndup(args, DEFAULT_TEXT_BUFFER_SIZE);
105         }
106
107         return NULL;
108 }
109
110 char *scan_graph(const char *args, int *w, int *h,
111                  unsigned int *first_colour, unsigned int *last_colour,
112                  unsigned int *scale, char *showaslog, char *tempgrad)
113 {
114         char buf[1024];
115         memset(buf, 0, 1024);
116
117         /* zero width means all space that is available */
118         *w = default_graph_width;
119         *h = default_graph_height;
120         *first_colour = 0;
121         *last_colour = 0;
122         *scale = 0;
123         *tempgrad = FALSE;
124         *showaslog = FALSE;
125         if (args) {
126                 if (strstr(args, " "TEMPGRAD) || strncmp(args, TEMPGRAD, strlen(TEMPGRAD)) == 0) {
127                         *tempgrad = TRUE;
128                 }
129                 if (strstr(args, " "LOGGRAPH) || strncmp(args, LOGGRAPH, strlen(LOGGRAPH)) == 0) {
130                         *showaslog = TRUE;
131                 }
132                 if (sscanf(args, "%d,%d %x %x %u", h, w, first_colour, last_colour, scale) == 5) {
133                         return NULL;
134                 }
135                 *scale = 0;
136                 if (sscanf(args, "%d,%d %x %x", h, w, first_colour, last_colour) == 4) {
137                         return NULL;
138                 }
139                 if (sscanf(args, "%1023s %d,%d %x %x %u", buf, h, w, first_colour, last_colour, scale) == 6) {
140                         return strndup(buf, text_buffer_size);
141                 }
142                 *scale = 0;
143                 if (sscanf(args, "%1023s %d,%d %x %x", buf, h, w, first_colour, last_colour) == 5) {
144                         return strndup(buf, text_buffer_size);
145                 }
146                 buf[0] = '\0';
147                 *h = 25;
148                 *w = 0;
149                 if (sscanf(args, "%x %x %u", first_colour, last_colour, scale) == 3) {
150                         return NULL;
151                 }
152                 *scale = 0;
153                 if (sscanf(args, "%x %x", first_colour, last_colour) == 2) {
154                         return NULL;
155                 }
156                 if (sscanf(args, "%1023s %x %x %u", buf, first_colour, last_colour, scale) == 4) {
157                         return strndup(buf, text_buffer_size);
158                 }
159                 *scale = 0;
160                 if (sscanf(args, "%1023s %x %x", buf, first_colour, last_colour) == 3) {
161                         return strndup(buf, text_buffer_size);
162                 }
163                 buf[0] = '\0';
164                 *first_colour = 0;
165                 *last_colour = 0;
166                 if (sscanf(args, "%d,%d %u", h, w, scale) == 3) {
167                         return NULL;
168                 }
169                 *scale = 0;
170                 if (sscanf(args, "%d,%d", h, w) == 2) {
171                         return NULL;
172                 }
173                 if (sscanf(args, "%1023s %d,%d %u", buf, h, w, scale) < 4) {
174                         *scale = 0;
175                         //TODO: check the return value and throw an error?
176                         sscanf(args, "%1023s %d,%d", buf, h, w);
177                 }
178
179                 return strndup(buf, text_buffer_size);
180         }
181
182         if (buf[0] == '\0') {
183                 return NULL;
184         } else {
185                 return strndup(buf, text_buffer_size);
186         }
187 }
188 #endif /* X11 */
189
190 /*
191  * Printing various special text objects
192  */
193
194 static struct special_t *new_special(char *buf, enum special_types t)
195 {
196         if (special_count >= max_specials) {
197                 CRIT_ERR(NULL, NULL, "too many special things in text");
198         }
199
200         buf[0] = SPECIAL_CHAR;
201         buf[1] = '\0';
202         specials[special_count].type = t;
203         return &specials[special_count++];
204 }
205
206 #ifdef X11
207 void new_gauge(char *buf, int w, int h, int usage)
208 {
209         struct special_t *s = 0;
210         if ((output_methods & TO_X) == 0)
211                 return;
212
213         s = new_special(buf, GAUGE);
214
215         s->arg = (usage > 255) ? 255 : ((usage < 0) ? 0 : usage);
216         s->width = w;
217         s->height = h;
218 }
219
220 void new_bar(char *buf, int w, int h, int usage)
221 {
222         struct special_t *s = 0;
223
224         if ((output_methods & TO_X) == 0)
225                 return;
226
227         s = new_special(buf, BAR);
228
229         s->arg = (usage > 255) ? 255 : ((usage < 0) ? 0 : usage);
230         s->width = w;
231         s->height = h;
232 }
233
234 void new_font(char *buf, char *args)
235 {
236         if ((output_methods & TO_X) == 0)
237                 return;
238
239         if (args) {
240                 struct special_t *s = new_special(buf, FONT);
241
242                 if (s->font_added > font_count || !s->font_added || (strncmp(args, fonts[s->font_added].name, DEFAULT_TEXT_BUFFER_SIZE) != EQUAL) ) {
243                         int tmp = selected_font;
244
245                         selected_font = s->font_added = add_font(args);
246                         selected_font = tmp;
247                 }
248         } else {
249                 struct special_t *s = new_special(buf, FONT);
250                 int tmp = selected_font;
251
252                 selected_font = s->font_added = 0;
253                 selected_font = tmp;
254         }
255 }
256
257 static void graph_append(struct special_t *graph, double f, char showaslog)
258 {
259         int i;
260
261         if (showaslog) {
262 #ifdef MATH
263                 f = log10(f + 1);
264 #endif
265         }
266         
267         if (!graph->scaled && f > graph->graph_scale) {
268                 f = graph->graph_scale;
269         }
270
271         graph->graph[0] = f;    /* add new data */
272         /* shift all the data by 1 */
273         for (i = graph->graph_width - 1; i > 0; i--) {
274                 graph->graph[i] = graph->graph[i - 1];
275                 if (graph->scaled && graph->graph[i - 1] > graph->graph_scale) {
276                         /* check if we need to update the scale */
277                         graph->graph_scale = graph->graph[i - 1];
278                 }
279         }
280         if (graph->scaled && graph->graph[graph->graph_width] > graph->graph_scale) {
281                 /* check if we need to update the scale */
282                 graph->graph_scale = graph->graph[graph->graph_width];
283         }
284 }
285
286 void new_graph(char *buf, int w, int h, unsigned int first_colour,
287                 unsigned int second_colour, double i, int scale, int append, char showaslog, char tempgrad)
288 {
289         struct special_t *s = 0;
290
291         if ((output_methods & TO_X) == 0)
292                 return;
293
294         s = new_special(buf, GRAPH);
295
296         s->width = w;
297         if (s->graph == NULL) {
298                 if (s->width > 0 && s->width < MAX_GRAPH_DEPTH) {
299                         // subtract 2 for the box
300                         s->graph_width = s->width /* - 2 */;
301                 } else {
302                         s->graph_width = MAX_GRAPH_DEPTH - 2;
303                 }
304                 s->graph = malloc(s->graph_width * sizeof(double));
305                 memset(s->graph, 0, s->graph_width * sizeof(double));
306                 s->graph_scale = 100;
307         }
308         s->height = h;
309         s->first_colour = adjust_colours(first_colour);
310         s->last_colour = adjust_colours(second_colour);
311         if (scale != 0) {
312                 s->scaled = 0;
313                 s->graph_scale = scale;
314                 s->show_scale = 0;
315         } else {
316                 s->scaled = 1;
317                 s->graph_scale = 1;
318                 s->show_scale = 1;
319         }
320         s->tempgrad = tempgrad;
321         /* if (s->width) {
322                 s->graph_width = s->width - 2;  // subtract 2 for rectangle around
323         } */
324 #ifdef MATH
325         if (showaslog) {
326                 s->graph_scale = log10(s->graph_scale + 1);
327         }
328 #endif
329         if (append) {
330                 graph_append(s, i, showaslog);
331         }
332 }
333
334 void new_hr(char *buf, int a)
335 {
336         if ((output_methods & TO_X) == 0)
337                 return;
338
339         new_special(buf, HORIZONTAL_LINE)->height = a;
340 }
341
342 void new_stippled_hr(char *buf, int a, int b)
343 {
344         struct special_t *s = 0;
345
346         if ((output_methods & TO_X) == 0)
347                 return;
348
349         s = new_special(buf, STIPPLED_HR);
350
351         s->height = b;
352         s->arg = a;
353 }
354 #endif /* X11 */
355
356 void new_fg(char *buf, long c)
357 {
358 #ifdef X11
359         if (output_methods & TO_X)
360                 new_special(buf, FG)->arg = c;
361 #endif /* X11 */
362 #ifdef NCURSES
363         if (output_methods & TO_NCURSES)
364                 new_special(buf, FG)->arg = c;
365 #endif /* NCURSES */
366         UNUSED(buf);
367         UNUSED(c);
368 }
369
370 #ifdef X11
371 void new_bg(char *buf, long c)
372 {
373         if ((output_methods & TO_X) == 0)
374                 return;
375
376         new_special(buf, BG)->arg = c;
377 }
378 #endif /* X11 */
379
380 void new_bar_in_shell(char* buffer, int buf_max_size, double usage, int width)
381 {
382         if(width<=buf_max_size){
383                 int i = 0, j = 0, scaledusage = round_to_int( usage * width / 100);
384
385                 #ifdef HAVE_OPENMP
386                 #pragma omp parallel for schedule(dynamic,10)
387                 #endif /* HAVE_OPENMP */
388                 for(i=0; i<(int)scaledusage; i++) {
389                         *(buffer+i)='#';
390                 }
391                 /* gcc seems to think i is not initialized properly :/ */
392                 j = i;
393                 #ifdef HAVE_OPENMP
394                 #pragma omp parallel for schedule(dynamic,10)
395                 #endif /* HAVE_OPENMP */
396                 for(i = j/* cheats */; i < width; i++) {
397                         *(buffer+i)='_';
398                 }
399                 *(buffer+i)=0;
400         }
401 }
402
403 void new_outline(char *buf, long c)
404 {
405         new_special(buf, OUTLINE)->arg = c;
406 }
407
408 void new_offset(char *buf, long c)
409 {
410         new_special(buf, OFFSET)->arg = c;
411 }
412
413 void new_voffset(char *buf, long c)
414 {
415         new_special(buf, VOFFSET)->arg = c;
416 }
417
418 void new_alignr(char *buf, long c)
419 {
420         new_special(buf, ALIGNR)->arg = c;
421 }
422
423 // A postive offset pushes the text further left
424 void new_alignc(char *buf, long c)
425 {
426         new_special(buf, ALIGNC)->arg = c;
427 }
428
429 void new_goto(char *buf, long c)
430 {
431         new_special(buf, GOTO)->arg = c;
432 }
433
434 void new_tab(char *buf, int a, int b)
435 {
436         struct special_t *s = new_special(buf, TAB);
437
438         s->width = a;
439         s->arg = b;
440 }
441