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