1 /*
2  * Copyright (c) Tristan Gingold and Tony Bybell 2006-2017.
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 #include <config.h>
10 #include "globals.h"
11 #include <gtk/gtk.h>
12 #include <gdk/gdkkeysyms.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include "gtk12compat.h"
16 #include "analyzer.h"
17 #include "tree.h"
18 #include "symbol.h"
19 #include "vcd.h"
20 #include "lx2.h"
21 #include "busy.h"
22 #include "debug.h"
23 #include "hierpack.h"
24 #include "tcl_helper.h"
25 
26 WAVE_NODEVARTYPE_STR
27 WAVE_NODEVARDIR_STR
28 WAVE_NODEVARDATATYPE_STR
29 
30 enum { VIEW_DRAG_INACTIVE, TREE_TO_VIEW_DRAG_ACTIVE, SEARCH_TO_VIEW_DRAG_ACTIVE };
31 
32 /* Treesearch is a pop-up window used to select signals.
33    It is composed of two main areas:
34    * A tree area to select the hierarchy [tree area]
35    * The (filtered) list of signals contained in the hierarchy [signal area].
36 */
37 
38 /* SIG_ROOT is the branch currently selected.
39    Signals of SIG_ROOT are displayed in the signals window.  */
40 
41 /* Only signals which match the filter are displayed in the signal area.  */
42 
43 /* The signal area is based on a tree view which requires a store model.
44    This store model contains the list of signals to be displayed.
45 */
46 enum { NAME_COLUMN, TREE_COLUMN, TYPE_COLUMN, DIR_COLUMN, DTYPE_COLUMN, N_COLUMNS };
47 
48 /* list of autocoalesced (synthesized) filter names that need to be freed at some point) */
49 
free_afl(void)50 void free_afl(void)
51 {
52 struct autocoalesce_free_list *at;
53 
54 while(GLOBALS->afl_treesearch_gtk2_c_1)
55 	{
56 	if(GLOBALS->afl_treesearch_gtk2_c_1->name) free_2(GLOBALS->afl_treesearch_gtk2_c_1->name);
57 	at = GLOBALS->afl_treesearch_gtk2_c_1->next;
58 	free_2(GLOBALS->afl_treesearch_gtk2_c_1);
59 	GLOBALS->afl_treesearch_gtk2_c_1 = at;
60 	}
61 }
62 
63 
64 /* point to pure signame (remove hierarchy) for fill_sig_store() */
prune_hierarchy(char * nam)65 static char *prune_hierarchy(char *nam)
66 {
67 char cmpchar = GLOBALS->alt_hier_delimeter ? GLOBALS->alt_hier_delimeter : '.';
68 char *t = nam;
69 char *lastmatch = NULL;
70 
71 while(t && *t)
72 	{
73 	if(*t == cmpchar) { lastmatch = t+1; }
74 	t++;
75 	}
76 
77 return(lastmatch ? lastmatch : nam);
78 }
79 
80 /* fix escaped signal names */
fix_escaped_names(char * s,int do_free)81 static void *fix_escaped_names(char *s, int do_free)
82 {
83 char *s2 = s;
84 int found = 0;
85 
86 while(*s2)
87 	{
88 	if((*s2) == VCDNAM_ESCAPE)
89 		{
90 		found = 1;
91 		break;
92 		}
93 	s2++;
94 	}
95 
96 if(found)
97 	{
98 	s2 = strdup_2(s);
99 	if(do_free) free_2(s);
100 	s = s2;
101 
102 	while(*s2)
103 		{
104 		if(*s2 == VCDNAM_ESCAPE) { *s2 = GLOBALS->hier_delimeter; } /* restore back to normal */
105 		s2++;
106 		}
107 	}
108 
109 return(s);
110 }
111 
112 
113 /* truncate VHDL types to string directly after final '.' */
varxt_fix(char * s)114 char *varxt_fix(char *s)
115 {
116 char *pnt = strrchr(s, '.');
117 return(pnt ? (pnt+1) : s);
118 }
119 
120 
121 /* Fill the store model using current SIG_ROOT and FILTER_STR.  */
122 void
fill_sig_store(void)123 fill_sig_store (void)
124 {
125   struct tree *t;
126   struct tree *t_prev = NULL;
127   GtkTreeIter iter;
128 
129   if(GLOBALS->selected_sig_name)
130 	{
131 	free_2(GLOBALS->selected_sig_name);
132 	GLOBALS->selected_sig_name = NULL;
133 	}
134 
135   free_afl();
136   gtk_list_store_clear (GLOBALS->sig_store_treesearch_gtk2_c_1);
137 
138   for (t = GLOBALS->sig_root_treesearch_gtk2_c_1; t != NULL; t = t->next)
139 	{
140 	int i = t->t_which;
141 	char *s, *tmp2;
142 	int vartype;
143 	int vardir;
144 	int is_tname = 0;
145 	int wrexm;
146 	int vardt;
147 	unsigned int varxt;
148 	char *varxt_pnt;
149 
150 	if(i < 0)
151 		{
152 		t_prev = NULL;
153 		continue;
154 		}
155 
156 	if(t_prev) /* duplicates removal for faulty dumpers */
157 		{
158 		if(!strcmp(t_prev->name, t->name))
159 			{
160 			continue;
161 			}
162 		}
163 	t_prev = t;
164 
165 	varxt = GLOBALS->facs[i]->n->varxt;
166 	varxt_pnt = varxt ? varxt_fix(GLOBALS->subvar_pnt[varxt]) : NULL;
167 
168 	vartype = GLOBALS->facs[i]->n->vartype;
169 	if((vartype < 0) || (vartype > ND_VARTYPE_MAX))
170 		{
171 		vartype = 0;
172 		}
173 
174 	vardir = GLOBALS->facs[i]->n->vardir; /* two bit already chops down to 0..3, but this doesn't hurt */
175 	if((vardir < 0) || (vardir > ND_DIR_MAX))
176 		{
177 		vardir = 0;
178 		}
179 
180 	vardt = GLOBALS->facs[i]->n->vardt;
181 	if((vardt < 0) || (vardt > ND_VDT_MAX))
182 		{
183 		vardt = 0;
184 		}
185 
186         if(!GLOBALS->facs[i]->vec_root)
187 		{
188 		is_tname = 1;
189 		s = t->name;
190 		s = fix_escaped_names(s, 0);
191                 }
192                 else
193                 {
194                 if(GLOBALS->autocoalesce)
195                 	{
196 			char *p;
197                         if(GLOBALS->facs[i]->vec_root!=GLOBALS->facs[i]) continue;
198 
199                         tmp2=makename_chain(GLOBALS->facs[i]);
200 			p = prune_hierarchy(tmp2);
201                         s=(char *)malloc_2(strlen(p)+4);
202                         strcpy(s,"[] ");
203                         strcpy(s+3, p);
204 			s = fix_escaped_names(s, 1);
205                         free_2(tmp2);
206                         }
207                         else
208                         {
209 			char *p = prune_hierarchy(GLOBALS->facs[i]->name);
210                         s=(char *)malloc_2(strlen(p)+4);
211                         strcpy(s,"[] ");
212                         strcpy(s+3, p);
213 			s = fix_escaped_names(s, 1);
214                         }
215                 }
216 
217 	wrexm = 0;
218 	if 	(
219 		(GLOBALS->filter_str_treesearch_gtk2_c_1 == NULL) ||
220 		((!GLOBALS->filter_noregex_treesearch_gtk2_c_1) && (wrexm = wave_regex_match(t->name, WAVE_REGEX_TREE)) && (!GLOBALS->filter_matlen_treesearch_gtk2_c_1)) ||
221 		(GLOBALS->filter_matlen_treesearch_gtk2_c_1 && ((GLOBALS->filter_typ_treesearch_gtk2_c_1 == vardir) ^ GLOBALS->filter_typ_polarity_treesearch_gtk2_c_1) &&
222 			(wrexm || (wrexm = wave_regex_match(t->name, WAVE_REGEX_TREE)))	)
223 		)
224       		{
225 		gtk_list_store_prepend (GLOBALS->sig_store_treesearch_gtk2_c_1, &iter);
226 		if(is_tname)
227 			{
228 			gtk_list_store_set (GLOBALS->sig_store_treesearch_gtk2_c_1, &iter,
229 				    NAME_COLUMN, s,
230 				    TREE_COLUMN, t,
231 				    TYPE_COLUMN,
232 						(((GLOBALS->supplemental_datatypes_encountered) && (!GLOBALS->supplemental_vartypes_encountered)) ?
233 							(varxt ? varxt_pnt : vardatatype_strings[vardt]) : vartype_strings[vartype]),
234 				    DIR_COLUMN, vardir_strings[vardir],
235 				    DTYPE_COLUMN, varxt ? varxt_pnt : vardatatype_strings[vardt],
236 				    -1);
237 
238 			if(s != t->name)
239 				{
240 				free_2(s);
241 				}
242 			}
243 			else
244 			{
245 			struct autocoalesce_free_list *a = calloc_2(1, sizeof(struct autocoalesce_free_list));
246 			a->name = s;
247 			a->next = GLOBALS->afl_treesearch_gtk2_c_1;
248 			GLOBALS->afl_treesearch_gtk2_c_1 = a;
249 
250 			gtk_list_store_set (GLOBALS->sig_store_treesearch_gtk2_c_1, &iter,
251 				    NAME_COLUMN, s,
252 				    TREE_COLUMN, t,
253 				    TYPE_COLUMN,
254 						(((GLOBALS->supplemental_datatypes_encountered) && (!GLOBALS->supplemental_vartypes_encountered)) ?
255 							(varxt ? varxt_pnt : vardatatype_strings[vardt]) : vartype_strings[vartype]),
256 				    DIR_COLUMN, vardir_strings[vardir],
257 				    DTYPE_COLUMN, varxt ? varxt_pnt : vardatatype_strings[vardt],
258 				    -1);
259 			}
260       		}
261 		else
262 		{
263 		if(s != t->name)
264 			{
265 			free_2(s);
266 			}
267 		}
268 	}
269 }
270 
271 /*
272  * tree open/close handling
273  */
create_sst_nodes_if_necessary(GtkCTreeNode * node)274 static void create_sst_nodes_if_necessary(GtkCTreeNode *node)
275 {
276 #ifndef WAVE_DISABLE_FAST_TREE
277 if(node)
278 	{
279 	GtkCTreeRow *gctr = GTK_CTREE_ROW(node);
280 	struct tree *t = (struct tree *)(gctr->row.data);
281 
282 	if(t->child)
283 		{
284 		GtkCTree *ctree = GLOBALS->ctree_main;
285 		GtkCTreeNode *n = gctr->children;
286 
287 		gtk_clist_freeze(GTK_CLIST(ctree));
288 
289 		while(n)
290 			{
291 			GtkCTreeRow *g = GTK_CTREE_ROW(n);
292 
293 			t = (struct tree *)(g->row.data);
294 			if(t->t_which < 0)
295 				{
296 				if(!t->children_in_gui)
297 					{
298 					t->children_in_gui = 1;
299 					maketree2(n, t, 0, n);
300 					}
301 				}
302 
303 			n = GTK_CTREE_NODE_NEXT(n);
304 			}
305 
306 		gtk_clist_thaw(GTK_CLIST(ctree));
307 		}
308 	}
309 #endif
310 }
311 
312 
force_open_tree_node(char * name,int keep_path_nodes_open,struct tree ** t_pnt)313 int force_open_tree_node(char *name, int keep_path_nodes_open, struct tree **t_pnt) {
314   GtkCTree *ctree = GLOBALS->ctree_main;
315   int rv = 1 ;			/* can possible open */
316   if(ctree && GLOBALS->any_tree_node) {
317     int namlen = strlen(name);
318     char *namecache = wave_alloca(namlen+1);
319     char *name_end = name + namlen - 1;
320     char *zap = name;
321     GtkCTreeNode *node = GLOBALS->any_tree_node;
322     GtkCTreeRow *gctr = GTK_CTREE_ROW(node);
323     int depth = 1;
324 
325     strcpy(namecache, name);
326     while(gctr->parent)	{
327       node = gctr->parent;
328       gctr = GTK_CTREE_ROW(node);
329     }
330     for(;;) {
331       struct tree *t = gctr->row.data;
332       if(t_pnt) { *t_pnt = t; }
333       while(*zap) {
334 	if(*zap != GLOBALS->hier_delimeter) {
335 	  zap++;
336 	}
337 	else {
338 	  *zap = 0;
339 	  break;
340 	}
341       }
342       if(!strcmp(t->name, name)) {
343 	if(zap == name_end) {
344 	  GtkCTreeNode **nodehist = wave_alloca(depth * sizeof(GtkCTreeNode *));
345 	  int *exp1 = wave_alloca(depth * sizeof(int));
346 	  int i = depth-1;
347 	  nodehist[i] = node;
348 	  exp1[i--] = 1;
349 	  /* now work backwards up to parent getting the node open/close history*/
350 	  gctr = GTK_CTREE_ROW(node);
351 	  while(gctr->parent) {
352 	    node = gctr->parent;
353 	    gctr = GTK_CTREE_ROW(node);
354 	    nodehist[i] = node;
355 	    exp1[i--] = gctr->expanded || (keep_path_nodes_open != 0);
356 	  }
357 	  gtk_clist_freeze(GTK_CLIST(ctree));
358 	  /* fully expand down */
359 	  for(i=0;i<depth;i++) {
360 	    gtk_ctree_expand(ctree, nodehist[i]);
361 	  }
362 	  /* work backwards and close up nodes that were originally closed */
363 	  for(i=depth-1;i>=0;i--) {
364 	    if(exp1[i]) {
365 	      gtk_ctree_expand(ctree, nodehist[i]);
366 	    }
367 	    else {
368 	      gtk_ctree_collapse(ctree, nodehist[i]);
369 	    }
370 	  }
371 	  gtk_clist_thaw(GTK_CLIST(ctree));
372 
373 	  gtk_ctree_node_moveto(ctree, nodehist[depth-1],
374 				depth /*column*/,
375 				0.5 /*row_align*/,
376 				0.5 /*col_align*/);
377 	  /* printf("[treeopennode] '%s' ok\n", name); */
378 	  rv = 0 ;		/* opened */
379 	  GLOBALS->open_tree_nodes = xl_insert(namecache, GLOBALS->open_tree_nodes, NULL);
380 	  return rv;
381 	}
382 	else {
383 	  depth++;
384 	  create_sst_nodes_if_necessary(node);
385 	  node = gctr->children;
386 	  if(!node) break;
387 	  gctr = GTK_CTREE_ROW(node);
388 	  if(!gctr) break;
389 	  name = ++zap;
390 	  continue;
391 	}
392       }
393       node = gctr->sibling;
394       if(!node) break;
395       gctr = GTK_CTREE_ROW(node);
396     }
397      /* printf("[treeopennode] '%s' failed\n", name); */
398   } else {
399     rv = -1 ;			/* tree does not exist */
400   }
401   return rv ;
402 }
403 
dump_open_tree_nodes(FILE * wave,xl_Tree * t)404 void dump_open_tree_nodes(FILE *wave, xl_Tree *t)
405 {
406 if(t->left)
407 	{
408 	dump_open_tree_nodes(wave, t->left);
409 	}
410 
411 fprintf(wave, "[treeopen] %s\n", t->item);
412 
413 if(t->right)
414 	{
415 	dump_open_tree_nodes(wave, t->right);
416 	}
417 }
418 
generic_tree_expand_collapse_callback(int is_expand,GtkCTreeNode * node)419 static void generic_tree_expand_collapse_callback(int is_expand, GtkCTreeNode *node)
420 {
421 GtkCTreeRow **gctr;
422 int depth, i;
423 int len = 1;
424 char *tstring;
425 char hier_suffix[2];
426 int found;
427 
428 hier_suffix[0] = GLOBALS->hier_delimeter;
429 hier_suffix[1] = 0;
430 
431 if(!node) return;
432 
433 depth = GTK_CTREE_ROW(node)->level;
434 gctr = wave_alloca(depth * sizeof(GtkCTreeRow *));
435 
436 for(i=depth-1;i>=0;i--)
437 	{
438 	struct tree *t;
439 	gctr[i] = GTK_CTREE_ROW(node);
440 	t = gctr[i]->row.data;
441 	len += (strlen(t->name) + 1);
442 	node = gctr[i]->parent;
443 	}
444 
445 tstring = wave_alloca(len);
446 memset(tstring, 0, len);
447 
448 for(i=0;i<depth;i++)
449 	{
450 	struct tree *t = gctr[i]->row.data;
451 	strcat(tstring, t->name);
452 	strcat(tstring, hier_suffix);
453 	}
454 
455 
456 if(GLOBALS->open_tree_nodes) /* cut down on chatter to Tcl clients */
457 	{
458 	GLOBALS->open_tree_nodes = xl_splay(tstring, GLOBALS->open_tree_nodes);
459 	if(!strcmp(GLOBALS->open_tree_nodes->item, tstring))
460 		{
461 		found = 1;
462 		}
463 		else
464 		{
465 		found = 0;
466 		}
467 	}
468 	else
469 	{
470 	found = 0;
471 	}
472 
473 if(is_expand)
474 	{
475 	GLOBALS->open_tree_nodes = xl_insert(tstring, GLOBALS->open_tree_nodes, NULL);
476 	if(!found)
477 		{
478 		gtkwavetcl_setvar(WAVE_TCLCB_TREE_EXPAND, tstring, WAVE_TCLCB_TREE_EXPAND_FLAGS);
479 		}
480 	}
481 	else
482 	{
483 	GLOBALS->open_tree_nodes = xl_delete(tstring, GLOBALS->open_tree_nodes);
484 	if(found)
485 		{
486 		gtkwavetcl_setvar(WAVE_TCLCB_TREE_COLLAPSE, tstring, WAVE_TCLCB_TREE_COLLAPSE_FLAGS);
487 		}
488 	}
489 }
490 
tree_expand_callback(GtkCTree * ctree,GtkCTreeNode * node,gpointer user_data)491 static void tree_expand_callback(GtkCTree *ctree, GtkCTreeNode *node, gpointer user_data)
492 {
493 (void)ctree;
494 (void)user_data;
495 
496 create_sst_nodes_if_necessary(node);
497 generic_tree_expand_collapse_callback(1, node);
498 #ifdef WAVE_ALLOW_QUARTZ_FLUSH_WORKAROUND
499 #ifdef MAC_INTEGRATION
500 /* workaround for ctree not rendering properly in OSX */
501 gtk_widget_hide(GTK_WIDGET(GLOBALS->tree_treesearch_gtk2_c_1));
502 gtk_widget_show(GTK_WIDGET(GLOBALS->tree_treesearch_gtk2_c_1));
503 #endif
504 #endif
505 }
506 
tree_collapse_callback(GtkCTree * ctree,GtkCTreeNode * node,gpointer user_data)507 static void tree_collapse_callback(GtkCTree *ctree, GtkCTreeNode *node, gpointer user_data)
508 {
509 (void)ctree;
510 (void)user_data;
511 
512 generic_tree_expand_collapse_callback(0, node);
513 #ifdef WAVE_ALLOW_QUARTZ_FLUSH_WORKAROUND
514 #ifdef MAC_INTEGRATION
515 /* workaround for ctree not rendering properly in OSX */
516 gtk_widget_hide(GTK_WIDGET(GLOBALS->tree_treesearch_gtk2_c_1));
517 gtk_widget_show(GTK_WIDGET(GLOBALS->tree_treesearch_gtk2_c_1));
518 #endif
519 #endif
520 }
521 
522 
select_tree_node(char * name)523 void select_tree_node(char *name)
524 {
525 GtkCTree *ctree = GLOBALS->ctree_main;
526 
527 if(ctree && GLOBALS->any_tree_node)
528 	{
529 	int namlen = strlen(name);
530 	char *namecache = wave_alloca(namlen+1);
531 	char *name_end = name + namlen - 1;
532 	char *zap = name;
533 	GtkCTreeNode *node = GLOBALS->any_tree_node;
534 	GtkCTreeRow *gctr = GTK_CTREE_ROW(node);
535 
536 	strcpy(namecache, name);
537 
538 	while(gctr->parent)
539 		{
540 		node = gctr->parent;
541 		gctr = GTK_CTREE_ROW(node);
542 		}
543 
544 	for(;;)
545 		{
546 		struct tree *t = gctr->row.data;
547 
548 		while(*zap)
549 			{
550 			if(*zap != GLOBALS->hier_delimeter)
551 				{
552 				zap++;
553 				}
554 				else
555 				{
556 				*zap = 0;
557 				break;
558 				}
559 			}
560 
561 		if(!strcmp(t->name, name))
562 			{
563 			if(zap == name_end)
564 				{
565 				/* printf("[treeselectnode] '%s' ok\n", name); */
566 				gtk_ctree_select(ctree, node);
567 
568 				GLOBALS->sst_sig_root_treesearch_gtk2_c_1 = t;
569 				GLOBALS->sig_root_treesearch_gtk2_c_1 = t->child;
570 				fill_sig_store ();
571 
572 				return;
573 				}
574 				else
575 				{
576 				node = gctr->children;
577 				gctr = GTK_CTREE_ROW(node);
578 				if(!gctr) break;
579 
580 				name = ++zap;
581 				continue;
582 				}
583 			}
584 
585 		node = gctr->sibling;
586 		if(!node) break;
587 		gctr = GTK_CTREE_ROW(node);
588 		}
589 
590 	/* printf("[treeselectnode] '%s' failed\n", name); */
591 	}
592 }
593 
594 
595 
596 /* Callbacks for tree area when a row is selected/deselected.  */
select_row_callback(GtkWidget * widget,gint row,gint column,GdkEventButton * event,gpointer data)597 static void select_row_callback(GtkWidget *widget, gint row, gint column,
598         GdkEventButton *event, gpointer data)
599 {
600 (void)widget;
601 (void)column;
602 (void)event;
603 (void)data;
604 
605 struct tree *t;
606 GtkCTreeNode* node = gtk_ctree_node_nth(GLOBALS->ctree_main, row);
607 
608 if(node)
609 	{
610 	GtkCTreeRow **gctr;
611 	int depth, i;
612 	int len = 1;
613 	char *tstring;
614 	char hier_suffix[2];
615 
616 	hier_suffix[0] = GLOBALS->hier_delimeter;
617 	hier_suffix[1] = 0;
618 
619 	depth = GTK_CTREE_ROW(node)->level;
620 	gctr = wave_alloca(depth * sizeof(GtkCTreeRow *));
621 
622 	for(i=depth-1;i>=0;i--)
623 	        {
624 	        gctr[i] = GTK_CTREE_ROW(node);
625 	        t = gctr[i]->row.data;
626 	        len += (strlen(t->name) + 1);
627 	        node = gctr[i]->parent;
628 	        }
629 
630 	tstring = wave_alloca(len);
631 	memset(tstring, 0, len);
632 
633 	for(i=0;i<depth;i++)
634 	        {
635 	        t = gctr[i]->row.data;
636 	        strcat(tstring, t->name);
637 	        strcat(tstring, hier_suffix);
638 	        }
639 
640 	if(GLOBALS->selected_hierarchy_name)
641 		{
642 		free_2(GLOBALS->selected_hierarchy_name);
643 		}
644 	GLOBALS->selected_hierarchy_name = strdup_2(tstring);
645 	}
646 
647 t=(struct tree *)gtk_clist_get_row_data(GTK_CLIST(GLOBALS->ctree_main), row);
648 DEBUG(printf("TS: %08x %s\n",t,t->name));
649  GLOBALS->sst_sig_root_treesearch_gtk2_c_1 = t;
650  GLOBALS->sig_root_treesearch_gtk2_c_1 = t->child;
651  fill_sig_store ();
652  gtkwavetcl_setvar(WAVE_TCLCB_TREE_SELECT, GLOBALS->selected_hierarchy_name, WAVE_TCLCB_TREE_SELECT_FLAGS);
653 }
654 
unselect_row_callback(GtkWidget * widget,gint row,gint column,GdkEventButton * event,gpointer data)655 static void unselect_row_callback(GtkWidget *widget, gint row, gint column,
656         GdkEventButton *event, gpointer data)
657 {
658 (void)widget;
659 (void)column;
660 (void)event;
661 (void)data;
662 
663 struct tree *t;
664 
665 if(GLOBALS->selected_hierarchy_name)
666 	{
667 	gtkwavetcl_setvar(WAVE_TCLCB_TREE_UNSELECT, GLOBALS->selected_hierarchy_name, WAVE_TCLCB_TREE_UNSELECT_FLAGS);
668 	free_2(GLOBALS->selected_hierarchy_name);
669 	GLOBALS->selected_hierarchy_name = NULL;
670 	}
671 
672 t=(struct tree *)gtk_clist_get_row_data(GTK_CLIST(GLOBALS->ctree_main), row);
673 if(t)
674 	{
675 	/* unused */
676 	}
677 DEBUG(printf("TU: %08x %s\n",t,t->name));
678  GLOBALS->sst_sig_root_treesearch_gtk2_c_1 = NULL;
679  GLOBALS->sig_root_treesearch_gtk2_c_1 = GLOBALS->treeroot;
680  fill_sig_store ();
681 }
682 
683 /* Signal callback for the filter widget.
684    This catch the return key to update the signal area.  */
685 static
filter_edit_cb(GtkWidget * widget,GdkEventKey * ev,gpointer * data)686 gboolean filter_edit_cb (GtkWidget *widget, GdkEventKey *ev, gpointer *data)
687 {
688 (void)data;
689 
690   /* Maybe this test is too strong ?  */
691   if (ev->keyval == GDK_Return)
692     {
693       const char *t;
694 
695       /* Get the filter string, save it and change the store.  */
696       if(GLOBALS->filter_str_treesearch_gtk2_c_1)
697 	{
698       	free_2((char *)GLOBALS->filter_str_treesearch_gtk2_c_1);
699 	GLOBALS->filter_str_treesearch_gtk2_c_1 = NULL;
700 	}
701       t = gtk_entry_get_text (GTK_ENTRY (widget));
702       if (t == NULL || *t == 0)
703 	GLOBALS->filter_str_treesearch_gtk2_c_1 = NULL;
704       else
705 	{
706 	int i;
707 
708 	GLOBALS->filter_str_treesearch_gtk2_c_1 = malloc_2(strlen(t) + 1);
709 	strcpy(GLOBALS->filter_str_treesearch_gtk2_c_1, t);
710 
711 	GLOBALS->filter_typ_treesearch_gtk2_c_1 = ND_DIR_UNSPECIFIED;
712 	GLOBALS->filter_typ_polarity_treesearch_gtk2_c_1 = 0;
713 	GLOBALS->filter_matlen_treesearch_gtk2_c_1 = 0;
714 	GLOBALS->filter_noregex_treesearch_gtk2_c_1 = 0;
715 
716 	if(GLOBALS->filter_str_treesearch_gtk2_c_1[0] == '+')
717 		{
718 		for(i=0;i<=ND_DIR_MAX;i++)
719 			{
720 			int tlen = strlen(vardir_strings[i]);
721 			if(!strncasecmp(vardir_strings[i], GLOBALS->filter_str_treesearch_gtk2_c_1 + 1, tlen))
722 				{
723 				if(GLOBALS->filter_str_treesearch_gtk2_c_1[tlen + 1] == '+')
724 					{
725 					GLOBALS->filter_matlen_treesearch_gtk2_c_1 = tlen + 2;
726 					GLOBALS->filter_typ_treesearch_gtk2_c_1 = i;
727 					if(GLOBALS->filter_str_treesearch_gtk2_c_1[tlen + 2] == 0)
728 						{
729 						GLOBALS->filter_noregex_treesearch_gtk2_c_1 = 1;
730 						}
731 					}
732 				}
733 			}
734 		}
735 	else
736 	if(GLOBALS->filter_str_treesearch_gtk2_c_1[0] == '-')
737 		{
738 		for(i=0;i<=ND_DIR_MAX;i++)
739 			{
740 			int tlen = strlen(vardir_strings[i]);
741 			if(!strncasecmp(vardir_strings[i], GLOBALS->filter_str_treesearch_gtk2_c_1 + 1, tlen))
742 				{
743 				if(GLOBALS->filter_str_treesearch_gtk2_c_1[tlen + 1] == '-')
744 					{
745 					GLOBALS->filter_matlen_treesearch_gtk2_c_1 = tlen + 2;
746 					GLOBALS->filter_typ_treesearch_gtk2_c_1 = i;
747 					GLOBALS->filter_typ_polarity_treesearch_gtk2_c_1 = 1; /* invert via XOR with 1 */
748 					if(GLOBALS->filter_str_treesearch_gtk2_c_1[tlen + 2] == 0)
749 						{
750 						GLOBALS->filter_noregex_treesearch_gtk2_c_1 = 1;
751 						}
752 					}
753 				}
754 			}
755 		}
756 
757 	wave_regex_compile(GLOBALS->filter_str_treesearch_gtk2_c_1 + GLOBALS->filter_matlen_treesearch_gtk2_c_1, WAVE_REGEX_TREE);
758 	}
759       fill_sig_store ();
760     }
761   return FALSE;
762 }
763 
764 
765 /*
766  * for dynamic updates, simply fake the return key to the function above
767  */
768 static
press_callback(GtkWidget * widget,gpointer * data)769 void press_callback (GtkWidget *widget, gpointer *data)
770 {
771 GdkEventKey ev;
772 
773 ev.keyval = GDK_Return;
774 
775 filter_edit_cb (widget, &ev, data);
776 }
777 
778 
779 /*
780  * select/unselect all in treeview
781  */
treeview_select_all_callback(void)782 void treeview_select_all_callback(void)
783 {
784 GtkTreeSelection* ts = gtk_tree_view_get_selection(GTK_TREE_VIEW(GLOBALS->dnd_sigview));
785 gtk_tree_selection_select_all(ts);
786 }
787 
treeview_unselect_all_callback(void)788 void treeview_unselect_all_callback(void)
789 {
790 GtkTreeSelection* ts = gtk_tree_view_get_selection(GTK_TREE_VIEW(GLOBALS->dnd_sigview));
791 gtk_tree_selection_unselect_all(ts);
792 }
793 
794 
treebox_is_active(void)795 int treebox_is_active(void)
796 {
797 return(GLOBALS->is_active_treesearch_gtk2_c_6);
798 }
799 
800 #if 0
801 static void enter_callback_e(GtkWidget *widget, GtkWidget *nothing)
802 {
803 (void)widget;
804 (void)nothing;
805 
806   G_CONST_RETURN gchar *entry_text;
807   int len;
808   entry_text = gtk_entry_get_text(GTK_ENTRY(GLOBALS->entry_a_treesearch_gtk2_c_2));
809   entry_text = entry_text ? entry_text : "";
810   DEBUG(printf("Entry contents: %s\n", entry_text));
811   if(!(len=strlen(entry_text))) GLOBALS->entrybox_text_local_treesearch_gtk2_c_3=NULL;
812 	else strcpy((GLOBALS->entrybox_text_local_treesearch_gtk2_c_3=(char *)malloc_2(len+1)),entry_text);
813 
814   wave_gtk_grab_remove(GLOBALS->window1_treesearch_gtk2_c_3);
815   gtk_widget_destroy(GLOBALS->window1_treesearch_gtk2_c_3);
816   GLOBALS->window1_treesearch_gtk2_c_3 = NULL;
817 
818   GLOBALS->cleanup_e_treesearch_gtk2_c_3();
819 }
820 
821 static void destroy_callback_e(GtkWidget *widget, GtkWidget *nothing)
822 {
823 (void)widget;
824 (void)nothing;
825 
826   DEBUG(printf("Entry Cancel\n"));
827   GLOBALS->entrybox_text_local_treesearch_gtk2_c_3=NULL;
828   wave_gtk_grab_remove(GLOBALS->window1_treesearch_gtk2_c_3);
829   gtk_widget_destroy(GLOBALS->window1_treesearch_gtk2_c_3);
830   GLOBALS->window1_treesearch_gtk2_c_3 = NULL;
831 }
832 
833 static void entrybox_local(char *title, int width, char *default_text, int maxch, GtkSignalFunc func)
834 {
835     GtkWidget *vbox, *hbox;
836     GtkWidget *button1, *button2;
837 
838     GLOBALS->cleanup_e_treesearch_gtk2_c_3=func;
839 
840     /* fix problem where ungrab doesn't occur if button pressed + simultaneous accelerator key occurs */
841     if(GLOBALS->in_button_press_wavewindow_c_1) { gdk_pointer_ungrab(GDK_CURRENT_TIME); }
842 
843     /* create a new modal window */
844     GLOBALS->window1_treesearch_gtk2_c_3 = gtk_window_new(GLOBALS->disable_window_manager ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
845     install_focus_cb(GLOBALS->window1_treesearch_gtk2_c_3, ((char *)&GLOBALS->window1_treesearch_gtk2_c_3) - ((char *)GLOBALS));
846 
847     gtk_widget_set_usize( GTK_WIDGET (GLOBALS->window1_treesearch_gtk2_c_3), width, 60);
848     gtk_window_set_title(GTK_WINDOW (GLOBALS->window1_treesearch_gtk2_c_3), title);
849     gtkwave_signal_connect(GTK_OBJECT (GLOBALS->window1_treesearch_gtk2_c_3), "delete_event",(GtkSignalFunc) destroy_callback_e, NULL);
850 
851     vbox = gtk_vbox_new (FALSE, 0);
852     gtk_container_add (GTK_CONTAINER (GLOBALS->window1_treesearch_gtk2_c_3), vbox);
853     gtk_widget_show (vbox);
854 
855     GLOBALS->entry_a_treesearch_gtk2_c_2 = gtk_entry_new_with_max_length (maxch);
856     gtkwave_signal_connect(GTK_OBJECT(GLOBALS->entry_a_treesearch_gtk2_c_2), "activate",GTK_SIGNAL_FUNC(enter_callback_e),GLOBALS->entry_a_treesearch_gtk2_c_2);
857     gtk_entry_set_text (GTK_ENTRY (GLOBALS->entry_a_treesearch_gtk2_c_2), default_text);
858     gtk_entry_select_region (GTK_ENTRY (GLOBALS->entry_a_treesearch_gtk2_c_2),0, GTK_ENTRY(GLOBALS->entry_a_treesearch_gtk2_c_2)->text_length);
859     gtk_box_pack_start (GTK_BOX (vbox), GLOBALS->entry_a_treesearch_gtk2_c_2, TRUE, TRUE, 0);
860     gtk_widget_show (GLOBALS->entry_a_treesearch_gtk2_c_2);
861 
862     hbox = gtk_hbox_new (FALSE, 1);
863     gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
864     gtk_widget_show (hbox);
865 
866     button1 = gtk_button_new_with_label ("OK");
867     gtk_widget_set_usize(button1, 100, -1);
868     gtkwave_signal_connect(GTK_OBJECT (button1), "clicked", GTK_SIGNAL_FUNC(enter_callback_e), NULL);
869     gtk_widget_show (button1);
870     gtk_container_add (GTK_CONTAINER (hbox), button1);
871     GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT);
872     gtkwave_signal_connect_object (GTK_OBJECT (button1), "realize", (GtkSignalFunc) gtk_widget_grab_default, GTK_OBJECT (button1));
873 
874     button2 = gtk_button_new_with_label ("Cancel");
875     gtk_widget_set_usize(button2, 100, -1);
876     gtkwave_signal_connect(GTK_OBJECT (button2), "clicked", GTK_SIGNAL_FUNC(destroy_callback_e), NULL);
877     GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT);
878     gtk_widget_show (button2);
879     gtk_container_add (GTK_CONTAINER (hbox), button2);
880 
881     gtk_widget_show(GLOBALS->window1_treesearch_gtk2_c_3);
882     wave_gtk_grab_add(GLOBALS->window1_treesearch_gtk2_c_3);
883 }
884 #endif
885 
886 /***************************************************************************/
887 
888 /* Callback for insert/replace/append buttions.
889    This call-back is called for every signal selected.  */
890 
891 static void
sig_selection_foreach(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)892 sig_selection_foreach (GtkTreeModel *model,
893 		       GtkTreePath *path,
894 		       GtkTreeIter *iter,
895 		       gpointer data)
896 {
897 (void)path;
898 (void)data;
899 
900   struct tree *sel;
901   /* const enum sst_cb_action action = (enum sst_cb_action)data; */
902   int i;
903   int low, high;
904 
905   /* Get the tree.  */
906   gtk_tree_model_get (model, iter, TREE_COLUMN, &sel, -1);
907 
908   if(!sel) return;
909 
910   low = fetchlow(sel)->t_which;
911   high = fetchhigh(sel)->t_which;
912 
913   /* Add signals and vectors.  */
914   for(i=low;i<=high;i++)
915         {
916 	int len;
917         struct symbol *s, *t;
918         s=GLOBALS->facs[i];
919 	t=s->vec_root;
920 	if((t)&&(GLOBALS->autocoalesce))
921 		{
922 		if(get_s_selected(t))
923 			{
924 			set_s_selected(t,0);
925 			len=0;
926 			while(t)
927 				{
928 				len++;
929 				t=t->vec_chain;
930 				}
931 			if(len) add_vector_chain(s->vec_root, len);
932 			}
933 		}
934 		else
935 		{
936 	        AddNodeUnroll(s->n, NULL);
937 		}
938         }
939 }
940 
941 static void
sig_selection_foreach_finalize(gpointer data)942 sig_selection_foreach_finalize (gpointer data)
943 {
944  const enum sst_cb_action action = (enum sst_cb_action)data;
945 
946  if (action == SST_ACTION_REPLACE || action == SST_ACTION_INSERT || action == SST_ACTION_PREPEND)
947    {
948      Trptr tfirst=NULL, tlast=NULL;
949      Trptr t;
950      Trptr *tp = NULL;
951      int numhigh = 0;
952      int it;
953 
954      if (action == SST_ACTION_REPLACE)
955        {
956 	tfirst=GLOBALS->traces.first; tlast=GLOBALS->traces.last; /* cache for highlighting */
957        }
958 
959      GLOBALS->traces.buffercount=GLOBALS->traces.total;
960      GLOBALS->traces.buffer=GLOBALS->traces.first;
961      GLOBALS->traces.bufferlast=GLOBALS->traces.last;
962      GLOBALS->traces.first=GLOBALS->tcache_treesearch_gtk2_c_2.first;
963      GLOBALS->traces.last=GLOBALS->tcache_treesearch_gtk2_c_2.last;
964      GLOBALS->traces.total=GLOBALS->tcache_treesearch_gtk2_c_2.total;
965 
966      if (action == SST_ACTION_REPLACE)
967        {
968 	t = GLOBALS->traces.first;
969 	while(t) { if(t->flags & TR_HIGHLIGHT) { numhigh++; } t = t->t_next; }
970 	if(numhigh)
971 	        {
972 	        tp = calloc_2(numhigh, sizeof(Trptr));
973 	        t = GLOBALS->traces.first;
974 	        it = 0;
975 	        while(t) { if(t->flags & TR_HIGHLIGHT) { tp[it++] = t; } t = t->t_next; }
976 	        }
977        }
978 
979      if(action == SST_ACTION_PREPEND)
980 	{
981 	PrependBuffer();
982 	}
983 	else
984 	{
985 	PasteBuffer();
986 	}
987 
988      GLOBALS->traces.buffercount=GLOBALS->tcache_treesearch_gtk2_c_2.buffercount;
989      GLOBALS->traces.buffer=GLOBALS->tcache_treesearch_gtk2_c_2.buffer;
990      GLOBALS->traces.bufferlast=GLOBALS->tcache_treesearch_gtk2_c_2.bufferlast;
991 
992      if (action == SST_ACTION_REPLACE)
993        {
994 	for(it=0;it<numhigh;it++)
995 	        {
996 	        tp[it]->flags |= TR_HIGHLIGHT;
997 	        }
998 
999 	t = tfirst;
1000 	while(t)
1001 	        {
1002 	        t->flags &= ~TR_HIGHLIGHT;
1003 	        if(t==tlast) break;
1004 	        t=t->t_next;
1005 	        }
1006 
1007 	CutBuffer();
1008 
1009 	while(tfirst)
1010 	        {
1011 	        tfirst->flags |= TR_HIGHLIGHT;
1012 	        if(tfirst==tlast) break;
1013 	        tfirst=tfirst->t_next;
1014 	        }
1015 
1016 	if(tp)
1017 	        {
1018 	        free_2(tp);
1019 	        }
1020        }
1021    }
1022 }
1023 
1024 static void
sig_selection_foreach_preload_lx2(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)1025 sig_selection_foreach_preload_lx2
1026 		      (GtkTreeModel *model,
1027 		       GtkTreePath *path,
1028 		       GtkTreeIter *iter,
1029 		       gpointer data)
1030 {
1031 (void)path;
1032 (void)data;
1033 
1034   struct tree *sel;
1035   /* const enum sst_cb_action action = (enum sst_cb_action)data; */
1036   int i;
1037   int low, high;
1038 
1039   /* Get the tree.  */
1040   gtk_tree_model_get (model, iter, TREE_COLUMN, &sel, -1);
1041 
1042   if(!sel) return;
1043 
1044   low = fetchlow(sel)->t_which;
1045   high = fetchhigh(sel)->t_which;
1046 
1047   /* If signals are vectors, coalesces vectors if so.  */
1048   for(i=low;i<=high;i++)
1049         {
1050         struct symbol *s;
1051         s=GLOBALS->facs[i];
1052 	if(s->vec_root)
1053 		{
1054 		set_s_selected(s->vec_root, GLOBALS->autocoalesce);
1055 		}
1056         }
1057 
1058   /* LX2 */
1059   if(GLOBALS->is_lx2)
1060         {
1061         for(i=low;i<=high;i++)
1062                 {
1063                 struct symbol *s, *t;
1064                 s=GLOBALS->facs[i];
1065                 t=s->vec_root;
1066                 if((t)&&(GLOBALS->autocoalesce))
1067                         {
1068                         if(get_s_selected(t))
1069                                 {
1070                                 while(t)
1071                                         {
1072                                         if(t->n->mv.mvlfac)
1073                                                 {
1074                                                 lx2_set_fac_process_mask(t->n);
1075                                                 GLOBALS->pre_import_treesearch_gtk2_c_1++;
1076                                                 }
1077                                         t=t->vec_chain;
1078                                         }
1079                                 }
1080                         }
1081                         else
1082                         {
1083                         if(s->n->mv.mvlfac)
1084                                 {
1085                                 lx2_set_fac_process_mask(s->n);
1086                                 GLOBALS->pre_import_treesearch_gtk2_c_1++;
1087                                 }
1088                         }
1089                 }
1090         }
1091   /* LX2 */
1092 }
1093 
1094 
1095 static void
action_callback(enum sst_cb_action action)1096 action_callback(enum sst_cb_action action)
1097 {
1098   if(action == SST_ACTION_NONE) return; /* only used for double-click in signals pane of SST */
1099 
1100   GLOBALS->pre_import_treesearch_gtk2_c_1 = 0;
1101 
1102   /* once through to mass gather lx2 traces... */
1103   gtk_tree_selection_selected_foreach
1104     (GLOBALS->sig_selection_treesearch_gtk2_c_1, &sig_selection_foreach_preload_lx2, (void *)action);
1105   if(GLOBALS->pre_import_treesearch_gtk2_c_1)
1106 	{
1107         lx2_import_masked();
1108         }
1109 
1110   /* then do */
1111   if (action == SST_ACTION_INSERT || action == SST_ACTION_REPLACE || action == SST_ACTION_PREPEND)
1112     {
1113       /* Save and clear current traces.  */
1114       memcpy(&GLOBALS->tcache_treesearch_gtk2_c_2,&GLOBALS->traces,sizeof(Traces));
1115       GLOBALS->traces.total=0;
1116       GLOBALS->traces.first=GLOBALS->traces.last=NULL;
1117     }
1118 
1119   gtk_tree_selection_selected_foreach
1120     (GLOBALS->sig_selection_treesearch_gtk2_c_1, &sig_selection_foreach, (void *)action);
1121 
1122   sig_selection_foreach_finalize((void *)action);
1123 
1124   if(action == SST_ACTION_APPEND)
1125 	{
1126 	GLOBALS->traces.scroll_top = GLOBALS->traces.scroll_bottom = GLOBALS->traces.last;
1127 	}
1128   MaxSignalLength();
1129   signalarea_configure_event(GLOBALS->signalarea, NULL);
1130   wavearea_configure_event(GLOBALS->wavearea, NULL);
1131 }
1132 
insert_callback(GtkWidget * widget,GtkWidget * nothing)1133 static void insert_callback(GtkWidget *widget, GtkWidget *nothing)
1134 {
1135 (void)nothing;
1136 
1137   set_window_busy(widget);
1138   action_callback (SST_ACTION_INSERT);
1139   set_window_idle(widget);
1140 }
1141 
replace_callback(GtkWidget * widget,GtkWidget * nothing)1142 static void replace_callback(GtkWidget *widget, GtkWidget *nothing)
1143 {
1144 (void)nothing;
1145 
1146   set_window_busy(widget);
1147   action_callback (SST_ACTION_REPLACE);
1148   set_window_idle(widget);
1149 }
1150 
ok_callback(GtkWidget * widget,GtkWidget * nothing)1151 static void ok_callback(GtkWidget *widget, GtkWidget *nothing)
1152 {
1153 (void)nothing;
1154 
1155   set_window_busy(widget);
1156   action_callback (SST_ACTION_APPEND);
1157   set_window_idle(widget);
1158 }
1159 
1160 
destroy_callback(GtkWidget * widget,GtkWidget * nothing)1161 static void destroy_callback(GtkWidget *widget, GtkWidget *nothing)
1162 {
1163 (void)widget;
1164 (void)nothing;
1165 
1166   GLOBALS->is_active_treesearch_gtk2_c_6=0;
1167   gtk_widget_destroy(GLOBALS->window_treesearch_gtk2_c_12);
1168   GLOBALS->window_treesearch_gtk2_c_12 = NULL;
1169   GLOBALS->dnd_sigview = NULL;
1170   GLOBALS->gtk2_tree_frame = NULL;
1171   GLOBALS->ctree_main = NULL;
1172   GLOBALS->filter_entry = NULL; /* when treebox() SST goes away after closed and rc hide_sst is true */
1173   free_afl();
1174 
1175   if(GLOBALS->selected_hierarchy_name)
1176 	{
1177 	free_2(GLOBALS->selected_hierarchy_name);
1178 	GLOBALS->selected_hierarchy_name = NULL;
1179 	}
1180 }
1181 
1182 /**********************************************************************/
1183 
1184 static gboolean
view_selection_func(GtkTreeSelection * selection,GtkTreeModel * model,GtkTreePath * path,gboolean path_currently_selected,gpointer userdata)1185   view_selection_func (GtkTreeSelection *selection,
1186                        GtkTreeModel     *model,
1187                        GtkTreePath      *path,
1188                        gboolean          path_currently_selected,
1189                        gpointer          userdata)
1190   {
1191 (void)selection;
1192 (void)userdata;
1193 
1194     GtkTreeIter iter;
1195 
1196     if (gtk_tree_model_get_iter(model, &iter, path))
1197     {
1198       gchar *name;
1199 
1200       gtk_tree_model_get(model, &iter, 0, &name, -1);
1201 
1202       if(GLOBALS->selected_sig_name)
1203 	{
1204 	free_2(GLOBALS->selected_sig_name);
1205 	GLOBALS->selected_sig_name = NULL;
1206 	}
1207 
1208       if (!path_currently_selected)
1209       {
1210 	GLOBALS->selected_sig_name = strdup_2(name);
1211 	gtkwavetcl_setvar(WAVE_TCLCB_TREE_SIG_SELECT, name, WAVE_TCLCB_TREE_SIG_SELECT_FLAGS);
1212       }
1213       else
1214       {
1215 	gtkwavetcl_setvar(WAVE_TCLCB_TREE_SIG_UNSELECT, name, WAVE_TCLCB_TREE_SIG_UNSELECT_FLAGS);
1216       }
1217 
1218       g_free(name);
1219     }
1220     return TRUE; /* allow selection state to change */
1221   }
1222 
1223 /**********************************************************************/
1224 
button_press_event_std(GtkWidget * widget,GdkEventButton * event)1225 static gint button_press_event_std(GtkWidget *widget, GdkEventButton *event)
1226 {
1227 (void)widget;
1228 
1229 if(event->type == GDK_2BUTTON_PRESS)
1230 	{
1231 	if(GLOBALS->selected_hierarchy_name && GLOBALS->selected_sig_name)
1232 		{
1233 		char *sstr = wave_alloca(strlen(GLOBALS->selected_hierarchy_name) + strlen(GLOBALS->selected_sig_name) + 1);
1234 		strcpy(sstr, GLOBALS->selected_hierarchy_name);
1235 		strcat(sstr, GLOBALS->selected_sig_name);
1236 
1237 		gtkwavetcl_setvar(WAVE_TCLCB_TREE_SIG_DOUBLE_CLICK, sstr, WAVE_TCLCB_TREE_SIG_DOUBLE_CLICK_FLAGS);
1238 		action_callback(GLOBALS->sst_dbl_action_type);
1239 		}
1240 	}
1241 
1242 return(FALSE);
1243 }
1244 
hier_top_button_press_event_std(GtkWidget * widget,GdkEventButton * event)1245 static gint hier_top_button_press_event_std(GtkWidget *widget, GdkEventButton *event)
1246 {
1247 if((event->button == 3) && (event->type == GDK_BUTTON_PRESS))
1248         {
1249 	if(GLOBALS->sst_sig_root_treesearch_gtk2_c_1)
1250 		{
1251 	        do_sst_popup_menu (widget, event);
1252 		return(TRUE);
1253 		}
1254         }
1255 
1256 return(FALSE);
1257 }
1258 
1259 /**********************************************************************/
1260 
1261 /*
1262  * mainline..
1263  */
treebox(char * title,GtkSignalFunc func,GtkWidget * old_window)1264 void treebox(char *title, GtkSignalFunc func, GtkWidget *old_window)
1265 {
1266     GtkWidget *scrolled_win, *sig_scroll_win;
1267     GtkWidget *hbox;
1268     GtkWidget *button1, *button2, *button4, *button5;
1269     GtkWidget *frameh, *sig_frame;
1270     GtkWidget *vbox, *vpan, *filter_hbox;
1271     GtkWidget *filter_label;
1272     GtkWidget *sig_view;
1273     GtkTooltips *tooltips;
1274     GtkCList  *clist;
1275 
1276     /* fix problem where ungrab doesn't occur if button pressed + simultaneous accelerator key occurs */
1277     if(GLOBALS->in_button_press_wavewindow_c_1) { gdk_pointer_ungrab(GDK_CURRENT_TIME); }
1278 
1279     if(old_window)
1280 	{
1281 	GLOBALS->is_active_treesearch_gtk2_c_6=1;
1282     	GLOBALS->cleanup_treesearch_gtk2_c_8=func;
1283 	goto do_tooltips;
1284 	}
1285 
1286     if(GLOBALS->is_active_treesearch_gtk2_c_6)
1287 	{
1288 	if(GLOBALS->window_treesearch_gtk2_c_12)
1289 		{
1290 		gdk_window_raise(GLOBALS->window_treesearch_gtk2_c_12->window);
1291 		}
1292 		else
1293 		{
1294 #if GTK_CHECK_VERSION(2,4,0)
1295 		if(GLOBALS->expanderwindow)
1296 			{
1297 			gtk_expander_set_expanded(GTK_EXPANDER(GLOBALS->expanderwindow), TRUE);
1298 			}
1299 #endif
1300 		}
1301 	return;
1302 	}
1303 
1304     GLOBALS->is_active_treesearch_gtk2_c_6=1;
1305     GLOBALS->cleanup_treesearch_gtk2_c_8=func;
1306 
1307     /* create a new modal window */
1308     GLOBALS->window_treesearch_gtk2_c_12 = gtk_window_new(GLOBALS->disable_window_manager ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
1309     install_focus_cb(GLOBALS->window_treesearch_gtk2_c_12, ((char *)&GLOBALS->window_treesearch_gtk2_c_12) - ((char *)GLOBALS));
1310 
1311     gtk_window_set_title(GTK_WINDOW (GLOBALS->window_treesearch_gtk2_c_12), title);
1312     gtkwave_signal_connect(GTK_OBJECT (GLOBALS->window_treesearch_gtk2_c_12), "delete_event",(GtkSignalFunc) destroy_callback, NULL);
1313 
1314 do_tooltips:
1315     tooltips=gtk_tooltips_new_2();
1316 
1317     GLOBALS->treesearch_gtk2_window_vbox = vbox = gtk_vbox_new (FALSE, 1);
1318     gtk_widget_show (vbox);
1319 
1320     gtkwave_signal_connect(GTK_OBJECT(vbox), "button_press_event",GTK_SIGNAL_FUNC(hier_top_button_press_event_std), NULL);
1321 
1322     vpan = gtk_vpaned_new ();
1323     gtk_widget_show (vpan);
1324     gtk_box_pack_start (GTK_BOX (vbox), vpan, TRUE, TRUE, 1);
1325 
1326     /* Hierarchy.  */
1327     GLOBALS->gtk2_tree_frame = gtk_frame_new (NULL);
1328     gtk_container_border_width (GTK_CONTAINER (GLOBALS->gtk2_tree_frame), 3);
1329     gtk_widget_show(GLOBALS->gtk2_tree_frame);
1330 
1331     gtk_paned_pack1 (GTK_PANED (vpan), GLOBALS->gtk2_tree_frame, TRUE, FALSE);
1332 
1333     GLOBALS->tree_treesearch_gtk2_c_1=gtk_ctree_new(1,0);
1334     GLOBALS->ctree_main=GTK_CTREE(GLOBALS->tree_treesearch_gtk2_c_1);
1335     gtk_clist_set_column_auto_resize (GTK_CLIST (GLOBALS->tree_treesearch_gtk2_c_1), 0, TRUE);
1336     gtk_widget_show(GLOBALS->tree_treesearch_gtk2_c_1);
1337 
1338     gtk_clist_set_use_drag_icons(GTK_CLIST (GLOBALS->tree_treesearch_gtk2_c_1), FALSE);
1339 
1340     clist=GTK_CLIST(GLOBALS->tree_treesearch_gtk2_c_1);
1341 
1342     gtkwave_signal_connect_object (GTK_OBJECT (clist), "select_row", GTK_SIGNAL_FUNC(select_row_callback), NULL);
1343     gtkwave_signal_connect_object (GTK_OBJECT (clist), "unselect_row", GTK_SIGNAL_FUNC(unselect_row_callback), NULL);
1344     gtkwave_signal_connect_object (GTK_OBJECT (clist), "tree_expand", GTK_SIGNAL_FUNC(tree_expand_callback), NULL);
1345     gtkwave_signal_connect_object (GTK_OBJECT (clist), "tree_collapse", GTK_SIGNAL_FUNC(tree_collapse_callback), NULL);
1346 
1347     gtk_clist_freeze(clist);
1348     gtk_clist_clear(clist);
1349 
1350     decorated_module_cleanup();
1351     maketree(NULL, GLOBALS->treeroot);
1352     gtk_clist_thaw(clist);
1353 
1354     scrolled_win = gtk_scrolled_window_new (NULL, NULL);
1355     gtk_widget_set_usize( GTK_WIDGET (scrolled_win), -1, 50);
1356     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
1357                                       GTK_POLICY_AUTOMATIC,
1358                                       GTK_POLICY_AUTOMATIC);
1359     gtk_widget_show(scrolled_win);
1360     gtk_container_add (GTK_CONTAINER (scrolled_win), GTK_WIDGET (GLOBALS->tree_treesearch_gtk2_c_1));
1361     gtk_container_add (GTK_CONTAINER (GLOBALS->gtk2_tree_frame), scrolled_win);
1362 
1363 
1364     /* Signal names.  */
1365     GLOBALS->sig_store_treesearch_gtk2_c_1 = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
1366     GLOBALS->sst_sig_root_treesearch_gtk2_c_1 = NULL;
1367     GLOBALS->sig_root_treesearch_gtk2_c_1 = GLOBALS->treeroot;
1368     fill_sig_store ();
1369 
1370     sig_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (GLOBALS->sig_store_treesearch_gtk2_c_1));
1371     gtkwave_signal_connect(GTK_OBJECT(sig_view), "button_press_event",GTK_SIGNAL_FUNC(hier_top_button_press_event_std), NULL);
1372 
1373     /* The view now holds a reference.  We can get rid of our own reference */
1374     g_object_unref (G_OBJECT (GLOBALS->sig_store_treesearch_gtk2_c_1));
1375 
1376 
1377       {
1378 	GtkCellRenderer *renderer;
1379 	GtkTreeViewColumn *column;
1380 
1381 	renderer = gtk_cell_renderer_text_new ();
1382 
1383 	switch(GLOBALS->loaded_file_type)
1384 		{
1385 #ifdef EXTLOAD_SUFFIX
1386 		case EXTLOAD_FILE:
1387 #endif
1388 		case FST_FILE:
1389 					/* fallthrough for Dir is deliberate for extload and FST */
1390 					if(GLOBALS->nonimplicit_direction_encountered)
1391 						{
1392 						column = gtk_tree_view_column_new_with_attributes ("Dir",
1393 								   renderer,
1394 								   "text", DIR_COLUMN,
1395 								   NULL);
1396 						gtk_tree_view_append_column (GTK_TREE_VIEW (sig_view), column);
1397 						}
1398 					/* fallthrough */
1399 		case AE2_FILE:
1400 		case VCD_FILE:
1401 		case VCD_RECODER_FILE:
1402 		case DUMPLESS_FILE:
1403 					column = gtk_tree_view_column_new_with_attributes (((GLOBALS->supplemental_datatypes_encountered) && (GLOBALS->supplemental_vartypes_encountered)) ? "VType" : "Type",
1404 							   renderer,
1405 							   "text", TYPE_COLUMN,
1406 							   NULL);
1407 					gtk_tree_view_append_column (GTK_TREE_VIEW (sig_view), column);
1408 					if((GLOBALS->supplemental_datatypes_encountered) && (GLOBALS->supplemental_vartypes_encountered))
1409 						{
1410 						column = gtk_tree_view_column_new_with_attributes ("DType",
1411 							   renderer,
1412 							   "text", DTYPE_COLUMN,
1413 							   NULL);
1414 						gtk_tree_view_append_column (GTK_TREE_VIEW (sig_view), column);
1415 						}
1416 					break;
1417 		default:
1418 			 		break;
1419 		}
1420 
1421 	column = gtk_tree_view_column_new_with_attributes ("Signals",
1422 							   renderer,
1423 							   "text", NAME_COLUMN,
1424 							   NULL);
1425 	gtk_tree_view_append_column (GTK_TREE_VIEW (sig_view), column);
1426 
1427 
1428 	/* Setup the selection handler */
1429 	GLOBALS->sig_selection_treesearch_gtk2_c_1 = gtk_tree_view_get_selection (GTK_TREE_VIEW (sig_view));
1430 	gtk_tree_selection_set_mode (GLOBALS->sig_selection_treesearch_gtk2_c_1, GTK_SELECTION_MULTIPLE);
1431         gtk_tree_selection_set_select_function (GLOBALS->sig_selection_treesearch_gtk2_c_1,
1432                                                 view_selection_func, NULL, NULL);
1433 
1434 	gtkwave_signal_connect(GTK_OBJECT(sig_view), "button_press_event",GTK_SIGNAL_FUNC(button_press_event_std), NULL);
1435       }
1436 
1437     GLOBALS->dnd_sigview = sig_view;
1438     dnd_setup(GLOBALS->dnd_sigview, GLOBALS->signalarea, 0);
1439 
1440     sig_frame = gtk_frame_new (NULL);
1441     gtk_container_border_width (GTK_CONTAINER (sig_frame), 3);
1442     gtk_widget_show(sig_frame);
1443 
1444     gtk_paned_pack2 (GTK_PANED (vpan), sig_frame, TRUE, FALSE);
1445 
1446     sig_scroll_win = gtk_scrolled_window_new (NULL, NULL);
1447     gtk_widget_set_usize (GTK_WIDGET (sig_scroll_win), 80, 100);
1448     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sig_scroll_win),
1449                                       GTK_POLICY_AUTOMATIC,
1450                                       GTK_POLICY_AUTOMATIC);
1451     gtk_widget_show(sig_scroll_win);
1452     gtk_container_add (GTK_CONTAINER (sig_frame), sig_scroll_win);
1453     gtk_container_add (GTK_CONTAINER (sig_scroll_win), sig_view);
1454     gtk_widget_show (sig_view);
1455 
1456 
1457     /* Filter.  */
1458     filter_hbox = gtk_hbox_new (FALSE, 1);
1459     gtk_widget_show (filter_hbox);
1460 
1461     filter_label = gtk_label_new ("Filter:");
1462     gtk_widget_show (filter_label);
1463     gtk_box_pack_start (GTK_BOX (filter_hbox), filter_label, FALSE, FALSE, 1);
1464 
1465     GLOBALS->filter_entry = gtk_entry_new ();
1466     if(GLOBALS->filter_str_treesearch_gtk2_c_1)
1467 	{
1468 	gtk_entry_set_text(GTK_ENTRY(GLOBALS->filter_entry), GLOBALS->filter_str_treesearch_gtk2_c_1);
1469 	}
1470 
1471     gtk_widget_show (GLOBALS->filter_entry);
1472 
1473     gtkwave_signal_connect(GTK_OBJECT(GLOBALS->filter_entry), "activate", GTK_SIGNAL_FUNC(press_callback), NULL);
1474     if(!GLOBALS->do_dynamic_treefilter)
1475 	{
1476     	gtkwave_signal_connect(GTK_OBJECT (GLOBALS->filter_entry), "key_press_event", (GtkSignalFunc) filter_edit_cb, NULL);
1477 	}
1478 	else
1479 	{
1480     	gtkwave_signal_connect(GTK_OBJECT(GLOBALS->filter_entry), "changed", GTK_SIGNAL_FUNC(press_callback), NULL);
1481 	}
1482 
1483     gtk_tooltips_set_tip_2(tooltips, GLOBALS->filter_entry,
1484 	   "Add a POSIX filter. "
1485 	   "'.*' matches any number of characters,"
1486 	   " '.' matches any character.  Hit Return to apply."
1487 	   " The filter may be preceded with the port direction if it exists such as ++ (show only non-port), +I+, +O+, +IO+, etc."
1488 	   " Use -- to exclude all non-ports (i.e., show only all ports), -I- to exclude all input ports, etc.",
1489 	   NULL);
1490 
1491     gtk_box_pack_start (GTK_BOX (filter_hbox), GLOBALS->filter_entry, FALSE, FALSE, 1);
1492 
1493     gtk_box_pack_start (GTK_BOX (vbox), filter_hbox, FALSE, FALSE, 1);
1494 
1495     /* Buttons.  */
1496     frameh = gtk_frame_new (NULL);
1497     gtk_container_border_width (GTK_CONTAINER (frameh), 3);
1498     gtk_widget_show(frameh);
1499     gtk_box_pack_start (GTK_BOX (vbox), frameh, FALSE, FALSE, 1);
1500 
1501 
1502     hbox = gtk_hbox_new (FALSE, 1);
1503     gtk_widget_show (hbox);
1504 
1505     button1 = gtk_button_new_with_label ("Append");
1506     gtk_container_border_width (GTK_CONTAINER (button1), 3);
1507     gtkwave_signal_connect_object (GTK_OBJECT (button1), "clicked",GTK_SIGNAL_FUNC(ok_callback),GTK_OBJECT (GLOBALS->window_treesearch_gtk2_c_12));
1508     gtk_widget_show (button1);
1509     gtk_tooltips_set_tip_2(tooltips, button1,
1510 		"Add selected signal hierarchy to end of the display on the main window.",NULL);
1511 
1512     gtk_box_pack_start (GTK_BOX (hbox), button1, TRUE, FALSE, 0);
1513 
1514     button2 = gtk_button_new_with_label (" Insert ");
1515     gtk_container_border_width (GTK_CONTAINER (button2), 3);
1516     gtkwave_signal_connect_object (GTK_OBJECT (button2), "clicked",GTK_SIGNAL_FUNC(insert_callback),GTK_OBJECT (GLOBALS->window_treesearch_gtk2_c_12));
1517     gtk_widget_show (button2);
1518     gtk_tooltips_set_tip_2(tooltips, button2,
1519 		"Add selected signal hierarchy after last highlighted signal on the main window.",NULL);
1520     gtk_box_pack_start (GTK_BOX (hbox), button2, TRUE, FALSE, 0);
1521 
1522     button4 = gtk_button_new_with_label (" Replace ");
1523     gtk_container_border_width (GTK_CONTAINER (button4), 3);
1524     gtkwave_signal_connect_object (GTK_OBJECT (button4), "clicked",GTK_SIGNAL_FUNC(replace_callback),GTK_OBJECT (GLOBALS->window_treesearch_gtk2_c_12));
1525     gtk_widget_show (button4);
1526     gtk_tooltips_set_tip_2(tooltips, button4,
1527 		"Replace highlighted signals on the main window with signals selected above.",NULL);
1528     gtk_box_pack_start (GTK_BOX (hbox), button4, TRUE, FALSE, 0);
1529 
1530     button5 = gtk_button_new_with_label (" Exit ");
1531     gtk_container_border_width (GTK_CONTAINER (button5), 3);
1532     gtkwave_signal_connect_object (GTK_OBJECT (button5), "clicked",GTK_SIGNAL_FUNC(destroy_callback),GTK_OBJECT (GLOBALS->window_treesearch_gtk2_c_12));
1533     gtk_tooltips_set_tip_2(tooltips, button5,
1534 		"Do nothing and return to the main window.",NULL);
1535     gtk_widget_show (button5);
1536     gtk_box_pack_start (GTK_BOX (hbox), button5, TRUE, FALSE, 0);
1537 
1538     gtk_container_add (GTK_CONTAINER (frameh), hbox);
1539     gtk_container_add (GTK_CONTAINER (GLOBALS->window_treesearch_gtk2_c_12), vbox);
1540 
1541     gtk_window_set_default_size (GTK_WINDOW (GLOBALS->window_treesearch_gtk2_c_12), 200, 400);
1542     gtk_widget_show(GLOBALS->window_treesearch_gtk2_c_12);
1543 }
1544 
1545 
1546 /*
1547  * for use with expander in gtk2.4 and higher...
1548  */
treeboxframe(char * title,GtkSignalFunc func)1549 GtkWidget* treeboxframe(char *title, GtkSignalFunc func)
1550 {
1551 (void)title;
1552 
1553     GtkWidget *scrolled_win, *sig_scroll_win;
1554     GtkWidget *hbox;
1555     GtkWidget *button1, *button2, *button4;
1556     GtkWidget *frameh, *sig_frame;
1557     GtkWidget *vbox, *vpan, *filter_hbox;
1558     GtkWidget *filter_label;
1559     GtkWidget *sig_view;
1560     GtkTooltips *tooltips;
1561     GtkCList  *clist;
1562 
1563     GLOBALS->is_active_treesearch_gtk2_c_6=1;
1564     GLOBALS->cleanup_treesearch_gtk2_c_8=func;
1565 
1566     /* create a new modal window */
1567     tooltips=gtk_tooltips_new_2();
1568 
1569     vbox = gtk_vbox_new (FALSE, 1);
1570     gtk_widget_show (vbox);
1571 
1572     gtkwave_signal_connect(GTK_OBJECT(vbox), "button_press_event",GTK_SIGNAL_FUNC(hier_top_button_press_event_std), NULL);
1573 
1574     vpan = gtk_vpaned_new (); /* GLOBALS->sst_vpaned is to be used to clone position over during reload */
1575     GLOBALS->sst_vpaned = (GtkPaned *)vpan;
1576     if(GLOBALS->vpanedwindow_size_cache)
1577 	{
1578 	gtk_paned_set_position(GTK_PANED(GLOBALS->sst_vpaned), GLOBALS->vpanedwindow_size_cache);
1579 	GLOBALS->vpanedwindow_size_cache = 0;
1580 	}
1581     gtk_widget_show (vpan);
1582     gtk_box_pack_start (GTK_BOX (vbox), vpan, TRUE, TRUE, 1);
1583 
1584     /* Hierarchy.  */
1585     GLOBALS->gtk2_tree_frame = gtk_frame_new (NULL);
1586     gtk_container_border_width (GTK_CONTAINER (GLOBALS->gtk2_tree_frame), 3);
1587     gtk_widget_show(GLOBALS->gtk2_tree_frame);
1588 
1589     gtk_paned_pack1 (GTK_PANED (vpan), GLOBALS->gtk2_tree_frame, TRUE, FALSE);
1590 
1591     GLOBALS->tree_treesearch_gtk2_c_1=gtk_ctree_new(1,0);
1592     GLOBALS->ctree_main=GTK_CTREE(GLOBALS->tree_treesearch_gtk2_c_1);
1593     gtk_clist_set_column_auto_resize (GTK_CLIST (GLOBALS->tree_treesearch_gtk2_c_1), 0, TRUE);
1594     gtk_widget_show(GLOBALS->tree_treesearch_gtk2_c_1);
1595 
1596     clist=GTK_CLIST(GLOBALS->tree_treesearch_gtk2_c_1);
1597     gtkwave_signal_connect_object (GTK_OBJECT (clist), "select_row", GTK_SIGNAL_FUNC(select_row_callback), NULL);
1598     gtkwave_signal_connect_object (GTK_OBJECT (clist), "unselect_row", GTK_SIGNAL_FUNC(unselect_row_callback), NULL);
1599     gtkwave_signal_connect_object (GTK_OBJECT (clist), "tree_expand", GTK_SIGNAL_FUNC(tree_expand_callback), NULL);
1600     gtkwave_signal_connect_object (GTK_OBJECT (clist), "tree_collapse", GTK_SIGNAL_FUNC(tree_collapse_callback), NULL);
1601 
1602     gtk_clist_freeze(clist);
1603     gtk_clist_clear(clist);
1604 
1605     decorated_module_cleanup();
1606     maketree(NULL, GLOBALS->treeroot);
1607     gtk_clist_thaw(clist);
1608 
1609     scrolled_win = gtk_scrolled_window_new (NULL, NULL);
1610     gtk_widget_set_usize( GTK_WIDGET (scrolled_win), -1, 50);
1611     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
1612                                       GTK_POLICY_AUTOMATIC,
1613                                       GTK_POLICY_AUTOMATIC);
1614     gtk_widget_show(scrolled_win);
1615     gtk_container_add (GTK_CONTAINER (scrolled_win), GTK_WIDGET (GLOBALS->tree_treesearch_gtk2_c_1));
1616     gtk_container_add (GTK_CONTAINER (GLOBALS->gtk2_tree_frame), scrolled_win);
1617 
1618 
1619     /* Signal names.  */
1620     GLOBALS->sig_store_treesearch_gtk2_c_1 = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
1621     GLOBALS->sst_sig_root_treesearch_gtk2_c_1 = NULL;
1622     GLOBALS->sig_root_treesearch_gtk2_c_1 = GLOBALS->treeroot;
1623     fill_sig_store ();
1624 
1625     sig_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (GLOBALS->sig_store_treesearch_gtk2_c_1));
1626     gtkwave_signal_connect(GTK_OBJECT(sig_view), "button_press_event",GTK_SIGNAL_FUNC(hier_top_button_press_event_std), NULL);
1627 
1628     /* The view now holds a reference.  We can get rid of our own reference */
1629     g_object_unref (G_OBJECT (GLOBALS->sig_store_treesearch_gtk2_c_1));
1630 
1631 
1632       {
1633 	GtkCellRenderer *renderer;
1634 	GtkTreeViewColumn *column;
1635 
1636 	renderer = gtk_cell_renderer_text_new ();
1637 
1638 	switch(GLOBALS->loaded_file_type)
1639 		{
1640 #ifdef EXTLOAD_SUFFIX
1641 		case EXTLOAD_FILE:
1642 #endif
1643 		case FST_FILE:
1644 					/* fallthrough for Dir is deliberate for extload and FST */
1645 					if(GLOBALS->nonimplicit_direction_encountered)
1646 						{
1647 						column = gtk_tree_view_column_new_with_attributes ("Dir",
1648 								   renderer,
1649 								   "text", DIR_COLUMN,
1650 								   NULL);
1651 						gtk_tree_view_append_column (GTK_TREE_VIEW (sig_view), column);
1652 						}
1653 					/* fallthrough */
1654 
1655 		case AE2_FILE:
1656 		case VCD_FILE:
1657 		case VCD_RECODER_FILE:
1658 		case DUMPLESS_FILE:
1659 					column = gtk_tree_view_column_new_with_attributes (((GLOBALS->supplemental_datatypes_encountered) && (GLOBALS->supplemental_vartypes_encountered)) ? "VType" : "Type",
1660 							   renderer,
1661 							   "text", TYPE_COLUMN,
1662 							   NULL);
1663 					gtk_tree_view_append_column (GTK_TREE_VIEW (sig_view), column);
1664 					if((GLOBALS->supplemental_datatypes_encountered) && (GLOBALS->supplemental_vartypes_encountered))
1665 						{
1666 						column = gtk_tree_view_column_new_with_attributes ("DType",
1667 							   renderer,
1668 							   "text", DTYPE_COLUMN,
1669 							   NULL);
1670 						gtk_tree_view_append_column (GTK_TREE_VIEW (sig_view), column);
1671 						}
1672 					break;
1673 		default:
1674 					break;
1675 		}
1676 
1677 	column = gtk_tree_view_column_new_with_attributes ("Signals",
1678 							   renderer,
1679 							   "text", NAME_COLUMN,
1680 							   NULL);
1681 	gtk_tree_view_append_column (GTK_TREE_VIEW (sig_view), column);
1682 
1683 	/* Setup the selection handler */
1684 	GLOBALS->sig_selection_treesearch_gtk2_c_1 = gtk_tree_view_get_selection (GTK_TREE_VIEW (sig_view));
1685 	gtk_tree_selection_set_mode (GLOBALS->sig_selection_treesearch_gtk2_c_1, GTK_SELECTION_MULTIPLE);
1686         gtk_tree_selection_set_select_function (GLOBALS->sig_selection_treesearch_gtk2_c_1,
1687                                                 view_selection_func, NULL, NULL);
1688 
1689 	gtkwave_signal_connect(GTK_OBJECT(sig_view), "button_press_event",GTK_SIGNAL_FUNC(button_press_event_std), NULL);
1690       }
1691 
1692     GLOBALS->dnd_sigview = sig_view;
1693 
1694     sig_frame = gtk_frame_new (NULL);
1695     gtk_container_border_width (GTK_CONTAINER (sig_frame), 3);
1696     gtk_widget_show(sig_frame);
1697 
1698     gtk_paned_pack2 (GTK_PANED (vpan), sig_frame, TRUE, FALSE);
1699 
1700     sig_scroll_win = gtk_scrolled_window_new (NULL, NULL);
1701     gtk_widget_set_usize (GTK_WIDGET (sig_scroll_win), 80, 100);
1702     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sig_scroll_win),
1703                                       GTK_POLICY_AUTOMATIC,
1704                                       GTK_POLICY_AUTOMATIC);
1705     gtk_widget_show(sig_scroll_win);
1706     gtk_container_add (GTK_CONTAINER (sig_frame), sig_scroll_win);
1707     gtk_container_add (GTK_CONTAINER (sig_scroll_win), sig_view);
1708     gtk_widget_show (sig_view);
1709 
1710 
1711     /* Filter.  */
1712     filter_hbox = gtk_hbox_new (FALSE, 1);
1713     gtk_widget_show (filter_hbox);
1714 
1715     filter_label = gtk_label_new ("Filter:");
1716     gtk_widget_show (filter_label);
1717     gtk_box_pack_start (GTK_BOX (filter_hbox), filter_label, FALSE, FALSE, 1);
1718 
1719     GLOBALS->filter_entry = gtk_entry_new ();
1720     if(GLOBALS->filter_str_treesearch_gtk2_c_1) { gtk_entry_set_text(GTK_ENTRY(GLOBALS->filter_entry), GLOBALS->filter_str_treesearch_gtk2_c_1); }
1721     gtk_widget_show (GLOBALS->filter_entry);
1722 
1723     gtkwave_signal_connect(GTK_OBJECT(GLOBALS->filter_entry), "activate", GTK_SIGNAL_FUNC(press_callback), NULL);
1724     if(!GLOBALS->do_dynamic_treefilter)
1725 	{
1726     	gtkwave_signal_connect(GTK_OBJECT (GLOBALS->filter_entry), "key_press_event", (GtkSignalFunc) filter_edit_cb, NULL);
1727 	}
1728 	else
1729 	{
1730 	gtkwave_signal_connect(GTK_OBJECT(GLOBALS->filter_entry), "changed", GTK_SIGNAL_FUNC(press_callback), NULL);
1731 	}
1732 
1733     gtk_tooltips_set_tip_2(tooltips, GLOBALS->filter_entry,
1734 	   "Add a POSIX filter. "
1735 	   "'.*' matches any number of characters,"
1736 	   " '.' matches any character.  Hit Return to apply."
1737 	   " The filter may be preceded with the port direction if it exists such as ++ (show only non-port), +I+, +O+, +IO+, etc."
1738 	   " Use -- to exclude all non-ports (i.e., show only all ports), -I- to exclude all input ports, etc.",
1739 	   NULL);
1740 
1741     gtk_box_pack_start (GTK_BOX (filter_hbox), GLOBALS->filter_entry, FALSE, FALSE, 1);
1742 
1743     gtk_box_pack_start (GTK_BOX (vbox), filter_hbox, FALSE, FALSE, 1);
1744 
1745     /* Buttons.  */
1746     frameh = gtk_frame_new (NULL);
1747     gtk_container_border_width (GTK_CONTAINER (frameh), 3);
1748     gtk_widget_show(frameh);
1749     gtk_box_pack_start (GTK_BOX (vbox), frameh, FALSE, FALSE, 1);
1750 
1751 
1752     hbox = gtk_hbox_new (FALSE, 1);
1753     gtk_widget_show (hbox);
1754 
1755     button1 = gtk_button_new_with_label ("Append");
1756     gtk_container_border_width (GTK_CONTAINER (button1), 3);
1757     gtkwave_signal_connect_object (GTK_OBJECT (button1), "clicked", GTK_SIGNAL_FUNC(ok_callback), GTK_OBJECT (GLOBALS->gtk2_tree_frame));
1758     gtk_widget_show (button1);
1759     gtk_tooltips_set_tip_2(tooltips, button1,
1760 		"Add selected signal hierarchy to end of the display on the main window.",NULL);
1761 
1762     gtk_box_pack_start (GTK_BOX (hbox), button1, TRUE, FALSE, 0);
1763 
1764     button2 = gtk_button_new_with_label (" Insert ");
1765     gtk_container_border_width (GTK_CONTAINER (button2), 3);
1766     gtkwave_signal_connect_object (GTK_OBJECT (button2), "clicked", GTK_SIGNAL_FUNC(insert_callback), GTK_OBJECT (GLOBALS->gtk2_tree_frame));
1767     gtk_widget_show (button2);
1768     gtk_tooltips_set_tip_2(tooltips, button2,
1769 		"Add selected signal hierarchy after last highlighted signal on the main window.",NULL);
1770     gtk_box_pack_start (GTK_BOX (hbox), button2, TRUE, FALSE, 0);
1771 
1772     button4 = gtk_button_new_with_label (" Replace ");
1773     gtk_container_border_width (GTK_CONTAINER (button4), 3);
1774     gtkwave_signal_connect_object (GTK_OBJECT (button4), "clicked", GTK_SIGNAL_FUNC(replace_callback), GTK_OBJECT (GLOBALS->gtk2_tree_frame));
1775     gtk_widget_show (button4);
1776     gtk_tooltips_set_tip_2(tooltips, button4,
1777 		"Replace highlighted signals on the main window with signals selected above.",NULL);
1778     gtk_box_pack_start (GTK_BOX (hbox), button4, TRUE, FALSE, 0);
1779 
1780     gtk_container_add (GTK_CONTAINER (frameh), hbox);
1781     return vbox;
1782 }
1783 
1784 
1785 /****************************************************************
1786  **
1787  ** dnd
1788  **
1789  ****************************************************************/
1790 
1791 /*
1792  *	DND "drag_begin" handler, this is called whenever a drag starts.
1793  */
DNDBeginCB(GtkWidget * widget,GdkDragContext * dc,gpointer data)1794 static void DNDBeginCB(
1795 	GtkWidget *widget, GdkDragContext *dc, gpointer data
1796 )
1797 {
1798 (void)data;
1799 
1800         if((widget == NULL) || (dc == NULL))
1801 		return;
1802 
1803 	/* Put any needed drag begin setup code here. */
1804 	if(!GLOBALS->dnd_state)
1805 		{
1806 		if(widget == GLOBALS->clist_search_c_3)
1807 			{
1808 			GLOBALS->tree_dnd_begin = SEARCH_TO_VIEW_DRAG_ACTIVE;
1809 			}
1810 			else
1811 			{
1812 			GLOBALS->tree_dnd_begin = TREE_TO_VIEW_DRAG_ACTIVE;
1813 			}
1814 		}
1815 }
1816 
1817 /*
1818  *      DND "drag_failed" handler, this is called when a drag and drop has
1819  *      failed (e.g., by pressing ESC).
1820  */
DNDFailedCB(GtkWidget * widget,GdkDragContext * context,GtkDragResult result)1821 static gboolean DNDFailedCB(
1822         GtkWidget *widget, GdkDragContext *context, GtkDragResult result)
1823 {
1824 (void)widget;
1825 (void)context;
1826 (void)result;
1827 
1828 GLOBALS->dnd_state = 0;
1829 GLOBALS->tree_dnd_begin = VIEW_DRAG_INACTIVE;
1830 GLOBALS->tree_dnd_requested = 0;
1831 
1832 MaxSignalLength();
1833 signalarea_configure_event(GLOBALS->signalarea, NULL);
1834 wavearea_configure_event(GLOBALS->wavearea, NULL);
1835 
1836 return(FALSE);
1837 }
1838 
1839 
1840 /*
1841  *      DND "drag_end" handler, this is called when a drag and drop has
1842  *	completed. So this function is the last one to be called in
1843  *	any given DND operation.
1844  */
DNDEndCB_2(GtkWidget * widget,GdkDragContext * dc,gpointer data)1845 static void DNDEndCB_2(
1846 	GtkWidget *widget, GdkDragContext *dc, gpointer data
1847 )
1848 {
1849 (void)widget;
1850 (void)dc;
1851 (void)data;
1852 
1853 Trptr t;
1854 int trwhich, trtarget;
1855 GdkModifierType state;
1856 gdouble x, y;
1857 #ifdef WAVE_USE_GTK2
1858 gint xi, yi;
1859 #endif
1860 
1861 /* Put any needed drag end cleanup code here. */
1862 
1863 if(GLOBALS->dnd_tgt_on_signalarea_treesearch_gtk2_c_1)
1864 	{
1865 	WAVE_GDK_GET_POINTER(GLOBALS->signalarea->window, &x, &y, &xi, &yi, &state);
1866 	WAVE_GDK_GET_POINTER_COPY;
1867 
1868 	if((x<0)||(y<0)||(x>=GLOBALS->signalarea->allocation.width)||(y>=GLOBALS->signalarea->allocation.height)) return;
1869 	}
1870 else
1871 if(GLOBALS->dnd_tgt_on_wavearea_treesearch_gtk2_c_1)
1872 	{
1873 	WAVE_GDK_GET_POINTER(GLOBALS->wavearea->window, &x, &y, &xi, &yi, &state);
1874 	WAVE_GDK_GET_POINTER_COPY;
1875 
1876 	if((x<0)||(y<0)||(x>=GLOBALS->wavearea->allocation.width)||(y>=GLOBALS->wavearea->allocation.height)) return;
1877 	}
1878 else
1879 	{
1880 	return;
1881 	}
1882 
1883 
1884 if((t=GLOBALS->traces.first))
1885         {
1886         while(t)
1887                 {
1888                 t->flags&=~TR_HIGHLIGHT;
1889                 t=t->t_next;
1890                 }
1891         signalarea_configure_event(GLOBALS->signalarea, NULL);
1892         wavearea_configure_event(GLOBALS->wavearea, NULL);
1893 	}
1894 
1895 trtarget = ((int)y / (int)GLOBALS->fontheight) - 2;
1896 if(trtarget < 0)
1897 	{
1898 	Trptr tp = GLOBALS->topmost_trace ? GivePrevTrace(GLOBALS->topmost_trace): NULL;
1899 	trtarget = 0;
1900 
1901 	if(tp)
1902 		{
1903 		t = tp;
1904 		}
1905 		else
1906 		{
1907 		if(GLOBALS->tree_dnd_begin == SEARCH_TO_VIEW_DRAG_ACTIVE)
1908 			{
1909 			if(GLOBALS->window_search_c_7)
1910 				{
1911 				search_insert_callback(GLOBALS->window_search_c_7, 1 /* is prepend */);
1912 				}
1913 			}
1914 			else
1915 			{
1916 			action_callback(SST_ACTION_PREPEND);  /* prepend in this widget only ever used by this function call */
1917 			}
1918 		goto dnd_import_fini;
1919 		}
1920 	}
1921 	else
1922 	{
1923 	t=GLOBALS->topmost_trace;
1924 	}
1925 
1926 trwhich=0;
1927 while(t)
1928 	{
1929         if((trwhich<trtarget)&&(GiveNextTrace(t)))
1930         	{
1931                 trwhich++;
1932                 t=GiveNextTrace(t);
1933                 }
1934                 else
1935                 {
1936                 break;
1937                 }
1938 	}
1939 
1940 if(t)
1941 	{
1942 	t->flags |= TR_HIGHLIGHT;
1943 	}
1944 
1945 if(GLOBALS->tree_dnd_begin == SEARCH_TO_VIEW_DRAG_ACTIVE)
1946 	{
1947 	if(GLOBALS->window_search_c_7)
1948 		{
1949 		search_insert_callback(GLOBALS->window_search_c_7, 0 /* is insert */);
1950 		}
1951 	}
1952 	else
1953 	{
1954 	action_callback (SST_ACTION_INSERT);
1955 	}
1956 
1957 if(t)
1958 	{
1959 	t->flags &= ~TR_HIGHLIGHT;
1960 	}
1961 
1962 dnd_import_fini:
1963 
1964 MaxSignalLength();
1965 signalarea_configure_event(GLOBALS->signalarea, NULL);
1966 wavearea_configure_event(GLOBALS->wavearea, NULL);
1967 }
1968 
1969 
DNDEndCB(GtkWidget * widget,GdkDragContext * dc,gpointer data)1970 static void DNDEndCB(
1971 	GtkWidget *widget, GdkDragContext *dc, gpointer data
1972 )
1973 {
1974 if((widget == NULL) || (dc == NULL))
1975 	{
1976 	GLOBALS->tree_dnd_begin = VIEW_DRAG_INACTIVE;
1977 	return;
1978 	}
1979 
1980 if(GLOBALS->tree_dnd_begin == VIEW_DRAG_INACTIVE)
1981 	{
1982 	return; /* to keep cut and paste in signalwindow from conflicting */
1983 	}
1984 
1985 if(GLOBALS->tree_dnd_requested)
1986 	{
1987 	GLOBALS->tree_dnd_requested = 0;
1988 
1989 	if(GLOBALS->is_lx2 == LXT2_IS_VLIST)
1990 		{
1991 		set_window_busy(NULL);
1992 		}
1993 	DNDEndCB_2(widget, dc, data);
1994 	if(GLOBALS->is_lx2 == LXT2_IS_VLIST)
1995 		{
1996 		set_window_idle(NULL);
1997 		}
1998 	}
1999 
2000 GLOBALS->tree_dnd_begin = VIEW_DRAG_INACTIVE;
2001 }
2002 
2003 
2004 
2005 /*
2006  *	DND "drag_motion" handler, this is called whenever the
2007  *	pointer is dragging over the target widget.
2008  */
DNDDragMotionCB(GtkWidget * widget,GdkDragContext * dc,gint x,gint y,guint t,gpointer data)2009 static gboolean DNDDragMotionCB(
2010         GtkWidget *widget, GdkDragContext *dc,
2011         gint x, gint y, guint t,
2012         gpointer data
2013 )
2014 {
2015 (void)x;
2016 (void)y;
2017 (void)data;
2018 
2019 	gboolean same_widget;
2020 	GdkDragAction suggested_action;
2021 	GtkWidget *src_widget, *tar_widget;
2022         if((widget == NULL) || (dc == NULL))
2023 		{
2024                 gdk_drag_status(dc, 0, t);
2025                 return(FALSE);
2026 		}
2027 
2028 	/* Get source widget and target widget. */
2029 	src_widget = gtk_drag_get_source_widget(dc);
2030 	tar_widget = widget;
2031 
2032 	/* Note if source widget is the same as the target. */
2033 	same_widget = (src_widget == tar_widget) ? TRUE : FALSE;
2034 
2035 	GLOBALS->dnd_tgt_on_signalarea_treesearch_gtk2_c_1 = (tar_widget == GLOBALS->signalarea);
2036 	GLOBALS->dnd_tgt_on_wavearea_treesearch_gtk2_c_1 = (tar_widget == GLOBALS->wavearea);
2037 
2038 	/* If this is the same widget, our suggested action should be
2039 	 * move.  For all other case we assume copy.
2040 	 */
2041 	if(same_widget)
2042 		suggested_action = GDK_ACTION_MOVE;
2043 	else
2044 		suggested_action = GDK_ACTION_COPY;
2045 
2046 	/* Respond with default drag action (status). First we check
2047 	 * the dc's list of actions. If the list only contains
2048 	 * move, copy, or link then we select just that, otherwise we
2049 	 * return with our default suggested action.
2050 	 * If no valid actions are listed then we respond with 0.
2051 	 */
2052 
2053         /* Only move? */
2054         if(dc->actions == GDK_ACTION_MOVE)
2055             gdk_drag_status(dc, GDK_ACTION_MOVE, t);
2056         /* Only copy? */
2057         else if(dc->actions == GDK_ACTION_COPY)
2058             gdk_drag_status(dc, GDK_ACTION_COPY, t);
2059         /* Only link? */
2060         else if(dc->actions == GDK_ACTION_LINK)
2061             gdk_drag_status(dc, GDK_ACTION_LINK, t);
2062         /* Other action, check if listed in our actions list? */
2063         else if(dc->actions & suggested_action)
2064             gdk_drag_status(dc, suggested_action, t);
2065         /* All else respond with 0. */
2066         else
2067             gdk_drag_status(dc, 0, t);
2068 
2069 	return(FALSE);
2070 }
2071 
2072 /*
2073  *	DND "drag_data_get" handler, for handling requests for DND
2074  *	data on the specified widget. This function is called when
2075  *	there is need for DND data on the source, so this function is
2076  *	responsable for setting up the dynamic data exchange buffer
2077  *	(DDE as sometimes it is called) and sending it out.
2078  */
DNDDataRequestCB(GtkWidget * widget,GdkDragContext * dc,GtkSelectionData * selection_data,guint info,guint t,gpointer data)2079 static void DNDDataRequestCB(
2080 	GtkWidget *widget, GdkDragContext *dc,
2081 	GtkSelectionData *selection_data, guint info, guint t,
2082 	gpointer data
2083 )
2084 {
2085 (void)dc;
2086 (void)info;
2087 (void)t;
2088 (void)data;
2089 
2090 int upd = 0;
2091 GLOBALS->tree_dnd_requested = 1;  /* indicate that a request for data occurred... */
2092 
2093 if(widget == GLOBALS->clist_search_c_3)	/* from search */
2094 	{
2095 	char *text = add_dnd_from_searchbox();
2096 	if(text)
2097 		{
2098 		gtk_selection_data_set(selection_data,GDK_SELECTION_TYPE_STRING, 8, (guchar*)text, strlen(text));
2099 		free_2(text);
2100 		}
2101 	upd = 1;
2102 	}
2103 else if(widget == GLOBALS->signalarea)
2104 	{
2105 	char *text = add_dnd_from_signal_window();
2106 	if(text)
2107 		{
2108 		char *text2 = emit_gtkwave_savefile_formatted_entries_in_tcl_list(GLOBALS->traces.first, TRUE);
2109 		if(text2)
2110 			{
2111 			int textlen = strlen(text);
2112 			int text2len = strlen(text2);
2113 			char *pnt = calloc_2(1, textlen + text2len + 1);
2114 
2115 			memcpy(pnt, text, textlen);
2116 			memcpy(pnt + textlen, text2, text2len);
2117 
2118 			free_2(text2);
2119 			free_2(text);
2120 			text = pnt;
2121 			}
2122 
2123 		gtk_selection_data_set(selection_data,GDK_SELECTION_TYPE_STRING, 8, (guchar*)text, strlen(text));
2124 		free_2(text);
2125 		}
2126 	upd = 1;
2127 	}
2128 else if(widget == GLOBALS->dnd_sigview)
2129 	{
2130 	char *text = add_dnd_from_tree_window();
2131 	if(text)
2132 		{
2133 		gtk_selection_data_set(selection_data,GDK_SELECTION_TYPE_STRING, 8, (guchar*)text, strlen(text));
2134 		free_2(text);
2135 		}
2136 	upd = 1;
2137 	}
2138 
2139 if(upd)
2140 	{
2141 	MaxSignalLength();
2142 	signalarea_configure_event(GLOBALS->signalarea, NULL);
2143 	wavearea_configure_event(GLOBALS->wavearea, NULL);
2144 	}
2145 }
2146 
2147 /*
2148  *      DND "drag_data_received" handler. When DNDDataRequestCB()
2149  *	calls gtk_selection_data_set() to send out the data, this function
2150  *	receives it and is responsible for handling it.
2151  *
2152  *	This is also the only DND callback function where the given
2153  *	inputs may reflect those of the drop target so we need to check
2154  *	if this is the same structure or not.
2155  */
DNDDataReceivedCB(GtkWidget * widget,GdkDragContext * dc,gint x,gint y,GtkSelectionData * selection_data,guint info,guint t,gpointer data)2156 static void DNDDataReceivedCB(
2157 	GtkWidget *widget, GdkDragContext *dc,
2158 	gint x, gint y, GtkSelectionData *selection_data,
2159 	guint info, guint t, gpointer data) {
2160 (void)x;
2161 (void)y;
2162 (void)t;
2163 
2164     gboolean same;
2165     GtkWidget *source_widget;
2166 
2167     if((widget == NULL) || (data == NULL) || (dc == NULL)) return;
2168 
2169     /* Important, check if we actually got data.  Sometimes errors
2170      * occure and selection_data will be NULL.
2171      */
2172     if(selection_data == NULL)     return;
2173     if(selection_data->length < 0) return;
2174 
2175     /* Source and target widgets are the same? */
2176     source_widget = gtk_drag_get_source_widget(dc);
2177     same = (source_widget == widget) ? TRUE : FALSE;
2178     if(same)
2179 	{
2180 	/* unused */
2181 	}
2182 
2183     if(source_widget)
2184     if((source_widget == GLOBALS->clist_search_c_3) || /* from search */
2185        (source_widget == GLOBALS->signalarea) ||
2186        (source_widget == GLOBALS->dnd_sigview))
2187 		{
2188 		/* use internal mechanism instead of passing names around... */
2189 		return;
2190 		}
2191 
2192     GLOBALS->dnd_state = 0;
2193     GLOBALS->tree_dnd_requested = 0;
2194 
2195     /* Now check if the data format type is one that we support
2196      * (remember, data format type, not data type).
2197      *
2198      * We check this by testing if info matches one of the info
2199      * values that we have defined.
2200      *
2201      * Note that we can also iterate through the atoms in:
2202      *	GList *glist = dc->targets;
2203      *
2204      *	while(glist != NULL)
2205      *	{
2206      *	    gchar *name = gdk_atom_name((GdkAtom)glist->data);
2207      *	     * strcmp the name to see if it matches
2208      *	     * one that we support
2209      *	     *
2210      *	    glist = glist->next;
2211      *	}
2212      */
2213     if((info == WAVE_DRAG_TAR_INFO_0) ||
2214        (info == WAVE_DRAG_TAR_INFO_1) ||
2215        (info == WAVE_DRAG_TAR_INFO_2))
2216     {
2217     /* printf("XXX %08x '%s'\n", selection_data->data, selection_data->data); */
2218 #ifndef MAC_INTEGRATION
2219     DND_helper_quartz((char *)selection_data->data);
2220 #else
2221     if(!GLOBALS->dnd_helper_quartz)
2222         {
2223         GLOBALS->dnd_helper_quartz = strdup_2((const char *)selection_data->data);
2224         }
2225 #endif
2226     }
2227 }
2228 
2229 
DND_helper_quartz(char * data)2230 void DND_helper_quartz(char *data)
2231 {
2232 int num_found;
2233 
2234 if(!GLOBALS->splash_is_loading)
2235 	{
2236 #if GTK_CHECK_VERSION(2,4,0)
2237 	if(!GLOBALS->pFileChoose)
2238 #endif
2239 		{
2240 		if(!(num_found = process_url_list(data)))
2241 		        {
2242 		        num_found = process_tcl_list(data, TRUE);
2243 		        }
2244 
2245 		if(num_found)
2246 		        {
2247 		        MaxSignalLength();
2248 		        signalarea_configure_event(GLOBALS->signalarea, NULL);
2249 		        wavearea_configure_event(GLOBALS->wavearea, NULL);
2250 		        }
2251 		}
2252 #if GTK_CHECK_VERSION(2,4,0)
2253 		else
2254 		{
2255 	        MaxSignalLength();
2256 	        signalarea_configure_event(GLOBALS->signalarea, NULL);
2257 	        wavearea_configure_event(GLOBALS->wavearea, NULL);
2258 		}
2259 #endif
2260 	}
2261 }
2262 
2263 
2264 /*
2265  *	DND "drag_data_delete" handler, this function is called when
2266  *	the data on the source `should' be deleted (ie if the DND was
2267  *	a move).
2268  */
DNDDataDeleteCB(GtkWidget * widget,GdkDragContext * dc,gpointer data)2269 static void DNDDataDeleteCB(
2270 	GtkWidget *widget, GdkDragContext *dc, gpointer data
2271 )
2272 {
2273 (void)widget;
2274 (void)dc;
2275 (void)data;
2276 
2277 /* nothing */
2278 }
2279 
2280 
2281 /***********************/
2282 
2283 
dnd_setup(GtkWidget * src,GtkWidget * w,int enable_receive)2284 void dnd_setup(GtkWidget *src, GtkWidget *w, int enable_receive)
2285 {
2286 	GtkWidget *win = w;
2287 	GtkTargetEntry target_entry[3];
2288 
2289 	/* Realize the clist widget and make sure it has a window,
2290 	 * this will be for DND setup.
2291 	 */
2292         if(!GTK_WIDGET_NO_WINDOW(w))
2293 	{
2294 		/* DND: Set up the clist as a potential DND destination.
2295 		 * First we set up target_entry which is a sequence of of
2296 		 * structure which specify the kinds (which we define) of
2297 		 * drops accepted on this widget.
2298 		 */
2299 
2300 		/* Set up the list of data format types that our DND
2301 		 * callbacks will accept.
2302 		 */
2303 		target_entry[0].target = WAVE_DRAG_TAR_NAME_0;
2304 		target_entry[0].flags = 0;
2305 		target_entry[0].info = WAVE_DRAG_TAR_INFO_0;
2306                 target_entry[1].target = WAVE_DRAG_TAR_NAME_1;
2307                 target_entry[1].flags = 0;
2308                 target_entry[1].info = WAVE_DRAG_TAR_INFO_1;
2309                 target_entry[2].target = WAVE_DRAG_TAR_NAME_2;
2310                 target_entry[2].flags = 0;
2311                 target_entry[2].info = WAVE_DRAG_TAR_INFO_2;
2312 
2313 		/* Set the drag destination for this widget, using the
2314 		 * above target entry types, accept move's and coppies'.
2315 		 */
2316 		gtk_drag_dest_set(
2317 			w,
2318 			GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT |
2319 			GTK_DEST_DEFAULT_DROP,
2320 			target_entry,
2321 			sizeof(target_entry) / sizeof(GtkTargetEntry),
2322 			GDK_ACTION_MOVE | GDK_ACTION_COPY
2323 		);
2324 		gtkwave_signal_connect(GTK_OBJECT(w), "drag_motion", GTK_SIGNAL_FUNC(DNDDragMotionCB), win);
2325 
2326 		/* Set the drag source for this widget, allowing the user
2327 		 * to drag items off of this clist.
2328 		 */
2329 		if(src)
2330 			{
2331 			gtk_drag_source_set(
2332 				src,
2333 				GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
2334 	                        target_entry,
2335 	                        sizeof(target_entry) / sizeof(GtkTargetEntry),
2336 				GDK_ACTION_MOVE | GDK_ACTION_COPY
2337 			);
2338 			/* Set DND signals on clist. */
2339 			gtkwave_signal_connect(GTK_OBJECT(src), "drag_begin", GTK_SIGNAL_FUNC(DNDBeginCB), win);
2340 	                gtkwave_signal_connect(GTK_OBJECT(src), "drag_end", GTK_SIGNAL_FUNC(DNDEndCB), win);
2341 	                gtkwave_signal_connect(GTK_OBJECT(src), "drag_data_get", GTK_SIGNAL_FUNC(DNDDataRequestCB), win);
2342 	                gtkwave_signal_connect(GTK_OBJECT(src), "drag_data_delete", GTK_SIGNAL_FUNC(DNDDataDeleteCB), win);
2343 			gtkwave_signal_connect(GTK_OBJECT(src), "drag_failed", GTK_SIGNAL_FUNC(DNDFailedCB), win);
2344 			}
2345 
2346                 if(enable_receive) gtkwave_signal_connect(GTK_OBJECT(w),   "drag_data_received", GTK_SIGNAL_FUNC(DNDDataReceivedCB), win);
2347 	}
2348 }
2349 
2350 /***************************************************************************/
2351 
recurse_append_callback(GtkWidget * widget,gpointer data)2352 static void recurse_append_callback(GtkWidget *widget, gpointer data)
2353 {
2354 int i;
2355 
2356 if(!GLOBALS->sst_sig_root_treesearch_gtk2_c_1 || !data) return;
2357 
2358 set_window_busy(widget);
2359 
2360 for(i=GLOBALS->fetchlow;i<=GLOBALS->fetchhigh;i++)
2361         {
2362         struct symbol *s;
2363 	if(i<0) break; /* GHW */
2364         s=GLOBALS->facs[i];
2365 	if(s->vec_root)
2366 		{
2367 		set_s_selected(s->vec_root, GLOBALS->autocoalesce);
2368 		}
2369         }
2370 
2371 /* LX2 */
2372 if(GLOBALS->is_lx2)
2373 	{
2374 	int pre_import = 0;
2375 
2376 	for(i=GLOBALS->fetchlow;i<=GLOBALS->fetchhigh;i++)
2377 	        {
2378 	        struct symbol *s, *t;
2379 		if(i<0) break; /* GHW */
2380 	        s=GLOBALS->facs[i];
2381 		t=s->vec_root;
2382 		if((t)&&(GLOBALS->autocoalesce))
2383 			{
2384 			if(get_s_selected(t))
2385 				{
2386 				while(t)
2387 					{
2388 					if(t->n->mv.mvlfac)
2389 						{
2390 						lx2_set_fac_process_mask(t->n);
2391 						pre_import++;
2392 						}
2393 					t=t->vec_chain;
2394 					}
2395 				}
2396 			}
2397 			else
2398 			{
2399 			if(s->n->mv.mvlfac)
2400 				{
2401 				lx2_set_fac_process_mask(s->n);
2402 				pre_import++;
2403 				}
2404 			}
2405 	        }
2406 
2407 	if(pre_import)
2408 		{
2409 		lx2_import_masked();
2410 		}
2411 	}
2412 /* LX2 */
2413 
2414 for(i=GLOBALS->fetchlow;i<=GLOBALS->fetchhigh;i++)
2415         {
2416 	int len;
2417         struct symbol *s, *t;
2418 	if(i<0) break; /* GHW */
2419         s=GLOBALS->facs[i];
2420 	t=s->vec_root;
2421 	if((t)&&(GLOBALS->autocoalesce))
2422 		{
2423 		if(get_s_selected(t))
2424 			{
2425 			set_s_selected(t, 0);
2426 			len=0;
2427 			while(t)
2428 				{
2429 				len++;
2430 				t=t->vec_chain;
2431 				}
2432 			if(len) add_vector_chain(s->vec_root, len);
2433 			}
2434 		}
2435 		else
2436 		{
2437 	        AddNodeUnroll(s->n, NULL);
2438 		}
2439         }
2440 
2441 set_window_idle(widget);
2442 
2443 GLOBALS->traces.scroll_top = GLOBALS->traces.scroll_bottom = GLOBALS->traces.last;
2444 MaxSignalLength();
2445 signalarea_configure_event(GLOBALS->signalarea, NULL);
2446 wavearea_configure_event(GLOBALS->wavearea, NULL);
2447 }
2448 
2449 
recurse_insert_callback(GtkWidget * widget,gpointer data)2450 static void recurse_insert_callback(GtkWidget *widget, gpointer data)
2451 {
2452 Traces tcache;
2453 int i;
2454 
2455 if(!GLOBALS->sst_sig_root_treesearch_gtk2_c_1 || !data) return;
2456 
2457 memcpy(&tcache,&GLOBALS->traces,sizeof(Traces));
2458 GLOBALS->traces.total=0;
2459 GLOBALS->traces.first=GLOBALS->traces.last=NULL;
2460 
2461 set_window_busy(widget);
2462 
2463 for(i=GLOBALS->fetchlow;i<=GLOBALS->fetchhigh;i++)
2464         {
2465         struct symbol *s;
2466 	if(i<0) break; /* GHW */
2467         s=GLOBALS->facs[i];
2468 	if(s->vec_root)
2469 		{
2470 		set_s_selected(s->vec_root, GLOBALS->autocoalesce);
2471 		}
2472         }
2473 
2474 /* LX2 */
2475 if(GLOBALS->is_lx2)
2476 	{
2477 	int pre_import = 0;
2478 
2479 	for(i=GLOBALS->fetchlow;i<=GLOBALS->fetchhigh;i++)
2480 	        {
2481 	        struct symbol *s, *t;
2482 		if(i<0) break; /* GHW */
2483 	        s=GLOBALS->facs[i];
2484 		t=s->vec_root;
2485 		if((t)&&(GLOBALS->autocoalesce))
2486 			{
2487 			if(get_s_selected(t))
2488 				{
2489 				while(t)
2490 					{
2491 					if(t->n->mv.mvlfac)
2492 						{
2493 						lx2_set_fac_process_mask(t->n);
2494 						pre_import++;
2495 						}
2496 					t=t->vec_chain;
2497 					}
2498 				}
2499 			}
2500 			else
2501 			{
2502 			if(s->n->mv.mvlfac)
2503 				{
2504 				lx2_set_fac_process_mask(s->n);
2505 				pre_import++;
2506 				}
2507 			}
2508 	        }
2509 
2510 	if(pre_import)
2511 		{
2512 		lx2_import_masked();
2513 		}
2514 	}
2515 /* LX2 */
2516 
2517 for(i=GLOBALS->fetchlow;i<=GLOBALS->fetchhigh;i++)
2518         {
2519 	int len;
2520         struct symbol *s, *t;
2521 	if(i<0) break; /* GHW */
2522         s=GLOBALS->facs[i];
2523 	t=s->vec_root;
2524 	if((t)&&(GLOBALS->autocoalesce))
2525 		{
2526 		if(get_s_selected(t))
2527 			{
2528 			set_s_selected(t, 0);
2529 			len=0;
2530 			while(t)
2531 				{
2532 				len++;
2533 				t=t->vec_chain;
2534 				}
2535 			if(len) add_vector_chain(s->vec_root, len);
2536 			}
2537 		}
2538 		else
2539 		{
2540 	        AddNodeUnroll(s->n, NULL);
2541 		}
2542         }
2543 
2544 set_window_idle(widget);
2545 
2546 GLOBALS->traces.buffercount=GLOBALS->traces.total;
2547 GLOBALS->traces.buffer=GLOBALS->traces.first;
2548 GLOBALS->traces.bufferlast=GLOBALS->traces.last;
2549 GLOBALS->traces.first=tcache.first;
2550 GLOBALS->traces.last=tcache.last;
2551 GLOBALS->traces.total=tcache.total;
2552 
2553 PasteBuffer();
2554 
2555 GLOBALS->traces.buffercount=tcache.buffercount;
2556 GLOBALS->traces.buffer=tcache.buffer;
2557 GLOBALS->traces.bufferlast=tcache.bufferlast;
2558 
2559 MaxSignalLength();
2560 signalarea_configure_event(GLOBALS->signalarea, NULL);
2561 wavearea_configure_event(GLOBALS->wavearea, NULL);
2562 }
2563 
2564 
recurse_replace_callback(GtkWidget * widget,gpointer data)2565 static void recurse_replace_callback(GtkWidget *widget, gpointer data)
2566 {
2567 Traces tcache;
2568 int i;
2569 Trptr tfirst=NULL, tlast=NULL;
2570 
2571 if(!GLOBALS->sst_sig_root_treesearch_gtk2_c_1 || !data) return;
2572 
2573 memcpy(&tcache,&GLOBALS->traces,sizeof(Traces));
2574 GLOBALS->traces.total=0;
2575 GLOBALS->traces.first=GLOBALS->traces.last=NULL;
2576 
2577 set_window_busy(widget);
2578 
2579 for(i=GLOBALS->fetchlow;i<=GLOBALS->fetchhigh;i++)
2580         {
2581         struct symbol *s;
2582 	if(i<0) break; /* GHW */
2583         s=GLOBALS->facs[i];
2584 	if(s->vec_root)
2585 		{
2586 		set_s_selected(s->vec_root, GLOBALS->autocoalesce);
2587 		}
2588         }
2589 
2590 /* LX2 */
2591 if(GLOBALS->is_lx2)
2592 	{
2593 	int pre_import = 0;
2594 
2595 	for(i=GLOBALS->fetchlow;i<=GLOBALS->fetchhigh;i++)
2596 	        {
2597 	        struct symbol *s, *t;
2598 		if(i<0) break; /* GHW */
2599 	        s=GLOBALS->facs[i];
2600 		t=s->vec_root;
2601 		if((t)&&(GLOBALS->autocoalesce))
2602 			{
2603 			if(get_s_selected(t))
2604 				{
2605 				while(t)
2606 					{
2607 					if(t->n->mv.mvlfac)
2608 						{
2609 						lx2_set_fac_process_mask(t->n);
2610 						pre_import++;
2611 						}
2612 					t=t->vec_chain;
2613 					}
2614 				}
2615 			}
2616 			else
2617 			{
2618 			if(s->n->mv.mvlfac)
2619 				{
2620 				lx2_set_fac_process_mask(s->n);
2621 				pre_import++;
2622 				}
2623 			}
2624 	        }
2625 
2626 	if(pre_import)
2627 		{
2628 		lx2_import_masked();
2629 		}
2630 	}
2631 /* LX2 */
2632 
2633 for(i=GLOBALS->fetchlow;i<=GLOBALS->fetchhigh;i++)
2634         {
2635 	int len;
2636         struct symbol *s, *t;
2637 	if(i<0) break; /* GHW */
2638         s=GLOBALS->facs[i];
2639 	t=s->vec_root;
2640 	if((t)&&(GLOBALS->autocoalesce))
2641 		{
2642 		if(get_s_selected(t))
2643 			{
2644 			set_s_selected(t, 0);
2645 			len=0;
2646 			while(t)
2647 				{
2648 				len++;
2649 				t=t->vec_chain;
2650 				}
2651 			if(len) add_vector_chain(s->vec_root, len);
2652 			}
2653 		}
2654 		else
2655 		{
2656 	        AddNodeUnroll(s->n, NULL);
2657 		}
2658         }
2659 
2660 set_window_idle(widget);
2661 
2662 tfirst=GLOBALS->traces.first; tlast=GLOBALS->traces.last;       /* cache for highlighting */
2663 
2664 GLOBALS->traces.buffercount=GLOBALS->traces.total;
2665 GLOBALS->traces.buffer=GLOBALS->traces.first;
2666 GLOBALS->traces.bufferlast=GLOBALS->traces.last;
2667 GLOBALS->traces.first=tcache.first;
2668 GLOBALS->traces.last=tcache.last;
2669 GLOBALS->traces.total=tcache.total;
2670 
2671 {
2672 Trptr t = GLOBALS->traces.first;
2673 Trptr *tp = NULL;
2674 int numhigh = 0;
2675 int it;
2676 
2677 while(t) { if(t->flags & TR_HIGHLIGHT) { numhigh++; } t = t->t_next; }
2678 if(numhigh)
2679         {
2680         tp = calloc_2(numhigh, sizeof(Trptr));
2681         t = GLOBALS->traces.first;
2682         it = 0;
2683         while(t) { if(t->flags & TR_HIGHLIGHT) { tp[it++] = t; } t = t->t_next; }
2684         }
2685 
2686 PasteBuffer();
2687 
2688 GLOBALS->traces.buffercount=tcache.buffercount;
2689 GLOBALS->traces.buffer=tcache.buffer;
2690 GLOBALS->traces.bufferlast=tcache.bufferlast;
2691 
2692 for(i=0;i<numhigh;i++)
2693         {
2694         tp[i]->flags |= TR_HIGHLIGHT;
2695         }
2696 
2697 t = tfirst;
2698 while(t)
2699         {
2700         t->flags &= ~TR_HIGHLIGHT;
2701         if(t==tlast) break;
2702         t=t->t_next;
2703         }
2704 
2705 CutBuffer();
2706 
2707 while(tfirst)
2708         {
2709         tfirst->flags |= TR_HIGHLIGHT;
2710         if(tfirst==tlast) break;
2711         tfirst=tfirst->t_next;
2712         }
2713 
2714 if(tp)
2715         {
2716         free_2(tp);
2717         }
2718 }
2719 
2720 MaxSignalLength();
2721 signalarea_configure_event(GLOBALS->signalarea, NULL);
2722 wavearea_configure_event(GLOBALS->wavearea, NULL);
2723 }
2724 
2725 
recurse_import(GtkWidget * widget,guint callback_action)2726 void recurse_import(GtkWidget *widget, guint callback_action)
2727 {
2728 if(GLOBALS->sst_sig_root_treesearch_gtk2_c_1)
2729 	{
2730 	int fz;
2731 
2732 	GLOBALS->fetchlow = GLOBALS->fetchhigh = -1;
2733 	if(GLOBALS->sst_sig_root_treesearch_gtk2_c_1->child) recurse_fetch_high_low(GLOBALS->sst_sig_root_treesearch_gtk2_c_1->child);
2734 	fz = GLOBALS->fetchhigh - GLOBALS->fetchlow + 1;
2735 	void (*func)(GtkWidget *, gpointer);
2736 
2737 	switch(callback_action)
2738 		{
2739 		case WV_RECURSE_INSERT:		func = recurse_insert_callback; break;
2740 		case WV_RECURSE_REPLACE:	func = recurse_replace_callback; break;
2741 
2742 		case WV_RECURSE_APPEND:
2743 		default:			func = recurse_append_callback; break;
2744 		}
2745 
2746 	if((GLOBALS->fetchlow >= 0) && (GLOBALS->fetchhigh >= 0))
2747 		{
2748 		widget = GLOBALS->mainwindow; /* otherwise using widget passed from the menu item crashes on OSX */
2749 
2750 		if(fz > WV_RECURSE_IMPORT_WARN)
2751 			{
2752 			char recwarn[128];
2753 			sprintf(recwarn, "Really import %d facilit%s?", fz, (fz==1)?"y":"ies");
2754 
2755 			simplereqbox("Recurse Warning",300,recwarn,"Yes", "No", GTK_SIGNAL_FUNC(func), 0);
2756 			}
2757 			else
2758 			{
2759 			func(widget, (gpointer)1);
2760 			}
2761 		}
2762 	}
2763 }
2764 
2765 /***************************************************************************/
2766