1 /*
2 * Copyright (c) Tony Bybell 2008-2012.
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 "currenttime.h"
13 #include "pixmaps.h"
14 #include "strace.h"
15 #include "debug.h"
16
find_first_highlighted_trace(void)17 static Trptr find_first_highlighted_trace(void)
18 {
19 Trptr t = NULL;
20
21 for(t=GLOBALS->traces.first;t;t=t->t_next)
22 {
23 if ((t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH))||(!(t->flags&TR_HIGHLIGHT))||(!(t->name)))
24 {
25 continue;
26 }
27 else
28 {
29 break;
30 }
31 }
32
33 return(t);
34 }
35
find_next_highlighted_trace(Trptr t)36 static Trptr find_next_highlighted_trace(Trptr t)
37 {
38 if(t)
39 {
40 t = t->t_next;
41 for(;t;t=t->t_next)
42 {
43 if ((t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH))||(!(t->flags&TR_HIGHLIGHT))||(!(t->name)))
44 {
45 continue;
46 }
47 else
48 {
49 break;
50 }
51 }
52 }
53
54 return(t);
55 }
56
57 /************************************************/
58
59 /*
60 * strace backward or forward..this was cut and
61 * pasted from strace.c and special cased to handle
62 * just a single trace. this might be relaxed later.
63 */
edge_search_2(int direction,int is_last_iteration)64 static void edge_search_2(int direction, int is_last_iteration)
65 {
66 struct strace s_tmp;
67 struct strace *s_head, *s;
68 TimeType basetime, maxbase, sttim, fintim;
69 Trptr t = find_first_highlighted_trace();
70 int totaltraces;
71 #ifdef DEBUG_PRINTF
72 int passcount;
73 #endif
74 int whichpass;
75 TimeType middle=0, width;
76
77 if(!t) return;
78 memset(s_head = &s_tmp, 0, sizeof(struct strace));
79 s_head->trace = t;
80 s_head->value = ST_ANY;
81 s = s_head;
82
83 while(t)
84 {
85 t = find_next_highlighted_trace(t);
86 if(t)
87 {
88 s->next = wave_alloca(sizeof(struct strace));
89 memset(s = s->next, 0, sizeof(struct strace));
90 s->trace = t;
91 s->value = ST_ANY;
92 }
93 }
94
95 if(direction==STRACE_BACKWARD) /* backwards */
96 {
97 if(GLOBALS->tims.marker<0)
98 {
99 basetime=MAX_HISTENT_TIME;
100 }
101 else
102 {
103 basetime=GLOBALS->tims.marker;
104 }
105 }
106 else /* go forwards */
107 {
108 if(GLOBALS->tims.marker<0)
109 {
110 basetime=GLOBALS->tims.first;
111 }
112 else
113 {
114 basetime=GLOBALS->tims.marker;
115 }
116 }
117
118 sttim=GLOBALS->tims.first;
119 fintim=GLOBALS->tims.last;
120
121 for(whichpass=0;;whichpass++)
122 {
123
124 if(direction==STRACE_BACKWARD) /* backwards */
125 {
126 maxbase=-1;
127 s=s_head;
128 while(s)
129 {
130 t=s->trace;
131 GLOBALS->shift_timebase=t->shift;
132 if(!(t->vector))
133 {
134 hptr h;
135 hptr *hp;
136 UTimeType utt;
137 TimeType tt;
138
139 /* h= */ bsearch_node(t->n.nd, basetime - t->shift); /* scan-build */
140 hp=GLOBALS->max_compare_index;
141 if((hp==&(t->n.nd->harray[1]))||(hp==&(t->n.nd->harray[0]))) return;
142 if(basetime == ((*hp)->time+GLOBALS->shift_timebase)) hp--;
143 h=*hp;
144 s->his.h=h;
145 utt=strace_adjust(h->time,GLOBALS->shift_timebase); tt=utt;
146 if(tt > maxbase) maxbase=tt;
147 }
148 else
149 {
150 vptr v;
151 vptr *vp;
152 UTimeType utt;
153 TimeType tt;
154
155 /* v= */ bsearch_vector(t->n.vec, basetime - t->shift); /* scan-build */
156 vp=GLOBALS->vmax_compare_index;
157 if((vp==&(t->n.vec->vectors[1]))||(vp==&(t->n.vec->vectors[0]))) return;
158 if(basetime == ((*vp)->time+GLOBALS->shift_timebase)) vp--;
159 v=*vp;
160 s->his.v=v;
161 utt=strace_adjust(v->time,GLOBALS->shift_timebase); tt=utt;
162 if(tt > maxbase) maxbase=tt;
163 }
164
165 s=s->next;
166 }
167 }
168 else /* go forward */
169 {
170 maxbase=MAX_HISTENT_TIME;
171 s=s_head;
172 while(s)
173 {
174 t=s->trace;
175 GLOBALS->shift_timebase=t->shift;
176 if(!(t->vector))
177 {
178 hptr h;
179 UTimeType utt;
180 TimeType tt;
181
182 h=bsearch_node(t->n.nd, basetime - t->shift);
183 while(h->next && h->time==h->next->time) h=h->next;
184 if((whichpass)||(GLOBALS->tims.marker>=0)) h=h->next;
185 if(!h) return;
186 s->his.h=h;
187 utt=strace_adjust(h->time,GLOBALS->shift_timebase); tt=utt;
188 if(tt < maxbase) maxbase=tt;
189 }
190 else
191 {
192 vptr v;
193 UTimeType utt;
194 TimeType tt;
195
196 v=bsearch_vector(t->n.vec, basetime - t->shift);
197 while(v->next && v->time==v->next->time) v=v->next;
198 if((whichpass)||(GLOBALS->tims.marker>=0)) v=v->next;
199 if(!v) return;
200 s->his.v=v;
201 utt=strace_adjust(v->time,GLOBALS->shift_timebase); tt=utt;
202 if(tt < maxbase) maxbase=tt;
203 }
204
205 s=s->next;
206 }
207 }
208
209 s=s_head;
210 totaltraces=0; /* increment when not don't care */
211 while(s)
212 {
213 /* commented out, maybe will have possible future expansion later,
214 * this was cut and pasted from strace.c */
215 #if 0
216 char str[2];
217 #endif
218 t=s->trace;
219 s->search_result=0; /* explicitly must set this */
220 GLOBALS->shift_timebase=t->shift;
221
222 if((!t->vector)&&(!(t->n.nd->extvals)))
223 {
224 if(strace_adjust(s->his.h->time,GLOBALS->shift_timebase)!=maxbase)
225 {
226 s->his.h=bsearch_node(t->n.nd, maxbase - t->shift);
227 while(s->his.h->next && s->his.h->time==s->his.h->next->time) s->his.h=s->his.h->next;
228 }
229 /* commented out, maybe will have possible future expansion later,
230 * this was cut and pasted from strace.c */
231 #if 0
232 if(t->flags&TR_INVERT)
233 {
234 str[0]=AN_STR_INV[s->his.h->v.h_val];
235 }
236 else
237 {
238 str[0]=AN_STR[s->his.h->v.h_val];
239 }
240 str[1]=0x00;
241 #endif
242
243 switch(s->value)
244 {
245 case ST_ANY:
246 totaltraces++;
247 s->search_result=1;
248 break;
249
250 /* commented out, maybe will have possible future expansion later,
251 * this was cut and pasted from strace.c */
252 #if 0
253 case ST_DC:
254 break;
255
256 case ST_HIGH:
257 totaltraces++;
258 if((str[0]=='1')||(str[0]=='H')) s->search_result=1;
259 break;
260
261 case ST_RISE:
262 if((str[0]=='1')||(str[0]=='H')) s->search_result=1;
263 totaltraces++;
264 break;
265
266 case ST_LOW:
267 totaltraces++;
268 if((str[0]=='0')||(str[0]=='L')) s->search_result=1;
269 break;
270
271 case ST_FALL:
272 totaltraces++;
273 if((str[0]=='0')||(str[0]=='L')) s->search_result=1;
274 break;
275
276 case ST_MID:
277 totaltraces++;
278 if(str[0]=='Z')
279 s->search_result=1;
280 break;
281
282 case ST_X:
283 totaltraces++;
284 if(str[0]=='X') s->search_result=1;
285 break;
286
287 case ST_STRING:
288 totaltraces++;
289 if(s->string)
290 if(strstr_i(s->string,str)) s->search_result=1;
291 break;
292 #endif
293
294 default:
295 fprintf(stderr, "Internal error: st_type of %d\n",s->value);
296 exit(255);
297 }
298
299
300 }
301 else
302 {
303 char *chval, *chval2;
304 char ch;
305
306 if(t->vector)
307 {
308 if(strace_adjust(s->his.v->time,GLOBALS->shift_timebase)!=maxbase)
309 {
310 s->his.v=bsearch_vector(t->n.vec, maxbase - t->shift);
311 while(s->his.v->next && s->his.v->time==s->his.v->next->time) s->his.v=s->his.v->next;
312 }
313 chval=convert_ascii(t,s->his.v);
314 }
315 else
316 {
317 if(strace_adjust(s->his.h->time,GLOBALS->shift_timebase)!=maxbase)
318 {
319 s->his.h=bsearch_node(t->n.nd, maxbase - t->shift);
320 while(s->his.h->next && s->his.h->time==s->his.h->next->time) s->his.h=s->his.h->next;
321 }
322 if(s->his.h->flags&HIST_REAL)
323 {
324 if(!(s->his.h->flags&HIST_STRING))
325 {
326 #ifdef WAVE_HAS_H_DOUBLE
327 chval=convert_ascii_real(t, &s->his.h->v.h_double);
328 #else
329 chval=convert_ascii_real(t, (double *)s->his.h->v.h_vector);
330 #endif
331 }
332 else
333 {
334 chval=convert_ascii_string((char *)s->his.h->v.h_vector);
335 chval2=chval;
336 while((ch=*chval2)) /* toupper() the string */
337 {
338 if((ch>='a')&&(ch<='z')) { *chval2= ch-('a'-'A'); }
339 chval2++;
340 }
341 }
342 }
343 else
344 {
345 chval=convert_ascii_vec(t,s->his.h->v.h_vector);
346 }
347 }
348
349 switch(s->value)
350 {
351 case ST_ANY:
352 totaltraces++;
353 s->search_result=1;
354 break;
355
356 /* commented out, maybe will have possible future expansion later,
357 * this was cut and pasted from strace.c */
358 #if 0
359 case ST_DC:
360 break;
361
362 case ST_RISE:
363 case ST_FALL:
364 totaltraces++;
365 break;
366
367 case ST_HIGH:
368 totaltraces++;
369 if((chval2=chval))
370 while((ch=*(chval2++)))
371 {
372 if(((ch>='1')&&(ch<='9'))||(ch=='h')||(ch=='H')||((ch>='A')&&(ch<='F')))
373 {
374 s->search_result=1;
375 break;
376 }
377 }
378 break;
379
380 case ST_LOW:
381 totaltraces++;
382 if((chval2=chval))
383 {
384 s->search_result=1;
385 while((ch=*(chval2++)))
386 {
387 if((ch!='0')&&(ch!='l')&&(ch!='L'))
388 {
389 s->search_result=0;
390 break;
391 }
392 }
393 }
394 break;
395
396 case ST_MID:
397 totaltraces++;
398 if((chval2=chval))
399 {
400 s->search_result=1;
401 while((ch=*(chval2++)))
402 {
403 if((ch!='z')&&(ch!='Z'))
404 {
405 s->search_result=0;
406 break;
407 }
408 }
409 }
410 break;
411
412 case ST_X:
413 totaltraces++;
414 if((chval2=chval))
415 {
416 s->search_result=1;
417 while((ch=*(chval2++)))
418 {
419 if((ch!='X')&&(ch!='W')&&(ch!='x')&&(ch!='w'))
420 {
421 s->search_result=0;
422 break;
423 }
424 }
425 }
426 break;
427
428 case ST_STRING:
429 totaltraces++;
430 if(s->string)
431 if(strstr_i(chval, s->string)) s->search_result=1;
432 break;
433 #endif
434
435 default:
436 fprintf(stderr, "Internal error: st_type of %d\n",s->value);
437 exit(255);
438 }
439
440 free_2(chval);
441 }
442 s=s->next;
443 }
444
445 if((maxbase<sttim)||(maxbase>fintim)) return;
446
447 #ifdef DEBUG_PRINTF
448 DEBUG(printf("Maxbase: "TTFormat", total traces: %d\n",maxbase, totaltraces));
449 s=s_head;
450 passcount=0;
451 while(s)
452 {
453 DEBUG(printf("\tPass: %d, Name: %s\n",s->search_result, s->trace->name));
454 if(s->search_result) passcount++;
455 s=s->next;
456 }
457 #endif
458
459 if(totaltraces)
460 {
461 break;
462 }
463
464 basetime=maxbase;
465 }
466
467
468 GLOBALS->tims.marker=maxbase;
469 if(is_last_iteration)
470 {
471 update_markertime(GLOBALS->tims.marker);
472
473 width=(TimeType)(((gdouble)GLOBALS->wavewidth)*GLOBALS->nspx);
474 if((GLOBALS->tims.marker<GLOBALS->tims.start)||(GLOBALS->tims.marker>=GLOBALS->tims.start+width))
475 {
476 if((GLOBALS->tims.marker<0)||(GLOBALS->tims.marker<GLOBALS->tims.first)||(GLOBALS->tims.marker>GLOBALS->tims.last))
477 {
478 if(GLOBALS->tims.end>GLOBALS->tims.last) GLOBALS->tims.end=GLOBALS->tims.last;
479 middle=(GLOBALS->tims.start/2)+(GLOBALS->tims.end/2);
480 if((GLOBALS->tims.start&1)&&(GLOBALS->tims.end&1)) middle++;
481 }
482 else
483 {
484 middle=GLOBALS->tims.marker;
485 }
486
487 GLOBALS->tims.start=time_trunc(middle-(width/2));
488 if(GLOBALS->tims.start+width>GLOBALS->tims.last) GLOBALS->tims.start=GLOBALS->tims.last-width;
489 if(GLOBALS->tims.start<GLOBALS->tims.first) GLOBALS->tims.start=GLOBALS->tims.first;
490 GTK_ADJUSTMENT(GLOBALS->wave_hslider)->value=GLOBALS->tims.timecache=GLOBALS->tims.start;
491 }
492
493 MaxSignalLength();
494 signalarea_configure_event(GLOBALS->signalarea, NULL);
495 wavearea_configure_event(GLOBALS->wavearea, NULL);
496 }
497 }
498
edge_search(int direction)499 void edge_search(int direction)
500 {
501 int i;
502 int i_high_cnt = ((GLOBALS->strace_repeat_count > 0) ? GLOBALS->strace_repeat_count : 1) - 1;
503
504 for(i=0;i<=i_high_cnt;i++)
505 {
506 edge_search_2(direction, (i == i_high_cnt));
507 }
508 }
509
510 /************************************************/
511
512 void
service_left_edge(GtkWidget * text,gpointer data)513 service_left_edge(GtkWidget *text, gpointer data)
514 {
515 (void)text;
516 (void)data;
517
518 if(GLOBALS->helpbox_is_active)
519 {
520 help_text_bold("\n\nFind Previous Edge");
521 help_text(
522 " moves the marker to the closest transition to the left of the marker"
523 " of the first highlighted trace. If the marker is not nailed down, it starts from max time."
524 );
525 return;
526 }
527
528 edge_search(STRACE_BACKWARD);
529
530 DEBUG(printf("Edge Left\n"));
531 }
532
533 void
service_right_edge(GtkWidget * text,gpointer data)534 service_right_edge(GtkWidget *text, gpointer data)
535 {
536 (void)text;
537 (void)data;
538
539 if(GLOBALS->helpbox_is_active)
540 {
541 help_text_bold("\n\nFind Next Edge");
542 help_text(
543 " moves the marker to the closest transition to the right of the marker"
544 " of the first highlighted trace. If the marker is not nailed down, it starts from min time."
545 );
546 return;
547 }
548
549 edge_search(STRACE_FORWARD);
550
551 DEBUG(printf("Edge Right\n"));
552 }
553
554 /* Create shift buttons */
555 GtkWidget *
create_edge_buttons(void)556 create_edge_buttons (void)
557 {
558 GtkWidget *table;
559 GtkWidget *table2;
560 GtkWidget *frame;
561 GtkWidget *main_vbox;
562 GtkWidget *b1;
563 GtkWidget *b2;
564 GtkWidget *pixmapwid1, *pixmapwid2;
565
566 GtkTooltips *tooltips;
567
568 tooltips=gtk_tooltips_new_2();
569 gtk_tooltips_set_delay_2(tooltips,1500);
570
571 pixmapwid1=gtk_pixmap_new(GLOBALS->larrow_pixmap, GLOBALS->larrow_mask);
572 gtk_widget_show(pixmapwid1);
573 pixmapwid2=gtk_pixmap_new(GLOBALS->rarrow_pixmap, GLOBALS->rarrow_mask);
574 gtk_widget_show(pixmapwid2);
575
576 /* Create a table to hold the text widget and scrollbars */
577 table = gtk_table_new (1, 1, FALSE);
578
579 main_vbox = gtk_vbox_new (FALSE, 1);
580 gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
581 gtk_container_add (GTK_CONTAINER (table), main_vbox);
582
583 frame = gtk_frame_new ("Edge ");
584 gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
585
586 gtk_widget_show (frame);
587 gtk_widget_show (main_vbox);
588
589 table2 = gtk_table_new (2, 1, FALSE);
590
591 b1 = gtk_button_new();
592 gtk_container_add(GTK_CONTAINER(b1), pixmapwid1);
593 gtk_table_attach (GTK_TABLE (table2), b1, 0, 1, 0, 1,
594 GTK_FILL | GTK_EXPAND,
595 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
596 gtk_signal_connect_object (GTK_OBJECT (b1), "clicked", GTK_SIGNAL_FUNC(service_left_edge), GTK_OBJECT (table2));
597 gtk_tooltips_set_tip_2(tooltips, b1, "Find next transition of highlighted trace scanning left", NULL);
598 gtk_widget_show(b1);
599
600 b2 = gtk_button_new();
601 gtk_container_add(GTK_CONTAINER(b2), pixmapwid2);
602 gtk_table_attach (GTK_TABLE (table2), b2, 0, 1, 1, 2,
603 GTK_FILL | GTK_EXPAND,
604 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 1, 1);
605 gtk_signal_connect_object (GTK_OBJECT (b2), "clicked", GTK_SIGNAL_FUNC(service_right_edge), GTK_OBJECT (table2));
606 gtk_tooltips_set_tip_2(tooltips, b2, "Find next transition of highlighted trace scanning right", NULL);
607 gtk_widget_show(b2);
608
609 gtk_container_add (GTK_CONTAINER (frame), table2);
610 gtk_widget_show(table2);
611 return(table);
612 }
613
614