1 /*
2 * Copyright (c) Tony Bybell 1999-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
10 /*
11 * note: any functions which add/remove traces must first look at
12 * the global "straces". if it's active, complain to the status
13 * window and don't do the op. same for "dnd_state".
14 */
15
16 #include "globals.h"
17 #include <config.h>
18 #include <string.h>
19 #include "gtk12compat.h"
20 #include "main.h"
21 #include "menu.h"
22 #include "vcd.h"
23 #include "vcd_saver.h"
24 #include "translate.h"
25 #include "ptranslate.h"
26 #include "ttranslate.h"
27 #include "lx2.h"
28 #include "hierpack.h"
29 #include "tcl_helper.h"
30 #include <cocoa_misc.h>
31 #include <assert.h>
32
33 #if !defined __MINGW32__ && !defined _MSC_VER
34 #include <unistd.h>
35 #include <sys/mman.h>
36 #else
37 #include <windows.h>
38 #include <io.h>
39 #endif
40
41 #ifdef _MSC_VER
42 #define strcasecmp _stricmp
43 #endif
44
45 #undef WAVE_USE_MENU_BLACKOUTS
46
47 static gtkwave_mlist_t menu_items[WV_MENU_NUMITEMS];
48 #ifdef WAVE_USE_MLIST_T
49 static GtkWidget **menu_wlist=NULL;
50 #endif
51
52 extern char *gtkwave_argv0_cached; /* for new window */
53
54 /* marshals for handling menu items vs button pressed items */
55
service_left_edge_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)56 static void service_left_edge_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
57 {
58 (void)callback_action;
59
60 service_left_edge(widget, null_data);
61 }
62
service_right_edge_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)63 static void service_right_edge_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
64 {
65 (void)callback_action;
66
67 service_right_edge(widget, null_data);
68 }
69
service_zoom_in_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)70 static void service_zoom_in_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
71 {
72 (void)callback_action;
73
74 service_zoom_in(widget, null_data);
75 }
76
service_zoom_out_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)77 static void service_zoom_out_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
78 {
79 (void)callback_action;
80
81 service_zoom_out(widget, null_data);
82 }
83
service_zoom_full_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)84 static void service_zoom_full_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
85 {
86 (void)callback_action;
87
88 service_zoom_full(widget, null_data);
89 }
90
service_zoom_fit_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)91 static void service_zoom_fit_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
92 {
93 (void)callback_action;
94
95 service_zoom_fit(widget, null_data);
96 }
97
service_zoom_left_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)98 static void service_zoom_left_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
99 {
100 (void)callback_action;
101
102 service_zoom_left(widget, null_data);
103 }
104
service_zoom_right_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)105 static void service_zoom_right_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
106 {
107 (void)callback_action;
108
109 service_zoom_right(widget, null_data);
110 }
111
service_zoom_undo_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)112 static void service_zoom_undo_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
113 {
114 (void)callback_action;
115
116 service_zoom_undo(widget, null_data);
117 }
118
fetch_right_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)119 static void fetch_right_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
120 {
121 (void)callback_action;
122
123 fetch_right(widget, null_data);
124 }
125
fetch_left_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)126 static void fetch_left_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
127 {
128 (void)callback_action;
129
130 fetch_left(widget, null_data);
131 }
132
discard_right_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)133 static void discard_right_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
134 {
135 (void)callback_action;
136
137 discard_right(widget, null_data);
138 }
139
discard_left_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)140 static void discard_left_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
141 {
142 (void)callback_action;
143
144 discard_left(widget, null_data);
145 }
146
service_right_shift_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)147 static void service_right_shift_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
148 {
149 (void)callback_action;
150
151 service_right_shift(widget, null_data);
152 }
153
service_left_shift_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)154 static void service_left_shift_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
155 {
156 (void)callback_action;
157
158 service_left_shift(widget, null_data);
159 }
160
service_right_page_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)161 static void service_right_page_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
162 {
163 (void)callback_action;
164
165 service_right_page(widget, null_data);
166 }
167
service_left_page_marshal(gpointer null_data,guint callback_action,GtkWidget * widget)168 static void service_left_page_marshal(gpointer null_data, guint callback_action, GtkWidget *widget)
169 {
170 (void)callback_action;
171
172 service_left_page(widget, null_data);
173 }
174
175 /* ruler */
176
menu_def_ruler(gpointer null_data,guint callback_action,GtkWidget * widget)177 static void menu_def_ruler(gpointer null_data, guint callback_action, GtkWidget *widget)
178 {
179 (void)null_data;
180 (void)callback_action;
181 (void)widget;
182
183 if(GLOBALS->helpbox_is_active)
184 {
185 help_text_bold("\n\nDefine Time Ruler Marks");
186 help_text(
187 " changes the ruler markings such that the Baseline marker"
188 " defines the origin and the Primary marker distance from"
189 " the Baseline marker defines the period. If either the"
190 " Baseline marker or Primary marker are not present, the"
191 " default ruler markers are used. If the Baseline marker"
192 " and Primary marker have the same value, the default ruler"
193 " markers are used."
194 );
195
196 return;
197 }
198
199 if((GLOBALS->tims.baseline>=0) && (GLOBALS->tims.marker>=0))
200 {
201 GLOBALS->ruler_origin = GLOBALS->tims.baseline;
202 GLOBALS->ruler_step = GLOBALS->tims.baseline - GLOBALS->tims.marker;
203 if(GLOBALS->ruler_step < 0) GLOBALS->ruler_step = -GLOBALS->ruler_step;
204 }
205 else
206 {
207 GLOBALS->ruler_origin = GLOBALS->ruler_step = LLDescriptor(0);
208 }
209
210 GLOBALS->signalwindow_width_dirty=1;
211 MaxSignalLength();
212 signalarea_configure_event(GLOBALS->signalarea, NULL);
213 wavearea_configure_event(GLOBALS->wavearea, NULL);
214 }
215
216
217 /* marker locking */
218
lock_marker_left(gpointer null_data,guint callback_action,GtkWidget * widget)219 static void lock_marker_left(gpointer null_data, guint callback_action, GtkWidget *widget)
220 {
221 (void)null_data;
222 (void)callback_action;
223 (void)widget;
224
225 int ent_idx = GLOBALS->named_marker_lock_idx;
226 int i;
227 int success = 0;
228
229 if(GLOBALS->helpbox_is_active)
230 {
231 help_text_bold("\n\nLock to Lesser Named Marker");
232 help_text(
233 " locks the primary marker to a named marker."
234 " If no named marker is currently selected, the last defined one is used,"
235 " otherwise the marker selected will be one lower in the alphabet, scrolling"
236 " through to the end of the alphabet on wrap."
237 " If no named marker exists, one is dropped down for 'A' and the primary"
238 " marker is locked to it."
239 );
240
241 return;
242 }
243
244 if(ent_idx < 0) ent_idx = WAVE_NUM_NAMED_MARKERS;
245 ent_idx--;
246 if(ent_idx < 0) ent_idx = WAVE_NUM_NAMED_MARKERS-1;
247
248 for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
249 {
250 if(GLOBALS->named_markers[ent_idx] >= 0)
251 {
252 success = 1;
253 break;
254 }
255
256 ent_idx--;
257 if(ent_idx < 0) ent_idx = WAVE_NUM_NAMED_MARKERS-1;
258 }
259
260 if(!success)
261 {
262 ent_idx = 0;
263 GLOBALS->named_markers[ent_idx] = GLOBALS->tims.marker;
264 }
265
266 GLOBALS->named_marker_lock_idx = ent_idx;
267 GLOBALS->tims.marker = GLOBALS->named_markers[ent_idx];
268
269 update_markertime(GLOBALS->tims.marker);
270 GLOBALS->signalwindow_width_dirty=1;
271 MaxSignalLength();
272 signalarea_configure_event(GLOBALS->signalarea, NULL);
273 wavearea_configure_event(GLOBALS->wavearea, NULL);
274 }
275
lock_marker_right(gpointer null_data,guint callback_action,GtkWidget * widget)276 static void lock_marker_right(gpointer null_data, guint callback_action, GtkWidget *widget)
277 {
278 (void)null_data;
279 (void)callback_action;
280 (void)widget;
281
282 int ent_idx = GLOBALS->named_marker_lock_idx;
283 int i;
284 int success = 0;
285
286 if(ent_idx < 0) ent_idx = -1; /* not really necessary */
287 ent_idx++;
288 if(ent_idx > (WAVE_NUM_NAMED_MARKERS-1)) ent_idx = 0;
289
290 if(GLOBALS->helpbox_is_active)
291 {
292 help_text_bold("\n\nLock to Greater Named Marker");
293 help_text(
294 " locks the primary marker to a named marker."
295 " If no named marker is currently selected, the first defined one is used,"
296 " otherwise the marker selected will be one higher in the alphabet, scrolling"
297 " through to the beginning of the alphabet on wrap."
298 " If no named marker exists, one is dropped down for 'A' and the primary"
299 " marker is locked to it."
300 );
301
302 return;
303 }
304
305 for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
306 {
307 if(GLOBALS->named_markers[ent_idx] >= 0)
308 {
309 success = 1;
310 break;
311 }
312
313 ent_idx++;
314 if(ent_idx > (WAVE_NUM_NAMED_MARKERS-1)) ent_idx = 0;
315 }
316
317 if(!success)
318 {
319 ent_idx = 0;
320 GLOBALS->named_markers[ent_idx] = GLOBALS->tims.marker;
321 }
322
323 GLOBALS->named_marker_lock_idx = ent_idx;
324 GLOBALS->tims.marker = GLOBALS->named_markers[ent_idx];
325
326 update_markertime(GLOBALS->tims.marker);
327
328 GLOBALS->signalwindow_width_dirty=1;
329 MaxSignalLength();
330 signalarea_configure_event(GLOBALS->signalarea, NULL);
331 wavearea_configure_event(GLOBALS->wavearea, NULL);
332 }
333
334
unlock_marker(gpointer null_data,guint callback_action,GtkWidget * widget)335 static void unlock_marker(gpointer null_data, guint callback_action, GtkWidget *widget)
336 {
337 (void)null_data;
338 (void)callback_action;
339 (void)widget;
340
341 if(GLOBALS->helpbox_is_active)
342 {
343 help_text_bold("\n\nUnlock from Named Marker");
344 help_text(
345 " unlocks the primary marker from the currently selected named marker."
346 );
347
348 return;
349 }
350
351 GLOBALS->named_marker_lock_idx = -1;
352
353 GLOBALS->signalwindow_width_dirty=1;
354 MaxSignalLength();
355 signalarea_configure_event(GLOBALS->signalarea, NULL);
356 wavearea_configure_event(GLOBALS->wavearea, NULL);
357 }
358
359
360 /* toggles for time dimension conversion */
361
362 #ifdef WAVE_USE_MLIST_T
menu_scale_to_td_x(GtkWidget * widget,gpointer data)363 void menu_scale_to_td_x(GtkWidget *widget, gpointer data)
364 {
365 (void)widget;
366 (void)data;
367 #else
368 void menu_scale_to_td_x(gpointer null_data, guint callback_action, GtkWidget *widget)
369 {
370 (void)null_data;
371 (void)callback_action;
372 (void)widget;
373 #endif
374
375 if(GLOBALS->helpbox_is_active)
376 {
377 help_text_bold("\n\nScale To Time Dimension: None");
378 help_text(
379 " turns off time dimension conversion."
380 );
381 }
382 else
383 {
384 #ifdef WAVE_USE_MLIST_T
385 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
386 #endif
387 {
388 GLOBALS->scale_to_time_dimension = 0;
389 set_scale_to_time_dimension_toggles();
390 signalarea_configure_event(GLOBALS->signalarea, NULL);
391 wavearea_configure_event(GLOBALS->wavearea, NULL);
392 }
393 }
394 }
395
396 #ifdef WAVE_USE_MLIST_T
397 void menu_scale_to_td_s(GtkWidget *widget, gpointer data)
398 {
399 (void)widget;
400 (void)data;
401 #else
402 void menu_scale_to_td_s(gpointer null_data, guint callback_action, GtkWidget *widget)
403 {
404 (void)null_data;
405 (void)callback_action;
406 (void)widget;
407 #endif
408
409 if(GLOBALS->helpbox_is_active)
410 {
411 help_text_bold("\n\nScale To Time Dimension: sec");
412 help_text(
413 " changes the time dimension conversion value to seconds."
414 );
415 }
416 else
417 {
418 #ifdef WAVE_USE_MLIST_T
419 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
420 #endif
421 {
422 GLOBALS->scale_to_time_dimension = 's';
423 set_scale_to_time_dimension_toggles();
424 signalarea_configure_event(GLOBALS->signalarea, NULL);
425 wavearea_configure_event(GLOBALS->wavearea, NULL);
426 }
427 }
428 }
429
430 #ifdef WAVE_USE_MLIST_T
431 void menu_scale_to_td_m(GtkWidget *widget, gpointer data)
432 {
433 (void)widget;
434 (void)data;
435 #else
436 void menu_scale_to_td_m(gpointer null_data, guint callback_action, GtkWidget *widget)
437 {
438 (void)null_data;
439 (void)callback_action;
440 (void)widget;
441 #endif
442
443 if(GLOBALS->helpbox_is_active)
444 {
445 help_text_bold("\n\nScale To Time Dimension: ms");
446 help_text(
447 " changes the time dimension conversion value to milliseconds."
448 );
449 }
450 else
451 {
452 #ifdef WAVE_USE_MLIST_T
453 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
454 #endif
455 {
456 GLOBALS->scale_to_time_dimension = 'm';
457 set_scale_to_time_dimension_toggles();
458 signalarea_configure_event(GLOBALS->signalarea, NULL);
459 wavearea_configure_event(GLOBALS->wavearea, NULL);
460 }
461 }
462 }
463
464 #ifdef WAVE_USE_MLIST_T
465 void menu_scale_to_td_u(GtkWidget *widget, gpointer data)
466 {
467 (void)widget;
468 (void)data;
469 #else
470 void menu_scale_to_td_u(gpointer null_data, guint callback_action, GtkWidget *widget)
471 {
472 (void)null_data;
473 (void)callback_action;
474 (void)widget;
475 #endif
476
477 if(GLOBALS->helpbox_is_active)
478 {
479 help_text_bold("\n\nScale To Time Dimension: us");
480 help_text(
481 " changes the time dimension conversion value to microseconds."
482 );
483 }
484 else
485 {
486 #ifdef WAVE_USE_MLIST_T
487 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
488 #endif
489 {
490 GLOBALS->scale_to_time_dimension = 'u';
491 set_scale_to_time_dimension_toggles();
492 signalarea_configure_event(GLOBALS->signalarea, NULL);
493 wavearea_configure_event(GLOBALS->wavearea, NULL);
494 }
495 }
496 }
497
498 #ifdef WAVE_USE_MLIST_T
499 void menu_scale_to_td_n(GtkWidget *widget, gpointer data)
500 {
501 (void)widget;
502 (void)data;
503 #else
504 void menu_scale_to_td_n(gpointer null_data, guint callback_action, GtkWidget *widget)
505 {
506 (void)null_data;
507 (void)callback_action;
508 (void)widget;
509 #endif
510
511 if(GLOBALS->helpbox_is_active)
512 {
513 help_text_bold("\n\nScale To Time Dimension: ns");
514 help_text(
515 " changes the time dimension conversion value to nanoseconds."
516 );
517 }
518 else
519 {
520 #ifdef WAVE_USE_MLIST_T
521 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
522 #endif
523 {
524 GLOBALS->scale_to_time_dimension = 'n';
525 set_scale_to_time_dimension_toggles();
526 signalarea_configure_event(GLOBALS->signalarea, NULL);
527 wavearea_configure_event(GLOBALS->wavearea, NULL);
528 }
529 }
530 }
531
532 #ifdef WAVE_USE_MLIST_T
533 void menu_scale_to_td_p(GtkWidget *widget, gpointer data)
534 {
535 (void)widget;
536 (void)data;
537 #else
538 void menu_scale_to_td_p(gpointer null_data, guint callback_action, GtkWidget *widget)
539 {
540 (void)null_data;
541 (void)callback_action;
542 (void)widget;
543 #endif
544
545 if(GLOBALS->helpbox_is_active)
546 {
547 help_text_bold("\n\nScale To Time Dimension: ps");
548 help_text(
549 " changes the time dimension conversion value to picoseconds."
550 );
551 }
552 else
553 {
554 #ifdef WAVE_USE_MLIST_T
555 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
556 #endif
557 {
558 GLOBALS->scale_to_time_dimension = 'p';
559 set_scale_to_time_dimension_toggles();
560 signalarea_configure_event(GLOBALS->signalarea, NULL);
561 wavearea_configure_event(GLOBALS->wavearea, NULL);
562 }
563 }
564 }
565
566 #ifdef WAVE_USE_MLIST_T
567 void menu_scale_to_td_f(GtkWidget *widget, gpointer data)
568 {
569 (void)widget;
570 (void)data;
571 #else
572 void menu_scale_to_td_f(gpointer null_data, guint callback_action, GtkWidget *widget)
573 {
574 (void)null_data;
575 (void)callback_action;
576 (void)widget;
577 #endif
578
579 if(GLOBALS->helpbox_is_active)
580 {
581 help_text_bold("\n\nScale To Time Dimension: fs");
582 help_text(
583 " changes the time dimension conversion value to femtoseconds."
584 );
585 }
586 else
587 {
588 #ifdef WAVE_USE_MLIST_T
589 if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
590 #endif
591 {
592 GLOBALS->scale_to_time_dimension = 'f';
593 set_scale_to_time_dimension_toggles();
594 signalarea_configure_event(GLOBALS->signalarea, NULL);
595 wavearea_configure_event(GLOBALS->wavearea, NULL);
596 }
597 }
598 }
599
600
601 /********** transaction procsel filter install ********/
602
603 void menu_dataformat_xlate_ttrans_1(gpointer null_data, guint callback_action, GtkWidget *widget)
604 {
605 (void)null_data;
606 (void)callback_action;
607 (void)widget;
608
609 if(GLOBALS->helpbox_is_active)
610 {
611 help_text_bold("\n\nTransaction Filter Process");
612 help_text(
613 " will enable transaction filtering on marked traces using a filter process. A requester will appear to get the filter filename."
614 );
615 return;
616 }
617
618 ttrans_searchbox("Select Transaction Filter Process");
619 }
620
621 void menu_dataformat_xlate_ttrans_0(gpointer null_data, guint callback_action, GtkWidget *widget)
622 {
623 (void)null_data;
624 (void)callback_action;
625 (void)widget;
626
627 if(GLOBALS->helpbox_is_active)
628 {
629 help_text_bold("\n\nTransaction Filter Process Disable");
630 help_text(
631 " will remove transaction filtering."
632 );
633 return;
634 }
635
636 install_ttrans_filter(0); /* disable, 0 is always NULL */
637 }
638
639 /********** procsel filter install ********/
640
641 void menu_dataformat_xlate_proc_1(gpointer null_data, guint callback_action, GtkWidget *widget)
642 {
643 (void)null_data;
644 (void)callback_action;
645 (void)widget;
646
647 if(GLOBALS->helpbox_is_active)
648 {
649 help_text_bold("\n\nTranslate Filter Process");
650 help_text(
651 " will enable translation on marked traces using a filter process. A requester will appear to get the filter filename."
652 );
653 return;
654 }
655
656 ptrans_searchbox("Select Signal Filter Process");
657 }
658
659 void menu_dataformat_xlate_proc_0(gpointer null_data, guint callback_action, GtkWidget *widget)
660 {
661 (void)null_data;
662 (void)callback_action;
663 (void)widget;
664
665 if(GLOBALS->helpbox_is_active)
666 {
667 help_text_bold("\n\nTranslate Filter Process Disable");
668 help_text(
669 " will remove translation filtering used to reconstruct"
670 " enums for marked traces."
671 );
672 return;
673 }
674
675 install_proc_filter(0); /* disable, 0 is always NULL */
676 }
677
678 /********** filesel filter install ********/
679
680 void menu_dataformat_xlate_file_1(gpointer null_data, guint callback_action, GtkWidget *widget)
681 {
682 (void)null_data;
683 (void)callback_action;
684 (void)widget;
685
686 if(GLOBALS->helpbox_is_active)
687 {
688 help_text_bold("\n\nTranslate Filter File");
689 help_text(
690 " will enable translation on marked traces using a filter file. A requester will appear to get the filter filename."
691 );
692 return;
693 }
694
695 trans_searchbox("Select Signal Filter");
696 }
697
698
699 void menu_dataformat_xlate_file_0(gpointer null_data, guint callback_action, GtkWidget *widget)
700 {
701 (void)null_data;
702 (void)callback_action;
703 (void)widget;
704
705 if(GLOBALS->helpbox_is_active)
706 {
707 help_text_bold("\n\nTranslate Filter File Disable");
708 help_text(
709 " will remove translation filtering used to reconstruct"
710 " enums for marked traces."
711 );
712 return;
713 }
714
715 install_file_filter(0); /* disable, 0 is always NULL */
716 }
717
718
719 /******************************************************************/
720
721 void menu_write_lxt_file_cleanup(GtkWidget *widget, gpointer data)
722 {
723 (void)widget;
724 (void)data;
725
726 int rc;
727
728 if(!GLOBALS->filesel_ok)
729 {
730 return;
731 }
732
733 if(GLOBALS->lock_menu_c_1 == 1) return; /* avoid recursion */
734 GLOBALS->lock_menu_c_1 = 1;
735
736 status_text("Saving LXT...\n");
737 gtkwave_main_iteration(); /* make requester disappear requester */
738
739 rc = save_nodes_to_export(*GLOBALS->fileselbox_text, WAVE_EXPORT_LXT);
740
741 GLOBALS->lock_menu_c_1 = 0;
742
743 switch(rc)
744 {
745 case VCDSAV_EMPTY: status_text("No traces onscreen to save!\n");
746 break;
747
748 case VCDSAV_FILE_ERROR: status_text("Problem writing LXT: ");
749 status_text(strerror(errno));
750 break;
751
752 case VCDSAV_OK: status_text("LXT written successfully.\n");
753 default: break;
754 }
755 }
756
757 void
758 menu_write_lxt_file(gpointer null_data, guint callback_action, GtkWidget *widget)
759 {
760 (void)null_data;
761 (void)callback_action;
762 (void)widget;
763
764 if(GLOBALS->helpbox_is_active)
765 {
766 help_text_bold("\n\nWrite LXT File As");
767 help_text(
768 " will open a file requester that will ask for the name"
769 " of an LXT dumpfile. The contents of the dumpfile"
770 " generated will be the vcd representation of the traces onscreen"
771 " that can be seen by manipulating the signal and wavewindow scrollbars."
772 " The data saved corresponds to the trace information needed"
773 " to allow viewing when used in tandem with the corresponding GTKWave save file."
774 );
775 return;
776 }
777
778 if(GLOBALS->traces.first)
779 {
780 if((GLOBALS->is_ghw)&&(0))
781 {
782 status_text("LXT export not supported for GHW.\n");
783 }
784 else
785 {
786 fileselbox("Write LXT File As",&GLOBALS->filesel_lxt_writesave,GTK_SIGNAL_FUNC(menu_write_lxt_file_cleanup), GTK_SIGNAL_FUNC(NULL),"*.lxt", 1);
787 }
788 }
789 else
790 {
791 status_text("No traces onscreen to save!\n");
792 }
793 }
794
795
796 /******************************************************************/
797
798 void menu_write_vcd_file_cleanup(GtkWidget *widget, gpointer data)
799 {
800 (void)widget;
801 (void)data;
802
803 int rc;
804
805 if(!GLOBALS->filesel_ok)
806 {
807 return;
808 }
809
810 if(GLOBALS->lock_menu_c_2 == 1) return; /* avoid recursion */
811 GLOBALS->lock_menu_c_2 = 1;
812
813 status_text("Saving VCD...\n");
814 gtkwave_main_iteration(); /* make requester disappear requester */
815
816 rc = save_nodes_to_export(*GLOBALS->fileselbox_text, WAVE_EXPORT_VCD);
817
818 GLOBALS->lock_menu_c_2 = 0;
819
820 switch(rc)
821 {
822 case VCDSAV_EMPTY: status_text("No traces onscreen to save!\n");
823 break;
824
825 case VCDSAV_FILE_ERROR: status_text("Problem writing VCD: ");
826 status_text(strerror(errno));
827 break;
828
829 case VCDSAV_OK: status_text("VCD written successfully.\n");
830 default: break;
831 }
832 }
833
834 void
835 menu_write_vcd_file(gpointer null_data, guint callback_action, GtkWidget *widget)
836 {
837 (void)null_data;
838 (void)callback_action;
839 (void)widget;
840
841 if(GLOBALS->helpbox_is_active)
842 {
843 help_text_bold("\n\nWrite VCD File As");
844 help_text(
845 " will open a file requester that will ask for the name"
846 " of a VCD dumpfile. The contents of the dumpfile"
847 " generated will be the vcd representation of the traces onscreen"
848 " that can be seen by manipulating the signal and wavewindow scrollbars."
849 " The data saved corresponds to the trace information needed"
850 " to allow viewing when used in tandem with the corresponding GTKWave save file."
851 );
852 return;
853 }
854
855 if(GLOBALS->traces.first)
856 {
857 fileselbox("Write VCD File As",&GLOBALS->filesel_vcd_writesave,GTK_SIGNAL_FUNC(menu_write_vcd_file_cleanup), GTK_SIGNAL_FUNC(NULL),"*.vcd", 1);
858 }
859 else
860 {
861 status_text("No traces onscreen to save!\n");
862 }
863 }
864
865 /******************************************************************/
866
867 void menu_write_tim_file_cleanup(GtkWidget *widget, gpointer data)
868 {
869 (void)widget;
870 (void)data;
871
872 int rc;
873
874 if(!GLOBALS->filesel_ok)
875 {
876 return;
877 }
878
879 if(GLOBALS->lock_menu_c_2 == 1) return; /* avoid recursion */
880 GLOBALS->lock_menu_c_2 = 1;
881
882 status_text("Saving TIM...\n");
883 gtkwave_main_iteration(); /* make requester disappear requester */
884
885 rc = save_nodes_to_export(*GLOBALS->fileselbox_text, WAVE_EXPORT_TIM);
886
887 GLOBALS->lock_menu_c_2 = 0;
888
889 switch(rc)
890 {
891 case VCDSAV_EMPTY: status_text("No traces onscreen to save!\n");
892 break;
893
894 case VCDSAV_FILE_ERROR: status_text("Problem writing TIM: ");
895 status_text(strerror(errno));
896 break;
897
898 case VCDSAV_OK: status_text("TIM written successfully.\n");
899 default: break;
900 }
901 }
902
903 void
904 menu_write_tim_file(gpointer null_data, guint callback_action, GtkWidget *widget)
905 {
906 (void)null_data;
907 (void)callback_action;
908 (void)widget;
909
910 if(GLOBALS->helpbox_is_active)
911 {
912 help_text_bold("\n\nWrite TIM File As");
913 help_text(
914 " will open a file requester that will ask for the name"
915 " of a TimingAnalyzer .tim file. The contents of the file"
916 " generated will be the representation of the traces onscreen."
917 " If the baseline and primary marker are set, the time range"
918 " written to the file will be between the two markers, otherwise"
919 " it will be the entire time range."
920 );
921 return;
922 }
923
924 if(GLOBALS->traces.first)
925 {
926 fileselbox("Write TIM File As",&GLOBALS->filesel_tim_writesave,GTK_SIGNAL_FUNC(menu_write_tim_file_cleanup), GTK_SIGNAL_FUNC(NULL),"*.tim", 1);
927 }
928 else
929 {
930 status_text("No traces onscreen to save!\n");
931 }
932 }
933
934
935 /******************************************************************/
936
937 void menu_unwarp_traces_all(gpointer null_data, guint callback_action, GtkWidget *widget)
938 {
939 (void)null_data;
940 (void)callback_action;
941 (void)widget;
942
943 Trptr t;
944 int found=0;
945
946 if(GLOBALS->helpbox_is_active)
947 {
948 help_text_bold("\n\nUnwarp All");
949 help_text(
950 " unconditionally removes all offsets on all traces."
951 );
952 return;
953 }
954
955 t=GLOBALS->traces.first;
956 while(t)
957 {
958 if(t->shift)
959 {
960 t->shift=LLDescriptor(0);
961 found++;
962 }
963 t=t->t_next;
964 }
965
966 if(found)
967 {
968 GLOBALS->signalwindow_width_dirty=1;
969 MaxSignalLength();
970 signalarea_configure_event(GLOBALS->signalarea, NULL);
971 wavearea_configure_event(GLOBALS->wavearea, NULL);
972 }
973 }
974
975 void menu_unwarp_traces(gpointer null_data, guint callback_action, GtkWidget *widget)
976 {
977 (void)null_data;
978 (void)callback_action;
979 (void)widget;
980
981 Trptr t;
982 int found=0;
983
984 if(GLOBALS->helpbox_is_active)
985 {
986 help_text_bold("\n\nUnwarp Marked");
987 help_text(
988 " removes all offsets on all highlighted traces."
989 );
990 return;
991 }
992
993 t=GLOBALS->traces.first;
994 while(t)
995 {
996 if(t->flags&TR_HIGHLIGHT)
997 {
998 t->shift=LLDescriptor(0);
999 t->flags&=(~TR_HIGHLIGHT);
1000 found++;
1001 }
1002 t=t->t_next;
1003 }
1004
1005 if(found)
1006 {
1007 GLOBALS->signalwindow_width_dirty=1;
1008 MaxSignalLength();
1009 signalarea_configure_event(GLOBALS->signalarea, NULL);
1010 wavearea_configure_event(GLOBALS->wavearea, NULL);
1011 }
1012 }
1013
1014 void warp_cleanup(GtkWidget *widget, gpointer data)
1015 {
1016 (void)widget;
1017 (void)data;
1018
1019 if(GLOBALS->entrybox_text)
1020 {
1021 TimeType gt, delta;
1022 Trptr t;
1023
1024 gt=unformat_time(GLOBALS->entrybox_text, GLOBALS->time_dimension);
1025 free_2(GLOBALS->entrybox_text);
1026 GLOBALS->entrybox_text=NULL;
1027
1028 if(gt<0)
1029 {
1030 delta=GLOBALS->tims.first-GLOBALS->tims.last;
1031 if(gt<delta) gt=delta;
1032 }
1033 else
1034 if(gt>0)
1035 {
1036 delta=GLOBALS->tims.last-GLOBALS->tims.first;
1037 if(gt>delta) gt=delta;
1038 }
1039
1040 t=GLOBALS->traces.first;
1041 while(t)
1042 {
1043 if(t->flags&TR_HIGHLIGHT)
1044 {
1045 if(HasWave(t)) /* though note if a user specifies comment warping in a .sav file we will honor it.. */
1046 {
1047 t->shift=gt;
1048 }
1049 else
1050 {
1051 t->shift=LLDescriptor(0);
1052 }
1053 t->flags&=(~TR_HIGHLIGHT);
1054 }
1055 t=t->t_next;
1056 }
1057 }
1058
1059 GLOBALS->signalwindow_width_dirty=1;
1060 MaxSignalLength();
1061 signalarea_configure_event(GLOBALS->signalarea, NULL);
1062 wavearea_configure_event(GLOBALS->wavearea, NULL);
1063 }
1064
1065 void menu_warp_traces(gpointer null_data, guint callback_action, GtkWidget *widget)
1066 {
1067 (void)null_data;
1068 (void)callback_action;
1069 (void)widget;
1070
1071 char gt[32];
1072 Trptr t;
1073 int found=0;
1074
1075 if(GLOBALS->helpbox_is_active)
1076 {
1077 help_text_bold("\n\nWarp Marked");
1078 help_text(
1079 " offsets all highlighted traces by the amount of"
1080 " time entered in the requester. (Positive values"
1081 " will shift traces to the right.)"
1082 " Attempting to shift greater than the absolute value of total simulation"
1083 " time will cap the shift magnitude at the length of simulation."
1084 " Note that you can also warp traces dynamically by holding"
1085 " down CTRL and dragging a group of highlighted traces to"
1086 " the left or right with the left mouse button pressed. When you release"
1087 " the mouse button, if CTRL is pressed, the drag warp commits, else"
1088 " it reverts to its pre-drag condition."
1089 );
1090 return;
1091 }
1092
1093
1094 t=GLOBALS->traces.first;
1095 while(t)
1096 {
1097 if(t->flags&TR_HIGHLIGHT)
1098 {
1099 found++;
1100 break;
1101 }
1102 t=t->t_next;
1103 }
1104
1105 if(found)
1106 {
1107 reformat_time(gt, LLDescriptor(0), GLOBALS->time_dimension);
1108 entrybox("Warp Traces",200,gt,NULL,20,GTK_SIGNAL_FUNC(warp_cleanup));
1109 }
1110 }
1111
1112
1113
1114
1115 void menu_altwheel(gpointer null_data, guint callback_action, GtkWidget *widget)
1116 {
1117 (void)null_data;
1118 (void)callback_action;
1119 (void)widget;
1120
1121 if(GLOBALS->helpbox_is_active)
1122 {
1123 help_text_bold("\n\nAlternate Wheel Mode");
1124 help_text(
1125 " makes the mouse wheel act how TomB expects it to."
1126 " Wheel alone will pan part of a page (so you can still"
1127 " see where you were). Ctrl+Wheel will zoom around the"
1128 " cursor (not where the marker is), and Alt+Wheel will"
1129 " edge left or right on the selected signal.");
1130 }
1131 else
1132 {
1133 #ifndef WAVE_USE_MLIST_T
1134 if(!GLOBALS->alt_wheel_mode)
1135 {
1136 status_text("Alternate Wheel Mode On.\n");
1137 GLOBALS->alt_wheel_mode=1;
1138 }
1139 else
1140 {
1141 status_text("Alternate Wheel Mode Off.\n");
1142 GLOBALS->alt_wheel_mode=0;
1143 }
1144 #else
1145 GLOBALS->alt_wheel_mode = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_HSWM]));
1146 if(GLOBALS->alt_wheel_mode)
1147 {
1148 status_text("Alternate Wheel Mode On.\n");
1149 }
1150 else
1151 {
1152 status_text("Alternate Wheel Mode Off.\n");
1153 }
1154 #endif
1155 }
1156 #ifndef WAVE_USE_MLIST_T
1157 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_HSWM].path))->active=(GLOBALS->alt_wheel_mode)?TRUE:FALSE;
1158 #endif
1159 }
1160
1161
1162
1163
1164 void wave_scrolling_on(gpointer null_data, guint callback_action, GtkWidget *widget)
1165 {
1166 (void)null_data;
1167 (void)callback_action;
1168 (void)widget;
1169
1170 if(GLOBALS->helpbox_is_active)
1171 {
1172 help_text_bold("\n\nWave Scrolling");
1173 help_text(
1174 " allows movement of the primary marker beyond screen boundaries"
1175 " which causes the wave window to scroll when enabled."
1176 " When disabled, it"
1177 " disallows movement of the primary marker beyond screen boundaries."
1178 );
1179 }
1180 else
1181 {
1182 #ifndef WAVE_USE_MLIST_T
1183 if(!GLOBALS->wave_scrolling)
1184 {
1185 status_text("Wave Scrolling On.\n");
1186 GLOBALS->wave_scrolling=1;
1187 }
1188 else
1189 {
1190 status_text("Wave Scrolling Off.\n");
1191 GLOBALS->wave_scrolling=0;
1192 }
1193 #else
1194 GLOBALS->wave_scrolling = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_MWSON]));
1195 if(GLOBALS->wave_scrolling)
1196 {
1197 status_text("Wave Scrolling On.\n");
1198 }
1199 else
1200 {
1201 status_text("Wave Scrolling Off.\n");
1202 }
1203 #endif
1204 }
1205 #ifndef WAVE_USE_MLIST_T
1206 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_MWSON].path))->active=(GLOBALS->wave_scrolling)?TRUE:FALSE;
1207 #endif
1208 }
1209
1210
1211
1212
1213 /**/
1214
1215 void menu_keep_xz_colors(gpointer null_data, guint callback_action, GtkWidget *widget)
1216 {
1217 (void)null_data;
1218 (void)callback_action;
1219 (void)widget;
1220
1221 if(GLOBALS->helpbox_is_active)
1222 {
1223 help_text_bold("\n\nKeep xz Colors");
1224 help_text(
1225 " when enabled"
1226 " keeps the old non 0/1 signal value colors when a user specifies a color override"
1227 " by using Edit/Color Format."
1228 );
1229 }
1230 else
1231 {
1232 #ifndef WAVE_USE_MLIST_T
1233 if(!GLOBALS->keep_xz_colors)
1234 {
1235 GLOBALS->keep_xz_colors=1;
1236 }
1237 else
1238 {
1239 GLOBALS->keep_xz_colors=0;
1240 }
1241 #else
1242 GLOBALS->keep_xz_colors = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_KEEPXZ]));
1243 #endif
1244 }
1245
1246 #ifndef WAVE_USE_MLIST_T
1247 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_KEEPXZ].path))->active=(GLOBALS->keep_xz_colors)?TRUE:FALSE;
1248 #endif
1249
1250 GLOBALS->signalwindow_width_dirty=1;
1251 MaxSignalLength();
1252 signalarea_configure_event(GLOBALS->signalarea, NULL);
1253 wavearea_configure_event(GLOBALS->wavearea, NULL);
1254 }
1255
1256 /**/
1257
1258 void menu_autocoalesce(gpointer null_data, guint callback_action, GtkWidget *widget)
1259 {
1260 (void)null_data;
1261 (void)callback_action;
1262 (void)widget;
1263
1264 if(GLOBALS->helpbox_is_active)
1265 {
1266 help_text_bold("\n\nAutocoalesce");
1267 help_text(
1268 " when enabled"
1269 " allows the wave viewer to reconstruct split vectors."
1270 " Split vectors will be indicated by a \"[]\""
1271 " prefix in the search requesters."
1272 );
1273 }
1274 else
1275 {
1276 #ifndef WAVE_USE_MLIST_T
1277 if(!GLOBALS->autocoalesce)
1278 {
1279 status_text("Autocoalesce On.\n");
1280 GLOBALS->autocoalesce=1;
1281 }
1282 else
1283 {
1284 status_text("Autocoalesce Off.\n");
1285 GLOBALS->autocoalesce=0;
1286 }
1287 #else
1288 GLOBALS->autocoalesce = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_ACOL]));
1289 if(GLOBALS->autocoalesce)
1290 {
1291 status_text("Autocoalesce On.\n");
1292 }
1293 else
1294 {
1295 status_text("Autocoalesce Off.\n");
1296 }
1297 #endif
1298 }
1299
1300 #ifndef WAVE_USE_MLIST_T
1301 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_ACOL].path))->active=(GLOBALS->autocoalesce)?TRUE:FALSE;
1302 #endif
1303 }
1304
1305 void menu_autocoalesce_reversal(gpointer null_data, guint callback_action, GtkWidget *widget)
1306 {
1307 (void)null_data;
1308 (void)callback_action;
1309 (void)widget;
1310
1311 if(GLOBALS->helpbox_is_active)
1312 {
1313 help_text_bold("\n\nAutocoalesce Reversal");
1314 help_text(
1315 " causes split vectors to be reconstructed in reverse order (only if autocoalesce is also active). This is necessary with some simulators."
1316 " Split vectors will be indicated by a \"[]\""
1317 " prefix in the search requesters."
1318 );
1319 }
1320 else
1321 {
1322 #ifndef WAVE_USE_MLIST_T
1323 if(!GLOBALS->autocoalesce_reversal)
1324 {
1325 status_text("Autocoalesce Rvs On.\n");
1326 GLOBALS->autocoalesce_reversal=1;
1327 }
1328 else
1329 {
1330 status_text("Autocoalesce Rvs Off.\n");
1331 GLOBALS->autocoalesce_reversal=0;
1332 }
1333 #else
1334 GLOBALS->autocoalesce_reversal = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_ACOLR]));
1335 if(GLOBALS->autocoalesce_reversal)
1336 {
1337 status_text("Autocoalesce Rvs On.\n");
1338 }
1339 else
1340 {
1341 status_text("Autocoalesce Rvs Off.\n");
1342 }
1343 #endif
1344 }
1345
1346 #ifndef WAVE_USE_MLIST_T
1347 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_ACOLR].path))->active=(GLOBALS->autocoalesce_reversal)?TRUE:FALSE;
1348 #endif
1349 }
1350
1351 void menu_autoname_bundles_on(gpointer null_data, guint callback_action, GtkWidget *widget)
1352 {
1353 (void)null_data;
1354 (void)callback_action;
1355 (void)widget;
1356
1357 if(GLOBALS->helpbox_is_active)
1358 {
1359 help_text_bold("\n\nAutoname Bundles");
1360 help_text(
1361 " when enabled"
1362 " modifies the bundle up/down operations in the hierarchy"
1363 " and tree searches such that a NULL bundle name is"
1364 " implicitly created which informs GTKWave to create bundle"
1365 " and signal names based on the position in the hierarchy."
1366 " When disabled, it"
1367 " modifies the bundle up/down operations in the hierarchy"
1368 " and tree searches such that a NULL bundle name is"
1369 " not implicitly created. This informs GTKWave to create bundle"
1370 " and signal names based on the position in the hierarchy"
1371 " only if the user enters a zero-length bundle name. This"
1372 " behavior is the default."
1373 );
1374 }
1375 else
1376 {
1377 #ifndef WAVE_USE_MLIST_T
1378 if(!GLOBALS->autoname_bundles)
1379 {
1380 status_text("Autoname On.\n");
1381 GLOBALS->autoname_bundles=1;
1382 }
1383 else
1384 {
1385 status_text("Autoname Off.\n");
1386 GLOBALS->autoname_bundles=0;
1387 }
1388 #else
1389 GLOBALS->autoname_bundles = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_ABON]));
1390 if(GLOBALS->autoname_bundles)
1391 {
1392 status_text("Autoname On.\n");
1393 }
1394 else
1395 {
1396 status_text("Autoname Off.\n");
1397 }
1398 #endif
1399 }
1400
1401 #ifndef WAVE_USE_MLIST_T
1402 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_ABON].path))->active=(GLOBALS->autoname_bundles)?TRUE:FALSE;
1403 #endif
1404 }
1405
1406
1407 void menu_hgrouping(gpointer null_data, guint callback_action, GtkWidget *widget)
1408 {
1409 (void)null_data;
1410 (void)callback_action;
1411 (void)widget;
1412
1413 if(GLOBALS->helpbox_is_active)
1414 {
1415 help_text_bold("\n\nSearch Hierarchy Grouping");
1416 help_text(
1417 " when enabled ensures that new members added to the ``Tree Search'' and"
1418 " ``Hierarchy Search'' widgets are added alphanumerically: first hierarchy names as a group followed by signal names as a group."
1419 " This is the default and is recommended. When disabled, hierarchy names and signal names are interleaved together in"
1420 " strict alphanumerical ordering."
1421 " Note that due to the caching mechanism in ``Tree Search'', dynamically changing this flag when the widget is active"
1422 " may not produce immediately obvious results. Closing the widget then opening it up again will ensure that it follows the"
1423 " behavior of this flag."
1424 );
1425 }
1426 else
1427 {
1428 #ifndef WAVE_USE_MLIST_T
1429 if(!GLOBALS->hier_grouping)
1430 {
1431 status_text("Hier Grouping On.\n");
1432 GLOBALS->hier_grouping=1;
1433 }
1434 else
1435 {
1436 status_text("Hier Grouping Off.\n");
1437 GLOBALS->hier_grouping=0;
1438 }
1439 #else
1440 GLOBALS->hier_grouping = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_HTGP]));
1441 if(GLOBALS->hier_grouping)
1442 {
1443 status_text("Hier Grouping On.\n");
1444 }
1445 else
1446 {
1447 status_text("Hier Grouping Off.\n");
1448 }
1449 #endif
1450 }
1451
1452 #ifndef WAVE_USE_MLIST_T
1453 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_HTGP].path))->active=(GLOBALS->hier_grouping)?TRUE:FALSE;
1454 #endif
1455 }
1456
1457
1458 void set_hier_cleanup(GtkWidget *widget, gpointer data, int level)
1459 {
1460 (void)widget;
1461 (void)data;
1462
1463 char update_string[128];
1464 Trptr t;
1465 int i;
1466
1467 GLOBALS->hier_max_level=level;
1468 if(GLOBALS->hier_max_level<0) GLOBALS->hier_max_level=0;
1469
1470 for(i=0;i<2;i++)
1471 {
1472 if(i==0) t=GLOBALS->traces.first; else t=GLOBALS->traces.buffer;
1473
1474 while(t)
1475 {
1476 if(!(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH)))
1477 {
1478 if (HasAlias(t))
1479 {
1480 t->name = t->name_full;
1481 if(GLOBALS->hier_max_level)
1482 t->name = hier_extract(t->name, GLOBALS->hier_max_level);
1483 }
1484 else if(t->vector==TRUE)
1485 {
1486 t->name = t->n.vec->bvname;
1487 if(GLOBALS->hier_max_level)
1488 t->name = hier_extract(t->name, GLOBALS->hier_max_level);
1489 }
1490 else
1491 {
1492 if(!GLOBALS->hier_max_level)
1493 {
1494 int flagged = HIER_DEPACK_ALLOC;
1495
1496 if(t->name&&t->is_depacked) { free_2(t->name); }
1497 t->name = hier_decompress_flagged(t->n.nd->nname, &flagged);
1498 t->is_depacked = (flagged != 0);
1499 }
1500 else
1501 {
1502 int flagged = HIER_DEPACK_ALLOC;
1503 char *tbuff;
1504
1505 if(t->name&&t->is_depacked) { free_2(t->name); }
1506 tbuff = hier_decompress_flagged(t->n.nd->nname, &flagged);
1507 t->is_depacked = (flagged != 0);
1508
1509 if(!flagged)
1510 {
1511 t->name = hier_extract(t->n.nd->nname, GLOBALS->hier_max_level);
1512 }
1513 else
1514 {
1515 t->name = strdup_2(hier_extract(tbuff, GLOBALS->hier_max_level));
1516 free_2(tbuff);
1517 }
1518 }
1519 }
1520 }
1521 t=t->t_next;
1522 }
1523 }
1524
1525 GLOBALS->signalwindow_width_dirty=1;
1526 MaxSignalLength();
1527 signalarea_configure_event(GLOBALS->signalarea, NULL);
1528 wavearea_configure_event(GLOBALS->wavearea, NULL);
1529 sprintf(update_string, "Trace Hier Max Depth is now: %d\n", GLOBALS->hier_max_level);
1530 status_text(update_string);
1531
1532 }
1533
1534 void max_hier_cleanup(GtkWidget *widget, gpointer data)
1535 {
1536 if(GLOBALS->entrybox_text)
1537 {
1538 int i;
1539
1540 i = atoi_64(GLOBALS->entrybox_text);
1541 set_hier_cleanup(widget, data, i);
1542 GLOBALS->hier_max_level_shadow = GLOBALS->hier_max_level; /* used for the toggle function */
1543
1544 free_2(GLOBALS->entrybox_text);
1545 GLOBALS->entrybox_text=NULL;
1546 }
1547 }
1548
1549
1550 void menu_set_max_hier(gpointer null_data, guint callback_action, GtkWidget *widget)
1551 {
1552 (void)null_data;
1553 (void)callback_action;
1554 (void)widget;
1555
1556 char za[32];
1557
1558 if(GLOBALS->helpbox_is_active)
1559 {
1560 help_text_bold("\n\nSet Max Hier");
1561 help_text(
1562 " sets the maximum hierarchy depth (counting from the right"
1563 " with bit numbers or ranges ignored) that is displayable"
1564 " for trace names. Zero indicates that no truncation will"
1565 " be performed (default). Note that any aliased signals"
1566 " (prefix of a \"+\") will not have truncated names."
1567 );
1568 return;
1569 }
1570
1571
1572 sprintf(za,"%d",GLOBALS->hier_max_level);
1573
1574 entrybox("Max Hier Depth",200,za,NULL,20,GTK_SIGNAL_FUNC(max_hier_cleanup));
1575 }
1576
1577 void menu_toggle_hier(gpointer null_data, guint callback_action, GtkWidget *widget)
1578 {
1579 (void)callback_action;
1580
1581 if(GLOBALS->helpbox_is_active)
1582 {
1583 help_text_bold("\n\nToggle Trace Hier");
1584 help_text(
1585 " toggles the maximum hierarchy depth from zero to whatever was previously set."
1586 );
1587 return;
1588 }
1589
1590 if (GLOBALS->hier_max_level)
1591 set_hier_cleanup(widget, null_data, 0);
1592 else
1593 set_hier_cleanup(widget, null_data, GLOBALS->hier_max_level_shadow); /* instead of just '1' */
1594 }
1595
1596
1597 /**/
1598 void menu_use_roundcaps(gpointer null_data, guint callback_action, GtkWidget *widget)
1599 {
1600 (void)null_data;
1601 (void)callback_action;
1602 (void)widget;
1603
1604 if(GLOBALS->helpbox_is_active)
1605 {
1606 help_text_bold("\n\nDraw Roundcapped Vectors");
1607 help_text(
1608 " draws vector transitions that have sloping edges when enabled."
1609 " Draws vector transitions that have sharp edges when disabled;"
1610 " this is the default."
1611 );
1612 }
1613 else
1614 {
1615 #ifndef WAVE_USE_MLIST_T
1616 if(!GLOBALS->use_roundcaps)
1617 {
1618 status_text("Using roundcaps.\n");
1619 GLOBALS->use_roundcaps=1;
1620 }
1621 else
1622 {
1623 status_text("Using flatcaps.\n");
1624 GLOBALS->use_roundcaps=0;
1625 }
1626 MaxSignalLength();
1627 signalarea_configure_event(GLOBALS->signalarea, NULL);
1628 wavearea_configure_event(GLOBALS->wavearea, NULL);
1629 #else
1630 GLOBALS->use_roundcaps = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VDRV]));
1631 if(GLOBALS->use_roundcaps)
1632 {
1633 status_text("Using roundcaps.\n");
1634 }
1635 else
1636 {
1637 status_text("Using flatcaps.\n");
1638 }
1639 if(GLOBALS->signalarea && GLOBALS->wavearea)
1640 {
1641 MaxSignalLength();
1642 signalarea_configure_event(GLOBALS->signalarea, NULL);
1643 wavearea_configure_event(GLOBALS->wavearea, NULL);
1644 }
1645 #endif
1646 }
1647
1648 #ifndef WAVE_USE_MLIST_T
1649 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VDRV].path))->active=(GLOBALS->use_roundcaps)?TRUE:FALSE;
1650 #endif
1651 }
1652
1653 /**/
1654 void menu_lxt_clk_compress(gpointer null_data, guint callback_action, GtkWidget *widget)
1655 {
1656 (void)null_data;
1657 (void)callback_action;
1658 (void)widget;
1659
1660 if(GLOBALS->helpbox_is_active)
1661 {
1662 help_text_bold("\n\nLXT Clock Compress to Z");
1663 help_text(
1664 " reduces memory usage when active as clocks compressed in LXT format are"
1665 " kept at Z in order to save memory. Traces imported with this are permanently"
1666 " kept at Z."
1667 );
1668 }
1669 else
1670 {
1671 #ifndef WAVE_USE_MLIST_T
1672 if(GLOBALS->lxt_clock_compress_to_z)
1673 {
1674 GLOBALS->lxt_clock_compress_to_z=0;
1675 status_text("LXT CC2Z Off.\n");
1676 }
1677 else
1678 {
1679 GLOBALS->lxt_clock_compress_to_z=1;
1680 status_text("LXT CC2Z On.\n");
1681 }
1682 #else
1683 GLOBALS->lxt_clock_compress_to_z = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_LXTCC2Z]));
1684 if(!GLOBALS->lxt_clock_compress_to_z)
1685 {
1686 status_text("LXT CC2Z Off.\n");
1687 }
1688 else
1689 {
1690 status_text("LXT CC2Z On.\n");
1691 }
1692 #endif
1693 }
1694
1695 #ifndef WAVE_USE_MLIST_T
1696 if(GLOBALS->loaded_file_type == LXT_FILE)
1697 {
1698 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_LXTCC2Z].path))->active=(GLOBALS->lxt_clock_compress_to_z)?TRUE:FALSE;
1699 }
1700 #endif
1701 }
1702 /**/
1703 void menu_use_full_precision(gpointer null_data, guint callback_action, GtkWidget *widget)
1704 {
1705 (void)null_data;
1706 (void)callback_action;
1707 (void)widget;
1708
1709 if(GLOBALS->helpbox_is_active)
1710 {
1711 help_text_bold("\n\nFull Precision");
1712 help_text(
1713 " does not round time values when the number of ticks per pixel onscreen is greater than"
1714 " 10 when active. The default is that this feature is disabled."
1715 );
1716 }
1717 else
1718 {
1719 #ifndef WAVE_USE_MLIST_T
1720 if(GLOBALS->use_full_precision)
1721 {
1722 GLOBALS->use_full_precision=0;
1723 status_text("Full Prec Off.\n");
1724 }
1725 else
1726 {
1727 GLOBALS->use_full_precision=1;
1728 status_text("Full Prec On.\n");
1729 }
1730 #else
1731 GLOBALS->use_full_precision = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VFTP]));
1732 if(!GLOBALS->use_full_precision)
1733 {
1734 status_text("Full Prec Off.\n");
1735 }
1736 else
1737 {
1738 status_text("Full Prec On.\n");
1739 }
1740 #endif
1741
1742 calczoom(GLOBALS->tims.zoom);
1743 fix_wavehadj();
1744
1745 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "changed"); /* force zoom update */
1746 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "value_changed"); /* force zoom update */
1747 update_maxmarker_labels();
1748 }
1749
1750 #ifndef WAVE_USE_MLIST_T
1751 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VFTP].path))->active=(GLOBALS->use_full_precision)?TRUE:FALSE;
1752 #endif
1753 }
1754 /**/
1755 void menu_remove_marked(gpointer null_data, guint callback_action, GtkWidget *widget)
1756 {
1757 (void)null_data;
1758 (void)callback_action;
1759 (void)widget;
1760
1761 if(GLOBALS->helpbox_is_active)
1762 {
1763 help_text_bold("\n\nRemove Pattern Marks");
1764 help_text(
1765 " removes any vertical traces on the display caused by the Mark"
1766 " feature in pattern search and reverts to the normal format."
1767 );
1768 }
1769 else
1770 {
1771 int i;
1772
1773 WAVE_STRACE_ITERATOR(i)
1774 {
1775 GLOBALS->strace_ctx = &GLOBALS->strace_windows[GLOBALS->strace_current_window = i];
1776
1777 if(GLOBALS->strace_ctx->shadow_straces)
1778 {
1779 delete_strace_context();
1780 }
1781
1782 strace_maketimetrace(0);
1783 }
1784
1785 MaxSignalLength();
1786 signalarea_configure_event(GLOBALS->signalarea, NULL);
1787 wavearea_configure_event(GLOBALS->wavearea, NULL);
1788 }
1789 }
1790 /**/
1791 void menu_use_color(gpointer null_data, guint callback_action, GtkWidget *widget)
1792 {
1793 (void)null_data;
1794 (void)callback_action;
1795 (void)widget;
1796
1797 if(GLOBALS->helpbox_is_active)
1798 {
1799 help_text_bold("\n\nUse Color");
1800 help_text(
1801 " draws signal names and trace data in color. This is normal operation."
1802 );
1803 }
1804 else
1805 {
1806 force_normal_gcs();
1807
1808 MaxSignalLength();
1809 signalarea_configure_event(GLOBALS->signalarea, NULL);
1810 wavearea_configure_event(GLOBALS->wavearea, NULL);
1811 }
1812 }
1813 /**/
1814 void menu_use_bw(gpointer null_data, guint callback_action, GtkWidget *widget)
1815 {
1816 (void)null_data;
1817 (void)callback_action;
1818 (void)widget;
1819
1820 if(GLOBALS->helpbox_is_active)
1821 {
1822 help_text_bold("\n\nUse Black and White");
1823 help_text(
1824 " draws signal names and trace data in black and white. This is intended for use in"
1825 " black and white screen dumps."
1826 );
1827 }
1828 else
1829 {
1830 force_screengrab_gcs();
1831
1832 MaxSignalLength();
1833 signalarea_configure_event(GLOBALS->signalarea, NULL);
1834 wavearea_configure_event(GLOBALS->wavearea, NULL);
1835 }
1836 }
1837 /**/
1838 void menu_zoom10_snap(gpointer null_data, guint callback_action, GtkWidget *widget)
1839 {
1840 (void)null_data;
1841 (void)callback_action;
1842 (void)widget;
1843
1844 if(GLOBALS->helpbox_is_active)
1845 {
1846 help_text_bold("\n\nZoom Pow10 Snap");
1847 help_text(
1848 " snaps time values to a power of ten boundary when active. Fractional zooms are"
1849 " internally stored, but what is actually displayed will be rounded up/down to the"
1850 " nearest power of 10. This only works when the ticks per frame is greater than 100"
1851 " units."
1852 );
1853 }
1854 else
1855 {
1856 #ifndef WAVE_USE_MLIST_T
1857 if(GLOBALS->zoom_pow10_snap)
1858 {
1859 GLOBALS->zoom_pow10_snap=0;
1860 status_text("Pow10 Snap Off.\n");
1861 }
1862 else
1863 {
1864 GLOBALS->zoom_pow10_snap=1;
1865 status_text("Pow10 Snap On.\n");
1866 }
1867 #else
1868 GLOBALS->zoom_pow10_snap = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VZPS]));
1869 if(!GLOBALS->zoom_pow10_snap)
1870 {
1871 status_text("Pow10 Snap Off.\n");
1872 }
1873 else
1874 {
1875 status_text("Pow10 Snap On.\n");
1876 }
1877 #endif
1878
1879 if(GLOBALS->wave_hslider)
1880 {
1881 calczoom(GLOBALS->tims.zoom);
1882 fix_wavehadj();
1883
1884 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "changed"); /* force zoom update */
1885 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "value_changed"); /* force zoom update */
1886 }
1887 }
1888
1889 #ifndef WAVE_USE_MLIST_T
1890 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VZPS].path))->active=(GLOBALS->zoom_pow10_snap)?TRUE:FALSE;
1891 #endif
1892 }
1893
1894 /**/
1895 void menu_zoom_dynf(gpointer null_data, guint callback_action, GtkWidget *widget)
1896 {
1897 (void)null_data;
1898 (void)callback_action;
1899 (void)widget;
1900
1901 if(GLOBALS->helpbox_is_active)
1902 {
1903 help_text_bold("\n\nPartial VCD Dynamic Zoom Full");
1904 help_text(
1905 " causes the screen to be in full zoom mode while a VCD file is loading"
1906 " incrementally."
1907 );
1908 }
1909 else
1910 {
1911 #ifndef WAVE_USE_MLIST_T
1912 if(GLOBALS->zoom_dyn)
1913 {
1914 GLOBALS->zoom_dyn=0;
1915 status_text("Dynamic Zoom Full Off.\n");
1916 }
1917 else
1918 {
1919 GLOBALS->zoom_dyn=1;
1920 status_text("Dynamic Zoom Full On.\n");
1921 }
1922 #else
1923 GLOBALS->zoom_dyn = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VZDYN]));
1924 if(!GLOBALS->zoom_dyn)
1925 {
1926 status_text("Dynamic Zoom Full Off.\n");
1927 }
1928 else
1929 {
1930 status_text("Dynamic Zoom Full On.\n");
1931 }
1932 #endif
1933 }
1934
1935 #ifndef WAVE_USE_MLIST_T
1936 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VZDYN].path))->active=(GLOBALS->zoom_dyn)?TRUE:FALSE;
1937 #endif
1938 }
1939
1940 /**/
1941 void menu_zoom_dyne(gpointer null_data, guint callback_action, GtkWidget *widget)
1942 {
1943 (void)null_data;
1944 (void)callback_action;
1945 (void)widget;
1946
1947 if(GLOBALS->helpbox_is_active)
1948 {
1949 help_text_bold("\n\nPartial VCD Dynamic Zoom To End");
1950 help_text(
1951 " causes the screen to zoom to the end while a VCD file is loading"
1952 " incrementally."
1953 );
1954 }
1955 else
1956 {
1957 #ifndef WAVE_USE_MLIST_T
1958 if(GLOBALS->zoom_dyne)
1959 {
1960 GLOBALS->zoom_dyne=0;
1961 status_text("Dynamic Zoom To End Off.\n");
1962 }
1963 else
1964 {
1965 GLOBALS->zoom_dyne=1;
1966 status_text("Dynamic Zoom To End On.\n");
1967 }
1968 #else
1969 GLOBALS->zoom_dyne = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VZDYNE]));
1970 if(!GLOBALS->zoom_dyne)
1971 {
1972 status_text("Dynamic Zoom To End Off.\n");
1973 }
1974 else
1975 {
1976 status_text("Dynamic Zoom To End On.\n");
1977 }
1978 #endif
1979 }
1980
1981 #ifndef WAVE_USE_MLIST_T
1982 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VZDYNE].path))->active=(GLOBALS->zoom_dyne)?TRUE:FALSE;
1983 #endif
1984 }
1985
1986 /**/
1987 void menu_left_justify(gpointer null_data, guint callback_action, GtkWidget *widget)
1988 {
1989 (void)null_data;
1990 (void)callback_action;
1991 (void)widget;
1992
1993 if(GLOBALS->helpbox_is_active)
1994 {
1995 help_text_bold("\n\nLeft Justify Signals");
1996 help_text(
1997 " draws signal names flushed to the left border of the signal window."
1998 );
1999 }
2000 else
2001 {
2002 status_text("Left Justification.\n");
2003 GLOBALS->left_justify_sigs=~0;
2004 MaxSignalLength();
2005 signalarea_configure_event(GLOBALS->signalarea, NULL);
2006 }
2007 }
2008
2009 /**/
2010 void menu_right_justify(gpointer null_data, guint callback_action, GtkWidget *widget)
2011 {
2012 (void)null_data;
2013 (void)callback_action;
2014 (void)widget;
2015
2016 if(GLOBALS->helpbox_is_active)
2017 {
2018 help_text_bold("\n\nRight Justify Signals");
2019 help_text(
2020 " draws signal names flushed to the right (\"equals\") side of the signal window."
2021 );
2022 }
2023 else
2024 {
2025 status_text("Right Justification.\n");
2026 GLOBALS->left_justify_sigs=0;
2027 MaxSignalLength();
2028 signalarea_configure_event(GLOBALS->signalarea, NULL);
2029 }
2030 }
2031
2032 /**/
2033 void menu_enable_constant_marker_update(gpointer null_data, guint callback_action, GtkWidget *widget)
2034 {
2035 (void)null_data;
2036 (void)callback_action;
2037 (void)widget;
2038
2039 if(GLOBALS->helpbox_is_active)
2040 {
2041 help_text_bold("\n\nConstant Marker Update");
2042 help_text(
2043 " when enabled,"
2044 " allows GTKWave to dynamically show the changing values of the"
2045 " traces under the primary marker while it is being dragged"
2046 " across the screen. This works best with dynamic resizing disabled."
2047 " When disabled, it"
2048 " restricts GTKWave to only update the trace values when the"
2049 " left mouse button is initially pressed then again when it is released."
2050 " This is the default behavior."
2051 );
2052 }
2053 else
2054 {
2055 #ifndef WAVE_USE_MLIST_T
2056 if(!GLOBALS->constant_marker_update)
2057 {
2058 status_text("Constant marker update enabled.\n");
2059 GLOBALS->constant_marker_update=~0;
2060 }
2061 else
2062 {
2063 status_text("Constant marker update disabled.\n");
2064 GLOBALS->constant_marker_update=0;
2065 }
2066 #else
2067 GLOBALS->constant_marker_update = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VCMU]));
2068 if(GLOBALS->constant_marker_update)
2069 {
2070 status_text("Constant marker update enabled.\n");
2071 }
2072 else
2073 {
2074 status_text("Constant marker update disabled.\n");
2075 }
2076 #endif
2077 }
2078
2079 #ifndef WAVE_USE_MLIST_T
2080 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VCMU].path))->active=(GLOBALS->constant_marker_update)?TRUE:FALSE;
2081 #endif
2082 }
2083 /**/
2084 void menu_enable_standard_trace_select(gpointer null_data, guint callback_action, GtkWidget *widget)
2085 {
2086 (void)null_data;
2087 (void)callback_action;
2088 (void)widget;
2089
2090 if(GLOBALS->helpbox_is_active)
2091 {
2092 help_text_bold("\n\nStandard Trace Select");
2093 help_text(
2094 " when enabled,"
2095 " keeps the currently selected traces from deselecting on mouse button press."
2096 " This allows drag and drop to function more smoothly. As this behavior is not"
2097 " how GTK normally functions, it is by default disabled."
2098 );
2099 }
2100 else
2101 {
2102 #ifndef WAVE_USE_MLIST_T
2103 if(!GLOBALS->use_standard_trace_select)
2104 {
2105 status_text("Standard Trace Select enabled.\n");
2106 GLOBALS->use_standard_trace_select=~0;
2107 }
2108 else
2109 {
2110 status_text("Standard Trace Select disabled.\n");
2111 GLOBALS->use_standard_trace_select=0;
2112 }
2113 #else
2114 GLOBALS->use_standard_trace_select = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_ESTS]));
2115 if(GLOBALS->use_standard_trace_select)
2116 {
2117 status_text("Standard Trace Select enabled.\n");
2118 }
2119 else
2120 {
2121 status_text("Standard Trace Select disabled.\n");
2122 }
2123 #endif
2124 }
2125
2126 #ifndef WAVE_USE_MLIST_T
2127 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_ESTS].path))->active=(GLOBALS->use_standard_trace_select)?TRUE:FALSE;
2128 #endif
2129 }
2130 /**/
2131 void menu_enable_dynamic_resize(gpointer null_data, guint callback_action, GtkWidget *widget)
2132 {
2133 (void)null_data;
2134 (void)callback_action;
2135 (void)widget;
2136 int i;
2137
2138 if(GLOBALS->helpbox_is_active)
2139 {
2140 help_text_bold("\n\nDynamic Resize");
2141 help_text(
2142 " allows GTKWave to dynamically resize the signal"
2143 " window for you when toggled active. This can be helpful during numerous"
2144 " signal additions and/or deletions. This is the default"
2145 " behavior."
2146 );
2147 }
2148 else
2149 {
2150 #ifndef WAVE_USE_MLIST_T
2151 if(!GLOBALS->do_resize_signals)
2152 {
2153 status_text("Resizing enabled.\n");
2154 GLOBALS->do_resize_signals=~0;
2155 }
2156 else
2157 {
2158 status_text("Resizing disabled.\n");
2159 GLOBALS->do_resize_signals=0;
2160 }
2161
2162 for(i=0;i<2;i++)
2163 {
2164 GLOBALS->signalwindow_width_dirty=1;
2165 MaxSignalLength();
2166 signalarea_configure_event(GLOBALS->signalarea, NULL);
2167 wavearea_configure_event(GLOBALS->wavearea, NULL);
2168 }
2169 #else
2170 GLOBALS->do_resize_signals = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VDR]));
2171 if(GLOBALS->do_resize_signals)
2172 {
2173 status_text("Resizing enabled.\n");
2174 }
2175 else
2176 {
2177 status_text("Resizing disabled.\n");
2178 }
2179
2180 if(GLOBALS->signalarea && GLOBALS->wavearea)
2181 {
2182 for(i=0;i<2;i++)
2183 {
2184 GLOBALS->signalwindow_width_dirty=1;
2185 MaxSignalLength();
2186 signalarea_configure_event(GLOBALS->signalarea, NULL);
2187 wavearea_configure_event(GLOBALS->wavearea, NULL);
2188 }
2189 }
2190 #endif
2191 }
2192
2193 #ifndef WAVE_USE_MLIST_T
2194 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VDR].path))->active=(GLOBALS->do_resize_signals)?TRUE:FALSE;
2195 #endif
2196 }
2197 /**/
2198 void menu_toggle_delta_or_frequency(gpointer null_data, guint callback_action, GtkWidget *widget)
2199 {
2200 (void)null_data;
2201 (void)callback_action;
2202 (void)widget;
2203
2204 if(GLOBALS->helpbox_is_active)
2205 {
2206 help_text_bold("\n\nToggle Delta-Frequency");
2207 help_text(
2208 " allows you to switch between the delta time and"
2209 " frequency display in the upper right corner"
2210 " of the main window when measuring distances between markers. Default behavior is that the"
2211 " delta time is displayed."
2212 );
2213 }
2214 else
2215 {
2216 GLOBALS->use_frequency_delta=(GLOBALS->use_frequency_delta)?0:1;
2217 update_maxmarker_labels();
2218 }
2219 }
2220 /**/
2221 void menu_toggle_max_or_marker(gpointer null_data, guint callback_action, GtkWidget *widget)
2222 {
2223 (void)null_data;
2224 (void)callback_action;
2225 (void)widget;
2226
2227 if(GLOBALS->helpbox_is_active)
2228 {
2229 help_text_bold("\n\nToggle Max-Marker");
2230 help_text(
2231 " allows you to switch between the maximum time and"
2232 " marker time for display in the upper right corner"
2233 " of the main window. Default behavior is that the"
2234 " maximum time is displayed."
2235 );
2236 }
2237 else
2238 {
2239 GLOBALS->use_maxtime_display=(GLOBALS->use_maxtime_display)?0:1;
2240 update_maxmarker_labels();
2241 }
2242 }
2243 /**/
2244 #ifdef MAC_INTEGRATION
2245 void menu_help_manual(gpointer null_data, guint callback_action, GtkWidget *widget)
2246 {
2247 (void)null_data;
2248 (void)callback_action;
2249 (void)widget;
2250
2251 if(GLOBALS->helpbox_is_active)
2252 {
2253 help_text_bold("\n\nWave User's Guide");
2254 help_text(
2255 " opens the PDF file of the GTKWave User's Guide for viewing."
2256 );
2257 return;
2258 }
2259 else
2260 {
2261 const gchar *bundle_id = gtkosx_application_get_bundle_id();
2262 if(bundle_id)
2263 {
2264 const gchar *rpath = gtkosx_application_get_resource_path();
2265 const char *suf = "/doc/gtkwave.pdf";
2266 char *pdfpath = NULL;
2267 FILE *handle;
2268
2269 if(rpath)
2270 {
2271 pdfpath = (char *)alloca(strlen(rpath) + strlen(suf) + 1);
2272 strcpy(pdfpath, rpath);
2273 strcat(pdfpath, suf);
2274 }
2275
2276 if(!pdfpath || !(handle=fopen(pdfpath,"rb")))
2277 {
2278 }
2279 else
2280 {
2281 fclose(handle);
2282 gtk_open_external_file(pdfpath);
2283 return;
2284 }
2285 }
2286
2287 simplereqbox("Wave User's Guide",400,"Could not open PDF!","OK", NULL, NULL, 1);
2288 }
2289 }
2290 #endif
2291 /**/
2292 void menu_help(gpointer null_data, guint callback_action, GtkWidget *widget)
2293 {
2294 (void)null_data;
2295 (void)callback_action;
2296 (void)widget;
2297
2298 if(GLOBALS->helpbox_is_active)
2299 {
2300 help_text_bold("\n\nWave Help");
2301 help_text(
2302 " is already active. It's this window."
2303 );
2304 return;
2305 }
2306
2307 helpbox("Wave Help",480,"Select any main window menu item");
2308 }
2309 /**/
2310 void menu_version(gpointer null_data, guint callback_action, GtkWidget *widget)
2311 {
2312 (void)null_data;
2313 (void)callback_action;
2314 (void)widget;
2315
2316 if(GLOBALS->helpbox_is_active)
2317 {
2318 help_text_bold("\n\nWave Version");
2319 help_text(
2320 " merely brings up a requester which indicates the current"
2321 " version of this program."
2322 );
2323 return;
2324 }
2325
2326 simplereqbox("Wave Version",480,WAVE_VERSION_INFO,"OK", NULL, NULL, 0);
2327 }
2328 /**/
2329 void menu_quit_callback(GtkWidget *widget, gpointer data)
2330 {
2331 (void)widget;
2332
2333 char sstr[32];
2334
2335 if(data)
2336 {
2337 #ifdef __CYGWIN__
2338 kill_stems_browser();
2339 #endif
2340 g_print("Exiting.\n");
2341 sprintf(sstr, "%d", GLOBALS->this_context_page);
2342 gtkwavetcl_setvar(WAVE_TCLCB_QUIT_PROGRAM, sstr, WAVE_TCLCB_QUIT_PROGRAM_FLAGS);
2343
2344 gtk_exit(0);
2345 }
2346 }
2347 void menu_quit(gpointer null_data, guint callback_action, GtkWidget *widget)
2348 {
2349 (void)null_data;
2350 (void)callback_action;
2351 (void)widget;
2352
2353 if(GLOBALS->helpbox_is_active)
2354 {
2355 help_text_bold("\n\nQuit");
2356 help_text(
2357 " closes GTKWave and exits immediately."
2358 );
2359 return;
2360 }
2361
2362 if(GLOBALS->save_on_exit) { menu_write_save_file(NULL, 0, NULL); }
2363
2364 if(!GLOBALS->enable_fast_exit)
2365 {
2366 simplereqbox("Quit Program",300,"Do you really want to quit?","Yes", "No", GTK_SIGNAL_FUNC(menu_quit_callback), 1);
2367 }
2368 else
2369 {
2370 menu_quit_callback(NULL, &GLOBALS->enable_fast_exit); /* nonzero dummy arg */
2371 }
2372 }
2373
2374 /**/
2375
2376 void menu_quit_close_callback(GtkWidget *widget, gpointer dummy_data)
2377 {
2378 (void)widget;
2379 (void)dummy_data;
2380
2381 unsigned int i, j=0;
2382 unsigned int this_page = GLOBALS->this_context_page;
2383 unsigned np = GLOBALS->num_notebook_pages;
2384 unsigned int new_page = (this_page != np-1) ? this_page : (this_page-1);
2385 GtkWidget *n = GLOBALS->notebook;
2386 struct Global *old_g = NULL, *saved_g;
2387 char sstr[32];
2388 gboolean is_mf = (GLOBALS->loaded_file_type == MISSING_FILE);
2389
2390 sprintf(sstr, "%d", this_page);
2391 gtkwavetcl_setvar(WAVE_TCLCB_CLOSE_TAB_NUMBER, sstr, WAVE_TCLCB_CLOSE_TAB_NUMBER_FLAGS);
2392
2393 kill_stems_browser_single(GLOBALS);
2394 dead_context_sweep();
2395
2396 for(i=0;i<np;i++)
2397 {
2398 if(i!=this_page)
2399 {
2400 (*GLOBALS->contexts)[j] = (*GLOBALS->contexts)[i];
2401 (*GLOBALS->contexts)[j]->this_context_page = j;
2402 (*GLOBALS->contexts)[j]->num_notebook_pages--;
2403
2404 j++;
2405 }
2406 else
2407 {
2408 old_g = (*GLOBALS->contexts)[j];
2409 }
2410 }
2411 (*GLOBALS->contexts)[j] = old_g;
2412
2413 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(n), (np>2));
2414 gtk_notebook_set_show_border(GTK_NOTEBOOK(n), (np>2));
2415
2416 gtk_notebook_remove_page(GTK_NOTEBOOK(n), this_page);
2417 gtk_notebook_set_current_page(GTK_NOTEBOOK(n), new_page);
2418
2419 set_GLOBALS((*GLOBALS->contexts)[new_page]);
2420 saved_g = GLOBALS;
2421
2422 gtkwave_main_iteration();
2423
2424 set_GLOBALS(old_g);
2425 if(!is_mf)
2426 {
2427 free_and_destroy_page_context();
2428 }
2429 set_GLOBALS(saved_g);
2430
2431 /* need to do this if 2 pages -> 1 */
2432 reformat_time(sstr, GLOBALS->tims.first, GLOBALS->time_dimension);
2433 gtk_entry_set_text(GTK_ENTRY(GLOBALS->from_entry),sstr);
2434 reformat_time(sstr, GLOBALS->tims.last, GLOBALS->time_dimension);
2435 gtk_entry_set_text(GTK_ENTRY(GLOBALS->to_entry),sstr);
2436 update_maxmarker_labels();
2437 update_basetime(GLOBALS->tims.baseline);
2438
2439 gtk_window_set_title(GTK_WINDOW(GLOBALS->mainwindow), GLOBALS->winname);
2440
2441 MaxSignalLength();
2442 signalarea_configure_event(GLOBALS->signalarea, NULL);
2443 wavearea_configure_event(GLOBALS->wavearea, NULL);
2444 }
2445
2446 void menu_quit_close(gpointer null_data, guint callback_action, GtkWidget *widget)
2447 {
2448 (void)null_data;
2449 (void)callback_action;
2450 (void)widget;
2451
2452 if(GLOBALS->helpbox_is_active)
2453 {
2454 help_text_bold("\n\nClose");
2455 help_text(
2456 " immediately closes the current tab if multiple tabs exist or"
2457 " exits GTKWave after an additional confirmation"
2458 " requester is given the OK to quit."
2459 );
2460 return;
2461 }
2462
2463 if((GLOBALS->num_notebook_pages < 2) && (!GLOBALS->enable_fast_exit))
2464 {
2465 simplereqbox("Quit Program",300,"Do you really want to quit?","Yes", "No", GTK_SIGNAL_FUNC(menu_quit_callback), 1);
2466 }
2467 else
2468 {
2469 if(GLOBALS->num_notebook_pages < 2)
2470 {
2471 menu_quit_callback(NULL, &GLOBALS->num_notebook_pages); /* nonzero dummy arg */
2472 }
2473 else
2474 {
2475 menu_quit_close_callback(NULL, NULL); /* dummy arg, not needed to be nonzero */
2476 }
2477 }
2478 }
2479
2480 /**/
2481 void must_sel(void)
2482 {
2483 status_text("Select one or more traces.\n");
2484 }
2485 static void must_sel_nb(void)
2486 {
2487 status_text("Select one or more nonblank traces.\n");
2488 }
2489 static void must_sel_bg(void)
2490 {
2491 status_text("Select a bundle or group.\n");
2492 }
2493 /**/
2494
2495 static void
2496 menu_open_group(GtkWidget *widget, gpointer data)
2497 {
2498 (void)widget;
2499 (void)data;
2500
2501 Trptr t;
2502 unsigned dirty = 0;
2503
2504 /* currently only called by toggle menu option, so no help menu text */
2505
2506 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
2507
2508 t=GLOBALS->traces.first;
2509 while(t)
2510 {
2511 if((t->flags&TR_HIGHLIGHT)&&(IsGroupBegin(t) || IsGroupEnd(t)))
2512 {
2513 dirty=1;
2514 break;
2515 }
2516 t=t->t_next;
2517 }
2518
2519 if(dirty)
2520 {
2521 OpenTrace(t);
2522 GLOBALS->signalwindow_width_dirty=1;
2523 MaxSignalLength();
2524 signalarea_configure_event(GLOBALS->signalarea, NULL);
2525 wavearea_configure_event(GLOBALS->wavearea, NULL);
2526 }
2527 else
2528 {
2529 must_sel_bg();
2530 }
2531 }
2532
2533
2534 static void
2535 menu_close_group(GtkWidget *widget, gpointer data)
2536 {
2537 (void)widget;
2538 (void)data;
2539
2540 Trptr t;
2541 unsigned dirty = 0;
2542
2543 /* currently only called by toggle menu option, so no help menu text */
2544
2545 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
2546
2547 t=GLOBALS->traces.first;
2548 while(t)
2549 {
2550 if((t->flags&TR_HIGHLIGHT)&&(IsGroupBegin(t) || IsGroupEnd(t)))
2551 {
2552 dirty=1;
2553 break;
2554 }
2555 t=t->t_next;
2556 }
2557
2558 if(dirty)
2559 {
2560
2561 CloseTrace(t);
2562 GLOBALS->signalwindow_width_dirty=1;
2563 MaxSignalLength();
2564 signalarea_configure_event(GLOBALS->signalarea, NULL);
2565 wavearea_configure_event(GLOBALS->wavearea, NULL);
2566 }
2567 else
2568 {
2569 must_sel_bg();
2570 }
2571 }
2572
2573
2574
2575
2576 unsigned create_group (char* name, Trptr t_composite)
2577 {
2578 Trptr t, t_prev, t_begin, t_end;
2579 unsigned dirty = 0;
2580
2581 if(!name) name = "Group"; /* generate anonymous name */
2582
2583 t=GLOBALS->traces.first;
2584 while(t)
2585 {
2586 if(t->flags&TR_HIGHLIGHT)
2587 {
2588 dirty=1;
2589 break;
2590 }
2591 t=t->t_next;
2592 }
2593
2594 if(dirty)
2595 {
2596
2597 t_prev = t->t_prev;
2598
2599 CutBuffer();
2600
2601 if (t_composite)
2602 {
2603 t_begin = t_composite;
2604 t_begin->flags |=TR_GRP_BEGIN;
2605 }
2606 else
2607 {
2608 if( (t_begin = (Trptr) calloc_2( 1, sizeof( TraceEnt ))) == NULL )
2609 {
2610 fprintf( stderr, "Out of memory, can't add trace.\n");
2611 return(0);
2612 }
2613
2614 t_begin->flags = (TR_BLANK|TR_GRP_BEGIN);
2615 t_begin->name = (char *)malloc_2(1+strlen(name));
2616 strcpy(t_begin->name, name);
2617 }
2618
2619 GLOBALS->traces.buffer->t_prev = t_begin;
2620 t_begin->t_next = GLOBALS->traces.buffer;
2621 GLOBALS->traces.buffer = t_begin;
2622 GLOBALS->traces.buffercount++;
2623
2624 if( (t_end = (Trptr) calloc_2( 1, sizeof( TraceEnt ))) == NULL )
2625 {
2626 fprintf( stderr, "Out of memory, can't add trace.\n");
2627 return(0);
2628 }
2629
2630 t_end->flags = (TR_BLANK|TR_GRP_END);
2631
2632 if (t_composite)
2633 {
2634 /* make the group end trace invisible */
2635 t_end->flags |= TR_COLLAPSED;
2636 t_end->name = (char *)malloc_2(1+strlen("group_end"));
2637 strcpy(t_end->name, "group_end");
2638 }
2639 else
2640 {
2641 t_end->name = (char *)malloc_2(1+strlen(name));
2642 strcpy(t_end->name, name);
2643 }
2644
2645 GLOBALS->traces.bufferlast->t_next = t_end;
2646 t_end->t_prev = GLOBALS->traces.bufferlast;
2647 GLOBALS->traces.bufferlast = t_end;
2648 GLOBALS->traces.buffercount++;
2649
2650 t_begin->t_match = t_end;
2651 t_end->t_match = t_begin;
2652
2653 if (t_prev)
2654 {
2655 t_prev->flags |= TR_HIGHLIGHT;
2656 PasteBuffer();
2657 }
2658 else
2659 {
2660 PrependBuffer();
2661 }
2662 }
2663 return dirty;
2664 }
2665
2666
2667 static void
2668 create_group_cleanup(GtkWidget *widget, gpointer data)
2669 {
2670 (void)widget;
2671 (void)data;
2672
2673 unsigned dirty = 0;
2674
2675 dirty = create_group(GLOBALS->entrybox_text, NULL);
2676
2677 if (!dirty)
2678 {
2679 must_sel_bg();
2680 }
2681 else
2682 {
2683 GLOBALS->signalwindow_width_dirty=1;
2684 MaxSignalLength();
2685 signalarea_configure_event(GLOBALS->signalarea, NULL);
2686 wavearea_configure_event(GLOBALS->wavearea, NULL);
2687 }
2688 }
2689
2690
2691
2692 void
2693 menu_create_group(gpointer null_data, guint callback_action, GtkWidget *widget)
2694 {
2695 (void)null_data;
2696 (void)callback_action;
2697 (void)widget;
2698
2699 Trptr t;
2700 unsigned dirty = 0;
2701
2702 if(GLOBALS->helpbox_is_active)
2703 {
2704 help_text_bold("\n\nCreate Group");
2705 help_text(
2706 " creates a group of traces which may be opened or closed."
2707 " It is permitted for groups to be nested."
2708 );
2709 return;
2710 }
2711
2712 t=GLOBALS->traces.first;
2713 while(t)
2714 {
2715 if(t->flags&TR_HIGHLIGHT)
2716 {
2717 dirty=1;
2718 break;
2719 }
2720 t=t->t_next;
2721 }
2722
2723 if(dirty)
2724 {
2725 /* don't mess with sigs when dnd active */
2726 if(GLOBALS->dnd_state) { dnd_error(); return; }
2727 entrybox("Create Group",300,"","Enter group name:",128,GTK_SIGNAL_FUNC(create_group_cleanup));
2728 }
2729 else
2730 {
2731 must_sel_bg();
2732 }
2733 }
2734
2735
2736 static unsigned expand_trace(Trptr t_top)
2737 {
2738
2739 Trptr t, tmp;
2740 int tmpi;
2741 unsigned dirty = 0;
2742 int color;
2743
2744 t = t_top;
2745
2746 if(HasWave(t) && !IsGroupBegin(t) && !IsGroupEnd(t))
2747 {
2748 FreeCutBuffer();
2749 GLOBALS->traces.buffer=GLOBALS->traces.first;
2750 GLOBALS->traces.bufferlast=GLOBALS->traces.last;
2751 GLOBALS->traces.buffercount=GLOBALS->traces.total;
2752
2753 GLOBALS->traces.first=GLOBALS->traces.last=NULL; GLOBALS->traces.total=0;
2754
2755 color = t->t_color;
2756
2757 if(t->vector)
2758 {
2759 bptr bits;
2760 int i;
2761 Trptr tfix;
2762 TimeType otime = t->shift;
2763
2764 bits=t->n.vec->bits;
2765 if(!(t->flags&TR_REVERSE))
2766 {
2767 for(i=0;i<bits->nnbits;i++)
2768 {
2769 if(bits->nodes[i]->expansion) bits->nodes[i]->expansion->refcnt++;
2770 GLOBALS->which_t_color = color;
2771 AddNodeTraceReturn(bits->nodes[i],NULL, &tfix);
2772 if(bits->attribs)
2773 {
2774 tfix->shift = otime + bits->attribs[i].shift;
2775 }
2776 }
2777 }
2778 else
2779 {
2780 for(i=(bits->nnbits-1);i>-1;i--)
2781 {
2782 if(bits->nodes[i]->expansion) bits->nodes[i]->expansion->refcnt++;
2783 GLOBALS->which_t_color = color;
2784 AddNodeTraceReturn(bits->nodes[i],NULL, &tfix);
2785 if(bits->attribs)
2786 {
2787 tfix->shift = otime + bits->attribs[i].shift;
2788 }
2789 }
2790 }
2791 }
2792 else
2793 {
2794 eptr e=ExpandNode(t->n.nd);
2795 int i;
2796 if(!e)
2797 {
2798 /* if(t->n.nd->expansion) t->n.nd->expansion->refcnt++; */
2799 /* AddNode(t->n.nd,NULL); */
2800 }
2801 else
2802 {
2803 int dhc_sav = GLOBALS->do_hier_compress;
2804 GLOBALS->do_hier_compress = 0;
2805 for(i=0;i<e->width;i++)
2806 {
2807 GLOBALS->which_t_color = color;
2808 AddNode(e->narray[i], NULL);
2809 }
2810 GLOBALS->do_hier_compress = dhc_sav;
2811 free_2(e->narray);
2812 free_2(e);
2813 }
2814 }
2815
2816 tmp=GLOBALS->traces.buffer; GLOBALS->traces.buffer=GLOBALS->traces.first; GLOBALS->traces.first=tmp;
2817 tmp=GLOBALS->traces.bufferlast; GLOBALS->traces.bufferlast=GLOBALS->traces.last; GLOBALS->traces.last=tmp;
2818 tmpi=GLOBALS->traces.buffercount; GLOBALS->traces.buffercount=GLOBALS->traces.total;
2819 GLOBALS->traces.total=tmpi;
2820
2821 if (GLOBALS->traces.buffercount > 0)
2822 {
2823
2824 /* buffer now contains the created signals */
2825 ClearTraces();
2826
2827 if (t_top->t_prev)
2828 {
2829 t_top->t_prev->flags |= TR_HIGHLIGHT;
2830 RemoveTrace(t_top, 0);
2831 PasteBuffer();
2832 t_top->t_prev->flags &= ~TR_HIGHLIGHT;
2833 }
2834 else
2835 {
2836 RemoveTrace(t_top, 0);
2837 PrependBuffer();
2838 }
2839
2840 dirty = create_group("unused_2", t_top);
2841
2842 }
2843 }
2844
2845 GLOBALS->which_t_color = 0;
2846 return dirty;
2847 }
2848
2849 void
2850 menu_expand(gpointer null_data, guint callback_action, GtkWidget *widget)
2851 {
2852 (void)null_data;
2853 (void)callback_action;
2854 (void)widget;
2855
2856 Trptr t, t_next;
2857 int dirty=0;
2858 int j;
2859 GtkAdjustment *wadj;
2860
2861 if(GLOBALS->helpbox_is_active)
2862 {
2863 help_text_bold("\n\nExpand");
2864 help_text(
2865 " decomposes the highlighted signals into their individual bits."
2866 " The resulting bits are converted to traces and inserted after the"
2867 " last highlighted trace. The original unexpanded traces will"
2868 " be placed in the cut buffer."
2869 " It will function seemingly randomly"
2870 " when used upon real valued single-bit traces."
2871 " When used upon multi-bit vectors that contain"
2872 " real valued traces, those traces will expand to their normal \"correct\" values,"
2873 " not individual bits."
2874 );
2875 return;
2876 }
2877
2878
2879 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
2880
2881 DEBUG(printf("Expand Traces\n"));
2882
2883 t=GLOBALS->traces.first;
2884 while(t)
2885 {
2886 if(IsSelected(t) && HasWave(t))
2887 {
2888 t->flags |= TR_COLLAPSED;
2889 dirty=1;
2890 }
2891 t=t->t_next;
2892 }
2893
2894 if(dirty)
2895 {
2896 ClearTraces();
2897 t=GLOBALS->traces.first;
2898 while(t)
2899 {
2900 t_next = t->t_next;
2901 if(HasWave(t) && (t->flags&TR_COLLAPSED))
2902 {
2903 if (!IsGroupBegin(t) && !IsGroupEnd(t))
2904 {
2905 expand_trace(t);
2906 }
2907 else
2908 {
2909 OpenTrace(t);
2910 }
2911 }
2912 t=t_next;
2913 }
2914 t=GLOBALS->traces.first;
2915 if(t) { t->t_grp = NULL; } /* scan-build */
2916 while(t)
2917 {
2918 if(HasWave(t) && (t->flags&TR_COLLAPSED))
2919 {
2920 t->flags &= ~TR_COLLAPSED;
2921 t->flags |= TR_HIGHLIGHT;
2922 }
2923
2924 updateTraceGroup(t);
2925 t=t->t_next;
2926 }
2927
2928 t=GLOBALS->traces.first;
2929 while(t)
2930 {
2931 if (IsSelected(t)) { break; }
2932 t=t->t_next;
2933 }
2934
2935 j = GetTraceNumber(t);
2936 wadj=GTK_ADJUSTMENT(GLOBALS->wave_vslider);
2937 if (j < wadj->value)
2938 {
2939 SetTraceScrollbarRowValue(j, 0);
2940 }
2941
2942 GLOBALS->signalwindow_width_dirty=1;
2943 MaxSignalLength();
2944 signalarea_configure_event(GLOBALS->signalarea, NULL);
2945 wavearea_configure_event(GLOBALS->wavearea, NULL);
2946 }
2947 else
2948 {
2949 must_sel_nb();
2950 }
2951 }
2952
2953 void
2954 menu_toggle_group(gpointer null_data, guint callback_action, GtkWidget *widget)
2955 {
2956 (void)null_data;
2957 (void)callback_action;
2958 (void)widget;
2959
2960 Trptr t;
2961 unsigned dirty_group = 0;
2962 unsigned dirty_signal = 0;
2963
2964 if(GLOBALS->helpbox_is_active)
2965 {
2966 help_text_bold("\n\nToggle Group");
2967 help_text(
2968 " toggles a group opened or closed."
2969 );
2970 return;
2971 }
2972
2973
2974 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
2975
2976 t=GLOBALS->traces.first;
2977 while(t)
2978 {
2979 if((t->flags&TR_HIGHLIGHT)&&(IsGroupBegin(t) || IsGroupEnd(t)))
2980 {
2981 dirty_group=1;
2982 break;
2983 }
2984
2985 if((t->flags&TR_HIGHLIGHT)&&HasWave(t))
2986 {
2987 dirty_signal=1;
2988 break;
2989 }
2990 t=t->t_next;
2991 }
2992
2993 if(dirty_group)
2994 {
2995 if(IsClosed(t))
2996 {
2997 menu_open_group(widget, null_data);
2998 gtkwavetcl_setvar(WAVE_TCLCB_OPEN_TRACE_GROUP, t->name, WAVE_TCLCB_OPEN_TRACE_GROUP_FLAGS);
2999 }
3000 else
3001 {
3002 menu_close_group(widget, null_data);
3003 gtkwavetcl_setvar(WAVE_TCLCB_CLOSE_TRACE_GROUP, t->name, WAVE_TCLCB_CLOSE_TRACE_GROUP_FLAGS);
3004 }
3005 return;
3006 }
3007 if(dirty_signal)
3008 {
3009 ClearTraces();
3010 t->flags |= TR_HIGHLIGHT;
3011 menu_expand(null_data, 0, widget);
3012 gtkwavetcl_setvar(WAVE_TCLCB_OPEN_TRACE_GROUP, t->name, WAVE_TCLCB_OPEN_TRACE_GROUP_FLAGS);
3013 return;
3014 }
3015
3016 must_sel_bg();
3017 }
3018
3019 static void rename_cleanup(GtkWidget *widget, gpointer data)
3020 {
3021 (void)widget;
3022 (void)data;
3023
3024 Trptr t = GLOBALS->trace_to_alias_menu_c_1;
3025
3026 if(GLOBALS->entrybox_text)
3027 {
3028 char *efix;
3029 /* code to turn '{' and '}' into '[' and ']' */
3030 if(!(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH)))
3031 {
3032 efix=GLOBALS->entrybox_text;
3033 while(*efix)
3034 {
3035 if(*efix=='{')
3036 {
3037 *efix='[';
3038 }
3039 if(*efix=='}')
3040 {
3041 *efix=']';
3042 }
3043 efix++;
3044 }
3045 }
3046
3047 if(t->vector)
3048 {
3049 if(t->name_full)
3050 {
3051 free_2(t->name_full);
3052 t->name_full = NULL;
3053 }
3054 if (t->n.vec->bvname)
3055 {
3056 free_2(t->n.vec->bvname);
3057 }
3058
3059 t->n.vec->bvname = (char *)malloc_2(1+strlen(GLOBALS->entrybox_text));
3060 strcpy(t->n.vec->bvname, GLOBALS->entrybox_text);
3061 t->name = t->n.vec->bvname;
3062 if(GLOBALS->hier_max_level)
3063 t->name = hier_extract(t->name, GLOBALS->hier_max_level);
3064
3065 t->flags&= ~TR_HIGHLIGHT;
3066
3067 }
3068
3069 GLOBALS->signalwindow_width_dirty=1;
3070 MaxSignalLength();
3071 signalarea_configure_event(GLOBALS->signalarea, NULL);
3072 wavearea_configure_event(GLOBALS->wavearea, NULL);
3073 }
3074 }
3075
3076
3077 static void menu_rename(GtkWidget *widget, gpointer data)
3078 {
3079 (void)widget;
3080 (void)data;
3081
3082 Trptr t;
3083 /* currently only called by various combine menu options, so no help menu text */
3084
3085 GLOBALS->trace_to_alias_menu_c_1=NULL;
3086
3087 /* don't mess with sigs when dnd active */
3088 if(GLOBALS->dnd_state) { dnd_error(); return; }
3089
3090 t = GLOBALS->traces.first;
3091 while(t)
3092 {
3093 if(IsSelected(t)&&(t->vector==TRUE))
3094 {
3095 GLOBALS->trace_to_alias_menu_c_1 = t;
3096 break;
3097 }
3098 t=t->t_next;
3099 }
3100
3101 if(GLOBALS->trace_to_alias_menu_c_1)
3102 {
3103 int was_packed = HIER_DEPACK_ALLOC;
3104 char* current = GetFullName(GLOBALS->trace_to_alias_menu_c_1, &was_packed);
3105 ClearTraces();
3106 GLOBALS->trace_to_alias_menu_c_1->flags |= TR_HIGHLIGHT;
3107 entrybox("Trace Name",300,current,NULL,128,GTK_SIGNAL_FUNC(rename_cleanup));
3108 if(was_packed) { free_2(current); }
3109 }
3110 else
3111 {
3112 must_sel();
3113 }
3114 }
3115
3116
3117 bvptr combine_traces(int direction, Trptr single_trace_only)
3118 {
3119 Trptr t, tmp;
3120 Trptr tfirst = NULL;
3121 int tmpi,dirty=0, attrib_reqd=0;
3122 nptr bitblast_parent;
3123 int bitblast_delta=0;
3124
3125 DEBUG(printf("Combine Traces\n"));
3126
3127 t=single_trace_only ? single_trace_only : GLOBALS->traces.first;
3128 while(t)
3129 {
3130 if((t->flags&TR_HIGHLIGHT)&&(!(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH))))
3131 {
3132 if(t->vector)
3133 {
3134 dirty+=t->n.vec->nbits;
3135 }
3136 else
3137 {
3138 if(t->n.nd->extvals)
3139 {
3140 int msb, lsb, width;
3141 msb = t->n.nd->msi;
3142 lsb = t->n.nd->lsi;
3143 if(msb>lsb) width = msb-lsb+1; else width = lsb-msb+1;
3144 dirty += width;
3145 }
3146 else
3147 {
3148 dirty++;
3149 }
3150 }
3151 }
3152 if(t == single_trace_only) break;
3153 t=t->t_next;
3154 }
3155
3156 if(!dirty)
3157 {
3158 if(!single_trace_only) must_sel_nb();
3159 return NULL;
3160 }
3161 if(dirty>BITATTRIBUTES_MAX)
3162 {
3163 char buf[128];
3164
3165 if(!single_trace_only)
3166 {
3167 sprintf(buf, "%d bits selected, please use <= %d.\n", dirty, BITATTRIBUTES_MAX);
3168 status_text(buf);
3169 }
3170 return NULL;
3171 }
3172 else
3173 {
3174 int i,nodepnt=0;
3175 struct Node *n[BITATTRIBUTES_MAX];
3176 struct BitAttributes ba[BITATTRIBUTES_MAX];
3177 struct Bits *b=NULL;
3178 bvptr v=NULL;
3179
3180 memset(n, 0, sizeof(n)); /* scan-build */
3181
3182 if(!single_trace_only)
3183 {
3184 FreeCutBuffer();
3185 GLOBALS->traces.buffer=GLOBALS->traces.first;
3186 GLOBALS->traces.bufferlast=GLOBALS->traces.last;
3187 GLOBALS->traces.buffercount=GLOBALS->traces.total;
3188
3189 GLOBALS->traces.first=GLOBALS->traces.last=NULL; GLOBALS->traces.total=0;
3190
3191 t=GLOBALS->traces.buffer;
3192 }
3193 else
3194 {
3195 t = single_trace_only;
3196 }
3197
3198 tfirst = t;
3199 while(t)
3200 {
3201 if(t->flags&TR_HIGHLIGHT)
3202 {
3203 if(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH))
3204 {
3205 /* nothing */
3206 }
3207 else
3208 {
3209 if(t->vector)
3210 {
3211 int ix;
3212 bptr bits = t->n.vec->bits;
3213 baptr oldba = bits ? bits->attribs : NULL;
3214
3215 bits=t->n.vec->bits;
3216
3217 if(!(t->flags&TR_REVERSE))
3218 {
3219 for(ix=0;ix<bits->nnbits;ix++)
3220 {
3221 if(bits->nodes[ix]->expansion) bits->nodes[ix]->expansion->refcnt++;
3222 ba[nodepnt].shift = t->shift + (oldba ? oldba[ix].shift : 0);
3223 ba[nodepnt].flags = t->flags ^ (oldba ? oldba[ix].flags&TR_INVERT : 0);
3224 n[nodepnt++]=bits->nodes[ix];
3225 }
3226 }
3227 else
3228 {
3229 for(ix=(bits->nnbits-1);ix>-1;ix--)
3230 {
3231 if(bits->nodes[ix]->expansion) bits->nodes[ix]->expansion->refcnt++;
3232 ba[nodepnt].shift = t->shift + (oldba ? oldba[ix].shift : 0);
3233 ba[nodepnt].flags = t->flags ^ (oldba ? oldba[ix].flags&TR_INVERT : 0);
3234 n[nodepnt++]=bits->nodes[ix];
3235 }
3236 }
3237 }
3238 else
3239 {
3240 eptr e=ExpandNode(t->n.nd);
3241 int ix;
3242 if(!e)
3243 {
3244 if(t->n.nd->expansion) t->n.nd->expansion->refcnt++;
3245 ba[nodepnt].shift = t->shift;
3246 ba[nodepnt].flags = t->flags;
3247 n[nodepnt++]=t->n.nd;
3248 }
3249 else
3250 {
3251 for(ix=0;ix<e->width;ix++)
3252 {
3253 ba[nodepnt].shift = t->shift;
3254 ba[nodepnt].flags = t->flags;
3255 n[nodepnt++]=e->narray[ix];
3256 e->narray[ix]->expansion->refcnt++;
3257 }
3258 free_2(e->narray);
3259 free_2(e);
3260 }
3261 }
3262 }
3263 }
3264 if(nodepnt==dirty) break;
3265 if(t == single_trace_only) break;
3266 t=t->t_next;
3267 }
3268
3269 b=(struct Bits *)calloc_2(1,sizeof(struct Bits)+(nodepnt)*sizeof(struct Node *));
3270
3271 b->attribs = malloc_2(nodepnt * sizeof(struct BitAttributes));
3272 for(i=0;i<nodepnt;i++) /* for up combine we need to reverse the attribs list! */
3273 {
3274 if(direction)
3275 {
3276 memcpy(b->attribs+i, ba+i, sizeof(struct BitAttributes));
3277 }
3278 else
3279 {
3280 memcpy(b->attribs+i, ba+(nodepnt-1-i), sizeof(struct BitAttributes));
3281 }
3282
3283 if((ba[i].shift)||(ba[i].flags&TR_INVERT)) /* timeshift/invert are only relevant flags */
3284 {
3285 attrib_reqd = 1;
3286 }
3287 }
3288
3289 if(!attrib_reqd)
3290 {
3291 free_2(b->attribs);
3292 b->attribs = NULL;
3293 }
3294
3295 if(nodepnt && n[0] && n[0]->expansion) /* scan-build */
3296 {
3297 bitblast_parent = n[0]->expansion->parent;
3298 }
3299 else
3300 {
3301 bitblast_parent = NULL;
3302 }
3303
3304 if(direction)
3305 {
3306 for(i=0;i<nodepnt;i++)
3307 {
3308 b->nodes[i]=n[i];
3309 if(n[i] && n[i]->expansion) /* scan-build */
3310 {
3311 if(bitblast_parent != n[i]->expansion->parent)
3312 {
3313 bitblast_parent=NULL;
3314 }
3315 else
3316 {
3317 if(i==1)
3318 {
3319 if(n[0] && n[0]->expansion) /* scan-build */
3320 {
3321 bitblast_delta = n[1]->expansion->actual - n[0]->expansion->actual;
3322 if(bitblast_delta<-1) bitblast_delta=0;
3323 else if(bitblast_delta>1) bitblast_delta=0;
3324 }
3325 else
3326 {
3327 bitblast_delta = 0;
3328 }
3329 }
3330 else if((bitblast_delta)&&(i>1))
3331 {
3332 if((n[i]->expansion->actual - n[i-1]->expansion->actual) != bitblast_delta) bitblast_delta=0;
3333 }
3334 }
3335 }
3336 else
3337 {
3338 bitblast_parent = NULL;
3339 }
3340 }
3341 }
3342 else
3343 {
3344 int rev;
3345 rev=nodepnt-1;
3346 for(i=0;i<nodepnt;i++)
3347 {
3348 b->nodes[i]=n[rev--];
3349 if(n[i] && n[i]->expansion) /* scan-build */
3350 {
3351 if(bitblast_parent != n[i]->expansion->parent)
3352 {
3353 bitblast_parent=NULL;
3354 }
3355 else
3356 {
3357 if(i==1)
3358 {
3359 if(n[0] && n[0]->expansion) /* scan-build */
3360 {
3361 bitblast_delta = n[1]->expansion->actual - n[0]->expansion->actual;
3362 if(bitblast_delta<-1) bitblast_delta=0;
3363 else if(bitblast_delta>1) bitblast_delta=0;
3364 }
3365 else
3366 {
3367 bitblast_delta=0;
3368 }
3369 }
3370 else if((bitblast_delta)&&(i>1))
3371 {
3372 if((n[i]->expansion->actual - n[i-1]->expansion->actual) != bitblast_delta) bitblast_delta=0;
3373 }
3374 }
3375 }
3376 else
3377 {
3378 bitblast_parent = NULL;
3379 }
3380 }
3381 }
3382
3383 b->nnbits=nodepnt;
3384
3385 if(!bitblast_parent)
3386 {
3387 char *aname;
3388 int match_iter = 1;
3389
3390 if(direction)
3391 {
3392 aname = (nodepnt && n[0]) ? attempt_vecmatch(n[0]->nname, n[nodepnt-1]->nname) : NULL; /* scan-build */
3393 }
3394 else
3395 {
3396 aname = (nodepnt && n[0]) ? attempt_vecmatch(n[nodepnt-1]->nname, n[0]->nname) : NULL; /* scan-build */
3397 }
3398
3399 if(aname)
3400 {
3401 int ix;
3402
3403 for(ix=0;ix<nodepnt-1;ix++)
3404 {
3405 char *mat = attempt_vecmatch(n[0]->nname, n[ix]->nname);
3406 if(!mat) { match_iter = 0; break; } else { free_2(mat); }
3407 }
3408 }
3409
3410 if(!match_iter)
3411 {
3412 free_2(aname);
3413 aname = NULL;
3414 }
3415
3416 if((!aname) && !single_trace_only) /* ajb 020716: recent add to handle combine down on 2D vectors */
3417 {
3418 char *t_topname = NULL;
3419 char *t_botname = NULL;
3420 t = tfirst;
3421 while(t)
3422 {
3423 if(t->flags&TR_HIGHLIGHT)
3424 {
3425 if(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH))
3426 {
3427 /* nothing */
3428 }
3429 else
3430 {
3431 if(t->vector)
3432 {
3433 char *vname = t->n.vec ? t->n.vec->bvname : NULL;
3434 if(vname)
3435 {
3436 if(!t_topname)
3437 {
3438 t_topname = vname;
3439 }
3440 else
3441 {
3442 t_botname = vname;
3443 }
3444 }
3445 }
3446 else
3447 {
3448 if(!t_topname)
3449 {
3450 t_topname = t->n.nd->nname;
3451 }
3452 else
3453 {
3454 t_botname = t->n.nd->nname;
3455 }
3456
3457 if(t_topname && t_botname)
3458 {
3459 char *mat = attempt_vecmatch(t_topname, t_botname);
3460 if(!mat) { t_topname = t_botname = NULL; break; } else { free_2(mat); }
3461 }
3462 }
3463 }
3464
3465 }
3466
3467 t=t->t_next;
3468 }
3469
3470 if(t_topname && t_botname)
3471 {
3472 aname = direction ? attempt_vecmatch(t_topname, t_botname) : attempt_vecmatch(t_botname, t_topname); /* return this match */
3473 }
3474 }
3475
3476
3477 if(!b->attribs)
3478 {
3479 if(aname)
3480 {
3481 b->name = aname;
3482 }
3483 else
3484 {
3485 strcpy(b->name=(char *)malloc_2(strlen("<Vector>")+1),"<Vector>");
3486 }
3487 }
3488 else
3489 {
3490 if(aname)
3491 {
3492 b->name = aname;
3493 }
3494 else
3495 {
3496 strcpy(b->name=(char *)malloc_2(strlen("<ComplexVector>")+1),"<ComplexVector>");
3497 }
3498 }
3499 }
3500 else
3501 {
3502 int ix, offset;
3503 char *nam;
3504 char *namex;
3505 int was_packed = HIER_DEPACK_ALLOC;
3506
3507 int row = 0, bit = 0;
3508 int row2 = 0, bit2 = 0;
3509 int is_2d = 0;
3510 int iy, offsety;
3511 char *namey;
3512 char sep2d = ':';
3513
3514 namex = hier_decompress_flagged(n[0]->nname, &was_packed);
3515
3516 offset = strlen(namex);
3517 for(ix=offset-1;ix>=0;ix--)
3518 {
3519 if(namex[ix]=='[') break;
3520 }
3521 if(ix>-1) offset=ix;
3522
3523 if(ix>3) /* is_2d is for handling 2-d stored in 1-d vector */
3524 {
3525 if(namex[ix-1]==']')
3526 {
3527 int j = ix-2;
3528 for(;j>=0;j--)
3529 {
3530 if(namex[j]=='[') break;
3531 }
3532
3533 if(j>-1)
3534 {
3535 int items = sscanf(namex+j, "[%d][%d]", &row, &bit);
3536 if(items == 2)
3537 {
3538 /* printf(">> %d %d (items = %d)\n", row, bit, items); */
3539
3540 offset = j;
3541 is_2d = 1;
3542 }
3543 }
3544 }
3545 }
3546
3547 nam=(char *)wave_alloca(offset+50); /* to handle [a:b][c:d] case */
3548 memcpy(nam, namex, offset);
3549 if(was_packed) { free_2(namex); }
3550
3551 if(is_2d)
3552 {
3553 is_2d = 0;
3554 namey = hier_decompress_flagged(n[nodepnt-1]->nname, &was_packed);
3555
3556 offsety = strlen(namey);
3557 for(iy=offsety-1;iy>=0;iy--)
3558 {
3559 if(namey[iy]=='[') break;
3560 }
3561 /* if(iy>-1) offsety=iy; not needed as in above as gets overwritten below by offsety = j */
3562 if(iy>3)
3563 {
3564 if(namey[iy-1]==']')
3565 {
3566 int j = iy-2;
3567 for(;j>=0;j--)
3568 {
3569 if(namey[j]=='[') break;
3570 }
3571
3572 if(j>-1)
3573 {
3574 int items = sscanf(namey+j, "[%d][%d]", &row2, &bit2);
3575 if(items == 2)
3576 {
3577 int rowabs, bitabs, width2d;
3578 /* printf(">> %d %d (items = %d)\n", row2, bit2, items); */
3579
3580 offsety = j;
3581 is_2d = (offset == offsety) && !memcmp(nam, namey, offsety);
3582
3583 rowabs = (row2 > row) ? (row2 - row + 1) : (row - row2 + 1);
3584 bitabs = (bit2 > bit) ? (bit2 - bit + 1) : (bit - bit2 + 1);
3585 width2d = rowabs * bitabs;
3586 sep2d = (width2d == nodepnt) ? ':' : '|';
3587 }
3588 }
3589 }
3590 }
3591
3592 if(was_packed) { free_2(namey); }
3593 }
3594
3595
3596 if(direction)
3597 {
3598 if(!is_2d)
3599 {
3600 sprintf(nam+offset, "[%d%s%d]", n[0]->expansion->actual, (bitblast_delta!=0) ? ":" : "|", n[nodepnt-1]->expansion->actual);
3601 }
3602 else
3603 {
3604 if(row == row2)
3605 {
3606 if(bit == bit2)
3607 {
3608 sprintf(nam+offset, "[%d][%d]", row, bit);
3609 }
3610 else
3611 {
3612 sprintf(nam+offset, "[%d][%d%c%d]", row, bit, sep2d, bit2);
3613 }
3614 }
3615 else
3616 {
3617 if(bit == bit2)
3618 {
3619 sprintf(nam+offset, "[%d%c%d][%d]", row, sep2d, row2, bit);
3620 }
3621 else
3622 {
3623 sprintf(nam+offset, "[%d%c%d][%d%c%d]", row, sep2d, row2, bit, sep2d, bit2);
3624 }
3625 }
3626 }
3627 }
3628 else
3629 {
3630 if(!is_2d)
3631 {
3632 sprintf(nam+offset, "[%d%s%d]", n[nodepnt-1]->expansion->actual, (bitblast_delta!=0) ? ":" : "|", n[0]->expansion->actual);
3633 }
3634 else
3635 {
3636 if(row == row2)
3637 {
3638 if(bit == bit2)
3639 {
3640 sprintf(nam+offset, "[%d][%d]", row, bit);
3641 }
3642 else
3643 {
3644 sprintf(nam+offset, "[%d][%d%c%d]", row, bit2, sep2d, bit);
3645 }
3646 }
3647 else
3648 {
3649 if(bit == bit2)
3650 {
3651 sprintf(nam+offset, "[%d%c%d][%d]", row2, sep2d, row, bit);
3652 }
3653 else
3654 {
3655 sprintf(nam+offset, "[%d%c%d][%d%c%d]", row2, sep2d, row, bit2, sep2d, bit);
3656 }
3657 }
3658 }
3659 }
3660
3661 strcpy(b->name=(char *)malloc_2(offset + strlen(nam+offset)+1), nam);
3662 DEBUG(printf("Name is: '%s'\n", nam));
3663 }
3664
3665 if((v=bits2vector(b)))
3666 {
3667 v->bits=b; /* only needed for savefile function */
3668 }
3669 else
3670 {
3671 free_2(b->name);
3672 if(b->attribs) free_2(b->attribs);
3673 free_2(b);
3674 return NULL;
3675 }
3676
3677 if(!single_trace_only)
3678 {
3679 tmp=GLOBALS->traces.buffer; GLOBALS->traces.buffer=GLOBALS->traces.first; GLOBALS->traces.first=tmp;
3680 tmp=GLOBALS->traces.bufferlast; GLOBALS->traces.bufferlast=GLOBALS->traces.last; GLOBALS->traces.last=tmp;
3681 tmpi=GLOBALS->traces.buffercount; GLOBALS->traces.buffercount=GLOBALS->traces.total;
3682 GLOBALS->traces.total=tmpi;
3683 PasteBuffer();
3684 }
3685
3686 return v;
3687 }
3688 }
3689
3690 void
3691 menu_combine_down(gpointer null_data, guint callback_action, GtkWidget *widget)
3692 {
3693 (void)null_data;
3694 (void)callback_action;
3695 (void)widget;
3696
3697 bvptr v;
3698
3699 if(GLOBALS->helpbox_is_active)
3700 {
3701 help_text_bold("\n\nCombine Down");
3702 help_text(
3703 " coalesces the highlighted signals into a single vector named"
3704 " \"<Vector>\" in a top to bottom fashion"
3705 " placed after the last highlighted trace. The original traces will"
3706 " be placed in the cut buffer."
3707 " It will function seemingly randomly"
3708 " when used upon real valued single-bit traces."
3709 );
3710 return;
3711 }
3712
3713 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
3714 v = combine_traces(1, NULL); /* down */
3715
3716 if (v)
3717 {
3718 Trptr t;
3719
3720 AddVector(v, NULL);
3721 free_2(v->bits->name);
3722 v->bits->name=NULL;
3723
3724 t = GLOBALS->traces.last;
3725
3726 RemoveTrace(t, 0);
3727
3728 /* t is now the composite signal trace */
3729
3730 create_group("unused_0", t);
3731
3732 GLOBALS->signalwindow_width_dirty=1;
3733 MaxSignalLength();
3734 signalarea_configure_event(GLOBALS->signalarea, NULL);
3735 wavearea_configure_event(GLOBALS->wavearea, NULL);
3736
3737 menu_rename(widget, null_data);
3738 }
3739 else
3740 {
3741 }
3742 }
3743
3744 void
3745 menu_combine_up(gpointer null_data, guint callback_action, GtkWidget *widget)
3746 {
3747 (void)null_data;
3748 (void)callback_action;
3749 (void)widget;
3750
3751 bvptr v;
3752
3753 if(GLOBALS->helpbox_is_active)
3754 {
3755 help_text_bold("\n\nCombine Up");
3756 help_text(
3757 " coalesces the highlighted signals into a single vector named"
3758 " \"<Vector>\" in a bottom to top fashion"
3759 " placed after the last highlighted trace. The original traces will"
3760 " be placed in the cut buffer."
3761 " It will function seemingly randomly"
3762 " when used upon real valued single-bit traces."
3763 );
3764 return;
3765 }
3766
3767 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
3768 v = combine_traces(0, NULL); /* up */
3769
3770 if (v)
3771 {
3772 Trptr t;
3773
3774 AddVector(v, NULL);
3775 free_2(v->bits->name);
3776 v->bits->name=NULL;
3777
3778 t = GLOBALS->traces.last;
3779
3780 RemoveTrace(t, 0);
3781
3782 /* t is now the composite signal trace */
3783
3784 create_group("unused_1", t);
3785
3786 GLOBALS->signalwindow_width_dirty=1;
3787 MaxSignalLength();
3788 signalarea_configure_event(GLOBALS->signalarea, NULL);
3789 wavearea_configure_event(GLOBALS->wavearea, NULL);
3790
3791 menu_rename(widget, null_data);
3792 }
3793 else
3794 {
3795 }
3796 }
3797
3798 /**/
3799
3800 void menu_tracesearchbox_callback(GtkWidget *widget, gpointer data)
3801 {
3802 (void)widget;
3803 (void)data;
3804 }
3805
3806 void menu_tracesearchbox(gpointer null_data, guint callback_action, GtkWidget *widget)
3807 {
3808 (void)null_data;
3809 (void)callback_action;
3810 (void)widget;
3811
3812 Trptr t;
3813
3814 if(GLOBALS->helpbox_is_active)
3815 {
3816 help_text_bold("\n\nPattern Search");
3817 help_text(
3818 " only works when at least one trace is highlighted. "
3819 " A requester will appear that lists all the selected"
3820 " traces (maximum of 500) and allows various criteria"
3821 " to be specified for each trace. Searches can go forward"
3822 " or backward from the primary (unnamed) marker. If the"
3823 " primary marker has not been set, the search starts at the"
3824 " beginning of the displayed data (\"From\") for a forwards"
3825 " search and starts at the end of the displayed data (\"To\")"
3826 " for a backwards search."
3827 " \"Mark\" and \"Clear\" are used to modify the normal time"
3828 " vertical markings such that they can be used to indicate"
3829 " all the times that a specific pattern search condition is"
3830 " true (e.g., every upclock of a specific signal). The"
3831 " \"Mark Count\" field indicates how many times the specific"
3832 " pattern search condition was encountered."
3833 " The \"Marking Begins at\" and \"Marking Stops at\" fields are"
3834 " used to limit the time over which marking is applied"
3835 " (but they have no effect on searching)."
3836 );
3837 return;
3838 }
3839
3840 for(t=GLOBALS->traces.first;t;t=t->t_next)
3841 {
3842 if ((t->flags&TR_HIGHLIGHT)&&HasWave(t))
3843 {
3844 /* at least one good trace, so do it */
3845 /* data contains WV_MENU_SPS or WV_MENU_SPS2 or ... but the base is WV_MENU_SPS*/
3846 char buf[128];
3847 intptr_t which = ((long)callback_action) - WV_MENU_SPS;
3848
3849 if((which < 0) || (which >= WAVE_NUM_STRACE_WINDOWS))
3850 { /* should never happen unless menus are defined wrong */
3851 sprintf(buf, "Pattern search ID %d out of range of 1-%d available, ignoring.", (int)(which+1), WAVE_NUM_STRACE_WINDOWS);
3852 status_text(buf);
3853 }
3854 else
3855 {
3856 sprintf(buf, "Waveform Display Search (%d)", (int)(which+1));
3857 tracesearchbox(buf, GTK_SIGNAL_FUNC(menu_tracesearchbox_callback), (gpointer)which);
3858 }
3859 return;
3860 }
3861 }
3862 must_sel();
3863 }
3864
3865 /**/
3866 void
3867 menu_new_viewer_cleanup(GtkWidget *widget, gpointer data)
3868 {
3869 (void)widget;
3870 (void)data;
3871
3872 pid_t pid;
3873
3874 if(GLOBALS->filesel_ok)
3875 {
3876 /* fix problem where ungrab doesn't occur if button pressed + simultaneous accelerator key occurs */
3877 if(GLOBALS->in_button_press_wavewindow_c_1) { gdk_pointer_ungrab(GDK_CURRENT_TIME); }
3878
3879 #if !defined __MINGW32__ && !defined _MSC_VER
3880 /*
3881 * for some reason, X won't let us double-fork in order to cleanup zombies.. *shrug*
3882 */
3883 pid=fork();
3884 if(((int)pid) < 0) { return; /* not much we can do about this.. */ }
3885
3886 if(pid) /* parent==original server_pid */
3887 {
3888 return;
3889 }
3890
3891 #ifdef MAC_INTEGRATION
3892 /* from : @pfx = split(' ', "open -n -W -a gtkwave --args --chdir dummy"); */
3893 if(GLOBALS->optimize_vcd)
3894 {
3895 execlp("open", "open", "-n", "-W", "-a", "gtkwave", "--args", "--optimize", "--dump", *GLOBALS->fileselbox_text, NULL);
3896 }
3897 else
3898 {
3899 execlp("open", "open", "-n", "-W", "-a", "gtkwave", "--args", "--dump", *GLOBALS->fileselbox_text, NULL);
3900 }
3901 #else
3902 if(GLOBALS->optimize_vcd)
3903 {
3904 execlp(GLOBALS->whoami, GLOBALS->whoami, "-o", *GLOBALS->fileselbox_text, NULL);
3905 }
3906 else
3907 {
3908 execlp(GLOBALS->whoami, GLOBALS->whoami, *GLOBALS->fileselbox_text, NULL);
3909 }
3910 #endif
3911 exit(0); /* control never gets here if successful */
3912
3913 #else
3914
3915 BOOL bSuccess = FALSE;
3916 PROCESS_INFORMATION piProcInfo;
3917 TCHAR *szCmdline;
3918 STARTUPINFO si;
3919
3920 memset(&piProcInfo, 0, sizeof(PROCESS_INFORMATION));
3921 memset(&si, 0, sizeof(STARTUPINFO));
3922
3923 szCmdline = malloc_2(strlen(GLOBALS->whoami) + 1 + strlen(*GLOBALS->fileselbox_text) + 1);
3924 sprintf(szCmdline, "%s %s", GLOBALS->whoami, *GLOBALS->fileselbox_text);
3925
3926 bSuccess = CreateProcess(NULL,
3927 szCmdline, /* command line */
3928 NULL, /* process security attributes */
3929 NULL, /* primary thread security attributes */
3930 TRUE, /* handles are inherited */
3931 0, /* creation flags */
3932 NULL, /* use parent's environment */
3933 NULL, /* use parent's current directory */
3934 &si, /* STARTUPINFO pointer */
3935 &piProcInfo); /* receives PROCESS_INFORMATION */
3936
3937 free_2(szCmdline);
3938
3939 if(!bSuccess)
3940 {
3941 /* failed */
3942 }
3943 #endif
3944 }
3945 }
3946
3947 void
3948 menu_new_viewer(gpointer null_data, guint callback_action, GtkWidget *widget)
3949 {
3950 (void)null_data;
3951 (void)callback_action;
3952 (void)widget;
3953
3954 static int mnv = 0;
3955
3956 if(!mnv && !GLOBALS->busy_busy_c_1)
3957 {
3958 mnv = 1;
3959 if(GLOBALS->helpbox_is_active)
3960 {
3961 help_text_bold("\n\nOpen New Window");
3962 help_text(
3963 " will open a file requester that will ask for the name"
3964 " of a VCD or AET file to view. This will fork off a"
3965 " new viewer process."
3966 );
3967 }
3968 else
3969 {
3970 if(in_main_iteration()) { mnv = 0; return; }
3971
3972 fileselbox("Select a trace to view...",&GLOBALS->filesel_newviewer_menu_c_1,GTK_SIGNAL_FUNC(menu_new_viewer_cleanup), GTK_SIGNAL_FUNC(NULL), NULL, 0);
3973 }
3974 mnv = 0;
3975 }
3976 }
3977
3978 /**/
3979
3980 int
3981 menu_new_viewer_tab_cleanup_2(char *fname, int optimize_vcd)
3982 {
3983 int rc = 0;
3984 char *argv[2];
3985 struct Global *g_old = GLOBALS;
3986 struct Global *g_now;
3987
3988 argv[0] = gtkwave_argv0_cached ? gtkwave_argv0_cached : "gtkwave";
3989 argv[1] = fname;
3990
3991 /* fix problem where ungrab doesn't occur if button pressed + simultaneous accelerator key occurs */
3992 if(GLOBALS->in_button_press_wavewindow_c_1) { gdk_pointer_ungrab(GDK_CURRENT_TIME); }
3993
3994 GLOBALS->vcd_jmp_buf = calloc(1, sizeof(jmp_buf));
3995
3996 splash_button_press_event(NULL, NULL); /* kill any possible splash screens (e.g., if automated) */
3997 set_window_busy(NULL);
3998 gtkwave_main_iteration();
3999
4000 if(!setjmp(*(GLOBALS->vcd_jmp_buf)))
4001 {
4002 main_2(optimize_vcd, 2, argv);
4003
4004 g_now = GLOBALS;
4005 set_GLOBALS(g_old);
4006
4007 clone_icon_pointers_across_contexts(g_now, GLOBALS);
4008
4009 free(GLOBALS->vcd_jmp_buf); GLOBALS->vcd_jmp_buf = NULL;
4010 set_window_idle(NULL);
4011 set_GLOBALS(g_now);
4012 g_now->vcd_jmp_buf = NULL;
4013
4014 /* copy old file req strings into new context */
4015 strcpy2_into_new_context(GLOBALS, &GLOBALS->fcurr_ttranslate_c_1, &g_old->fcurr_ttranslate_c_1);
4016 strcpy2_into_new_context(GLOBALS, &GLOBALS->fcurr_ptranslate_c_1, &g_old->fcurr_ptranslate_c_1);
4017 strcpy2_into_new_context(GLOBALS, &GLOBALS->fcurr_translate_c_2, &g_old->fcurr_translate_c_2);
4018
4019 #if 0
4020 /* disabled for now...these probably would be disruptive */
4021 strcpy2_into_new_context(GLOBALS, &GLOBALS->filesel_lxt_writesave, &g_old->filesel_lxt_writesave);
4022 strcpy2_into_new_context(GLOBALS, &GLOBALS->filesel_vcd_writesave, &g_old->filesel_vcd_writesave);
4023 strcpy2_into_new_context(GLOBALS, &GLOBALS->filesel_tim_writesave, &g_old->filesel_tim_writesave);
4024 strcpy2_into_new_context(GLOBALS, &GLOBALS->filesel_writesave, &g_old->filesel_writesave);
4025 strcpy2_into_new_context(GLOBALS, &GLOBALS->stems_name, &g_old->stems_name);
4026 strcpy2_into_new_context(GLOBALS, &GLOBALS->filesel_logfile_menu_c_1, &g_old->filesel_logfile_menu_c_1);
4027 strcpy2_into_new_context(GLOBALS, &GLOBALS->filesel_scriptfile_menu, &g_old->filesel_scriptfile_menu);
4028 strcpy2_into_new_context(GLOBALS, &GLOBALS->filesel_print_pdf_renderopt_c_1, &g_old->filesel_print_pdf_renderopt_c_1);
4029 strcpy2_into_new_context(GLOBALS, &GLOBALS->filesel_print_ps_renderopt_c_1, &g_old->filesel_print_ps_renderopt_c_1);
4030 strcpy2_into_new_context(GLOBALS, &GLOBALS->filesel_print_mif_renderopt_c_1, &g_old->filesel_print_mif_renderopt_c_1);
4031 #endif
4032
4033 /* not sure what's really needed here */
4034 /* for now, add back in repscript_name */
4035 GLOBALS->repscript_period = g_old->repscript_period;
4036 strcpy2_into_new_context(GLOBALS, &GLOBALS->repscript_name, &g_old->repscript_name);
4037
4038 GLOBALS->strace_repeat_count = g_old->strace_repeat_count;
4039
4040 if(g_old->loaded_file_type == MISSING_FILE) /* remove original "blank" page */
4041 {
4042 if(g_old->missing_file_toolbar) gtk_widget_set_sensitive(g_old->missing_file_toolbar, TRUE);
4043 menu_set_sensitive();
4044 gtk_notebook_set_current_page(GTK_NOTEBOOK(g_old->notebook), g_old->this_context_page);
4045 set_GLOBALS(g_old);
4046 menu_quit_close_callback(NULL, NULL);
4047 }
4048
4049 wave_gconf_client_set_string("/current/pwd", getenv("PWD"));
4050
4051 wave_gconf_client_set_string("/current/dumpfile", GLOBALS->optimize_vcd ? GLOBALS->unoptimized_vcd_file_name : GLOBALS->loaded_file_name);
4052 wave_gconf_client_set_string("/current/optimized_vcd", GLOBALS->optimize_vcd ? "1" : "0");
4053
4054 wave_gconf_client_set_string("/current/savefile", GLOBALS->filesel_writesave);
4055
4056 rc = 1;
4057 }
4058 else
4059 {
4060 if(GLOBALS->vcd_handle_vcd_c_1) { fclose(GLOBALS->vcd_handle_vcd_c_1); GLOBALS->vcd_handle_vcd_c_1 = NULL; }
4061 if(GLOBALS->vcd_handle_vcd_recoder_c_2) { fclose(GLOBALS->vcd_handle_vcd_recoder_c_2); GLOBALS->vcd_handle_vcd_recoder_c_2 =NULL; }
4062 if(GLOBALS->mm_lxt_mmap_addr)
4063 {
4064 munmap(GLOBALS->mm_lxt_mmap_addr, GLOBALS->mm_lxt_mmap_len);
4065 GLOBALS->mm_lxt_mmap_addr = NULL;
4066 }
4067 free_outstanding(); /* free anything allocated in loader ctx */
4068 free(GLOBALS);
4069 GLOBALS = NULL; /* valgrind fix */
4070
4071 set_GLOBALS(g_old);
4072 free(GLOBALS->vcd_jmp_buf); GLOBALS->vcd_jmp_buf = NULL;
4073 set_window_idle(NULL);
4074
4075 /* load failed */
4076 wave_gtk_window_set_title(GTK_WINDOW(GLOBALS->mainwindow), GLOBALS->winname, GLOBALS->dumpfile_is_modified ? WAVE_SET_TITLE_MODIFIED: WAVE_SET_TITLE_NONE, 0);
4077 printf("GTKWAVE | File load failure, new tab not created.\n");
4078 rc = 0;
4079 }
4080
4081 return(rc);
4082 }
4083
4084
4085 void
4086 menu_new_viewer_tab_cleanup(GtkWidget *widget, gpointer data)
4087 {
4088 (void)widget;
4089 (void)data;
4090
4091 if(GLOBALS->filesel_ok)
4092 {
4093 menu_new_viewer_tab_cleanup_2(*GLOBALS->fileselbox_text, GLOBALS->optimize_vcd);
4094 }
4095 }
4096
4097
4098 void
4099 menu_new_viewer_tab(gpointer null_data, guint callback_action, GtkWidget *widget)
4100 {
4101 (void)null_data;
4102 (void)callback_action;
4103 (void)widget;
4104
4105 if(GLOBALS->helpbox_is_active)
4106 {
4107 help_text_bold("\n\nOpen New Tab");
4108 help_text(
4109 " will open a file requester that will ask for the name"
4110 " of a VCD or AET file to view. This will create a tabbed page."
4111 );
4112 return;
4113 }
4114
4115 if(in_main_iteration()) return;
4116
4117 #ifdef WAVE_USE_GTK2
4118 if((!GLOBALS->socket_xid)&&(!GLOBALS->partial_vcd))
4119 #else
4120 if(!GLOBALS->partial_vcd)
4121 #endif
4122 {
4123 fileselbox("Select a trace to view...",&GLOBALS->filesel_newviewer_menu_c_1,GTK_SIGNAL_FUNC(menu_new_viewer_tab_cleanup), GTK_SIGNAL_FUNC(NULL), NULL, 0);
4124 }
4125 }
4126
4127 /**/
4128
4129 void
4130 menu_reload_waveform(gpointer null_data, guint callback_action, GtkWidget *widget)
4131 {
4132 (void)null_data;
4133 (void)callback_action;
4134 (void)widget;
4135
4136 if(GLOBALS->helpbox_is_active)
4137 {
4138 help_text_bold("\n\nReload Current Waveform");
4139 help_text(
4140 " will reload the currently displayed waveform"
4141 " from a potentially updated file."
4142 );
4143 return;
4144 }
4145
4146 if(in_main_iteration()) return;
4147
4148 if(GLOBALS->gt_splash_c_1 || GLOBALS->splash_is_loading)
4149 {
4150 return; /* don't attempt reload if splash screen is still active...that's pointless anyway */
4151 }
4152
4153 /* XXX if there's no file (for some reason), this function shouldn't occur
4154 we should probably gray it out. */
4155 if(GLOBALS->loaded_file_type == DUMPLESS_FILE) {
4156 printf("GTKWAVE | DUMPLESS_FILE type cannot be reloaded\n");
4157 return;
4158 }
4159
4160 reload_into_new_context();
4161 }
4162
4163
4164 void
4165 menu_reload_waveform_marshal(GtkWidget *widget, gpointer data)
4166 {
4167 menu_reload_waveform(data, 0, widget);
4168 }
4169
4170
4171 /**/
4172
4173 void
4174 menu_print(gpointer null_data, guint callback_action, GtkWidget *widget)
4175 {
4176 (void)null_data;
4177 (void)callback_action;
4178 (void)widget;
4179
4180 if(GLOBALS->helpbox_is_active)
4181 {
4182 help_text_bold("\n\nPrint To File");
4183 help_text(
4184 " will open up a requester that will allow you to select"
4185 " print options (PS or MIF; Letter, A4, or Legal; Full or Minimal)."
4186 " After selecting the options you want,"
4187 " a file requester will ask for the name of the"
4188 " output file to generate"
4189 " that reflects the current main window display's contents."
4190 );
4191 return;
4192 }
4193
4194 renderbox("Print Formatting Options");
4195 }
4196
4197 /**/
4198 void menu_markerbox_callback(GtkWidget *widget, gpointer data)
4199 {
4200 (void)widget;
4201 (void)data;
4202 }
4203
4204 void menu_markerbox(gpointer null_data, guint callback_action, GtkWidget *widget)
4205 {
4206 (void)null_data;
4207 (void)callback_action;
4208 (void)widget;
4209
4210 if(GLOBALS->helpbox_is_active)
4211 {
4212 help_text_bold("\n\nShow-Change Marker Data");
4213 help_text(
4214 " displays and allows the modification of the times for"
4215 " all named markers by filling in the leftmost entry boxes. In addition, optional marker text"
4216 " rather than a generic single letter name may be specified by filling in the rightmost entry boxes."
4217 " Note that the time for each marker must be unique."
4218 );
4219 return;
4220 }
4221
4222 markerbox("Markers", GTK_SIGNAL_FUNC(menu_markerbox_callback));
4223 }
4224
4225
4226 void copy_pri_b_marker(gpointer null_data, guint callback_action, GtkWidget *widget)
4227 {
4228 (void)null_data;
4229 (void)callback_action;
4230 (void)widget;
4231
4232 if(GLOBALS->helpbox_is_active)
4233 {
4234 help_text_bold("\n\nCopy Primary -> B Marker");
4235 help_text(
4236 " copies the primary marker position to the B marker (handy for measuring deltas)."
4237 );
4238 return;
4239 }
4240
4241 DEBUG(printf("copy_pri_b_marker()\n"));
4242
4243 if(GLOBALS->tims.marker!=-1)
4244 {
4245 GLOBALS->tims.baseline = GLOBALS->tims.marker;
4246 update_basetime(GLOBALS->tims.baseline);
4247 GLOBALS->signalwindow_width_dirty=1;
4248 MaxSignalLength();
4249 signalarea_configure_event(GLOBALS->signalarea, NULL);
4250 wavearea_configure_event(GLOBALS->wavearea, NULL);
4251 }
4252 }
4253
4254
4255
4256 /**/
4257 void delete_unnamed_marker(gpointer null_data, guint callback_action, GtkWidget *widget)
4258 {
4259 (void)null_data;
4260 (void)callback_action;
4261 (void)widget;
4262
4263 if(GLOBALS->helpbox_is_active)
4264 {
4265 help_text_bold("\n\nDelete Primary Marker");
4266 help_text(
4267 " removes the primary marker from the display if present."
4268 );
4269 return;
4270 }
4271
4272 DEBUG(printf("delete_unnamed marker()\n"));
4273
4274 if(GLOBALS->tims.marker!=-1)
4275 {
4276 Trptr t;
4277
4278 for(t=GLOBALS->traces.first;t;t=t->t_next)
4279 {
4280 if(t->asciivalue) { free_2(t->asciivalue); t->asciivalue=NULL; }
4281 }
4282
4283 for(t=GLOBALS->traces.buffer;t;t=t->t_next)
4284 {
4285 if(t->asciivalue) { free_2(t->asciivalue); t->asciivalue=NULL; }
4286 }
4287
4288 update_markertime(GLOBALS->tims.marker=-1);
4289 GLOBALS->signalwindow_width_dirty=1;
4290 MaxSignalLength();
4291 signalarea_configure_event(GLOBALS->signalarea, NULL);
4292 wavearea_configure_event(GLOBALS->wavearea, NULL);
4293 }
4294 }
4295
4296 /**/
4297 void collect_all_named_markers(gpointer null_data, guint callback_action, GtkWidget *widget)
4298 {
4299 (void)null_data;
4300 (void)callback_action;
4301 (void)widget;
4302
4303 int i;
4304 int dirty=0;
4305
4306 if(GLOBALS->helpbox_is_active)
4307 {
4308 help_text_bold("\n\nCollect All Named Markers");
4309 help_text(
4310 " simply collects any and all named markers which have"
4311 " been dropped."
4312 );
4313 return;
4314 }
4315
4316 DEBUG(printf("collect_all_unnamed_markers()\n"));
4317
4318 for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
4319 {
4320 if(GLOBALS->named_markers[i]!=-1)
4321 {
4322 GLOBALS->named_markers[i]=-1;
4323 dirty=1;
4324 }
4325
4326 if(GLOBALS->marker_names[i])
4327 {
4328 free_2(GLOBALS->marker_names[i]);
4329 GLOBALS->marker_names[i] = NULL;
4330 }
4331 }
4332
4333 if(dirty)
4334 {
4335 signalarea_configure_event(GLOBALS->signalarea, NULL);
4336 wavearea_configure_event(GLOBALS->wavearea, NULL);
4337 }
4338 }
4339 /**/
4340 void collect_named_marker(gpointer null_data, guint callback_action, GtkWidget *widget)
4341 {
4342 (void)null_data;
4343 (void)callback_action;
4344 (void)widget;
4345
4346 int i;
4347
4348 if(GLOBALS->helpbox_is_active)
4349 {
4350 help_text_bold("\n\nCollect Named Marker");
4351 help_text(
4352 " collects a named marker where the current primary (unnamed)"
4353 " marker is placed if there is a named marker at its position."
4354 );
4355 return;
4356 }
4357
4358 DEBUG(printf("collect_named_marker()\n"));
4359
4360 if(GLOBALS->tims.marker!=-1)
4361 {
4362 for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
4363 {
4364 if(GLOBALS->named_markers[i]==GLOBALS->tims.marker)
4365 {
4366 GLOBALS->named_markers[i]=-1;
4367 signalarea_configure_event(GLOBALS->signalarea, NULL);
4368 wavearea_configure_event(GLOBALS->wavearea, NULL);
4369
4370 if(GLOBALS->marker_names[i])
4371 {
4372 free_2(GLOBALS->marker_names[i]);
4373 GLOBALS->marker_names[i] = NULL;
4374 }
4375
4376 /* return; */
4377 }
4378 }
4379 }
4380 }
4381 /**/
4382 void drop_named_marker(gpointer null_data, guint callback_action, GtkWidget *widget)
4383 {
4384 (void)null_data;
4385 (void)callback_action;
4386 (void)widget;
4387
4388 int i;
4389
4390 if(GLOBALS->helpbox_is_active)
4391 {
4392 char nm_s[32];
4393
4394 sprintf(nm_s, "%d", WAVE_NUM_NAMED_MARKERS);
4395
4396 help_text_bold("\n\nDrop Named Marker");
4397 help_text(
4398 " drops a named marker where the current primary (unnamed)"
4399 " marker is placed. A maximum of "
4400 );
4401
4402 help_text(
4403 nm_s
4404 );
4405
4406 help_text(
4407 " named markers are allowed"
4408 " and the times for all must be different."
4409 );
4410 return;
4411 }
4412
4413
4414 DEBUG(printf("drop_named_marker()\n"));
4415
4416 if(GLOBALS->tims.marker!=-1)
4417 {
4418 /* only one per slot requirement removed...
4419 #if 0
4420 for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
4421 {
4422 if(GLOBALS->named_markers[i]==GLOBALS->tims.marker) return;
4423 }
4424 #endif
4425 ...only one per slot requirement removed */
4426
4427 for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
4428 {
4429 if(GLOBALS->named_markers[i]==-1)
4430 {
4431 GLOBALS->named_markers[i]=GLOBALS->tims.marker;
4432 signalarea_configure_event(GLOBALS->signalarea, NULL);
4433 wavearea_configure_event(GLOBALS->wavearea, NULL);
4434 return;
4435 }
4436 }
4437 }
4438 }
4439 /**/
4440 void menu_treesearch_cleanup(GtkWidget *widget, gpointer data)
4441 {
4442 (void)widget;
4443 (void)data;
4444
4445 MaxSignalLength();
4446 signalarea_configure_event(GLOBALS->signalarea, NULL);
4447 wavearea_configure_event(GLOBALS->wavearea, NULL);
4448 DEBUG(printf("menu_treesearch_cleanup()\n"));
4449 }
4450
4451 void menu_treesearch(gpointer null_data, guint callback_action, GtkWidget *widget)
4452 {
4453 (void)null_data;
4454 (void)callback_action;
4455 (void)widget;
4456
4457 if(GLOBALS->helpbox_is_active)
4458 {
4459 help_text_bold("\n\nSignal Search Tree");
4460 help_text(
4461 " provides an easy means of adding traces to the display."
4462 " Various functions are provided in the Signal Search Tree requester"
4463 " which allow searching a treelike hierarchy and bundling"
4464 " (coalescing individual bits into a single vector)."
4465 );
4466 return;
4467 }
4468
4469 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
4470
4471 treebox("Signal Search Tree",GTK_SIGNAL_FUNC(menu_treesearch_cleanup), NULL);
4472 }
4473 /**/
4474 void
4475 menu_showchangeall_cleanup(GtkWidget *widget, gpointer data)
4476 {
4477 (void)widget;
4478 (void)data;
4479
4480 Trptr t;
4481 TraceFlagsType flags;
4482
4483 t=GLOBALS->showchangeall_menu_c_1;
4484 if(t)
4485 {
4486 flags = t->flags & (TR_NUMMASK | TR_HIGHLIGHT | TR_ATTRIBS);
4487 while(t)
4488 {
4489 if((t->flags&TR_HIGHLIGHT)&&(!(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH)))&&(t->name))
4490 {
4491 t->flags = (t->flags & ~(TR_NUMMASK | TR_HIGHLIGHT | TR_ATTRIBS)) | flags;
4492 t->minmax_valid = 0; /* force analog traces to regenerate if necessary */
4493 }
4494 t=t->t_next;
4495 }
4496 }
4497
4498 GLOBALS->signalwindow_width_dirty=1;
4499 MaxSignalLength();
4500 signalarea_configure_event(GLOBALS->signalarea, NULL);
4501 wavearea_configure_event(GLOBALS->wavearea, NULL);
4502 DEBUG(printf("menu_showchangeall_cleanup()\n"));
4503 }
4504
4505 void
4506 menu_showchangeall(gpointer null_data, guint callback_action, GtkWidget *widget)
4507 {
4508 (void)null_data;
4509 (void)callback_action;
4510 (void)widget;
4511
4512 Trptr t;
4513
4514 if(GLOBALS->helpbox_is_active)
4515 {
4516 help_text_bold("\n\nShow-Change All Highlighted");
4517 help_text(
4518 " provides an easy means of changing trace attributes en masse."
4519 " Various functions are provided in a Show-Change requester."
4520 );
4521 return;
4522 }
4523
4524 DEBUG(printf("menu_showchangeall()\n"));
4525
4526 GLOBALS->showchangeall_menu_c_1=NULL;
4527 t=GLOBALS->traces.first;
4528 while(t)
4529 {
4530 if((t->flags&TR_HIGHLIGHT)&&(!(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH)))&&(t->name))
4531 {
4532 showchange("Show-Change All", GLOBALS->showchangeall_menu_c_1=t, GTK_SIGNAL_FUNC(menu_showchangeall_cleanup));
4533 return;
4534 }
4535 t=t->t_next;
4536 }
4537
4538 must_sel();
4539 }
4540
4541 /**/
4542 void
4543 menu_showchange_cleanup(GtkWidget *widget, gpointer data)
4544 {
4545 (void)widget;
4546 (void)data;
4547
4548 GLOBALS->signalwindow_width_dirty=1;
4549 MaxSignalLength();
4550 signalarea_configure_event(GLOBALS->signalarea, NULL);
4551 wavearea_configure_event(GLOBALS->wavearea, NULL);
4552 DEBUG(printf("menu_showchange_cleanup()\n"));
4553 }
4554
4555 void
4556 menu_showchange(gpointer null_data, guint callback_action, GtkWidget *widget)
4557 {
4558 (void)null_data;
4559 (void)callback_action;
4560 (void)widget;
4561
4562 Trptr t;
4563
4564 if(GLOBALS->helpbox_is_active)
4565 {
4566 help_text_bold("\n\nShow-Change First Highlighted");
4567 help_text(
4568 " provides a means of changing trace attributes for the"
4569 " first highlighted trace. "
4570 " Various functions are provided in a Show-Change requester. "
4571 " When a function is applied, the trace will be unhighlighted."
4572 );
4573 return;
4574 }
4575
4576 DEBUG(printf("menu_showchange()\n"));
4577
4578 t=GLOBALS->traces.first;
4579 while(t)
4580 {
4581 if((t->flags&TR_HIGHLIGHT)&&(!(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH)))&&(t->name))
4582 {
4583 showchange("Show-Change", t, GTK_SIGNAL_FUNC(menu_showchange_cleanup));
4584 return;
4585 }
4586 t=t->t_next;
4587 }
4588
4589 must_sel();
4590 }
4591 /**/
4592 void menu_remove_aliases(gpointer null_data, guint callback_action, GtkWidget *widget)
4593 {
4594 (void)null_data;
4595 (void)callback_action;
4596 (void)widget;
4597
4598 Trptr t;
4599 int dirty=0, none_selected = 1;
4600
4601 if(GLOBALS->helpbox_is_active)
4602 {
4603 help_text_bold("\n\nRemove Highlighted Aliases");
4604 help_text(
4605 " only works when at least one trace has been highlighted. "
4606 " Any aliased traces will have their names restored to their"
4607 " original names. As vectors get their names from aliases,"
4608 " vector aliases will not be removed."
4609 );
4610 return;
4611 }
4612
4613 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
4614
4615 t=GLOBALS->traces.first;
4616 while(t)
4617 {
4618 if(HasAlias(t) && IsSelected(t))
4619 {
4620 char *name_full;
4621 int was_packed = HIER_DEPACK_ALLOC;
4622
4623 free_2(t->name_full);
4624 t->name_full = NULL;
4625
4626 if(t->vector)
4627 {
4628 name_full = t->n.vec->bvname;
4629 }
4630 else
4631 {
4632 name_full = hier_decompress_flagged(t->n.nd->nname, &was_packed);
4633 }
4634
4635 t->name = name_full;
4636 if (GLOBALS->hier_max_level)
4637 {
4638 if(!was_packed)
4639 {
4640 t->name = hier_extract(t->name, GLOBALS->hier_max_level);
4641 }
4642 else
4643 {
4644 t->name = strdup_2(hier_extract(name_full, GLOBALS->hier_max_level));
4645 free_2(name_full);
4646 }
4647 }
4648
4649 if(was_packed) t->is_depacked = 1;
4650
4651 dirty = 1;
4652 }
4653 if (IsSelected(t)) none_selected = 0;
4654 t=t->t_next;
4655 }
4656
4657 if(dirty)
4658 {
4659 GLOBALS->signalwindow_width_dirty=1;
4660 MaxSignalLength();
4661 signalarea_configure_event(GLOBALS->signalarea, NULL);
4662 wavearea_configure_event(GLOBALS->wavearea, NULL);
4663 DEBUG(printf("menu_remove_aliases()\n"));
4664 }
4665 if (none_selected)
4666 {
4667 must_sel();
4668 }
4669 }
4670
4671
4672 static void alias_cleanup(GtkWidget *widget, gpointer data)
4673 {
4674 (void)widget;
4675 (void)data;
4676
4677 Trptr t = GLOBALS->trace_to_alias_menu_c_1;
4678
4679 if(GLOBALS->entrybox_text)
4680 {
4681 char *efix;
4682 /* code to turn '{' and '}' into '[' and ']' */
4683 if(!(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH)))
4684 {
4685 efix=GLOBALS->entrybox_text;
4686 while(*efix)
4687 {
4688 if(*efix=='{')
4689 {
4690 *efix='[';
4691 }
4692 if(*efix=='}')
4693 {
4694 *efix=']';
4695 }
4696 efix++;
4697 }
4698 }
4699
4700 if (CanAlias(t))
4701 {
4702 if(HasAlias(t)) free_2(t->name_full);
4703 t->name_full = (char *)malloc_2(1+strlen(GLOBALS->entrybox_text));
4704 strcpy(t->name_full, GLOBALS->entrybox_text);
4705 t->name = t->name_full;
4706 if(GLOBALS->hier_max_level)
4707 t->name = hier_extract(t->name, GLOBALS->hier_max_level);
4708
4709 t->flags&= ~TR_HIGHLIGHT;
4710 }
4711
4712 GLOBALS->signalwindow_width_dirty=1;
4713 MaxSignalLength();
4714 signalarea_configure_event(GLOBALS->signalarea, NULL);
4715 wavearea_configure_event(GLOBALS->wavearea, NULL);
4716 }
4717 }
4718
4719 void menu_alias(gpointer null_data, guint callback_action, GtkWidget *widget)
4720 {
4721 (void)null_data;
4722 (void)callback_action;
4723 (void)widget;
4724
4725 Trptr t;
4726
4727 if(GLOBALS->helpbox_is_active)
4728 {
4729 help_text_bold("\n\nAlias Highlighted Trace");
4730 help_text(
4731 " only works when at least one trace has been highlighted. "
4732 " With this function, you will be prompted for an alias"
4733 " name for the first highlighted trace. After successfully"
4734 " aliasing a trace, the aliased trace will be unhighlighted."
4735 " Single bits will be marked with a leading \"+\" and vectors"
4736 " will have no such designation. The purpose of this is to"
4737 " provide a fast method of determining which trace names are"
4738 " real and which ones are aliases."
4739 );
4740 return;
4741 }
4742
4743 GLOBALS->trace_to_alias_menu_c_1=NULL;
4744
4745 /* don't mess with sigs when dnd active */
4746 if(GLOBALS->dnd_state) { dnd_error(); return; }
4747
4748 t = GLOBALS->traces.first;
4749 while(t)
4750 {
4751 if(IsSelected(t)&&CanAlias(t))
4752 {
4753 GLOBALS->trace_to_alias_menu_c_1=t;
4754 break;
4755 }
4756 t=t->t_next;
4757 }
4758
4759 if(GLOBALS->trace_to_alias_menu_c_1)
4760 {
4761 int was_packed = HIER_DEPACK_ALLOC;
4762 char* current = GetFullName(GLOBALS->trace_to_alias_menu_c_1, &was_packed);
4763 ClearTraces();
4764 GLOBALS->trace_to_alias_menu_c_1->flags |= TR_HIGHLIGHT;
4765 entrybox("Alias Highlighted Trace",300,current,NULL,128,GTK_SIGNAL_FUNC(alias_cleanup));
4766 if(was_packed) { free_2(current); }
4767 }
4768 else
4769 {
4770 must_sel();
4771 }
4772 }
4773
4774
4775
4776
4777 /**/
4778 void menu_hiersearch_cleanup(GtkWidget *widget, gpointer data)
4779 {
4780 (void)widget;
4781 (void)data;
4782
4783 MaxSignalLength();
4784 signalarea_configure_event(GLOBALS->signalarea, NULL);
4785 wavearea_configure_event(GLOBALS->wavearea, NULL);
4786 DEBUG(printf("menu_hiersearch_cleanup()\n"));
4787 }
4788
4789 void menu_hiersearch(gpointer null_data, guint callback_action, GtkWidget *widget)
4790 {
4791 (void)null_data;
4792 (void)callback_action;
4793 (void)widget;
4794
4795 if(GLOBALS->helpbox_is_active)
4796 {
4797 help_text_bold("\n\nHierarchy Search");
4798 help_text(
4799 " provides an easy means of adding traces to the display in a text based"
4800 " treelike fashion."
4801 );
4802 return;
4803 }
4804
4805 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
4806
4807 hier_searchbox("Hierarchy Search",GTK_SIGNAL_FUNC(menu_hiersearch_cleanup));
4808 }
4809 /**/
4810 void menu_signalsearch_cleanup(GtkWidget *widget, gpointer data)
4811 {
4812 (void)widget;
4813 (void)data;
4814
4815 MaxSignalLength();
4816 signalarea_configure_event(GLOBALS->signalarea, NULL);
4817 wavearea_configure_event(GLOBALS->wavearea, NULL);
4818 DEBUG(printf("menu_signalsearch_cleanup()\n"));
4819 }
4820
4821 void menu_signalsearch(gpointer null_data, guint callback_action, GtkWidget *widget)
4822 {
4823 (void)null_data;
4824 (void)callback_action;
4825 (void)widget;
4826
4827 if(GLOBALS->helpbox_is_active)
4828 {
4829 help_text_bold("\n\nSignal Search Regexp");
4830 help_text(
4831 " provides an easy means of adding traces to the display. "
4832 " Various functions are provided in the Signal Search requester"
4833 " which allow searching using POSIX regular expressions and bundling"
4834 " (coalescing individual bits into a single vector). "
4835 );
4836 return;
4837 }
4838
4839 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
4840
4841 searchbox("Signal Search",GTK_SIGNAL_FUNC(menu_signalsearch_cleanup));
4842 }
4843 /**/
4844 static void
4845 regexp_highlight_generic(int mode)
4846 {
4847 if(GLOBALS->entrybox_text)
4848 {
4849 Trptr t;
4850 Ulong modebits;
4851 char dirty=0;
4852
4853 modebits=(mode)?TR_HIGHLIGHT:0;
4854
4855 strcpy(GLOBALS->regexp_string_menu_c_1, GLOBALS->entrybox_text);
4856 wave_regex_compile(GLOBALS->regexp_string_menu_c_1, WAVE_REGEX_SEARCH);
4857 free_2(GLOBALS->entrybox_text);
4858 t=GLOBALS->traces.first;
4859 while(t)
4860 {
4861 char *pnt;
4862
4863 pnt=(t->name)?t->name:""; /* handle (really) blank lines */
4864
4865 if(*pnt=='+') /* skip alias prefix if present */
4866 {
4867 pnt++;
4868 if(*pnt==' ')
4869 {
4870 pnt++;
4871 }
4872 }
4873
4874 if(wave_regex_match(pnt, WAVE_REGEX_SEARCH))
4875 {
4876 t->flags=((t->flags&(~TR_HIGHLIGHT))|modebits);
4877 dirty=1;
4878 }
4879
4880 t=t->t_next;
4881 }
4882
4883 if(dirty)
4884 {
4885 signalarea_configure_event(GLOBALS->signalarea, NULL);
4886 wavearea_configure_event(GLOBALS->wavearea, NULL);
4887 }
4888 }
4889 }
4890
4891 static void
4892 regexp_unhighlight_cleanup(GtkWidget *widget, gpointer data)
4893 {
4894 (void)widget;
4895 (void)data;
4896
4897 regexp_highlight_generic(0);
4898 }
4899
4900 void
4901 menu_regexp_unhighlight(gpointer null_data, guint callback_action, GtkWidget *widget)
4902 {
4903 (void)null_data;
4904 (void)callback_action;
4905 (void)widget;
4906
4907 if(GLOBALS->helpbox_is_active)
4908 {
4909 help_text_bold("\n\nUnHighlight Regexp");
4910 help_text(
4911 " brings up a text requester that will ask for a"
4912 " regular expression that may contain text with POSIX regular expressions."
4913 " All traces meeting this criterion / these criteria will be"
4914 " unhighlighted if they are currently highlighted."
4915 );
4916 return;
4917 }
4918
4919 entrybox("Regexp UnHighlight",300,GLOBALS->regexp_string_menu_c_1,NULL,128,GTK_SIGNAL_FUNC(regexp_unhighlight_cleanup));
4920 }
4921 /**/
4922 static void
4923 regexp_highlight_cleanup(GtkWidget *widget, gpointer data)
4924 {
4925 (void)widget;
4926 (void)data;
4927
4928 regexp_highlight_generic(1);
4929 }
4930
4931 void
4932 menu_regexp_highlight(gpointer null_data, guint callback_action, GtkWidget *widget)
4933 {
4934 (void)null_data;
4935 (void)callback_action;
4936 (void)widget;
4937
4938 if(GLOBALS->helpbox_is_active)
4939 {
4940 help_text_bold("\n\nHighlight Regexp");
4941 help_text(
4942 " brings up a text requester that will ask for a"
4943 " regular expression that may contain text with POSIX regular expressions."
4944 " All traces meeting this criterion / these criteria will be"
4945 " highlighted."
4946 );
4947 return;
4948 }
4949
4950 entrybox("Regexp Highlight",300,GLOBALS->regexp_string_menu_c_1,NULL,128,GTK_SIGNAL_FUNC(regexp_highlight_cleanup));
4951 }
4952
4953 /**/
4954
4955 #if GTK_CHECK_VERSION(2,14,0)
4956
4957 void
4958 menu_write_screengrab_cleanup(GtkWidget *widget, gpointer data)
4959 {
4960 (void)widget;
4961 (void)data;
4962
4963 GdkWindow *gw;
4964 gint w, h;
4965 GdkColormap *cm;
4966 GdkPixbuf *dest = NULL;
4967 GdkPixbuf *dest2;
4968 GError *err = NULL;
4969 gboolean succ = FALSE;
4970
4971 if(!GLOBALS->filesel_ok)
4972 {
4973 return;
4974 }
4975
4976 gw = gtk_widget_get_window(GTK_WIDGET(GLOBALS->mainwindow));
4977 if(gw)
4978 {
4979 gdk_drawable_get_size(gw, &w, &h);
4980 cm = gdk_drawable_get_colormap(gw);
4981 if(cm)
4982 {
4983 dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, w, h);
4984 if(dest)
4985 {
4986 dest2 = gdk_pixbuf_get_from_drawable(dest, gw, cm, 0, 0, 0, 0, w, h);
4987 if(dest2)
4988 {
4989 succ = gdk_pixbuf_save (dest2, *GLOBALS->fileselbox_text, "png", &err, NULL);
4990 }
4991 }
4992 }
4993 }
4994
4995 if(dest)
4996 {
4997 g_object_unref(dest);
4998 }
4999
5000 if(!succ)
5001 {
5002 fprintf(stderr, "Error opening imagegrab file '%s' for writing.\n",*GLOBALS->fileselbox_text);
5003 perror("Why");
5004 errno=0;
5005 }
5006 else
5007 {
5008 wave_gconf_client_set_string("/current/imagegrab", GLOBALS->filesel_imagegrab);
5009 }
5010 }
5011
5012 void
5013 menu_write_screengrab_as(gpointer null_data, guint callback_action, GtkWidget *widget)
5014 {
5015 (void)null_data;
5016 (void)callback_action;
5017 (void)widget;
5018
5019 if(GLOBALS->helpbox_is_active)
5020 {
5021 help_text_bold("\n\nGrab To File");
5022 help_text(
5023 " will open a file requester that will ask for the name"
5024 " to be used for a PNG format image grab of the main GTKWave window."
5025 " Note that if the main window is covered by other windows or"
5026 " is partially offscreen, the grabbed image might not appear properly."
5027 );
5028 return;
5029 }
5030
5031 errno = 0;
5032 fileselbox("Grab To File",&GLOBALS->filesel_imagegrab,GTK_SIGNAL_FUNC(menu_write_screengrab_cleanup), GTK_SIGNAL_FUNC(NULL), "*.png", 1);
5033 }
5034
5035 #endif
5036
5037 /**/
5038
5039 void
5040 menu_write_save_cleanup(GtkWidget *widget, gpointer data)
5041 {
5042 (void)widget;
5043 (void)data;
5044
5045 FILE *wave;
5046 int len;
5047
5048 if(!GLOBALS->filesel_ok)
5049 {
5050 return;
5051 }
5052
5053 len = strlen(*GLOBALS->fileselbox_text);
5054 if((!len) || ((*GLOBALS->fileselbox_text)[len-1] == '/')
5055 #if !defined __MINGW32__ && !defined _MSC_VER
5056 || ((*GLOBALS->fileselbox_text)[len-1] == '\\')
5057 #endif
5058 )
5059 {
5060 GLOBALS->save_success_menu_c_1 = 2;
5061 return;
5062 }
5063
5064 if(!(wave=fopen(*GLOBALS->fileselbox_text,"wb")))
5065 {
5066 fprintf(stderr, "Error opening save file '%s' for writing.\n",*GLOBALS->fileselbox_text);
5067 perror("Why");
5068 errno=0;
5069 }
5070 else
5071 {
5072 write_save_helper(*GLOBALS->fileselbox_text, wave);
5073 wave_gconf_client_set_string("/current/savefile", GLOBALS->filesel_writesave);
5074 GLOBALS->save_success_menu_c_1 = 1;
5075 fclose(wave);
5076 }
5077
5078 }
5079
5080 void
5081 menu_write_save_file_as(gpointer null_data, guint callback_action, GtkWidget *widget)
5082 {
5083 (void)null_data;
5084 (void)callback_action;
5085 (void)widget;
5086
5087 if(GLOBALS->helpbox_is_active)
5088 {
5089 help_text_bold("\n\nWrite Save File As");
5090 help_text(
5091 " will open a file requester that will ask for the name"
5092 " of a GTKWave save file. The contents of the save file"
5093 " generated will be the traces as well as their"
5094 " format (binary, decimal, hex, reverse, etc.) which"
5095 " are currently a part of the display. Marker positional"
5096 " data and the zoom factor are also a part of the save file."
5097 );
5098 return;
5099 }
5100
5101 fileselbox("Write Save File",&GLOBALS->filesel_writesave,GTK_SIGNAL_FUNC(menu_write_save_cleanup), GTK_SIGNAL_FUNC(NULL), GLOBALS->is_gtkw_save_file ? "*.gtkw" : "*.sav", 1);
5102 }
5103
5104 void
5105 menu_write_save_file(gpointer null_data, guint callback_action, GtkWidget *widget)
5106 {
5107 (void)null_data;
5108 (void)callback_action;
5109 (void)widget;
5110 int len = 0;
5111
5112 if(GLOBALS->helpbox_is_active)
5113 {
5114 help_text_bold("\n\nWrite Save File");
5115 help_text(
5116 " will invoke Write Save File As if no save file name has been specified previously."
5117 " Otherwise it will write the save file data without prompting."
5118 );
5119 return;
5120 }
5121
5122 if(GLOBALS->filesel_writesave)
5123 {
5124 len = strlen(GLOBALS->filesel_writesave);
5125 }
5126
5127 if ((!len) || (GLOBALS->filesel_writesave[len-1] == '/')
5128 #if !defined __MINGW32__ && !defined _MSC_VER
5129 || (GLOBALS->filesel_writesave[len-1] == '\\')
5130 #endif
5131 )
5132 {
5133 fileselbox("Write Save File",&GLOBALS->filesel_writesave,GTK_SIGNAL_FUNC(menu_write_save_cleanup), GTK_SIGNAL_FUNC(NULL), GLOBALS->is_gtkw_save_file ? "*.gtkw" : "*.sav", 1);
5134 }
5135 else
5136 {
5137 GLOBALS->filesel_ok = 1;
5138 GLOBALS->save_success_menu_c_1 = 0;
5139 GLOBALS->fileselbox_text = &GLOBALS->filesel_writesave;
5140 menu_write_save_cleanup(NULL, NULL);
5141 if(GLOBALS->save_success_menu_c_1 != 2) /* cancelled */
5142 {
5143 if(GLOBALS->save_success_menu_c_1)
5144 {
5145 status_text("Wrote save file OK.\n");
5146 }
5147 else
5148 {
5149 status_text("Problem writing save file.\n");
5150 }
5151 }
5152 }
5153 }
5154 /**/
5155
5156 void
5157 menu_read_save_cleanup(GtkWidget *widget, gpointer data)
5158 {
5159 (void)widget;
5160 (void)data;
5161
5162 if(GLOBALS->filesel_ok)
5163 {
5164 char *wname;
5165
5166 DEBUG(printf("Read Save Fini: %s\n", *GLOBALS->fileselbox_text));
5167
5168 wname=*GLOBALS->fileselbox_text;
5169 wave_gconf_client_set_string("/current/savefile", wname);
5170 read_save_helper(wname, NULL, NULL, NULL, NULL, NULL);
5171 }
5172 }
5173
5174
5175 void
5176 menu_read_save_file(gpointer null_data, guint callback_action, GtkWidget *widget)
5177 {
5178 (void)null_data;
5179 (void)callback_action;
5180 (void)widget;
5181
5182 if(GLOBALS->helpbox_is_active)
5183 {
5184 help_text_bold("\n\nRead Save File");
5185 help_text(
5186 " will open a file requester that will ask for the name"
5187 " of a GTKWave save file. The contents of the save file"
5188 " will determine which traces and vectors as well as their"
5189 " format (binary, decimal, hex, reverse, etc.) are to be"
5190 " appended to the display. Note that the marker positional"
5191 " data and zoom factor present in the save file will"
5192 " replace any current settings."
5193 );
5194 return;
5195 }
5196
5197 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
5198
5199 fileselbox("Read Save File",&GLOBALS->filesel_writesave,GTK_SIGNAL_FUNC(menu_read_save_cleanup), GTK_SIGNAL_FUNC(NULL), GLOBALS->is_gtkw_save_file ? "*.gtkw" : "*.sav", 0);
5200 }
5201
5202 #if !defined _MSC_VER
5203 /**/
5204 void
5205 menu_read_stems_cleanup(GtkWidget *widget, gpointer data)
5206 {
5207 (void)widget;
5208 (void)data;
5209
5210 char *fname;
5211
5212 if(GLOBALS->filesel_ok)
5213 {
5214 DEBUG(printf("Read Stems Fini: %s\n", *GLOBALS->fileselbox_text));
5215
5216 fname=*GLOBALS->fileselbox_text;
5217 if((fname)&&strlen(fname))
5218 {
5219 activate_stems_reader(fname);
5220 }
5221 }
5222 }
5223 /**/
5224 void
5225 menu_read_stems_file(gpointer null_data, guint callback_action, GtkWidget *widget)
5226 {
5227 (void)null_data;
5228 (void)callback_action;
5229 (void)widget;
5230
5231 if(GLOBALS->helpbox_is_active)
5232 {
5233 help_text_bold("\n\nRead Verilog Stemsfile");
5234 help_text(
5235 " will open a file requester that will ask for the name"
5236 " of a Verilog stemsfile. This will then launch an RTL browser and allow source code annotation based on"
5237 " the primary marker position."
5238 " Stems files are generated by xml2stems. Please see its manpage"
5239 " for syntax and more information on stems file generation."
5240 );
5241 return;
5242 }
5243
5244 if(!stems_are_active())
5245 {
5246 if(GLOBALS->stems_type != WAVE_ANNO_NONE)
5247 {
5248 fileselbox("Read Verilog Stemsfile",&GLOBALS->stems_name, GTK_SIGNAL_FUNC(menu_read_stems_cleanup), GTK_SIGNAL_FUNC(NULL), NULL, 0);
5249 }
5250 else
5251 {
5252 status_text("Unsupported dumpfile type for rtlbrowse.\n");
5253 }
5254 }
5255 }
5256 #endif
5257
5258 /**/
5259 void
5260 menu_read_log_cleanup(GtkWidget *widget, gpointer data)
5261 {
5262 (void)widget;
5263 (void)data;
5264
5265 char *fname ;
5266
5267 if(GLOBALS->filesel_ok)
5268 {
5269 DEBUG(printf("Read Log Fini: %s\n", *GLOBALS->fileselbox_text));
5270
5271 fname=*GLOBALS->fileselbox_text;
5272 if((fname)&&strlen(fname))
5273 {
5274 logbox("Logfile viewer", 480, fname);
5275 }
5276 }
5277 }
5278 /**/
5279 void
5280 menu_read_log_file(gpointer null_data, guint callback_action, GtkWidget *widget)
5281 {
5282 (void)null_data;
5283 (void)callback_action;
5284 (void)widget;
5285
5286 if(GLOBALS->helpbox_is_active)
5287 {
5288 help_text_bold("\n\nRead Logfile");
5289 help_text(
5290 " will open a file requester that will ask for the name"
5291 " of a plaintext simulation log. By clicking on the numbers in the logfile,"
5292 " the marker will jump to the appropriate time value in the wave window."
5293 );
5294 return;
5295 }
5296
5297 fileselbox("Read Logfile",&GLOBALS->filesel_logfile_menu_c_1,GTK_SIGNAL_FUNC(menu_read_log_cleanup), GTK_SIGNAL_FUNC(NULL), NULL, 0);
5298 }
5299
5300 /**/
5301 void
5302 menu_read_script_cleanup(GtkWidget *widget, gpointer data)
5303 {
5304 (void)widget;
5305 (void)data;
5306
5307 char *fname;
5308
5309 if(GLOBALS->filesel_ok)
5310 {
5311 DEBUG(printf("Read Script Fini: %s\n", *GLOBALS->fileselbox_text));
5312
5313 fname=*GLOBALS->fileselbox_text;
5314 if((fname)&&strlen(fname))
5315 {
5316 execute_script(fname, 0);
5317 }
5318 }
5319 }
5320 /**/
5321 void
5322 menu_read_script_file(gpointer null_data, guint callback_action, GtkWidget *widget)
5323 {
5324 (void)null_data;
5325 (void)callback_action;
5326 (void)widget;
5327
5328 if(GLOBALS->helpbox_is_active)
5329 {
5330 help_text_bold("\n\nRead Script File");
5331 help_text(
5332 " will open a file requester that will ask for the name"
5333 " of a TCL script to run. This menu option itself is not callable"
5334 " by TCL scripts."
5335 );
5336 return;
5337 }
5338
5339 fileselbox("Read Script File",&GLOBALS->filesel_scriptfile_menu,GTK_SIGNAL_FUNC(menu_read_script_cleanup), GTK_SIGNAL_FUNC(NULL), "*.tcl", 0);
5340 }
5341
5342 /**/
5343 void
5344 menu_insert_blank_traces(gpointer null_data, guint callback_action, GtkWidget *widget)
5345 {
5346 (void)null_data;
5347 (void)callback_action;
5348 (void)widget;
5349
5350 if(GLOBALS->helpbox_is_active)
5351 {
5352 help_text_bold("\n\nInsert Blank");
5353 help_text(
5354 " inserts a blank trace after the last highlighted trace."
5355 " If no traces are highlighted, the blank is inserted after"
5356 " the last trace."
5357 );
5358 return;
5359 }
5360
5361 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
5362
5363 DEBUG(printf("Insert Blank Trace\n"));
5364
5365 InsertBlankTrace(NULL, 0);
5366 signalarea_configure_event(GLOBALS->signalarea, NULL);
5367 wavearea_configure_event(GLOBALS->wavearea, NULL);
5368 }
5369
5370 void
5371 menu_insert_analog_height_extension(gpointer null_data, guint callback_action, GtkWidget *widget)
5372 {
5373 (void)null_data;
5374 (void)callback_action;
5375 (void)widget;
5376
5377 if(GLOBALS->helpbox_is_active)
5378 {
5379 help_text_bold("\n\nInsert Analog Height Extension");
5380 help_text(
5381 " inserts a blank analog extension trace after the last highlighted trace."
5382 " If no traces are highlighted, the blank is inserted after"
5383 " the last trace. This type of trace is used to increase the height of analog traces."
5384 );
5385 return;
5386 }
5387
5388 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
5389
5390 DEBUG(printf("Insert Analog Blank Trace\n"));
5391
5392 InsertBlankTrace(NULL, TR_ANALOG_BLANK_STRETCH);
5393 signalarea_configure_event(GLOBALS->signalarea, NULL);
5394 wavearea_configure_event(GLOBALS->wavearea, NULL);
5395 }
5396 /**/
5397 static void
5398 comment_trace_cleanup(GtkWidget *widget, gpointer data)
5399 {
5400 (void)widget;
5401 (void)data;
5402
5403 InsertBlankTrace(GLOBALS->entrybox_text, 0);
5404 if(GLOBALS->entrybox_text) { free_2(GLOBALS->entrybox_text); GLOBALS->entrybox_text=NULL; }
5405 GLOBALS->signalwindow_width_dirty=1;
5406 MaxSignalLength();
5407 signalarea_configure_event(GLOBALS->signalarea, NULL);
5408 wavearea_configure_event(GLOBALS->wavearea, NULL);
5409 }
5410
5411 void
5412 menu_insert_comment_traces(gpointer null_data, guint callback_action, GtkWidget *widget)
5413 {
5414 (void)null_data;
5415 (void)callback_action;
5416 (void)widget;
5417
5418 if(GLOBALS->helpbox_is_active)
5419 {
5420 help_text_bold("\n\nInsert Comment");
5421 help_text(
5422 " inserts a comment trace after the last highlighted trace."
5423 " If no traces are highlighted, the comment is inserted after"
5424 " the last trace."
5425 );
5426 return;
5427 }
5428
5429 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
5430
5431 DEBUG(printf("Insert Comment Trace\n"));
5432
5433 entrybox("Insert Comment Trace",300,"",NULL,128,GTK_SIGNAL_FUNC(comment_trace_cleanup));
5434 }
5435 /**/
5436 static void strace_repcnt_cleanup(GtkWidget *widget, gpointer data)
5437 {
5438 (void)widget;
5439 (void)data;
5440
5441 if(GLOBALS->entrybox_text)
5442 {
5443 GLOBALS->strace_repeat_count = atoi_64(GLOBALS->entrybox_text);
5444
5445 free_2(GLOBALS->entrybox_text);
5446 GLOBALS->entrybox_text=NULL;
5447 }
5448 }
5449
5450 void menu_strace_repcnt(gpointer null_data, guint callback_action, GtkWidget *widget)
5451 {
5452 (void)null_data;
5453 (void)callback_action;
5454 (void)widget;
5455
5456 char gt[32];
5457
5458 if(GLOBALS->helpbox_is_active)
5459 {
5460 help_text_bold("\n\nSet Pattern Search Repeat Count");
5461 help_text(
5462 " sets the number of times that both edge and pattern searches iterate forward or backward when marker forward/backward is selected."
5463 " Default value is one. This can be used, for example, to skip forward 10 clock edges at a time rather than a single edge."
5464 );
5465 return;
5466 }
5467
5468 sprintf(gt, "%d", GLOBALS->strace_repeat_count);
5469 entrybox("Repeat Count",300,gt,NULL,20,GTK_SIGNAL_FUNC(strace_repcnt_cleanup));
5470 }
5471 /**/
5472 void movetotime_cleanup(GtkWidget *widget, gpointer data)
5473 {
5474 (void)widget;
5475 (void)data;
5476
5477 if(GLOBALS->entrybox_text)
5478 {
5479 TimeType gt = GLOBALS->tims.first;
5480 char update_string[128];
5481 char timval[40];
5482 GtkAdjustment *hadj;
5483 TimeType pageinc;
5484
5485 if((GLOBALS->entrybox_text[0] >= 'A' && GLOBALS->entrybox_text[0] <= 'Z')||(GLOBALS->entrybox_text[0] >= 'a' && GLOBALS->entrybox_text[0] <= 'z'))
5486 {
5487 char *su = GLOBALS->entrybox_text;
5488 int uch;
5489 while(*su)
5490 {
5491 uch = toupper((int)(unsigned char)*su);
5492 *su = uch;
5493 su++;
5494 }
5495
5496 uch = bijective_marker_id_string_hash(GLOBALS->entrybox_text);
5497
5498 if((uch >= 0)&&(uch < WAVE_NUM_NAMED_MARKERS))
5499 {
5500 gt=GLOBALS->named_markers[uch];
5501 }
5502 }
5503 else
5504 {
5505 gt=unformat_time(GLOBALS->entrybox_text, GLOBALS->time_dimension);
5506 gt -= GLOBALS->global_time_offset;
5507 }
5508 free_2(GLOBALS->entrybox_text);
5509 GLOBALS->entrybox_text=NULL;
5510
5511 if(gt<GLOBALS->tims.first) gt=GLOBALS->tims.first;
5512 else if(gt>GLOBALS->tims.last) gt=GLOBALS->tims.last;
5513
5514 hadj=GTK_ADJUSTMENT(GLOBALS->wave_hslider);
5515 hadj->value=gt;
5516
5517 pageinc=(TimeType)(((gdouble)GLOBALS->wavewidth)*GLOBALS->nspx);
5518 if(gt<(GLOBALS->tims.last-pageinc+1))
5519 GLOBALS->tims.timecache=gt;
5520 else
5521 {
5522 GLOBALS->tims.timecache=GLOBALS->tims.last-pageinc+1;
5523 if(GLOBALS->tims.timecache<GLOBALS->tims.first) GLOBALS->tims.timecache=GLOBALS->tims.first;
5524 }
5525
5526 reformat_time(timval,GLOBALS->tims.timecache + GLOBALS->global_time_offset,GLOBALS->time_dimension);
5527 sprintf(update_string, "Moved to time: %s\n", timval);
5528 status_text(update_string);
5529
5530 time_update();
5531 }
5532 }
5533
5534 void menu_movetotime(gpointer null_data, guint callback_action, GtkWidget *widget)
5535 {
5536 (void)null_data;
5537 (void)callback_action;
5538 (void)widget;
5539
5540 char gt[32];
5541
5542 if(GLOBALS->helpbox_is_active)
5543 {
5544 help_text_bold("\n\nMove To Time");
5545 help_text(
5546 " scrolls the waveform display such that the left border"
5547 " is the time entered in the requester."
5548 " Use one of the letters A-Z to move to a named marker."
5549 );
5550 return;
5551 }
5552
5553 reformat_time(gt, GLOBALS->tims.start + GLOBALS->global_time_offset, GLOBALS->time_dimension);
5554
5555 entrybox("Move To Time",200,gt,NULL,20,GTK_SIGNAL_FUNC(movetotime_cleanup));
5556 }
5557 /**/
5558 static void fetchsize_cleanup(GtkWidget *widget, gpointer data)
5559 {
5560 (void)widget;
5561 (void)data;
5562
5563 if(GLOBALS->entrybox_text)
5564 {
5565 TimeType fw;
5566 char update_string[128];
5567 fw=unformat_time(GLOBALS->entrybox_text, GLOBALS->time_dimension);
5568 if(fw<1)
5569 {
5570 fw=GLOBALS->fetchwindow; /* in case they try to pull 0 or <0 */
5571 }
5572 else
5573 {
5574 GLOBALS->fetchwindow=fw;
5575 }
5576 free_2(GLOBALS->entrybox_text);
5577 GLOBALS->entrybox_text=NULL;
5578 sprintf(update_string, "Fetch Size is now: "TTFormat"\n", fw);
5579 status_text(update_string);
5580 }
5581 }
5582
5583 void menu_fetchsize(gpointer null_data, guint callback_action, GtkWidget *widget)
5584 {
5585 (void)null_data;
5586 (void)callback_action;
5587 (void)widget;
5588
5589 char fw[32];
5590
5591 if(GLOBALS->helpbox_is_active)
5592 {
5593 help_text_bold("\n\nFetch Size");
5594 help_text(
5595 " brings up a requester which allows input of the"
5596 " number of ticks used for fetch/discard operations."
5597 " Default is 100."
5598 );
5599 return;
5600 }
5601
5602 reformat_time(fw, GLOBALS->fetchwindow, GLOBALS->time_dimension);
5603
5604 entrybox("New Fetch Size",200,fw,NULL,20,GTK_SIGNAL_FUNC(fetchsize_cleanup));
5605 }
5606 /**/
5607 void zoomsize_cleanup(GtkWidget *widget, gpointer data)
5608 {
5609 (void)widget;
5610 (void)data;
5611
5612 if(GLOBALS->entrybox_text)
5613 {
5614 float f;
5615 char update_string[128];
5616
5617 sscanf(GLOBALS->entrybox_text, "%f", &f);
5618 if(f>0.0)
5619 {
5620 f=0.0; /* in case they try to go out of range */
5621 }
5622 else
5623 if(f<-62.0)
5624 {
5625 f=-62.0; /* in case they try to go out of range */
5626 }
5627
5628 GLOBALS->tims.prevzoom=GLOBALS->tims.zoom;
5629 GLOBALS->tims.zoom=(gdouble)f;
5630 calczoom(GLOBALS->tims.zoom);
5631 fix_wavehadj();
5632
5633 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "changed");
5634 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "value_changed");
5635
5636 free_2(GLOBALS->entrybox_text);
5637 GLOBALS->entrybox_text=NULL;
5638 sprintf(update_string, "Zoom Amount is now: %g\n", f);
5639 status_text(update_string);
5640 }
5641 }
5642
5643 void menu_zoomsize(gpointer null_data, guint callback_action, GtkWidget *widget)
5644 {
5645 (void)null_data;
5646 (void)callback_action;
5647 (void)widget;
5648
5649 char za[32];
5650
5651 if(GLOBALS->helpbox_is_active)
5652 {
5653 help_text_bold("\n\nZoom Amount");
5654 help_text(
5655 " allows entry of zero or a negative value for the display"
5656 " zoom. Zero is no magnification."
5657 );
5658 return;
5659 }
5660
5661
5662 sprintf(za,"%g",(float)(GLOBALS->tims.zoom));
5663
5664 entrybox("New Zoom Amount",200,za,NULL,20,GTK_SIGNAL_FUNC(zoomsize_cleanup));
5665 }
5666 /**/
5667 static void zoombase_cleanup(GtkWidget *widget, gpointer data)
5668 {
5669 (void)widget;
5670 (void)data;
5671
5672 if(GLOBALS->entrybox_text)
5673 {
5674 float za;
5675 char update_string[128];
5676 sscanf(GLOBALS->entrybox_text, "%f", &za);
5677 if(za>10.0)
5678 {
5679 za=10.0;
5680 }
5681 else
5682 if(za<1.5)
5683 {
5684 za=1.5;
5685 }
5686
5687 GLOBALS->zoombase=(gdouble)za;
5688 calczoom(GLOBALS->tims.zoom);
5689 fix_wavehadj();
5690
5691 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "changed");
5692 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)), "value_changed");
5693
5694 free_2(GLOBALS->entrybox_text);
5695 GLOBALS->entrybox_text=NULL;
5696 sprintf(update_string, "Zoom Base is now: %g\n", za);
5697 status_text(update_string);
5698 }
5699 }
5700
5701 void menu_zoombase(gpointer null_data, guint callback_action, GtkWidget *widget)
5702 {
5703 (void)null_data;
5704 (void)callback_action;
5705 (void)widget;
5706
5707 char za[32];
5708
5709 if(GLOBALS->helpbox_is_active)
5710 {
5711 help_text_bold("\n\nZoom Base");
5712 help_text(
5713 " allows entry of a zoom base for the zoom (magnification per integer step)"
5714 " Allowable values are 1.5 to 10.0. Default is 2.0."
5715 );
5716 return;
5717 }
5718
5719
5720 sprintf(za,"%g",GLOBALS->zoombase);
5721
5722 entrybox("New Zoom Base Amount",200,za,NULL,20,GTK_SIGNAL_FUNC(zoombase_cleanup));
5723 }
5724 /**/
5725 static void colorformat(int color)
5726 {
5727 Trptr t;
5728 int fix=0;
5729 int color_prev = WAVE_COLOR_NORMAL;
5730 int is_first = 0;
5731
5732 if((t=GLOBALS->traces.first))
5733 {
5734 while(t)
5735 {
5736 if(IsSelected(t)&&!IsShadowed(t))
5737 {
5738 if(color != WAVE_COLOR_CYCLE)
5739 {
5740 t->t_color = color;
5741 }
5742 else
5743 {
5744 if(!is_first)
5745 {
5746 is_first = 1;
5747 if(t->t_color == WAVE_COLOR_NORMAL) { color_prev = WAVE_COLOR_RED; } else { color_prev = t->t_color; }
5748 }
5749 else
5750 {
5751 color_prev++;
5752 }
5753
5754 if(color_prev > WAVE_COLOR_VIOLET) color_prev = WAVE_COLOR_RED;
5755 t->t_color = color_prev;
5756 }
5757 fix=1;
5758 }
5759 t=t->t_next;
5760 }
5761 if(fix)
5762 {
5763 GLOBALS->signalwindow_width_dirty=1;
5764 MaxSignalLength();
5765 signalarea_configure_event(GLOBALS->signalarea, NULL);
5766 wavearea_configure_event(GLOBALS->wavearea, NULL);
5767 }
5768 }
5769 }
5770
5771 void
5772 menu_colorformat_0(gpointer null_data, guint callback_action, GtkWidget *widget)
5773 {
5774 (void)null_data;
5775 (void)callback_action;
5776 (void)widget;
5777
5778 if(GLOBALS->helpbox_is_active)
5779 {
5780 help_text_bold("\n\nColor Format Normal");
5781 help_text(
5782 " uses normal waveform colorings for all selected traces."
5783 );
5784 return;
5785 }
5786
5787 colorformat(WAVE_COLOR_NORMAL);
5788 }
5789
5790 void
5791 menu_colorformat_1(gpointer null_data, guint callback_action, GtkWidget *widget)
5792 {
5793 (void)null_data;
5794 (void)callback_action;
5795 (void)widget;
5796
5797 if(GLOBALS->helpbox_is_active)
5798 {
5799 help_text_bold("\n\nColor Format Red");
5800 help_text(
5801 " uses red waveform colorings for all selected traces."
5802 );
5803 return;
5804 }
5805
5806 colorformat(WAVE_COLOR_RED);
5807 }
5808
5809 void
5810 menu_colorformat_2(gpointer null_data, guint callback_action, GtkWidget *widget)
5811 {
5812 (void)null_data;
5813 (void)callback_action;
5814 (void)widget;
5815
5816 if(GLOBALS->helpbox_is_active)
5817 {
5818 help_text_bold("\n\nColor Format Orange");
5819 help_text(
5820 " uses orange waveform colorings for all selected traces."
5821 );
5822 return;
5823 }
5824
5825 colorformat(WAVE_COLOR_ORANGE);
5826 }
5827
5828 void
5829 menu_colorformat_3(gpointer null_data, guint callback_action, GtkWidget *widget)
5830 {
5831 (void)null_data;
5832 (void)callback_action;
5833 (void)widget;
5834
5835 if(GLOBALS->helpbox_is_active)
5836 {
5837 help_text_bold("\n\nColor Format Yellow");
5838 help_text(
5839 " uses yellow waveform colorings for all selected traces."
5840 );
5841 return;
5842 }
5843
5844 colorformat(WAVE_COLOR_YELLOW);
5845 }
5846
5847 void
5848 menu_colorformat_4(gpointer null_data, guint callback_action, GtkWidget *widget)
5849 {
5850 (void)null_data;
5851 (void)callback_action;
5852 (void)widget;
5853
5854 if(GLOBALS->helpbox_is_active)
5855 {
5856 help_text_bold("\n\nColor Format Green");
5857 help_text(
5858 " uses green waveform colorings for all selected traces."
5859 );
5860 return;
5861 }
5862
5863 colorformat(WAVE_COLOR_GREEN);
5864 }
5865
5866 void
5867 menu_colorformat_5(gpointer null_data, guint callback_action, GtkWidget *widget)
5868 {
5869 (void)null_data;
5870 (void)callback_action;
5871 (void)widget;
5872
5873 if(GLOBALS->helpbox_is_active)
5874 {
5875 help_text_bold("\n\nColor Format Blue");
5876 help_text(
5877 " uses blue waveform colorings for all selected traces."
5878 );
5879 return;
5880 }
5881
5882 colorformat(WAVE_COLOR_BLUE);
5883 }
5884
5885 void
5886 menu_colorformat_6(gpointer null_data, guint callback_action, GtkWidget *widget)
5887 {
5888 (void)null_data;
5889 (void)callback_action;
5890 (void)widget;
5891
5892 if(GLOBALS->helpbox_is_active)
5893 {
5894 help_text_bold("\n\nColor Format Indigo");
5895 help_text(
5896 " uses indigo waveform colorings for all selected traces."
5897 );
5898 return;
5899 }
5900
5901 colorformat(WAVE_COLOR_INDIGO);
5902 }
5903
5904 void
5905 menu_colorformat_7(gpointer null_data, guint callback_action, GtkWidget *widget)
5906 {
5907 (void)null_data;
5908 (void)callback_action;
5909 (void)widget;
5910
5911 if(GLOBALS->helpbox_is_active)
5912 {
5913 help_text_bold("\n\nColor Format Violet");
5914 help_text(
5915 " uses violet waveform colorings for all selected traces."
5916 );
5917 return;
5918 }
5919
5920 colorformat(WAVE_COLOR_VIOLET);
5921 }
5922
5923 void
5924 menu_colorformat_cyc(gpointer null_data, guint callback_action, GtkWidget *widget)
5925 {
5926 (void)null_data;
5927 (void)callback_action;
5928 (void)widget;
5929
5930 if(GLOBALS->helpbox_is_active)
5931 {
5932 help_text_bold("\n\nColor Format Cycle");
5933 help_text(
5934 " uses cycling waveform colorings for all selected traces."
5935 );
5936 return;
5937 }
5938
5939 colorformat(WAVE_COLOR_CYCLE);
5940 }
5941 /**/
5942
5943 char **grow_array(char ***src, int *siz, char *str)
5944 {
5945 if(!*src)
5946 {
5947 *src = malloc_2(sizeof(char *));
5948 (*src)[0] = str;
5949 *siz = 1;
5950 }
5951 else
5952 {
5953 *src = realloc_2(*src, (*siz + 1) * sizeof(char *));
5954 (*src)[*siz] = str;
5955 *siz = *siz + 1;
5956 }
5957
5958 return(*src);
5959 }
5960
5961
5962 #if WAVE_USE_GTK2
5963 static void open_index_in_forked_editor(uint32_t idx, int typ)
5964 {
5965 if(idx)
5966 {
5967 int lineno = 1;
5968 char *edname = getenv("GTKWAVE_EDITOR");
5969 char *fname = NULL;
5970 FILE *ftest = NULL;
5971
5972 if(GLOBALS->editor_name)
5973 {
5974 edname = GLOBALS->editor_name; /* rcfile "editor" variable first */
5975 }
5976 else
5977 {
5978 if(edname)
5979 {
5980 /* ok, env var GTKWAVE_EDITOR second */
5981 }
5982 #ifdef GEDIT_PATH
5983 else
5984 {
5985 /* fallback */
5986 edname = GEDIT_PATH;
5987 }
5988 #endif
5989 }
5990
5991 #ifdef MAC_INTEGRATION
5992 if(!edname)
5993 {
5994 edname = "open -t"; /* Use OSX TextEdit as editor of last resort */
5995 }
5996 #endif
5997
5998 idx--;
5999 if(typ == FST_MT_SOURCESTEM)
6000 {
6001 lineno = GLOBALS->stem_struct_base[idx].stem_line_number;
6002 fname = GLOBALS->stem_path_string_table[GLOBALS->stem_struct_base[idx].stem_idx];
6003 }
6004 else
6005 {
6006 lineno = GLOBALS->istem_struct_base[idx].stem_line_number;
6007 fname = GLOBALS->stem_path_string_table[GLOBALS->istem_struct_base[idx].stem_idx];
6008 }
6009
6010 #ifdef __MINGW32__
6011 {
6012 fprintf(stderr, "GTKWAVE | Not supported in Windows!\n");
6013 }
6014 #else
6015
6016 if(!(ftest = fopen(fname, "rb")))
6017 {
6018 char *rp = get_relative_adjusted_name(GLOBALS->loaded_file_name, fname, GLOBALS->loaded_file_name);
6019 if(!rp)
6020 {
6021 int clen = strlen(fname);
6022 int wid = clen * 10;
6023
6024 if(wid < 400) wid = 400;
6025
6026 simplereqbox("Could not open file!", wid, fname, "OK", NULL, NULL, 1);
6027 return;
6028 }
6029
6030 fname = wave_alloca(strlen(rp) + 1);
6031 strcpy(fname, rp);
6032 free_2(rp);
6033 }
6034 else
6035 {
6036 fclose(ftest); ftest = NULL;
6037 }
6038
6039 {
6040 pid_t pid=fork();
6041
6042 if(((int)pid) < 0)
6043 {
6044 /* can't do anything about this */
6045 }
6046 else
6047 {
6048 if(pid) /* parent==original server_pid */
6049 {
6050 }
6051 else
6052 {
6053 char *str = strdup_2(edname);
6054 char nbuf[32];
6055
6056 char *saveptr1 = NULL;
6057 char *str1, *token, *sd_token;
6058 const char *delim = " \t";
6059 int num_seen = 0;
6060 int fn_seen = 0;
6061
6062 char **ar = NULL;
6063 int siz = 0;
6064
6065 for(str1 = str;;str1 = NULL)
6066 {
6067 token = strtok_r(str1, delim, &saveptr1);
6068 if(!token) break;
6069
6070 if(strstr(token, "%d"))
6071 {
6072 sprintf(nbuf, token, lineno);
6073 sd_token = strdup_2(nbuf);
6074 num_seen = 1;
6075 }
6076 else if(!strcmp(token, "%s"))
6077 {
6078 sd_token = strdup_2(fname);
6079 fn_seen = 1;
6080 }
6081 else
6082 {
6083 sd_token = strdup_2(token);
6084 }
6085 grow_array(&ar, &siz, sd_token);
6086 }
6087
6088 if(ar && edname)
6089 {
6090 if(!num_seen)
6091 {
6092 if((strstr(ar[0], "vi")) || (strstr(ar[0], "emacs")) || (strstr(ar[0], "gedit")))
6093 {
6094 sprintf(nbuf, "+%d", lineno);
6095 sd_token = strdup_2(nbuf);
6096 grow_array(&ar, &siz, sd_token);
6097 }
6098 }
6099
6100 if(!fn_seen)
6101 {
6102 sd_token = strdup_2(fname);
6103 grow_array(&ar, &siz, sd_token);
6104 }
6105
6106 grow_array(&ar, &siz, NULL);
6107
6108 execvp(ar[0], ar);
6109 }
6110
6111 fprintf(stderr, "GTKWAVE | Could not find editor executable!\n");
6112 exit(255); /* control never gets here if successful */
6113 }
6114 }
6115 }
6116 #endif
6117 }
6118 else
6119 {
6120 simplereqbox("Open Source", 400, "Source stem not present!", "OK", NULL, NULL, 1);
6121 }
6122 }
6123 #endif
6124
6125
6126 static void
6127 menu_open_hierarchy_2(gpointer null_data, guint callback_action, GtkWidget *widget, int typ)
6128 {
6129 (void)null_data;
6130 (void)callback_action;
6131 (void)widget;
6132
6133 #if WAVE_USE_GTK2
6134 Trptr t;
6135 int fix=0;
6136 struct tree *t_forced = NULL;
6137 #endif
6138
6139 if(GLOBALS->helpbox_is_active)
6140 {
6141 if((typ == FST_MT_SOURCESTEM) || (typ == FST_MT_SOURCEISTEM))
6142 {
6143 if(typ == FST_MT_SOURCESTEM)
6144 {
6145 help_text_bold("\n\nOpen Source Definition");
6146 }
6147 else
6148 {
6149 help_text_bold("\n\nOpen Source Instantiation");
6150 }
6151 help_text(
6152 #if WAVE_USE_GTK2
6153 " opens and selects the appropriate level of hierarchy in the SST"
6154 " for the first selected signal and also invokes the editor specified by the"
6155 " \"editor\" gtkwaverc variable, that specified by the environment variable $GTKWAVE_EDITOR,"
6156 #ifndef MAC_INTEGRATION
6157
6158 " or gedit (if found during ./configure)"
6159 #else
6160 " gedit (if found during ./configure), or lastly open -t"
6161 #endif
6162 " on the appropriate source unit. This is currently only supported by FST."
6163 #else
6164 " is not available with this build. Please build against GTK 2."
6165 #endif
6166 );
6167 }
6168 else
6169 {
6170 help_text_bold("\n\nOpen Scope");
6171 help_text(
6172 #if WAVE_USE_GTK2
6173 " opens and selects the appropriate level of hierarchy in the SST"
6174 " for the first selected signal."
6175 #else
6176 " is not available with this build. Please build against GTK 2."
6177 #endif
6178 );
6179 }
6180 return;
6181 }
6182
6183 #if WAVE_USE_GTK2
6184
6185 if((t=GLOBALS->traces.first))
6186 {
6187 while(t)
6188 {
6189 if(IsSelected(t)&&!IsShadowed(t))
6190 {
6191 char *tname = NULL;
6192
6193 if(!HasWave(t))
6194 {
6195 break;
6196 }
6197
6198 if (HasAlias(t))
6199 {
6200 tname = strdup_2(t->name_full);
6201 }
6202 else if(t->vector==TRUE)
6203 {
6204 tname = strdup_2(t->n.vec->bvname);
6205 }
6206 else
6207 {
6208 int flagged = HIER_DEPACK_ALLOC;
6209
6210 if(!t->n.nd)
6211 {
6212 break; /* additional guard on top of !HasWave(t) */
6213 }
6214
6215 tname = hier_decompress_flagged(t->n.nd->nname, &flagged);
6216 if(!flagged)
6217 {
6218 tname = strdup_2(tname);
6219 }
6220 }
6221
6222 if(tname)
6223 {
6224 char *lasthier = strrchr(tname, GLOBALS->hier_delimeter);
6225 if(lasthier)
6226 {
6227 char *tname_copy;
6228
6229 lasthier++; /* zero out character after hierarchy */
6230 *lasthier = 0;
6231 tname_copy = strdup_2(tname); /* force_open_tree_node() is destructive */
6232 if(force_open_tree_node(tname_copy, 1, &t_forced) >= 0)
6233 {
6234 if(GLOBALS->selected_hierarchy_name)
6235 {
6236 free_2(GLOBALS->selected_hierarchy_name);
6237 GLOBALS->selected_hierarchy_name = strdup_2(tname);
6238 }
6239
6240 select_tree_node(tname);
6241 }
6242 free_2(tname_copy);
6243 }
6244
6245 free_2(tname);
6246 fix=1;
6247 break;
6248 }
6249 }
6250
6251 t=t->t_next;
6252 }
6253
6254 if(fix)
6255 {
6256 GLOBALS->signalwindow_width_dirty=1;
6257 MaxSignalLength();
6258 signalarea_configure_event(GLOBALS->signalarea, NULL);
6259 wavearea_configure_event(GLOBALS->wavearea, NULL);
6260 }
6261
6262 }
6263
6264 if(((typ == FST_MT_SOURCESTEM) || (typ == FST_MT_SOURCEISTEM)) && t_forced)
6265 {
6266 uint32_t idx = (typ == FST_MT_SOURCESTEM) ? t_forced->t_stem : t_forced->t_istem;
6267
6268 if(!GLOBALS->stem_path_string_table)
6269 {
6270 fprintf(stderr, "GTKWAVE | Could not find stems information in this file!\n");
6271 }
6272 else
6273 {
6274 if(!idx && (typ == FST_MT_SOURCEISTEM) && GLOBALS->istem_struct_base)
6275 {
6276 /* handle top level where istem == stem and istem is deliberately not specified */
6277 typ = FST_MT_SOURCESTEM;
6278 idx = t_forced->t_stem;
6279 }
6280
6281 open_index_in_forked_editor(idx, typ);
6282 }
6283 }
6284
6285 #endif
6286 }
6287
6288
6289 static void
6290 menu_open_hierarchy_2a(gpointer null_data, guint callback_action, GtkWidget *widget, int typ)
6291 {
6292 (void)null_data;
6293 (void)callback_action;
6294 (void)widget;
6295
6296 if(GLOBALS->helpbox_is_active)
6297 {
6298 if((typ == FST_MT_SOURCESTEM) || (typ == FST_MT_SOURCEISTEM))
6299 {
6300 if(typ == FST_MT_SOURCESTEM)
6301 {
6302 help_text_bold("\n\nOpen Source Definition");
6303 }
6304 else
6305 {
6306 help_text_bold("\n\nOpen Source Instantiation");
6307 }
6308 help_text(
6309 #if WAVE_USE_GTK2
6310 " invokes $GTKWAVE_EDITOR or gedit (if found) on the appropriate source unit."
6311 #else
6312 " is not available with this build. Please build against GTK 2."
6313 #endif
6314 );
6315 }
6316 else
6317 {
6318 help_text_bold("\n\nOpen Scope");
6319 help_text(
6320 #if WAVE_USE_GTK2
6321 " opens and selects the appropriate level of hierarchy in the SST"
6322 " for the first selected signal."
6323 #else
6324 " is not available with this build. Please build against GTK 2."
6325 #endif
6326 );
6327 }
6328 return;
6329 }
6330
6331 #if WAVE_USE_GTK2
6332
6333 if((typ == FST_MT_SOURCESTEM) || (typ == FST_MT_SOURCEISTEM))
6334 {
6335 struct tree *t_forced = GLOBALS->sst_sig_root_treesearch_gtk2_c_1;
6336
6337 if(t_forced)
6338 {
6339 uint32_t idx = (typ == FST_MT_SOURCESTEM) ? t_forced->t_stem : t_forced->t_istem;
6340
6341 if(!GLOBALS->stem_path_string_table)
6342 {
6343 fprintf(stderr, "GTKWAVE | Could not find stems information in this file!\n");
6344 }
6345 else
6346 {
6347 if(!idx && (typ == FST_MT_SOURCEISTEM) && GLOBALS->istem_struct_base)
6348 {
6349 /* handle top level where istem == stem and istem is deliberately not specified */
6350 typ = FST_MT_SOURCESTEM;
6351 idx = t_forced->t_stem;
6352 }
6353
6354 open_index_in_forked_editor(idx, typ);
6355 }
6356 }
6357 }
6358
6359 #endif
6360 }
6361
6362
6363 void menu_open_hierarchy(gpointer null_data, guint callback_action, GtkWidget *widget)
6364 {
6365 menu_open_hierarchy_2(null_data, callback_action, widget, FST_MT_MIN); /* zero for regular open */
6366 }
6367
6368
6369 void menu_open_hierarchy_source(gpointer null_data, guint callback_action, GtkWidget *widget)
6370 {
6371 menu_open_hierarchy_2(null_data, callback_action, widget, FST_MT_SOURCESTEM); /* for definition source */
6372 }
6373
6374 void menu_open_hierarchy_isource(gpointer null_data, guint callback_action, GtkWidget *widget)
6375 {
6376 menu_open_hierarchy_2(null_data, callback_action, widget, FST_MT_SOURCEISTEM); /* for instantiation source */
6377 }
6378
6379
6380 void menu_open_sst_hierarchy_source(gpointer null_data, guint callback_action, GtkWidget *widget)
6381 {
6382 menu_open_hierarchy_2a(null_data, callback_action, widget, FST_MT_SOURCESTEM); /* for definition source */
6383 }
6384
6385 void menu_open_sst_hierarchy_isource(gpointer null_data, guint callback_action, GtkWidget *widget)
6386 {
6387 menu_open_hierarchy_2a(null_data, callback_action, widget, FST_MT_SOURCEISTEM); /* for instantiation source */
6388 }
6389
6390 /**/
6391
6392 #if WAVE_USE_GTK2
6393 void menu_recurse_import(gpointer null_data, guint callback_action, GtkWidget *widget)
6394 {
6395 (void) null_data;
6396
6397 recurse_import(widget, callback_action);
6398 }
6399 #endif
6400
6401 /**/
6402
6403
6404 static void dataformat(TraceFlagsType mask, TraceFlagsType patch)
6405 {
6406 Trptr t;
6407 int fix=0;
6408
6409 if((t=GLOBALS->traces.first))
6410 {
6411 while(t)
6412 {
6413 if(IsSelected(t)&&!IsShadowed(t))
6414 {
6415 t->minmax_valid = 0; /* force analog traces to regenerate if necessary */
6416 t->flags=((t->flags)&mask)|patch;
6417 fix=1;
6418 }
6419 t=t->t_next;
6420 }
6421 if(fix)
6422 {
6423 GLOBALS->signalwindow_width_dirty=1;
6424 MaxSignalLength();
6425 signalarea_configure_event(GLOBALS->signalarea, NULL);
6426 wavearea_configure_event(GLOBALS->wavearea, NULL);
6427 }
6428 }
6429 }
6430
6431 void
6432 menu_dataformat_ascii(gpointer null_data, guint callback_action, GtkWidget *widget)
6433 {
6434 (void)null_data;
6435 (void)callback_action;
6436 (void)widget;
6437
6438 if(GLOBALS->helpbox_is_active)
6439 {
6440 help_text_bold("\n\nData Format-ASCII");
6441 help_text(
6442 " will step through all highlighted traces and ensure that"
6443 " vectors with this qualifier will be displayed with ASCII"
6444 " values."
6445 );
6446 return;
6447 }
6448
6449 dataformat( ~(TR_NUMMASK|TR_ANALOGMASK), TR_ASCII );
6450 }
6451
6452 void
6453 menu_dataformat_real(gpointer null_data, guint callback_action, GtkWidget *widget)
6454 {
6455 (void)null_data;
6456 (void)callback_action;
6457 (void)widget;
6458
6459 if(GLOBALS->helpbox_is_active)
6460 {
6461 help_text_bold("\n\nData Format-BitsToReal");
6462 help_text(
6463 " will step through all highlighted traces and ensure that"
6464 " vectors with this qualifier will be displayed with Real"
6465 " values. Note that this only works for 64 or 32-bit quantities"
6466 " and that ones of other sizes (e.g., binary16) will display as binary."
6467 );
6468 return;
6469 }
6470
6471 dataformat( ~(TR_NUMMASK), TR_REAL );
6472 }
6473
6474 void
6475 menu_dataformat_real2bon(gpointer null_data, guint callback_action, GtkWidget *widget)
6476 {
6477 (void)null_data;
6478 (void)callback_action;
6479 (void)widget;
6480
6481 if(GLOBALS->helpbox_is_active)
6482 {
6483 help_text_bold("\n\nData Format-RealToBits On");
6484 help_text(
6485 " will step through all highlighted traces and ensure that"
6486 " Real vectors with this qualifier will be displayed as Hex"
6487 " values. Note that this only works for Real quantities"
6488 " and other ones will remain to display as binary. This is a pre-filter"
6489 " so it is possible to invert, reverse, apply Decimal, etc. It will not be"
6490 " possible however to expand those values into their constituent bits."
6491 );
6492 return;
6493 }
6494
6495 dataformat( ~(TR_REAL2BITS|TR_NUMMASK|TR_ANALOGMASK), TR_REAL2BITS|TR_HEX );
6496 }
6497
6498 void
6499 menu_dataformat_real2boff(gpointer null_data, guint callback_action, GtkWidget *widget)
6500 {
6501 (void)null_data;
6502 (void)callback_action;
6503 (void)widget;
6504
6505 if(GLOBALS->helpbox_is_active)
6506 {
6507 help_text_bold("\n\nData Format-RealToBits Off");
6508 help_text(
6509 " will step through all highlighted traces and ensure that"
6510 " the Real To Bits qualifier is removed from those traces."
6511 );
6512 return;
6513 }
6514
6515 dataformat( ~(TR_REAL2BITS|TR_ANALOGMASK), 0 );
6516 }
6517
6518 void
6519 menu_dataformat_hex(gpointer null_data, guint callback_action, GtkWidget *widget)
6520 {
6521 (void)null_data;
6522 (void)callback_action;
6523 (void)widget;
6524
6525 if(GLOBALS->helpbox_is_active)
6526 {
6527 help_text_bold("\n\nData Format-Hex");
6528 help_text(
6529 " will step through all highlighted traces and ensure that"
6530 " vectors with this qualifier will be displayed with hexadecimal"
6531 " values."
6532 );
6533 return;
6534 }
6535
6536 dataformat( ~(TR_NUMMASK), TR_HEX );
6537 }
6538
6539 void
6540 menu_dataformat_dec(gpointer null_data, guint callback_action, GtkWidget *widget)
6541 {
6542 (void)null_data;
6543 (void)callback_action;
6544 (void)widget;
6545
6546 if(GLOBALS->helpbox_is_active)
6547 {
6548 help_text_bold("\n\nData Format-Decimal");
6549 help_text(
6550 " will step through all highlighted traces and ensure that"
6551 " vectors with this qualifier will be displayed with decimal"
6552 " values."
6553 );
6554 return;
6555 }
6556
6557 dataformat( ~(TR_NUMMASK), TR_DEC );
6558 }
6559
6560 void
6561 menu_dataformat_signed(gpointer null_data, guint callback_action, GtkWidget *widget)
6562 {
6563 (void)null_data;
6564 (void)callback_action;
6565 (void)widget;
6566
6567 if(GLOBALS->helpbox_is_active)
6568 {
6569 help_text_bold("\n\nData Format-Signed");
6570 help_text(
6571 " will step through all highlighted traces and ensure that"
6572 " vectors with this qualifier will be displayed as sign extended decimal"
6573 " values."
6574 );
6575 return;
6576 }
6577
6578 dataformat( ~(TR_NUMMASK), TR_SIGNED );
6579 }
6580
6581 void
6582 menu_dataformat_bin(gpointer null_data, guint callback_action, GtkWidget *widget)
6583 {
6584 (void)null_data;
6585 (void)callback_action;
6586 (void)widget;
6587
6588 if(GLOBALS->helpbox_is_active)
6589 {
6590 help_text_bold("\n\nData Format-Binary");
6591 help_text(
6592 " will step through all highlighted traces and ensure that"
6593 " vectors with this qualifier will be displayed with binary"
6594 " values."
6595 );
6596 return;
6597 }
6598
6599 dataformat( ~(TR_NUMMASK), TR_BIN );
6600 }
6601
6602 void
6603 menu_dataformat_oct(gpointer null_data, guint callback_action, GtkWidget *widget)
6604 {
6605 (void)null_data;
6606 (void)callback_action;
6607 (void)widget;
6608
6609 if(GLOBALS->helpbox_is_active)
6610 {
6611 help_text_bold("\n\nData Format-Octal");
6612 help_text(
6613 " will step through all highlighted traces and ensure that"
6614 " vectors with this qualifier will be displayed with octal"
6615 " values."
6616 );
6617 return;
6618 }
6619
6620 dataformat( ~(TR_NUMMASK), TR_OCT );
6621 }
6622
6623 void
6624 menu_dataformat_rjustify_on(gpointer null_data, guint callback_action, GtkWidget *widget)
6625 {
6626 (void)null_data;
6627 (void)callback_action;
6628 (void)widget;
6629
6630 if(GLOBALS->helpbox_is_active)
6631 {
6632 help_text_bold("\n\nData Format-Right Justify-On");
6633 help_text(
6634 " will step through all highlighted traces and ensure that"
6635 " vectors with this qualifier will be displayed right"
6636 " justified."
6637 );
6638 return;
6639 }
6640
6641 dataformat( ~(TR_RJUSTIFY), TR_RJUSTIFY );
6642 }
6643
6644 void
6645 menu_dataformat_rjustify_off(gpointer null_data, guint callback_action, GtkWidget *widget)
6646 {
6647 (void)null_data;
6648 (void)callback_action;
6649 (void)widget;
6650
6651 if(GLOBALS->helpbox_is_active)
6652 {
6653 help_text_bold("\n\nData Format-Right Justify-Off");
6654 help_text(
6655 " will step through all highlighted traces and ensure that"
6656 " vectors with this qualifier will not be displayed right"
6657 " justified."
6658 );
6659 return;
6660 }
6661
6662 dataformat( ~(TR_RJUSTIFY), 0 );
6663 }
6664
6665 void
6666 menu_dataformat_bingray_on(gpointer null_data, guint callback_action, GtkWidget *widget)
6667 {
6668 (void)null_data;
6669 (void)callback_action;
6670 (void)widget;
6671
6672 if(GLOBALS->helpbox_is_active)
6673 {
6674 help_text_bold("\n\nData Format-Gray Filters-To Gray");
6675 help_text(
6676 " will step through all highlighted traces and ensure that"
6677 " bits and vectors with this qualifier will be displayed after"
6678 " going through normal to gray conversion. This is a filter"
6679 " which sits before other Data Format options such as hex, etc."
6680 );
6681 return;
6682 }
6683
6684 dataformat( ~(TR_GRAYMASK|TR_ANALOGMASK), TR_BINGRAY );
6685 }
6686
6687 void
6688 menu_dataformat_graybin_on(gpointer null_data, guint callback_action, GtkWidget *widget)
6689 {
6690 (void)null_data;
6691 (void)callback_action;
6692 (void)widget;
6693
6694 if(GLOBALS->helpbox_is_active)
6695 {
6696 help_text_bold("\n\nData Format-Gray Filters-From Gray");
6697 help_text(
6698 " will step through all highlighted traces and ensure that"
6699 " bits and vectors with this qualifier will be displayed after"
6700 " going through gray to normal conversion. This is a filter"
6701 " which sits before other Data Format options such as hex, etc."
6702 );
6703 return;
6704 }
6705
6706 dataformat( ~(TR_GRAYMASK|TR_ANALOGMASK), TR_GRAYBIN );
6707 }
6708
6709
6710 void
6711 menu_dataformat_nogray(gpointer null_data, guint callback_action, GtkWidget *widget)
6712 {
6713 (void)null_data;
6714 (void)callback_action;
6715 (void)widget;
6716
6717 if(GLOBALS->helpbox_is_active)
6718 {
6719 help_text_bold("\n\nData Format-Gray Filters-None");
6720 help_text(
6721 " will step through all highlighted traces and ensure that"
6722 " bits and vectors with this qualifier will be displayed with"
6723 " normal encoding."
6724 );
6725 return;
6726 }
6727
6728 dataformat( ~(TR_GRAYMASK|TR_ANALOGMASK), 0 );
6729 }
6730
6731 void
6732 menu_dataformat_popcnt_on(gpointer null_data, guint callback_action, GtkWidget *widget)
6733 {
6734 (void)null_data;
6735 (void)callback_action;
6736 (void)widget;
6737
6738 if(GLOBALS->helpbox_is_active)
6739 {
6740 help_text_bold("\n\nData Format-Popcnt-On");
6741 help_text(
6742 " will step through all highlighted traces and ensure that"
6743 " bits and vectors with this qualifier will be displayed after"
6744 " going through a population (one's) count conversion. This is a filter"
6745 " which sits before other Data Format options such as hex, etc."
6746 );
6747 return;
6748 }
6749
6750 dataformat( ~(TR_POPCNT), TR_POPCNT );
6751 }
6752
6753 void
6754 menu_dataformat_popcnt_off(gpointer null_data, guint callback_action, GtkWidget *widget)
6755 {
6756 (void)null_data;
6757 (void)callback_action;
6758 (void)widget;
6759
6760 if(GLOBALS->helpbox_is_active)
6761 {
6762 help_text_bold("\n\nData Format-Popcnt-Off");
6763 help_text(
6764 " will step through all highlighted traces and ensure that"
6765 " bits and vectors with this qualifier will be displayed with"
6766 " normal encoding."
6767 );
6768 return;
6769 }
6770
6771 dataformat( ~(TR_POPCNT), 0 );
6772 }
6773
6774 void
6775 menu_dataformat_ffo_on(gpointer null_data, guint callback_action, GtkWidget *widget)
6776 {
6777 (void)null_data;
6778 (void)callback_action;
6779 (void)widget;
6780
6781 if(GLOBALS->helpbox_is_active)
6782 {
6783 help_text_bold("\n\nData Format-Find First Rightmost One Index-On");
6784 help_text(
6785 " will step through all highlighted traces and ensure that"
6786 " bits and vectors with this qualifier will be displayed after"
6787 " going through a right->left FFO index conversion. This is a filter"
6788 " which sits before other Data Format options such as hex, etc."
6789 );
6790 return;
6791 }
6792
6793 dataformat( ~(TR_FFO), TR_FFO );
6794 }
6795
6796 void
6797 menu_dataformat_ffo_off(gpointer null_data, guint callback_action, GtkWidget *widget)
6798 {
6799 (void)null_data;
6800 (void)callback_action;
6801 (void)widget;
6802
6803 if(GLOBALS->helpbox_is_active)
6804 {
6805 help_text_bold("\n\nData Format-Find First Rightmost One Index-Off");
6806 help_text(
6807 " will step through all highlighted traces and ensure that"
6808 " bits and vectors with this qualifier will be displayed with"
6809 " normal encoding."
6810 );
6811 return;
6812 }
6813
6814 dataformat( ~(TR_FFO), 0 );
6815 }
6816
6817
6818 void
6819 menu_dataformat_time(gpointer null_data, guint callback_action, GtkWidget *widget)
6820 {
6821 (void)null_data;
6822 (void)callback_action;
6823 (void)widget;
6824
6825 if(GLOBALS->helpbox_is_active)
6826 {
6827 help_text_bold("\n\nData Format-Time");
6828 help_text(
6829 " will step through all highlighted traces and ensure that"
6830 " bits and vectors with this qualifier will display as time values."
6831 );
6832 return;
6833 }
6834
6835 dataformat( ~(TR_NUMMASK), (TR_TIME | TR_DEC) );
6836 }
6837
6838 void
6839 menu_dataformat_enum(gpointer null_data, guint callback_action, GtkWidget *widget)
6840 {
6841 (void)null_data;
6842 (void)callback_action;
6843 (void)widget;
6844
6845 if(GLOBALS->helpbox_is_active)
6846 {
6847 help_text_bold("\n\nData Format-Enum");
6848 help_text(
6849 " will step through all highlighted traces and ensure that"
6850 " bits and vectors with this qualifier will display as enum values, provided such values were dumped into file."
6851 );
6852 return;
6853 }
6854
6855 dataformat( ~(TR_NUMMASK), (TR_ENUM | TR_BIN) );
6856 }
6857
6858
6859 void
6860 menu_dataformat_fpshift_on(gpointer null_data, guint callback_action, GtkWidget *widget)
6861 {
6862 (void)null_data;
6863 (void)callback_action;
6864 (void)widget;
6865
6866 if(GLOBALS->helpbox_is_active)
6867 {
6868 help_text_bold("\n\nData Format-Fixed Point Shift-On");
6869 help_text(
6870 " will step through all highlighted traces and ensure that"
6871 " bits and vectors with this qualifier will be right shifted"
6872 " prior to being displayed as Signed Decimal or Decimal values."
6873 );
6874 return;
6875 }
6876
6877 dataformat( ~(TR_FPDECSHIFT), TR_FPDECSHIFT );
6878 }
6879
6880 void
6881 menu_dataformat_fpshift_off(gpointer null_data, guint callback_action, GtkWidget *widget)
6882 {
6883 (void)null_data;
6884 (void)callback_action;
6885 (void)widget;
6886
6887 if(GLOBALS->helpbox_is_active)
6888 {
6889 help_text_bold("\n\nData Format-Fixed Point Shift-Off");
6890 help_text(
6891 " will step through all highlighted traces and ensure that"
6892 " bits and vectors with this qualifier will not be right shifted"
6893 " prior to being displayed as Signed Decimal or Decimal values."
6894 );
6895 return;
6896 }
6897
6898 dataformat( ~(TR_FPDECSHIFT), 0 );
6899 }
6900
6901
6902 static void
6903 menu_dataformat_fpshift_specify_cleanup(GtkWidget *widget, gpointer data)
6904 {
6905 (void)widget;
6906 (void)data;
6907
6908 Trptr t;
6909 int fix=0;
6910 int shamt = GLOBALS->entrybox_text ? atoi(GLOBALS->entrybox_text) : 0;
6911 TraceFlagsType mask = ~(TR_FPDECSHIFT);
6912 TraceFlagsType patch = TR_FPDECSHIFT;
6913
6914 if((shamt < 0)||(shamt > 255)) { shamt = 0; patch = 0; }
6915
6916 if((t=GLOBALS->traces.first))
6917 {
6918 while(t)
6919 {
6920 if(IsSelected(t)&&!IsShadowed(t))
6921 {
6922 t->minmax_valid = 0; /* force analog traces to regenerate if necessary */
6923
6924 t->t_fpdecshift = shamt;
6925 t->flags=((t->flags)&mask)|patch;
6926 fix=1;
6927 }
6928 t=t->t_next;
6929 }
6930 if(fix)
6931 {
6932 GLOBALS->signalwindow_width_dirty=1;
6933 MaxSignalLength();
6934 signalarea_configure_event(GLOBALS->signalarea, NULL);
6935 wavearea_configure_event(GLOBALS->wavearea, NULL);
6936 }
6937 }
6938
6939 if(GLOBALS->entrybox_text) { free_2(GLOBALS->entrybox_text); GLOBALS->entrybox_text=NULL; }
6940 GLOBALS->signalwindow_width_dirty=1;
6941 MaxSignalLength();
6942 signalarea_configure_event(GLOBALS->signalarea, NULL);
6943 wavearea_configure_event(GLOBALS->wavearea, NULL);
6944 }
6945
6946
6947 void
6948 menu_dataformat_fpshift_specify(gpointer null_data, guint callback_action, GtkWidget *widget)
6949 {
6950 (void)null_data;
6951 (void)callback_action;
6952 (void)widget;
6953
6954 if(GLOBALS->helpbox_is_active)
6955 {
6956 help_text_bold("\n\nData Format-Fixed Point Shift-Specify");
6957 help_text(
6958 " will open up a requester to specify a shift count then"
6959 " will step through all highlighted traces and ensure that"
6960 " bits and vectors with this qualifier will be right shifted"
6961 " prior to being displayed as Signed Decimal or Decimal values."
6962 );
6963 return;
6964 }
6965
6966 entrybox("Fixed Point Shift Specify",300,"",NULL,128,GTK_SIGNAL_FUNC(menu_dataformat_fpshift_specify_cleanup));
6967
6968 dataformat( ~(TR_FPDECSHIFT), 0 );
6969 }
6970
6971 void
6972 menu_dataformat_invert_on(gpointer null_data, guint callback_action, GtkWidget *widget)
6973 {
6974 (void)null_data;
6975 (void)callback_action;
6976 (void)widget;
6977
6978 if(GLOBALS->helpbox_is_active)
6979 {
6980 help_text_bold("\n\nData Format-Invert-On");
6981 help_text(
6982 " will step through all highlighted traces and ensure that"
6983 " bits and vectors with this qualifier will be displayed with"
6984 " 1's and 0's inverted."
6985 );
6986 return;
6987 }
6988
6989 dataformat( ~(TR_INVERT), TR_INVERT );
6990 }
6991
6992 void
6993 menu_dataformat_invert_off(gpointer null_data, guint callback_action, GtkWidget *widget)
6994 {
6995 (void)null_data;
6996 (void)callback_action;
6997 (void)widget;
6998
6999 if(GLOBALS->helpbox_is_active)
7000 {
7001 help_text_bold("\n\nData Format-Invert-Off");
7002 help_text(
7003 " will step through all highlighted traces and ensure that"
7004 " bits and vectors with this qualifier will not be displayed with"
7005 " 1's and 0's inverted."
7006 );
7007 return;
7008 }
7009
7010 dataformat( ~(TR_INVERT), 0 );
7011 }
7012
7013 void
7014 menu_dataformat_reverse_on(gpointer null_data, guint callback_action, GtkWidget *widget)
7015 {
7016 (void)null_data;
7017 (void)callback_action;
7018 (void)widget;
7019
7020 if(GLOBALS->helpbox_is_active)
7021 {
7022 help_text_bold("\n\nData Format-Reverse Bits-On");
7023 help_text(
7024 " will step through all highlighted traces and ensure that"
7025 " vectors with this qualifier will be displayed in"
7026 " reversed bit order."
7027 );
7028 return;
7029 }
7030
7031 dataformat( ~(TR_REVERSE), TR_REVERSE );
7032 }
7033
7034 void
7035 menu_dataformat_reverse_off(gpointer null_data, guint callback_action, GtkWidget *widget)
7036 {
7037 (void)null_data;
7038 (void)callback_action;
7039 (void)widget;
7040
7041 if(GLOBALS->helpbox_is_active)
7042 {
7043 help_text_bold("\n\nData Format-Reverse Bits-Off");
7044 help_text(
7045 " will step through all highlighted traces and ensure that"
7046 " vectors with this qualifier will not be displayed in"
7047 " reversed bit order."
7048 );
7049 return;
7050 }
7051
7052 dataformat( ~(TR_REVERSE), 0 );
7053 }
7054
7055 void
7056 menu_dataformat_exclude_on(gpointer null_data, guint callback_action, GtkWidget *widget)
7057 {
7058 (void)null_data;
7059 (void)callback_action;
7060 (void)widget;
7061
7062 if(GLOBALS->helpbox_is_active)
7063 {
7064 help_text_bold("\n\nExclude");
7065 help_text(
7066 " causes the waveform data for all currently highlighted traces"
7067 " to be blanked out."
7068 );
7069 return;
7070 }
7071
7072 dataformat( ~(TR_EXCLUDE), TR_EXCLUDE );
7073 }
7074
7075 void
7076 menu_dataformat_exclude_off(gpointer null_data, guint callback_action, GtkWidget *widget)
7077 {
7078 (void)null_data;
7079 (void)callback_action;
7080 (void)widget;
7081
7082 if(GLOBALS->helpbox_is_active)
7083 {
7084 help_text_bold("\n\nShow");
7085 help_text(
7086 " causes the waveform data for all currently highlighted traces"
7087 " to be displayed as normal if the exclude attribute is currently"
7088 " set on the highlighted traces."
7089 );
7090 return;
7091 }
7092
7093 dataformat( ~(TR_EXCLUDE), 0 );
7094 }
7095 /**/
7096 void
7097 menu_dataformat_rangefill_zero(gpointer null_data, guint callback_action, GtkWidget *widget)
7098 {
7099 (void)null_data;
7100 (void)callback_action;
7101 (void)widget;
7102
7103 if(GLOBALS->helpbox_is_active)
7104 {
7105 help_text_bold("\n\nData Format-Range Fill With 0s");
7106 help_text(
7107 " will step through all highlighted traces and ensure that"
7108 " vectors with this qualifier will be displayed as if"
7109 " the bitrange of the MSB or LSB as appropriate goes to zero."
7110 " Zero bits will be filled in for the missing bits."
7111 );
7112 return;
7113 }
7114
7115 dataformat( ~(TR_ZEROFILL|TR_ONEFILL|TR_ANALOGMASK), TR_ZEROFILL );
7116 }
7117
7118 void
7119 menu_dataformat_rangefill_one(gpointer null_data, guint callback_action, GtkWidget *widget)
7120 {
7121 (void)null_data;
7122 (void)callback_action;
7123 (void)widget;
7124
7125 if(GLOBALS->helpbox_is_active)
7126 {
7127 help_text_bold("\n\nData Format-Range Fill With 1s");
7128 help_text(
7129 " will step through all highlighted traces and ensure that"
7130 " vectors with this qualifier will be displayed as if"
7131 " the bitrange of the MSB or LSB as appropriate goes to zero."
7132 " One bits will be filled in for the missing bits; this is mostly intended"
7133 " to be used when viewing values which are inverted in the logic and need"
7134 " to be inverted in the viewer."
7135 );
7136 return;
7137 }
7138
7139 dataformat( ~(TR_ZEROFILL|TR_ONEFILL|TR_ANALOGMASK), TR_ONEFILL );
7140 }
7141
7142 void
7143 menu_dataformat_rangefill_off(gpointer null_data, guint callback_action, GtkWidget *widget)
7144 {
7145 (void)null_data;
7146 (void)callback_action;
7147 (void)widget;
7148
7149 if(GLOBALS->helpbox_is_active)
7150 {
7151 help_text_bold("\n\nData Format-Zero Range Fill Off");
7152 help_text(
7153 " will step through all highlighted traces and ensure that"
7154 " normal bitrange displays are used."
7155 );
7156 return;
7157 }
7158
7159 dataformat( ~(TR_ZEROFILL|TR_ONEFILL|TR_ANALOGMASK), 0 );
7160 }
7161 /**/
7162 void
7163 menu_dataformat_analog_off(gpointer null_data, guint callback_action, GtkWidget *widget)
7164 {
7165 (void)null_data;
7166 (void)callback_action;
7167 (void)widget;
7168
7169 if(GLOBALS->helpbox_is_active)
7170 {
7171 help_text_bold("\n\nAnalog Off");
7172 help_text(
7173 " causes the waveform data for all currently highlighted traces"
7174 " to be displayed as normal."
7175 );
7176 return;
7177 }
7178
7179 dataformat( ~(TR_ANALOGMASK), 0 );
7180 }
7181
7182 void
7183 menu_dataformat_analog_step(gpointer null_data, guint callback_action, GtkWidget *widget)
7184 {
7185 (void)null_data;
7186 (void)callback_action;
7187 (void)widget;
7188
7189 if(GLOBALS->helpbox_is_active)
7190 {
7191 help_text_bold("\n\nAnalog Step");
7192 help_text(
7193 " causes the waveform data for all currently highlighted traces"
7194 " to be displayed as stepwise analog waveform."
7195 );
7196 return;
7197 }
7198
7199 dataformat( ~(TR_ANALOGMASK), TR_ANALOG_STEP );
7200 }
7201
7202 void
7203 menu_dataformat_analog_interpol(gpointer null_data, guint callback_action, GtkWidget *widget)
7204 {
7205 (void)null_data;
7206 (void)callback_action;
7207 (void)widget;
7208
7209 if(GLOBALS->helpbox_is_active)
7210 {
7211 help_text_bold("\n\nAnalog Interpolate");
7212 help_text(
7213 " causes the waveform data for all currently highlighted traces"
7214 " to be displayed as interpolated analog waveform."
7215 );
7216 return;
7217 }
7218
7219 dataformat( ~(TR_ANALOGMASK), TR_ANALOG_INTERPOLATED );
7220 }
7221
7222 void
7223 menu_dataformat_analog_interpol_step(gpointer null_data, guint callback_action, GtkWidget *widget)
7224 {
7225 (void)null_data;
7226 (void)callback_action;
7227 (void)widget;
7228
7229 if(GLOBALS->helpbox_is_active)
7230 {
7231 help_text_bold("\n\nAnalog Interpolate Annotated");
7232 help_text(
7233 " causes the waveform data for all currently highlighted traces"
7234 " to be displayed as an interpolated analog waveform annotated"
7235 " with the non-interpolated data sampling points that the cursor snaps to."
7236 );
7237 return;
7238 }
7239
7240 dataformat( ~(TR_ANALOGMASK), (TR_ANALOG_INTERPOLATED|TR_ANALOG_STEP) );
7241 }
7242
7243 void
7244 menu_dataformat_analog_resize_screen(gpointer null_data, guint callback_action, GtkWidget *widget)
7245 {
7246 (void)null_data;
7247 (void)callback_action;
7248 (void)widget;
7249
7250 if(GLOBALS->helpbox_is_active)
7251 {
7252 help_text_bold("\n\nAnalog Resizing Screen Data");
7253 help_text(
7254 " causes the waveform data for all currently highlighted traces"
7255 " to be displayed such that the y-value scaling maximizes the on-screen trace"
7256 " data so if fills the whole trace width at all times."
7257 );
7258 return;
7259 }
7260
7261 dataformat( ~(TR_ANALOG_FULLSCALE), 0 );
7262 }
7263
7264 void
7265 menu_dataformat_analog_resize_all(gpointer null_data, guint callback_action, GtkWidget *widget)
7266 {
7267 (void)null_data;
7268 (void)callback_action;
7269 (void)widget;
7270
7271 if(GLOBALS->helpbox_is_active)
7272 {
7273 help_text_bold("\n\nAnalog Resizing All Data");
7274 help_text(
7275 " causes the waveform data for all currently highlighted traces"
7276 " to be displayed such that the y-value scaling maximizes the on-screen trace"
7277 " data so if fills the whole trace width only when fully zoomed out."
7278 " (i.e., the scale used goes across all trace data)"
7279 );
7280 return;
7281 }
7282
7283 dataformat( ~(TR_ANALOG_FULLSCALE), (TR_ANALOG_FULLSCALE) );
7284 }
7285 /**/
7286 void menu_dataformat_highlight_all(gpointer null_data, guint callback_action, GtkWidget *widget)
7287 {
7288 (void)null_data;
7289 (void)callback_action;
7290 (void)widget;
7291
7292 Trptr t;
7293
7294 if(GLOBALS->helpbox_is_active)
7295 {
7296 help_text_bold("\n\nHighlight All");
7297 help_text(
7298 " simply highlights all displayed traces."
7299 );
7300 return;
7301 }
7302
7303 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
7304
7305 if((t=GLOBALS->traces.first))
7306 {
7307 while(t)
7308 {
7309 t->flags|=TR_HIGHLIGHT;
7310 t=t->t_next;
7311 }
7312 signalarea_configure_event(GLOBALS->signalarea, NULL);
7313 wavearea_configure_event(GLOBALS->wavearea, NULL);
7314 }
7315 }
7316
7317 void menu_dataformat_unhighlight_all(gpointer null_data, guint callback_action, GtkWidget *widget)
7318 {
7319 (void)null_data;
7320 (void)callback_action;
7321 (void)widget;
7322
7323 Trptr t;
7324
7325 if(GLOBALS->helpbox_is_active)
7326 {
7327 help_text_bold("\n\nUnHighlight All");
7328 help_text(
7329 " simply unhighlights all displayed traces."
7330 );
7331 return;
7332 }
7333
7334 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
7335
7336 if((t=GLOBALS->traces.first))
7337 {
7338 while(t)
7339 {
7340 t->flags&=(~TR_HIGHLIGHT);
7341 t=t->t_next;
7342 }
7343 signalarea_configure_event(GLOBALS->signalarea, NULL);
7344 wavearea_configure_event(GLOBALS->wavearea, NULL);
7345 }
7346 }
7347
7348 void menu_lexize(gpointer null_data, guint callback_action, GtkWidget *widget)
7349 {
7350 (void)null_data;
7351 (void)callback_action;
7352 (void)widget;
7353
7354 if(GLOBALS->helpbox_is_active)
7355 {
7356 help_text_bold("\n\nSigsort All");
7357 help_text(
7358 " sorts all displayed traces with the numeric parts being taken into account. Blank traces are sorted to the bottom."
7359 );
7360 return;
7361 }
7362
7363 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
7364
7365 if(GLOBALS->traces.first)
7366 {
7367 if(TracesReorder(TR_SORT_LEX))
7368 {
7369 signalarea_configure_event(GLOBALS->signalarea, NULL);
7370 wavearea_configure_event(GLOBALS->wavearea, NULL);
7371 }
7372 }
7373 }
7374 /**/
7375 void menu_alphabetize(gpointer null_data, guint callback_action, GtkWidget *widget)
7376 {
7377 (void)null_data;
7378 (void)callback_action;
7379 (void)widget;
7380
7381 if(GLOBALS->helpbox_is_active)
7382 {
7383 help_text_bold("\n\nAlphabetize All");
7384 help_text(
7385 " alphabetizes all displayed traces. Blank traces are sorted to the bottom."
7386 );
7387 return;
7388 }
7389
7390 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
7391
7392 if(GLOBALS->traces.first)
7393 {
7394 if(TracesReorder(TR_SORT_NORM))
7395 {
7396 signalarea_configure_event(GLOBALS->signalarea, NULL);
7397 wavearea_configure_event(GLOBALS->wavearea, NULL);
7398 }
7399 }
7400 }
7401 /**/
7402 void menu_alphabetize2(gpointer null_data, guint callback_action, GtkWidget *widget)
7403 {
7404 (void)null_data;
7405 (void)callback_action;
7406 (void)widget;
7407
7408 if(GLOBALS->helpbox_is_active)
7409 {
7410 help_text_bold("\n\nAlphabetize All (CaseIns)");
7411 help_text(
7412 " alphabetizes all displayed traces without regard to case. Blank traces are sorted to the bottom."
7413 );
7414 return;
7415 }
7416
7417 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
7418
7419 if(GLOBALS->traces.first)
7420 {
7421 if(TracesReorder(TR_SORT_INS))
7422 {
7423 signalarea_configure_event(GLOBALS->signalarea, NULL);
7424 wavearea_configure_event(GLOBALS->wavearea, NULL);
7425 }
7426 }
7427 }
7428 /**/
7429 void menu_reverse(gpointer null_data, guint callback_action, GtkWidget *widget)
7430 {
7431 (void)null_data;
7432 (void)callback_action;
7433 (void)widget;
7434
7435 if(GLOBALS->helpbox_is_active)
7436 {
7437 help_text_bold("\n\nReverse All");
7438 help_text(
7439 " reverses all displayed traces unconditionally."
7440 );
7441 return;
7442 }
7443
7444 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
7445
7446 if(GLOBALS->traces.first)
7447 {
7448 if(TracesReorder(TR_SORT_RVS))
7449 {
7450 signalarea_configure_event(GLOBALS->signalarea, NULL);
7451 wavearea_configure_event(GLOBALS->wavearea, NULL);
7452 }
7453 }
7454 }
7455 /**/
7456 void
7457 menu_cut_traces(gpointer null_data, guint callback_action, GtkWidget *widget)
7458 {
7459 (void)null_data;
7460 (void)callback_action;
7461 (void)widget;
7462
7463 Trptr cutbuffer = NULL;
7464
7465 if(GLOBALS->helpbox_is_active)
7466 {
7467 help_text_bold("\n\nCut");
7468 help_text(
7469 " removes highlighted signals from the display and places them"
7470 " in an offscreen cut/copy buffer for later Paste operations. "
7471 " Cut implicitly destroys the previous contents of the cut/copy buffer."
7472 );
7473 return;
7474 }
7475
7476 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
7477
7478 DEBUG(printf("Cut Traces\n"));
7479
7480 /* fix up if there are traces above the current row being cut */
7481 if(GLOBALS->wave_vslider)
7482 {
7483 GtkAdjustment *wadj=GTK_ADJUSTMENT(GLOBALS->wave_vslider);
7484 int value = wadj->value;
7485
7486 Trptr t = GLOBALS->traces.first;
7487 int cnt = 0;
7488 int high = 0;
7489
7490 while(t)
7491 {
7492 if(cnt >= value) break;
7493
7494 if(t->flags & TR_HIGHLIGHT)
7495 {
7496 high++;
7497 }
7498
7499 t = GiveNextTrace(t);
7500 cnt++;
7501 }
7502
7503 if(value - high > 0) { wadj->value -= high; }
7504 }
7505
7506 cutbuffer = CutBuffer();
7507 if(cutbuffer)
7508 {
7509 if(GLOBALS->cutcopylist)
7510 {
7511 free_2(GLOBALS->cutcopylist);
7512 }
7513 GLOBALS->cutcopylist = emit_gtkwave_savefile_formatted_entries_in_tcl_list(cutbuffer, FALSE);
7514 /* printf("Cutlist: '%s'\n", GLOBALS->cutcopylist); */
7515
7516 MaxSignalLength();
7517 signalarea_configure_event(GLOBALS->signalarea, NULL);
7518 wavearea_configure_event(GLOBALS->wavearea, NULL);
7519 }
7520 else
7521 {
7522 must_sel();
7523 }
7524 }
7525
7526 void
7527 menu_delete_traces(gpointer null_data, guint callback_action, GtkWidget *widget)
7528 {
7529 (void)null_data;
7530 (void)callback_action;
7531 (void)widget;
7532
7533 int num_cut;
7534
7535 if(GLOBALS->helpbox_is_active)
7536 {
7537 help_text_bold("\n\nDelete");
7538 help_text(
7539 " removes highlighted signals from the display and discards them"
7540 " without affecting the previous contents of the cut/copy buffer."
7541 );
7542 return;
7543 }
7544
7545 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
7546
7547 DEBUG(printf("Delete Traces\n"));
7548
7549 num_cut = DeleteBuffer();
7550 if(num_cut)
7551 {
7552 MaxSignalLength();
7553 signalarea_configure_event(GLOBALS->signalarea, NULL);
7554 wavearea_configure_event(GLOBALS->wavearea, NULL);
7555 }
7556 else
7557 {
7558 must_sel();
7559 }
7560 }
7561
7562 void
7563 menu_copy_traces(gpointer null_data, guint callback_action, GtkWidget *widget)
7564 {
7565 (void)null_data;
7566 (void)callback_action;
7567 (void)widget;
7568
7569 Trptr t = GLOBALS->traces.first;
7570 gboolean highlighted = FALSE;
7571
7572 if(GLOBALS->helpbox_is_active)
7573 {
7574 help_text_bold("\n\nCopy");
7575 help_text(
7576 " copies highlighted signals from the display and places them"
7577 " in an offscreen cut/copy buffer for later Paste operations. "
7578 " Copy implicitly destroys the previous contents of the cut/copy buffer."
7579 );
7580 return;
7581 }
7582
7583 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
7584
7585 DEBUG(printf("Copy Traces\n"));
7586
7587 while(t)
7588 {
7589 if(t->flags & TR_HIGHLIGHT)
7590 {
7591 highlighted = TRUE;
7592 break;
7593 }
7594 t = t->t_next;
7595 }
7596
7597 if(!highlighted)
7598 {
7599 must_sel();
7600 }
7601 else
7602 {
7603 if(GLOBALS->cutcopylist)
7604 {
7605 free_2(GLOBALS->cutcopylist);
7606 }
7607 GLOBALS->cutcopylist = emit_gtkwave_savefile_formatted_entries_in_tcl_list(GLOBALS->traces.first, TRUE);
7608 /* printf("Copylist: '%s'\n", GLOBALS->cutcopylist); */
7609
7610 FreeCutBuffer();
7611 }
7612 }
7613
7614 void
7615 menu_paste_traces(gpointer null_data, guint callback_action, GtkWidget *widget)
7616 {
7617 (void)null_data;
7618 (void)callback_action;
7619 (void)widget;
7620
7621 if(GLOBALS->helpbox_is_active)
7622 {
7623 help_text_bold("\n\nPaste");
7624 help_text(
7625 " pastes signals from"
7626 " an offscreen cut/copy buffer and places them in a group after"
7627 " the last highlighted signal, or at the end of the display"
7628 " if no signal is highlighted."
7629 );
7630 return;
7631 }
7632
7633 if(GLOBALS->dnd_state) { dnd_error(); return; } /* don't mess with sigs when dnd active */
7634
7635 DEBUG(printf("Paste Traces\n"));
7636
7637 if(PasteBuffer())
7638 {
7639 GLOBALS->signalwindow_width_dirty=1;
7640 MaxSignalLength();
7641 signalarea_configure_event(GLOBALS->signalarea, NULL);
7642 wavearea_configure_event(GLOBALS->wavearea, NULL);
7643 }
7644 else
7645 {
7646 if(GLOBALS->cutcopylist)
7647 {
7648 /*int num_traces =*/ process_tcl_list(GLOBALS->cutcopylist, FALSE);
7649 /* printf("Pastelist: %d '%s'\n", num_traces, GLOBALS->cutcopylist); */
7650
7651 GLOBALS->signalwindow_width_dirty=1;
7652 MaxSignalLength();
7653 signalarea_configure_event(GLOBALS->signalarea, NULL);
7654 wavearea_configure_event(GLOBALS->wavearea, NULL);
7655 }
7656 }
7657
7658 }
7659 /**/
7660 void menu_center_zooms(gpointer null_data, guint callback_action, GtkWidget *widget)
7661 {
7662 (void)null_data;
7663 (void)callback_action;
7664 (void)widget;
7665
7666 if(GLOBALS->helpbox_is_active)
7667 {
7668 help_text_bold("\n\nCenter Zooms");
7669 help_text(
7670 " when enabled"
7671 " configures zoom in/out operations such that all zooms use the center of the"
7672 " display as the fixed zoom origin if the primary (unnamed) marker is"
7673 " not present, otherwise, the primary marker is used as the center origin."
7674 " When disabled, it"
7675 " configures zoom in/out operations such that all zooms use the"
7676 " left margin of the display as the fixed zoom origin."
7677 );
7678 }
7679 else
7680 {
7681 #ifndef WAVE_USE_MLIST_T
7682 GLOBALS->do_zoom_center=(GLOBALS->do_zoom_center)?0:1;
7683 #else
7684 GLOBALS->do_zoom_center = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VCZ]));
7685 #endif
7686 DEBUG(printf("Center Zooms\n"));
7687 }
7688
7689 #ifndef WAVE_USE_MLIST_T
7690 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VCZ].path))->active=(GLOBALS->do_zoom_center)?TRUE:FALSE;
7691 #endif
7692 }
7693
7694
7695 void menu_show_base(gpointer null_data, guint callback_action, GtkWidget *widget)
7696 {
7697 (void)null_data;
7698 (void)callback_action;
7699 (void)widget;
7700
7701 if(GLOBALS->helpbox_is_active)
7702 {
7703 help_text_bold("\n\nShow Base Symbols");
7704 help_text(
7705 " enables the display of leading base symbols ('$' for hex,"
7706 " '%' for binary, '#' for octal if they are turned off and"
7707 " disables the drawing of leading base symbols if"
7708 " they are turned on."
7709 " Base symbols are displayed by default."
7710 );
7711 }
7712 else
7713 {
7714 #ifndef WAVE_USE_MLIST_T
7715 GLOBALS->show_base=(GLOBALS->show_base)?0:~0;
7716 #else
7717 GLOBALS->show_base = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VSBS]));
7718 #endif
7719 GLOBALS->signalwindow_width_dirty=1;
7720 MaxSignalLength();
7721 signalarea_configure_event(GLOBALS->signalarea, NULL);
7722 wavearea_configure_event(GLOBALS->wavearea, NULL);
7723 DEBUG(printf("Show Base Symbols\n"));
7724 }
7725
7726 #ifndef WAVE_USE_MLIST_T
7727 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VSBS].path))->active=(GLOBALS->show_base)?TRUE:FALSE;
7728 #endif
7729 }
7730
7731 /**/
7732 void menu_show_grid(gpointer null_data, guint callback_action, GtkWidget *widget)
7733 {
7734 (void)null_data;
7735 (void)callback_action;
7736 (void)widget;
7737
7738 if(GLOBALS->helpbox_is_active)
7739 {
7740 help_text_bold("\n\nShow Grid");
7741 help_text(
7742 " toggles the drawing of gridlines in the waveform display."
7743 );
7744 }
7745 else
7746 {
7747 #ifndef WAVE_USE_MLIST_T
7748 GLOBALS->display_grid=(GLOBALS->display_grid)?0:~0;
7749 #else
7750 GLOBALS->display_grid = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VSG]));
7751 #endif
7752 if(GLOBALS->wave_hslider)
7753 {
7754 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)),"changed");
7755 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)),"value_changed");
7756 }
7757 DEBUG(printf("Show Grid\n"));
7758 }
7759
7760 #ifndef WAVE_USE_MLIST_T
7761 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VSG].path))->active=(GLOBALS->display_grid)?TRUE:FALSE;
7762 #endif
7763 }
7764
7765 /**/
7766 void menu_show_wave_highlight(gpointer null_data, guint callback_action, GtkWidget *widget)
7767 {
7768 (void)null_data;
7769 (void)callback_action;
7770 (void)widget;
7771
7772 if(GLOBALS->helpbox_is_active)
7773 {
7774 help_text_bold("\n\nShow Wave Highlight");
7775 help_text(
7776 " toggles the drawing of highlighted waveforms (instead of gridlines) in the waveform display."
7777 );
7778 }
7779 else
7780 {
7781 #ifndef WAVE_USE_MLIST_T
7782 GLOBALS->highlight_wavewindow=(GLOBALS->highlight_wavewindow)?0:~0;
7783 #else
7784 GLOBALS->highlight_wavewindow = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_SHW]));
7785 #endif
7786 if(GLOBALS->wave_hslider)
7787 {
7788 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)),"changed");
7789 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)),"value_changed");
7790 }
7791 DEBUG(printf("Show Wave Highlight\n"));
7792 }
7793
7794 #ifndef WAVE_USE_MLIST_T
7795 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_SHW].path))->active=(GLOBALS->highlight_wavewindow)?TRUE:FALSE;
7796 #endif
7797 }
7798
7799 /**/
7800 void menu_show_filled_high_values(gpointer null_data, guint callback_action, GtkWidget *widget)
7801 {
7802 (void)null_data;
7803 (void)callback_action;
7804 (void)widget;
7805
7806 if(GLOBALS->helpbox_is_active)
7807 {
7808 help_text_bold("\n\nShow Filled High Values");
7809 help_text(
7810 " toggles the drawing of filled in 1/H values in the waveform display."
7811 );
7812 }
7813 else
7814 {
7815 #ifndef WAVE_USE_MLIST_T
7816 GLOBALS->fill_waveform=(GLOBALS->fill_waveform)?0:~0;
7817 #else
7818 GLOBALS->fill_waveform = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_FILL1]));
7819 #endif
7820 if(GLOBALS->wave_hslider)
7821 {
7822 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)),"changed");
7823 gtk_signal_emit_by_name (GTK_OBJECT (GTK_ADJUSTMENT(GLOBALS->wave_hslider)),"value_changed");
7824 }
7825 DEBUG(printf("Show Filled High Values\n"));
7826 }
7827
7828 #ifndef WAVE_USE_MLIST_T
7829 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_FILL1].path))->active=(GLOBALS->fill_waveform)?TRUE:FALSE;
7830 #endif
7831 }
7832
7833 /**/
7834 void menu_show_mouseover(gpointer null_data, guint callback_action, GtkWidget *widget)
7835 {
7836 (void)null_data;
7837 (void)callback_action;
7838 (void)widget;
7839
7840 if(GLOBALS->helpbox_is_active)
7841 {
7842 help_text_bold("\n\nShow Mouseover");
7843 help_text(
7844 " toggles the dynamic tooltip for signal names and values which follow the marker on mouse button presses in the waveform display."
7845 " This is useful for examining the values of closely packed value changes without having to zoom outward and without having to"
7846 " refer to the signal name pane to the left. Note that an encoded string will be displayed next to the signal name that"
7847 " indicates what data format flags are currently active for that signal. Flags are as follows:\n"
7848 " + = Signed Decimal\n"
7849 " X = Hexadecimal\n"
7850 " A = ASCII\n"
7851 " D = Decimal\n"
7852 " B = Binary\n"
7853 " O = Octal\n"
7854 " J = Right Justify\n"
7855 " ~ = Invert\n"
7856 " V = Reverse\n"
7857 " * = Analog Step+Interpolated\n"
7858 " S = Analog Step\n"
7859 " I = Analog Interpolated\n"
7860 " R = Real\n"
7861 " r = Real to Bits\n"
7862 " 0 = Range Fill with 0s\n"
7863 " 1 = Range Fill with 1s\n"
7864 " G = Binary to Gray\n"
7865 " g = Gray to Binary\n"
7866 " F = File Filter\n"
7867 " P = Process Filter\n"
7868 " T = Transaction Filter\n"
7869 " p = Population Count\n"
7870 " s = Fixed Point Shift (count)\n"
7871 );
7872 }
7873 else
7874 {
7875 GLOBALS->disable_mouseover=(GLOBALS->disable_mouseover)?0:~0;
7876 DEBUG(printf("Show Mouseover\n"));
7877 }
7878
7879 #ifndef WAVE_USE_MLIST_T
7880 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VSMO].path))->active=(GLOBALS->disable_mouseover)?FALSE:TRUE;
7881 #else
7882 GLOBALS->disable_mouseover = !gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VSMO]));
7883 #endif
7884 }
7885
7886 /**/
7887 #ifdef WAVE_USE_GTK2
7888 void menu_clipboard_mouseover(gpointer null_data, guint callback_action, GtkWidget *widget)
7889 {
7890 (void)null_data;
7891 (void)callback_action;
7892 (void)widget;
7893
7894 if(GLOBALS->helpbox_is_active)
7895 {
7896 help_text_bold("\n\nMouseover Copies To Clipboard");
7897 help_text(
7898 " toggles automatic copying to the clipboard of mouseover values. Requires that Show Mouseover is enabled.\n"
7899 );
7900 }
7901 else
7902 {
7903 GLOBALS->clipboard_mouseover=(GLOBALS->clipboard_mouseover)?0:~0;
7904 DEBUG(printf("Mouseover Copies To Clipboard\n"));
7905 }
7906
7907 #ifndef WAVE_USE_MLIST_T
7908 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VSMC].path))->active=(GLOBALS->clipboard_mouseover)?TRUE:FALSE;
7909 #else
7910 GLOBALS->clipboard_mouseover = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VSMC]));
7911 #endif
7912 }
7913 #endif
7914 /**/
7915
7916
7917 /* this is the GtkMenuEntry structure used to create new menus. The
7918 * first member is the menu definition string. The second, the
7919 * default accelerator key used to access this menu function with
7920 * the keyboard. The third is the callback function to call when
7921 * this menu item is selected (by the accelerator key, or with the
7922 * mouse.) The last member is the data to pass to your callback function.
7923 *
7924 * ...This has all been changed to use itemfactory stuff which is more
7925 * powerful. The only real difference is the final item which tells
7926 * the itemfactory just what the item "is".
7927 */
7928 #ifdef WAVE_USE_MENU_BLACKOUTS
7929 static const char *menu_blackouts[] = { "/Edit", "/Search", "/Time", "/Markers", "/View" };
7930 #endif
7931
7932 static gtkwave_mlist_t menu_items[] =
7933 {
7934 WAVE_GTKIFE("/File/Open New Window", "<Control>N", menu_new_viewer, WV_MENU_FONV, "<Item>"),
7935 WAVE_GTKIFE("/File/Open New Tab", "<Control>T", menu_new_viewer_tab, WV_MENU_FONVT, "<Item>"),
7936 WAVE_GTKIFE("/File/Reload Waveform", "<Shift><Control>R", menu_reload_waveform, WV_MENU_FRW, "<Item>"),
7937 WAVE_GTKIFE("/File/Export/Write VCD File As", NULL, menu_write_vcd_file, WV_MENU_WRVCD, "<Item>"),
7938 WAVE_GTKIFE("/File/Export/Write LXT File As", NULL, menu_write_lxt_file, WV_MENU_WRLXT, "<Item>"),
7939 WAVE_GTKIFE("/File/Export/Write TIM File As", NULL, menu_write_tim_file, WV_MENU_WRTIM, "<Item>"),
7940 WAVE_GTKIFE("/File/Close", "<Control>W", menu_quit_close, WV_MENU_WCLOSE, "<Item>"),
7941 WAVE_GTKIFE("/File/<separator>", NULL, NULL, WV_MENU_SEP2VCD, "<Separator>"),
7942 WAVE_GTKIFE("/File/Print To File", "<Control>P", menu_print, WV_MENU_FPTF, "<Item>"),
7943
7944 #if GTK_CHECK_VERSION(2,14,0)
7945 WAVE_GTKIFE("/File/Grab To File", NULL, menu_write_screengrab_as, WV_MENU_SGRAB, "<Item>"),
7946 #endif
7947
7948 WAVE_GTKIFE("/File/<separator>", NULL, NULL, WV_MENU_SEP1, "<Separator>"),
7949 WAVE_GTKIFE("/File/Read Save File", "<Control>O", menu_read_save_file, WV_MENU_FRSF, "<Item>"),
7950 WAVE_GTKIFE("/File/Write Save File", "<Control>S", menu_write_save_file, WV_MENU_FWSF, "<Item>"),
7951 WAVE_GTKIFE("/File/Write Save File As", "<Shift><Control>S", menu_write_save_file_as, WV_MENU_FWSFAS, "<Item>"),
7952 WAVE_GTKIFE("/File/<separator>", NULL, NULL, WV_MENU_SEP2, "<Separator>"),
7953 WAVE_GTKIFE("/File/Read Sim Logfile", "L", menu_read_log_file, WV_MENU_FRLF, "<Item>"),
7954 /* 10 */
7955 WAVE_GTKIFE("/File/<separator>", NULL, NULL, WV_MENU_SEP2LF, "<Separator>"),
7956 #if !defined _MSC_VER
7957 WAVE_GTKIFE("/File/Read Verilog Stemsfile", NULL, menu_read_stems_file, WV_MENU_FRSTMF, "<Item>"),
7958 WAVE_GTKIFE("/File/<separator>", NULL, NULL, WV_MENU_SEP2STMF, "<Separator>"),
7959 #endif
7960 #if defined(HAVE_LIBTCL)
7961 WAVE_GTKIFE("/File/Read Tcl Script File", NULL, menu_read_script_file, WV_MENU_TCLSCR, "<Item>"),
7962 WAVE_GTKIFE("/File/<separator>", NULL, NULL, WV_MENU_TCLSEP, "<Separator>"),
7963 #endif
7964
7965 WAVE_GTKIFE("/File/Quit", "<Control>Q", menu_quit, WV_MENU_FQY, "<Item>"),
7966
7967 WAVE_GTKIFE("/Edit/Set Trace Max Hier", NULL, menu_set_max_hier, WV_MENU_ESTMH, "<Item>"),
7968 WAVE_GTKIFE("/Edit/Toggle Trace Hier", "H", menu_toggle_hier, WV_MENU_ETH, "<Item>"),
7969 WAVE_GTKIFE("/Edit/<separator>", NULL, NULL, WV_MENU_SEP3, "<Separator>"),
7970 WAVE_GTKIFE("/Edit/Insert Blank", "<Control>B", menu_insert_blank_traces, WV_MENU_EIB, "<Item>"),
7971 WAVE_GTKIFE("/Edit/Insert Comment", NULL, menu_insert_comment_traces, WV_MENU_EIC, "<Item>"),
7972 WAVE_GTKIFE("/Edit/Insert Analog Height Extension", NULL, menu_insert_analog_height_extension, WV_MENU_EIA, "<Item>"),
7973
7974 #ifdef MAC_INTEGRATION
7975 WAVE_GTKIFE("/Edit/Cut", NULL, menu_cut_traces, WV_MENU_EC, "<Item>"),
7976 WAVE_GTKIFE("/Edit/Copy", NULL, menu_copy_traces, WV_MENU_ECY, "<Item>"),
7977 WAVE_GTKIFE("/Edit/Paste", NULL, menu_paste_traces, WV_MENU_EP, "<Item>"),
7978 WAVE_GTKIFE("/Edit/Delete", NULL, menu_delete_traces, WV_MENU_DEL, "<Item>"),
7979 #else
7980 WAVE_GTKIFE("/Edit/Cut", "<Control>X", menu_cut_traces, WV_MENU_EC, "<Item>"),
7981 WAVE_GTKIFE("/Edit/Copy", "<Control>C", menu_copy_traces, WV_MENU_ECY, "<Item>"),
7982 WAVE_GTKIFE("/Edit/Paste", "<Control>V", menu_paste_traces, WV_MENU_EP, "<Item>"),
7983 WAVE_GTKIFE("/Edit/Delete", "<Control>Delete", menu_delete_traces, WV_MENU_DEL, "<Item>"),
7984 #endif
7985
7986 WAVE_GTKIFE("/Edit/<separator>", NULL, NULL, WV_MENU_SEP3A, "<Separator>"),
7987
7988 WAVE_GTKIFE("/Edit/Alias Highlighted Trace", "<Alt>A", menu_alias, WV_MENU_EAHT, "<Item>"),
7989 WAVE_GTKIFE("/Edit/Remove Highlighted Aliases", "<Shift><Alt>A", menu_remove_aliases, WV_MENU_ERHA, "<Item>"),
7990 /* 20 */
7991 WAVE_GTKIFE("/Edit/<separator>", NULL, NULL, WV_MENU_SEP4, "<Separator>"),
7992 WAVE_GTKIFE("/Edit/Expand", "F3", menu_expand, WV_MENU_EE, "<Item>"),
7993 WAVE_GTKIFE("/Edit/Combine Down", "F4", menu_combine_down, WV_MENU_ECD, "<Item>"),
7994 WAVE_GTKIFE("/Edit/Combine Up", "F5", menu_combine_up, WV_MENU_ECU, "<Item>"),
7995 WAVE_GTKIFE("/Edit/<separator>", NULL, NULL, WV_MENU_SEP5, "<Separator>"),
7996 WAVE_GTKIFE("/Edit/Data Format/Hex", "<Alt>X", menu_dataformat_hex, WV_MENU_EDFH, "<Item>"),
7997 WAVE_GTKIFE("/Edit/Data Format/Decimal", "<Alt>D", menu_dataformat_dec, WV_MENU_EDFD, "<Item>"),
7998 /* 30 */
7999 WAVE_GTKIFE("/Edit/Data Format/Signed Decimal", NULL, menu_dataformat_signed, WV_MENU_EDFSD, "<Item>"),
8000 WAVE_GTKIFE("/Edit/Data Format/Binary", "<Alt>B", menu_dataformat_bin, WV_MENU_EDFB, "<Item>"),
8001 WAVE_GTKIFE("/Edit/Data Format/Octal", "<Alt>O", menu_dataformat_oct, WV_MENU_EDFO, "<Item>"),
8002 WAVE_GTKIFE("/Edit/Data Format/ASCII", NULL, menu_dataformat_ascii, WV_MENU_EDFA, "<Item>"),
8003 WAVE_GTKIFE("/Edit/Data Format/Time", NULL, menu_dataformat_time, WV_MENU_TIME, "<Item>"),
8004 WAVE_GTKIFE("/Edit/Data Format/Enum", NULL, menu_dataformat_enum, WV_MENU_ENUM, "<Item>"),
8005 WAVE_GTKIFE("/Edit/Data Format/BitsToReal", NULL, menu_dataformat_real, WV_MENU_EDRL, "<Item>"),
8006 WAVE_GTKIFE("/Edit/Data Format/RealToBits/On", NULL, menu_dataformat_real2bon, WV_MENU_EDR2BON, "<Item>"),
8007 WAVE_GTKIFE("/Edit/Data Format/RealToBits/Off", NULL, menu_dataformat_real2boff, WV_MENU_EDR2BOFF, "<Item>"),
8008 WAVE_GTKIFE("/Edit/Data Format/Right Justify/On", "<Alt>J", menu_dataformat_rjustify_on, WV_MENU_EDFRJON, "<Item>"),
8009 WAVE_GTKIFE("/Edit/Data Format/Right Justify/Off", "<Shift><Alt>J", menu_dataformat_rjustify_off, WV_MENU_EDFRJOFF, "<Item>"),
8010 WAVE_GTKIFE("/Edit/Data Format/Invert/On", "<Alt>I", menu_dataformat_invert_on, WV_MENU_EDFION, "<Item>"),
8011 WAVE_GTKIFE("/Edit/Data Format/Invert/Off", "<Shift><Alt>I", menu_dataformat_invert_off, WV_MENU_EDFIOFF, "<Item>"),
8012 WAVE_GTKIFE("/Edit/Data Format/Reverse Bits/On", "<Alt>V", menu_dataformat_reverse_on, WV_MENU_EDFRON, "<Item>"),
8013 /* 40 */
8014 WAVE_GTKIFE("/Edit/Data Format/Reverse Bits/Off", "<Shift><Alt>V", menu_dataformat_reverse_off, WV_MENU_EDFROFF, "<Item>"),
8015 WAVE_GTKIFE("/Edit/Data Format/Translate Filter File/Disable", NULL, menu_dataformat_xlate_file_0, WV_MENU_XLF_0, "<Item>"),
8016 WAVE_GTKIFE("/Edit/Data Format/Translate Filter File/Enable and Select", NULL, menu_dataformat_xlate_file_1, WV_MENU_XLF_1, "<Item>"),
8017 WAVE_GTKIFE("/Edit/Data Format/Translate Filter Process/Disable", NULL, menu_dataformat_xlate_proc_0, WV_MENU_XLP_0, "<Item>"),
8018 WAVE_GTKIFE("/Edit/Data Format/Translate Filter Process/Enable and Select", NULL, menu_dataformat_xlate_proc_1, WV_MENU_XLP_1, "<Item>"),
8019 WAVE_GTKIFE("/Edit/Data Format/Transaction Filter Process/Disable", NULL, menu_dataformat_xlate_ttrans_0, WV_MENU_TTXLP_0, "<Item>"),
8020 WAVE_GTKIFE("/Edit/Data Format/Transaction Filter Process/Enable and Select", NULL, menu_dataformat_xlate_ttrans_1, WV_MENU_TTXLP_1, "<Item>"),
8021 WAVE_GTKIFE("/Edit/Data Format/Analog/Off", NULL, menu_dataformat_analog_off, WV_MENU_EDFAOFF, "<Item>"),
8022 WAVE_GTKIFE("/Edit/Data Format/Analog/Step", NULL, menu_dataformat_analog_step, WV_MENU_EDFASTEP, "<Item>"),
8023 WAVE_GTKIFE("/Edit/Data Format/Analog/Interpolated", NULL, menu_dataformat_analog_interpol, WV_MENU_EDFAINTERPOL, "<Item>"),
8024 WAVE_GTKIFE("/Edit/Data Format/Analog/Interpolated Annotated", NULL, menu_dataformat_analog_interpol_step, WV_MENU_EDFAINTERPOL2, "<Item>"),
8025 WAVE_GTKIFE("/Edit/Data Format/Analog/Resizing/Screen Data", NULL, menu_dataformat_analog_resize_screen, WV_MENU_EDFARSD, "<Item>"),
8026 WAVE_GTKIFE("/Edit/Data Format/Analog/Resizing/All Data", NULL, menu_dataformat_analog_resize_all, WV_MENU_EDFARAD, "<Item>"),
8027 WAVE_GTKIFE("/Edit/Data Format/Range Fill/With 0s", NULL, menu_dataformat_rangefill_zero, WV_MENU_RFILL0, "<Item>"),
8028 WAVE_GTKIFE("/Edit/Data Format/Range Fill/With 1s", NULL, menu_dataformat_rangefill_one, WV_MENU_RFILL1, "<Item>"),
8029 WAVE_GTKIFE("/Edit/Data Format/Range Fill/Off", NULL, menu_dataformat_rangefill_off, WV_MENU_RFILLOFF, "<Item>"),
8030
8031 WAVE_GTKIFE("/Edit/Data Format/Gray Filters/To Gray", NULL, menu_dataformat_bingray_on, WV_MENU_B2G, "<Item>"),
8032 WAVE_GTKIFE("/Edit/Data Format/Gray Filters/From Gray", NULL, menu_dataformat_graybin_on, WV_MENU_G2B, "<Item>"),
8033 WAVE_GTKIFE("/Edit/Data Format/Gray Filters/None", NULL, menu_dataformat_nogray, WV_MENU_GBNONE, "<Item>"),
8034 WAVE_GTKIFE("/Edit/Data Format/Popcnt/On", NULL, menu_dataformat_popcnt_on, WV_MENU_POPON, "<Item>"),
8035 WAVE_GTKIFE("/Edit/Data Format/Popcnt/Off", NULL, menu_dataformat_popcnt_off, WV_MENU_POPOFF, "<Item>"),
8036 WAVE_GTKIFE("/Edit/Data Format/Find First One/On", NULL, menu_dataformat_ffo_on, WV_MENU_FFOON, "<Item>"),
8037 WAVE_GTKIFE("/Edit/Data Format/Find First One/Off", NULL, menu_dataformat_ffo_off, WV_MENU_FFOOFF, "<Item>"),
8038 WAVE_GTKIFE("/Edit/Data Format/Fixed Point Shift/On", NULL, menu_dataformat_fpshift_on, WV_MENU_FPSHIFTON, "<Item>"),
8039 WAVE_GTKIFE("/Edit/Data Format/Fixed Point Shift/Off", NULL, menu_dataformat_fpshift_off, WV_MENU_FPSHIFTOFF, "<Item>"),
8040 WAVE_GTKIFE("/Edit/Data Format/Fixed Point Shift/Specify", NULL, menu_dataformat_fpshift_specify, WV_MENU_FPSHIFTVAL, "<Item>"),
8041
8042 WAVE_GTKIFE("/Edit/Color Format/Normal", NULL, menu_colorformat_0, WV_MENU_CLRFMT0, "<Item>"),
8043 WAVE_GTKIFE("/Edit/Color Format/Red", NULL, menu_colorformat_1, WV_MENU_CLRFMT1, "<Item>"),
8044 WAVE_GTKIFE("/Edit/Color Format/Orange", NULL, menu_colorformat_2, WV_MENU_CLRFMT2, "<Item>"),
8045 WAVE_GTKIFE("/Edit/Color Format/Yellow", NULL, menu_colorformat_3, WV_MENU_CLRFMT3, "<Item>"),
8046 WAVE_GTKIFE("/Edit/Color Format/Green", NULL, menu_colorformat_4, WV_MENU_CLRFMT4, "<Item>"),
8047 WAVE_GTKIFE("/Edit/Color Format/Blue", NULL, menu_colorformat_5, WV_MENU_CLRFMT5, "<Item>"),
8048 WAVE_GTKIFE("/Edit/Color Format/Indigo", NULL, menu_colorformat_6, WV_MENU_CLRFMT6, "<Item>"),
8049 WAVE_GTKIFE("/Edit/Color Format/Violet", NULL, menu_colorformat_7, WV_MENU_CLRFMT7, "<Item>"),
8050 WAVE_GTKIFE("/Edit/Color Format/Cycle", NULL, menu_colorformat_cyc, WV_MENU_CLRFMTC, "<Item>"),
8051 WAVE_GTKIFE("/Edit/Color Format/<separator>", NULL, NULL, WV_MENU_SEP5A, "<Separator>"),
8052 WAVE_GTKIFE("/Edit/Color Format/Keep xz Colors", NULL, menu_keep_xz_colors, WV_MENU_KEEPXZ, "<ToggleItem>"),
8053 WAVE_GTKIFE("/Edit/Show-Change All Highlighted", NULL, menu_showchangeall, WV_MENU_ESCAH, "<Item>"),
8054 WAVE_GTKIFE("/Edit/Show-Change First Highlighted", "<Control>F", menu_showchange, WV_MENU_ESCFH, "<Item>"),
8055 /* 50 */
8056 WAVE_GTKIFE("/Edit/<separator>", NULL, NULL, WV_MENU_SEP6, "<Separator>"),
8057 WAVE_GTKIFE("/Edit/Time Warp/Warp Marked", NULL, menu_warp_traces, WV_MENU_WARP, "<Item>"),
8058 WAVE_GTKIFE("/Edit/Time Warp/Unwarp Marked", NULL, menu_unwarp_traces, WV_MENU_UNWARP, "<Item>"),
8059 WAVE_GTKIFE("/Edit/Time Warp/Unwarp All", NULL, menu_unwarp_traces_all, WV_MENU_UNWARPA, "<Item>"),
8060 WAVE_GTKIFE("/Edit/<separator>", NULL, NULL, WV_MENU_SEP7A, "<Separator>"),
8061 WAVE_GTKIFE("/Edit/Exclude", "<Shift><Alt>E", menu_dataformat_exclude_on, WV_MENU_EEX, "<Item>"),
8062 WAVE_GTKIFE("/Edit/Show", "<Shift><Alt>S", menu_dataformat_exclude_off, WV_MENU_ESH, "<Item>"),
8063 WAVE_GTKIFE("/Edit/<separator>", NULL, NULL, WV_MENU_SEP6A, "<Separator>"),
8064 /* WAVE_GTKIFE("/Edit/Expand All Groups", "F12", menu_expand_all, WV_MENU_EXA, "<Item>"), */
8065 /* WAVE_GTKIFE("/Edit/Collapse All Groups", "<Shift>F12", menu_collapse_all, WV_MENU_CPA, "<Item>"), */
8066 /* 60 */
8067 WAVE_GTKIFE("/Edit/Toggle Group Open|Close", "T", menu_toggle_group, WV_MENU_TG, "<Item>"),
8068 WAVE_GTKIFE("/Edit/Create Group", "G", menu_create_group, WV_MENU_AG, "<Item>"),
8069 WAVE_GTKIFE("/Edit/<separator>", NULL, NULL, WV_MENU_SEP6A1, "<Separator>"),
8070 WAVE_GTKIFE("/Edit/Highlight Regexp", "<Alt>R", menu_regexp_highlight, WV_MENU_EHR, "<Item>"),
8071 WAVE_GTKIFE("/Edit/UnHighlight Regexp", "<Shift><Alt>R", menu_regexp_unhighlight, WV_MENU_EUHR, "<Item>"),
8072
8073 #ifdef MAC_INTEGRATION
8074 WAVE_GTKIFE("/Edit/Highlight All", NULL, menu_dataformat_highlight_all, WV_MENU_EHA, "<Item>"),
8075 WAVE_GTKIFE("/Edit/UnHighlight All", NULL, menu_dataformat_unhighlight_all, WV_MENU_EUHA, "<Item>"),
8076 #else
8077 WAVE_GTKIFE("/Edit/Highlight All", "<Control>A", menu_dataformat_highlight_all, WV_MENU_EHA, "<Item>"),
8078 WAVE_GTKIFE("/Edit/UnHighlight All", "<Shift><Control>A", menu_dataformat_unhighlight_all, WV_MENU_EUHA, "<Item>"),
8079 #endif
8080
8081 WAVE_GTKIFE("/Edit/<separator>", NULL, NULL, WV_MENU_SEP6B, "<Separator>"),
8082 WAVE_GTKIFE("/Edit/Sort/Alphabetize All", NULL, menu_alphabetize, WV_MENU_ALPHA, "<Item>"),
8083 WAVE_GTKIFE("/Edit/Sort/Alphabetize All (CaseIns)", NULL, menu_alphabetize2, WV_MENU_ALPHA2, "<Item>"),
8084 WAVE_GTKIFE("/Edit/Sort/Sigsort All", NULL, menu_lexize, WV_MENU_LEX, "<Item>"),
8085 WAVE_GTKIFE("/Edit/Sort/Reverse All", NULL, menu_reverse, WV_MENU_RVS, "<Item>"),
8086 /* 70 */
8087 WAVE_GTKIFE("/Search/Pattern Search 1", NULL, menu_tracesearchbox, WV_MENU_SPS, "<Item>"),
8088 #ifdef WAVE_USE_GTK2
8089 WAVE_GTKIFE("/Search/Pattern Search 2", NULL, menu_tracesearchbox, WV_MENU_SPS2, "<Item>"),
8090 #endif
8091 WAVE_GTKIFE("/Search/<separator>", NULL, NULL, WV_MENU_SEP7B, "<Separator>"),
8092 WAVE_GTKIFE("/Search/Signal Search Regexp", "<Alt>S", menu_signalsearch, WV_MENU_SSR, "<Item>"),
8093 WAVE_GTKIFE("/Search/Signal Search Hierarchy", "<Alt>T", menu_hiersearch, WV_MENU_SSH, "<Item>"),
8094 WAVE_GTKIFE("/Search/Signal Search Tree", "<Shift><Alt>T", menu_treesearch, WV_MENU_SST, "<Item>"),
8095 WAVE_GTKIFE("/Search/<separator>", NULL, NULL, WV_MENU_SEP7, "<Separator>"),
8096 #if !defined __MINGW32__ && !defined _MSC_VER
8097 WAVE_GTKIFE("/Search/Open Source Definition", NULL, menu_open_hierarchy_source, WV_MENU_OPENHS, "<Item>"),
8098 WAVE_GTKIFE("/Search/Open Source Instantiation", NULL, menu_open_hierarchy_isource, WV_MENU_OPENIHS, "<Item>"),
8099 #endif
8100 WAVE_GTKIFE("/Search/Open Scope", NULL, menu_open_hierarchy, WV_MENU_OPENH, "<Item>"),
8101 WAVE_GTKIFE("/Search/<separator>", NULL, NULL, WV_MENU_SEP7D, "<Separator>"),
8102 WAVE_GTKIFE("/Search/Autocoalesce", NULL, menu_autocoalesce, WV_MENU_ACOL, "<ToggleItem>"),
8103 WAVE_GTKIFE("/Search/Autocoalesce Reversal", NULL, menu_autocoalesce_reversal, WV_MENU_ACOLR, "<ToggleItem>"),
8104 WAVE_GTKIFE("/Search/Autoname Bundles", NULL, menu_autoname_bundles_on, WV_MENU_ABON, "<ToggleItem>"),
8105 WAVE_GTKIFE("/Search/Search Hierarchy Grouping", NULL, menu_hgrouping, WV_MENU_HTGP, "<ToggleItem>"),
8106 /* 80 */
8107 WAVE_GTKIFE("/Search/<separator>", NULL, NULL, WV_MENU_SEP7C, "<Separator>"),
8108 WAVE_GTKIFE("/Search/Set Pattern Search Repeat Count", NULL, menu_strace_repcnt, WV_MENU_STRSE, "<Item>"),
8109
8110 WAVE_GTKIFE("/Time/Move To Time", "F1", menu_movetotime, WV_MENU_TMTT, "<Item>"),
8111 WAVE_GTKIFE("/Time/Zoom/Zoom Amount", "F2", menu_zoomsize, WV_MENU_TZZA, "<Item>"),
8112 WAVE_GTKIFE("/Time/Zoom/Zoom Base", "<Shift>F2", menu_zoombase, WV_MENU_TZZB, "<Item>"),
8113 WAVE_GTKIFE("/Time/Zoom/Zoom In", "<Control>plus", service_zoom_in_marshal, WV_MENU_TZZI, "<Item>"),
8114 WAVE_GTKIFE("/Time/Zoom/Zoom Out", "<Control>minus", service_zoom_out_marshal, WV_MENU_TZZO, "<Item>"),
8115 WAVE_GTKIFE("/Time/Zoom/Zoom Full", "<Control>0", service_zoom_full_marshal, WV_MENU_TZZBFL, "<Item>"),
8116 WAVE_GTKIFE("/Time/Zoom/Zoom Best Fit", "<Shift><Alt>F", service_zoom_fit_marshal, WV_MENU_TZZBF, "<Item>"),
8117 WAVE_GTKIFE("/Time/Zoom/Zoom To Start", "Home", service_zoom_left_marshal, WV_MENU_TZZTS, "<Item>"),
8118 WAVE_GTKIFE("/Time/Zoom/Zoom To End", "End", service_zoom_right_marshal, WV_MENU_TZZTE, "<Item>"),
8119 WAVE_GTKIFE("/Time/Zoom/Undo Zoom", "<Alt>U", service_zoom_undo_marshal, WV_MENU_TZUZ, "<Item>"),
8120 /* 90 */
8121 WAVE_GTKIFE("/Time/Fetch/Fetch Size", "F7", menu_fetchsize, WV_MENU_TFFS, "<Item>"),
8122 WAVE_GTKIFE("/Time/Fetch/Fetch ->", "<Alt>2", fetch_right_marshal, WV_MENU_TFFR, "<Item>"),
8123 WAVE_GTKIFE("/Time/Fetch/Fetch <-", "<Alt>1", fetch_left_marshal, WV_MENU_TFFL, "<Item>"),
8124 WAVE_GTKIFE("/Time/Discard/Discard ->", "<Alt>4", discard_right_marshal, WV_MENU_TDDR, "<Item>"),
8125 WAVE_GTKIFE("/Time/Discard/Discard <-", "<Alt>3", discard_left_marshal, WV_MENU_TDDL, "<Item>"),
8126 WAVE_GTKIFE("/Time/Shift/Shift ->", "<Alt>6", service_right_shift_marshal, WV_MENU_TSSR, "<Item>"),
8127 WAVE_GTKIFE("/Time/Shift/Shift <-", "<Alt>5", service_left_shift_marshal, WV_MENU_TSSL, "<Item>"),
8128 WAVE_GTKIFE("/Time/Page/Page ->", "<Alt>8", service_right_page_marshal, WV_MENU_TPPR, "<Item>"),
8129 WAVE_GTKIFE("/Time/Page/Page <-", "<Alt>7", service_left_page_marshal, WV_MENU_TPPL, "<Item>"),
8130 WAVE_GTKIFE("/Markers/Show-Change Marker Data", "<Alt>M", menu_markerbox, WV_MENU_MSCMD, "<Item>"),
8131 /* 100 */
8132 WAVE_GTKIFE("/Markers/Drop Named Marker", "<Alt>N", drop_named_marker, WV_MENU_MDNM, "<Item>"),
8133 WAVE_GTKIFE("/Markers/Collect Named Marker", "<Shift><Alt>N", collect_named_marker, WV_MENU_MCNM, "<Item>"),
8134 WAVE_GTKIFE("/Markers/Collect All Named Markers", "<Shift><Control><Alt>N", collect_all_named_markers, WV_MENU_MCANM, "<Item>"),
8135 #ifdef MAC_INTEGRATION
8136 WAVE_GTKIFE("/Markers/Copy Primary->B Marker", NULL, copy_pri_b_marker, WV_MENU_MCAB, "<Item>"),
8137 #else
8138 WAVE_GTKIFE("/Markers/Copy Primary->B Marker", "B", copy_pri_b_marker, WV_MENU_MCAB, "<Item>"),
8139 #endif
8140 WAVE_GTKIFE("/Markers/Delete Primary Marker", "<Shift><Alt>M", delete_unnamed_marker, WV_MENU_MDPM, "<Item>"),
8141 WAVE_GTKIFE("/Markers/<separator>", NULL, NULL, WV_MENU_SEP8, "<Separator>"),
8142 WAVE_GTKIFE("/Markers/Find Previous Edge", NULL, service_left_edge_marshal, WV_MENU_SLE, "<Item>"),
8143 WAVE_GTKIFE("/Markers/Find Next Edge", NULL, service_right_edge_marshal, WV_MENU_SRE, "<Item>"),
8144 WAVE_GTKIFE("/Markers/<separator>", NULL, NULL, WV_MENU_SEP8B, "<Separator>"),
8145 WAVE_GTKIFE("/Markers/Alternate Wheel Mode", NULL, menu_altwheel, WV_MENU_HSWM, "<ToggleItem>"),
8146 WAVE_GTKIFE("/Markers/Wave Scrolling", "F9", wave_scrolling_on, WV_MENU_MWSON, "<ToggleItem>"),
8147
8148 WAVE_GTKIFE("/Markers/Locking/Lock to Lesser Named Marker", "Q", lock_marker_left, WV_MENU_MLKLT, "<Item>"),
8149 WAVE_GTKIFE("/Markers/Locking/Lock to Greater Named Marker", "W", lock_marker_right, WV_MENU_MLKRT, "<Item>"),
8150 WAVE_GTKIFE("/Markers/Locking/Unlock from Named Marker", "O", unlock_marker, WV_MENU_MLKOFF, "<Item>"),
8151
8152 WAVE_GTKIFE("/View/Show Grid", "<Alt>G", menu_show_grid, WV_MENU_VSG, "<ToggleItem>"),
8153 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP9, "<Separator>"),
8154 WAVE_GTKIFE("/View/Show Wave Highlight", NULL, menu_show_wave_highlight, WV_MENU_SHW, "<ToggleItem>"),
8155 WAVE_GTKIFE("/View/Show Filled High Values", NULL, menu_show_filled_high_values, WV_MENU_FILL1, "<ToggleItem>"),
8156 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP9B, "<Separator>"),
8157 WAVE_GTKIFE("/View/Show Mouseover", NULL, menu_show_mouseover, WV_MENU_VSMO, "<ToggleItem>"),
8158 #ifdef WAVE_USE_GTK2
8159 WAVE_GTKIFE("/View/Mouseover Copies To Clipboard", NULL, menu_clipboard_mouseover, WV_MENU_VSMC, "<ToggleItem>"),
8160 #endif
8161 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP9A, "<Separator>"),
8162 WAVE_GTKIFE("/View/Show Base Symbols", "<Alt>F1", menu_show_base, WV_MENU_VSBS, "<ToggleItem>"),
8163 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP10, "<Separator>"),
8164 /* 110 */
8165 WAVE_GTKIFE("/View/Standard Trace Select", NULL, menu_enable_standard_trace_select, WV_MENU_ESTS, "<ToggleItem>"),
8166 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP10A, "<Separator>"),
8167 WAVE_GTKIFE("/View/Dynamic Resize", "<Alt>9", menu_enable_dynamic_resize, WV_MENU_VDR, "<ToggleItem>"),
8168 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP11, "<Separator>"),
8169 WAVE_GTKIFE("/View/Center Zooms", "F8", menu_center_zooms, WV_MENU_VCZ, "<ToggleItem>"),
8170 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP12, "<Separator>"),
8171 WAVE_GTKIFE("/View/Toggle Delta-Frequency", NULL, menu_toggle_delta_or_frequency, WV_MENU_VTDF, "<Item>"),
8172 WAVE_GTKIFE("/View/Toggle Max-Marker", "F10", menu_toggle_max_or_marker, WV_MENU_VTMM, "<Item>"),
8173 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP13, "<Separator>"),
8174 WAVE_GTKIFE("/View/Constant Marker Update", "F11", menu_enable_constant_marker_update, WV_MENU_VCMU, "<ToggleItem>"),
8175 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP14, "<Separator>"),
8176 WAVE_GTKIFE("/View/Draw Roundcapped Vectors", "<Alt>F2", menu_use_roundcaps, WV_MENU_VDRV, "<ToggleItem>"),
8177 /* 120 */
8178 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP15, "<Separator>"),
8179 WAVE_GTKIFE("/View/Left Justified Signals", "<Shift>Home", menu_left_justify, WV_MENU_VLJS, "<Item>"),
8180 WAVE_GTKIFE("/View/Right Justified Signals", "<Shift>End", menu_right_justify, WV_MENU_VRJS, "<Item>"),
8181 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP16, "<Separator>"),
8182 WAVE_GTKIFE("/View/Zoom Pow10 Snap", "<Shift>Pause", menu_zoom10_snap, WV_MENU_VZPS, "<ToggleItem>"),
8183 WAVE_GTKIFE("/View/Partial VCD Dynamic Zoom Full", NULL, menu_zoom_dynf, WV_MENU_VZDYN, "<ToggleItem>"),
8184 WAVE_GTKIFE("/View/Partial VCD Dynamic Zoom To End", NULL, menu_zoom_dyne, WV_MENU_VZDYNE, "<ToggleItem>"),
8185 WAVE_GTKIFE("/View/Full Precision", "<Alt>Pause", menu_use_full_precision, WV_MENU_VFTP, "<ToggleItem>"),
8186 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP17, "<Separator>"),
8187 WAVE_GTKIFE("/View/Define Time Ruler Marks", NULL, menu_def_ruler, WV_MENU_RULER, "<Item>"),
8188 WAVE_GTKIFE("/View/Remove Pattern Marks", NULL, menu_remove_marked, WV_MENU_RMRKS, "<Item>"),
8189 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP17A, "<Separator>"),
8190 WAVE_GTKIFE("/View/Use Color", NULL, menu_use_color, WV_MENU_USECOLOR, "<Item>"),
8191 WAVE_GTKIFE("/View/Use Black and White", NULL, menu_use_bw, WV_MENU_USEBW, "<Item>"),
8192 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP18, "<Separator>"),
8193 WAVE_GTKIFE("/View/LXT Clock Compress to Z", NULL, menu_lxt_clk_compress, WV_MENU_LXTCC2Z, "<ToggleItem>"),
8194
8195 WAVE_GTKIFE("/View/<separator>", NULL, NULL, WV_MENU_SEP19, "<Separator>"),
8196 WAVE_GTKIFE("/View/Scale To Time Dimension/None", NULL, menu_scale_to_td_x, WV_MENU_TDSCALEX, "<ToggleItem>"),
8197 WAVE_GTKIFE("/View/Scale To Time Dimension/sec", NULL, menu_scale_to_td_s, WV_MENU_TDSCALES, "<ToggleItem>"),
8198 WAVE_GTKIFE("/View/Scale To Time Dimension/ms", NULL, menu_scale_to_td_m, WV_MENU_TDSCALEM, "<ToggleItem>"),
8199 WAVE_GTKIFE("/View/Scale To Time Dimension/us", NULL, menu_scale_to_td_u, WV_MENU_TDSCALEU, "<ToggleItem>"),
8200 WAVE_GTKIFE("/View/Scale To Time Dimension/ns", NULL, menu_scale_to_td_n, WV_MENU_TDSCALEN, "<ToggleItem>"),
8201 WAVE_GTKIFE("/View/Scale To Time Dimension/ps", NULL, menu_scale_to_td_p, WV_MENU_TDSCALEP, "<ToggleItem>"),
8202 WAVE_GTKIFE("/View/Scale To Time Dimension/fs", NULL, menu_scale_to_td_f, WV_MENU_TDSCALEF, "<ToggleItem>"),
8203
8204 /* 130 */
8205 WAVE_GTKIFE("/Help/WAVE Help", "<Control>H", menu_help, WV_MENU_HWH, "<Item>"),
8206 #ifdef MAC_INTEGRATION
8207 WAVE_GTKIFE("/Help/WAVE User Manual", NULL, menu_help_manual, WV_MENU_HWM, "<Item>"),
8208 #endif
8209 WAVE_GTKIFE("/Help/Wave Version", NULL, menu_version, WV_MENU_HWV, "<Item>"),
8210 };
8211
8212
8213 #ifndef WAVE_USE_MLIST_T
8214 void set_scale_to_time_dimension_toggles(void)
8215 {
8216 int i;
8217
8218 for(i = WV_MENU_TDSCALEX; i<= WV_MENU_TDSCALEF; i++)
8219 {
8220 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[i].path))->active=FALSE;
8221 }
8222
8223 switch(GLOBALS->scale_to_time_dimension)
8224 {
8225 case 's': i = WV_MENU_TDSCALES; break;
8226 case 'm': i = WV_MENU_TDSCALEM; break;
8227 case 'u': i = WV_MENU_TDSCALEU; break;
8228 case 'n': i = WV_MENU_TDSCALEN; break;
8229 case 'p': i = WV_MENU_TDSCALEP; break;
8230 case 'f': i = WV_MENU_TDSCALEF; break;
8231 default: i = WV_MENU_TDSCALEX; break;
8232 }
8233
8234 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[i].path))->active=TRUE;
8235 }
8236 #else
8237 void set_scale_to_time_dimension_toggles(void)
8238 {
8239 int i, ii;
8240
8241 switch(GLOBALS->scale_to_time_dimension)
8242 {
8243 case 's': ii = WV_MENU_TDSCALES; break;
8244 case 'm': ii = WV_MENU_TDSCALEM; break;
8245 case 'u': ii = WV_MENU_TDSCALEU; break;
8246 case 'n': ii = WV_MENU_TDSCALEN; break;
8247 case 'p': ii = WV_MENU_TDSCALEP; break;
8248 case 'f': ii = WV_MENU_TDSCALEF; break;
8249 default: ii = WV_MENU_TDSCALEX; break;
8250 }
8251
8252 for(i = WV_MENU_TDSCALEX; i<= WV_MENU_TDSCALEF; i++)
8253 {
8254 gboolean is_active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[i]));
8255 if(i!=ii)
8256 {
8257 if(is_active)
8258 {
8259 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[i]), FALSE);
8260 }
8261 }
8262 else
8263 {
8264 if(!is_active)
8265 {
8266 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[i]), TRUE);
8267 }
8268 }
8269 }
8270 }
8271 #endif
8272
8273 /*
8274 * set toggleitems to their initial states
8275 */
8276 #ifndef WAVE_USE_MLIST_T
8277 static void set_menu_toggles(void)
8278 {
8279 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VZPS].path))->active=(GLOBALS->zoom_pow10_snap)?TRUE:FALSE;
8280
8281 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VSG].path))->active=(GLOBALS->display_grid)?TRUE:FALSE;
8282
8283 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_SHW].path))->active=(GLOBALS->highlight_wavewindow)?TRUE:FALSE;
8284
8285 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_FILL1].path))->active=(GLOBALS->fill_waveform)?TRUE:FALSE;
8286
8287 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_HSWM].path))->active=(GLOBALS->alt_wheel_mode)?TRUE:FALSE;
8288
8289 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1,menu_items[WV_MENU_VSMO].path))->active=(GLOBALS->disable_mouseover)?FALSE:TRUE;
8290
8291 #ifdef WAVE_USE_GTK2
8292 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1,menu_items[WV_MENU_VSMC].path))->active=(GLOBALS->clipboard_mouseover)?TRUE:FALSE;
8293 #endif
8294
8295 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VSBS].path))->active=(GLOBALS->show_base)?TRUE:FALSE;
8296
8297 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VDR].path))->active=(GLOBALS->do_resize_signals)?TRUE:FALSE;
8298
8299 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_ESTS].path))->active=(GLOBALS->use_standard_trace_select)?TRUE:FALSE;
8300
8301 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VCMU].path))->active=(GLOBALS->constant_marker_update)?TRUE:FALSE;
8302
8303 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VCZ].path))->active=(GLOBALS->do_zoom_center)?TRUE:FALSE;
8304
8305 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VDRV].path))->active=(GLOBALS->use_roundcaps)?TRUE:FALSE;
8306
8307 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_MWSON].path))->active=(GLOBALS->wave_scrolling)?TRUE:FALSE;
8308
8309 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_ABON].path))->active=(GLOBALS->autoname_bundles)?TRUE:FALSE;
8310
8311 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_HTGP].path))->active=(GLOBALS->hier_grouping)?TRUE:FALSE;
8312
8313 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VFTP].path))->active=(GLOBALS->use_full_precision)?TRUE:FALSE;
8314
8315 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_ACOL].path))->active=(GLOBALS->autocoalesce)?TRUE:FALSE;
8316
8317 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_ACOLR].path))->active=(GLOBALS->autocoalesce_reversal)?TRUE:FALSE;
8318
8319 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_KEEPXZ].path))->active=(GLOBALS->keep_xz_colors)?TRUE:FALSE;
8320
8321 if(GLOBALS->partial_vcd)
8322 {
8323 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VZDYN].path))->active=(GLOBALS->zoom_dyn)?TRUE:FALSE;
8324 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VZDYNE].path))->active=(GLOBALS->zoom_dyne)?TRUE:FALSE;
8325 }
8326
8327 if(GLOBALS->loaded_file_type == LXT_FILE)
8328 {
8329 GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_LXTCC2Z].path))->active=(GLOBALS->lxt_clock_compress_to_z)?TRUE:FALSE;
8330 }
8331
8332 set_scale_to_time_dimension_toggles();
8333 }
8334 #else
8335 void set_menu_toggles(void)
8336 {
8337 GLOBALS->quiet_checkmenu = 1;
8338
8339 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VZPS]), GLOBALS->zoom_pow10_snap);
8340 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VSG]), GLOBALS->display_grid);
8341 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_SHW]), GLOBALS->highlight_wavewindow);
8342 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_FILL1]), GLOBALS->fill_waveform);
8343 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_HSWM]), GLOBALS->alt_wheel_mode);
8344
8345 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VSMO]), !GLOBALS->disable_mouseover);
8346
8347 #ifdef WAVE_USE_GTK2
8348 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VSMC]), GLOBALS->clipboard_mouseover);
8349 #endif
8350
8351 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VSBS]), GLOBALS->show_base);
8352 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VDR]), GLOBALS->do_resize_signals);
8353 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_ESTS]), GLOBALS->use_standard_trace_select);
8354 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VCMU]), GLOBALS->constant_marker_update);
8355 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VCZ]), GLOBALS->do_zoom_center);
8356 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VDRV]), GLOBALS->use_roundcaps);
8357 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_MWSON]), GLOBALS->wave_scrolling);
8358 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_ABON]), GLOBALS->autoname_bundles);
8359 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_HTGP]), GLOBALS->hier_grouping);
8360 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VFTP]), GLOBALS->use_full_precision);
8361 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_ACOL]), GLOBALS->autocoalesce);
8362 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_ACOLR]), GLOBALS->autocoalesce_reversal);
8363 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_KEEPXZ]), GLOBALS->keep_xz_colors);
8364
8365 if(GLOBALS->partial_vcd)
8366 {
8367 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VZDYN]), GLOBALS->zoom_dyn);
8368 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VZDYNE]), GLOBALS->zoom_dyne);
8369 }
8370
8371 if(GLOBALS->loaded_file_type == LXT_FILE)
8372 {
8373 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_LXTCC2Z]), GLOBALS->lxt_clock_compress_to_z);
8374 }
8375
8376 set_scale_to_time_dimension_toggles();
8377 GLOBALS->quiet_checkmenu = 0;
8378 }
8379 #endif
8380
8381
8382 /*
8383 * kill accelerator keys (e.g., if using twinwave as focus is sometimes wrong from parent window)
8384 */
8385 void kill_main_menu_accelerators(void)
8386 {
8387 int i;
8388
8389 for(i=0;i<WV_MENU_NUMITEMS;i++)
8390 {
8391 menu_items[i].accelerator = NULL;
8392 }
8393 }
8394
8395
8396 /*
8397 * create the menu through an itemfactory instance
8398 */
8399 #ifndef WAVE_USE_MLIST_T
8400 void get_main_menu(GtkWidget *window, GtkWidget ** menubar)
8401 {
8402 int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
8403 GtkAccelGroup *global_accel;
8404 int i;
8405 GtkWidget *mw;
8406
8407 GLOBALS->regexp_string_menu_c_1 = calloc_2(1, 129);
8408
8409 global_accel = gtk_accel_group_new();
8410 GLOBALS->item_factory_menu_c_1 = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", global_accel);
8411 gtk_item_factory_create_items(GLOBALS->item_factory_menu_c_1, nmenu_items, menu_items, NULL);
8412
8413 if(GLOBALS->loaded_file_type == MISSING_FILE)
8414 {
8415 for(i=0;i<nmenu_items;i++)
8416 {
8417 switch(i)
8418 {
8419 case WV_MENU_FONVT:
8420 case WV_MENU_WCLOSE:
8421 #if defined(HAVE_LIBTCL)
8422 case WV_MENU_TCLSCR:
8423 #endif
8424 case WV_MENU_FQY:
8425 case WV_MENU_HWH:
8426 #ifdef MAC_INTEGRATION
8427 case WV_MENU_HWM:
8428 #endif
8429 case WV_MENU_HWV:
8430 break;
8431
8432 default:
8433 mw = gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[i].path);
8434 if(mw) gtk_widget_set_sensitive(mw, FALSE);
8435 break;
8436 }
8437 }
8438
8439 #ifdef WAVE_USE_MENU_BLACKOUTS
8440 for(i=0;i<(sizeof(menu_blackouts)/sizeof(char *));i++)
8441 {
8442 mw = gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_blackouts[i]);
8443 if(mw) gtk_widget_set_sensitive(mw, FALSE);
8444 }
8445 #endif
8446 }
8447
8448 if(
8449 #ifdef WAVE_USE_GTK2
8450 (GLOBALS->socket_xid)||
8451 #endif
8452 (GLOBALS->partial_vcd))
8453 {
8454 gtk_item_factory_delete_item(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_FONVT].path);
8455 }
8456
8457 if(!GLOBALS->partial_vcd)
8458 {
8459 gtk_item_factory_delete_item(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VZDYN].path);
8460 gtk_item_factory_delete_item(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_VZDYNE].path);
8461 }
8462
8463 if(GLOBALS->loaded_file_type == DUMPLESS_FILE)
8464 {
8465 gtk_item_factory_delete_item(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_FRW].path);
8466 }
8467
8468 if(GLOBALS->loaded_file_type != LXT_FILE)
8469 {
8470 gtk_item_factory_delete_item(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_SEP18].path);
8471 gtk_item_factory_delete_item(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_LXTCC2Z].path);
8472 }
8473
8474 gtk_window_add_accel_group(GTK_WINDOW(window), global_accel);
8475 if(menubar)
8476 {
8477 *menubar = gtk_item_factory_get_widget (GLOBALS->item_factory_menu_c_1, "<main>");
8478 set_menu_toggles();
8479 }
8480 }
8481 #endif
8482
8483
8484 void menu_set_sensitive(void)
8485 {
8486 int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
8487 int i;
8488 GtkWidget *mw;
8489 #ifdef WAVE_USE_MENU_BLACKOUTS
8490 for(i=0;i<(sizeof(menu_blackouts)/sizeof(char *));i++)
8491 {
8492 mw = gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_blackouts[i]);
8493 if(mw) gtk_widget_set_sensitive(mw, TRUE);
8494 }
8495 #endif
8496
8497 for(i=0;i<nmenu_items;i++)
8498 {
8499 switch(i)
8500 {
8501 case WV_MENU_FONVT:
8502 case WV_MENU_WCLOSE:
8503 #if defined(HAVE_LIBTCL)
8504 case WV_MENU_TCLSCR:
8505 #endif
8506 case WV_MENU_FQY:
8507 case WV_MENU_HWH:
8508 #ifdef MAC_INTEGRATION
8509 case WV_MENU_HWM:
8510 #endif
8511 case WV_MENU_HWV:
8512 break;
8513
8514 default:
8515 #ifdef WAVE_USE_MLIST_T
8516 mw = menu_wlist[i];
8517 #else
8518 mw = gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[i].path);
8519 #endif
8520 if(mw)
8521 {
8522 #ifdef MAC_INTEGRATION
8523 if(menu_items[i].callback)
8524 #endif
8525 {
8526 gtk_widget_set_sensitive(mw, TRUE);
8527 }
8528 }
8529 break;
8530 }
8531 }
8532 }
8533
8534 /*
8535 * bail out
8536 */
8537 int file_quit_cmd_callback (GtkWidget *widget, gpointer data)
8538 {
8539 (void)widget;
8540 (void)data;
8541
8542 if(GLOBALS->save_on_exit) { menu_write_save_file(NULL, 0, NULL); }
8543
8544 if(!GLOBALS->enable_fast_exit)
8545 {
8546 simplereqbox("Quit Program",300,"Do you really want to quit?","Yes", "No", GTK_SIGNAL_FUNC(menu_quit_callback), 1);
8547 }
8548 else
8549 {
8550 #ifdef __CYGWIN__
8551 kill_stems_browser();
8552 #endif
8553 g_print ("WM Destroy\n");
8554 gtk_exit(0);
8555 }
8556
8557 return(TRUE); /* keeps "delete_event" from happening...we'll manually destory later if need be */
8558 }
8559
8560
8561 /*
8562 * RPC
8563 */
8564 int execute_script(char *name, int dealloc_name)
8565 {
8566 unsigned int i;
8567 int nlen = strlen(name);
8568
8569 if(GLOBALS->tcl_running)
8570 {
8571 fprintf(stderr, "Could not run script file '%s', as one is already running.\n", name);
8572
8573 if(dealloc_name)
8574 {
8575 free_2(name);
8576 }
8577
8578 return(0);
8579 }
8580
8581 GLOBALS->tcl_running = 1;
8582
8583 if(1) /* all scripts are Tcl now */
8584 {
8585 #if defined(HAVE_LIBTCL)
8586 int tclrc;
8587 char *tcl_cmd = wave_alloca(8 + nlen + 1 + 1); /* originally a malloc, but the script can change the context! */
8588 strcpy(tcl_cmd, "source {");
8589 strcpy(tcl_cmd+8, name);
8590 strcpy(tcl_cmd+8+nlen, "}");
8591
8592 fprintf(stderr, "GTKWAVE | Executing Tcl script '%s'\n", name);
8593
8594 if(dealloc_name)
8595 {
8596 free_2(name);
8597 }
8598
8599 #ifdef WIN32
8600 {
8601 char *slashfix = tcl_cmd;
8602 while(*slashfix)
8603 {
8604 if(*slashfix=='\\') *slashfix='/';
8605 slashfix++;
8606 }
8607 }
8608 #endif
8609
8610 tclrc = Tcl_Eval (GLOBALS->interp, tcl_cmd);
8611 if(tclrc != TCL_OK) { fprintf (stderr, "GTKWAVE | %s\n", Tcl_GetStringResult (GLOBALS->interp)); }
8612 #else
8613 fprintf(stderr, "GTKWAVE | Tcl support not compiled into gtkwave, exiting.\n");
8614 gtk_exit(255);
8615 #endif
8616 }
8617
8618 for(i=0;i<GLOBALS->num_notebook_pages;i++)
8619 {
8620 (*GLOBALS->contexts)[i]->wave_script_args = NULL; /* just in case there was a CTX swap */
8621 }
8622
8623 GLOBALS->tcl_running = 0;
8624 return(0);
8625 }
8626
8627
8628 gtkwave_mlist_t *retrieve_menu_items_array(int *num_items)
8629 {
8630 *num_items = sizeof(menu_items) / sizeof(menu_items[0]);
8631
8632 return(menu_items);
8633 }
8634
8635
8636 /*
8637 * support for menu accelerator modifications...
8638 */
8639 int set_wave_menu_accelerator(char *str)
8640 {
8641 char *path, *pathend;
8642 char *accel;
8643 int i;
8644
8645 path = strchr(str, '\"');
8646 if(!path) return(1);
8647 path++;
8648 if(!*path) return(1);
8649
8650 pathend = strchr(path, '\"');
8651 if(!pathend) return(1);
8652
8653 *pathend = 0;
8654
8655 accel = pathend + 1;
8656 while(*accel)
8657 {
8658 if(!isspace((int)(unsigned char)*accel)) break;
8659 accel++;
8660 }
8661
8662 if(!*accel) return(1);
8663
8664 if(strstr(path, "<separator>")) return(1);
8665 if(!strcmp(accel, "(null)"))
8666 {
8667 accel = NULL;
8668 }
8669 else
8670 {
8671 for(i=0;i<WV_MENU_NUMITEMS;i++)
8672 {
8673 if(menu_items[i].accelerator)
8674 {
8675 if(!strcmp(menu_items[i].accelerator, accel))
8676 {
8677 menu_items[i].accelerator = NULL;
8678 }
8679 }
8680 }
8681 }
8682
8683 for(i=0;i<WV_MENU_NUMITEMS;i++)
8684 {
8685 if(menu_items[i].path)
8686 {
8687 if(!strcmp(menu_items[i].path, path))
8688 {
8689 menu_items[i].accelerator = accel ? strdup_2(accel) : NULL;
8690 break;
8691 }
8692 }
8693 }
8694
8695 return(0);
8696 }
8697
8698
8699 /***********************/
8700 /*** popup menu code ***/
8701 /***********************/
8702
8703 static gtkwave_mlist_t popmenu_items[] =
8704 {
8705 WAVE_GTKIFE("/Data Format/Hex", NULL, menu_dataformat_hex, WV_MENU_EDFH, "<Item>"),
8706 WAVE_GTKIFE("/Data Format/Decimal", NULL, menu_dataformat_dec, WV_MENU_EDFD, "<Item>"),
8707 WAVE_GTKIFE("/Data Format/Signed Decimal", NULL, menu_dataformat_signed, WV_MENU_EDFSD, "<Item>"),
8708 WAVE_GTKIFE("/Data Format/Binary", NULL, menu_dataformat_bin, WV_MENU_EDFB, "<Item>"),
8709 WAVE_GTKIFE("/Data Format/Octal", NULL, menu_dataformat_oct, WV_MENU_EDFO, "<Item>"),
8710 WAVE_GTKIFE("/Data Format/ASCII", NULL, menu_dataformat_ascii, WV_MENU_EDFA, "<Item>"),
8711 WAVE_GTKIFE("/Data Format/Time", NULL, menu_dataformat_time, WV_MENU_TIME, "<Item>"),
8712 WAVE_GTKIFE("/Data Format/Enum", NULL, menu_dataformat_enum, WV_MENU_ENUM, "<Item>"),
8713 WAVE_GTKIFE("/Data Format/BitsToReal", NULL, menu_dataformat_real, WV_MENU_EDRL, "<Item>"),
8714 WAVE_GTKIFE("/Data Format/RealToBits/On", NULL, menu_dataformat_real2bon, WV_MENU_EDR2BON, "<Item>"),
8715 WAVE_GTKIFE("/Data Format/RealToBits/Off", NULL, menu_dataformat_real2boff, WV_MENU_EDR2BOFF, "<Item>"),
8716 WAVE_GTKIFE("/Data Format/Right Justify/On", NULL, menu_dataformat_rjustify_on, WV_MENU_EDFRJON, "<Item>"),
8717 WAVE_GTKIFE("/Data Format/Right Justify/Off", NULL, menu_dataformat_rjustify_off, WV_MENU_EDFRJOFF, "<Item>"),
8718 WAVE_GTKIFE("/Data Format/Invert/On", NULL, menu_dataformat_invert_on, WV_MENU_EDFION, "<Item>"),
8719 WAVE_GTKIFE("/Data Format/Invert/Off", NULL, menu_dataformat_invert_off, WV_MENU_EDFIOFF, "<Item>"),
8720 WAVE_GTKIFE("/Data Format/Reverse Bits/On", NULL, menu_dataformat_reverse_on, WV_MENU_EDFRON, "<Item>"),
8721 WAVE_GTKIFE("/Data Format/Reverse Bits/Off", NULL, menu_dataformat_reverse_off, WV_MENU_EDFROFF, "<Item>"),
8722 WAVE_GTKIFE("/Data Format/Translate Filter File/Disable", NULL, menu_dataformat_xlate_file_0, WV_MENU_XLF_0, "<Item>"),
8723 WAVE_GTKIFE("/Data Format/Translate Filter File/Enable and Select", NULL, menu_dataformat_xlate_file_1, WV_MENU_XLF_1, "<Item>"),
8724 WAVE_GTKIFE("/Data Format/Translate Filter Process/Disable", NULL, menu_dataformat_xlate_proc_0, WV_MENU_XLP_0, "<Item>"),
8725 WAVE_GTKIFE("/Data Format/Translate Filter Process/Enable and Select", NULL, menu_dataformat_xlate_proc_1, WV_MENU_XLP_1, "<Item>"),
8726 WAVE_GTKIFE("/Data Format/Transaction Filter Process/Disable", NULL, menu_dataformat_xlate_ttrans_0, WV_MENU_TTXLP_0, "<Item>"),
8727 WAVE_GTKIFE("/Data Format/Transaction Filter Process/Enable and Select", NULL, menu_dataformat_xlate_ttrans_1, WV_MENU_TTXLP_1, "<Item>"),
8728 WAVE_GTKIFE("/Data Format/Analog/Off", NULL, menu_dataformat_analog_off, WV_MENU_EDFAOFF, "<Item>"),
8729 WAVE_GTKIFE("/Data Format/Analog/Step", NULL, menu_dataformat_analog_step, WV_MENU_EDFASTEP, "<Item>"),
8730 WAVE_GTKIFE("/Data Format/Analog/Interpolated", NULL, menu_dataformat_analog_interpol, WV_MENU_EDFAINTERPOL, "<Item>"),
8731 WAVE_GTKIFE("/Data Format/Analog/Interpolated Annotated", NULL, menu_dataformat_analog_interpol_step, WV_MENU_EDFAINTERPOL2, "<Item>"),
8732 WAVE_GTKIFE("/Data Format/Analog/Resizing/Screen Data", NULL, menu_dataformat_analog_resize_screen, WV_MENU_EDFARSD, "<Item>"),
8733 WAVE_GTKIFE("/Data Format/Analog/Resizing/All Data", NULL, menu_dataformat_analog_resize_all, WV_MENU_EDFARAD, "<Item>"),
8734
8735 WAVE_GTKIFE("/Data Format/Range Fill/With 0s", NULL, menu_dataformat_rangefill_zero, WV_MENU_RFILL0, "<Item>"),
8736 WAVE_GTKIFE("/Data Format/Range Fill/With 1s", NULL, menu_dataformat_rangefill_one, WV_MENU_RFILL1, "<Item>"),
8737 WAVE_GTKIFE("/Data Format/Range Fill/Off", NULL, menu_dataformat_rangefill_off, WV_MENU_RFILLOFF, "<Item>"),
8738
8739 WAVE_GTKIFE("/Data Format/Gray Filters/To Gray", NULL, menu_dataformat_bingray_on, WV_MENU_B2G, "<Item>"),
8740 WAVE_GTKIFE("/Data Format/Gray Filters/From Gray", NULL, menu_dataformat_graybin_on, WV_MENU_G2B, "<Item>"),
8741 WAVE_GTKIFE("/Data Format/Gray Filters/None", NULL, menu_dataformat_nogray, WV_MENU_GBNONE, "<Item>"),
8742 WAVE_GTKIFE("/Data Format/Popcnt/On", NULL, menu_dataformat_popcnt_on, WV_MENU_POPON, "<Item>"),
8743 WAVE_GTKIFE("/Data Format/Popcnt/Off", NULL, menu_dataformat_popcnt_off, WV_MENU_POPOFF, "<Item>"),
8744 WAVE_GTKIFE("/Data Format/Find First One/On", NULL, menu_dataformat_ffo_on, WV_MENU_FFOON, "<Item>"),
8745 WAVE_GTKIFE("/Data Format/Find First One/Off", NULL, menu_dataformat_ffo_off, WV_MENU_FFOOFF, "<Item>"),
8746 WAVE_GTKIFE("/Data Format/Fixed Point Shift/On", NULL, menu_dataformat_fpshift_on, WV_MENU_FPSHIFTON, "<Item>"),
8747 WAVE_GTKIFE("/Data Format/Fixed Point Shift/Off", NULL, menu_dataformat_fpshift_off, WV_MENU_FPSHIFTOFF, "<Item>"),
8748 WAVE_GTKIFE("/Data Format/Fixed Point Shift/Specify", NULL, menu_dataformat_fpshift_specify, WV_MENU_FPSHIFTVAL, "<Item>"),
8749
8750 WAVE_GTKIFE("/Color Format/Normal", NULL, menu_colorformat_0, WV_MENU_CLRFMT0, "<Item>"),
8751 WAVE_GTKIFE("/Color Format/Red", NULL, menu_colorformat_1, WV_MENU_CLRFMT1, "<Item>"),
8752 WAVE_GTKIFE("/Color Format/Orange", NULL, menu_colorformat_2, WV_MENU_CLRFMT2, "<Item>"),
8753 WAVE_GTKIFE("/Color Format/Yellow", NULL, menu_colorformat_3, WV_MENU_CLRFMT3, "<Item>"),
8754 WAVE_GTKIFE("/Color Format/Green", NULL, menu_colorformat_4, WV_MENU_CLRFMT4, "<Item>"),
8755 WAVE_GTKIFE("/Color Format/Blue", NULL, menu_colorformat_5, WV_MENU_CLRFMT5, "<Item>"),
8756 WAVE_GTKIFE("/Color Format/Indigo", NULL, menu_colorformat_6, WV_MENU_CLRFMT6, "<Item>"),
8757 WAVE_GTKIFE("/Color Format/Violet", NULL, menu_colorformat_7, WV_MENU_CLRFMT7, "<Item>"),
8758 WAVE_GTKIFE("/Color Format/Cycle", NULL, menu_colorformat_cyc, WV_MENU_CLRFMTC, "<Item>"),
8759 WAVE_GTKIFE("/<separator>", NULL, NULL, WV_MENU_SEP1, "<Separator>"),
8760 WAVE_GTKIFE("/Insert Analog Height Extension", NULL, menu_insert_analog_height_extension, WV_MENU_EIA, "<Item>"),
8761 WAVE_GTKIFE("/<separator>", NULL, NULL, WV_MENU_SEP2, "<Separator>"),
8762
8763 WAVE_GTKIFE("/Insert Blank", NULL, menu_insert_blank_traces, WV_MENU_EIB, "<Item>"),
8764 WAVE_GTKIFE("/Insert Comment", NULL, menu_insert_comment_traces, WV_MENU_EIC, "<Item>"),
8765 WAVE_GTKIFE("/Alias Highlighted Trace", NULL, menu_alias, WV_MENU_EAHT, "<Item>"),
8766 WAVE_GTKIFE("/Remove Highlighted Aliases", NULL, menu_remove_aliases, WV_MENU_ERHA, "<Item>"),
8767 WAVE_GTKIFE("/<separator>", NULL, NULL, WV_MENU_SEP3, "<Separator>"),
8768 WAVE_GTKIFE("/Cut", NULL, menu_cut_traces, WV_MENU_EC, "<Item>"),
8769 WAVE_GTKIFE("/Copy", NULL, menu_copy_traces, WV_MENU_ECY, "<Item>"),
8770 WAVE_GTKIFE("/Paste", NULL, menu_paste_traces, WV_MENU_EP, "<Item>"),
8771 WAVE_GTKIFE("/Delete", NULL, menu_delete_traces, WV_MENU_DEL, "<Item>"),
8772 WAVE_GTKIFE("/<separator>", NULL, NULL, WV_MENU_SEP4, "<Separator>"),
8773 WAVE_GTKIFE("/Open Scope", NULL, menu_open_hierarchy, WV_MENU_OPENH, "<Item>")
8774 #if !defined __MINGW32__ && !defined _MSC_VER
8775 ,
8776 /* see do_popup_menu() for specific patch for this for if(!GLOBALS->stem_path_string_table) ... */
8777 WAVE_GTKIFE("/Open Source Definition", NULL, menu_open_hierarchy_source, WV_MENU_OPENHS, "<Item>"),
8778 WAVE_GTKIFE("/Open Source Instantiation", NULL, menu_open_hierarchy_isource, WV_MENU_OPENIHS, "<Item>")
8779 #endif
8780 };
8781
8782
8783 void do_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
8784 {
8785 (void)my_widget;
8786
8787 GtkWidget *menu;
8788 int button, event_time;
8789
8790 if(!GLOBALS->signal_popup_menu)
8791 {
8792 int nmenu_items = sizeof(popmenu_items) / sizeof(popmenu_items[0]);
8793
8794 #if !defined __MINGW32__ && !defined _MSC_VER
8795 if(!GLOBALS->stem_path_string_table)
8796 {
8797 nmenu_items = nmenu_items - 2; /* to remove WV_MENU_OPENHS, WV_MENU_OPENIHS -> keep at end of list! */
8798 }
8799 else
8800 {
8801 if(!GLOBALS->istem_struct_base)
8802 {
8803 nmenu_items--; /* remove "/Open Source Instantiation" if not present */
8804 }
8805 }
8806 #endif
8807
8808 #ifdef WAVE_USE_MLIST_T
8809 GLOBALS->signal_popup_menu = menu = alt_menu(popmenu_items, nmenu_items, NULL, NULL, FALSE);
8810 #else
8811 GtkItemFactory *item_factory = gtk_item_factory_new (GTK_TYPE_MENU, "<main>", NULL);
8812 gtk_item_factory_create_items (item_factory, nmenu_items, popmenu_items, NULL);
8813 GLOBALS->signal_popup_menu = menu = gtk_item_factory_get_widget (item_factory, "<main>");
8814 #endif
8815 }
8816 else
8817 {
8818 menu = GLOBALS->signal_popup_menu;
8819 }
8820
8821 if (event)
8822 {
8823 button = event->button;
8824 event_time = event->time;
8825 }
8826 else
8827 {
8828 button = 0;
8829 #if WAVE_USE_GTK2
8830 event_time = gtk_get_current_event_time ();
8831 #else
8832 return; /* disabled in GTK1.2 */
8833 #endif
8834 }
8835
8836 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
8837 button, event_time);
8838 }
8839
8840 /***************************/
8841 /*** sst popup menu code ***/
8842 /***************************/
8843
8844 #if WAVE_USE_GTK2
8845 static gtkwave_mlist_t sst_popmenu_items[] =
8846 {
8847 WAVE_GTKIFE("/Recurse Import/Append", NULL, menu_recurse_import, WV_RECURSE_APPEND, "<Item>"),
8848 WAVE_GTKIFE("/Recurse Import/Insert", NULL, menu_recurse_import, WV_RECURSE_INSERT, "<Item>"),
8849 WAVE_GTKIFE("/Recurse Import/Replace", NULL, menu_recurse_import, WV_RECURSE_REPLACE, "<Item>"),
8850
8851 #if !defined __MINGW32__ && !defined _MSC_VER
8852 WAVE_GTKIFE("/Open Source Definition", NULL, menu_open_sst_hierarchy_source, WV_MENU_OPENHS, "<Item>"),
8853 WAVE_GTKIFE("/Open Source Instantiation", NULL, menu_open_sst_hierarchy_isource, WV_MENU_OPENIHS, "<Item>"),
8854 #endif
8855 };
8856
8857
8858 void do_sst_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
8859 {
8860 (void)my_widget;
8861
8862 GtkWidget *menu;
8863 int button, event_time;
8864
8865 if(!GLOBALS->sst_signal_popup_menu)
8866 {
8867 int nmenu_items = sizeof(sst_popmenu_items) / sizeof(sst_popmenu_items[0]);
8868
8869 #if !defined __MINGW32__ && !defined _MSC_VER
8870 if(!GLOBALS->stem_path_string_table)
8871 {
8872 nmenu_items-=2; /* remove all stems popups */
8873 }
8874 else
8875 if(!GLOBALS->istem_struct_base)
8876 {
8877 nmenu_items--; /* remove "/Open Source Instantiation" if not present */
8878 }
8879 /* still have recurse import popup */
8880 #endif
8881
8882 #ifdef WAVE_USE_MLIST_T
8883 GLOBALS->sst_signal_popup_menu = menu = alt_menu(sst_popmenu_items, nmenu_items, NULL, NULL, FALSE);
8884 #else
8885 GtkItemFactory *item_factory = gtk_item_factory_new (GTK_TYPE_MENU, "<main>", NULL);
8886 gtk_item_factory_create_items (item_factory, nmenu_items, sst_popmenu_items, NULL);
8887 GLOBALS->sst_signal_popup_menu = menu = gtk_item_factory_get_widget (item_factory, "<main>");
8888 #endif
8889 }
8890 else
8891 {
8892 menu = GLOBALS->sst_signal_popup_menu;
8893 }
8894
8895 if (event)
8896 {
8897 button = event->button;
8898 event_time = event->time;
8899 }
8900 else
8901 {
8902 button = 0;
8903 #if WAVE_USE_GTK2
8904 event_time = gtk_get_current_event_time ();
8905 #else
8906 return; /* disabled in GTK1.2 */
8907 #endif
8908 }
8909
8910 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
8911 button, event_time);
8912 }
8913
8914 #else
8915
8916 void do_sst_popup_menu (GtkWidget *my_widget, GdkEventButton *event)
8917 {
8918 /* nothing */
8919 }
8920 #endif
8921
8922
8923 void SetTraceScrollbarRowValue(int row, unsigned location)
8924 {
8925 if(row >= 0)
8926 {
8927 GtkAdjustment *wadj=GTK_ADJUSTMENT(GLOBALS->wave_vslider);
8928 int target = row;
8929
8930 int num_traces_displayable=(GLOBALS->signalarea->allocation.height)/(GLOBALS->fontheight);
8931 num_traces_displayable--; /* for the time trace that is always there */
8932
8933 /* center */
8934 if (location == 1) {
8935 target = target - num_traces_displayable/2;
8936 }
8937
8938 /* end */
8939 if (location == 2) {
8940 target = target - num_traces_displayable;
8941 }
8942
8943 if(target > GLOBALS->traces.visible - num_traces_displayable) target = GLOBALS->traces.visible - num_traces_displayable;
8944
8945 if(target < 0) target = 0;
8946
8947 wadj->value = target;
8948
8949 gtk_signal_emit_by_name (GTK_OBJECT (wadj), "changed"); /* force bar update */
8950 gtk_signal_emit_by_name (GTK_OBJECT (wadj), "value_changed"); /* force text update */
8951 gtkwave_main_iteration();
8952
8953 }
8954 }
8955
8956
8957 #ifdef WAVE_USE_MLIST_T
8958
8959 /*
8960 * the following is for the eventual migration to GtkMenu from the item factory.
8961 * all menu features are implemented.
8962 */
8963
8964 struct menu_item_t
8965 {
8966 struct menu_item_t *next;
8967 struct menu_item_t *child;
8968
8969 char *name;
8970 int idx;
8971 unsigned valid : 1;
8972 };
8973
8974
8975 static void decompose_path(char *pathname, int *items, char ***parts)
8976 {
8977 char *s, **slashes;
8978 int i;
8979 int slashcount = 0;
8980 char *p_copy = strdup_2(pathname);
8981
8982 s = p_copy;
8983 while(*s)
8984 {
8985 if(*s == '/') slashcount++;
8986 s++;
8987 }
8988
8989 *parts = calloc_2(slashcount, sizeof(char *));
8990 slashes = calloc_2(slashcount, sizeof(char *));
8991
8992 s = p_copy;
8993 slashcount = 0;
8994 while(*s)
8995 {
8996 if(*s == '/') slashes[slashcount++] = s;
8997 s++;
8998 }
8999
9000 for(i=0;i<slashcount;i++)
9001 {
9002 if(i != (slashcount-1)) *(slashes[i+1]) = 0;
9003 (*parts)[i] = strdup_2(slashes[i] + 1);
9004
9005 if(i != (slashcount-1)) *(slashes[i+1]) = '/';
9006 }
9007
9008 *items = slashcount;
9009
9010 free_2(slashes);
9011 free_2(p_copy);
9012 }
9013
9014
9015 static void free_decomposed_path(int items, char **parts)
9016 {
9017 int i;
9018 for(i=0;i<items;i++)
9019 {
9020 free_2(parts[i]);
9021 }
9022
9023 free_2(parts);
9024 }
9025
9026
9027 static void alt_menu_install_accelerator(GtkAccelGroup *accel, GtkWidget *menuitem, const char *accelerator, const char *path)
9028 {
9029 if(accel && menuitem && path)
9030 {
9031 int no_map = 0;
9032 guint accelerator_key = 0;
9033 GdkModifierType accelerator_mods = 0;
9034 char full_path[1024];
9035 sprintf(full_path, "<main>%s", path);
9036
9037 if(accelerator)
9038 {
9039 gtk_accelerator_parse(accelerator, &accelerator_key, &accelerator_mods);
9040
9041 #ifdef MAC_INTEGRATION
9042 if((accelerator_mods & GDK_MOD1_MASK) ||
9043 (!accelerator_mods) || (accelerator_mods == GDK_SHIFT_MASK))
9044 {
9045 no_map = 1; /* ALT not available with GTK menus on OSX? */
9046 /* also remove "normal" keys to avoid conflicts with OSX menubar */
9047 }
9048 if(accelerator_mods & GDK_CONTROL_MASK)
9049 {
9050 accelerator_mods &= ~GDK_CONTROL_MASK;
9051 accelerator_mods |= GDK_META_MASK;
9052 }
9053 #endif
9054 }
9055
9056 if(!no_map)
9057 {
9058 gtk_accel_map_add_entry (full_path, accelerator_key, accelerator_mods);
9059 gtk_widget_set_accel_path (menuitem, full_path, accel);
9060 }
9061 }
9062 }
9063
9064 static GtkWidget *alt_menu_walk(gtkwave_mlist_t *mi, GtkWidget **wlist, struct menu_item_t *lst, int depth, GtkAccelGroup *accel)
9065 {
9066 struct menu_item_t *ptr = lst;
9067 struct menu_item_t *optr;
9068 GtkWidget *menu;
9069 GtkWidget *menuitem;
9070
9071 if(depth)
9072 {
9073 menu = gtk_menu_new();
9074
9075 if(accel) gtk_menu_set_accel_group (GTK_MENU(menu), accel);
9076 }
9077 else
9078 {
9079 menu = gtk_menu_bar_new();
9080 }
9081
9082 while(ptr)
9083 {
9084 /* mi[ptr->idx] is menu item */
9085
9086 if(!strcmp(mi[ptr->idx].item_type, "<Separator>"))
9087 {
9088 #ifdef MAC_INTEGRATION
9089 menuitem = gtk_separator_menu_item_new();
9090 #else
9091 menuitem = gtk_menu_item_new();
9092 #endif
9093 }
9094 else
9095 {
9096 if((!strcmp(mi[ptr->idx].item_type, "<ToggleItem>")) && !ptr->child)
9097 {
9098 menuitem = gtk_check_menu_item_new_with_label(ptr->name);
9099 }
9100 else
9101 {
9102 menuitem = gtk_menu_item_new_with_label(ptr->name);
9103 }
9104
9105 if(!ptr->child && mi[ptr->idx].callback)
9106 {
9107 g_signal_connect (menuitem, "activate", G_CALLBACK (mi[ptr->idx].callback), (gpointer)(intptr_t)mi[ptr->idx].callback_action);
9108 alt_menu_install_accelerator(accel, menuitem, mi[ptr->idx].accelerator, mi[ptr->idx].path);
9109 }
9110 }
9111
9112 gtk_menu_shell_append(GTK_MENU_SHELL (menu), menuitem);
9113 gtk_widget_show (menuitem);
9114
9115 if(wlist)
9116 {
9117 wlist[ptr->idx] = menuitem;
9118 }
9119
9120 if(ptr->child)
9121 {
9122 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), alt_menu_walk(mi, wlist, ptr->child, depth+1, accel));
9123 }
9124
9125 optr = ptr;
9126 ptr = ptr->next;
9127
9128 free_2(optr->name);
9129 free_2(optr);
9130 }
9131
9132 return(menu);
9133 }
9134
9135
9136 GtkWidget *alt_menu(gtkwave_mlist_t *mi, int nmenu_items, GtkWidget **wlist, GtkAccelGroup *accel, gboolean is_menubar)
9137 {
9138 int i, j;
9139 struct menu_item_t *mtree = calloc_2(1, sizeof(struct menu_item_t));
9140 struct menu_item_t *n, *n2 = NULL, *n3;
9141 GtkWidget *menubar;
9142
9143 for(i=0;i<nmenu_items;i++)
9144 {
9145 char **parts;
9146 int items;
9147
9148 decompose_path(mi[i].path, &items, &parts);
9149
9150 n = mtree;
9151 for(j=0;j<items;j++)
9152 {
9153 assert(n != NULL); /* scan-build */
9154 if(n->name && (j != (items-1))) /* 2nd comparison is to let separators through */
9155 {
9156 n2 = n;
9157 while(n2)
9158 {
9159 if(!strcmp(n2->name, parts[j])) break;
9160 n2 = n2->next;
9161 }
9162 }
9163 else
9164 {
9165 n2 = NULL;
9166 }
9167
9168
9169 if(!n2)
9170 {
9171 n3 = (j != (items-1)) ? calloc_2(1, sizeof(struct menu_item_t)) : NULL;
9172
9173 assert(n != NULL); /* scan-build */
9174 if(n->name)
9175 {
9176 while(n->next) { n = n->next; }
9177 n->next = calloc_2(1, sizeof(struct menu_item_t));
9178 n = n->next;
9179 }
9180 n->name = strdup_2(parts[j]);
9181 n->child = n3;
9182
9183 n2 = n;
9184 n = n3;
9185 }
9186 else
9187 {
9188 n = n2->child;
9189 }
9190
9191 }
9192
9193 if(n2) /* scan-build */
9194 {
9195 n2->idx = i;
9196 n2->valid = 1;
9197 }
9198
9199 free_decomposed_path(items, parts);
9200 }
9201
9202 menubar = alt_menu_walk(mi, wlist, mtree, is_menubar ? 0 : 1, accel); /* returns a menubar */
9203
9204 return(menubar);
9205 }
9206
9207
9208 GtkWidget *alt_menu_top(GtkWidget *window)
9209 {
9210 gtkwave_mlist_t *mi = menu_items;
9211 int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
9212 GtkWidget *menubar;
9213 GtkAccelGroup *global_accel = gtk_accel_group_new();
9214 int i;
9215 GtkWidget *mw;
9216
9217 menu_wlist = calloc(nmenu_items, sizeof(GtkWidget *)); /* calloc, not calloc_2() */
9218
9219 menubar = alt_menu(mi, nmenu_items, menu_wlist, global_accel, TRUE);
9220
9221 GLOBALS->regexp_string_menu_c_1 = calloc_2(1, 129);
9222
9223 if(GLOBALS->loaded_file_type == MISSING_FILE)
9224 {
9225 for(i=0;i<nmenu_items;i++)
9226 {
9227 switch(i)
9228 {
9229 case WV_MENU_FONVT:
9230 case WV_MENU_WCLOSE:
9231 #if defined(HAVE_LIBTCL)
9232 case WV_MENU_TCLSCR:
9233 #endif
9234 case WV_MENU_FQY:
9235 case WV_MENU_HWH:
9236 #ifdef MAC_INTEGRATION
9237 case WV_MENU_HWM:
9238 #endif
9239 case WV_MENU_HWV:
9240 break;
9241
9242 default:
9243 mw = menu_wlist[i];
9244 if(mw)
9245 {
9246 #ifdef MAC_INTEGRATION
9247 if(menu_items[i].callback)
9248 #endif
9249 {
9250 gtk_widget_set_sensitive(mw, FALSE);
9251 }
9252 }
9253 break;
9254 }
9255 }
9256
9257 #ifdef WAVE_USE_MENU_BLACKOUTS
9258 for(i=0;i<(sizeof(menu_blackouts)/sizeof(char *));i++)
9259 {
9260 mw = menu_wlist[i];
9261 if(mw)
9262 {
9263 gtk_widget_set_sensitive(mw, FALSE);
9264 }
9265 }
9266 #endif
9267 }
9268
9269 if(
9270 (GLOBALS->socket_xid)||
9271 (GLOBALS->partial_vcd))
9272 {
9273 gtk_widget_destroy(menu_wlist[WV_MENU_FONVT]); menu_wlist[WV_MENU_FONVT] = NULL;
9274 }
9275
9276 if(!GLOBALS->partial_vcd)
9277 {
9278 gtk_widget_destroy(menu_wlist[WV_MENU_VZDYN]); menu_wlist[WV_MENU_VZDYN] = NULL;
9279 gtk_widget_destroy(menu_wlist[WV_MENU_VZDYNE]); menu_wlist[WV_MENU_VZDYNE] = NULL;
9280 }
9281
9282 if(GLOBALS->loaded_file_type == DUMPLESS_FILE)
9283 {
9284 gtk_widget_destroy(menu_wlist[WV_MENU_FRW]); menu_wlist[WV_MENU_FRW] = NULL;
9285 }
9286
9287 if(GLOBALS->loaded_file_type != LXT_FILE)
9288 {
9289 gtk_widget_destroy(menu_wlist[WV_MENU_SEP18]); menu_wlist[WV_MENU_SEP18] = NULL;
9290 gtk_widget_destroy(menu_wlist[WV_MENU_LXTCC2Z]); menu_wlist[WV_MENU_LXTCC2Z] = NULL;
9291 }
9292
9293 gtk_window_add_accel_group(GTK_WINDOW(window), global_accel);
9294
9295 #ifdef MAC_INTEGRATION
9296 #if defined(HAVE_LIBTCL)
9297 gtk_widget_hide(menu_wlist[WV_MENU_TCLSEP]);
9298 #endif
9299 gtk_widget_hide(menu_wlist[WV_MENU_FQY]);
9300 #endif
9301
9302 set_menu_toggles();
9303
9304 return(menubar);
9305 }
9306
9307 #ifdef MAC_INTEGRATION
9308 void osx_menu_sensitivity(gboolean tr)
9309 {
9310 GtkWidget *mw;
9311 int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
9312 int i;
9313
9314 for(i=0;i<nmenu_items;i++)
9315 {
9316 mw = menu_wlist[i];
9317 if(mw)
9318 {
9319 if(menu_items[i].callback)
9320 {
9321 gtk_widget_set_sensitive(mw, tr);
9322 }
9323 }
9324 }
9325 }
9326 #endif
9327
9328 #endif
9329
9330
9331 void wave_gtk_grab_add(GtkWidget *w)
9332 {
9333 gtk_grab_add(w);
9334
9335 #ifdef MAC_INTEGRATION
9336 osx_menu_sensitivity(FALSE);
9337 #endif
9338 }
9339
9340 void wave_gtk_grab_remove(GtkWidget *w)
9341 {
9342 gtk_grab_remove(w);
9343
9344 #ifdef MAC_INTEGRATION
9345 if(GLOBALS->loaded_file_type != MISSING_FILE)
9346 {
9347 osx_menu_sensitivity(TRUE);
9348 }
9349 else
9350 {
9351 int i;
9352 GtkWidget *mw;
9353 int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
9354
9355 for(i=0;i<nmenu_items;i++)
9356 {
9357 switch(i)
9358 {
9359 case WV_MENU_FONVT:
9360 case WV_MENU_WCLOSE:
9361 #if defined(HAVE_LIBTCL)
9362 case WV_MENU_TCLSCR:
9363 #endif
9364 case WV_MENU_FQY:
9365 case WV_MENU_HWH:
9366 #ifdef MAC_INTEGRATION
9367 case WV_MENU_HWM:
9368 #endif
9369 case WV_MENU_HWV:
9370 mw = menu_wlist[i];
9371 if(mw)
9372 {
9373 #ifdef MAC_INTEGRATION
9374 if(menu_items[i].callback)
9375 #endif
9376 {
9377 gtk_widget_set_sensitive(mw, TRUE);
9378 }
9379 }
9380 break;
9381
9382 default:
9383 break;
9384 }
9385 }
9386 }
9387 #endif
9388 }
9389