1 /*
2 * Copyright (c) Tony Bybell 2012-2018.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 */
9
10 #include <config.h>
11 #include "gconf.h"
12 #include "wavealloca.h"
13 #include "globals.h"
14
15 int wave_rpc_id = 0;
16
17 #ifdef WAVE_HAVE_GSETTINGS
18 static GSettings *gs = NULL;
19
remove_client(void)20 static void remove_client(void)
21 {
22 if(gs)
23 {
24 g_object_unref(gs);
25 gs = NULL;
26 }
27 }
28
parse_rpc_id(char * str,int * this_wave_rpc_id)29 static char *parse_rpc_id(char *str, int *this_wave_rpc_id)
30 {
31 char *comma = strchr(str, ',');
32 char *str2 = comma ? (comma+1) : NULL;
33
34 *this_wave_rpc_id = atoi(str);
35
36 return(str2);
37 }
38
39 static void
user_function(GSettings * settings,gchar * key,gpointer user_data)40 user_function (GSettings *settings,
41 gchar *key,
42 gpointer user_data)
43 {
44 (void)user_data;
45
46 char *str = NULL;
47 char *str2 = NULL;
48 int this_wave_rpc_id = -1;
49
50 g_settings_get (settings, key, "s", &str);
51
52 if(!strcmp(key, "open"))
53 {
54 if((str)&&(str[0]))
55 {
56 str2 = parse_rpc_id(str, &this_wave_rpc_id);
57 if((this_wave_rpc_id == wave_rpc_id) && str2)
58 {
59 fprintf(stderr, "GTKWAVE | RPC Open: '%s'\n", str2);
60
61 deal_with_rpc_open(str, NULL);
62 g_settings_set(settings, "open", "s", "");
63 }
64 }
65 }
66 else
67 if(!strcmp(key, "quit"))
68 {
69 if((str)&&(str[0]))
70 {
71 str2 = parse_rpc_id(str, &this_wave_rpc_id);
72 if((this_wave_rpc_id == wave_rpc_id) && str2)
73 {
74 const char *rc = str2;
75 int rcv = atoi(rc);
76 fprintf(stderr, "GTKWAVE | RPC Quit: exit return code %d\n", rcv);
77 g_settings_set(settings, "quit", "s", "");
78 exit(rcv);
79 }
80 }
81 }
82 else
83 if(!strcmp(key, "reload"))
84 {
85 if((str)&&(str[0]))
86 {
87 this_wave_rpc_id = atoi(str);
88 if(this_wave_rpc_id == wave_rpc_id)
89 {
90 if(in_main_iteration()) goto bot;
91 reload_into_new_context();
92 g_settings_set(settings, "reload", "s", "");
93 }
94 }
95 }
96 else
97 if(!strcmp(key, "zoom-full"))
98 {
99 if((str)&&(str[0]))
100 {
101 this_wave_rpc_id = atoi(str);
102 if(this_wave_rpc_id == wave_rpc_id)
103 {
104 if(in_main_iteration()) goto bot;
105 service_zoom_full(NULL, NULL);
106 g_settings_set(settings, "zoom-full", "s", "");
107 }
108 }
109 }
110 else
111 if(!strcmp(key, "writesave"))
112 {
113 if((str)&&(str[0]))
114 {
115 str2 = parse_rpc_id(str, &this_wave_rpc_id);
116 if((this_wave_rpc_id == wave_rpc_id) && str2)
117 {
118 const char *fni = str2;
119 if(fni && !in_main_iteration())
120 {
121 int use_arg = strcmp(fni, "+"); /* plus filename uses default */
122 const char *fn = use_arg ? fni : GLOBALS->filesel_writesave;
123 if(fn)
124 {
125 FILE *wave;
126
127 if(!(wave=fopen(fn, "wb")))
128 {
129 fprintf(stderr, "GTKWAVE | RPC Writesave: error opening save file '%s' for writing.\n", fn);
130 perror("Why");
131 errno=0;
132 }
133 else
134 {
135 write_save_helper(fn, wave);
136 if(use_arg)
137 {
138 if(GLOBALS->filesel_writesave) { free_2(GLOBALS->filesel_writesave); }
139 GLOBALS->filesel_writesave = strdup_2(fn);
140 }
141 wave_gconf_client_set_string("/current/savefile", fn);
142 fclose(wave);
143 fprintf(stderr, "GTKWAVE | RPC Writesave: wrote save file '%s'.\n", GLOBALS->filesel_writesave);
144 }
145 }
146 }
147
148 g_settings_set(settings, "writesave", "s", "");
149 }
150 }
151 }
152 else
153 if(!strcmp(key, "move-to-time"))
154 {
155 if((str)&&(str[0]))
156 {
157 str2 = parse_rpc_id(str, &this_wave_rpc_id);
158 if((this_wave_rpc_id == wave_rpc_id) && str2)
159 {
160 if(!in_main_iteration())
161 {
162 char *e_copy = GLOBALS->entrybox_text;
163 GLOBALS->entrybox_text=strdup_2(str2);
164 movetotime_cleanup(NULL, NULL);
165
166 GLOBALS->entrybox_text = e_copy;
167 }
168
169 g_settings_set(settings, "move-to-time", "s", "");
170 }
171 }
172 }
173 else
174 if(!strcmp(key, "zoom-size"))
175 {
176 if((str)&&(str[0]))
177 {
178 str2 = parse_rpc_id(str, &this_wave_rpc_id);
179 if((this_wave_rpc_id == wave_rpc_id) && str2)
180 {
181 if(!in_main_iteration())
182 {
183 char *e_copy = GLOBALS->entrybox_text;
184 GLOBALS->entrybox_text=strdup_2(str2);
185
186 zoomsize_cleanup(NULL, NULL);
187
188 GLOBALS->entrybox_text = e_copy;
189 }
190
191 g_settings_set(settings, "zoom-size", "s", "");
192 }
193 }
194 }
195
196 bot:
197 if(str) g_free(str);
198 }
199
wave_gconf_init(int argc,char ** argv)200 void wave_gconf_init(int argc, char **argv)
201 {
202 (void)argc;
203 (void)argv;
204
205 if(!gs)
206 {
207 gs = g_settings_new (WAVE_GSETTINGS_SCHEMA_ID);
208 g_signal_connect (gs, "changed", G_CALLBACK (user_function), NULL);
209 atexit(remove_client);
210 }
211 }
212
wave_gconf_client_set_string(const gchar * key,const gchar * val)213 gboolean wave_gconf_client_set_string(const gchar *key, const gchar *val)
214 {
215 if(key && gs)
216 {
217 const char *ks = strrchr(key, '/');
218 char *k2 = NULL;
219 if(ks) { ks = ks+1; } else { ks = key; }
220 if(strchr(ks, '_'))
221 {
222 char *s;
223 k2 = s = strdup_2(ks);
224 while(*s) { if(*s=='_') *s='-'; s++; }
225 }
226 g_settings_set(gs, k2 ? k2 : ks, "s", val ? val : "");
227 if(k2) free_2(k2);
228 return(TRUE);
229 }
230
231 return(FALSE);
232 }
233
234
wave_gconf_client_get_string(const gchar * key)235 static gchar *wave_gconf_client_get_string(const gchar *key)
236 {
237 if(key && gs)
238 {
239 const char *ks = strrchr(key, '/');
240 char *k2 = NULL;
241 char *str = NULL;
242 if(ks) { ks = ks+1; } else { ks = key; }
243 if(strchr(ks, '_'))
244 {
245 char *s;
246 k2 = s = strdup_2(ks);
247 while(*s) { if(*s=='_') *s='-'; s++; }
248 }
249 g_settings_get (gs, k2 ? k2 : ks, "s", &str);
250 if(k2) free_2(k2);
251 return(str);
252 }
253
254 return(NULL);
255 }
256
wave_gconf_restore(char ** dumpfile,char ** savefile,char ** rcfile,char ** wave_pwd,int * opt_vcd)257 void wave_gconf_restore(char **dumpfile, char **savefile, char **rcfile, char **wave_pwd, int *opt_vcd)
258 {
259 char *s;
260
261 if(dumpfile && savefile && rcfile && wave_pwd && opt_vcd)
262 {
263 if(*dumpfile) { free_2(*dumpfile); *dumpfile = NULL; }
264 s = wave_gconf_client_get_string("/current/dumpfile");
265 if(s) { if(s[0]) *dumpfile = strdup_2(s); g_free(s); }
266
267 if(*savefile) { free_2(*savefile); *savefile = NULL; }
268 s = wave_gconf_client_get_string("/current/savefile");
269 if(s) { if(s[0]) *savefile = strdup_2(s); g_free(s); }
270
271 if(*rcfile) { free_2(*rcfile); *rcfile = NULL; }
272 s = wave_gconf_client_get_string("/current/rcfile");
273 if(s) { if(s[0]) *rcfile = strdup_2(s); g_free(s); }
274
275 if(*wave_pwd) { free_2(*wave_pwd); *wave_pwd = NULL; }
276 s = wave_gconf_client_get_string("/current/pwd");
277 if(s) { if(s[0]) *wave_pwd = strdup_2(s); g_free(s); }
278
279 s = wave_gconf_client_get_string("/current/optimized-vcd");
280 if(s) { if(s[0]) *opt_vcd = atoi(s); g_free(s); }
281 }
282 }
283
284 #else
285
286 #ifdef WAVE_HAVE_GCONF
287
288 static GConfClient* client = NULL;
289
290 /************************************************************/
291
292 static void
open_callback(GConfClient * gclient,guint cnxn_id,GConfEntry * entry,gpointer user_data)293 open_callback(GConfClient* gclient,
294 guint cnxn_id,
295 GConfEntry *entry,
296 gpointer user_data)
297 {
298 (void)gclient;
299 (void)cnxn_id;
300 (void)user_data;
301
302 if (gconf_entry_get_value (entry) == NULL)
303 {
304 /* value is unset */
305 }
306 else
307 {
308 if (gconf_entry_get_value (entry)->type == GCONF_VALUE_STRING)
309 {
310 fprintf(stderr, "GTKWAVE | RPC Open: '%s'\n", gconf_value_get_string (gconf_entry_get_value (entry)) );
311
312 deal_with_rpc_open(gconf_value_get_string (gconf_entry_get_value (entry)), NULL);
313 gconf_entry_set_value(entry, NULL);
314 }
315 else
316 {
317 /* value is of wrong type */
318 }
319 }
320 }
321
322
323 static void
quit_callback(GConfClient * gclient,guint cnxn_id,GConfEntry * entry,gpointer user_data)324 quit_callback(GConfClient* gclient,
325 guint cnxn_id,
326 GConfEntry *entry,
327 gpointer user_data)
328 {
329 (void)gclient;
330 (void)cnxn_id;
331 (void)user_data;
332
333 if (gconf_entry_get_value (entry) == NULL)
334 {
335 /* value is unset */
336 }
337 else
338 {
339 if (gconf_entry_get_value (entry)->type == GCONF_VALUE_STRING)
340 {
341 const char *rc = gconf_value_get_string (gconf_entry_get_value (entry));
342 int rcv = atoi(rc);
343 fprintf(stderr, "GTKWAVE | RPC Quit: exit return code %d\n", rcv);
344 gconf_entry_set_value(entry, NULL);
345 exit(rcv);
346 }
347 else
348 {
349 /* value is of wrong type */
350 }
351 }
352 }
353
354
355 static void
reload_callback(GConfClient * gclient,guint cnxn_id,GConfEntry * entry,gpointer user_data)356 reload_callback(GConfClient* gclient,
357 guint cnxn_id,
358 GConfEntry *entry,
359 gpointer user_data)
360 {
361 (void)gclient;
362 (void)cnxn_id;
363 (void)user_data;
364
365 if (gconf_entry_get_value (entry) == NULL)
366 {
367 /* value is unset */
368 }
369 else
370 {
371 if (gconf_entry_get_value (entry)->type == GCONF_VALUE_STRING)
372 {
373 if(in_main_iteration()) return;
374 reload_into_new_context();
375 gconf_entry_set_value(entry, NULL);
376 }
377 else
378 {
379 /* value is of wrong type */
380 }
381 }
382 }
383
384
385 static void
zoomfull_callback(GConfClient * gclient,guint cnxn_id,GConfEntry * entry,gpointer user_data)386 zoomfull_callback(GConfClient* gclient,
387 guint cnxn_id,
388 GConfEntry *entry,
389 gpointer user_data)
390 {
391 (void)gclient;
392 (void)cnxn_id;
393 (void)user_data;
394
395 if (gconf_entry_get_value (entry) == NULL)
396 {
397 /* value is unset */
398 }
399 else
400 {
401 if (gconf_entry_get_value (entry)->type == GCONF_VALUE_STRING)
402 {
403 if(in_main_iteration()) return;
404 service_zoom_full(NULL, NULL);
405 gconf_entry_set_value(entry, NULL);
406 }
407 else
408 {
409 /* value is of wrong type */
410 }
411 }
412 }
413
414
415 static void
writesave_callback(GConfClient * gclient,guint cnxn_id,GConfEntry * entry,gpointer user_data)416 writesave_callback(GConfClient* gclient,
417 guint cnxn_id,
418 GConfEntry *entry,
419 gpointer user_data)
420 {
421 (void)gclient;
422 (void)cnxn_id;
423 (void)user_data;
424
425 if (gconf_entry_get_value (entry) == NULL)
426 {
427 /* value is unset */
428 }
429 else
430 {
431 if (gconf_entry_get_value (entry)->type == GCONF_VALUE_STRING)
432 {
433 const char *fni = gconf_value_get_string (gconf_entry_get_value (entry));
434 if(fni && !in_main_iteration())
435 {
436 int use_arg = strcmp(fni, "+"); /* plus filename uses default */
437 const char *fn = use_arg ? fni : GLOBALS->filesel_writesave;
438 if(fn)
439 {
440 FILE *wave;
441
442 if(!(wave=fopen(fn, "wb")))
443 {
444 fprintf(stderr, "GTKWAVE | RPC Writesave: error opening save file '%s' for writing.\n", fn);
445 perror("Why");
446 errno=0;
447 }
448 else
449 {
450 write_save_helper(fn, wave);
451 if(use_arg)
452 {
453 if(GLOBALS->filesel_writesave) { free_2(GLOBALS->filesel_writesave); }
454 GLOBALS->filesel_writesave = strdup_2(fn);
455 }
456 wave_gconf_client_set_string("/current/savefile", fn);
457 fclose(wave);
458 fprintf(stderr, "GTKWAVE | RPC Writesave: wrote save file '%s'.\n", GLOBALS->filesel_writesave);
459 }
460 }
461 }
462
463 gconf_entry_set_value(entry, NULL);
464 }
465 else
466 {
467 /* value is of wrong type */
468 }
469 }
470 }
471
472
473 static void
move_to_time_callback(GConfClient * gclient,guint cnxn_id,GConfEntry * entry,gpointer user_data)474 move_to_time_callback(GConfClient* gclient,
475 guint cnxn_id,
476 GConfEntry *entry,
477 gpointer user_data)
478 {
479 (void)gclient;
480 (void)cnxn_id;
481 (void)user_data;
482
483 if (gconf_entry_get_value (entry) == NULL)
484 {
485 /* value is unset */
486 }
487 else
488 {
489 if (gconf_entry_get_value (entry)->type == GCONF_VALUE_STRING)
490 {
491 const char *str = gconf_value_get_string (gconf_entry_get_value (entry));
492 if(str && !in_main_iteration())
493 {
494 char *e_copy = GLOBALS->entrybox_text;
495 GLOBALS->entrybox_text=strdup_2(str);
496
497 movetotime_cleanup(NULL, NULL);
498
499 GLOBALS->entrybox_text = e_copy;
500 }
501
502 gconf_entry_set_value(entry, NULL);
503 }
504 else
505 {
506 /* value is of wrong type */
507 }
508 }
509 }
510
511
512 static void
zoom_size_callback(GConfClient * gclient,guint cnxn_id,GConfEntry * entry,gpointer user_data)513 zoom_size_callback(GConfClient* gclient,
514 guint cnxn_id,
515 GConfEntry *entry,
516 gpointer user_data)
517 {
518 (void)gclient;
519 (void)cnxn_id;
520 (void)user_data;
521
522 if (gconf_entry_get_value (entry) == NULL)
523 {
524 /* value is unset */
525 }
526 else
527 {
528 if (gconf_entry_get_value (entry)->type == GCONF_VALUE_STRING)
529 {
530 const char *str = gconf_value_get_string (gconf_entry_get_value (entry));
531 if(str && !in_main_iteration())
532 {
533 char *e_copy = GLOBALS->entrybox_text;
534 GLOBALS->entrybox_text=strdup_2(str);
535
536 zoomsize_cleanup(NULL, NULL);
537
538 GLOBALS->entrybox_text = e_copy;
539 }
540
541 gconf_entry_set_value(entry, NULL);
542 }
543 else
544 {
545 /* value is of wrong type */
546 }
547 }
548 }
549
550 /************************************************************/
551
remove_client(void)552 static void remove_client(void)
553 {
554 if(client)
555 {
556 g_object_unref(client);
557 client = NULL;
558 }
559 }
560
561
wave_gconf_init(int argc,char ** argv)562 void wave_gconf_init(int argc, char **argv)
563 {
564 if(!client)
565 {
566 char *ks = wave_alloca(WAVE_GCONF_DIR_LEN + 32 + 32 + 1);
567 int len = sprintf(ks, WAVE_GCONF_DIR"/%d", wave_rpc_id);
568
569 gconf_init(argc, argv, NULL);
570 client = gconf_client_get_default();
571 atexit(remove_client);
572
573 gconf_client_add_dir(client,
574 ks,
575 GCONF_CLIENT_PRELOAD_NONE,
576 NULL);
577
578 strcpy(ks + len, "/open");
579 gconf_client_notify_add(client, ks,
580 open_callback,
581 NULL, /* user data */
582 NULL, NULL);
583
584 strcpy(ks + len, "/quit");
585 gconf_client_notify_add(client, ks,
586 quit_callback,
587 NULL, /* user data */
588 NULL, NULL);
589
590 strcpy(ks + len, "/writesave");
591 gconf_client_notify_add(client, ks,
592 writesave_callback,
593 NULL, /* user data */
594 NULL, NULL);
595
596 strcpy(ks + len, "/reload");
597 gconf_client_notify_add(client, ks,
598 reload_callback,
599 NULL, /* user data */
600 NULL, NULL);
601
602 strcpy(ks + len, "/zoom_full");
603 gconf_client_notify_add(client, ks,
604 zoomfull_callback,
605 NULL, /* user data */
606 NULL, NULL);
607
608 strcpy(ks + len, "/move_to_time");
609 gconf_client_notify_add(client, ks,
610 move_to_time_callback,
611 NULL, /* user data */
612 NULL, NULL);
613
614 strcpy(ks + len, "/zoom_size");
615 gconf_client_notify_add(client, ks,
616 zoom_size_callback,
617 NULL, /* user data */
618 NULL, NULL);
619 }
620 }
621
622
wave_gconf_client_set_string(const gchar * key,const gchar * val)623 gboolean wave_gconf_client_set_string(const gchar *key, const gchar *val)
624 {
625 if(key && client)
626 {
627 char *ks = wave_alloca(WAVE_GCONF_DIR_LEN + 32 + strlen(key) + 1);
628 sprintf(ks, WAVE_GCONF_DIR"/%d%s", wave_rpc_id, key);
629
630 return(gconf_client_set_string(client, ks, val ? val : "", NULL));
631 }
632
633 return(FALSE);
634 }
635
636
wave_gconf_client_get_string(const gchar * key)637 static gchar *wave_gconf_client_get_string(const gchar *key)
638 {
639 if(key && client)
640 {
641 char *ks = wave_alloca(WAVE_GCONF_DIR_LEN + 32 + strlen(key) + 1);
642 sprintf(ks, WAVE_GCONF_DIR"/%d%s", wave_rpc_id, key);
643
644 return(gconf_client_get_string(client, ks, NULL));
645 }
646
647 return(NULL);
648 }
649
650
wave_gconf_restore(char ** dumpfile,char ** savefile,char ** rcfile,char ** wave_pwd,int * opt_vcd)651 void wave_gconf_restore(char **dumpfile, char **savefile, char **rcfile, char **wave_pwd, int *opt_vcd)
652 {
653 char *s;
654
655 if(dumpfile && savefile && rcfile && wave_pwd && opt_vcd)
656 {
657 if(*dumpfile) { free_2(*dumpfile); *dumpfile = NULL; }
658 s = wave_gconf_client_get_string("/current/dumpfile");
659 if(s) { if(s[0]) *dumpfile = strdup_2(s); g_free(s); }
660
661 if(*savefile) { free_2(*savefile); *savefile = NULL; }
662 s = wave_gconf_client_get_string("/current/savefile");
663 if(s) { if(s[0]) *savefile = strdup_2(s); g_free(s); }
664
665 if(*rcfile) { free_2(*rcfile); *rcfile = NULL; }
666 s = wave_gconf_client_get_string("/current/rcfile");
667 if(s) { if(s[0]) *rcfile = strdup_2(s); g_free(s); }
668
669 if(*wave_pwd) { free_2(*wave_pwd); *wave_pwd = NULL; }
670 s = wave_gconf_client_get_string("/current/pwd");
671 if(s) { if(s[0]) *wave_pwd = strdup_2(s); g_free(s); }
672
673 s = wave_gconf_client_get_string("/current/optimized_vcd");
674 if(s) { if(s[0]) *opt_vcd = atoi(s); g_free(s); }
675 }
676 }
677
678 #else
679
wave_gconf_init(int argc,char ** argv)680 void wave_gconf_init(int argc, char **argv)
681 {
682 (void)argc;
683 (void)argv;
684 }
685
wave_gconf_client_set_string(const gchar * key,const gchar * val)686 gboolean wave_gconf_client_set_string(const gchar *key, const gchar *val)
687 {
688 (void)key;
689 (void)val;
690
691 return(FALSE);
692 }
693
wave_gconf_restore(char ** dumpfile,char ** savefile,char ** rcfile,char ** wave_pwd,int * opt_vcd)694 void wave_gconf_restore(char **dumpfile, char **savefile, char **rcfile, char **wave_pwd, int *opt_vcd)
695 {
696 (void)dumpfile;
697 (void)savefile;
698 (void)rcfile;
699 (void)wave_pwd;
700 (void)opt_vcd;
701
702 /* nothing */
703 }
704
705 #endif
706
707 #endif
708
709 /*
710
711 Examples of RPC manipulation (gconf):
712
713 gconftool-2 --dump /com.geda.gtkwave
714 gconftool-2 --dump /com.geda.gtkwave --recursive-unset
715
716 gconftool-2 --type string --set /com.geda.gtkwave/0/open /pub/systema_packed.fst
717 gconftool-2 --type string --set /com.geda.gtkwave/0/open `pwd`/`basename -- des.gtkw`
718
719 gconftool-2 --type string --set /com.geda.gtkwave/0/writesave /tmp/this.gtkw
720 gconftool-2 --type string --set /com.geda.gtkwave/0/writesave +
721
722 gconftool-2 --type string --set /com.geda.gtkwave/0/quit 0
723 gconftool-2 --type string --set /com.geda.gtkwave/0/reload 0
724
725 gconftool-2 --type string --set /com.geda.gtkwave/0/zoom_full 0
726 gconftool-2 --type string --set /com.geda.gtkwave/0/zoom_size -- -4.6
727 gconftool-2 --type string --set /com.geda.gtkwave/0/move_to_time 123ns
728 gconftool-2 --type string --set /com.geda.gtkwave/0/move_to_time A
729
730
731 Examples of RPC manipulation (gsettings).
732 First number is RPC ID:
733
734 gsettings set com.geda.gtkwave open 0,/pub/systema_packed.fst
735
736 gsettings set com.geda.gtkwave writesave 0,/tmp/this.gtkw
737 gsettings set com.geda.gtkwave writesave 0,+
738
739 gsettings set com.geda.gtkwave quit 0,0
740 gsettings set com.geda.gtkwave reload 0
741
742 gsettings set com.geda.gtkwave zoom-full 0
743 gsettings set com.geda.gtkwave zoom-size 0,-4.6
744 gsettings set com.geda.gtkwave move-to-time 0,123ns
745 gsettings set com.geda.gtkwave move-to-time 0,A
746
747 */
748