1 /* GKrellM
2 |  Copyright (C) 1999-2019 Bill Wilson
3 |
4 |  Author:  Bill Wilson    billw@gkrellm.net
5 |  Latest versions might be found at:  http://gkrellm.net
6 |
7 |
8 |  GKrellM is free software: you can redistribute it and/or modify it
9 |  under the terms of the GNU General Public License as published by
10 |  the Free Software Foundation, either version 3 of the License, or
11 |  (at your option) any later version.
12 |
13 |  GKrellM is distributed in the hope that it will be useful, but WITHOUT
14 |  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 |  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 |  License for more details.
17 |
18 |  You should have received a copy of the GNU General Public License
19 |  along with this program. If not, see http://www.gnu.org/licenses/
20 |
21 |
22 |  Additional permission under GNU GPL version 3 section 7
23 |
24 |  If you modify this program, or any covered work, by linking or
25 |  combining it with the OpenSSL project's OpenSSL library (or a
26 |  modified version of that library), containing parts covered by
27 |  the terms of the OpenSSL or SSLeay licenses, you are granted
28 |  additional permission to convey the resulting work.
29 |  Corresponding Source for a non-source form of such a combination
30 |  shall include the source code for the parts of OpenSSL used as well
31 |  as that of the covered work.
32 */
33 
34 #include "gkrellm.h"
35 #include "gkrellm-private.h"
36 
37 #if !defined(WIN32)
38 #include <unistd.h> /* needed for gethostname() */
39 #else
40 #include <winsock2.h> /* needed for gethostname() */
41 #endif
42 
43 #include	"pixmaps/frame_top.xpm"
44 #include	"pixmaps/frame_bottom.xpm"
45 #include	"pixmaps/frame_left.xpm"
46 #include	"pixmaps/frame_right.xpm"
47 
48 #include	"pixmaps/button_panel_out.xpm"
49 #include	"pixmaps/button_panel_in.xpm"
50 #include	"pixmaps/button_meter_out.xpm"
51 #include	"pixmaps/button_meter_in.xpm"
52 
53 #include	"pixmaps/bg_chart.xpm"
54 #include	"pixmaps/bg_grid.xpm"
55 #include	"pixmaps/bg_panel.xpm"
56 #include	"pixmaps/bg_separator.xpm"
57 
58 #include	"pixmaps/bg_meter.xpm"
59 
60 #include	"pixmaps/decal_alarm.xpm"
61 #include	"pixmaps/decal_warn.xpm"
62 //#include	"pixmaps/krell_alarm.xpm"
63 //#include	"pixmaps/krell_warn.xpm"
64 
65   /* These data images are used only for the default theme
66   */
67 #include	"pixmaps/data_in.xpm"
68 #include	"pixmaps/data_in_grid.xpm"
69 #include	"pixmaps/data_out.xpm"
70 #include	"pixmaps/data_out_grid.xpm"
71 
72 #include	"pixmaps/decal_misc.xpm"
73 #include	"pixmaps/decal_button.xpm"
74 
75 #include	"pixmaps/krell_panel.xpm"
76 #include	"pixmaps/krell_meter.xpm"
77 #include	"pixmaps/krell_slider.xpm"
78 #include	"pixmaps/krell_mini.xpm"
79 
80   /* Theme images for builtin monitors.
81   */
82 #include    "pixmaps/cal/bg_panel.xpm"
83 #include    "pixmaps/clock/bg_panel.xpm"
84 #include	"pixmaps/cpu/nice.xpm"
85 #include	"pixmaps/cpu/nice_grid.xpm"
86 #include    "pixmaps/fs/bg_panel.xpm"
87 #include    "pixmaps/fs/bg_panel_1.xpm"
88 #include    "pixmaps/fs/bg_panel_2.xpm"
89 #include	"pixmaps/fs/spacer_top.xpm"
90 #include	"pixmaps/fs/spacer_bottom.xpm"
91 #include	"pixmaps/host/bg_panel.xpm"
92 #ifdef BSD
93 #include	"pixmaps/mail/krell_mail_daemon.xpm"
94 #else
95 #include	"pixmaps/mail/krell_mail.xpm"
96 #endif
97 #include	"pixmaps/mem/bg_panel.xpm"
98 #include	"pixmaps/mem/krell.xpm"
99 #include    "pixmaps/sensors/bg_panel.xpm"
100 #include    "pixmaps/sensors/bg_panel_1.xpm"
101 #include    "pixmaps/sensors/bg_panel_2.xpm"
102 #include	"pixmaps/swap/bg_panel.xpm"
103 #include	"pixmaps/swap/krell.xpm"
104 #include	"pixmaps/uptime/bg_panel.xpm"
105 #include	"pixmaps/timer/bg_panel.xpm"
106 
107   /* Default theme images for various plugins
108   */
109 #include	"pixmaps/gkrellmms/krell.xpm"
110 #include	"pixmaps/gkrellmms/bg_scroll.xpm"
111 #include	"pixmaps/gkrellmms/bg_panel.xpm"
112 #include	"pixmaps/gkrellmms/bg_panel_1.xpm"
113 #include	"pixmaps/gkrellmms/bg_panel_2.xpm"
114 #include	"pixmaps/gkrellmms/spacer_top.xpm"
115 #include	"pixmaps/gkrellmms/spacer_bottom.xpm"
116 #include	"pixmaps/gkrellmms/play_button.xpm"
117 #include	"pixmaps/gkrellmms/prev_button.xpm"
118 #include	"pixmaps/gkrellmms/stop_button.xpm"
119 #include	"pixmaps/gkrellmms/next_button.xpm"
120 #include	"pixmaps/gkrellmms/eject_button.xpm"
121 #include	"pixmaps/gkrellmms/led_indicator.xpm"
122 
123 #include	"pixmaps/timers/bg_panel.xpm"
124 #include	"pixmaps/timers/bg_panel_1.xpm"
125 #include	"pixmaps/timers/bg_panel_2.xpm"
126 #include	"pixmaps/timers/spacer_top.xpm"
127 #include	"pixmaps/timers/spacer_bottom.xpm"
128 
129 #include	"pixmaps/volume/bg_panel.xpm"
130 #include	"pixmaps/volume/bg_panel_1.xpm"
131 #include	"pixmaps/volume/bg_panel_2.xpm"
132 #include	"pixmaps/volume/spacer_top.xpm"
133 #include	"pixmaps/volume/spacer_bottom.xpm"
134 
135 #include	"pixmaps/pmu/bg_panel.xpm"
136 #include	"pixmaps/pmu/bg_panel_1.xpm"
137 #include	"pixmaps/pmu/bg_panel_2.xpm"
138 #include	"pixmaps/pmu/spacer_top.xpm"
139 #include	"pixmaps/pmu/spacer_bottom.xpm"
140 
141 #define	SET_ALL_MARGINS	0x1000000
142 #define	OLD_SET_MARGIN	0x2000000
143 
144 static gchar	*image_type[] =
145 	{
146 	".png", ".jpg", ".xpm", ".gif"
147 	};
148 
149 gchar *
150 gkrellm_theme_file_exists(char *name, gchar *subdir)
151 	{
152 	gint			i;
153 	static gchar	*path;
154 	struct stat		st;
155 
156 	if (gkrellm_using_default_theme())
157 		return NULL;
158 	if (path)
159 		g_free(path);
160 	if (_GK.theme_alternative > 0)
161 		{
162 		for (i = 0; i < sizeof(image_type) / sizeof(char *); ++i)
163 			{
164 			if (subdir)
165 				path = g_strdup_printf("%s/%s/%s_%d%s", _GK.theme_path, subdir,
166 						name, _GK.theme_alternative, image_type[i]);
167 			else
168 				path = g_strdup_printf("%s/%s_%d%s", _GK.theme_path,
169 						name, _GK.theme_alternative, image_type[i]);
170 #ifdef WIN32
171 			if (g_stat(path, &st) == 0 && S_ISREG(st.st_mode))
172 #else
173 			if (   g_stat(path, &st) == 0
174 				&& (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))
175 			   )
176 #endif
177 				return path;
178 			g_free(path);
179 			path = NULL;
180 			}
181 		}
182 	for (i = 0; i < sizeof(image_type) / sizeof(char *); ++i)
183 		{
184 		if (subdir)
185 			path = g_strdup_printf("%s/%s/%s%s", _GK.theme_path, subdir, name,
186 					image_type[i]);
187 		else
188 			path = g_strdup_printf("%s/%s%s", _GK.theme_path, name,
189 					image_type[i]);
190 #ifdef WIN32
191 			if (g_stat(path, &st) == 0 && S_ISREG(st.st_mode))
192 #else
193 		if (   g_stat(path, &st) == 0
194 			&& (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))
195 		   )
196 #endif
197 			return path;
198 		g_free(path);
199 		path = NULL;
200 		}
201 	return NULL;
202 	}
203 
204 static void
205 set_border(GkrellmBorder *border, char *string)
206 	{
207 	if (!border)
208 		return;
209 	border->left = 0;
210 	border->right = 0;
211 	border->top = 0;
212 	border->bottom = 0;
213 	if (string == NULL)
214 		return;
215 	sscanf(string, "%d,%d,%d,%d", &border->left, &border->right,
216 				&border->top, &border->bottom);
217 	}
218 
219 static void
220 set_margins(GkrellmStyle *style, char *string)
221 	{
222 	GkrellmMargin	*m;
223 
224 	_GK.use_top_bottom_margins = TRUE;
225 	if (!style)
226 		return;
227 	m = &style->margin;
228 	m->left = 0;
229 	m->right = 0;
230 	m->top = 0;
231 	m->bottom = 0;
232 	if (string == NULL)
233 		return;
234 	sscanf(string, "%d,%d,%d,%d", &m->left, &m->right, &m->top, &m->bottom);
235 	m->left = m->left * _GK.theme_scale / 100;
236 	m->right = m->right * _GK.theme_scale / 100;
237 	m->top = m->top * _GK.theme_scale / 100;
238 	m->bottom = m->bottom * _GK.theme_scale / 100;
239 	}
240 
241 
242 static void
243 assign_font(GkrellmStyle *style, gchar *fontname, gint AorB)
244 	{
245 	GkrellmTextstyle	*ts;
246 
247 	ts = (AorB == GKRELLMSTYLE_TEXTFONT_A)
248 				? &style->label_tsA : &style->label_tsB;
249 
250 	if (strcmp(fontname, "large_font") == 0)
251 		ts->font_seed = &_GK.large_font;
252 	else if (strcmp(fontname, "normal_font") == 0)
253 		ts->font_seed = &_GK.normal_font;
254 	else if (strcmp(fontname, "small_font") == 0)
255 		ts->font_seed = &_GK.small_font;
256 	}
257 
258 static void
259 assign_textcolor(GkrellmStyle *style, gchar *arg, gint AorB)
260 	{
261 	GkrellmTextstyle *ts;
262 	gchar			*values, *s;
263 	gchar			*color, *shadowcolor, *effect;
264 
265 	values = g_strconcat(arg, NULL);
266 
267 	color = gkrellm_cut_quoted_string(values, &s);
268 	shadowcolor = gkrellm_cut_quoted_string(s, &s);
269 	effect = gkrellm_cut_quoted_string(s, &s);
270 	if (*color == '\0' || *shadowcolor == '\0' || *effect == '\0')
271 		{
272 		g_warning(_("Bad textcolor line %s\n"), arg);
273 		g_free(values);
274 		return;
275 		}
276 	ts = (AorB == GKRELLMSTYLE_TEXTCOLOR_A)
277 				? &style->label_tsA : &style->label_tsB;
278 	gkrellm_map_color_string(color, &(ts->color));
279 	gkrellm_map_color_string(shadowcolor, &(ts->shadow_color));
280 	ts->effect = gkrellm_effect_string_value(effect);
281 	g_free(values);
282 	}
283 
284 gboolean
285 gkrellm_style_is_themed(GkrellmStyle *style, gint query)
286 	{
287 	if (query == 0)
288 		query = ~0;
289 	return (style->themed & query) ? TRUE : FALSE;
290 	}
291 
292 void
293 gkrellm_set_style_krell_values(GkrellmStyle *s, gint yoff, gint depth,
294 		gint x_hot, gint expand, gint ema, gint left_margin, gint right_margin)
295 	{
296 	if (!s)
297 		return;
298 	if (yoff >= -3)
299 		{
300 		s->krell_yoff = yoff;
301 		if (yoff > 0)
302 			s->krell_yoff_not_scalable = TRUE;
303 		}
304 	if (left_margin >= 0)
305 		s->krell_left_margin = left_margin;
306 	if (right_margin >= 0)
307 		s->krell_right_margin = right_margin;
308 	if (depth > 0)
309 		s->krell_depth = depth;
310 	if (x_hot >= -1)
311 		s->krell_x_hot = x_hot;
312 	if (expand >= 0)
313 		s->krell_expand = expand;
314 	if (ema > 0)
315 		s->krell_ema_period = ema;
316 	}
317 
318 void
319 gkrellm_set_style_krell_values_default(GkrellmStyle *s, gint yoff, gint depth,
320 		gint x_hot, gint expand, gint ema, gint left_margin, gint right_margin)
321 	{
322 	if (!s)
323 		return;
324 	if (yoff >= -3 && !(s->themed & GKRELLMSTYLE_KRELL_YOFF))
325 		{
326 		s->krell_yoff = yoff;
327 		if (yoff > 0)
328 			s->krell_yoff_not_scalable = TRUE;
329 		}
330 	if (left_margin >= 0 && !(s->themed & GKRELLMSTYLE_KRELL_LEFT_MARGIN))
331 		s->krell_left_margin = left_margin;
332 	if (right_margin >= 0 && !(s->themed & GKRELLMSTYLE_KRELL_RIGHT_MARGIN))
333 		s->krell_right_margin = right_margin;
334 	if (depth > 0 && !(s->themed & GKRELLMSTYLE_KRELL_DEPTH))
335 		s->krell_depth = depth;
336 	if (x_hot >= -1 && !(s->themed & GKRELLMSTYLE_KRELL_X_HOT))
337 		s->krell_x_hot = x_hot;
338 	if (expand >= 0 && !(s->themed & GKRELLMSTYLE_KRELL_EXPAND))
339 		s->krell_expand = expand;
340 	if (ema > 0 && !(s->themed & GKRELLMSTYLE_KRELL_EMA_PERIOD))
341 		s->krell_ema_period = ema;
342 	}
343 
344 void
345 gkrellm_set_style_slider_values_default(GkrellmStyle *s, gint yoff,
346 		gint left_margin, gint right_margin)
347 	{
348 	gint	themed, y, left, right;
349 
350 	if (!s)
351 		return;
352 	themed = s->themed;
353 	y = s->krell_yoff;
354 	left = s->krell_left_margin;
355 	right = s->krell_right_margin;
356 	gkrellm_copy_style_values(s, _GK.krell_slider_style);
357 	s->themed = themed;
358 	s->krell_yoff = y;
359 	s->krell_left_margin = left;
360 	s->krell_right_margin = right;
361 
362 	if (yoff >= - 3 && !(s->themed & GKRELLMSTYLE_KRELL_YOFF))
363 		{
364 		s->krell_yoff = yoff;
365 		if (yoff > 0)
366 			s->krell_yoff_not_scalable = TRUE;
367 		}
368 	if (left_margin >= 0 && !(s->themed & GKRELLMSTYLE_KRELL_LEFT_MARGIN))
369 		s->krell_left_margin = left_margin;
370 	if (right_margin >= 0 && !(s->themed & GKRELLMSTYLE_KRELL_RIGHT_MARGIN))
371 		s->krell_right_margin = right_margin;
372 	}
373 
374 void
375 gkrellm_set_krell_expand(GkrellmStyle *style, gchar *value)
376 	{
377 	gint	expand	= KRELL_EXPAND_NONE;
378 
379 	if (!style)
380 		return;
381 	if (value)
382 		{
383 		if (!strcmp(value, "left"))
384 			expand = KRELL_EXPAND_LEFT;
385 		else if (!strcmp(value, "left-scaled"))
386 			expand = KRELL_EXPAND_LEFT_SCALED;
387 		else if (!strcmp(value, "right"))
388 			expand = KRELL_EXPAND_RIGHT;
389 		else if (!strcmp(value, "right-scaled"))
390 			expand = KRELL_EXPAND_RIGHT_SCALED;
391 		else if (!strcmp(value, "bar-mode"))
392 			expand = KRELL_EXPAND_BAR_MODE;
393 		else if (!strcmp(value, "bar-mode-scaled"))
394 			expand = KRELL_EXPAND_BAR_MODE_SCALED;
395 		}
396 	style->krell_expand = expand;
397 	}
398 
399 static gboolean
400 parse_boolean(gchar *value)
401 	{
402 	if (   !strcmp("1", value)
403 		|| !strcasecmp("true", value)
404 		|| !strcasecmp("on", value)
405 		|| !strcasecmp("yes", value)
406 	   )
407 		return TRUE;
408 	return FALSE;
409 	}
410 
411 static void
412 assign_style_entry(GkrellmStyle *style, gchar *value, gint entry_flag)
413 	{
414 	if (entry_flag == GKRELLMSTYLE_KRELL_YOFF)
415 		style->krell_yoff = atoi(value);
416 	else if (entry_flag == GKRELLMSTYLE_KRELL_YOFF_NOT_SCALABLE)
417 		style->krell_yoff_not_scalable = parse_boolean(value);
418 	else if (entry_flag == GKRELLMSTYLE_KRELL_EXPAND)
419 		gkrellm_set_krell_expand(style, value);
420 	else if (entry_flag == GKRELLMSTYLE_KRELL_X_HOT)
421 		style->krell_x_hot = atoi(value);
422 	else if (entry_flag == GKRELLMSTYLE_KRELL_EMA_PERIOD)
423 		style->krell_ema_period = atoi(value);
424 	else if (entry_flag == GKRELLMSTYLE_KRELL_DEPTH)
425 		style->krell_depth = atoi(value);
426 	else if (entry_flag == GKRELLMSTYLE_KRELL_LEFT_MARGIN)
427 		style->krell_left_margin = atoi(value);
428 	else if (entry_flag == GKRELLMSTYLE_KRELL_RIGHT_MARGIN)
429 		style->krell_right_margin = atoi(value);
430 	else if (entry_flag == GKRELLMSTYLE_LABEL_POSITION)
431 		{
432 		if (strcmp(value, "center") == 0)
433 			style->label_position = GKRELLM_LABEL_CENTER;
434 		else if (isdigit((unsigned char)*value))
435 			style->label_position = atoi(value);
436 		else
437 			style->label_position = GKRELLM_LABEL_NONE;
438 		}
439 	else if (entry_flag == GKRELLMSTYLE_LABEL_YOFF)
440 		style->label_yoff = atoi(value) * _GK.theme_scale / 100;
441 	else if (entry_flag == OLD_SET_MARGIN)	/* Deprecated as of 1.2.9 */
442 		{
443 		style->margin.left = atoi(value) * _GK.theme_scale / 100;
444 		style->margin.right = style->margin.left;
445 		}
446 	else if (entry_flag == GKRELLMSTYLE_TOP_MARGIN)
447 		{
448 		style->margin.top = atoi(value)  * _GK.theme_scale / 100;
449 		_GK.use_top_bottom_margins = TRUE;	/* Allow themes to adapt. */
450 		}
451 	else if (entry_flag == GKRELLMSTYLE_BOTTOM_MARGIN)
452 		{
453 		style->margin.bottom = atoi(value) * _GK.theme_scale / 100;
454 		_GK.use_top_bottom_margins = TRUE;	/* Allow themes to adapt. */
455 		}
456 	else if (entry_flag == GKRELLMSTYLE_LEFT_MARGIN)
457 		style->margin.left = atoi(value) * _GK.theme_scale / 100;
458 	else if (entry_flag == GKRELLMSTYLE_RIGHT_MARGIN)
459 		style->margin.right = atoi(value) * _GK.theme_scale / 100;
460 	else if (entry_flag == GKRELLMSTYLE_TRANSPARENCY)
461 		style->transparency = atoi(value);
462 	else if (entry_flag == GKRELLMSTYLE_SCROLL_TEXT_CACHE_OFF)
463 		style->scroll_text_cache_off = parse_boolean(value);
464 	else if (entry_flag == GKRELLMSTYLE_TEXTCOLOR_A)
465 		assign_textcolor(style, value, GKRELLMSTYLE_TEXTCOLOR_A);
466 	else if (entry_flag == GKRELLMSTYLE_TEXTCOLOR_B)
467 		assign_textcolor(style, value, GKRELLMSTYLE_TEXTCOLOR_B);
468 	else if (entry_flag == GKRELLMSTYLE_TEXTFONT_A)
469 		assign_font(style, value, GKRELLMSTYLE_TEXTFONT_A);
470 	else if (entry_flag == GKRELLMSTYLE_TEXTFONT_B)
471 		assign_font(style, value, GKRELLMSTYLE_TEXTFONT_B);
472 	else if (entry_flag == GKRELLMSTYLE_BORDER)
473 		set_border(&style->border, value);
474 	else if (entry_flag == SET_ALL_MARGINS)
475 		set_margins(style, value);
476 	}
477 
478 static void
479 set_themed(GkrellmStyle *s, gint flag)
480 	{
481 	if (flag == OLD_SET_MARGIN)
482 		flag = (GKRELLMSTYLE_LEFT_MARGIN | GKRELLMSTYLE_RIGHT_MARGIN);
483 	else if (flag == SET_ALL_MARGINS)
484 		flag = (  GKRELLMSTYLE_LEFT_MARGIN | GKRELLMSTYLE_RIGHT_MARGIN
485 				| GKRELLMSTYLE_TOP_MARGIN | GKRELLMSTYLE_BOTTOM_MARGIN);
486 	s->themed |= flag;
487 	}
488 
489 static void
490 assign_style(gchar *debug_name, GList *style_list, gint index,
491 				gchar *arg, gint entry_flag, gint override)
492 	{
493 	GkrellmStyle	*style;
494 	GList			*list;
495 
496 	style = (GkrellmStyle *) g_list_nth_data(style_list, index);
497 	if (!style)
498 		return;
499 
500 	/* If this is not an override assignment and this entry has already had
501 	|  an override assignment, then we do not assign.
502 	*/
503 	if (! override && (style->override & entry_flag))
504 		return;
505 	if (override)
506 		style->override |= entry_flag;
507 	assign_style_entry(style, arg, entry_flag);
508 	if (index > 0)	/* Theme has custom setting for this style */
509 		set_themed(style, entry_flag);
510 
511 	if (index++ == 0)		/* style == style_list */
512 		{
513 		if (override)
514 			g_warning("Bad override on DEFAULT: %s %s %d\n",
515 					debug_name, arg, entry_flag);
516 		for (list = style_list->next; list; list = list->next, ++index)
517 			{
518 			style = (GkrellmStyle *) list->data;
519 			if (style && !(style->override & entry_flag))
520 				assign_style_entry(style, arg, entry_flag);
521 			}
522 		}
523 	}
524 
525 #if 0
526 static void
527 assign_chart_style(gint index, gchar *arg, gint entry_flag, gint override)
528 	{
529 	assign_style("StyleChart", _GK.chart_style_list, index, arg,
530 				entry_flag, override);
531 	}
532 
533 static void
534 assign_panel_style(gint index, gchar *arg, gint entry_flag, gint override)
535 	{
536 	assign_style("StylePanel", _GK.panel_style_list, index, arg,
537 				entry_flag, override);
538 	}
539 #endif
540 
541 static void
542 assign_meter_style(gint index, gchar *arg, gint entry_flag, gint override)
543 	{
544 	assign_style("StyleMeter", _GK.meter_style_list, index, arg,
545 				entry_flag, override);
546 	}
547 
548 static void
549 assign_custom_style(gchar *debug_name, GList *style_list, gint index,
550 				gchar *arg, gint entry_flag, gchar *custom_name)
551 	{
552 	GkrellmStyle	*style, *custom_style;
553 	gint	i;
554 
555 	if ((i = gkrellm_string_position_in_list(_GK.custom_name_list, custom_name)) < 0)
556 		{
557 		style = (GkrellmStyle *) g_list_nth_data(style_list, index);
558 		if (!style)
559 			return;
560 		custom_style = gkrellm_copy_style(style);
561 		_GK.custom_name_list = g_list_append(_GK.custom_name_list,
562 				g_strdup(custom_name));
563 		_GK.custom_style_list = g_list_append(_GK.custom_style_list,
564 				custom_style);
565 		}
566 	else
567 		custom_style =
568 				(GkrellmStyle *) g_list_nth_data(_GK.custom_style_list, i);
569 
570 //g_debug("assign_custom_style(%s, %s, %d, %s) %d\n",
571 //debug_name, custom_name, entry_flag, arg, i);
572 	assign_style_entry(custom_style, arg, entry_flag);
573 	set_themed(custom_style, entry_flag);
574 	}
575 
576 static struct string_map
577 	{
578 	gchar	*string;
579 	gint	flag;
580 	}
581 	entry_map[] =
582 	{
583 	{ "krell_yoff",			GKRELLMSTYLE_KRELL_YOFF },
584 	{ "krell_yoff_not_scalable",GKRELLMSTYLE_KRELL_YOFF_NOT_SCALABLE },
585 	{ "krell_expand",		GKRELLMSTYLE_KRELL_EXPAND },
586 	{ "krell_x_hot",		GKRELLMSTYLE_KRELL_X_HOT },
587 	{ "krell_ema_period",	GKRELLMSTYLE_KRELL_EMA_PERIOD },
588 	{ "krell_depth",		GKRELLMSTYLE_KRELL_DEPTH },
589 	{ "krell_left_margin",	GKRELLMSTYLE_KRELL_LEFT_MARGIN },
590 	{ "krell_right_margin",	GKRELLMSTYLE_KRELL_RIGHT_MARGIN },
591 	{ "label_position",		GKRELLMSTYLE_LABEL_POSITION },
592 	{ "label_yoff",			GKRELLMSTYLE_LABEL_YOFF },
593 	{ "margins",			SET_ALL_MARGINS },
594 	{ "left_margin",		GKRELLMSTYLE_LEFT_MARGIN },
595 	{ "right_margin",		GKRELLMSTYLE_RIGHT_MARGIN },
596 	{ "top_margin",			GKRELLMSTYLE_TOP_MARGIN },
597 	{ "bottom_margin",		GKRELLMSTYLE_BOTTOM_MARGIN },
598 	{ "textcolor",			GKRELLMSTYLE_TEXTCOLOR_A },
599 	{ "alt_textcolor",		GKRELLMSTYLE_TEXTCOLOR_B },
600 	{ "font",				GKRELLMSTYLE_TEXTFONT_A },
601 	{ "alt_font",			GKRELLMSTYLE_TEXTFONT_B },
602 	{ "border",				GKRELLMSTYLE_BORDER },
603 	{ "transparency",		GKRELLMSTYLE_TRANSPARENCY },
604 	{ "scroll_text_cache_off",	GKRELLMSTYLE_SCROLL_TEXT_CACHE_OFF },
605 	{ "margin",				OLD_SET_MARGIN },	/* deprecated */
606 	};
607 
608 
609 static gint
610 get_entry_flag(gchar *entry)
611 	{
612 	struct string_map	*sm;
613 
614 	for (sm = &entry_map[0];
615 		sm < &entry_map[sizeof(entry_map) / sizeof(struct string_map)]; ++sm)
616 		if (!strcmp(entry, sm->string))
617 			return sm->flag;
618 	return -1;
619 	}
620 
621 static void
622 assign_gkrellmrc_style(gchar *source_line, gchar *area, gchar *string)
623 	{
624 	GList	*style_list = NULL, *name_list = NULL;
625 	gchar	*s;
626 	gchar	*arg = NULL, *mon_name = NULL, *custom_name = NULL, *entry = NULL;
627 	gint	index, entry_flag, override;
628 
629 	/* string starts out in format "*.yyy arg" or "foo.yyy arg"
630 	*/
631 	mon_name = strtok(string, " \t=:");	/* "*.yyy" or "foo.yyy" */
632 	if (mon_name && (arg = strtok(NULL, "\n")) != NULL)	/* arg is "arg" part */
633 		{
634 		while (*arg == ' ' || *arg == '\t' || *arg == '=' || *arg == ':')
635 			++arg;
636 		entry = strrchr(mon_name, '.');
637 		if (entry)
638 			*entry++ = '\0';
639 		if ((s = strchr(mon_name, '.')) != NULL)
640 			{
641 			custom_name = g_strdup(mon_name);
642 			*s = '\0';
643 			}
644 		}
645 	if (!mon_name || !entry || !*entry || !arg)
646 		{
647 		g_warning("StyleXXX ?: %s\n", source_line);
648 		g_free(custom_name);
649 		return;
650 		}
651 	override = TRUE;
652 	entry_flag = get_entry_flag(entry);
653 	if (!strcmp(area, "StyleChart"))
654 		{
655 		name_list = _GK.chart_name_list;
656 		style_list = _GK.chart_style_list;
657 		}
658 	else if (!strcmp(area, "StylePanel"))
659 		{
660 		name_list = _GK.chart_name_list;
661 		style_list = _GK.panel_style_list;
662 		}
663 	else if (!strcmp(area, "StyleMeter"))
664 		{
665 		name_list = _GK.meter_name_list;
666 		style_list = _GK.meter_style_list;
667 		}
668 	else
669 		{
670 		g_warning("StyleXXX ?: %s\n", source_line);
671 		g_free(custom_name);
672 		return;
673 		}
674 	index = gkrellm_string_position_in_list(name_list, mon_name);
675 	if (index == DEFAULT_STYLE_ID)
676 		override = FALSE;
677 
678 	if (entry_flag >= 0 && index >= 0)
679 		{
680 		if (custom_name)
681 			assign_custom_style(area, style_list, index, arg, entry_flag,
682 					custom_name);
683 		else
684 			assign_style(area, style_list, index, arg, entry_flag, override);
685 		}
686 	g_free(custom_name);
687 	}
688 
689 gint
690 gkrellm_add_chart_style(GkrellmMonitor *mon, gchar *name)
691 	{
692 	GkrellmStyle	*panel_style, *chart_style;
693 	gint			id;
694 	static gint		style_id;
695 
696 	if (!name)
697 		return 0;
698 	id = style_id++;
699 	chart_style = gkrellm_style_new0();
700 	panel_style = gkrellm_style_new0();
701 	if (mon)
702 		{
703 		if (mon->privat == NULL)
704 			mon->privat = g_new0(GkrellmMonprivate, 1);
705 		mon->privat->panel_style = panel_style;
706 		mon->privat->chart_style = chart_style;
707 		mon->privat->style_name = name;
708 		mon->privat->style_type = CHART_PANEL_TYPE;
709 		mon->privat->style_id = id;
710 		}
711 	_GK.chart_name_list = g_list_append(_GK.chart_name_list, (gchar *) name);
712 	_GK.chart_style_list = g_list_append(_GK.chart_style_list, chart_style);
713 	_GK.panel_style_list = g_list_append(_GK.panel_style_list, panel_style);
714 	_GK.bg_chart_piximage_list =
715 				g_list_append(_GK.bg_chart_piximage_list, NULL);
716 	_GK.bg_grid_piximage_list =
717 				g_list_append(_GK.bg_grid_piximage_list, NULL);
718 	_GK.bg_panel_piximage_list =
719 				g_list_append(_GK.bg_panel_piximage_list, NULL);
720 	_GK.krell_panel_piximage_list =
721 				g_list_append(_GK.krell_panel_piximage_list, NULL);
722 	return id;
723 	}
724 
725 gint
726 gkrellm_add_meter_style(GkrellmMonitor *mon, gchar *name)
727 	{
728 	GkrellmStyle	*style;
729 	gint			id;
730 	static gint		style_id;
731 
732 	if (!name)
733 		return 0;
734 	id = style_id++;
735 	style = gkrellm_style_new0();
736 	if (mon)
737 		{
738 		if (mon->privat == NULL)
739 			mon->privat = g_new0(GkrellmMonprivate, 1);
740 		mon->privat->panel_style = style;
741 		mon->privat->style_name = name;
742 		mon->privat->style_type = METER_PANEL_TYPE;
743 		mon->privat->style_id = id;
744 		}
745 	_GK.meter_name_list = g_list_append(_GK.meter_name_list, (gchar *) name);
746 	_GK.meter_style_list = g_list_append(_GK.meter_style_list, style);
747 	_GK.bg_meter_piximage_list =
748 				g_list_append(_GK.bg_meter_piximage_list, NULL);
749 	_GK.krell_meter_piximage_list =
750 				g_list_append(_GK.krell_meter_piximage_list, NULL);
751 	return id;
752 	}
753 
754 
755 static void
756 set_piximage_borders_in_list(GList *st_list, GList *im_list, GList *nm_list)
757 	{
758 	GkrellmStyle	*style;
759 	GkrellmPiximage	*image;
760 
761 	for ( ; st_list && im_list && nm_list;
762 			st_list = st_list->next, im_list = im_list->next,
763 			nm_list = nm_list->next)
764 		{
765 		style = (GkrellmStyle *) st_list->data;
766 		image = (GkrellmPiximage *) im_list->data;
767 		if (style && image)
768 			gkrellm_set_piximage_border(image, &style->border);
769 		}
770 	}
771 
772 static void
773 setup_piximages(void)
774 	{
775 	GList				*list;
776 	GkrellmMonitor		*mon;
777 	GkrellmMonprivate	*mp;
778 	gint				h;
779 
780 	gkrellm_set_piximage_border(_GK.frame_top_piximage, &_GK.frame_top_border);
781 	gkrellm_set_piximage_border(_GK.frame_bottom_piximage,
782 						&_GK.frame_bottom_border);
783 
784 	if (_GK.frame_left_width == 0)
785 		_GK.frame_left_width =
786 				gdk_pixbuf_get_width(_GK.frame_left_piximage->pixbuf);
787 //	_GK.frame_left_width =	_GK.frame_left_width * _GK.theme_scale / 100;
788 	gkrellm_set_piximage_border(_GK.frame_left_piximage,
789 						&_GK.frame_left_border);
790 
791 	if (_GK.frame_right_width == 0)
792 		_GK.frame_right_width =
793 				gdk_pixbuf_get_width(_GK.frame_right_piximage->pixbuf);
794 //	_GK.frame_right_width = _GK.frame_right_width * _GK.theme_scale / 100;
795 
796 	gkrellm_set_piximage_border(_GK.frame_right_piximage,
797 						&_GK.frame_right_border);
798 
799 	gkrellm_set_piximage_border(_GK.button_panel_out_piximage,
800 						&_GK.button_panel_border);
801 	gkrellm_set_piximage_border(_GK.button_panel_in_piximage,
802 						&_GK.button_panel_border);
803 
804 	gkrellm_set_piximage_border(_GK.button_meter_out_piximage,
805 						&_GK.button_meter_border);
806 	gkrellm_set_piximage_border(_GK.button_meter_in_piximage,
807 						&_GK.button_meter_border);
808 
809 	set_piximage_borders_in_list(_GK.chart_style_list,
810 						_GK.bg_chart_piximage_list, _GK.chart_name_list);
811 	set_piximage_borders_in_list(_GK.panel_style_list,
812 						_GK.bg_panel_piximage_list, _GK.chart_name_list);
813 	set_piximage_borders_in_list(_GK.meter_style_list,
814 						_GK.bg_meter_piximage_list, _GK.meter_name_list);
815 
816 	h = gdk_pixbuf_get_height(_GK.decal_misc_piximage->pixbuf) /
817 				N_MISC_DECALS * _GK.theme_scale / 100;
818 	gkrellm_scale_piximage_to_pixmap(_GK.decal_misc_piximage,
819 						&_GK.decal_misc_pixmap, &_GK.decal_misc_mask, -1,
820 						h * N_MISC_DECALS);
821 
822 	if (!_GK.spacer_top_chart_piximage)
823 		_GK.spacer_top_chart_piximage =
824 					gkrellm_clone_piximage(_GK.spacer_top_piximage);
825 	if (!_GK.spacer_bottom_chart_piximage)
826 		_GK.spacer_bottom_chart_piximage =
827 					gkrellm_clone_piximage(_GK.spacer_bottom_piximage);
828 
829 	if (!_GK.spacer_top_meter_piximage)
830 		_GK.spacer_top_meter_piximage =
831 					gkrellm_clone_piximage(_GK.spacer_top_piximage);
832 	if (!_GK.spacer_bottom_meter_piximage)
833 		_GK.spacer_bottom_meter_piximage =
834 					gkrellm_clone_piximage(_GK.spacer_bottom_piximage);
835 
836 	for (list = gkrellm_monitor_list; list; list = list->next)
837 		{
838 		GkrellmPiximage	*top_pix, *bot_pix;
839 
840 		mon = (GkrellmMonitor *) list->data;
841 		mp = mon->privat;
842 		if ((!mon->name || !mon->create_monitor) && mon != gkrellm_mon_host())
843 			continue;
844 		if (mp->style_type == CHART_PANEL_TYPE)
845 			{
846 			top_pix = _GK.spacer_top_chart_piximage;
847 			bot_pix = _GK.spacer_bottom_chart_piximage;
848 			mp->top_type = mp->bottom_type = GKRELLM_SPACER_CHART;
849 			}
850 		else
851 			{
852 			top_pix = _GK.spacer_top_meter_piximage;
853 			bot_pix = _GK.spacer_bottom_meter_piximage;
854 			mp->top_type = mp->bottom_type = GKRELLM_SPACER_METER;
855 			}
856 
857 		if (!mp->top_spacer.piximage)
858 			mp->top_spacer.piximage = gkrellm_clone_piximage(top_pix);
859 		gkrellm_set_piximage_border(mp->top_spacer.piximage,
860 								&_GK.spacer_top_border);
861 
862 		if (!mp->bottom_spacer.piximage)
863 			mp->bottom_spacer.piximage = gkrellm_clone_piximage(bot_pix);
864 		gkrellm_set_piximage_border(mp->bottom_spacer.piximage,
865 								&_GK.spacer_bottom_border);
866 		}
867 	}
868 
869 
870 typedef struct
871 	{
872 	gchar			*name;
873 	gchar			**xpm;
874 	GkrellmPiximage	**im;
875 	GList			**image_list;
876 	gchar			*name_in_list;
877 	}
878 	ImageTable;
879 
880 static ImageTable base_theme_piximages[]	=
881 	{
882 	/* Images in this table which have a non NULL _xpm default form the
883 	|  minimal set of required images for a complete theme change.
884 	|  If there is a NULL xpm, the image will be somehow constructed to
885 	|  a default image in the code.
886 	*/
887 { "frame_top",		frame_top_xpm,		&_GK.frame_top_piximage,	NULL, NULL},
888 { "frame_bottom",	frame_bottom_xpm,	&_GK.frame_bottom_piximage,	NULL, NULL},
889 { "frame_left",  	frame_left_xpm,		&_GK.frame_left_piximage,	NULL, NULL},
890 { "frame_right", 	frame_right_xpm,	&_GK.frame_right_piximage,	NULL, NULL},
891 
892 { "button_panel_out",	NULL,	&_GK.button_panel_out_piximage,		NULL, NULL},
893 { "button_panel_in",	NULL,	&_GK.button_panel_in_piximage,		NULL, NULL},
894 { "button_meter_out",	NULL,	&_GK.button_meter_out_piximage,		NULL, NULL},
895 { "button_meter_in",	NULL,	&_GK.button_meter_in_piximage,		NULL, NULL},
896 
897 { "bg_chart",	 	bg_chart_xpm, NULL,	&_GK.bg_chart_piximage_list,	"*"	},
898 { "bg_grid", 		bg_grid_xpm, NULL, &_GK.bg_grid_piximage_list,		"*"},
899 { "bg_panel",		bg_panel_xpm, NULL, &_GK.bg_panel_piximage_list,	"*" },
900 { "bg_meter",		bg_meter_xpm, NULL, &_GK.bg_meter_piximage_list, 	"*" },
901 
902 { "decal_alarm",	decal_alarm_xpm,	&_GK.decal_alarm_piximage, NULL, NULL},
903 { "decal_warn",		decal_warn_xpm,		&_GK.decal_warn_piximage, NULL,	NULL},
904 
905 { "decal_misc",		decal_misc_xpm,		&_GK.decal_misc_piximage, NULL, NULL},
906 { "decal_button",	decal_button_xpm,	&_GK.decal_button_piximage, NULL, NULL},
907 
908 { "data_in",	 	NULL,		&_GK.data_in_piximage,			NULL, 	NULL},
909 { "data_in_grid", 	NULL,		&_GK.data_in_grid_piximage,		NULL,	NULL},
910 { "data_out",	 	NULL,		&_GK.data_out_piximage,			NULL,	NULL},
911 { "data_out_grid", 	NULL,		&_GK.data_out_grid_piximage,	NULL,	NULL},
912 
913 { "bg_separator", NULL,		&_GK.bg_separator_piximage,			NULL,	NULL},
914 { "spacer_top",		NULL,	&_GK.spacer_top_piximage,			NULL,	NULL},
915 { "spacer_bottom",	NULL,	&_GK.spacer_bottom_piximage,		NULL,	NULL},
916 { "spacer_top_chart",	NULL, &_GK.spacer_top_chart_piximage,	NULL,	NULL},
917 { "spacer_bottom_chart",NULL, &_GK.spacer_bottom_chart_piximage,NULL,	NULL},
918 { "spacer_top_meter",	NULL, &_GK.spacer_top_meter_piximage,	NULL,	NULL},
919 { "spacer_bottom_meter",NULL, &_GK.spacer_bottom_meter_piximage,NULL,	NULL},
920 
921 { "cap_top_left_chart", NULL, &_GK.cap_top_left_chart_piximage, NULL, NULL},
922 { "cap_bottom_left_chart", NULL,&_GK.cap_bottom_left_chart_piximage,NULL,NULL},
923 { "cap_top_right_chart",   NULL, &_GK.cap_top_right_chart_piximage, NULL,NULL},
924 {"cap_bottom_right_chart",NULL,&_GK.cap_bottom_right_chart_piximage,NULL,NULL},
925 { "cap_top_left_meter", NULL, &_GK.cap_top_left_meter_piximage, NULL, NULL},
926 { "cap_bottom_left_meter", NULL,&_GK.cap_bottom_left_meter_piximage,NULL,NULL},
927 { "cap_top_right_meter",   NULL, &_GK.cap_top_right_meter_piximage, NULL,NULL},
928 {"cap_bottom_right_meter",NULL,&_GK.cap_bottom_right_meter_piximage,NULL,NULL},
929 
930 { "krell_panel",	krell_panel_xpm, NULL, &_GK.krell_panel_piximage_list, "*"},
931 { "krell_meter",	krell_meter_xpm, NULL, &_GK.krell_meter_piximage_list, "*"},
932 { "krell_mail", krell_mail_xpm, NULL,
933 								&_GK.krell_meter_piximage_list, MAIL_STYLE_NAME },
934 
935 { "krell_slider",	krell_slider_xpm,	&_GK.krell_slider_piximage,	NULL,	NULL},
936 { "krell_mini", 	krell_mini_xpm,		&_GK.krell_mini_piximage,	NULL,	NULL}
937 	};
938 
939 
940 static ImageTable	default_theme_piximages[] =
941 	{
942 { NULL, button_panel_out_xpm, &_GK.button_panel_out_piximage,NULL, NULL},
943 { NULL, button_panel_in_xpm, &_GK.button_panel_in_piximage, NULL, NULL},
944 { NULL, button_meter_out_xpm,&_GK.button_meter_out_piximage, NULL, NULL},
945 { NULL, button_meter_in_xpm, &_GK.button_meter_in_piximage, NULL, NULL},
946 
947 { NULL,	bg_separator_xpm,	&_GK.bg_separator_piximage, NULL, NULL},
948 
949 { NULL,	bg_panel_cal_xpm, NULL, &_GK.bg_meter_piximage_list, CAL_STYLE_NAME},
950 { NULL,	bg_panel_clock_xpm, NULL, &_GK.bg_meter_piximage_list, CLOCK_STYLE_NAME},
951 { NULL, bg_panel_mem_xpm, NULL, &_GK.bg_meter_piximage_list, MEM_STYLE_NAME},
952 { NULL,	bg_panel_host_xpm, NULL, &_GK.bg_meter_piximage_list, HOST_STYLE_NAME},
953 { NULL, bg_panel_uptime_xpm, NULL, &_GK.bg_meter_piximage_list, UPTIME_STYLE_NAME},
954 { NULL, bg_panel_timer_xpm, NULL, &_GK.bg_meter_piximage_list, TIMER_STYLE_NAME},
955 { NULL, bg_panel_swap_xpm, NULL, &_GK.bg_meter_piximage_list, SWAP_STYLE_NAME},
956 
957 { NULL,	data_in_xpm,		&_GK.data_in_piximage,		NULL, NULL},
958 { NULL,	data_in_grid_xpm,	&_GK.data_in_grid_piximage,	NULL, NULL},
959 { NULL,	data_out_xpm,		&_GK.data_out_piximage,		NULL, NULL},
960 { NULL,	data_out_grid_xpm,	&_GK.data_out_grid_piximage, NULL, NULL},
961 
962 { NULL,	krell_mem_xpm, NULL, &_GK.krell_meter_piximage_list, MEM_STYLE_NAME},
963 { NULL,	krell_swap_xpm, NULL, &_GK.krell_meter_piximage_list, SWAP_STYLE_NAME},
964 	};
965 
966 static ImageTable	default_theme_alt0_piximages[] =
967 	{
968 { NULL,	bg_panel_fs_xpm, NULL, &_GK.bg_meter_piximage_list, FS_STYLE_NAME},
969 { NULL,	bg_panel_sensors_xpm, NULL,&_GK.bg_meter_piximage_list, "sensors" },
970 
971 /* Plugins */
972 { NULL,	bg_panel_timers_xpm,	NULL, &_GK.bg_meter_piximage_list, "timers"},
973 { NULL,	bg_panel_volume_xpm,	NULL, &_GK.bg_meter_piximage_list, "volume"},
974 { NULL,	krell_gkrellmms_xpm,	NULL, &_GK.krell_meter_piximage_list, "gkrellmms"},
975 { NULL,	bg_panel_gkrellmms_xpm,	NULL, &_GK.bg_meter_piximage_list, "gkrellmms"},
976 { NULL,	bg_panel_pmu_xpm,		NULL, &_GK.bg_meter_piximage_list, "pmu"},
977 	};
978 
979 static ImageTable	default_theme_alt1_piximages[] =
980 	{
981 { NULL,	bg_panel_fs_1_xpm, NULL, &_GK.bg_meter_piximage_list, FS_STYLE_NAME},
982 { NULL,	bg_panel_sensors_1_xpm, NULL, &_GK.bg_meter_piximage_list,
983 			"sensors"},
984 
985 /* Plugins */
986 { NULL,	bg_panel_timers_1_xpm,	NULL, &_GK.bg_meter_piximage_list, "timers"},
987 { NULL,	bg_panel_volume_1_xpm,	NULL, &_GK.bg_meter_piximage_list, "volume"},
988 { NULL,	bg_panel_gkrellmms_1_xpm, NULL, &_GK.bg_meter_piximage_list, "gkrellmms"},
989 { NULL,	bg_panel_pmu_1_xpm,		NULL, &_GK.bg_meter_piximage_list, "pmu"},
990 	};
991 
992 static ImageTable	default_theme_alt2_piximages[] =
993 	{
994 { NULL,	bg_panel_fs_2_xpm, NULL, &_GK.bg_meter_piximage_list, FS_STYLE_NAME},
995 { NULL,	bg_panel_sensors_2_xpm, NULL, &_GK.bg_meter_piximage_list,
996 			"sensors"},
997 
998 /* Plugins */
999 { NULL,	bg_panel_timers_2_xpm,	NULL, &_GK.bg_meter_piximage_list, "timers"},
1000 { NULL,	bg_panel_volume_2_xpm,	NULL, &_GK.bg_meter_piximage_list, "volume"},
1001 { NULL,	bg_panel_gkrellmms_2_xpm, NULL, &_GK.bg_meter_piximage_list, "gkrellmms"},
1002 { NULL,	bg_panel_pmu_2_xpm,		NULL, &_GK.bg_meter_piximage_list, "pmu"},
1003 	};
1004 
1005 
1006   /* Need a trap to look for extra custom and extension images I've made for
1007   |  the default theme.
1008   */
1009 static GkrellmPiximage *
1010 default_theme_extension_piximage(gchar *name, gchar *subdir)
1011 	{
1012 	GkrellmPiximage	*im		= NULL;
1013 
1014 	if (!strcmp(subdir, "gkrellmms"))
1015 		{
1016 		if (!strcmp(name, "bg_scroll"))
1017 			im = gkrellm_piximage_new_from_xpm_data(bg_scroll_gkrellmms_xpm);
1018 		if (!strcmp(name, "play_button"))
1019 			im = gkrellm_piximage_new_from_xpm_data(gkrellmms_play_button_xpm);
1020 		if (!strcmp(name, "prev_button"))
1021 			im = gkrellm_piximage_new_from_xpm_data(gkrellmms_prev_button_xpm);
1022 		if (!strcmp(name, "stop_button"))
1023 			im = gkrellm_piximage_new_from_xpm_data(gkrellmms_stop_button_xpm);
1024 		if (!strcmp(name, "next_button"))
1025 			im = gkrellm_piximage_new_from_xpm_data(gkrellmms_next_button_xpm);
1026 		if (!strcmp(name, "eject_button"))
1027 			im =gkrellm_piximage_new_from_xpm_data(gkrellmms_eject_button_xpm);
1028 		if (!strcmp(name, "led_indicator"))
1029 			im=gkrellm_piximage_new_from_xpm_data(gkrellmms_led_indicator_xpm);
1030 		}
1031 	else if (!strcmp(subdir, CPU_STYLE_NAME) && !strcmp(name, "nice"))
1032 		im = gkrellm_piximage_new_from_xpm_data(nice_xpm);
1033 	else if (!strcmp(subdir, CPU_STYLE_NAME) && !strcmp(name,"nice_grid"))
1034 		im = gkrellm_piximage_new_from_xpm_data(nice_grid_xpm);
1035 	return im;
1036 	}
1037 
1038 gboolean
1039 gkrellm_load_piximage_from_inline(gchar *name, const guint8 *data,
1040 			GkrellmPiximage **image, gchar *subdir, gboolean copy_pixels)
1041 	{
1042 	GkrellmPiximage	*im		= NULL;
1043 	gchar			*fname;
1044 
1045 	if (gkrellm_using_default_theme() && name && subdir)
1046 		im = default_theme_extension_piximage(name, subdir);
1047 	else if (name && (fname = gkrellm_theme_file_exists(name, subdir)) != NULL)
1048 		{
1049 		name = fname;
1050 		im = gkrellm_piximage_new_from_file(fname);
1051 		if (im == NULL)
1052 			g_warning(_("  Cannot load file image: %s\n"), fname);
1053 		}
1054 	if (im == NULL && data)
1055 		{
1056 		im = gkrellm_piximage_new_from_inline(data, copy_pixels);
1057 		if (im == NULL)
1058 			g_warning(_("  Cannot load GdkPixbuf inline data.\n"));
1059 		}
1060 	if (im && image)
1061 		{
1062 		if (*image)
1063 			gkrellm_destroy_piximage(*image);
1064 		*image = im;
1065 		}
1066 	return (im ? TRUE : FALSE);
1067     }
1068 
1069 gboolean
1070 gkrellm_load_piximage(gchar *name, gchar **xpm, GkrellmPiximage **image,
1071 			gchar *subdir)
1072 	{
1073 	GkrellmPiximage	*im		= NULL;
1074 	gchar			*fname;
1075 
1076 	if (gkrellm_using_default_theme() && name && subdir)
1077 		im = default_theme_extension_piximage(name, subdir);
1078 	else if (name && (fname = gkrellm_theme_file_exists(name, subdir)) != NULL)
1079 		{
1080 		name = fname;
1081 		im = gkrellm_piximage_new_from_file(fname);
1082 		if (im == NULL)
1083 			g_warning(_("  Cannot load file image: %s\n"), fname);
1084 		}
1085 	if (im == NULL && xpm)
1086 		{
1087 		im = gkrellm_piximage_new_from_xpm_data(xpm);
1088 		if (im == NULL)
1089 			g_warning(_("  Cannot load xpm: %s\n"), name);
1090 		}
1091 	if (im && image)
1092 		{
1093 		if (*image)
1094 			gkrellm_destroy_piximage(*image);
1095 		*image = im;
1096 		}
1097 	return (im ? TRUE : FALSE);
1098     }
1099 
1100 static void
1101 load_from_piximage_list(gchar *name, GList *image_list,
1102 				gint index, gchar *subdir)
1103 	{
1104 	GList			*list;
1105 	GkrellmPiximage	*im;
1106 
1107 	list = g_list_nth(image_list, index);
1108 	if (list)
1109 		{
1110 		im = (GkrellmPiximage *) list->data;
1111 		gkrellm_load_piximage(name, NULL, &im, subdir);
1112 		list->data = (gpointer) im;
1113 		}
1114 	else
1115 		g_warning("Bad index %d for image list (meter/panel problem?)\n", index);
1116 	}
1117 
1118 static void
1119 load_monitor_specific_piximages(void)
1120 	{
1121 	GkrellmMonitor	*mon;
1122 	GList			*list;
1123 	gchar			*subdir;
1124 	gint			i;
1125 
1126 	for (list = gkrellm_monitor_list; list; list = list->next)
1127 		{
1128 		mon = (GkrellmMonitor *) list->data;
1129 		if ((subdir = mon->privat->style_name) == NULL)
1130 			continue;
1131 		i = mon->privat->style_id;
1132 		if (mon->privat->style_type == CHART_PANEL_TYPE)
1133 			{
1134 			load_from_piximage_list("bg_chart",
1135 						_GK.bg_chart_piximage_list, i, subdir);
1136 			load_from_piximage_list("bg_grid",
1137 						_GK.bg_grid_piximage_list, i, subdir);
1138 			load_from_piximage_list("bg_panel",
1139 						_GK.bg_panel_piximage_list, i, subdir);
1140 			load_from_piximage_list("krell",
1141 						_GK.krell_panel_piximage_list, i, subdir);
1142 			}
1143 		else
1144 			{
1145 			load_from_piximage_list("krell",
1146 						_GK.krell_meter_piximage_list, i, subdir);
1147 			load_from_piximage_list("bg_panel",
1148 						_GK.bg_meter_piximage_list, i, subdir);
1149 			load_from_piximage_list("bg_meter",
1150 						_GK.bg_meter_piximage_list, i, subdir);
1151 			}
1152 		gkrellm_load_piximage("spacer_top", NULL,
1153 					&mon->privat->top_spacer.piximage, subdir);
1154 		gkrellm_load_piximage("spacer_bottom", NULL,
1155 					&mon->privat->bottom_spacer.piximage, subdir);
1156 		}
1157 	}
1158 
1159 static void
1160 assign_gkrellmrc_spacer(gchar *source_line, gchar *area, gchar *string)
1161 	{
1162 	GkrellmMonitor	*mon = NULL;
1163 	gchar			style_name[32], arg[32], *s;
1164 	gint			n;
1165 
1166 	if ((n = sscanf(string, "%31s %31[^\n]", style_name, arg)) < 1)
1167 		return;
1168 	if (n == 1)
1169 		strcpy(arg, style_name);
1170 	else if ((mon = gkrellm_monitor_from_style_name(style_name)) == NULL)
1171 		return;
1172 
1173 	for (s = arg; *s == ' ' || *s == '=' || *s == '\t'; ++s)
1174 		;
1175 
1176 	if (!strncmp(area, "spacer_top_height", 17))
1177 		{
1178 		if (n == 1 && !strcmp(area, "spacer_top_height_chart"))
1179 			_GK.spacer_top_height_chart = atoi(s);
1180 		else if (n == 1 && !strcmp(area, "spacer_top_height_meter"))
1181 			_GK.spacer_top_height_meter = atoi(s);
1182 		else if (n == 1)
1183 			{
1184 			_GK.spacer_top_height_chart = atoi(s);
1185 			_GK.spacer_top_height_meter = _GK.spacer_top_height_chart;
1186 			}
1187 		else
1188 			mon->privat->top_spacer.height = atoi(s);
1189 		}
1190 	else if (!strncmp(area, "spacer_bottom_height", 20))
1191 		{
1192 		if (n == 1 && !strcmp(area, "spacer_bottom_height_chart"))
1193 			_GK.spacer_bottom_height_chart = atoi(s);
1194 		else if (n == 1 && !strcmp(area, "spacer_bottom_height_meter"))
1195 			_GK.spacer_bottom_height_meter = atoi(s);
1196 		else if (n == 1)
1197 			{
1198 			_GK.spacer_bottom_height_chart = atoi(s);
1199 			_GK.spacer_bottom_height_meter = _GK.spacer_bottom_height_chart;
1200 			}
1201 		else
1202 			mon->privat->bottom_spacer.height = atoi(s);
1203 		}
1204 	}
1205 
1206 
1207   /* I have to do something about separate chart/meter lists.
1208   */
1209 static GList *
1210 lookup_piximage_from_name(GList *image_list, gchar *name)
1211 	{
1212 	GList	*n_list, *i_list;
1213 
1214 	for (n_list = _GK.chart_name_list, i_list = image_list;
1215 			n_list && i_list; n_list = n_list->next, i_list = i_list->next)
1216 		if (!strcmp(name, (gchar *) n_list->data))
1217 			return i_list;
1218 	for (n_list = _GK.meter_name_list, i_list = image_list;
1219 			n_list && i_list; n_list = n_list->next, i_list = i_list->next)
1220 		if (!strcmp(name, (gchar *) n_list->data))
1221 			return i_list;
1222 	return NULL;
1223 	}
1224 
1225 static void
1226 load_piximage_table(ImageTable *ti, gint n_piximages, gchar *subdir)
1227 	{
1228 	GkrellmPiximage	*im;
1229 	GList			*list;
1230 	gint			i;
1231 
1232 	for (i = 0; i < n_piximages; ++i, ++ti)
1233 		{
1234 		if (ti->image_list)
1235 			{
1236 /*			list = g_list_nth(*(ti->image_list), ti->list_index); */
1237 			list = lookup_piximage_from_name(*(ti->image_list),
1238 							ti->name_in_list);
1239 			if (list)
1240 				{
1241 				im = (GkrellmPiximage *) list->data;
1242 				gkrellm_load_piximage(ti->name, ti->xpm, &im, subdir);
1243 				list->data = (gpointer) im;
1244 				}
1245 			}
1246 		else
1247 			gkrellm_load_piximage(ti->name, ti->xpm, ti->im, subdir);
1248 		}
1249     }
1250 
1251   /* When loading a new theme, required base level images are not cleaned
1252   |  so the program will not crash if a theme does not have all images yet.
1253   |  It will just look funny.  But all optional base level images are cleaned
1254   |  so they will not carry over to the new theme.  There are no optional
1255   |  base level images in the image_lists.
1256   */
1257 static void
1258 clean_base_piximage_table(void)
1259 	{
1260 	ImageTable	*ti;
1261 	gint		i;
1262 
1263 	ti = &base_theme_piximages[0];
1264 	for (i = 0; i < sizeof(base_theme_piximages) / sizeof(ImageTable);
1265 					++i, ++ti)
1266 		if (ti->xpm == NULL && ti->im && *(ti->im))	/* Is an optional image */
1267 			{
1268 			gkrellm_destroy_piximage(*(ti->im));
1269 			*(ti->im) = NULL;
1270 			}
1271 	}
1272 
1273 static void
1274 destroy_piximage(GkrellmPiximage **im)
1275 	{
1276 	if (im && *im)
1277 		{
1278 		gkrellm_destroy_piximage(*im);
1279 		*im = NULL;
1280 		}
1281 	}
1282 
1283 static void
1284 destroy_piximage_list(GList *list, GList *name_list, gchar *debug_name)
1285 	{
1286 	GkrellmPiximage *im;
1287 
1288 	for ( ; list; list = list->next, name_list = name_list->next)
1289 		{
1290 		im = (GkrellmPiximage *) list->data;
1291 		destroy_piximage(&im);
1292 		list->data = NULL;
1293 		}
1294 	}
1295 
1296 static void
1297 destroy_monitor_specific_piximages(void)
1298 	{
1299 	GkrellmMonitor	*mon;
1300 	GList			*list;
1301 
1302 	for (list = gkrellm_monitor_list; list; list = list->next)
1303 		{
1304 		mon = (GkrellmMonitor *) list->data;
1305 		destroy_piximage(&mon->privat->top_spacer.piximage);
1306 		destroy_piximage(&mon->privat->bottom_spacer.piximage);
1307 		}
1308 	}
1309 
1310 void
1311 gkrellm_load_theme_piximages(void)
1312 	{
1313 	GkrellmMonitor	*mon;
1314 	gint			n_base, n_default;
1315 
1316 	/* Free up all custom images from old theme.
1317 	*/
1318 	destroy_piximage_list(_GK.bg_chart_piximage_list, _GK.chart_name_list,
1319 				"bg_chart");
1320 	destroy_piximage_list(_GK.bg_grid_piximage_list, _GK.chart_name_list,
1321 				"bg_grid");
1322 	destroy_piximage_list(_GK.bg_panel_piximage_list, _GK.chart_name_list,
1323 				"bg_panel");
1324 	destroy_piximage_list(_GK.bg_meter_piximage_list, _GK.meter_name_list,
1325 				"bg_meter");
1326 	destroy_piximage_list(_GK.krell_panel_piximage_list, _GK.chart_name_list,
1327 				"krell_panel");
1328 	destroy_piximage_list(_GK.krell_meter_piximage_list, _GK.meter_name_list,
1329 				"krell_meter");
1330 	destroy_monitor_specific_piximages();
1331 
1332 	clean_base_piximage_table();
1333 
1334 	/* This loads the base images in the top level of the theme directory.
1335 	|  For backward compatibility, it also loads monitor specific name
1336 	|  qualified images in the top level directory.  The new way is for
1337 	|  monitor specific images to be in subdirectories, loaded below.
1338 	*/
1339 	n_base = sizeof(base_theme_piximages) / sizeof(ImageTable);
1340 	load_piximage_table(&base_theme_piximages[0], n_base, NULL);
1341 
1342 	if (gkrellm_using_default_theme())
1343 		{
1344 		n_default = sizeof(default_theme_piximages) / sizeof(ImageTable);
1345 		load_piximage_table(&default_theme_piximages[0], n_default, NULL);
1346 
1347 		if (_GK.theme_alternative == 2 || _GK.theme_alternative == 5)
1348 			{
1349 			n_default =
1350 					sizeof(default_theme_alt2_piximages) / sizeof(ImageTable);
1351 			load_piximage_table(&default_theme_alt2_piximages[0],
1352 					n_default, NULL);
1353 			}
1354 		else if (_GK.theme_alternative == 1 || _GK.theme_alternative == 4)
1355 			{
1356 			n_default =
1357 					sizeof(default_theme_alt1_piximages) / sizeof(ImageTable);
1358 			load_piximage_table(&default_theme_alt1_piximages[0],
1359 					n_default, NULL);
1360 			}
1361 		else
1362 			{
1363 			n_default =
1364 					sizeof(default_theme_alt0_piximages) / sizeof(ImageTable);
1365 			load_piximage_table(&default_theme_alt0_piximages[0],
1366 					n_default, NULL);
1367 			}
1368 
1369 		if ((mon = gkrellm_monitor_from_style_name("timers")) != NULL)
1370 			{
1371 			gkrellm_load_piximage(NULL, spacer_top_timers_xpm,
1372 						&mon->privat->top_spacer.piximage, NULL);
1373 			gkrellm_load_piximage(NULL, spacer_bottom_timers_xpm,
1374 						&mon->privat->bottom_spacer.piximage, NULL);
1375 			}
1376 		if ((mon = gkrellm_monitor_from_style_name("volume")) != NULL)
1377 			{
1378 			gkrellm_load_piximage(NULL, spacer_top_volume_xpm,
1379 						&mon->privat->top_spacer.piximage, NULL);
1380 			gkrellm_load_piximage(NULL, spacer_bottom_volume_xpm,
1381 						&mon->privat->bottom_spacer.piximage, NULL);
1382 			}
1383 		if ((mon = gkrellm_monitor_from_style_name("gkrellmms")) != NULL)
1384 			{
1385 			gkrellm_load_piximage(NULL, spacer_top_gkrellmms_xpm,
1386 						&mon->privat->top_spacer.piximage, NULL);
1387 			gkrellm_load_piximage(NULL, spacer_bottom_gkrellmms_xpm,
1388 						&mon->privat->bottom_spacer.piximage, NULL);
1389 			}
1390 		if ((mon = gkrellm_monitor_from_style_name("pmu")) != NULL)
1391 			{
1392 			gkrellm_load_piximage(NULL, spacer_top_pmu_xpm,
1393 						&mon->privat->top_spacer.piximage, NULL);
1394 			gkrellm_load_piximage(NULL, spacer_bottom_pmu_xpm,
1395 						&mon->privat->bottom_spacer.piximage, NULL);
1396 			}
1397 		if ((mon = gkrellm_monitor_from_style_name(FS_STYLE_NAME)) != NULL)
1398 			{
1399 			gkrellm_load_piximage(NULL, spacer_top_fs_xpm,
1400 						&mon->privat->top_spacer.piximage, NULL);
1401 			gkrellm_load_piximage(NULL, spacer_bottom_fs_xpm,
1402 						&mon->privat->bottom_spacer.piximage, NULL);
1403 			}
1404 		}
1405 	else
1406 		{
1407 		load_monitor_specific_piximages();
1408 		}
1409 	setup_piximages();
1410 	}
1411 
1412   /* Borders for things that are not primary background parts of a monitor,
1413   |  and so are not set by a style line.
1414   */
1415 static gchar
1416 			*frame_top_border,
1417 			*frame_bottom_border,
1418 			*frame_left_border,
1419 			*frame_right_border,
1420 			*button_panel_border,
1421 			*button_meter_border,
1422 			*krell_slider_expand,
1423 			*frame_left_chart_border,
1424 			*frame_right_chart_border,
1425 			*frame_left_panel_border,
1426 			*frame_right_panel_border,
1427 			*spacer_top_border,
1428 			*spacer_bottom_border;
1429 
1430 gint		krell_slider_depth,
1431 			krell_slider_x_hot;
1432 
1433 static struct	_config
1434 	{
1435 	gchar	*option;
1436 	gint	*value;
1437 	gchar	**arg;
1438 	gint	minimum;
1439 	}
1440 	theme_config []	=
1441 	{
1442 	{"author",				NULL,		NULL,			-100 },
1443 
1444 	{"theme_alternatives",	&_GK.theme_n_alternatives,	NULL,		0  },
1445 
1446 	{"frame_top_height",	&_GK.frame_top_height,		NULL,		0  },
1447 	{"frame_bottom_height",	&_GK.frame_bottom_height,	NULL,		0  },
1448 	{"frame_left_width",	&_GK.frame_left_width,		NULL,		0  },
1449 	{"frame_right_width",	&_GK.frame_right_width,		NULL,		0  },
1450 	{"frame_left_chart_overlap",  &_GK.frame_left_chart_overlap,   NULL, 0  },
1451 	{"frame_right_chart_overlap", &_GK.frame_right_chart_overlap,  NULL, 0  },
1452 	{"frame_left_panel_overlap",  &_GK.frame_left_panel_overlap,   NULL, 0  },
1453 	{"frame_right_panel_overlap", &_GK.frame_right_panel_overlap,  NULL, 0  },
1454 	{"frame_left_spacer_overlap",  &_GK.frame_left_spacer_overlap,   NULL, 0 },
1455 	{"frame_right_spacer_overlap", &_GK.frame_right_spacer_overlap,  NULL, 0 },
1456 	{"chart_width_ref",		&_GK.chart_width_ref,		NULL,		30 },
1457 	{"chart_height_min",	&_GK.chart_height_min,		NULL,		2 },
1458 	{"chart_height_max",	&_GK.chart_height_max,		NULL,		20 },
1459 	{"bg_separator_height", &_GK.bg_separator_height,	NULL,		0  },
1460 	{"allow_scaling",		&_GK.allow_scaling,			NULL,		0 },
1461 
1462 	{"rx_led_x",			&_GK.rx_led_x,				NULL,		-99 },
1463 	{"rx_led_y",			&_GK.rx_led_y,				NULL,		0   },
1464 	{"tx_led_x",			&_GK.tx_led_x,				NULL,		-99 },
1465 	{"tx_led_y",			&_GK.tx_led_y,				NULL,		0   },
1466 
1467 	/* These two are handled as a service for mail.c because of historical
1468 	|  reasons.  They should be set with set_integer in the gkrellmrc.
1469 	*/
1470 	{"decal_mail_frames",	&_GK.decal_mail_frames,	NULL,			1  },
1471 	{"decal_mail_delay",	&_GK.decal_mail_delay,	NULL,			1  },
1472 
1473 	{"decal_alarm_frames",	&_GK.decal_alarm_frames,	NULL,			1  },
1474 	{"decal_warn_frames",	&_GK.decal_warn_frames,	NULL,			1  },
1475 
1476 	{"chart_in_color",		NULL,		&_GK.chart_in_color,		-100 },
1477 	{"chart_in_color_grid",	NULL,		&_GK.chart_in_color_grid,	-100 },
1478 	{"chart_out_color",		NULL,		&_GK.chart_out_color,		-100 },
1479 	{"chart_out_color_grid",NULL,		&_GK.chart_out_color_grid,	-100 },
1480 
1481 	{"chart_text_no_fill",	&_GK.chart_text_no_fill,	NULL,			0  },
1482 
1483 	{"bg_grid_mode",		&_GK.bg_grid_mode,		NULL,			0  },
1484 
1485 	{"frame_top_border",	NULL,		&frame_top_border,			-100 },
1486 	{"frame_bottom_border",	NULL,		&frame_bottom_border,		-100 },
1487 	{"frame_left_border",	NULL,		&frame_left_border,			-100 },
1488 	{"frame_right_border",	NULL,		&frame_right_border,		-100 },
1489 	{"button_panel_border", NULL,		&button_panel_border,		-100 },
1490 	{"button_meter_border", NULL,		&button_meter_border,		-100 },
1491 	{"frame_left_chart_border", NULL,	&frame_left_chart_border,	-100 },
1492 	{"frame_right_chart_border", NULL,	&frame_right_chart_border,	-100 },
1493 	{"frame_left_panel_border", NULL,	&frame_left_panel_border,	-100 },
1494 	{"frame_right_panel_border", NULL,	&frame_right_panel_border,	-100 },
1495 	{"spacer_top_border",	NULL,		&spacer_top_border,			-100 },
1496 	{"spacer_bottom_border",	NULL,	&spacer_bottom_border,		-100 },
1497 
1498 	{"krell_slider_depth",	&krell_slider_depth,	NULL,			1  },
1499 	{"krell_slider_x_hot",	&krell_slider_x_hot,	NULL,			-1  },
1500 	{"krell_slider_expand",	NULL, 		&krell_slider_expand,		-1  },
1501 	};
1502 
1503 
1504   /* Handle borders set in gkrellmrc which are not set by a style line.
1505   */
1506 static void
1507 cleanup_gkrellmrc(void)
1508 	{
1509 	set_border(&_GK.frame_top_border, frame_top_border);
1510 	set_border(&_GK.frame_bottom_border, frame_bottom_border);
1511 	set_border(&_GK.frame_left_border, frame_left_border);
1512 	set_border(&_GK.frame_right_border, frame_right_border);
1513 
1514 	set_border(&_GK.frame_left_chart_border, frame_left_chart_border);
1515 	set_border(&_GK.frame_right_chart_border, frame_right_chart_border);
1516 	set_border(&_GK.frame_left_panel_border, frame_left_panel_border);
1517 	set_border(&_GK.frame_right_panel_border, frame_right_panel_border);
1518 
1519 	set_border(&_GK.spacer_top_border, spacer_top_border);
1520 	set_border(&_GK.spacer_bottom_border, spacer_bottom_border);
1521 
1522 	set_border(&_GK.button_panel_border, button_panel_border);
1523 	set_border(&_GK.button_meter_border, button_meter_border);
1524 
1525 	_GK.krell_slider_style->krell_x_hot  = krell_slider_x_hot;
1526 	_GK.krell_slider_style->krell_depth  = krell_slider_depth;
1527 	gkrellm_set_krell_expand(_GK.krell_slider_style, krell_slider_expand);
1528 	_GK.rx_led_x = _GK.rx_led_x * _GK.theme_scale / 100;
1529 	_GK.rx_led_y = _GK.rx_led_y * _GK.theme_scale / 100;
1530 	_GK.tx_led_x = _GK.tx_led_x * _GK.theme_scale / 100;
1531 	_GK.tx_led_y = _GK.tx_led_y * _GK.theme_scale / 100;
1532 	}
1533 
1534 static GList	*gkrellmrc_border_list,
1535 				*gkrellmrc_integer_list,
1536 				*gkrellmrc_string_list;
1537 
1538 
1539 static GkrellmBorder	zero_border;
1540 
1541 
1542 gboolean
1543 gkrellm_set_gkrellmrc_piximage_border(gchar *image_name,
1544 			GkrellmPiximage *image, GkrellmStyle *style)
1545 	{
1546 	static GkrellmBorder	b;
1547 	GList					*list;
1548 	gchar					name[64], border_string[32];
1549 	gchar					*s, *r;
1550 
1551 	if (style)
1552 		style->border = zero_border;
1553 	if (!image || !image_name)
1554 		return FALSE;
1555 	for (list = gkrellmrc_border_list; list; list = list->next)
1556 		{
1557 		s = list->data;
1558 		if ((r = strchr(s, '=')) != NULL)
1559 			*r = ' ';
1560 		sscanf(s, "%63s %31s", name, border_string);
1561 		if (!strcmp(name, image_name))
1562 			{
1563 			set_border(&b, border_string);
1564 			gkrellm_set_piximage_border(image, &b);
1565 			if (style)
1566 				style->border = b;
1567 			return TRUE;
1568 			}
1569 		}
1570 	return FALSE;
1571 	}
1572 
1573 gboolean
1574 gkrellm_get_gkrellmrc_piximage_border(gchar *image_name, GkrellmPiximage *image,
1575 				GkrellmBorder *border)
1576 	{
1577 	GkrellmBorder	b;
1578 	GList			*list;
1579 	gchar			name[64], border_string[32];
1580 	gchar			*s, *r;
1581 
1582 	if (!image || !image_name)
1583 		return FALSE;
1584 	for (list = gkrellmrc_border_list; list; list = list->next)
1585 		{
1586 		s = list->data;
1587 		if ((r = strchr(s, '=')) != NULL)
1588 			*r = ' ';
1589 		sscanf(s, "%63s %31s", name, border_string);
1590 		if (!strcmp(name, image_name))
1591 			{
1592 			set_border(&b, border_string);
1593 			gkrellm_set_piximage_border(image, &b);
1594 			if (border)
1595 				*border = b;
1596 			return TRUE;
1597 			}
1598 		}
1599 	return FALSE;
1600 	}
1601 
1602 gboolean
1603 gkrellm_get_gkrellmrc_integer(gchar *int_name, gint *result)
1604 	{
1605 	GList		*list;
1606 	gchar		name[64], string[64];
1607 	gchar		*s, *r;
1608 	gboolean	found = FALSE;
1609 
1610 	if (!int_name || !result)
1611 		return FALSE;
1612 	for (list = gkrellmrc_integer_list; list; list = list->next)
1613 		{
1614 		s = list->data;
1615 		if ((r = strchr(s, '=')) != NULL)
1616 			*r = ' ';
1617 		sscanf(s, "%63s %63s", name, string);
1618 		if (!strcmp(name, int_name) && sscanf(string, "%d", result) == 1)
1619 			found = TRUE;
1620 		}
1621 	return found;
1622 	}
1623 
1624 gchar *
1625 gkrellm_get_gkrellmrc_string(gchar *string_name)
1626 	{
1627 	GList	*list;
1628 	gchar	name[64], string[CFG_BUFSIZE];
1629 	gchar	*s, *r;
1630 
1631 	if (!string_name)
1632 		return NULL;
1633 	for (list = gkrellmrc_string_list; list; list = list->next)
1634 		{
1635 		s = list->data;
1636 		if ((r = strchr(s, '=')) != NULL)
1637 			*r = ' ';
1638 		sscanf(s, "%63s %[^\n]", name, string);
1639 		if (!strcmp(name, string_name))
1640 			{
1641 			if ((s = gkrellm_cut_quoted_string(string, NULL)) != NULL)
1642 				return g_strdup(s);
1643 			break;
1644 			}
1645 		}
1646 	return NULL;
1647 	}
1648 
1649 static gboolean
1650 parse_monitor_config_keyword(GkrellmMonitor *mon_only, gchar *line)
1651 	{
1652 	GList			*list;
1653 	GkrellmMonitor	*mon;
1654 	gchar			*keyword;
1655 	gboolean		result = FALSE;
1656 
1657 	keyword = gkrellm_dup_token(&line, NULL);
1658 	if (!*keyword)
1659 		{
1660 		g_free(keyword);
1661 		return FALSE;
1662 		}
1663 
1664 	for (list = gkrellm_monitor_list; list; list = list->next)
1665 		{
1666 		mon = (GkrellmMonitor *) list->data;
1667 		if (mon_only && mon != mon_only)
1668 			continue;
1669 		if (!mon->config_keyword || strcmp(mon->config_keyword, keyword))
1670 			continue;
1671 		while (*line == ' ' || *line == '\t')
1672 			++line;
1673 		if (*line && mon->load_user_config && mon->privat->enabled)
1674 			{
1675 			gkrellm_record_state(LOAD_CONFIG, mon);
1676 			(*(mon->load_user_config))(line);
1677 			gkrellm_record_state(INTERNAL, NULL);
1678 			}
1679 		result = TRUE;
1680 		}
1681 	g_free(keyword);
1682 	return result;
1683 	}
1684 
1685 static gboolean
1686 parse_gkrellmrc_keyword(gchar *line)
1687 	{
1688 	GkrellmMonitor	*mon;
1689 	gchar			buf[CFG_BUFSIZE];
1690 	gchar			*s, *arg;
1691 
1692 	strncpy(buf, line, CFG_BUFSIZE);	/* strtok() is destructive */
1693 	buf[CFG_BUFSIZE - 1] = '\0';
1694 	s = strtok(buf, " \t:=\n");
1695 	if (!s || *s == '#' || *s == '\n' || *s == '\0')
1696 		return FALSE;
1697 	arg = strtok(NULL, "\n");
1698 
1699 	if (strncmp(line, "Style", 5) == 0)	/* StyleChart ... */
1700 		assign_gkrellmrc_style(line, s, arg);
1701 	else if (   !strncmp(s, "spacer_top_height", 17)
1702 			 || !strncmp(s, "spacer_bottom_height", 20)
1703 			)
1704 		assign_gkrellmrc_spacer(line, s, arg);
1705 	else if (!strcmp(s, "cap_images_off"))
1706 		{
1707 		mon = gkrellm_monitor_from_style_name(arg);
1708 		if (mon)
1709 			mon->privat->cap_images_off = TRUE;
1710 		}
1711 	else if (!strcmp(s, "spacer_overlap_off"))
1712 		{
1713 		mon = gkrellm_monitor_from_style_name(arg);
1714 		if (mon)
1715 			mon->privat->spacer_overlap_off = TRUE;
1716 		}
1717 	else if (strcmp(s, "set_image_border") == 0)
1718 		gkrellmrc_border_list = g_list_append(gkrellmrc_border_list,
1719 				g_strdup(arg));
1720 	else if (strcmp(s, "set_integer") == 0)
1721 		gkrellmrc_integer_list = g_list_append(gkrellmrc_integer_list,
1722 				g_strdup(arg));
1723 	else if (strcmp(s, "set_string") == 0)
1724 		gkrellmrc_string_list = g_list_prepend(gkrellmrc_string_list,
1725 				g_strdup(arg));
1726 	else
1727 		return FALSE;
1728 	return TRUE;
1729 	}
1730 
1731 static gboolean
1732 parse_config_line(gchar *line, struct _config *cf, gint size)
1733 	{
1734 	struct _config	*conf;
1735 	gchar			*s, *ss;
1736 	gint			i, val, len;
1737 
1738 	s = line;
1739 	while (*s && *s != ' ' && *s != '\t' && *s != '=')
1740 		++s;
1741 	if (s == line || !*s || *s == '\n')
1742 		return FALSE;
1743 	for (i = 0; i < size; ++i)
1744 		{
1745 		conf = cf + i;
1746 		len = strlen(conf->option);
1747 		if (strncmp(conf->option, line, len) || len != s - line)
1748 			continue;
1749 		while (*s == ' ' || *s == '\t' || *s == '=')
1750 			++s;
1751 		if (!*s || *s == '\n')
1752 			{
1753 			g_warning(_("Incomplete config line:\n    %s\n"), line);
1754 			continue;
1755 			}
1756 		if (conf->value)
1757 			{
1758 			if (isdigit((unsigned char)*s) || *s == '-')
1759 				val = atoi(s);
1760 			else if (!strcmp(s, "on") || !strcmp(s, "true"))
1761 				val = 1;
1762 			else
1763 				val = 0;
1764 			if (conf->minimum > -100 && val < conf->minimum)
1765 				val = conf->minimum;
1766 			*(conf->value) = val;
1767 			}
1768 		else if (conf->arg)
1769 			{
1770 			if (*s == '"')
1771 				{
1772 				++s;
1773 				ss = strchr(s, '"');
1774 				}
1775 			else
1776 				{
1777 				ss = s;
1778 				while (*ss && *ss != ' ' && *ss != '\t' && *ss != '\n')
1779 					++ss;
1780 				if (*ss == '\0')
1781 					ss = NULL;
1782 				}
1783 			if (ss)
1784 				*(conf->arg) = g_strndup(s, ss - s);
1785 			else
1786 				*(conf->arg) = g_strdup(s);
1787 			}
1788 		return TRUE;
1789 		}
1790 	return FALSE;
1791 	}
1792 
1793 static void
1794 parse_gkrellmrc_line(gchar *line)
1795 	{
1796 	if (!parse_gkrellmrc_keyword(line))
1797 		parse_config_line(line, &theme_config[0],
1798 					sizeof(theme_config) / sizeof (struct _config));
1799 
1800 	}
1801 
1802 static void
1803 clear_style_list(GList *list, GList *name_list)
1804 	{
1805 	GkrellmStyle	*style;
1806 
1807 	for ( ; list; list = list->next, name_list = name_list->next)
1808 		{
1809 		style = (GkrellmStyle *) list->data;
1810 		if (style)
1811 			memset(style, 0, sizeof(GkrellmStyle));
1812 		}
1813 	}
1814 
1815 static gchar	*base_theme[]	=
1816 	{
1817 	"StyleChart *.border = 0,0,0,0",
1818 	"StyleChart *.margins = 0,0,0,0",
1819 	"StyleChart *.font = normal_font",
1820 	"StyleChart *.alt_font = small_font",
1821 	"StyleChart *.textcolor = #efd097 #000000 shadow",
1822 	"StyleChart *.alt_textcolor = #c0c0c0 #181818 shadow",
1823 
1824 	"StylePanel *.border = 0,0,2,1",
1825 	"StylePanel *.font = normal_font",
1826 	"StylePanel *.alt_font = normal_font",
1827 	"StylePanel *.textcolor = white #000000 shadow",
1828 	"StylePanel *.alt_textcolor = #d8e0c8 #000000 shadow",
1829 	"StylePanel *.label_position = 50",
1830 	"StylePanel *.margins = 1,1,2,2",
1831 	"StylePanel *.krell_yoff = 0",
1832 	"StylePanel *.krell_yoff_not_scalable = false",
1833 	"StylePanel *.krell_x_hot = 3",
1834 	"StylePanel *.krell_depth = 4",
1835 	"StylePanel *.krell_expand = 0",
1836 	"StylePanel *.krell_ema_period = 3",
1837 
1838 	"StyleMeter *.border = 3,3,3,2",
1839 	"StyleMeter *.font = normal_font",
1840 	"StyleMeter *.alt_font = small_font",
1841 	"StyleMeter *.textcolor = #ffeac4 #000000 shadow",
1842 	"StyleMeter *.alt_textcolor = wheat #000000 shadow",
1843 	"StyleMeter *.label_position = 50",
1844 	"StyleMeter *.margins = 2,2,2,2",
1845 	"StyleMeter *.krell_yoff = 1",
1846 	"StyleMeter *.krell_yoff_not_scalable = false",
1847 	"StyleMeter *.krell_expand = 0",
1848 	"StyleMeter *.krell_x_hot = -1",
1849 	"StyleMeter *.krell_depth = 1",
1850 	"StyleMeter *.krell_ema_period = 1",
1851 
1852 	/* These have an override effect */
1853 	"StyleMeter apm.bottom_margin = 2",
1854 	"StyleMeter mail.krell_depth = 15",
1855 	"StyleMeter mail.krell_yoff = 0",
1856 	"StyleMeter mail.krell_x_hot = -1",
1857 	"StyleMeter mail.krell_expand = 0",
1858 	"StyleMeter mail.label_position = 70",
1859 	"StyleChart net.alt_font = small_font",
1860 	};
1861 
1862 
1863 static void
1864 gkrellm_init_theme(void)
1865 	{
1866 	GkrellmMonitor	*mon;
1867 	GList			*list;
1868 	GkrellmStyle	*style;
1869 	gint			i, style_id;
1870 
1871 	_GK.theme_n_alternatives = 0;
1872 	_GK.frame_top_height = 0;		/* use image height. */
1873 	_GK.frame_bottom_height = 0;	/* use image height. */
1874 	_GK.frame_left_width = 0;
1875 	_GK.frame_right_width = 0;
1876 
1877 	_GK.frame_left_chart_overlap = 0;
1878 	_GK.frame_right_chart_overlap = 0;
1879 	_GK.frame_left_panel_overlap = 0;
1880 	_GK.frame_right_panel_overlap = 0;
1881 	_GK.frame_left_spacer_overlap = 0;
1882 	_GK.frame_right_spacer_overlap = 0;
1883 
1884 	_GK.chart_height_min = 5;
1885 	_GK.chart_height_max = 200;
1886 	_GK.chart_width_ref = 60;
1887 	_GK.chart_text_no_fill = FALSE;
1888 	_GK.bg_separator_height = 2;
1889 	_GK.allow_scaling = FALSE;
1890 	_GK.bg_grid_mode = GRID_MODE_NORMAL;
1891 	_GK.spacer_top_height_chart = 3;
1892 	_GK.spacer_bottom_height_chart = 3;
1893 	_GK.spacer_top_height_meter = 3;
1894 	_GK.spacer_bottom_height_meter = 3;
1895 
1896 	_GK.decal_mail_frames = 18;
1897 	_GK.decal_mail_delay = 1;
1898 
1899 	_GK.decal_alarm_frames = 10;
1900 	_GK.decal_warn_frames = 10;
1901 
1902 	_GK.rx_led_x = 3;
1903 	_GK.rx_led_y = 6;
1904 	_GK.tx_led_x = -3;
1905 	_GK.tx_led_y = 6;
1906 
1907 	gkrellm_dup_string(&_GK.large_font_string,
1908 				gkrellm_get_large_font_string());
1909 	gkrellm_dup_string(&_GK.normal_font_string,
1910 				gkrellm_get_normal_font_string());
1911 	gkrellm_dup_string(&_GK.small_font_string,
1912 				gkrellm_get_small_font_string());
1913 
1914 	gkrellm_dup_string(&_GK.chart_in_color, "#10d3d3");
1915 	gkrellm_dup_string(&_GK.chart_in_color_grid, "#00a3a3");
1916 	gkrellm_dup_string(&_GK.chart_out_color, "#f4ac4a");
1917 	gkrellm_dup_string(&_GK.chart_out_color_grid, "#b47c20");
1918 
1919 
1920 	/* Setup the default styles.  Substyles may be set in gkrellmrc.  If
1921 	|  they are not, then they will be set to point to the default after
1922 	|  parsing the gkrellmrc file.
1923 	*/
1924 	clear_style_list(_GK.chart_style_list, _GK.chart_name_list);
1925 	clear_style_list(_GK.panel_style_list, _GK.chart_name_list);
1926 	clear_style_list(_GK.meter_style_list, _GK.meter_name_list);
1927 	gkrellm_free_glist_and_data(&_GK.custom_name_list);
1928 	gkrellm_free_glist_and_data(&_GK.custom_style_list);
1929 
1930 	for (i = 0; i < sizeof(base_theme) / sizeof(gchar *); ++i)
1931 		parse_gkrellmrc_line(base_theme[i]);
1932 
1933 	/* Allow themes to transition to using top/bottom margins. */
1934 	_GK.use_top_bottom_margins = FALSE;
1935 
1936 	/* I set some base theme parameters with no override.  The idea is if
1937 	|  a theme does not bother to set anything, these will remain in effect,
1938 	|  but if the theme sets any "*" settings, they can wipe these out.
1939 	|  This is probably a mistake, I am contributing to theme author
1940 	|  laziness and should move these to the default theme.
1941 	*/
1942 	style_id = gkrellm_lookup_meter_style_id(BATTERY_STYLE_NAME);
1943 	assign_meter_style(style_id, "3,3,2,2", GKRELLMSTYLE_BORDER, 0);
1944 
1945 	style_id = gkrellm_lookup_meter_style_id(CAL_STYLE_NAME);
1946 	assign_meter_style(style_id,  "small_font", GKRELLMSTYLE_TEXTFONT_A, 0);
1947 	assign_meter_style(style_id,  "large_font", GKRELLMSTYLE_TEXTFONT_B, 0);
1948 
1949 	style_id = gkrellm_lookup_meter_style_id(CLOCK_STYLE_NAME);
1950 	assign_meter_style(style_id,"large_font", GKRELLMSTYLE_TEXTFONT_A, 0);
1951 
1952 	style_id = gkrellm_lookup_meter_style_id(FS_STYLE_NAME);
1953 	assign_meter_style(style_id, "0", GKRELLMSTYLE_LABEL_POSITION, 0);
1954 
1955 	if (_GK.krell_slider_style)
1956 		g_free(_GK.krell_slider_style);
1957 	_GK.krell_slider_style = gkrellm_style_new0();
1958 	style = (GkrellmStyle *) _GK.meter_style_list->data;
1959 	*_GK.krell_slider_style = *style;
1960 
1961 	if (_GK.krell_mini_style)
1962 		g_free(_GK.krell_mini_style);
1963 	_GK.krell_mini_style = gkrellm_style_new0();
1964 	*_GK.krell_mini_style = *style;
1965 
1966 	gkrellm_dup_string(&frame_top_border, "0,0,0,0");
1967 	gkrellm_dup_string(&frame_bottom_border, "0,0,0,0");
1968 	gkrellm_dup_string(&frame_left_border, "0,0,0,0");
1969 	gkrellm_dup_string(&frame_right_border, "0,0,0,0");
1970 	gkrellm_dup_string(&button_panel_border, "2,2,2,2");
1971 	gkrellm_dup_string(&button_meter_border, "2,2,2,2");
1972 	gkrellm_dup_string(&frame_left_chart_border, "0,0,0,0");
1973 	gkrellm_dup_string(&frame_right_chart_border, "0,0,0,0");
1974 	gkrellm_dup_string(&frame_left_panel_border, "0,0,0,0");
1975 	gkrellm_dup_string(&frame_right_panel_border, "0,0,0,0");
1976 	gkrellm_dup_string(&spacer_top_border, "0,0,0,0");
1977 	gkrellm_dup_string(&spacer_bottom_border, "0,0,0,0");
1978 
1979 	krell_slider_x_hot = -1;
1980 	krell_slider_depth = 6;
1981 	gkrellm_dup_string(&krell_slider_expand, "none");
1982 
1983 	gkrellm_free_glist_and_data(&gkrellmrc_border_list);
1984 	gkrellm_free_glist_and_data(&gkrellmrc_integer_list);
1985 	gkrellm_free_glist_and_data(&gkrellmrc_string_list);
1986 	for (list = gkrellm_monitor_list; list; list = list->next)
1987 		{
1988 		mon = (GkrellmMonitor *) list->data;
1989 		mon->privat->top_spacer.height = -1;
1990 		mon->privat->bottom_spacer.height = -1;
1991 		mon->privat->cap_images_off = FALSE;
1992 		mon->privat->spacer_overlap_off = FALSE;
1993 		}
1994 	}
1995 
1996 static gchar	*default_theme[]	=
1997 	{
1998 	"frame_left_border = 0,0,42,16",
1999 	"frame_right_border = 0,0,42,16",
2000 
2001 	"StyleChart *.textcolor = #efd097 #000000 shadow",
2002 	"StyleChart *.alt_textcolor = #a8e4e2 #000000 shadow",
2003 
2004 	"StylePanel *.margins = 1,1,2,1",
2005 	"StylePanel *.textcolor = white #000000 shadow",
2006 	"StylePanel *.alt_textcolor = #60fff0 #000000 shadow",
2007 
2008 	"StylePanel cpu.margins = 0,0,2,1",
2009 
2010 	"StyleMeter *.border = 4,4,3,2",
2011 	"StyleMeter *.margins = 2,2,2,2",
2012 	"StyleMeter *.krell_yoff = 1",
2013 
2014 	"StyleMeter *.textcolor = #c8e4e2 #000000 shadow",
2015 	"StyleMeter *.alt_textcolor = #e8e4d2 #000000 shadow",
2016 
2017 	"StyleMeter cal.textcolor = #c8e4e2 #000000 shadow",
2018 
2019 	"StyleMeter clock.textcolor = #e8e4d2 #000000 shadow",
2020 	"StyleMeter clock.alt_textcolor = #c8e4e2 #000000 shadow",
2021 
2022 	"StyleMeter sensors.textcolor = #60fff0 #000000 shadow",
2023 	"StyleMeter sensors.alt_textcolor = #c8e4e2 #000000 shadow",
2024 
2025 	"StyleMeter fs.border = 4,4,3,1",
2026 	"StyleMeter fs.bottom_margin = 1",
2027 	"StyleMeter fs.label_position = 0",
2028 	"StyleMeter fs.alt_font = normal_font",
2029 
2030 	"StyleMeter fs.alt_textcolor = #c8e4e2 #000000 shadow",
2031 	"StyleMeter mem.alt_textcolor = #c8e4e2 #000000 shadow",
2032 	"StyleMeter swap.alt_textcolor = #c8e4e2 #000000 shadow",
2033 
2034 
2035 	"StyleMeter host.textcolor = #c8d4d2 #000000 shadow",
2036 	"StyleMeter host.top_margin = 1",
2037 	"StyleMeter host.bottom_margin = 1",
2038 
2039 	"StyleMeter mail.alt_textcolor = #ffc0c0 #000000 shadow",
2040 
2041 	"StyleMeter mem.krell_yoff = 0",
2042 	"StyleMeter mem.alt_font = normal_font",
2043 	"StyleMeter mem.top_margin = 2",
2044 	"StyleMeter mem.bottom_margin = 0",
2045 	"StyleMeter swap.top_margin = 2",
2046 	"StyleMeter swap.bottom_margin = 1",
2047 
2048 	"StyleMeter swap.krell_yoff = -2",		/* Bottom justify */
2049 	"StyleMeter swap.alt_font = normal_font",
2050 
2051 	"StyleMeter sensors.alt_textcolor = #d8e0c8 #000000 shadow",
2052 	"StyleMeter sensors.top_margin = 3",
2053 	"StyleMeter sensors.bottom_margin = 3",
2054 	"set_image_border sensors_bg_volt 1,1,1,1",
2055 
2056 	"StyleMeter timer.textcolor = #e8e4d2 #000000 shadow",
2057 	"StyleMeter timer.alt_textcolor = #c8e4e2 #000000 shadow",
2058 	"StyleMeter timer.margins = 1,1,1,2",
2059 	"set_image_border timer_bg_timer 1,1,2,2",
2060 
2061 	"StyleMeter uptime.textcolor = #e8e4d2 #000000 shadow",
2062 	"StyleMeter uptime.border = 3,3,2,2",
2063 	"StyleMeter uptime.bottom_margin = 1",
2064 
2065 
2066 	/* ---- plugins ---- */
2067 
2068 	"spacer_top_height pmu 3",
2069 	"spacer_bottom_height pmu 2",
2070 
2071 	/* GKrellMMS scroll bar panel */
2072 	"spacer_top_height gkrellmms 3",
2073 	"spacer_bottom_height gkrellmms 3",
2074 	"set_image_border gkrellmms_bg_scroll 3,3,2,2",
2075 	"set_integer gkrellmms_scroll_margin 3",
2076 	"set_integer gkrellmms_scroll_top_margin 2",
2077 	"set_integer gkrellmms_scroll_bottom_margin 1",
2078 	/* GKrellMMS control (button) bar panel*/
2079 	"StyleMeter gkrellmms.alt_textcolor = black #dcdccc shadow",
2080 	"StyleMeter gkrellmms.margins = 2,2,2,0",
2081 	"StyleMeter gkrellmms.border = 2,2,4,0",
2082 	"StyleMeter gkrellmms.krell_yoff = 0",
2083 	"StyleMeter gkrellmms.krell_x_hot = 59",
2084 	"StyleMeter gkrellmms.krell_expand = left",
2085 	"StyleMeter gkrellmms.krell_left_margin = 3",
2086 	"StyleMeter gkrellmms.krell_right_margin = 2",
2087 
2088 	"set_string gkrellmms_play_button_position \"-27 4 0 0 c\"",
2089 	"set_string gkrellmms_prev_button_position \"-25 20 0 0 c\"",
2090 	"set_string gkrellmms_stop_button_position \"-13 21 0 0 c\"",
2091 	"set_string gkrellmms_next_button_position \"9 20 0 0 c\"",
2092 
2093 	"set_string gkrellmms_eject_button_position \"17 12 0 0 c\"",
2094 	"set_string gkrellmms_led_position \"7 7 c\"",
2095 	"set_string gkrellmms_label_position \"-25 7 c\"",
2096 
2097 
2098 
2099 	/* Timers panels */
2100 	"spacer_top_height timers 3",
2101 	"spacer_bottom_height timers 3",
2102 	"StyleMeter timers.border = 6,6,2,2",
2103 	"StyleMeter timers.font = large_font",
2104 	"StyleMeter timers.textcolor = #d8e4d2 #000000 shadow",
2105 	"StyleMeter timers.alt_textcolor = #c8e4e2 #000000 shadow",
2106 
2107 	/* All volume panels */
2108 	"spacer_top_height volume 3",
2109 	"spacer_bottom_height volume 3",
2110 	"StyleMeter volume.label_position = 0",
2111 	"StyleMeter volume.border = 26,3,0,0",
2112 	"StyleMeter volume.top_margin = 1",
2113 	"StyleMeter volume.bottom_margin = 0",
2114 	};
2115 
2116 static gchar	*default_theme_1[]	=
2117 	{
2118 	"StyleChart *.textcolor #efd097 #000000 shadow",
2119 	"StyleChart *.alt_textcolor #e4e4e2 #000000 shadow",
2120 	"StylePanel *.textcolor white #000000 shadow",
2121 	"StylePanel *.alt_textcolor #f0f080 #000000 shadow",
2122 	"StyleMeter *.textcolor = #f2f4d8 #000000 shadow",
2123 	"StyleMeter *.alt_textcolor #e8e4b2 #000000 shadow",
2124 	"StyleMeter cal.textcolor #f2f4d8 #000000 shadow",
2125 	"StyleMeter clock.textcolor #e8e4b2 #000000 shadow",
2126 	"StyleMeter clock.alt_textcolor #f2f4d8 #000000 shadow",
2127 	"StyleMeter fs.alt_textcolor = #f2f4d8 #000000 shadow",
2128 	"StyleMeter host.textcolor #b8c4c2 #000000 shadow",
2129 	"StyleMeter mail.alt_textcolor #e0c0c0 #000000 shadow",
2130 	"StyleMeter mem.alt_textcolor = #f2f4d8 #000000 shadow",
2131 	"StyleMeter swap.alt_textcolor = #f2f4d8 #000000 shadow",
2132 	"StyleMeter sensors.textcolor = #f0f080 #000000 shadow",
2133 	"StyleMeter sensors.alt_textcolor = #f2f4d8 #000000 shadow",
2134 	"StyleMeter timer.textcolor #e8e4b2 #000000 shadow",
2135 	"StyleMeter timer.alt_textcolor #f2f4d8 #000000 shadow",
2136 	"StyleMeter uptime.textcolor #e8e4b2 #000000 shadow",
2137 	"StyleMeter gkrellmms.alt_textcolor = black #dcdccc shadow",
2138 	"StyleMeter timers.textcolor #d2d8c0 #000000 shadow",
2139 	"StyleMeter timers.alt_textcolor = #f2f4d8 #000000 shadow",
2140 	};
2141 
2142 static gchar	*default_theme_2[]	=
2143 	{
2144 	"StyleChart *.textcolor #f8b080 #000000 shadow",
2145 	"StyleChart *.alt_textcolor #f0e8f0 #000000 shadow",
2146 	"StylePanel *.textcolor white #000000 shadow",
2147 	"StylePanel *.alt_textcolor #f0d0f0 #000000 shadow",
2148 	"StyleMeter *.textcolor = #f0e8f0 #000000 shadow",
2149 	"StyleMeter *.alt_textcolor #f0c0a0 #000000 shadow",
2150 	"StyleMeter cal.textcolor #f0e8f0 #000000 shadow",
2151 	"StyleMeter clock.textcolor #f0c0a0 #000000 shadow",
2152 	"StyleMeter clock.alt_textcolor #f0e8f0 #000000 shadow",
2153 	"StyleMeter fs.alt_textcolor = #f0e8f0 #000000 shadow",
2154 	"StyleMeter host.textcolor #b8c4c2 #000000 shadow",
2155 	"StyleMeter mail.alt_textcolor #e0c0c0 #000000 shadow",
2156 	"StyleMeter mem.alt_textcolor = #f0e8f0 #000000 shadow",
2157 	"StyleMeter swap.alt_textcolor = #f0e8f0 #000000 shadow",
2158 	"StyleMeter sensors.textcolor = #f0d0f0 #000000 shadow",
2159 	"StyleMeter sensors.alt_textcolor = #f0e8f0 #000000 shadow",
2160 	"StyleMeter timer.textcolor #f0c0a0 #000000 shadow",
2161 	"StyleMeter timer.alt_textcolor #f0e8f0 #000000 shadow",
2162 	"StyleMeter uptime.textcolor #f0c0a0 #000000 shadow",
2163 	"StyleMeter gkrellmms.alt_textcolor = black #dcdccc shadow",
2164 	"StyleMeter timers.textcolor #f0d0b0 #000000 shadow",
2165 	"StyleMeter timers.alt_textcolor = #f0e8f0 #000000 shadow",
2166 	};
2167 
2168 static void
2169 default_theme_config(void)
2170 	{
2171 	gint	i;
2172 
2173 	_GK.theme_n_alternatives = 5;
2174 	if (_GK.theme_alternative > _GK.theme_n_alternatives)
2175 		_GK.theme_alternative = _GK.theme_n_alternatives;
2176 
2177 	for (i = 0; i < sizeof(default_theme) / sizeof(gchar *); ++i)
2178 		parse_gkrellmrc_line(default_theme[i]);
2179 
2180 	if (_GK.theme_alternative == 1 || _GK.theme_alternative == 4)
2181 		{
2182 		for (i = 0; i < sizeof(default_theme_1) / sizeof(gchar *); ++i)
2183 			parse_gkrellmrc_line(default_theme_1[i]);
2184 		}
2185 	if (_GK.theme_alternative == 2 || _GK.theme_alternative == 5)
2186 		{
2187 		for (i = 0; i < sizeof(default_theme_2) / sizeof(gchar *); ++i)
2188 			parse_gkrellmrc_line(default_theme_2[i]);
2189 		}
2190 	if (_GK.theme_alternative > 2)
2191 		parse_gkrellmrc_keyword("StyleChart *.transparency = 1");
2192 	}
2193 
2194 static void
2195 parse_gkrellmrc(gint alternative)
2196 	{
2197 	FILE	*f;
2198 	gchar	*path, *s, *ss, lbuf[16];
2199 	gchar	buf[CFG_BUFSIZE];
2200 
2201 	lbuf[0] = '\0';
2202 	if (alternative > 0)
2203 		snprintf(lbuf, sizeof(lbuf), "_%d", alternative);
2204 	path = g_strdup_printf("%s/%s%s", _GK.theme_path, GKRELLMRC, lbuf);
2205 	if ((f = g_fopen(path, "r")) != NULL)
2206 		{
2207 		while (fgets(buf, sizeof(buf), f))
2208 			{
2209 			s = buf;
2210 			while (*s == ' ' || *s == '\t')
2211 				++s;
2212 			if (!*s || *s == '\n' || *s == '#')
2213 				continue;
2214 			ss = strchr(s, '\n');
2215 			if (ss)
2216 				*ss = '\0';
2217 			parse_gkrellmrc_line(s);
2218 			}
2219 		fclose(f);
2220 		}
2221 	g_free(path);
2222 	}
2223 
2224 gboolean
2225 gkrellm_using_default_theme(void)
2226 	{
2227 	return (*(_GK.theme_path) == '\0') ? TRUE : FALSE;
2228 	}
2229 
2230 void
2231 gkrellm_theme_config(void)
2232 	{
2233 	gkrellm_load_theme_config();
2234 	gkrellm_init_theme();
2235 
2236 	if (gkrellm_using_default_theme())
2237 		default_theme_config();
2238 	else
2239 		{
2240 		parse_gkrellmrc(0);
2241 		if (_GK.theme_alternative > _GK.theme_n_alternatives)
2242 			_GK.theme_alternative = _GK.theme_n_alternatives;
2243 		if (_GK.theme_alternative > 0)
2244 			parse_gkrellmrc(_GK.theme_alternative);
2245 		}
2246 	cleanup_gkrellmrc();
2247 	gkrellm_set_theme_alternatives_label();
2248 
2249 	/* Warn theme developers!
2250 	*/
2251 	if (!_GK.use_top_bottom_margins && _GK.command_line_theme)
2252 		{
2253 		g_warning("Top and bottom meter/panel margins are not set.\n" \
2254 				" Do not depend on borders!\n");
2255 		}
2256 	}
2257 
2258 
2259 /* --------------------------------------------------------------*/
2260 
2261 struct	_config	user_config[] =
2262 	{
2263 	{"enable_hostname",	&_GK.enable_hostname,		NULL,	0  },
2264 	{"hostname_short",	&_GK.hostname_short,		NULL,	0  },
2265 	{"enable_sysname",	&_GK.enable_system_name,	NULL,	0  },
2266 	{"mbmon_port",		&_GK.mbmon_port,			NULL,	0  },
2267 
2268 #if !defined(WIN32)
2269 	{"sticky_state",	&_GK.sticky_state,		NULL, 	0 },
2270 	{"dock_type",		&_GK.dock_type,			NULL,	0 },
2271 	{"decorated",		&_GK.decorated,			NULL,	0 },
2272 	{"skip_taskbar",	&_GK.state_skip_taskbar, NULL,	0 },
2273 	{"skip_pager",		&_GK.state_skip_pager,	NULL,	0 },
2274 	{"above",			&_GK.state_above,	NULL,	0 },
2275 	{"below",			&_GK.state_below,	NULL,	0 },
2276 #else
2277 	{"on_top",			&_GK.on_top,		NULL,		0  },
2278 #endif
2279 
2280 	{"track_gtk_theme_name", &_GK.track_gtk_theme_name, NULL,	0  },
2281 	{"default_track_theme", NULL, &_GK.default_track_theme,	0  },
2282 	{"save_position",	&_GK.save_position,		NULL,	0  },
2283 
2284 	{"chart_width",		&_GK.chart_width,		NULL,	0  },
2285 
2286 	{"update_HZ",		&_GK.update_HZ,			NULL,	0  },
2287 	{"allow_multiple_instances", &_GK.allow_multiple_instances,	NULL,	0  },
2288 	};
2289 
2290   /* The user_config is read twice.  Early to load _GK config values and then
2291   |  again when when building gkrellm for the first time to load monitor user
2292   |  config values.  It's also read at plugin enables in case existing configs.
2293   */
2294 void
2295 gkrellm_load_user_config(GkrellmMonitor *mon_only, gboolean monitor_values)
2296 	{
2297 	FILE	*f;
2298 	gchar	*s, *ss, *config;
2299 	gchar	buf[CFG_BUFSIZE];
2300 
2301 	if (!monitor_values)
2302 		{
2303 		_GK.enable_hostname = TRUE;
2304 		_GK.hostname_short = FALSE;
2305 		_GK.enable_system_name = FALSE;
2306 		_GK.chart_width = 100;
2307 		_GK.update_HZ = 10;
2308 		_GK.theme_scale = 100;
2309 		_GK.float_factor = 1.0;
2310 		_GK.default_track_theme = g_strdup("Default");
2311 		}
2312 	config = gkrellm_make_config_file_name(gkrellm_homedir(),
2313 				GKRELLM_USER_CONFIG);
2314 	f = g_fopen(config, "r");
2315 	g_free(config);
2316 
2317 	if (f)
2318 		{
2319 		while (fgets(buf, sizeof(buf), f))
2320 			{
2321 			s = buf;
2322 			while (*s == ' ' || *s == '\t')
2323 				++s;
2324 			if (!*s || *s == '\n' || *s == '#')
2325 				continue;
2326 			ss = strchr(s, '\n');
2327 			if (ss)
2328 				*ss = '\0';
2329 			if (!strncmp(s, "float_factor ", 13))
2330 				sscanf(s + 13, "%f", &_GK.float_factor);
2331 			else if (monitor_values)
2332 				parse_monitor_config_keyword(mon_only, s);
2333 			else
2334 				parse_config_line(s, &user_config[0],
2335 						sizeof(user_config) / sizeof (struct _config));
2336 			}
2337 		fclose(f);
2338 		}
2339 	if (_GK.chart_width < CHART_WIDTH_MIN)
2340 		_GK.chart_width = CHART_WIDTH_MIN;
2341 	if (_GK.chart_width > CHART_WIDTH_MAX)
2342 		_GK.chart_width = CHART_WIDTH_MAX;
2343 	}
2344 
2345 void
2346 gkrellm_config_modified(void)
2347 	{
2348 	if (_GK.no_config)
2349 		return;
2350 	_GK.config_modified = TRUE;
2351 	}
2352 
2353 gchar *
2354 gkrellm_make_data_file_name(gchar *subdir, gchar *name)
2355 	{
2356 	gchar	*dir, *path, *s;
2357 
2358 	dir = gkrellm_make_config_file_name(NULL, GKRELLM_DATA_DIR);
2359 	gkrellm_make_home_subdir(dir, &path);
2360 	if (subdir)
2361 		{
2362 		g_free(path);
2363 		s = g_strconcat(dir, G_DIR_SEPARATOR_S, subdir, NULL);
2364 		g_free(dir);
2365 		dir = s;
2366 		gkrellm_make_home_subdir(dir, &path);
2367 		}
2368 	g_free(dir);
2369 	if (name)
2370 		{
2371 		s = g_strconcat(path, G_DIR_SEPARATOR_S, name, NULL);
2372 		g_free(path);
2373 		path = s;
2374 		}
2375 	return path;
2376 	}
2377 
2378 gchar *
2379 gkrellm_make_config_file_name(gchar *dir, gchar *config)
2380 	{
2381 	gchar	hostname[256],
2382 			*fname, *d,
2383 			*s		= NULL;
2384 
2385 	if (_GK.client_mode)
2386 		{
2387 		s = g_strdup_printf("%s_S-%s", config, _GK.server_hostname);
2388 		if (_GK.config_suffix)
2389 			{
2390 			d = g_strconcat(s, "-", _GK.config_suffix, NULL);
2391 			g_free(s);
2392 			s = d;
2393 			}
2394 		}
2395 	else if (   _GK.config_suffix
2396 			 || _GK.found_host_config || _GK.force_host_config
2397 			)
2398 		{
2399 		if (_GK.config_suffix)
2400 			s = _GK.config_suffix;
2401 		else if (!gethostname(hostname, 256))
2402 			s = hostname;
2403 		if (s)
2404 			s = g_strdup_printf("%s-%s", config, s);
2405 		}
2406 	if (!s)
2407 		s = g_strdup(config);
2408 
2409 	if (dir)
2410 		{
2411 		fname = g_strdup_printf("%s/%s", dir, s);
2412 		g_free(s);
2413 		}
2414 	else
2415 		fname = s;
2416 	return fname;
2417 	}
2418 
2419 void
2420 gkrellm_save_user_config(void)
2421 	{
2422 	FILE			*f, *ff;
2423 	GList			*list;
2424 	GkrellmMonitor	*mon;
2425 	gint			i;
2426 	mode_t			mode;
2427 	gchar			*config, *config_new;
2428 
2429 	if (_GK.demo || _GK.no_config)
2430 		return;
2431 	config = gkrellm_make_config_file_name(gkrellm_homedir(),
2432 					GKRELLM_USER_CONFIG);
2433 	config_new = g_strconcat(config, ".new", NULL);
2434 
2435 	f = g_fopen(config_new, "w");
2436 	if (f == NULL)
2437 		{
2438 		g_warning(_("Cannot open config file %s for writing.\n"), config_new);
2439 		g_free(config_new);
2440 		g_free(config);
2441 		return;
2442 		}
2443 
2444 	fprintf(f,
2445 		"### GKrellM user config.  Auto written, do not edit (usually) ###\n");
2446 	fprintf(f, "### Version %d.%d.%d ###\n",
2447 			GKRELLM_VERSION_MAJOR, GKRELLM_VERSION_MINOR, GKRELLM_VERSION_REV);
2448 	for (i = 0; i < sizeof(user_config) / sizeof(struct _config); ++i)
2449 		{
2450 		if (user_config[i].value)
2451 			fprintf(f, "%s %d\n", user_config[i].option,
2452 							*(user_config[i].value));
2453 		else if (user_config[i].arg)	/* Put quotes around strings */
2454 			fprintf(f, "%s \"%s\"\n",user_config[i].option,
2455 						*(user_config[i].arg));
2456 		}
2457 	fprintf(f, "float_factor %.0f\n", GKRELLM_FLOAT_FACTOR);
2458 	for (list = gkrellm_monitor_list; list; list = list->next)
2459 		{
2460 		mon = (GkrellmMonitor *) list->data;
2461 		if (mon->save_user_config && mon->privat->enabled)
2462 			{
2463 			gkrellm_record_state(SAVE_CONFIG, mon);
2464 			(*(mon->save_user_config))(f);
2465 			gkrellm_record_state(INTERNAL, NULL);
2466 			}
2467 		}
2468 
2469 	if (   !_GK.config_clean
2470 	    && (ff = g_fopen(config, "r")) != NULL
2471 	   )
2472 		{
2473 		gchar		buf[CFG_BUFSIZE], *keyword, *ch, tmp;
2474 		struct _config
2475 					*cf,
2476 					*const end = user_config +
2477 								sizeof user_config / sizeof *user_config;
2478 
2479 		while (fgets(buf, sizeof(buf), ff))
2480 			{
2481 			for (ch = buf; *ch == ' ' || *ch == '\t'; ++ch)
2482 				;
2483 			if (*ch == '\n' || *ch == '#' || !*ch)
2484 				continue;
2485 			keyword = ch;
2486 			while (*ch && *ch != ' ' && *ch != '\t' && *ch != '\n')
2487 				++ch;
2488 			tmp = *ch;
2489 			*ch = 0;
2490 
2491 			for (list = gkrellm_monitor_list; list; list = list->next)
2492 				{
2493 				mon = (GkrellmMonitor *) list->data;
2494 				if (   mon->save_user_config && mon->privat->enabled
2495 				    && mon->config_keyword
2496 				    && !strcmp(mon->config_keyword, keyword)
2497 				   )
2498 					break;
2499 				}
2500 			if (list)
2501 				continue;
2502 
2503 			cf = user_config;
2504 			while (cf != end && strcmp(cf->option, keyword))
2505 				++cf;
2506 			if (cf != end)
2507 				continue;
2508 			if (!strcmp("float_factor", keyword))
2509 				continue;
2510 
2511 			*ch = tmp;
2512 			fputs(buf, f);
2513 			}
2514 		fclose(ff);
2515 		}
2516 	fclose(f);
2517 #if defined(WIN32)
2518 	/* windows rename() does not allow overwriting existing files! */
2519 	g_unlink(config);
2520 #endif
2521 	i = g_rename(config_new, config);
2522 	if (i != 0)
2523 		{
2524 		g_warning("Cannot rename new config file %s to %s.\n", config_new, config);
2525 		g_free(config);
2526 		g_free(config_new);
2527 		// NOTE: _GK.config_modified will stay true because saving failed
2528 		return;
2529 		}
2530 
2531 #if defined (S_IRUSR)
2532 	mode = (S_IRUSR | S_IWUSR);
2533 #elif defined (S_IREAD)
2534 	mode = (S_IREAD | S_IWRITE);
2535 #else
2536 	mode = 0600;
2537 #endif
2538 	g_chmod(config, mode);
2539 
2540 	g_free(config);
2541 	g_free(config_new);
2542 
2543 	_GK.config_modified = FALSE;
2544 	}
2545