1 /*
2 * Copyright (c) Tony Bybell 1999-2016.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 */
9
10 #include "globals.h"
11 #include <config.h>
12 #include <gtk/gtk.h>
13 #include <string.h>
14 #include "gtk12compat.h"
15 #include "debug.h"
16 #include "analyzer.h"
17 #include "currenttime.h"
18
gtkwave_strrev(char * p)19 static void gtkwave_strrev(char *p)
20 {
21 char *q = p;
22 while(q && *q) ++q;
23 for(--q; p < q; ++p, --q)
24 *p = *p ^ *q,
25 *q = *p ^ *q,
26 *p = *p ^ *q;
27 }
28
29
make_bijective_marker_id_string(char * buf,unsigned int value)30 char *make_bijective_marker_id_string(char *buf, unsigned int value)
31 {
32 char *pnt = buf;
33
34 value++; /* bijective values start at one */
35 while (value)
36 {
37 value--;
38 *(pnt++) = (char)('A' + value % ('Z'-'A'+1));
39 value = value / ('Z'-'A'+1);
40 }
41
42 *pnt = 0;
43 gtkwave_strrev(buf);
44 return(buf);
45 }
46
47
bijective_marker_id_string_hash(const char * so)48 unsigned int bijective_marker_id_string_hash(const char *so)
49 {
50 unsigned int val=0;
51 int i;
52 int len = strlen(so);
53 char sn[16];
54 char *s = sn;
55
56 strcpy(sn, so);
57 gtkwave_strrev(sn);
58
59 s += len;
60 for(i=0;i<len;i++)
61 {
62 char c = toupper(*(--s));
63 if((c < 'A') || (c > 'Z')) break;
64 val *= ('Z'-'A'+1);
65 val += ((unsigned char)c) - ('A' - 1);
66 }
67
68 val--; /* bijective values start at one so decrement */
69 return(val);
70 }
71
72
bijective_marker_id_string_len(const char * s)73 unsigned int bijective_marker_id_string_len(const char *s)
74 {
75 int len = 0;
76
77 while(*s)
78 {
79 char c = toupper(*s);
80 if((c >= 'A') && (c <= 'Z'))
81 {
82 len++;
83 s++;
84 continue;
85 }
86 else
87 {
88 break;
89 }
90 }
91
92 return(len);
93 }
94
95
str_change_callback(GtkWidget * entry,gpointer which)96 static void str_change_callback(GtkWidget *entry, gpointer which)
97 {
98 G_CONST_RETURN gchar *entry_text;
99 int i;
100 uint32_t hashmask = WAVE_NUM_NAMED_MARKERS;
101 hashmask |= hashmask >> 1;
102 hashmask |= hashmask >> 2;
103 hashmask |= hashmask >> 4;
104 hashmask |= hashmask >> 8;
105 hashmask |= hashmask >> 16;
106
107 i = ((int) (((intptr_t) which) & hashmask)) % WAVE_NUM_NAMED_MARKERS;
108 GLOBALS->dirty_markerbox_c_1 = 1;
109
110 entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
111 if(entry_text && strlen(entry_text))
112 {
113 if(GLOBALS->shadow_marker_names[i])
114 {
115 free_2(GLOBALS->shadow_marker_names[i]);
116 }
117
118 GLOBALS->shadow_marker_names[i] = strdup_2(entry_text);
119 }
120 else
121 {
122 if(GLOBALS->shadow_marker_names[i])
123 {
124 free_2(GLOBALS->shadow_marker_names[i]);
125 GLOBALS->shadow_marker_names[i] = NULL;
126 }
127 }
128 }
129
str_enter_callback(GtkWidget * entry,gpointer which)130 static void str_enter_callback(GtkWidget *entry, gpointer which)
131 {
132 G_CONST_RETURN gchar *entry_text;
133 int i;
134 uint32_t hashmask = WAVE_NUM_NAMED_MARKERS;
135 hashmask |= hashmask >> 1;
136 hashmask |= hashmask >> 2;
137 hashmask |= hashmask >> 4;
138 hashmask |= hashmask >> 8;
139 hashmask |= hashmask >> 16;
140
141 i = ((int) (((intptr_t) which) & hashmask)) % WAVE_NUM_NAMED_MARKERS;
142 GLOBALS->dirty_markerbox_c_1 = 1;
143
144 entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
145 if(entry_text && strlen(entry_text))
146 {
147 if(GLOBALS->shadow_marker_names[i])
148 {
149 free_2(GLOBALS->shadow_marker_names[i]);
150 }
151
152 GLOBALS->shadow_marker_names[i] = strdup_2(entry_text);
153 gtk_entry_select_region (GTK_ENTRY (entry),
154 0, GTK_ENTRY(entry)->text_length);
155
156 }
157 else
158 {
159 if(GLOBALS->shadow_marker_names[i])
160 {
161 free_2(GLOBALS->shadow_marker_names[i]);
162 GLOBALS->shadow_marker_names[i] = NULL;
163 }
164 }
165 }
166
167
change_callback(GtkWidget * widget,gpointer which)168 static void change_callback(GtkWidget *widget, gpointer which)
169 {
170 (void)widget;
171
172 GtkWidget *entry;
173 TimeType temp;
174 G_CONST_RETURN gchar *entry_text;
175 char buf[49];
176 int i;
177 int ent_idx;
178 uint32_t hashmask = WAVE_NUM_NAMED_MARKERS;
179 hashmask |= hashmask >> 1;
180 hashmask |= hashmask >> 2;
181 hashmask |= hashmask >> 4;
182 hashmask |= hashmask >> 8;
183 hashmask |= hashmask >> 16;
184
185 ent_idx = ((int) (((intptr_t) which) & hashmask)) % WAVE_NUM_NAMED_MARKERS;
186
187 entry=GLOBALS->entries_markerbox_c_1[ent_idx];
188
189 entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
190 entry_text = entry_text ? entry_text : "";
191 if(!strlen(entry_text)) goto failure;
192 if(entry_text[0] != '-')
193 {
194 if(!isdigit((int)(unsigned char)entry_text[0])) goto failure;
195 }
196
197 temp=unformat_time(entry_text, GLOBALS->time_dimension);
198 temp -= GLOBALS->global_time_offset;
199 if((temp<GLOBALS->tims.start)||(temp>GLOBALS->tims.last)) goto failure;
200
201 for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
202 {
203 if(temp==GLOBALS->shadow_markers_markerbox_c_1[i])
204 {
205 if(i!=ent_idx)
206 {
207 GLOBALS->shadow_markers_markerbox_c_1[ent_idx] = -1;
208 }
209 goto failure;
210 }
211 }
212
213 reformat_time_simple(buf, temp + GLOBALS->global_time_offset, GLOBALS->time_dimension);
214
215 GLOBALS->shadow_markers_markerbox_c_1[ent_idx]=temp;
216 GLOBALS->dirty_markerbox_c_1=1;
217
218 failure:
219 return;
220 }
221
enter_callback(GtkWidget * widget,gpointer which)222 static void enter_callback(GtkWidget *widget, gpointer which)
223 {
224 (void)widget;
225
226 GtkWidget *entry;
227 /* TimeType *modify; */ /* scan-build */
228 TimeType temp;
229 G_CONST_RETURN gchar *entry_text;
230 char buf[49];
231 int i;
232 int ent_idx;
233 uint32_t hashmask = WAVE_NUM_NAMED_MARKERS;
234 hashmask |= hashmask >> 1;
235 hashmask |= hashmask >> 2;
236 hashmask |= hashmask >> 4;
237 hashmask |= hashmask >> 8;
238 hashmask |= hashmask >> 16;
239
240 ent_idx = ((int) (((intptr_t) which) & hashmask)) % WAVE_NUM_NAMED_MARKERS;
241
242 entry=GLOBALS->entries_markerbox_c_1[ent_idx];
243
244 entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
245 entry_text = entry_text ? entry_text : "";
246 if(!strlen(entry_text)) goto failure;
247
248 temp=unformat_time(entry_text, GLOBALS->time_dimension);
249 temp -= GLOBALS->global_time_offset;
250 if((temp<GLOBALS->tims.start)||(temp>GLOBALS->tims.last)) goto failure;
251
252 for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
253 {
254 if(temp==GLOBALS->shadow_markers_markerbox_c_1[i]) goto failure;
255 }
256
257 reformat_time_simple(buf, temp + GLOBALS->global_time_offset, GLOBALS->time_dimension);
258 gtk_entry_set_text (GTK_ENTRY (entry), buf);
259
260 GLOBALS->shadow_markers_markerbox_c_1[ent_idx]=temp;
261 GLOBALS->dirty_markerbox_c_1=1;
262 gtk_entry_select_region (GTK_ENTRY (entry),
263 0, GTK_ENTRY(entry)->text_length);
264 return;
265
266 failure:
267 /* modify=(TimeType *)which; */ /* scan-build */
268 if(GLOBALS->shadow_markers_markerbox_c_1[ent_idx]==-1)
269 {
270 sprintf(buf,"<None>");
271 }
272 else
273 {
274 reformat_time_simple(buf, GLOBALS->shadow_markers_markerbox_c_1[ent_idx] + GLOBALS->global_time_offset, GLOBALS->time_dimension);
275 }
276 gtk_entry_set_text (GTK_ENTRY (entry), buf);
277 }
278
ok_callback(GtkWidget * widget,GtkWidget * nothing)279 static void ok_callback(GtkWidget *widget, GtkWidget *nothing)
280 {
281 (void)widget;
282 (void)nothing;
283
284 if(GLOBALS->dirty_markerbox_c_1)
285 {
286 int i;
287 for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
288 {
289 GLOBALS->named_markers[i]=GLOBALS->shadow_markers_markerbox_c_1[i];
290 if(GLOBALS->marker_names[i]) free_2(GLOBALS->marker_names[i]);
291 GLOBALS->marker_names[i] = GLOBALS->shadow_marker_names[i];
292 GLOBALS->shadow_marker_names[i] = NULL;
293 }
294 MaxSignalLength();
295 signalarea_configure_event(GLOBALS->signalarea, NULL);
296 wavearea_configure_event(GLOBALS->wavearea, NULL);
297 }
298
299 wave_gtk_grab_remove(GLOBALS->window_markerbox_c_4);
300 gtk_widget_destroy(GLOBALS->window_markerbox_c_4);
301 GLOBALS->window_markerbox_c_4 = NULL;
302
303 GLOBALS->cleanup_markerbox_c_4();
304 }
305
destroy_callback(GtkWidget * widget,GtkWidget * nothing)306 static void destroy_callback(GtkWidget *widget, GtkWidget *nothing)
307 {
308 (void)widget;
309 (void)nothing;
310
311 int i;
312 for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
313 {
314 if(GLOBALS->marker_names[i]) free_2(GLOBALS->marker_names[i]);
315 GLOBALS->marker_names[i] = GLOBALS->shadow_marker_names[i];
316 GLOBALS->shadow_marker_names[i] = NULL;
317 }
318
319 wave_gtk_grab_remove(GLOBALS->window_markerbox_c_4);
320 gtk_widget_destroy(GLOBALS->window_markerbox_c_4);
321 GLOBALS->window_markerbox_c_4 = NULL;
322 }
323
markerbox(char * title,GtkSignalFunc func)324 void markerbox(char *title, GtkSignalFunc func)
325 {
326 GtkWidget *entry;
327 GtkWidget *vbox, *hbox, *vbox_g, *label;
328 GtkWidget *button1, *button2, *scrolled_win, *frame, *separator;
329 GtkWidget *table;
330 char labtitle[16];
331 int i;
332
333 GLOBALS->cleanup_markerbox_c_4=func;
334 GLOBALS->dirty_markerbox_c_1=0;
335
336 for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
337 {
338 GLOBALS->shadow_markers_markerbox_c_1[i] = GLOBALS->named_markers[i];
339 GLOBALS->shadow_marker_names[i] = strdup_2(GLOBALS->marker_names[i]);
340 }
341
342 /* fix problem where ungrab doesn't occur if button pressed + simultaneous accelerator key occurs */
343 if(GLOBALS->in_button_press_wavewindow_c_1) { gdk_pointer_ungrab(GDK_CURRENT_TIME); }
344
345 /* create a new modal window */
346 GLOBALS->window_markerbox_c_4 = gtk_window_new(GLOBALS->disable_window_manager ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
347 install_focus_cb(GLOBALS->window_markerbox_c_4, ((char *)&GLOBALS->window_markerbox_c_4) - ((char *)GLOBALS));
348
349 gtk_window_set_title(GTK_WINDOW (GLOBALS->window_markerbox_c_4), title);
350 gtkwave_signal_connect(GTK_OBJECT (GLOBALS->window_markerbox_c_4), "delete_event",(GtkSignalFunc) destroy_callback, NULL);
351
352 vbox = gtk_vbox_new (FALSE, 0);
353 gtk_widget_show (vbox);
354
355 vbox_g = gtk_vbox_new (FALSE, 0);
356 gtk_widget_show (vbox_g);
357
358 table = gtk_table_new (256, 1, FALSE);
359 gtk_widget_show (table);
360
361 gtk_table_attach (GTK_TABLE (table), vbox, 0, 1, 0, 255,
362 GTK_FILL | GTK_EXPAND,
363 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
364
365 frame = gtk_frame_new (NULL);
366 gtk_container_border_width (GTK_CONTAINER (frame), 3);
367 gtk_widget_show(frame);
368
369 scrolled_win = gtk_scrolled_window_new (NULL, NULL);
370 gtk_widget_set_usize( GTK_WIDGET (scrolled_win), 400, 300);
371 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
372 GTK_POLICY_AUTOMATIC,
373 GTK_POLICY_AUTOMATIC);
374 gtk_widget_show(scrolled_win);
375 gtk_container_add (GTK_CONTAINER (frame), scrolled_win);
376 gtk_container_add (GTK_CONTAINER (vbox), frame);
377
378 for(i=0;i<WAVE_NUM_NAMED_MARKERS;i++)
379 {
380 char buf[49];
381
382 if(i)
383 {
384 separator = gtk_hseparator_new ();
385 gtk_widget_show (separator);
386 gtk_box_pack_start (GTK_BOX (vbox_g), separator, TRUE, TRUE, 0);
387 }
388
389
390 make_bijective_marker_id_string(labtitle, i);
391 label=gtk_label_new(labtitle);
392 gtk_widget_show (label);
393 gtk_box_pack_start (GTK_BOX (vbox_g), label, TRUE, TRUE, 0);
394
395 hbox = gtk_hbox_new(FALSE, 0);
396 gtk_widget_show (hbox);
397
398 GLOBALS->entries_markerbox_c_1[i]=entry = gtk_entry_new_with_max_length (48);
399 gtkwave_signal_connect(GTK_OBJECT(entry), "activate", GTK_SIGNAL_FUNC(enter_callback), (void *)((intptr_t) i));
400 gtkwave_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(change_callback), (void *)((intptr_t) i));
401 if(GLOBALS->shadow_markers_markerbox_c_1[i]==-1)
402 {
403 sprintf(buf,"<None>");
404 }
405 else
406 {
407 reformat_time_simple(buf, GLOBALS->shadow_markers_markerbox_c_1[i] + GLOBALS->global_time_offset, GLOBALS->time_dimension);
408 }
409
410 gtk_entry_set_text (GTK_ENTRY (entry), buf);
411 gtk_widget_show (entry);
412 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
413
414 /* string part */
415 entry = gtk_entry_new_with_max_length (48);
416 if(GLOBALS->shadow_marker_names[i]) gtk_entry_set_text (GTK_ENTRY (entry), GLOBALS->shadow_marker_names[i]);
417 gtk_widget_show (entry);
418 gtkwave_signal_connect(GTK_OBJECT(entry), "activate", GTK_SIGNAL_FUNC(str_enter_callback), (void *)((intptr_t) i));
419 gtkwave_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(str_change_callback), (void *)((intptr_t) i));
420
421 gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
422
423
424 gtk_box_pack_start (GTK_BOX (vbox_g), hbox, TRUE, TRUE, 0);
425 }
426
427 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_win), vbox_g);
428
429 hbox = gtk_hbox_new (FALSE, 1);
430 gtk_widget_show (hbox);
431
432 gtk_table_attach (GTK_TABLE (table), hbox, 0, 1, 255, 256,
433 GTK_FILL | GTK_EXPAND,
434 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
435
436 button1 = gtk_button_new_with_label ("OK");
437 gtk_widget_set_usize(button1, 100, -1);
438 gtkwave_signal_connect(GTK_OBJECT (button1), "clicked", GTK_SIGNAL_FUNC(ok_callback), NULL);
439 gtk_widget_show (button1);
440 gtk_container_add (GTK_CONTAINER (hbox), button1);
441 GTK_WIDGET_SET_FLAGS (button1, GTK_CAN_DEFAULT);
442 gtkwave_signal_connect_object (GTK_OBJECT (button1), "realize", (GtkSignalFunc) gtk_widget_grab_default, GTK_OBJECT (button1));
443
444
445 button2 = gtk_button_new_with_label ("Cancel");
446 gtk_widget_set_usize(button2, 100, -1);
447 gtkwave_signal_connect(GTK_OBJECT (button2), "clicked", GTK_SIGNAL_FUNC(destroy_callback), NULL);
448 GTK_WIDGET_SET_FLAGS (button2, GTK_CAN_DEFAULT);
449 gtk_widget_show (button2);
450 gtk_container_add (GTK_CONTAINER (hbox), button2);
451
452 gtk_container_add (GTK_CONTAINER (GLOBALS->window_markerbox_c_4), table); /* need this table to keep ok/cancel buttons from stretching! */
453 gtk_widget_show(GLOBALS->window_markerbox_c_4);
454 wave_gtk_grab_add(GLOBALS->window_markerbox_c_4);
455 }
456
457