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 #include "gkrellm-sysdeps.h"
37 
38 #include <gmodule.h>
39 
40 #if defined(WIN32)
41 	#include "win32-plugin.h"
42 #endif
43 
44 /* ======================================================================= */
45 /* Plugin interface to GKrellM.
46 */
47 
48 gchar *
gkrellm_get_hostname(void)49 gkrellm_get_hostname(void)
50 	{
51 	gchar	*hostname;
52 
53 	if (_GK.client_mode)
54 		hostname = _GK.server_hostname;
55 	else
56 		hostname = gkrellm_sys_get_host_name();
57 	return hostname;
58 	}
59 
60 gchar *
gkrellm_get_theme_path(void)61 gkrellm_get_theme_path(void)
62 	{
63 	return _GK.theme_path;
64 	}
65 
66 GkrellmKrell *
gkrellm_krell_new0(void)67 gkrellm_krell_new0(void)
68 	{
69 	GkrellmKrell *k;
70 
71 	k = g_new0(GkrellmKrell, 1);
72 	return k;
73 	}
74 
75 GkrellmDecal *
gkrellm_decal_new0(void)76 gkrellm_decal_new0(void)
77 	{
78 	GkrellmDecal	*d;
79 
80 	d = g_new0(GkrellmDecal, 1);
81 	return d;
82 	}
83 
84 
85 GkrellmLabel *
gkrellm_label_new0(void)86 gkrellm_label_new0(void)
87 	{
88 	GkrellmLabel *l;
89 
90 	l = g_new0(GkrellmLabel, 1);
91 	return l;
92 	}
93 
94 
95 GkrellmStyle *
gkrellm_style_new0(void)96 gkrellm_style_new0(void)
97 	{
98 	GkrellmStyle	*s;
99 
100 	s = g_new0(GkrellmStyle, 1);
101 	return s;
102 	}
103 
104 GkrellmStyle *
gkrellm_copy_style(GkrellmStyle * style)105 gkrellm_copy_style(GkrellmStyle *style)
106 	{
107 	GkrellmStyle *s = NULL;
108 
109 	if (style)
110 		{
111 		s = gkrellm_style_new0();
112 		*s = *style;
113 		}
114 	return s;
115 	}
116 
117 void
gkrellm_copy_style_values(GkrellmStyle * dst,GkrellmStyle * src)118 gkrellm_copy_style_values(GkrellmStyle *dst, GkrellmStyle *src)
119 	{
120 	if (src && dst)
121 		*dst = *src;
122 	}
123 
124 GkrellmTextstyle *
gkrellm_textstyle_new0(void)125 gkrellm_textstyle_new0(void)
126 	{
127 	GkrellmTextstyle	*t;
128 
129 	t = g_new0(GkrellmTextstyle, 1);
130 	return t;
131 	}
132 
133 GkrellmTextstyle *
gkrellm_copy_textstyle(GkrellmTextstyle * ts)134 gkrellm_copy_textstyle(GkrellmTextstyle *ts)
135 	{
136 	GkrellmTextstyle *t	= gkrellm_textstyle_new0();
137 
138 	*t = *ts;
139 	return t;
140 	}
141 
142 GkrellmChart *
gkrellm_chart_new0(void)143 gkrellm_chart_new0(void)
144 	{
145 	GkrellmChart	*c;
146 
147 	c = g_new0(GkrellmChart, 1);
148 	return c;
149 	}
150 
151 GkrellmChartconfig *
gkrellm_chartconfig_new0(void)152 gkrellm_chartconfig_new0(void)
153 	{
154 	GkrellmChartconfig	*config;
155 
156 	config = g_new0(GkrellmChartconfig, 1);
157 	return config;
158 	}
159 
160 GkrellmPanel *
gkrellm_panel_new0(void)161 gkrellm_panel_new0(void)
162 	{
163 	GkrellmPanel *p;
164 
165 	p = g_new0(GkrellmPanel, 1);
166 	p->label = gkrellm_label_new0();
167 	return p;
168 	}
169 
170 
171 static GkrellmStyle *
get_style_from_list(GList * list,gint n)172 get_style_from_list(GList *list, gint n)
173 	{
174 	GList			*l;
175 	GkrellmStyle	*style;
176 
177 	l = g_list_nth(list, n);
178 	if (l == NULL || l->data == NULL)
179 		l = list;
180 	if (l->data == NULL)
181 		{
182 		g_warning("Warning: NULL style returned %d\n", n);
183 		abort();
184 		}
185 	style = (GkrellmStyle *) l->data;
186 	return style;
187 	}
188 
189 GkrellmStyle *
gkrellm_meter_style(gint n)190 gkrellm_meter_style(gint n)
191 	{
192 	return get_style_from_list(_GK.meter_style_list, n);
193 	}
194 
195 GkrellmStyle *
gkrellm_panel_style(gint n)196 gkrellm_panel_style(gint n)
197 	{
198 	return get_style_from_list(_GK.panel_style_list, n);
199 	}
200 
201 GkrellmStyle *
gkrellm_chart_style(gint n)202 gkrellm_chart_style(gint n)
203 	{
204 	return get_style_from_list(_GK.chart_style_list, n);
205 	}
206 
207 static GkrellmStyle *
get_style_from_list_by_name(GList * name_list,GList * style_list,gchar * name)208 get_style_from_list_by_name(GList *name_list, GList *style_list, gchar *name)
209 	{
210 	GList	*list;
211 	gchar	*p, buf[128];
212 	gint	n;
213 
214 	strncpy(buf, name, sizeof(buf));
215 	buf[sizeof(buf) - 1] = '\0';
216 	if (   (p = strchr(buf, '.')) != NULL
217 		&& (n = gkrellm_string_position_in_list(_GK.custom_name_list, name)) >= 0
218 	   )
219 		list = _GK.custom_style_list;
220 	else
221 		{
222 		if (p)
223 			*p = '\0';
224 		if ((n = gkrellm_string_position_in_list(name_list, buf)) < 0)
225 			n = 0;
226 		list = style_list;
227 		}
228 	return get_style_from_list(list, n);
229 	}
230 
231 GkrellmStyle *
gkrellm_meter_style_by_name(gchar * name)232 gkrellm_meter_style_by_name(gchar *name)
233 	{
234 	return get_style_from_list_by_name(_GK.meter_name_list,
235 				_GK.meter_style_list, name);
236 	}
237 
238 GkrellmStyle *
gkrellm_panel_style_by_name(gchar * name)239 gkrellm_panel_style_by_name(gchar *name)
240 	{
241 	return get_style_from_list_by_name(_GK.chart_name_list,
242 				_GK.panel_style_list, name);
243 	}
244 
245 GkrellmStyle *
gkrellm_chart_style_by_name(gchar * name)246 gkrellm_chart_style_by_name(gchar *name)
247 	{
248 	return get_style_from_list_by_name(_GK.chart_name_list,
249 				_GK.chart_style_list, name);
250 	}
251 
252 gint
gkrellm_lookup_chart_style_id(gchar * name)253 gkrellm_lookup_chart_style_id(gchar *name)
254 	{
255 	GList	*list;
256 	gint	i;
257 
258 	for (list = _GK.chart_name_list, i = 0; list; list = list->next, ++i)
259 		if (name && !strcmp(name, (gchar *)list->data))
260 			return i;
261 	return 0;
262 	}
263 
264 gint
gkrellm_lookup_meter_style_id(gchar * name)265 gkrellm_lookup_meter_style_id(gchar *name)
266 	{
267 	GList	*list;
268 	gint	i;
269 
270 	for (list = _GK.meter_name_list, i = 0; list; list = list->next, ++i)
271 		if (name && !strcmp(name, (gchar *)list->data))
272 			return i;
273 	return 0;
274 	}
275 
276 static GkrellmPiximage *
get_piximage_from_list(GList * list,gint n)277 get_piximage_from_list(GList *list, gint n)
278 	{
279 	GList	*l;
280 
281 	l = g_list_nth(list, n);
282 	if (l == NULL || l->data == NULL)
283 		l = list;
284 	if (l->data == NULL)
285 		{
286 		g_warning("Warning: NULL image returned %d\n", n);
287 		abort();
288 		}
289 	return (GkrellmPiximage *) l->data;
290 	}
291 
292 GkrellmPiximage *
gkrellm_bg_chart_piximage(gint n)293 gkrellm_bg_chart_piximage(gint n)
294 	{
295 	return get_piximage_from_list(_GK.bg_chart_piximage_list, n);
296 	}
297 
298 GkrellmPiximage *
gkrellm_bg_grid_piximage(gint n)299 gkrellm_bg_grid_piximage(gint n)
300 	{
301 	return get_piximage_from_list(_GK.bg_grid_piximage_list, n);
302 	}
303 
304 GkrellmPiximage *
gkrellm_bg_panel_piximage(gint n)305 gkrellm_bg_panel_piximage(gint n)
306 	{
307 	return get_piximage_from_list(_GK.bg_panel_piximage_list, n);
308 	}
309 
310 GkrellmPiximage *
gkrellm_bg_meter_piximage(gint n)311 gkrellm_bg_meter_piximage(gint n)
312 	{
313 	return get_piximage_from_list(_GK.bg_meter_piximage_list, n);
314 	}
315 
316 GkrellmPiximage *
gkrellm_krell_panel_piximage(gint n)317 gkrellm_krell_panel_piximage(gint n)
318 	{
319 	return get_piximage_from_list(_GK.krell_panel_piximage_list, n);
320 	}
321 
322 GkrellmPiximage *
gkrellm_krell_meter_piximage(gint n)323 gkrellm_krell_meter_piximage(gint n)
324 	{
325 	return get_piximage_from_list(_GK.krell_meter_piximage_list, n);
326 	}
327 
328 void
gkrellm_get_decal_alarm_piximage(GkrellmPiximage ** im,gint * frames)329 gkrellm_get_decal_alarm_piximage(GkrellmPiximage **im, gint *frames)
330 	{
331 	if (im)
332 		*im = _GK.decal_alarm_piximage;
333 	if (frames)
334 		*frames = _GK.decal_alarm_frames;
335 	}
336 
337 void
gkrellm_get_decal_warn_piximage(GkrellmPiximage ** im,gint * frames)338 gkrellm_get_decal_warn_piximage(GkrellmPiximage **im, gint *frames)
339 	{
340 	if (im)
341 		*im = _GK.decal_warn_piximage;
342 	if (frames)
343 		*frames = _GK.decal_warn_frames;
344 	}
345 
346 
347 void
gkrellm_monitor_height_adjust(gint h)348 gkrellm_monitor_height_adjust(gint h)
349 	{
350 	_GK.monitor_height += h;
351 	}
352 
353 GdkPixmap *
gkrellm_decal_misc_pixmap(void)354 gkrellm_decal_misc_pixmap(void)
355 	{
356 	return _GK.decal_misc_pixmap;
357 	}
358 
359 GdkBitmap *
gkrellm_decal_misc_mask(void)360 gkrellm_decal_misc_mask(void)
361 	{
362 	return _GK.decal_misc_mask;
363 	}
364 
365 GdkPixmap **
gkrellm_data_in_pixmap(void)366 gkrellm_data_in_pixmap(void)
367 	{
368 	return &_GK.data_in_pixmap;
369 	}
370 
371 GdkPixmap *
gkrellm_data_in_grid_pixmap(void)372 gkrellm_data_in_grid_pixmap(void)
373 	{
374 	return _GK.data_in_grid_pixmap;
375 	}
376 
377 GdkPixmap **
gkrellm_data_out_pixmap(void)378 gkrellm_data_out_pixmap(void)
379 	{
380 	return &_GK.data_out_pixmap;
381 	}
382 
383 GdkPixmap *
gkrellm_data_out_grid_pixmap(void)384 gkrellm_data_out_grid_pixmap(void)
385 	{
386 	return _GK.data_out_grid_pixmap;
387 	}
388 
389 GkrellmPiximage *
gkrellm_krell_slider_piximage(void)390 gkrellm_krell_slider_piximage(void)
391 	{
392 	return _GK.krell_slider_piximage;
393 	}
394 
395 GkrellmStyle *
gkrellm_krell_slider_style(void)396 gkrellm_krell_slider_style(void)
397 	{
398 	return _GK.krell_slider_style;
399 	}
400 
401 GkrellmPiximage *
gkrellm_krell_mini_piximage(void)402 gkrellm_krell_mini_piximage(void)
403 	{
404 	return _GK.krell_mini_piximage;
405 	}
406 
407 GkrellmStyle *
gkrellm_krell_mini_style(void)408 gkrellm_krell_mini_style(void)
409 	{
410 	return _GK.krell_mini_style;
411 	}
412 
413 GdkGC *
gkrellm_draw_GC(gint n)414 gkrellm_draw_GC(gint n)
415 	{
416 	GdkGC	*gc;
417 
418 	if (n == 0)
419 		return _GK.draw_stencil_GC;
420 	else if (n == 1)
421 		gc = _GK.draw1_GC;
422 	else if (n == 2)
423 		gc = _GK.draw2_GC;
424 	else
425 		gc = _GK.draw3_GC;
426 	return gc;
427 	}
428 
429 GdkGC *
gkrellm_bit_GC(gint n)430 gkrellm_bit_GC(gint n)
431 	{
432 	if (n == 0)
433 		return _GK.bit0_GC;
434 	else
435 		return _GK.bit1_GC;
436 	}
437 
438 GkrellmTextstyle *
gkrellm_chart_textstyle(gint n)439 gkrellm_chart_textstyle(gint n)
440 	{
441 	GkrellmStyle		*style;
442 	GkrellmTextstyle	*ts;
443 
444 	style = get_style_from_list(_GK.chart_style_list, n);
445 	ts	= &style->label_tsA;
446 	ts->font = *(ts->font_seed);
447 	return ts;
448 	}
449 
450 GkrellmTextstyle *
gkrellm_panel_textstyle(gint n)451 gkrellm_panel_textstyle(gint n)
452 	{
453 	GkrellmStyle		*style;
454 	GkrellmTextstyle 	*ts;
455 
456 	style = get_style_from_list(_GK.panel_style_list, n);
457 	ts	= &style->label_tsA;
458 	ts->font = *(ts->font_seed);
459 	return ts;
460 	}
461 
462 GkrellmTextstyle *
gkrellm_meter_textstyle(gint n)463 gkrellm_meter_textstyle(gint n)
464 	{
465 	GkrellmStyle		*style;
466 	GkrellmTextstyle 	*ts;
467 
468 	style = get_style_from_list(_GK.meter_style_list, n);
469 	ts	= &style->label_tsA;
470 	ts->font = *(ts->font_seed);
471 	return ts;
472 	}
473 
474 
475 GkrellmTextstyle *
gkrellm_chart_alt_textstyle(gint n)476 gkrellm_chart_alt_textstyle(gint n)
477 	{
478 	GkrellmStyle		*style;
479 	GkrellmTextstyle 	*ts;
480 
481 	style = get_style_from_list(_GK.chart_style_list, n);
482 	ts	= &style->label_tsB;
483 	ts->font = *(ts->font_seed);
484 	return ts;
485 	}
486 
487 GkrellmTextstyle *
gkrellm_panel_alt_textstyle(gint n)488 gkrellm_panel_alt_textstyle(gint n)
489 	{
490 	GkrellmStyle		*style;
491 	GkrellmTextstyle 	*ts;
492 
493 	style = get_style_from_list(_GK.panel_style_list, n);
494 	ts	= &style->label_tsB;
495 	ts->font = *(ts->font_seed);
496 	return ts;
497 	}
498 
499 GkrellmTextstyle *
gkrellm_meter_alt_textstyle(gint n)500 gkrellm_meter_alt_textstyle(gint n)
501 	{
502 	GkrellmStyle		*style;
503 	GkrellmTextstyle 	*ts;
504 
505 	style = get_style_from_list(_GK.meter_style_list, n);
506 	ts	= &style->label_tsB;
507 	ts->font = *(ts->font_seed);
508 	return ts;
509 	}
510 
511 PangoFontDescription *
gkrellm_default_font(gint n)512 gkrellm_default_font(gint n)
513 	{
514 	if (n == 0)
515 		return _GK.small_font;
516 	else if (n == 1)
517 		return _GK.normal_font;
518 	else
519 		return _GK.large_font;
520 	}
521 
522 GdkColor *
gkrellm_white_color(void)523 gkrellm_white_color(void)
524 	{
525 	return &_GK.white_color;
526 	}
527 
528 GdkColor *
gkrellm_black_color(void)529 gkrellm_black_color(void)
530 	{
531 	return &_GK.background_color;
532 	}
533 
534 GdkColor *
gkrellm_in_color(void)535 gkrellm_in_color(void)
536 	{
537 	return &_GK.in_color;
538 	}
539 
540 GdkColor *
gkrellm_out_color(void)541 gkrellm_out_color(void)
542 	{
543 	return &_GK.out_color;
544 	}
545 
546 gboolean
gkrellm_demo_mode(void)547 gkrellm_demo_mode(void)
548 	{
549 	return _GK.demo;
550 	}
551 
552 gint
gkrellm_update_HZ(void)553 gkrellm_update_HZ(void)
554 	{
555 	return _GK.update_HZ;
556 	}
557 
558 gint
gkrellm_chart_width(void)559 gkrellm_chart_width(void)
560 	{
561 	return _GK.chart_width;
562 	}
563 
564 void
gkrellm_allow_scaling(gboolean * allow,gint * width_ref)565 gkrellm_allow_scaling(gboolean *allow, gint *width_ref)
566 	{
567 	if (allow)
568 		*allow = _GK.allow_scaling;
569 	if (width_ref)
570 		*width_ref = _GK.chart_width_ref;
571 	}
572 
573 gint
gkrellm_plugin_debug(void)574 gkrellm_plugin_debug(void)
575 	{
576 	return _GK.debug;
577 	}
578 
579 /* ======================================================================= */
580 typedef struct
581 	{
582 	GkrellmMonitor	*mon_plugin,
583 					*mon_target;
584 	gchar			key;
585 	gchar			*(*func)(gchar key, gchar *which);
586 	gint			id;
587 	}
588 	ExportLabel;
589 
590 static GList	*export_label_list;
591 
592 gint
gkrellm_plugin_export_label(GkrellmMonitor * mon_plugin,gchar * mon_name,gchar key,gchar * (* func)(gchar key,gchar * which))593 gkrellm_plugin_export_label(GkrellmMonitor *mon_plugin, gchar *mon_name,
594 			gchar key, gchar *(*func)(gchar key, gchar *which))
595 	{
596 	GkrellmMonitor	*mon;
597 	ExportLabel		*el;
598 	GList			*list;
599 	static gint		id;
600 
601 	if (!mon_name || !mon_plugin || !func || !key)
602 		return -1;
603 	for (list = gkrellm_monitor_list; list; list = list->next)
604 		{
605 		mon = (GkrellmMonitor *) list->data;
606 		if (mon->name && (_GK.debug_level & DEBUG_PLUGIN))
607 			g_print("    %s %s\n", mon->name, mon_name);
608 		if (mon->name && !strcmp(mon->name, mon_name))
609 			break;
610 		}
611 	if (!list)
612 		return -1;
613 
614 	el = g_new0(ExportLabel, 1);
615 	export_label_list = g_list_append(export_label_list, el);
616 	el->mon_target = mon;
617 	el->mon_plugin = mon_plugin;
618 	el->key = key;
619 	el->func = func;
620 	el->id = ++id;
621 
622 	return id;
623 	}
624 
625 void
gkrellm_plugin_cancel_label(GkrellmMonitor * mon_plugin,gint id)626 gkrellm_plugin_cancel_label(GkrellmMonitor *mon_plugin, gint id)
627 	{
628 	GList		*list;
629 	ExportLabel	*el;
630 
631 	if (!mon_plugin || id < 1)
632 		return;
633 	for (list = export_label_list; list; list = list->next)
634 		{
635 		el = (ExportLabel *) list->data;
636 		if (el->id == id)
637 			{
638 			export_label_list = g_list_remove(export_label_list, el);
639 			g_free(el);
640 			break;
641 			}
642 		}
643 	}
644 
645 gchar *
gkrellm_plugin_get_exported_label(GkrellmMonitor * mon,gchar key,gchar * which)646 gkrellm_plugin_get_exported_label(GkrellmMonitor *mon, gchar key, gchar *which)
647 	{
648 	GList		*list;
649 	ExportLabel	*el;
650 	gchar		*result = NULL;
651 
652 	for (list = export_label_list; list; list = list->next)
653 		{
654 		el = (ExportLabel *) list->data;
655 		if (   el->mon_target == mon && el->key == key
656 			&& el->mon_plugin->privat->enabled && el->func
657 		   )
658 			{
659 			result = (*el->func)(key, which);
660 			break;
661 			}
662 		}
663 	return result;
664 	}
665 
666 /* ======================================================================= */
667 
668 static GkrellmMonitor		*place_plugin;
669 
670 enum
671 	{
672 	NAME_COLUMN,
673 	ENABLE_COLUMN,
674 	MON_COLUMN,
675 	N_COLUMNS
676 	};
677 
678 static GtkTreeView		*treeview;
679 static GtkTreeRowReference *row_reference;
680 
681 static GtkWidget	*place_label,
682 					*place_button,
683 					*after_button,
684 					*before_button,
685 					*gravity_spin_button,
686 					*builtin_button[N_BUILTIN_MONITORS];
687 
688 static GList		*plugins_list,
689 					*plugins_enable_list,
690 					*plugins_place_list;
691 
692 static gboolean		plugin_enable_list_modified,
693 					plugin_placement_modified;
694 
695 gchar				*plugin_install_log;
696 
697 
698 GkrellmMonitor *
gkrellm_monitor_from_id(gint id)699 gkrellm_monitor_from_id(gint id)
700 	{
701 	GList			*list;
702 	GkrellmMonitor	*mon;
703 
704 	for (list = gkrellm_monitor_list; list; list = list->next)
705 		{
706 		mon = (GkrellmMonitor *) list->data;
707 		if (mon->id == id)
708 			return mon;
709 		}
710 	return NULL;
711 	}
712 
713 GkrellmMonitor *
lookup_monitor_from_name(gchar * name)714 lookup_monitor_from_name(gchar *name)
715 	{
716 	GkrellmMonitor	*mon;
717 	GList			*list;
718 
719 	for (list = gkrellm_monitor_list; list; list = list->next)
720 		{
721 		mon = (GkrellmMonitor *) list->data;
722 		if (!mon->name || mon->id < 0)
723 			continue;
724 		if (!strcmp(name, mon->name))
725 			return mon;
726 		}
727 	return NULL;
728 	}
729 
730 GkrellmMonitor *
gkrellm_monitor_from_style_name(gchar * style_name)731 gkrellm_monitor_from_style_name(gchar *style_name)
732 	{
733 	GkrellmMonitor	*mon;
734 	GList			*list;
735 
736 	for (list = gkrellm_monitor_list; list; list = list->next)
737 		{
738 		mon = (GkrellmMonitor *) list->data;
739 		if (!mon->privat || !mon->privat->style_name)
740 			continue;
741 		if (!strcmp(style_name, mon->privat->style_name))
742 			return mon;
743 		}
744 	return NULL;
745 	}
746 
747 static void
plugin_log(gchar * string1,...)748 plugin_log(gchar *string1, ...)
749 	{
750 	va_list		args;
751 	gchar		*s, *old_log;
752 
753 	if (!string1)
754 		return;
755 	va_start(args, string1);
756 	s = string1;
757 	while (s)
758 		{
759 		old_log = plugin_install_log;
760 		if (plugin_install_log)
761 			plugin_install_log = g_strconcat(plugin_install_log, s, NULL);
762 		else
763 			plugin_install_log = g_strconcat(s, NULL);
764 		g_free(old_log);
765 		s = va_arg(args, gchar *);
766 		}
767 	va_end(args);
768 	}
769 
770 static gboolean
user_placement(GkrellmMonitor * plugin)771 user_placement(GkrellmMonitor *plugin)
772 	{
773 	GList			*list;
774 	GkrellmMonitor	*mon;
775 	gchar			*line, *s, *plugin_name, *mon_name;
776 	gint			n, after, gravity;
777 
778 	if (!plugin->name)
779 		return FALSE;
780 	for (list = plugins_place_list; list; list = list->next)
781 		{
782 		line = g_strconcat((gchar *) list->data, NULL);
783 		plugin_name = gkrellm_cut_quoted_string(line, &s);
784 		mon_name = gkrellm_cut_quoted_string(s, &s);
785 		n = sscanf(s, "%d %d", &after, &gravity);
786 		if (n == 2)
787 			{
788 			if (after)
789 				gravity = 0;
790 			if (   !strcmp(plugin_name, plugin->name)
791 				&& (mon = lookup_monitor_from_name(mon_name)) != NULL
792 			   )
793 				{
794 				plugin->privat->insert_before_id = mon->id;
795 				plugin->privat->gravity = gravity;
796 				plugin->privat->insert_after = after;
797 				g_free(line);
798 				return TRUE;
799 				}
800 			}
801 		g_free(line);
802 		}
803 	return FALSE;
804 	}
805 
806 void
gkrellm_place_plugin(GList ** monitor_list,GkrellmMonitor * plugin)807 gkrellm_place_plugin(GList **monitor_list, GkrellmMonitor *plugin)
808 	{
809 	GkrellmMonitor	*mon;
810 	GList			*list, *plist;
811 	gint			n, gravity, after_flag;
812 	gchar			buf[120];
813 
814 	if (plugin->create_monitor && !plugin->privat->main_vbox)
815 		{
816 		plugin->privat->main_vbox = gtk_vbox_new(FALSE, 0);
817 		plugin->privat->top_spacer.vbox = gtk_vbox_new(FALSE, 0);
818 		plugin->privat->vbox = gtk_vbox_new(FALSE, 0);
819 		plugin->privat->bottom_spacer.vbox = gtk_vbox_new(FALSE, 0);
820 		}
821 	for (plist = NULL, list = *monitor_list; list; list = list->next)
822 		{
823 		mon = (GkrellmMonitor *) list->data;
824 
825 		/* Save list position as plugins are encountered so we can later
826 		|  walk through them looking at gravity.
827 		*/
828 		if (MONITOR_ID(mon) == MON_PLUGIN && plist == NULL)
829 			plist = list;
830 		if (MONITOR_ID(mon) == plugin->privat->insert_before_id)
831 			{
832 			after_flag = plugin->privat->insert_after;
833 			gravity = plugin->privat->gravity;
834 			snprintf(buf, sizeof(buf), _("\t%s: placement is %s %s  G:%d\n"),
835 					plugin->name,
836 					after_flag ? _("after") : _("before"), mon->name, gravity);
837 			plugin_log(buf, NULL);
838 			if (after_flag)
839 				{
840 				if ((n = g_list_position(*monitor_list, list)) < 0)
841 					n = 0;
842 				*monitor_list = g_list_insert(*monitor_list, plugin, n + 1);
843 				}
844 			else
845 				{
846 				/* If there are plugins already above this builtin, then place
847 				|  based on gravity.  Insert above the first plugin found that
848 				|  has greater gravity than the current placing plugin.
849 				*/
850 				if (plist)
851 					{
852 					for ( ; plist != list; plist = plist->next)
853 						{
854 						mon = (GkrellmMonitor *) plist->data;
855 						if (mon->privat->gravity > gravity)
856 							break;
857 						}
858 					list = plist;
859 					}
860 				if ((n = g_list_position(*monitor_list, list)) < 0)
861 					n = 0;
862 				*monitor_list = g_list_insert(*monitor_list, plugin, n);
863 				}
864 			return;
865 			}
866 		else if (MONITOR_ID(mon) != MON_PLUGIN)
867 			plist = NULL;
868 		}
869 	if (plugin->privat->insert_before_id != MON_UPTIME)
870 		{
871 		plugin->privat->insert_before_id = MON_UPTIME;
872 		gkrellm_place_plugin(monitor_list, plugin);
873 		return;
874 		}
875 	*monitor_list = g_list_append(*monitor_list, plugin);
876 	}
877 
878 GkrellmMonitor *
install_plugin(gchar * plugin_name)879 install_plugin(gchar *plugin_name)
880 	{
881 	GList					*list;
882 	GModule					*module;
883 	GkrellmMonitor			*m, *mm;
884 	GkrellmMonitor			*(*init_plugin)();
885 	gchar					buf[256];
886 	static GkrellmMonitor	mon_tmp;
887 
888 	if (!g_module_supported())
889 		return NULL;
890 	module = g_module_open(plugin_name, 0);
891 	plugin_log(plugin_name, "\n", NULL);
892 
893 	if (! module)
894 		{
895 		snprintf(buf, sizeof(buf), _("\tError: %s\n"), g_module_error());
896 		plugin_log(buf, NULL);
897 		return NULL;
898 		}
899 	if (!g_module_symbol(module, "gkrellm_init_plugin",
900 				(gpointer) &init_plugin))
901 		{
902 		snprintf(buf, sizeof(buf), _("\tError: %s\n"), g_module_error());
903 		plugin_log(buf, NULL);
904 		g_module_close(module);
905 		return NULL;
906 		}
907 	_GK.no_messages = TRUE;		/* Enforce policy */
908 
909 	mon_tmp.name = g_strdup(plugin_name);
910 	gkrellm_record_state(INIT_MONITOR, &mon_tmp);
911 
912 #if defined(WIN32)
913 	{
914 		win32_plugin_callbacks ** plugin_cb = NULL;
915 
916 		if (!g_module_symbol(module, "callbacks", (gpointer) &plugin_cb))
917 		{
918 			snprintf(buf, sizeof(buf), _("\tError: %s\n"), g_module_error());
919 			plugin_log(buf, NULL);
920 			g_module_close(module);
921 			return NULL;
922 		}
923 		*plugin_cb = &gkrellm_callbacks;
924 	}
925 #endif
926 
927 	m = (*init_plugin)();
928 
929 	_GK.no_messages = FALSE;
930 
931 	g_free(mon_tmp.name);
932 	mon_tmp.name = NULL;
933 	gkrellm_record_state(INTERNAL, NULL);
934 
935 	if (m == NULL)
936 		{
937 		plugin_log(_("\tOoops! plugin returned NULL, aborting\n"), NULL);
938 		g_module_close(module);
939 		return NULL;
940 		}
941 	for (list = gkrellm_monitor_list; list; list = list->next)
942 		{
943 		mm = (GkrellmMonitor *) list->data;
944 		if (   !mm->privat || !mm->privat->style_name
945 			|| !m->privat  || !m->privat->style_name
946 			|| strcmp(mm->privat->style_name, m->privat->style_name)
947 		   )
948 			continue;
949 		plugin_log(_("\tWarning: style name \""), m->privat->style_name,
950 			_("\" already used by:\n\t\t"), mm->path, "\n", NULL);
951 		}
952 	for (list = gkrellm_monitor_list; list; list = list->next)
953 		{
954 		mm = (GkrellmMonitor *) list->data;
955 		if (   !mm->config_keyword || !m->config_keyword
956 			|| strcmp(mm->config_keyword, m->config_keyword)
957 		   )
958 			continue;
959 		plugin_log(_("\tWarning: config keyword \""), m->config_keyword,
960 			_("\" already used by:\n\t\t"), mm->path, "\n", NULL);
961 		}
962 	m->handle = module;
963 	m->path = plugin_name;
964 	if (!m->name)
965 		m->name = g_path_get_basename(m->path);
966 	if (m->privat == NULL)		/* Won't be null if style was added */
967 		m->privat = g_new0(GkrellmMonprivate, 1);
968 	m->privat->enabled = TRUE;
969 
970 	/* Enforce some id fields.
971 	*/
972 	m->id &= ~(MON_ID_MASK | MON_CONFIG_MASK);
973 	m->id |= MON_PLUGIN;
974 	if (PLUGIN_INSERT_BEFORE_ID(m) >= N_BUILTIN_MONITORS)
975 		m->insert_before_id = MON_UPTIME;
976 	if (!user_placement(m))
977 		{
978 		m->privat->insert_before_id = PLUGIN_INSERT_BEFORE_ID(m);
979 		m->privat->gravity = PLUGIN_GRAVITY(m);
980 		m->privat->insert_after = PLUGIN_INSERT_AFTER(m);
981 		}
982 	gkrellm_place_plugin(&gkrellm_monitor_list, m);
983 	return m;
984 	}
985 
986 pid_t
gkrellm_get_pid(void)987 gkrellm_get_pid(void)
988 	{
989 	return getpid();
990 	}
991 
992 void
gkrellm_disable_plugin_connect(GkrellmMonitor * mon,void (* cb_func)())993 gkrellm_disable_plugin_connect(GkrellmMonitor *mon, void (*cb_func)())
994 	{
995 	if (!mon || !mon->privat || !cb_func)
996 		return;
997 	mon->privat->cb_disable_plugin = cb_func;
998 	}
999 
1000 static void
disable_plugin(GkrellmMonitor * plugin)1001 disable_plugin(GkrellmMonitor *plugin)
1002 	{
1003 	GkrellmMonprivate	*mp = plugin->privat;
1004 
1005 	if (!mp->enabled)
1006 		return;
1007 	if (mp->top_spacer.image)
1008 		gtk_widget_destroy(mp->top_spacer.image);
1009 	mp->top_spacer.image = NULL;
1010 	if (mp->bottom_spacer.image)
1011 		gtk_widget_destroy(mp->bottom_spacer.image);
1012 	mp->bottom_spacer.image = NULL;
1013 
1014 	/* It is not safe to destroy a plugin widget tree.
1015 	|  They have already done one time first_create stuff.
1016 	*/
1017 	gtk_widget_hide(mp->vbox);
1018 	gtk_widget_hide(mp->main_vbox);
1019 	mp->enabled = FALSE;
1020 	if (mp->cb_disable_plugin)
1021 		(*mp->cb_disable_plugin)();
1022 	gkrellm_build();
1023 	gkrellm_remove_plugin_config_page(plugin);
1024 	plugin_enable_list_modified = TRUE;
1025 	}
1026 
1027 static void
enable_plugin(GkrellmMonitor * plugin)1028 enable_plugin(GkrellmMonitor *plugin)
1029 	{
1030 	GkrellmMonprivate	*mp = plugin->privat;
1031 
1032 	if (mp->enabled)
1033 		return;
1034 	gtk_widget_show(mp->vbox);
1035 	gtk_widget_show(mp->main_vbox);
1036 	mp->enabled = TRUE;
1037 	gkrellm_load_user_config(plugin, TRUE);
1038 	gkrellm_build();
1039 	gkrellm_add_plugin_config_page(plugin);
1040 	plugin_enable_list_modified = TRUE;
1041 	}
1042 
1043 static void
load_plugins_placement_file(void)1044 load_plugins_placement_file(void)
1045 	{
1046 	FILE	*f;
1047 	gchar	*path, *s, buf[256];
1048 
1049 	gkrellm_free_glist_and_data(&plugins_place_list);
1050 	path = gkrellm_make_config_file_name(gkrellm_homedir(),
1051 				PLUGIN_PLACEMENT_FILE);
1052 	if ((f = g_fopen(path, "r")) != NULL)
1053 		{
1054 		while ((fgets(buf, sizeof(buf), f)) != NULL)
1055 			{
1056 			if ((s = strchr(buf, '\n')) != NULL)
1057 				*s = '\0';
1058 			s = g_strdup(buf);
1059 			plugins_place_list = g_list_append(plugins_place_list, s);
1060 			}
1061 		fclose(f);
1062 		}
1063 	g_free(path);
1064 	}
1065 
1066 static void
save_plugins_placement_file(void)1067 save_plugins_placement_file(void)
1068 	{
1069 	FILE				*f;
1070 	GList				*list;
1071 	GkrellmMonitor		*builtin, *plugin;
1072 	GkrellmMonprivate	*mp;
1073 	gchar				*path;
1074 
1075 	if (!plugin_placement_modified || _GK.demo || _GK.no_config)
1076 		return;
1077 	path = gkrellm_make_config_file_name(gkrellm_homedir(),
1078 				PLUGIN_PLACEMENT_FILE);
1079 	if ((f = g_fopen(path, "w")) != NULL)
1080 		{
1081 		for (list = plugins_list; list; list = list->next)
1082 			{
1083 			plugin = (GkrellmMonitor *) list->data;
1084 			mp  = plugin->privat;
1085 			if (   mp->enabled && !mp->from_command_line
1086 				&& (   mp->insert_before_id != PLUGIN_INSERT_BEFORE_ID(plugin)
1087 					|| mp->insert_after != PLUGIN_INSERT_AFTER(plugin)
1088 					|| mp->gravity != PLUGIN_GRAVITY(plugin)
1089 				   )
1090 			   )
1091 				{
1092 				builtin = gkrellm_monitor_from_id(mp->insert_before_id);
1093 				if (!builtin)
1094 					continue;
1095 				fprintf(f, "\"%s\" \"%s\" %d %d\n", plugin->name,
1096 						builtin->name, mp->insert_after, mp->gravity);
1097 				}
1098 			}
1099 		fclose(f);
1100 		}
1101 	plugin_placement_modified = FALSE;
1102 	g_free(path);
1103 	}
1104 
1105 static void
load_plugins_enable_file(void)1106 load_plugins_enable_file(void)
1107 	{
1108 	FILE	*f;
1109 	gchar	*path, *s, buf[256];
1110 
1111 	gkrellm_free_glist_and_data(&plugins_enable_list);
1112 	path = gkrellm_make_config_file_name(gkrellm_homedir(),PLUGIN_ENABLE_FILE);
1113 	if ((f = g_fopen(path, "r")) != NULL)
1114 		{
1115 		while ((fgets(buf, sizeof(buf), f)) != NULL)
1116 			{
1117 			if ((s = strchr(buf, '\n')) != NULL)
1118 				*s = '\0';
1119 			if (!buf[0])
1120 				continue;
1121 			s = g_path_get_basename(buf);
1122 			plugins_enable_list = g_list_append(plugins_enable_list, s);
1123 			}
1124 		fclose(f);
1125 		}
1126 	g_free(path);
1127 	}
1128 
1129 static void
save_plugins_enable_file(void)1130 save_plugins_enable_file(void)
1131 	{
1132 	FILE			*f;
1133 	GList			*list;
1134 	GkrellmMonitor	*m;
1135 	gchar			*path, *s;
1136 
1137 	if (!plugin_enable_list_modified || _GK.demo)
1138 		return;
1139 	path = gkrellm_make_config_file_name(gkrellm_homedir(),
1140 				PLUGIN_ENABLE_FILE);
1141 	if ((f = g_fopen(path, "w")) != NULL)
1142 		{
1143 		for (list = plugins_list; list; list = list->next)
1144 			{
1145 			m = (GkrellmMonitor *) list->data;
1146 			if (m->privat->enabled && !m->privat->from_command_line)
1147 				{
1148 				s = g_path_get_basename(m->path);
1149 				fprintf(f, "%s\n", s);
1150 				g_free(s);
1151 				}
1152 			}
1153 		fclose(f);
1154 		}
1155 	plugin_enable_list_modified = FALSE;
1156 	g_free(path);
1157 	}
1158 
1159 static gchar *
string_suffix(gchar * string,gchar * suffix)1160 string_suffix(gchar *string, gchar *suffix)
1161 	{
1162 	gchar	*dot;
1163 
1164 	dot = strrchr(string, '.');
1165 	if (dot && !strcmp(dot + 1, suffix))
1166 		return dot + 1;
1167 	return NULL;
1168 	}
1169 
1170 static void
scan_for_plugins(gchar * path)1171 scan_for_plugins(gchar *path)
1172 	{
1173     GDir			*dir;
1174     gchar			*name, *filename;
1175 	GList			*list;
1176 	GkrellmMonitor	*m = NULL;
1177 	gchar			*s;
1178 	gboolean		exists;
1179 
1180 	if (!path || !*path || (dir = g_dir_open(path, 0, NULL)) == NULL)
1181 		return;
1182 	while ((name = (gchar *) g_dir_read_name(dir)) != NULL)
1183 		{
1184 		if (   !string_suffix(name, "so")
1185 			&& !string_suffix(name, "la")
1186 			&& !string_suffix(name, "dll")
1187 		   )
1188 			continue;
1189 
1190 		/* If there's a libtool .la archive, won't want to load this .so
1191 		*/
1192 		if (   !string_suffix(name, "la")
1193 			&& (s = strrchr(name, '.')) != NULL
1194 		   )
1195 			{
1196 			s = g_strndup(name, s - name);
1197 			filename = g_strconcat(path, G_DIR_SEPARATOR_S, s, ".la", NULL);
1198 			exists = g_file_test(filename, G_FILE_TEST_EXISTS);
1199 			g_free(s);
1200 			g_free(filename);
1201 			if (exists)
1202 				continue;
1203 			}
1204 		for (list = plugins_list; list; list = list->next)
1205 			{
1206 			m = (GkrellmMonitor *) list->data;
1207 			s = g_path_get_basename(m->path);
1208 			exists = !strcmp(s, name);
1209 			g_free(s);
1210 			if (exists)
1211 				break;
1212 			m = NULL;
1213 			}
1214 		s = g_strconcat(path, G_DIR_SEPARATOR_S, name, NULL);
1215 		if (m)
1216 			{
1217 			plugin_log(_("Ignoring duplicate plugin "), s, "\n", NULL);
1218 			g_free(s);
1219 			continue;
1220 			}
1221 		m = install_plugin(s);
1222 		if (m)	/* s is saved for use */
1223 			{
1224 			plugins_list = g_list_append(plugins_list, m);
1225 			s = g_path_get_basename(m->path);
1226 			if (! gkrellm_string_in_list(plugins_enable_list, s))
1227 				m->privat->enabled = FALSE;
1228 			}
1229 		g_free(s);
1230 		}
1231 	g_dir_close(dir);
1232 	}
1233 
1234 void
gkrellm_plugins_load(void)1235 gkrellm_plugins_load(void)
1236 	{
1237 	GkrellmMonitor	*m;
1238 	gchar			*path;
1239 
1240 	if (_GK.command_line_plugin)
1241 		{
1242 		if (   *_GK.command_line_plugin != '.'
1243 			&& !strchr(_GK.command_line_plugin, G_DIR_SEPARATOR)
1244 		   )
1245 			path = g_strconcat(".", G_DIR_SEPARATOR_S,
1246 						_GK.command_line_plugin, NULL);
1247 		else
1248 			path = g_strdup(_GK.command_line_plugin);
1249 		plugin_log(_("*** Command line plugin:\n"), NULL);
1250 		if ((m = install_plugin(path)) == NULL)
1251 			g_free(path);
1252 		else
1253 			{
1254 			m->privat->from_command_line = TRUE;
1255 			plugins_list = g_list_append(plugins_list, m);
1256 			}
1257 		plugin_log("\n", NULL);
1258 		}
1259 	load_plugins_enable_file();
1260 	load_plugins_placement_file();
1261 	path = g_strconcat(gkrellm_homedir(), G_DIR_SEPARATOR_S,
1262 				GKRELLM_PLUGINS_DIR, NULL);
1263 	scan_for_plugins(path);
1264 	g_free(path);
1265 
1266 #if defined(WIN32)
1267 	gchar *install_path;
1268 	install_path = g_win32_get_package_installation_directory_of_module(NULL);
1269 	if (install_path != NULL)
1270 		{
1271 		path = g_build_filename(install_path, "lib", "gkrellm2", "plugins", NULL);
1272 		scan_for_plugins(path);
1273 		g_free(path);
1274 		g_free(install_path);
1275 		}
1276 #endif
1277 
1278 
1279 #if defined(LOCAL_PLUGINS_DIR)
1280 	scan_for_plugins(LOCAL_PLUGINS_DIR);
1281 #endif
1282 
1283 #if defined(SYSTEM_PLUGINS_DIR)
1284 	scan_for_plugins(SYSTEM_PLUGINS_DIR);
1285 #endif
1286 	}
1287 
1288 #if 0
1289 void
1290 shuffle_test(void)
1291 	{
1292 	GList			*list;
1293 	GkrellmMonitor	*mon;
1294 	gint			i;
1295 	static gboolean	srand_done;
1296 	extern GtkWidget *gkrellm_monitor_vbox();
1297 
1298 	if (!srand_done)
1299 		{
1300 		srandom((unsigned int) time(0));
1301 		srand_done = TRUE;
1302 		}
1303 	for (list = gkrellm_monitor_list; list; list = list->next)
1304 		{
1305 		i = (gint) random();
1306 		i = (i % (g_list_length(gkrellm_monitor_list) - 2)) + 1;
1307 		mon = (GkrellmMonitor *) list->data;
1308 		if (mon->privat->main_vbox && mon != gkrellm_mon_host())
1309 			{
1310 			gtk_box_reorder_child(GTK_BOX(gkrellm_monitor_vbox()),
1311 						mon->privat->main_vbox, i);
1312 			}
1313 		}
1314 	}
1315 #endif
1316 
1317 static void
replace_plugins()1318 replace_plugins()
1319 	{
1320 	GList			*new_monitor_list, *list;
1321 	GkrellmMonitor	*mon;
1322 	extern GtkWidget *gkrellm_monitor_vbox();
1323 
1324 	new_monitor_list = NULL;
1325 	for (list = gkrellm_monitor_list; list; list = list->next)
1326 		{
1327 		mon = (GkrellmMonitor *) list->data;
1328 		if (mon->privat->main_vbox && mon != gkrellm_mon_host())
1329 			{
1330                             g_object_ref(G_OBJECT(mon->privat->main_vbox));
1331 			gtk_container_remove(GTK_CONTAINER(gkrellm_monitor_vbox()),
1332 					mon->privat->main_vbox);
1333 			}
1334 		if (MONITOR_ID(mon) != MON_PLUGIN)
1335 			new_monitor_list = g_list_append(new_monitor_list, mon);
1336 		}
1337 	for (list = gkrellm_monitor_list; list; list = list->next)
1338 		{
1339 		mon = (GkrellmMonitor *) list->data;
1340 		if (MONITOR_ID(mon) == MON_PLUGIN)
1341 			gkrellm_place_plugin(&new_monitor_list, mon);
1342 		}
1343 	g_list_free(gkrellm_monitor_list);
1344 	gkrellm_monitor_list = new_monitor_list;
1345 	for (list = gkrellm_monitor_list; list; list = list->next)
1346 		{
1347 		mon = (GkrellmMonitor *) list->data;
1348 		if (mon->privat->main_vbox && mon != gkrellm_mon_host())
1349 			{
1350 			gtk_box_pack_start(GTK_BOX(gkrellm_monitor_vbox()),
1351 					mon->privat->main_vbox, FALSE, FALSE, 0);
1352 			g_object_unref(G_OBJECT(mon->privat->main_vbox));
1353 			}
1354 		}
1355 	}
1356 
1357 
1358 static GtkWidget	*place_plugin_window;
1359 static GtkWidget	*place_plugin_vbox;
1360 static gboolean		setting_place_buttons;
1361 
1362 static void
apply_place(void)1363 apply_place(void)
1364 	{
1365 	GList			*list;
1366 	GkrellmMonitor	*mon;
1367 	gint			i;
1368 
1369 	if (!place_plugin || setting_place_buttons)
1370 		return;
1371 	for (i = 0; i < N_BUILTIN_MONITORS; ++i)
1372 		if (GTK_TOGGLE_BUTTON(builtin_button[i])->active)
1373 			break;
1374 	for (list = gkrellm_monitor_list; list; list = list->next)
1375 		{
1376 		mon = (GkrellmMonitor *) list->data;
1377 		if (MONITOR_ID(mon) == MON_PLUGIN || i != mon->privat->button_id)
1378 			continue;
1379 		place_plugin->privat->insert_before_id = mon->id;
1380 		place_plugin->privat->insert_after =
1381 				GTK_TOGGLE_BUTTON(after_button)->active;
1382 		if (place_plugin->privat->insert_after)
1383 			place_plugin->privat->gravity = 0;
1384 		else
1385 			place_plugin->privat->gravity = gtk_spin_button_get_value_as_int(
1386 						GTK_SPIN_BUTTON(gravity_spin_button));
1387 
1388 		replace_plugins();
1389 		plugin_placement_modified = TRUE;
1390 		break;
1391 		}
1392 	}
1393 
1394 static void
cb_close_place(void)1395 cb_close_place(void)
1396 	{
1397 	if (place_plugin_window)
1398 		gtk_widget_destroy(place_plugin_window);
1399 	place_plugin_window = NULL;
1400 	place_plugin_vbox = NULL;
1401 	}
1402 
1403 static gint
place_plugin_window_delete_event(GtkWidget * widget,GdkEvent * ev,gpointer data)1404 place_plugin_window_delete_event(GtkWidget *widget, GdkEvent *ev,gpointer data)
1405 	{
1406 	cb_close_place();
1407 	return FALSE;
1408 	}
1409 
1410 static void
cb_place_default(GtkWidget * widget,gpointer data)1411 cb_place_default(GtkWidget *widget, gpointer data)
1412 	{
1413 	GkrellmMonitor	*mon;
1414 
1415 	if (!place_plugin)
1416 		return;
1417 	if (PLUGIN_INSERT_AFTER(place_plugin))
1418 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(after_button),
1419 				TRUE);
1420 	else
1421 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(before_button),
1422 				TRUE);
1423 	gtk_spin_button_set_value(GTK_SPIN_BUTTON(gravity_spin_button),
1424 			(gfloat) PLUGIN_GRAVITY(place_plugin));
1425 	mon = gkrellm_monitor_from_id(PLUGIN_INSERT_BEFORE_ID(place_plugin));
1426 	if (mon && mon->privat->button_id >= 0)
1427 		gtk_toggle_button_set_active(
1428 			GTK_TOGGLE_BUTTON(builtin_button[mon->privat->button_id]), TRUE);
1429 	}
1430 
1431 static void
place_button_sensitivity(GkrellmMonitor * plugin,gboolean state)1432 place_button_sensitivity(GkrellmMonitor *plugin, gboolean state)
1433 	{
1434 	GkrellmMonitor	*mon = NULL;
1435 
1436 	if (gkrellm_demo_mode())
1437 		{
1438 		gtk_widget_set_sensitive(place_button, FALSE);
1439 		return;
1440 		}
1441 	place_plugin = plugin;
1442 	if (state && plugin && plugin->create_monitor)
1443 		{
1444 		gtk_widget_set_sensitive(place_button, TRUE);
1445 		if (place_plugin_vbox)
1446 			gtk_widget_set_sensitive(place_plugin_vbox, TRUE);
1447 		}
1448 	else
1449 		{
1450 		gtk_widget_set_sensitive(place_button, FALSE);
1451 		if (place_plugin_vbox)
1452 			gtk_widget_set_sensitive(place_plugin_vbox, FALSE);
1453 		return;
1454 		}
1455 	if (!place_plugin_window)
1456 		return;
1457 
1458 	setting_place_buttons = TRUE;
1459 	gtk_label_set_text(GTK_LABEL(place_label), plugin->name);
1460 	if (plugin->privat->insert_after)
1461 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(after_button), TRUE);
1462 	else
1463 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(before_button), TRUE);
1464 	gtk_spin_button_set_value(GTK_SPIN_BUTTON(gravity_spin_button),
1465 			(gfloat) plugin->privat->gravity);
1466 	mon = gkrellm_monitor_from_id(plugin->privat->insert_before_id);
1467 	if (mon && mon->privat->button_id >= 0)
1468 		gtk_toggle_button_set_active(
1469 			GTK_TOGGLE_BUTTON(builtin_button[mon->privat->button_id]), TRUE);
1470 	setting_place_buttons = FALSE;
1471 	}
1472 
1473 static gboolean
cb_place(GtkToggleButton * button,gpointer data)1474 cb_place(GtkToggleButton *button, gpointer data)
1475 	{
1476 	if (!button->active)
1477 		return FALSE;
1478 	apply_place();
1479 	return TRUE;
1480 	}
1481 
1482 static void
cb_place_spin(GtkWidget * widget,GtkSpinButton * spin)1483 cb_place_spin(GtkWidget *widget, GtkSpinButton *spin)
1484 	{
1485 	if (!place_plugin)
1486 		return;
1487 	if (place_plugin->privat->insert_after)
1488 		gtk_spin_button_set_value(GTK_SPIN_BUTTON(gravity_spin_button), 0.0);
1489 	else
1490 		apply_place();
1491 	return;
1492 	}
1493 
1494 static void
cb_place_button(GtkWidget * widget,gpointer data)1495 cb_place_button(GtkWidget *widget, gpointer data)
1496 	{
1497 	GtkWidget		*main_vbox, *vbox, *vbox1, *vbox2, *vbox3, *hbox;
1498 	GtkWidget		*button;
1499 	GtkTreeModel	*model;
1500 	GtkTreePath		*path;
1501 	GtkTreeIter		iter;
1502 	GSList			*group;
1503 	GList			*list;
1504 	GkrellmMonitor	*mon;
1505 	gint			i;
1506 
1507 	if (gkrellm_demo_mode())
1508 		return;
1509 	if (!place_plugin_window)
1510 		{
1511 		place_plugin_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1512 		g_signal_connect(G_OBJECT(place_plugin_window), "delete_event",
1513 				G_CALLBACK(place_plugin_window_delete_event), NULL);
1514 		gtk_window_set_title(GTK_WINDOW(place_plugin_window),
1515 				_("GKrellM Place Plugin"));
1516 		gtk_window_set_wmclass(GTK_WINDOW(place_plugin_window),
1517 				"Gkrellm_conf", "Gkrellm");
1518 
1519 		main_vbox = gtk_vbox_new(FALSE, 0);
1520 		gtk_container_add(GTK_CONTAINER(place_plugin_window), main_vbox);
1521 		place_plugin_vbox = main_vbox;
1522 		vbox = gkrellm_gtk_framed_vbox(main_vbox, NULL, 3, FALSE, 4, 3);
1523 		hbox = gtk_hbox_new(FALSE, 0);
1524 		gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1525 
1526 		vbox1 = gkrellm_gtk_framed_vbox(hbox, _("Builtin Monitors"),
1527 				3, FALSE, 4, 3);
1528 		group = NULL;
1529 		for (i = 0, list = gkrellm_monitor_list; list; list = list->next)
1530 			{
1531 			mon = (GkrellmMonitor *) list->data;
1532 			mon->privat->button_id = -1;
1533 			if (MONITOR_ID(mon) != MON_PLUGIN)
1534 				{
1535 				if (   !mon->name || !mon->create_monitor
1536 					|| mon == gkrellm_mon_host()
1537 				   )
1538 					continue;
1539 				button = gtk_radio_button_new_with_label(group, mon->name);
1540 				g_signal_connect(G_OBJECT(button), "clicked",
1541 						G_CALLBACK(cb_place), NULL);
1542 				gtk_box_pack_start(GTK_BOX(vbox1), button, FALSE, FALSE, 0);
1543 				if (i < N_BUILTIN_MONITORS)
1544 					{
1545 					builtin_button[i] = button;
1546 					mon->privat->button_id = i++;
1547 					}
1548 				group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button));
1549 				}
1550 			}
1551 		vbox1 = gtk_vbox_new(FALSE, 0);
1552 		gtk_box_pack_start(GTK_BOX(hbox), vbox1, FALSE, FALSE, 0);
1553 		place_label = gtk_label_new("");
1554 		gtk_box_pack_start(GTK_BOX(vbox1), place_label, FALSE, FALSE, 10);
1555 		vbox2 = gkrellm_gtk_framed_vbox(vbox1, _("Place Plugin"),
1556 				3, FALSE, 4, 3);
1557 
1558 		group = NULL;
1559 		vbox3 = gkrellm_gtk_framed_vbox(vbox2, NULL, 3, FALSE, 4, 3);
1560 		before_button = gtk_radio_button_new_with_label(group,
1561 				_("Before selected builtin monitor"));
1562 		g_signal_connect(G_OBJECT(before_button), "clicked",
1563 				G_CALLBACK(cb_place), NULL);
1564 		gtk_box_pack_start(GTK_BOX(vbox3), before_button, FALSE, FALSE, 0);
1565 		gkrellm_gtk_spin_button(vbox3, &gravity_spin_button, 8,
1566 				0.0, 15.0, 1, 1, 0, 50,
1567 				cb_place_spin, NULL, FALSE,
1568 				_("With gravity"));
1569 
1570 		vbox3 = gkrellm_gtk_framed_vbox(vbox2, NULL, 3, FALSE, 4, 3);
1571 		group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(before_button));
1572 		after_button = gtk_radio_button_new_with_label(group,
1573 				_("After selected builtin monitor"));
1574 		g_signal_connect(G_OBJECT(after_button), "clicked",
1575 				G_CALLBACK(cb_place), NULL);
1576 		gtk_box_pack_start(GTK_BOX(vbox3), after_button, FALSE, FALSE, 0);
1577 
1578 		hbox = gtk_hbox_new(FALSE, 0);
1579 		gtk_box_pack_start(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
1580 		gkrellm_gtk_button_connected(hbox, NULL, TRUE, FALSE, 0,
1581 				cb_place_default, NULL, _("Plugin Defaults"));
1582 
1583 		hbox = gtk_hbutton_box_new();
1584 		gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
1585 		gtk_box_set_spacing(GTK_BOX(hbox), 5);
1586 		gtk_box_pack_end(GTK_BOX(vbox1), hbox, FALSE, FALSE, 0);
1587 
1588 		button = gtk_button_new_from_stock(GTK_STOCK_OK);
1589 		GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1590 		g_signal_connect(G_OBJECT(button), "clicked",
1591 				G_CALLBACK(cb_close_place), NULL);
1592 		gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
1593 
1594 		gtk_widget_show_all(place_plugin_window);
1595 		}
1596 	else
1597 		gtk_window_present(GTK_WINDOW(place_plugin_window));
1598 //		gdk_window_raise(place_plugin_window->window);
1599 
1600 	if (row_reference)
1601 		{
1602 		model = gtk_tree_view_get_model(treeview);
1603 		path = gtk_tree_row_reference_get_path(row_reference);
1604 		gtk_tree_model_get_iter(model, &iter, path);
1605 		gtk_tree_model_get(model, &iter, MON_COLUMN, &mon, -1);
1606 		place_button_sensitivity(mon, mon->privat->enabled);
1607 		}
1608 	}
1609 
1610 static void
cb_enable_plugin(GtkCellRendererToggle * cell,gchar * path_str,gpointer data)1611 cb_enable_plugin(GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
1612 	{
1613 	GtkTreeModel	*model = (GtkTreeModel *)data;
1614 	GtkTreeIter		iter;
1615 	GtkTreePath		*path;
1616 	GkrellmMonitor	*mon;
1617 	gboolean		enable;
1618 
1619 	path = gtk_tree_path_new_from_string(path_str);
1620 	gtk_tree_model_get_iter(model, &iter, path);
1621 	gtk_tree_path_free(path);
1622 	gtk_tree_model_get(model, &iter,
1623 				ENABLE_COLUMN, &enable,
1624 				MON_COLUMN, &mon,
1625 				-1);
1626 	if (mon->privat->from_command_line)
1627 		enable = TRUE;
1628 	else
1629 		enable = !enable;
1630 	gtk_list_store_set(GTK_LIST_STORE(model), &iter,
1631 				ENABLE_COLUMN, enable, -1);
1632 	if (enable)
1633 		enable_plugin(mon);
1634 	else
1635 		disable_plugin(mon);
1636 	place_button_sensitivity(mon, enable);
1637 	}
1638 
1639 static void
cb_tree_selection_changed(GtkTreeSelection * selection,gpointer data)1640 cb_tree_selection_changed(GtkTreeSelection *selection, gpointer data)
1641 	{
1642 	GtkTreeIter		iter;
1643 	GtkTreeModel	*model;
1644 	GtkTreePath		*path;
1645 	GkrellmMonitor	*mon;
1646 
1647 	gtk_tree_row_reference_free(row_reference);
1648 	if (!gtk_tree_selection_get_selected(selection, &model, &iter))
1649 		{
1650 		row_reference = NULL;
1651 		place_button_sensitivity(NULL, FALSE);
1652 		return;
1653 		}
1654 	path = gtk_tree_model_get_path(model, &iter);
1655 	row_reference = gtk_tree_row_reference_new(model, path);
1656 	gtk_tree_model_get(model, &iter, MON_COLUMN, &mon, -1);
1657 	place_button_sensitivity(mon, mon->privat->enabled);
1658 	}
1659 
1660 void
gkrellm_plugins_config_close(void)1661 gkrellm_plugins_config_close(void)
1662 	{
1663 	save_plugins_enable_file();
1664 	save_plugins_placement_file();
1665 	cb_close_place();
1666 	}
1667 
1668 static GtkTreeModel *
create_model(void)1669 create_model(void)
1670 	{
1671 	GtkListStore	*store;
1672 	GtkTreeIter		iter;
1673 	GkrellmMonitor	*mon;
1674 	GList			*list;
1675 	gchar			*buf;
1676 
1677 	store = gtk_list_store_new(N_COLUMNS,
1678 				G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER);
1679 	for (list = plugins_list; list; list = list->next)
1680 		{
1681 		mon = (GkrellmMonitor *) list->data;
1682 		if (mon->privat->from_command_line)
1683 			buf = g_strdup_printf("%s  (%s)", mon->name,
1684 					_("from command line"));
1685 		else
1686 			buf = NULL;
1687 
1688 		gtk_list_store_append(store, &iter);
1689 		gtk_list_store_set(store, &iter,
1690 				NAME_COLUMN, buf ? buf : mon->name,
1691 				ENABLE_COLUMN, mon->privat->enabled,
1692 				MON_COLUMN, mon,
1693 				-1);
1694 		g_free(buf);
1695 		}
1696 	return GTK_TREE_MODEL(store);
1697 	}
1698 
1699 void
gkrellm_plugins_config_create(GtkWidget * tab_vbox)1700 gkrellm_plugins_config_create(GtkWidget *tab_vbox)
1701 	{
1702 	GtkWidget			*tabs;
1703 	GtkWidget			*vbox;
1704 	GtkWidget			*hbox;
1705 	GtkWidget			*scrolled;
1706 	GtkWidget			*view;
1707 	GtkTreeModel		*model;
1708 	GtkCellRenderer		*renderer;
1709 	GtkTreeSelection	*selection;
1710 	GtkTreeViewColumn	*column;
1711 	GtkTextIter			iter;
1712 	GtkTextBuffer		*buffer;
1713 
1714 	row_reference = NULL;
1715 	tabs = gtk_notebook_new();
1716 	gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
1717 	gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0);
1718 
1719 
1720 /* -- Plugins tab */
1721 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Plugins"));
1722 
1723 	scrolled = gtk_scrolled_window_new(NULL, NULL);
1724 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1725 			GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1726 	gtk_box_pack_start(GTK_BOX(vbox), scrolled, TRUE, TRUE, 2);
1727 
1728 	model = create_model();
1729 	treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
1730 	g_object_unref(G_OBJECT(model));
1731 	gtk_tree_view_set_rules_hint(treeview, TRUE);
1732 
1733 	renderer = gtk_cell_renderer_toggle_new();
1734 	gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Enable"),
1735 				renderer,
1736 				"active", ENABLE_COLUMN, NULL);
1737 	g_signal_connect (G_OBJECT(renderer), "toggled",
1738 				G_CALLBACK(cb_enable_plugin), model);
1739 
1740 	renderer = gtk_cell_renderer_text_new();
1741 	column = gtk_tree_view_column_new_with_attributes (_("Plugin"),
1742 				renderer,
1743 				"text", NAME_COLUMN, NULL);
1744 	gtk_tree_view_append_column(treeview, column);
1745 	gtk_tree_view_column_set_sort_column_id(column, NAME_COLUMN);
1746 	gtk_tree_view_column_clicked(column);		/* Sort it */
1747 /* gtk_tree_sortable_set_sort_column_id(model,
1748 			NAME_COLUMN, GTK_ORDER_ASCENDING);
1749 */
1750 
1751 	gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(treeview));
1752 	selection = gtk_tree_view_get_selection(treeview);
1753 	gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
1754 	g_signal_connect(G_OBJECT(selection), "changed",
1755 				G_CALLBACK(cb_tree_selection_changed), NULL);
1756 
1757 	hbox = gtk_hbutton_box_new();
1758 	gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_START);
1759 	gtk_box_set_spacing(GTK_BOX(hbox), 5);
1760 	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 2);
1761 
1762 	place_button = gtk_button_new_with_label(_("Place"));
1763 	gtk_box_pack_start(GTK_BOX(hbox), place_button, TRUE, TRUE, 0);
1764 	g_signal_connect(G_OBJECT(GTK_BUTTON(place_button)), "clicked",
1765 			G_CALLBACK(cb_place_button), NULL);
1766 	gtk_widget_set_sensitive(place_button, FALSE);
1767 
1768 /* --Plugins detect log tab */
1769 	vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Install Log"));
1770 	view = gkrellm_gtk_scrolled_text_view(vbox, NULL,
1771 				GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1772 	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
1773 	gtk_text_buffer_get_end_iter(buffer, &iter);
1774 	if (plugin_install_log)
1775 		gtk_text_buffer_insert(buffer, &iter, plugin_install_log, -1);
1776 	else
1777 		gtk_text_buffer_insert(buffer, &iter, _("No plugins found."), -1);
1778 	}
1779