1 /******************************************************************************
2  * DESCRIPTION: Dinotrace source: value-at-a-time decoding
3  *
4  * This file is part of Dinotrace.
5  *
6  * Author: Wilson Snyder <wsnyder@wsnyder.org>
7  *
8  * Code available from: http://www.veripool.org/dinotrace
9  *
10  ******************************************************************************
11  *
12  * Some of the code in this file was originally developed for Digital
13  * Semiconductor, a division of Digital Equipment Corporation.  They
14  * gratefuly have agreed to share it, and thus the base version has been
15  * released to the public with the following provisions:
16  *
17  *
18  * This software is provided 'AS IS'.
19  *
20  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THE INFORMATION
21  * (INCLUDING ANY SOFTWARE) PROVIDED, INCLUDING ALL IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE, AND
23  * NON-INFRINGEMENT. DIGITAL NEITHER WARRANTS NOR REPRESENTS THAT THE USE
24  * OF ANY SOURCE, OR ANY DERIVATIVE WORK THEREOF, WILL BE UNINTERRUPTED OR
25  * ERROR FREE.  In no event shall DIGITAL be liable for any damages
26  * whatsoever, and in particular DIGITAL shall not be liable for special,
27  * indirect, consequential, or incidental damages, or damages for lost
28  * profits, loss of revenue, or loss of use, arising out of or related to
29  * any use of this software or the information contained in it, whether
30  * such damages arise in contract, tort, negligence, under statute, in
31  * equity, at law or otherwise. This Software is made available solely for
32  * use by end users for information and non-commercial or personal use
33  * only.  Any reproduction for sale of this Software is expressly
34  * prohibited. Any rights not expressly granted herein are reserved.
35  *
36  ******************************************************************************
37  *
38  * Changes made over the basic version are covered by the GNU public licence.
39  *
40  * Dinotrace is free software; you can redistribute it and/or modify
41  * it under the terms of the GNU General Public License as published by
42  * the Free Software Foundation; either version 3, or (at your option)
43  * any later version.
44  *
45  * Dinotrace is distributed in the hope that it will be useful,
46  * but WITHOUT ANY WARRANTY; without even the implied warranty of
47  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
48  * GNU General Public License for more details.
49  *
50  * You should have received a copy of the GNU General Public License
51  * along with Dinotrace; see the file COPYING.  If not, write to
52  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
53  * Boston, MA 02111-1307, USA.
54  *
55  *****************************************************************************/
56 
57 #include "dinotrace.h"
58 
59 #include <Xm/Form.h>
60 #include <Xm/PushB.h>
61 #include <Xm/PushBG.h>
62 #include <Xm/ToggleB.h>
63 #include <Xm/SelectioB.h>
64 #include <Xm/Text.h>
65 #include <Xm/BulletinB.h>
66 #include <Xm/RowColumn.h>
67 #include <Xm/RowColumnP.h>
68 #include <Xm/Label.h>
69 #include <Xm/LabelP.h>
70 #include <Xm/MenuShellP.h>
71 #include <Xm/GrabShell.h>
72 
73 #include "functions.h"
74 
75 char *val_state_name[] = { "STATE_0", "STATE_1", "STATE_U", "STATE_Z",
76 			   "STATE_B32", "STATE_F32", "STATE_B128", "STATE_F128"};
77 
78 /****************************** UTILITIES ******************************/
79 
val_bit(const Value_t * value_ptr,int bit)80 static uint_t val_bit (
81     const Value_t *value_ptr,
82     int bit)
83     /* Return bit value, understanding 4-state, may be 0/1/U/Z */
84 {
85     int bitpos = bit & 0x1f;
86     if (bit<0) return(0);
87     switch (value_ptr->siglw.stbits.state) {
88     case STATE_0:
89 	return (0);
90     case STATE_1:
91 	return (bit==0 ? 1:0);
92     case STATE_Z:
93 	return (3);
94     case STATE_B32:
95 	if (bit<32)  return (    (value_ptr->number[0] >>bitpos) & 1);
96 	return (0);
97     case STATE_F32:
98 	if (bit<32)  return ((   (value_ptr->number[0] >>bitpos) & 1)
99 			     | (((value_ptr->number[1] >>bitpos) & 1)<<1));
100 	return (0);
101     case STATE_B128:
102 	if (bit<32)  return (    (value_ptr->number[0] >>bitpos) & 1);
103 	if (bit<64)  return (    (value_ptr->number[1] >>bitpos) & 1);
104 	if (bit<96)  return (    (value_ptr->number[2] >>bitpos) & 1);
105 	if (bit<128) return (    (value_ptr->number[3] >>bitpos) & 1);
106 	return (0);
107     case STATE_F128:
108 	if (bit<32)  return ((   (value_ptr->number[0] >>bitpos) & 1)
109 			     | (((value_ptr->number[4] >>bitpos) & 1)<<1));
110 	if (bit<64)  return ((   (value_ptr->number[1] >>bitpos) & 1)
111 			     | (((value_ptr->number[5] >>bitpos) & 1)<<1));
112 	if (bit<96)  return ((   (value_ptr->number[2] >>bitpos) & 1)
113 			     | (((value_ptr->number[6] >>bitpos) & 1)<<1));
114 	if (bit<128) return ((   (value_ptr->number[3] >>bitpos) & 1)
115 			     | (((value_ptr->number[7] >>bitpos) & 1)<<1));
116 	return (0);
117     default:
118 	return (2);/*X*/
119     }
120 }
121 
val_str_digit_ascii(const Value_t * value_ptr,int lsb)122 static char	val_str_digit_ascii (
123     const Value_t *value_ptr,
124     int lsb)
125 {
126     uint_t val = 0;
127     uint_t bit;
128     int bitnum;
129 
130     for (bitnum=lsb+7; bitnum>=lsb; bitnum--) {
131 	bit = val_bit (value_ptr, bitnum);
132 	if (bit>1) return ('X');
133 	val = val<<1 | bit;
134     }
135     val &= 0xff;
136     if (val==0) return (' ');
137     if (!isprint(val)) return ('?');
138     return (val);
139 }
140 
val_str_ascii(char * strg,const Value_t * value_ptr,Boolean_t compressed)141 static void	val_str_ascii (
142     char *strg,
143     const Value_t *value_ptr,
144     Boolean_t compressed)		/* Drawing on screen; keep small & tidy */
145 {
146     Boolean_t keepspace = FALSE;
147     char *cp = strg;
148     switch (value_ptr->siglw.stbits.state) {
149     case STATE_U:
150 	*cp++ = 'x';
151 	break;
152     case STATE_Z:
153 	*cp++ = 'z';
154 	break;
155     case STATE_0:
156 	break;
157     default: {
158 	int bitnum;
159 	char c;
160 	if (!compressed) *cp++ = '\"';
161 	for (bitnum = 128-8; bitnum >= 0; bitnum-= 8) {
162 	    c = val_str_digit_ascii (value_ptr, bitnum);
163 	    if (c!=' ' || keepspace) {
164 		*cp++ = c;
165 		keepspace = FALSE;
166 	    }
167 	}
168 	while (cp>strg && *(cp-1) == ' ') cp--;
169 	if (!compressed) *cp++ = '\"';
170 	}
171     }
172     *cp++ = '\0';
173 }
174 
val_str_digit(int lsb,uint_t mask,uint_t lw,uint_t enlw)175 static char	val_str_digit (
176     int lsb,
177     uint_t mask,
178     uint_t lw,
179     uint_t enlw
180     )
181 {
182     lw = (lw>>lsb) & mask;
183     enlw = (enlw>>lsb) & mask;
184     if (enlw) {
185 	if ((enlw == mask) && (lw == mask)) {
186 	    return ('z');	/* All z's */
187 	} else if ((enlw == mask) && (lw == 0)) {
188 	    return ('x');	/* All u's */
189 	}
190 	return ('X');	/* U/Z/0/1 mix */
191     }
192 
193     return (lw + ((lw < 10) ? '0':('a'-10)));
194 }
195 
val_str_lw(const Radix_t * radix_ptr,char * strg,char sep,Boolean_t middle,int width,uint_t lw,uint_t enlw)196 static void    val_str_lw (
197     const Radix_t *radix_ptr,
198     char *strg,
199     char sep,
200     Boolean_t middle,	/* 2nd, 3rd, etc value on this line */
201     int width,
202     uint_t lw,
203     uint_t enlw
204     )
205 {
206     int bit = 31;
207 
208     /* Separate if needed */
209     if (middle) {
210 	*strg++ = sep;
211     }
212     if (!middle) {
213 	if (width) {
214 	    /* Start at appropriate bit */
215 	    bit = ((width-1) & 31);
216 	} else {
217 	    /* Skip leading 0's */
218 	    for (; bit>0; bit--) {
219 		if ((lw|enlw) & (1L<<bit)) break;
220 	    }
221 	}
222     }
223 
224     switch (radix_ptr->type) {
225     case RADIX_HEX_UN:
226 	for (; bit>=0; bit--) {
227 	    bit = (bit / 4) *4;	/* Next hex digit */
228 	    *strg++ = val_str_digit (bit, 0xf, lw, enlw);
229 	}
230 	*strg++ = '\0';
231 	break;
232     case RADIX_OCT_UN:
233 	for (; bit>=0; bit--) {
234 	    bit = (bit / 3) *3;	/* Next octal digit */
235 	    *strg++ = val_str_digit (bit, 0x7, lw, enlw);
236 	}
237 	*strg++ = '\0';
238 	break;
239     case RADIX_DEC_UN:
240 	if (enlw) {
241 	    strcpy (strg,"Mixed01XU");
242 	} else {
243 	    sprintf (strg,middle?"%010d":"%d", lw);
244 	}
245 	break;
246     case RADIX_DEC_SN:
247 	if (enlw) {
248 	    strcpy (strg,"Mixed01XU");
249 	} else {
250 	    if (lw & (1<<(width-1))) {  // Negative
251 		int masked = ~lw & ((1<<(width-1))-1);
252 		sprintf (strg,"-%d", masked+1);
253 	    } else {  // Signed and positive
254 		sprintf (strg,middle?"%010d":"%d", lw);
255 	    }
256 	}
257 	break;
258     case RADIX_BIN_UN: {
259 	for (;bit>=0;bit--) {
260 	    *strg++ = val_str_digit (bit, 0x1, lw, enlw);
261 	}
262 	*strg++ = '\0';
263 	break;
264     }
265     default: strcat (strg, "bad radix");
266     }
267 }
268 
val_to_string(const Radix_t * radix_ptr,char * strg,const Value_t * value_ptr,int width,Boolean_t compressed,Boolean_t dropleading)269 void    val_to_string (
270     const Radix_t *radix_ptr,
271     char *strg,
272     const Value_t *value_ptr,
273     int width,				/* or 0 to drop leading 0s */
274     Boolean_t compressed,		/* Drawing on screen; keep small & tidy */
275     Boolean_t dropleading)		/* Drop leading spaces */
276     /* Convert a string to a value */
277     /* Understand 'h 'b and other similar tags */
278     /* Try to convert a signal state also */
279     /* This isn't fast, so don't use when reading files!!! */
280 {
281     char sep = compressed ? ' ' : '_';
282     if (radix_ptr==NULL) {strcpy (strg,"nullradix_ptr"); return;}
283 
284     if (radix_ptr->type == RADIX_ASCII) {
285 	val_str_ascii (strg, value_ptr, compressed);
286 	return;
287     }
288 
289     switch (value_ptr->siglw.stbits.state) {
290     case STATE_0:
291 	*strg++ = '0';
292 	break;
293     case STATE_1:
294 	*strg++ = '1';
295 	break;
296     case STATE_U:
297 	*strg++ = 'x';
298 	break;
299     case STATE_Z:
300 	*strg++ = 'z';
301 	break;
302 
303     case STATE_B32:
304     case STATE_F32:
305     case STATE_B128:
306     case STATE_F128: {
307 	Boolean_t middle = FALSE;
308 	if (!compressed) {
309 	    strcpy (strg, radix_ptr->prefix);
310 	    strg += strlen (radix_ptr->prefix);
311 	}
312 	if (radix_ptr->type == RADIX_REAL
313 	    && value_ptr->siglw.stbits.state == STATE_B128) {
314 	    sprintf (strg, "%g", *(double*)(&value_ptr->number[0]));
315 	} else {
316 	    uint_t enlw;
317 	    if (value_ptr->siglw.stbits.state == STATE_B128
318 		|| value_ptr->siglw.stbits.state == STATE_F128) {
319 		if (value_ptr->number[3]
320 		    || (!dropleading && width>32*3)) {
321 		    val_str_lw (radix_ptr, strg, sep, middle, width,
322 				value_ptr->number[3],
323 				((value_ptr->siglw.stbits.state == STATE_F128)
324 				 ?value_ptr->number[7]:0));
325 		    strg += strlen (strg);
326 		    middle = TRUE;
327 		}
328 		if (value_ptr->number[3] || value_ptr->number[2]
329 		    || (!dropleading && width>32*2)) {
330 		    val_str_lw (radix_ptr, strg, sep, middle, width,
331 				value_ptr->number[2],
332 				((value_ptr->siglw.stbits.state == STATE_F128)
333 				 ?value_ptr->number[6]:0));
334 		    strg += strlen (strg);
335 		    middle = TRUE;
336 		}
337 		if (value_ptr->number[3] || value_ptr->number[2]
338 		    || value_ptr->number[1]
339 		    || (!dropleading && width>32*1)) {
340 		    val_str_lw (radix_ptr, strg, sep, middle, width,
341 				value_ptr->number[1],
342 				((value_ptr->siglw.stbits.state == STATE_F128)
343 				 ?value_ptr->number[5]:0));
344 		    strg += strlen (strg);
345 		    middle = TRUE;
346 		}
347 	    }
348 	    enlw = 0;
349 	    if (value_ptr->siglw.stbits.state == STATE_F128) {
350 		enlw = value_ptr->number[4];
351 	    }
352 	    if (value_ptr->siglw.stbits.state == STATE_F32) {
353 		enlw = value_ptr->number[1];
354 	    }
355 	    val_str_lw (radix_ptr, strg, sep, middle, width,
356 			value_ptr->number[0], enlw);
357 	}
358 	strg += strlen (strg);
359 	break;
360     }
361     default:
362 	*strg++ = '?';
363 	break;
364     }
365     *strg++ = '\0';
366 }
367 
val_minimize(Value_t * value_ptr,Signal_t * sig_ptr)368 void	val_minimize (
369     Value_t	*value_ptr,
370     Signal_t	*sig_ptr
371     )
372     /* Given a STATE_B128, try to shrink to something smaller if we can */
373 {
374     Boolean_t num123 = (value_ptr->number[1]
375 			|| value_ptr->number[2]
376 			|| value_ptr->number[3]);
377     Boolean_t num567 = (value_ptr->number[5]
378 			|| value_ptr->number[6]
379 			|| value_ptr->number[7]);
380     if (!value_ptr->number[4] && !num567) {
381 	if (!num123) {
382 	    if (!value_ptr->number[0])
383 		value_ptr->siglw.stbits.state = STATE_0;
384 	    else value_ptr->siglw.stbits.state = STATE_B32;
385 	}
386 	else value_ptr->siglw.stbits.state = STATE_B128;
387     } else {
388 	if ((value_ptr->number[0] == value_ptr->number[4])
389 	    && (value_ptr->number[1] == value_ptr->number[5])
390 	    && (value_ptr->number[2] == value_ptr->number[6])
391 	    && (value_ptr->number[3] == value_ptr->number[7])
392 	    && sig_ptr
393 	    && (value_ptr->number[0] == sig_ptr->value_mask[0])
394 	    && (value_ptr->number[1] == sig_ptr->value_mask[1])
395 	    && (value_ptr->number[2] == sig_ptr->value_mask[2])
396 	    && (value_ptr->number[3] == sig_ptr->value_mask[3])
397 	    ) {
398 	    value_ptr->siglw.stbits.state = STATE_Z;
399 	} else if (!num123 && !num567) {
400 	    value_ptr->siglw.stbits.state = STATE_F32;
401 	    value_ptr->number[1] = value_ptr->number[4];
402 	    value_ptr->number[4] = 0;
403 	} else {
404 	    value_ptr->siglw.stbits.state = STATE_F128;
405 	}
406     }
407     value_ptr->siglw.stbits.size = STATE_SIZE(value_ptr->siglw.stbits.state);
408 }
409 
string_to_value(Radix_t ** radix_pptr,const char * strg,Value_t * value_ptr)410 void    string_to_value (
411     Radix_t **radix_pptr,
412     const char *strg,
413     Value_t *value_ptr)
414 {
415     register char value;
416     uint_t MSO = (7L<<29);	/* Most significant octal digit */
417     uint_t MSH = (15L<<28);	/* Most significant hex digit */
418     uint_t MSB = (1L<<31);	/* Most significant binary digit */
419     uint_t MSC = (0xffL<<24);	/* Most significant char */
420     const char *cp = strg;
421     char radix_id;
422     uint_t *nptr = &(value_ptr->number[0]);
423     Boolean_t negate = FALSE;
424 
425     val_zero (value_ptr);
426 
427     radix_id = 'x';
428     *radix_pptr = global->radixs[RADIX_HEX_UN];
429     if (*cp=='\'') {
430 	radix_id = cp[1];
431 	cp+=2;
432     } else if (isalpha(*cp) && cp[1]=='"') {
433 	radix_id = cp[0];
434 	cp+=2;
435     } else if (*cp=='"') {
436 	radix_id = cp[0];
437 	cp++;
438     }
439     switch (toupper(radix_id)) {
440     case 'o': *radix_pptr = global->radixs[RADIX_OCT_UN]; break;
441     case 'd': *radix_pptr = global->radixs[RADIX_DEC_UN]; break;
442     case 'i': *radix_pptr = global->radixs[RADIX_DEC_SN]; break;
443     case 'b': *radix_pptr = global->radixs[RADIX_BIN_UN]; break;
444     case 'r': *radix_pptr = global->radixs[RADIX_REAL]; break;
445     case '"':
446     case 's':
447 	*radix_pptr = global->radixs[RADIX_ASCII];  break;
448     default:
449     case 'h':
450     case 'x':
451 	*radix_pptr = global->radixs[RADIX_HEX_UN];  break;
452     }
453 
454     if ((*radix_pptr)->type != RADIX_ASCII
455 	|| (cp == strg)) {
456         /*Value literals: Not in a string, or unquoted:*/
457 	if ((*cp == 'z' || *cp == 'Z') && cp[1]=='\0') {
458 	    value_ptr->siglw.stbits.state = STATE_Z;
459 	    return;
460 	}
461 	if ((*cp == 'u' || *cp == 'U' || *cp == 'x' || *cp == 'X') && cp[1]=='\0') {
462 	    value_ptr->siglw.stbits.state = STATE_U;
463 	    return;
464 	}
465     }
466 
467     if ((*radix_pptr)->type == RADIX_REAL) {
468 	double dnum = atof (cp);
469 	if (dnum == 0) 	value_ptr->siglw.stbits.state = STATE_0;
470 	else {
471 	    value_ptr->siglw.stbits.state = STATE_B128;
472 	    *((double*)&value_ptr->number[0]) = dnum;
473 	}
474 	return;
475     }
476 
477     for (; *cp; cp++) {
478 	value = -1;
479 	if (*cp >= '0' && *cp <= '9')
480 	    value = *cp - '0';
481 	else if (*cp >= 'A' && *cp <= 'F')
482 	    value = *cp - ('A' - 10);
483 	else if (*cp >= 'a' && *cp <= 'f')
484 	    value = *cp - ('a' - 10);
485 	else if (*cp == '-')
486 	    negate = !negate;
487 
488 	switch ((*radix_pptr)->type) {
489 	case RADIX_HEX_UN:
490 	    if (value >=0 && value <= 15) {
491 		nptr[3] = (nptr[3]<<4) + ((nptr[2] & MSH)>>28);
492 		nptr[2] = (nptr[2]<<4) + ((nptr[1] & MSH)>>28);
493 		nptr[1] = (nptr[1]<<4) + ((nptr[0] & MSH)>>28);
494 		nptr[0] = (nptr[0]<<4) + value;
495 	    }
496 	    break;
497 	case RADIX_OCT_UN:
498 	    if (value >=0 && value <= 7) {
499 		nptr[3] = (nptr[3]<<3) + ((nptr[2] & MSO)>>29);
500 		nptr[2] = (nptr[2]<<3) + ((nptr[1] & MSO)>>29);
501 		nptr[1] = (nptr[1]<<3) + ((nptr[0] & MSO)>>29);
502 		nptr[0] = (nptr[0]<<3) + value;
503 	    }
504 	    break;
505 	case RADIX_BIN_UN:
506 	    if (value >=0 && value <= 1) {
507 		nptr[3] = (nptr[3]<<1) + ((nptr[2] & MSB)>>31);
508 		nptr[2] = (nptr[2]<<1) + ((nptr[1] & MSB)>>31);
509 		nptr[1] = (nptr[1]<<1) + ((nptr[0] & MSB)>>31);
510 		nptr[0] = (nptr[0]<<1) + value;
511 	    }
512 	    break;
513 	case RADIX_DEC_UN:
514 	case RADIX_DEC_SN:
515 	    if (value >=0 && value <= 9) {
516 		/* This is buggy for large numbers */
517 		/* Note in spec that binary is for 32 bit or less numbers */
518 		nptr[3] = (nptr[3]*10) + ((cp>=(strg+30))?cp[-30]:0);
519 		nptr[2] = (nptr[2]*10) + ((cp>=(strg+20))?cp[-20]:0);
520 		nptr[1] = (nptr[1]*10) + ((cp>=(strg+10))?cp[-10]:0);
521 		nptr[0] = (nptr[0]*10) + value;
522 	    }
523 	    break;
524 	case RADIX_ASCII:
525 	    if (*cp != '\"') {
526 		nptr[3] = (nptr[3]<<8) + ((nptr[2] & MSC)>>24);
527 		nptr[2] = (nptr[2]<<8) + ((nptr[1] & MSC)>>24);
528 		nptr[1] = (nptr[1]<<8) + ((nptr[0] & MSC)>>24);
529 		nptr[0] = (nptr[0]<<8) + (*cp & 0xff);
530 	    }
531 	    break;
532 	case RADIX_MAX:
533 	case RADIX_REAL:
534 	    break;
535 	}
536     }
537 
538     if (negate && (nptr[0] || nptr[1] || nptr[2] || nptr[3])) {
539 	nptr[0] = ~nptr[0];
540 	nptr[1] = ~nptr[1];
541 	nptr[2] = ~nptr[2];
542 	nptr[3] = ~nptr[3];
543 	nptr[0]++;
544 	if (!nptr[0]) nptr[1]++;
545 	if (!nptr[0] && !nptr[1]) nptr[2]++;
546 	if (!nptr[0] && !nptr[1] && !nptr[2]) nptr[3]++;
547     }
548 
549     val_minimize (value_ptr, NULL);
550 }
551 
val_zero_or_one(const Value_t * vptr)552 Boolean_t  val_zero_or_one (
553     const Value_t	*vptr)
554 {
555     return ( (  vptr->siglw.stbits.state == STATE_0)
556 	     || (vptr->siglw.stbits.state == STATE_1)
557 	     || (vptr->siglw.stbits.state == STATE_B32
558 		 && (vptr->number[0] == 1)));
559 }
560 
val_equal(const Value_t * vptra,const Value_t * vptrb)561 Boolean_t  val_equal (
562     const Value_t	*vptra,
563     const Value_t	*vptrb)
564 {
565     return ((vptra->siglw.stbits.state == vptrb->siglw.stbits.state)
566 	    && (( (  vptra->siglw.stbits.state == STATE_0)
567 		  | (vptra->siglw.stbits.state == STATE_1)
568 		  | (vptra->siglw.stbits.state == STATE_U)
569 		  | (vptra->siglw.stbits.state == STATE_Z))
570 		|| ((vptra->siglw.stbits.state == STATE_B32)
571 		    & (vptra->number[0] == vptrb->number[0]))
572 		|| ((vptra->siglw.stbits.state == STATE_B128)
573 		    & (vptra->number[0] == vptrb->number[0])
574 		    & (vptra->number[1] == vptrb->number[1])
575 		    & (vptra->number[2] == vptrb->number[2])
576 		    & (vptra->number[3] == vptrb->number[3]))
577 		|| ((vptra->siglw.stbits.state == STATE_F32)
578 		    & (vptra->number[0] == vptrb->number[0])
579 		    & (vptra->number[1] == vptrb->number[1]))
580 		|| ((vptra->siglw.stbits.state == STATE_F128)
581 		    & (vptra->number[0] == vptrb->number[0])
582 		    & (vptra->number[1] == vptrb->number[1])
583 		    & (vptra->number[2] == vptrb->number[2])
584 		    & (vptra->number[3] == vptrb->number[3])
585 		    & (vptra->number[4] == vptrb->number[4])
586 		    & (vptra->number[5] == vptrb->number[5])
587 		    & (vptra->number[6] == vptrb->number[6])
588 		    & (vptra->number[7] == vptrb->number[7]))
589 		));
590 }
591 
val_update_search()592 void	val_update_search ()
593 {
594     Trace_t	*trace;
595     Signal_t	*sig_ptr;
596     Value_t	*cptr;
597     int		cursorize;
598     register int i;
599     DCursor_t	*csr_ptr;
600     Boolean_t	any_enabled;
601     Boolean_t	zero_or_one_search = FALSE;
602     Boolean_t	matches[MAX_SRCH];	/* Cache the wildmat for each bit, so searching is faster */
603     static Boolean_t enabled_lasttime = FALSE;
604     int		prev_cursor;
605 
606     if (DTPRINT_ENTRY) printf ("In val_update_search\n");
607 
608     /* This sometimes takes a while (don't XSync in case it doesn't) */
609     prev_cursor = last_set_cursor ();
610     set_cursor (DC_BUSY);
611 
612     /* If no searches are enabled, skip the cptr loop.  */
613     /* This saves 3% of the first reading time on large traces */
614     any_enabled = enabled_lasttime; 	/* if all get disabled, we still need to clean up enables */
615     for (i=0; i<MAX_SRCH; i++) {
616 	if ((global->val_srch[i].color != 0)
617 	    || (global->val_srch[i].cursor != 0)) {
618 	    any_enabled = TRUE;
619 	    if (val_zero_or_one(&global->val_srch[i].value)) zero_or_one_search = TRUE;
620 	}
621     }
622     enabled_lasttime = FALSE;
623 
624     /* Mark all cursors that are a result of a search as old (-1) */
625     for (csr_ptr = global->cursor_head; csr_ptr; csr_ptr = csr_ptr->next) {
626 	if (csr_ptr->type==SEARCH) csr_ptr->type = SEARCHOLD;
627     }
628 
629     /* Search every trace for the value, mark the signal if it has it to speed up displaying */
630     for (trace = global->deleted_trace_head; trace; trace = trace->next_trace) {
631 	for (sig_ptr = trace->firstsig; sig_ptr; sig_ptr = sig_ptr->forward) {
632 	    if (any_enabled) {
633 		if (!zero_or_one_search && sig_ptr->bits<2) {
634 		    /* Single bit signal, don't search for values > 1 for speed */
635 		    continue;
636 		}
637 
638 		cursorize=0;
639 		for (i=0; i<MAX_SRCH; i++) {
640 		    matches[i] = 0;
641 		}
642 
643 		for (cptr = sig_ptr->bptr; (CPTR_TIME(cptr) != EOT);
644 		     cptr = CPTR_NEXT(cptr)) {
645 		    int color_to_assign = 0;
646 		    switch (cptr->siglw.stbits.state) {
647 		    case STATE_0:
648 		    case STATE_1:
649 			if (!zero_or_one_search) break;
650 			/* FALLTHRU */
651 		    case STATE_B32:
652 		    case STATE_B128:
653 		    case STATE_F32:
654 		    case STATE_F128:
655 			for (i=0; i<MAX_SRCH; i++) {
656 			    if (val_equal (cptr, &global->val_srch[i].value)
657 				&& ( matches[i] || wildmat (sig_ptr->signame, global->val_srch[i].signal))  ) {
658 				matches[i] = TRUE;
659 				if ( global->val_srch[i].color != 0) {
660 				    color_to_assign = global->val_srch[i].color;
661 				    enabled_lasttime = TRUE;
662 				}
663 				if ( global->val_srch[i].cursor != 0) {
664 				    cursorize = global->val_srch[i].cursor;
665 				    enabled_lasttime = TRUE;
666 				}
667 				/* don't break, because if same value on two lines, one with cursor and one without will fail */
668 			    }
669 			}
670 			break;
671 		    } /* switch */
672 
673 		    if (color_to_assign != (int)cptr->siglw.stbits.color) {
674 			/* Don't write unless changes to save cache flushing */
675 			cptr->siglw.stbits.color = color_to_assign;
676 		    }
677 
678 		    if (cursorize) {
679 			if (NULL != (csr_ptr = time_to_cursor (CPTR_TIME(cptr)))) {
680 			    if (csr_ptr->type == SEARCHOLD) {
681 				/* mark the old cursor as new so won't be deleted */
682 				csr_ptr->type = SEARCH;
683 			    }
684 			}
685 			else {
686 			    /* Make new cursor at this location */
687 			    cur_new (CPTR_TIME(cptr), cursorize, SEARCH, NULL);
688 			}
689 			cursorize = 0;
690 		    }
691 
692 		} /* for cptr */
693 	    } /* if enabled */
694 	} /* for sig */
695     } /* for trace */
696 
697     /* Delete all old cursors */
698     cur_delete_of_type (SEARCHOLD);
699 
700     set_cursor (prev_cursor);
701 }
702 
val_transition_cnt(Signal_t * sig_ptr,Value_t * stop_cptr,int * negedgesp,int * posedgesp)703 void	val_transition_cnt (Signal_t* sig_ptr, Value_t* stop_cptr, int* negedgesp, int* posedgesp)
704 {
705     Value_t*	cptr;
706     int		posedges = 0;
707     int		negedges = 0;
708     int		last_state = -1;
709     for (cptr = sig_ptr->bptr; (CPTR_TIME(cptr) != EOT); cptr = CPTR_NEXT(cptr)) {
710 	/**/
711 	switch (cptr->siglw.stbits.state) {
712 	case STATE_0:
713 	    if (last_state==STATE_1 || last_state<0) negedges++;
714 	    break;
715 	case STATE_1:
716 	    if (last_state==STATE_0 || last_state<0) posedges++;
717 	    break;
718 	case STATE_Z:
719 	case STATE_B32:
720 	case STATE_B128:
721 	case STATE_F32:
722 	case STATE_F128:
723 	    break;
724 	}
725 	last_state = cptr->siglw.stbits.state;
726 	if (cptr == stop_cptr) break;
727     }
728     *negedgesp = negedges;
729     *posedgesp = posedges;
730 }
731 
732 /****************************** RADIXS ******************************/
733 
val_radix_find(const char * name)734 Radix_t *val_radix_find (
735     const char *name)
736 {
737     Radix_t *radix_ptr;
738     for (radix_ptr=global->radixs[0]; radix_ptr; radix_ptr = radix_ptr->next) {
739 	if (!strcasecmp(radix_ptr->name, name)) {
740 	    return (radix_ptr);
741 	}
742     }
743     return (NULL);
744 }
745 
val_radix_add(RadixType_t type,const char * name,const char * prefix)746 static Radix_t *val_radix_add (
747     RadixType_t type,
748     const char *name,
749     const char *prefix)
750 {
751     int radixnum;
752     Radix_t *radix_ptr;
753     Radix_t *found_radix_ptr;
754 
755     found_radix_ptr = val_radix_find (name); /* Null if not found */
756     radix_ptr = found_radix_ptr;
757 
758     if (found_radix_ptr == NULL) {
759 	Radix_t *radix_end_ptr;
760 	radix_ptr = DNewCalloc (Radix_t);
761 
762 	for (radix_end_ptr=global->radixs[0]; radix_end_ptr; radix_end_ptr = radix_end_ptr->next) {
763 	    if (!radix_end_ptr->next) {
764 		radix_end_ptr->next = radix_ptr;
765 		break;
766 	    }
767 	}
768 
769 	/* Can we fit it in the menu? */
770 	for (radixnum=0; radixnum < RADIX_MAX_MENU; radixnum++) {
771 	    if (global->radixs[radixnum]==NULL) {
772 		global->radixs[radixnum]=radix_ptr;
773 		break;
774 	    }
775 	}
776     }
777     radix_ptr->name = strdup (name);
778     radix_ptr->type = type;
779     radix_ptr->prefix = strdup(prefix);
780 
781     return (radix_ptr);
782 }
783 
val_radix_init()784 void	val_radix_init ()
785 {
786     int		radixnum;
787     /* Define default radixs */
788     for (radixnum=0; radixnum<RADIX_MAX; radixnum++) {
789 	global->radixs[radixnum] = NULL;
790     }
791     /* This order MUST match the enum order of RadixType_t */
792     /* The first one listed is the system default */
793 #define DEFAULT_RADIX_PREFIX "'h"
794     val_radix_add (RADIX_HEX_UN, "Hex", "");
795     val_radix_add (RADIX_OCT_UN, "Octal",	"'o");
796     val_radix_add (RADIX_BIN_UN, "Binary", "'b");
797     val_radix_add (RADIX_DEC_UN, "Decimal", "'d");
798     val_radix_add (RADIX_DEC_SN, "Signed Decimal", "'i");
799     val_radix_add (RADIX_ASCII,  "Ascii", "\"");
800     val_radix_add (RADIX_REAL,   "Real", "'r");
801 }
802 
803 /****************************** STATES ******************************/
804 
val_states_update()805 void	val_states_update ()
806 {
807     Trace_t	*trace;
808     Signal_t	*sig_ptr;
809 
810     if (DTPRINT_ENTRY) printf ("In val_states_update\n");
811 
812      for (trace = global->deleted_trace_head; trace; trace = trace->next_trace) {
813 	 for (sig_ptr = trace->firstsig; sig_ptr; sig_ptr = sig_ptr->forward) {
814 	     if (NULL != (sig_ptr->decode = signalstate_find (trace, sig_ptr->signame))) {
815 		 /* if (DTPRINT_FILE) printf ("Signal %s is patterned\n",sig_ptr->signame); */
816 	     }
817 	 }
818      }
819 }
820 
821 
822 /****************************** MENU OPTIONS ******************************/
823 
val_examine_cb(Widget w)824 void    val_examine_cb (
825     Widget	w)
826 {
827     Trace_t *trace = widget_to_trace(w);
828 
829     if (DTPRINT_ENTRY) printf ("In val_examine_cb - trace=%p\n",trace);
830 
831     /* process all subsequent button presses as cursor moves */
832     remove_all_events (trace);
833     set_cursor (DC_VAL_EXAM);
834     add_event (ButtonPressMask, val_examine_ev);
835 }
836 
val_highlight_cb(Widget w)837 void    val_highlight_cb (
838     Widget	w)
839 {
840     Trace_t *trace = widget_to_trace(w);
841     if (DTPRINT_ENTRY) printf ("In val_highlight_cb - trace=%p\n",trace);
842 
843     /* Grab color number from the menu button pointer */
844     global->highlight_color = submenu_to_color (trace, w, 0, trace->menu.val_highlight_pds);
845 
846     /* process all subsequent button presses as signal deletions */
847     remove_all_events (trace);
848     set_cursor (DC_VAL_HIGHLIGHT);
849     add_event (ButtonPressMask, val_highlight_ev);
850 }
851 
852 
853 /****************************** EVENTS ******************************/
854 
val_examine_string(Trace_t * trace,Signal_t * sig_ptr,DTime_t time)855 char *val_examine_string (
856     /* Return string with examine information in it */
857     Trace_t	*trace,
858     Signal_t	*sig_ptr,
859     DTime_t	time)
860 {
861     Value_t	*cptr;
862     static char	strg[2000];
863     char	strg2[2000];
864     int		rows, cols, bit, row, col;
865     int		lesser_index, greater_index;
866     char	*format;
867 
868     if (DTPRINT_ENTRY) printf ("\ttime = %d, signal = %s\n", time, sig_ptr->signame);
869 
870     /* Get information */
871     cptr = value_at_time (sig_ptr, time);
872 
873     lesser_index = MIN(sig_ptr->msb_index,sig_ptr->lsb_index);
874     greater_index = MAX(sig_ptr->msb_index,sig_ptr->lsb_index);
875     strcpy (strg, sig_ptr->signame);
876 
877     if (CPTR_TIME(cptr) == EOT) {
878 	strcat (strg, "\nValue at EOT:\n");
879     }
880     else {
881 	strcat (strg, "\nValue at times ");
882 	time_to_string (trace, strg2, CPTR_TIME(cptr), FALSE);
883 	strcat (strg, strg2);
884 	strcat (strg, " - ");
885 	time_to_string (trace, strg2, CPTR_TIME(CPTR_NEXT(cptr)), FALSE);
886 	strcat (strg, strg2);
887 	strcat (strg, ":\n");
888     }
889 
890     strcat (strg, "= ");
891     val_to_string (sig_ptr->radix, strg2, cptr, sig_ptr->bits, FALSE, FALSE);
892     strcat (strg, strg2);
893     strcat (strg, "\n");
894     if (sig_ptr->radix->type != global->radixs[0]->type) {
895 	strcat (strg, "= ");
896 	strcat (strg, DEFAULT_RADIX_PREFIX);
897 	val_to_string (global->radixs[0], strg2, cptr, sig_ptr->bits, FALSE, FALSE);
898 	strcat (strg, strg2);
899 	strcat (strg, "\n");
900     }
901 
902     if (sig_ptr->bits>1
903 	&& (lesser_index > 0)
904 	&& ((sig_ptr->bits + lesser_index) <= 32)
905 	&& (cptr->siglw.stbits.state == STATE_B32)) {
906 	Value_t shifted;
907 	val_zero (&shifted);
908 	(&shifted)->siglw     = cptr->siglw;
909 	(&shifted)->number[0] = cptr->number[0] << lesser_index;
910 	/* Show decode */
911 	sprintf (strg2, "[%d:0] = ", greater_index);
912 	strcat (strg, strg2);
913 	val_to_string (sig_ptr->radix, strg2, &shifted,
914 		       sig_ptr->bits + lesser_index, FALSE, FALSE);
915 	strcat (strg, strg2);
916 	strcat (strg, "\n");
917     }
918 
919     if (sig_ptr->bits>1
920 	&& (cptr->siglw.stbits.state == STATE_B32
921 	    || cptr->siglw.stbits.state == STATE_0)) {
922 	uint_t num0 = 0;
923 	if (cptr->siglw.stbits.state != STATE_0) num0 = cptr->number[0];
924 	if ((sig_ptr->decode != NULL)
925 	    && (num0 < sig_ptr->decode->numstates)
926 	    && (sig_ptr->decode->statename[num0][0] != '\0') ) {
927 	    /* Show decode */
928 	    sprintf (strg2, "State = %s\n", sig_ptr->decode->statename[num0] );
929 	    strcat (strg, strg2);
930 	}
931     }
932 
933     switch (cptr->siglw.stbits.state) {
934     case STATE_B32:
935     case STATE_F32:
936     case STATE_B128:
937     case STATE_F128:
938 	/* Bitwise information */
939 	rows = (int)(ceil (sqrt ((double)(sig_ptr->bits))));
940 	cols = (int)(ceil ((double)(rows) / 4.0) * 4);
941 	rows = (int)(ceil ((double)(sig_ptr->bits)/ (double)cols));
942 
943 	format = "[%01d]=%c ";
944 	if (greater_index >= 10)  format = "[%02d]=%c ";
945 	if (greater_index >= 100) format = "[%03d]=%c ";
946 
947 	bit = 0;
948 	for (row=rows - 1; row >= 0; row--) {
949 	    for (col = cols - 1; col >= 0; col--) {
950 		bit = (row * cols + col);
951 		if ((bit>=0) && (bit < sig_ptr->bits)) {
952 		    uint_t bit_value = val_bit (cptr, bit);
953 		    sprintf (strg2, format, greater_index +
954 			     ((greater_index >= lesser_index)
955 			      ? (bit - sig_ptr->bits + 1) : (sig_ptr->bits - bit - 1)),
956 			     "01uz"[bit_value]);
957 		    strcat (strg, strg2);
958 		    if (col==4 || col==8) strcat (strg, "  ");
959 		}
960 	    }
961 	    strcat (strg, "\n");
962 	}
963 	break;
964     }
965 
966     if (sig_ptr->bits > 2) {
967 	int par = 0;
968 	Boolean_t unknown = FALSE;
969 	for (bit=0; bit<=sig_ptr->bits; bit++) {
970 	    uint_t bit_value = val_bit (cptr, bit);
971 	    if (bit_value==0 || bit_value==1) par ^= bit_value;
972 	    else unknown = TRUE;
973 	}
974 	if (!unknown) {
975 	    if (par) strcat (strg, "Odd Parity\n");
976 	    else  strcat (strg, "Even Parity\n");
977 	}
978     }
979 
980     if (sig_ptr->bits == 1) {
981 	int	posedges = 0;
982 	int	negedges = 0;
983 	val_transition_cnt (sig_ptr, cptr, &negedges, &posedges);
984 	if (posedges && posedges>negedges) {
985 	    sprintf (strg2, "Posedge # %d\n", posedges);
986 	    strcat (strg, strg2);
987 	} else if (negedges) {
988 	    sprintf (strg2, "Negedge # %d\n", negedges);
989 	    strcat (strg, strg2);
990 	}
991     }
992 
993     /* Debugging information */
994     if (DTDEBUG) {
995 	strcat (strg, "\n");
996 	sprintf (strg2, "Value_stbits %08x  %s\n",
997 		 cptr->siglw.number,
998 		 val_state_name[cptr->siglw.stbits.state]);
999 	strcat (strg, strg2);
1000     }
1001 
1002     return (strg);
1003 }
1004 
val_examine_popdown(Trace_t * trace)1005 static void    val_examine_popdown (
1006     Trace_t	*trace)
1007 {
1008     if (trace->examine.popup) {
1009 	XtPopdown (trace->examine.popup);
1010 	if (XtIsManaged(trace->examine.rowcol)) {
1011 	    XtUnmanageChild (trace->examine.label);
1012 	    XtUnmanageChild (trace->examine.rowcol);
1013 	}
1014 
1015 	/* We'll regenerate, as the text gets hosed elsewise */
1016 	XtDestroyWidget (trace->examine.label);
1017 	XtDestroyWidget (trace->examine.rowcol);
1018 	XtDestroyWidget (trace->examine.popup);
1019 	trace->examine.popup = NULL;
1020     }
1021 }
1022 
val_examine_popup(Trace_t * trace,XButtonPressedEvent * ev)1023 static void    val_examine_popup (
1024     /* Create the popup menu for val_examine, based on cursor position x,y */
1025     Trace_t	*trace,
1026     XButtonPressedEvent	*ev)
1027 {
1028     DTime_t	time;
1029     Signal_t	*sig_ptr;
1030     char	*strg = "No information here";
1031     XmString	xs;
1032     int		x,y;	/* Must allow signed */
1033 
1034     time = posx_to_time (trace, ev->x);
1035     sig_ptr = posy_to_signal (trace, ev->y);
1036     if (DTPRINT_ENTRY) printf ("In val_examine_popup %d %d time %d\n", __LINE__, ev->x, time);
1037 
1038     val_examine_popdown (trace);
1039 
1040     /* Get the text to display */
1041     /* Brace yourself for something that should be object oriented... */
1042     if (sig_ptr) {
1043 	/* Get information */
1044 	if (time>=0) {
1045 	    strg = val_examine_string (trace, sig_ptr, time);
1046 	} else {
1047 	    strg = sig_examine_string (trace, sig_ptr);
1048 	}
1049     } else {
1050 	if (ev->y <= trace->ystart) {
1051 	    DTime_t grid_time;
1052 	    Grid_t *grid_ptr = posx_to_grid (trace, ev->x, &grid_time);
1053 	    if (grid_ptr) strg = grid_examine_string (trace, grid_ptr, grid_time);
1054 	} else {
1055 	    DCursor_t *csr_ptr = posx_to_cursor (trace, ev->x);
1056 	    if (csr_ptr) strg = cur_examine_string (trace, csr_ptr);
1057 	}
1058     }
1059 
1060 
1061     /* First, a override for the shell */
1062     /* It's probably tempting to use XmCreatePopupMenu. */
1063     /* Don't.  It was that way, but the keyboard grab proved problematic */
1064     /* Don't manage this guy, he's just a container */
1065     XtSetArg (arglist[0], XmNallowShellResize, FALSE);
1066     XtSetArg (arglist[1], XmNshadowThickness, 2);
1067 #if 1  /* If you get a error on the next line, try changing the 1 to a 0 */
1068     trace->examine.popup = (Widget)XmCreateGrabShell (trace->main, "examinepopup", arglist, 2);
1069 #else
1070     trace->examine.popup = XtCreatePopupShell
1071 	("examinepopup", overrideShellWidgetClass, trace->main, arglist, 1);
1072 #endif
1073 
1074     /* Row column for a nice border */
1075     /* For Lesstif we used to have MENU_POPUP, but that has mouse side effects */
1076     XtSetArg (arglist[0], XmNrowColumnType, XmWORK_AREA);
1077     XtSetArg (arglist[1], XmNborderWidth, 1);
1078     XtSetArg (arglist[2], XmNentryAlignment, XmALIGNMENT_CENTER);
1079     XtSetArg (arglist[3], XmNshadowThickness, 2);
1080     trace->examine.rowcol = XmCreateRowColumn (trace->examine.popup,"rowcol",arglist,4);
1081 
1082     /* Finally the label */
1083     xs = string_create_with_cr (strg);
1084     XtSetArg (arglist[0], XmNlabelString, xs);
1085     trace->examine.label = XmCreateLabel (trace->examine.rowcol,"popuplabel",arglist,1);
1086     DManageChild (trace->examine.label, trace, MC_GLOBALKEYS);
1087     XmStringFree (xs);
1088 
1089     /* Don't stretch past right screen edge if possible */
1090     x = ev->x_root;  y = ev->y_root;
1091     if (x + trace->examine.label->core.width >= (XtScreen(trace->examine.popup)->width)) {
1092 	x = (XtScreen(trace->examine.popup)->width) - trace->examine.label->core.width - 1;
1093     }
1094     if (y + trace->examine.label->core.height >= (XtScreen(trace->examine.popup)->height)) {
1095 	y = (XtScreen(trace->examine.popup)->height) - trace->examine.label->core.height - 1;
1096     }
1097     x = MAX(x,0); y = MAX(y,0);
1098     XtSetArg (arglist[0], XmNx, x);
1099     XtSetArg (arglist[1], XmNy, y);
1100     XtSetValues (trace->examine.popup, arglist, 2);
1101 
1102     /* Putem up */
1103     DManageChild (trace->examine.rowcol, trace, MC_GLOBALKEYS);
1104     XtPopup (trace->examine.popup, XtGrabNone); /* Don't manage! */
1105 
1106     /* Make sure we find out when button gets released */
1107     XSelectInput (XtDisplay (trace->work),XtWindow (trace->examine.popup),
1108 		 ButtonReleaseMask|PointerMotionMask|StructureNotifyMask|ExposureMask);
1109 
1110     /* We definately shouldn't have to force exposure of the popup. */
1111     /* However, the reality is lessTif doesn't seem to draw the text unless we do */
1112     /* This is a unknown bug in lessTif; it works fine on the true Motif */
1113     (xmRowColumnClassRec.core_class.expose) (trace->examine.rowcol, (XEvent*) ev, NULL);
1114     (xmLabelClassRec.core_class.expose) (trace->examine.label, (XEvent*) ev, NULL);
1115 }
1116 
val_examine_ev(Widget w,Trace_t * trace,XButtonPressedEvent * ev)1117 void    val_examine_ev (
1118     Widget		w,
1119     Trace_t		*trace,
1120     XButtonPressedEvent	*ev)
1121 {
1122     XEvent	event;
1123     XButtonPressedEvent *em;
1124     int		update_pending = FALSE;
1125 
1126     if (DTPRINT_ENTRY) printf ("In val_examine_ev, button=%d state=%d\n", ev->button, ev->state);
1127     if (ev->type != ButtonPress) return;	/* Used for both button 1 & 2. */
1128 
1129     /* not sure why this has to be done but it must be done */
1130     XSync (global->display, FALSE);
1131     XUngrabPointer (XtDisplay (trace->work),CurrentTime);
1132 
1133     /* select the events the widget will respond to */
1134     XSelectInput (XtDisplay (trace->work),XtWindow (trace->work),
1135 		 ButtonReleaseMask|PointerMotionMask|StructureNotifyMask|ExposureMask);
1136 
1137     /* Create */
1138     val_examine_popup (trace, ev);
1139 
1140     /* loop and service events until button is released */
1141     while ( 1 ) {
1142 	/* wait for next event */
1143 	XNextEvent (global->display, &event);
1144 	/* if (DTPRINT) { printf ("[ExEvent %s] ", events[ev->type]);fflush(stdout); } */
1145 
1146 	/* Mark an update as needed */
1147 	if (event.type == MotionNotify) {
1148 	    update_pending = TRUE;
1149 	}
1150 
1151 	/* if window was exposed, must redraw it */
1152 	if (event.type == Expose) win_expose_cb (0,trace);
1153 	/* if window was resized, must redraw it */
1154 	if (event.type == ConfigureNotify) win_resize_cb (0,trace);
1155 
1156 	/* button released - calculate cursor position and leave the loop */
1157 	if (event.type == ButtonRelease || event.type == ButtonPress) {
1158 	    /* ButtonPress in case user is freaking out, some strange X behavior caused the ButtonRelease to be lost */
1159 	    break;
1160 	}
1161 
1162 	/* If a update is needed, redraw the menu. */
1163 	/* Do it later if events pending, otherwise dragging is SLOWWWW */
1164 	if (update_pending && !XPending (global->display)) {
1165 	    update_pending = FALSE;
1166 	    em = (XButtonPressedEvent *)&event;
1167 	    val_examine_popup (trace, em);
1168 	}
1169 
1170 	if (global->redraw_needed && !XtAppPending (global->appcontext)) {
1171 	    draw_perform();
1172 	}
1173     }
1174 
1175     /* reset the events the widget will respond to */
1176     XSync (global->display, FALSE);
1177     XSelectInput (XtDisplay (trace->work),XtWindow (trace->work),
1178 		 ButtonPressMask|StructureNotifyMask|ExposureMask);
1179 
1180     /* unmanage popup */
1181     val_examine_popdown (trace);
1182     draw_needed (trace);
1183 }
1184 
val_examine_popup_act(Widget w,XButtonPressedEvent * ev,String params,Cardinal * num_params)1185 void    val_examine_popup_act (
1186     Widget		w,
1187     XButtonPressedEvent	*ev,
1188     String		params,
1189     Cardinal		*num_params)
1190 {
1191     Trace_t	*trace;		/* Display information */
1192     int		prev_cursor;
1193 
1194     if (ev->type != ButtonPress) return;
1195 
1196     if (DTPRINT_ENTRY) printf ("In val_examine_popup_ev, button=%d state=%d\n", ev->button, ev->state);
1197 
1198     if (!(trace = widget_to_trace (w))) return;
1199 
1200     /* Create */
1201     prev_cursor = last_set_cursor ();
1202     set_cursor (DC_VAL_EXAM);
1203 
1204     val_examine_ev (w, trace, ev);
1205 
1206     set_cursor (prev_cursor);
1207 }
1208 
val_search_widget_update(Trace_t * trace)1209 static void    val_search_widget_update (
1210     Trace_t	*trace)
1211 {
1212     VSearchNum_t search_pos;
1213     char	strg[MAXVALUELEN];
1214 
1215     /* Copy settings to local area to allow cancel to work */
1216     for (search_pos=0; search_pos<MAX_SRCH; search_pos++) {
1217 	ValSearch_t *vs_ptr = &global->val_srch[search_pos];
1218 
1219 	/* Update with current search enables */
1220 	XtSetArg (arglist[0], XmNset, (vs_ptr->color != 0));
1221 	XtSetValues (trace->value.enable[search_pos], arglist, 1);
1222 
1223 	/* Update with current cursor enables */
1224 	XtSetArg (arglist[0], XmNset, (vs_ptr->cursor != 0));
1225 	XtSetValues (trace->value.cursor[search_pos], arglist, 1);
1226 
1227 	/* Update with current search values */
1228 	val_to_string (vs_ptr->radix, strg, &vs_ptr->value, 0, FALSE, TRUE);
1229 	XmTextSetString (trace->value.text[search_pos], strg);
1230 
1231 	/* Update with current signal values */
1232 	XmTextSetString (trace->value.signal[search_pos], vs_ptr->signal);
1233     }
1234 }
1235 
val_search_cb(Widget w)1236 void    val_search_cb (
1237     Widget	w)
1238 {
1239     Trace_t *trace = widget_to_trace(w);
1240     int		i;
1241 
1242     if (DTPRINT_ENTRY) printf ("In val_search_cb - trace=%p\n",trace);
1243 
1244     if (!trace->value.dialog) {
1245 	XtSetArg (arglist[0], XmNdefaultPosition, TRUE);
1246 	XtSetArg (arglist[1], XmNdialogTitle, XmStringCreateSimple ("Value Search Requester") );
1247 	XtSetArg (arglist[2], XmNverticalSpacing, 7);
1248 	XtSetArg (arglist[3], XmNhorizontalSpacing, 10);
1249 	trace->value.dialog = XmCreateFormDialog (trace->work,"search",arglist,4);
1250 
1251 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("Color"));
1252 	XtSetArg (arglist[1], XmNleftAttachment, XmATTACH_FORM );
1253 	XtSetArg (arglist[2], XmNtopAttachment, XmATTACH_FORM );
1254 	trace->value.label1 = XmCreateLabel (trace->value.dialog,"label1",arglist,3);
1255 	DManageChild (trace->value.label1, trace, MC_NOKEYS);
1256 
1257 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("Place"));
1258 	XtSetArg (arglist[1], XmNleftAttachment, XmATTACH_WIDGET );
1259 	XtSetArg (arglist[2], XmNleftWidget, trace->value.label1);
1260 	XtSetArg (arglist[3], XmNtopAttachment, XmATTACH_FORM );
1261 	trace->value.label2 = XmCreateLabel (trace->value.dialog,"label2",arglist,4);
1262 	DManageChild (trace->value.label2, trace, MC_NOKEYS);
1263 
1264 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("Value"));
1265 	XtSetArg (arglist[1], XmNleftAttachment, XmATTACH_FORM );
1266 	XtSetArg (arglist[2], XmNtopAttachment, XmATTACH_WIDGET );
1267 	XtSetArg (arglist[3], XmNtopWidget, trace->value.label1);
1268 	trace->value.label4 = XmCreateLabel (trace->value.dialog,"label4",arglist,4);
1269 	DManageChild (trace->value.label4, trace, MC_NOKEYS);
1270 
1271 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("Cursor"));
1272 	XtSetArg (arglist[1], XmNleftAttachment, XmATTACH_WIDGET );
1273 	XtSetArg (arglist[2], XmNleftWidget, trace->value.label4);
1274 	XtSetArg (arglist[3], XmNtopAttachment, XmATTACH_WIDGET );
1275 	XtSetArg (arglist[4], XmNtopWidget, trace->value.label2);
1276 	trace->value.label5 = XmCreateLabel (trace->value.dialog,"label5",arglist,5);
1277 	DManageChild (trace->value.label5, trace, MC_NOKEYS);
1278 
1279 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple (
1280 	    "Search value, Hex default, 'd=decimal, 'b=binary"));
1281 	XtSetArg (arglist[1], XmNleftAttachment, XmATTACH_WIDGET );
1282 	XtSetArg (arglist[2], XmNleftWidget, trace->value.label5);
1283 	XtSetArg (arglist[3], XmNtopAttachment, XmATTACH_WIDGET );
1284 	XtSetArg (arglist[4], XmNtopWidget, trace->value.label1);
1285 	trace->value.label3 = XmCreateLabel (trace->value.dialog,"label3",arglist,5);
1286 	DManageChild (trace->value.label3, trace, MC_NOKEYS);
1287 
1288 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("Signal Wildcard"));
1289 	XtSetArg (arglist[1], XmNrightAttachment, XmATTACH_FORM);
1290 	XtSetArg (arglist[2], XmNtopAttachment, XmATTACH_WIDGET );
1291 	XtSetArg (arglist[3], XmNtopWidget, trace->value.label1);
1292 	trace->value.label6 = XmCreateLabel (trace->value.dialog,"label6",arglist,4);
1293 	DManageChild (trace->value.label6, trace, MC_NOKEYS);
1294 
1295 	for (i=0; i<MAX_SRCH; i++) {
1296 	    /* enable button */
1297 	    XtSetArg (arglist[0], XmNleftAttachment, XmATTACH_FORM);
1298 	    XtSetArg (arglist[1], XmNselectColor, trace->xcolornums[i+1]);
1299 	    XtSetArg (arglist[2], XmNlabelString, XmStringCreateSimple (" "));
1300 	    XtSetArg (arglist[3], XmNtopAttachment, XmATTACH_WIDGET );
1301 	    XtSetArg (arglist[4], XmNtopWidget, ((i==0)?(trace->value.label4):(trace->value.signal[i-1])));
1302 	    trace->value.enable[i] = XmCreateToggleButton (trace->value.dialog,"togglen",arglist,5);
1303 	    DManageChild (trace->value.enable[i], trace, MC_NOKEYS);
1304 
1305 	    /* enable button */
1306 	    XtSetArg (arglist[0], XmNselectColor, trace->xcolornums[i+1]);
1307 	    XtSetArg (arglist[1], XmNlabelString, XmStringCreateSimple (" "));
1308 	    XtSetArg (arglist[2], XmNtopAttachment, XmATTACH_WIDGET );
1309 	    XtSetArg (arglist[3], XmNtopWidget, ((i==0)?(trace->value.label4):(trace->value.signal[i-1])));
1310 	    XtSetArg (arglist[4], XmNleftAttachment, XmATTACH_WIDGET );
1311 	    XtSetArg (arglist[5], XmNleftWidget, trace->value.enable[i]);
1312 	    trace->value.cursor[i] = XmCreateToggleButton (trace->value.dialog,"cursorn",arglist,6);
1313 	    DManageChild (trace->value.cursor[i], trace, MC_NOKEYS);
1314 
1315 	    /* create the file name text widget */
1316 	    XtSetArg (arglist[0], XmNrows, 1);
1317 	    XtSetArg (arglist[1], XmNcolumns, MAXVALUELEN);
1318 	    XtSetArg (arglist[2], XmNresizeHeight, FALSE);
1319 	    XtSetArg (arglist[3], XmNeditMode, XmSINGLE_LINE_EDIT);
1320 	    XtSetArg (arglist[4], XmNtopAttachment, XmATTACH_WIDGET );
1321 	    XtSetArg (arglist[5], XmNtopWidget, ((i==0)?(trace->value.label4):(trace->value.signal[i-1])));
1322 	    XtSetArg (arglist[6], XmNleftAttachment, XmATTACH_WIDGET );
1323 	    XtSetArg (arglist[7], XmNleftOffset, 20);
1324 	    XtSetArg (arglist[8], XmNleftWidget, trace->value.cursor[i]);
1325 	    trace->value.text[i] = XmCreateText (trace->value.dialog,"textn",arglist,9);
1326 	    DAddCallback (trace->value.text[i], XmNactivateCallback, val_search_ok_cb, trace);
1327 	    DManageChild (trace->value.text[i], trace, MC_NOKEYS);
1328 
1329 	    /* create the signal text widget */
1330 	    XtSetArg (arglist[0], XmNrows, 1);
1331 	    XtSetArg (arglist[1], XmNcolumns, 30);
1332 	    XtSetArg (arglist[2], XmNresizeHeight, FALSE);
1333 	    XtSetArg (arglist[3], XmNeditMode, XmSINGLE_LINE_EDIT);
1334 	    XtSetArg (arglist[4], XmNtopAttachment, XmATTACH_WIDGET );
1335 	    XtSetArg (arglist[5], XmNtopWidget, ((i==0)?(trace->value.label4):(trace->value.signal[i-1])));
1336 	    XtSetArg (arglist[6], XmNleftAttachment, XmATTACH_WIDGET );
1337 	    XtSetArg (arglist[7], XmNleftOffset, 20);
1338 	    XtSetArg (arglist[8], XmNleftWidget, trace->value.text[i]);
1339 	    XtSetArg (arglist[9], XmNrightAttachment, XmATTACH_FORM );
1340 	    trace->value.signal[i] = XmCreateText (trace->value.dialog,"texts",arglist,10);
1341 	    DAddCallback (trace->value.signal[i], XmNactivateCallback, val_search_ok_cb, trace);
1342 	    DManageChild (trace->value.signal[i], trace, MC_NOKEYS);
1343 	}
1344 
1345 	/* Ok/apply/cancel */
1346 	ok_apply_cancel (&trace->value.okapply, trace->value.dialog,
1347 			 dmanage_last,
1348 			 (XtCallbackProc)val_search_ok_cb, trace,
1349 			 (XtCallbackProc)val_search_apply_cb, trace,
1350 			 NULL,NULL,
1351 			 (XtCallbackProc)unmanage_cb, (Trace_t*)trace->value.dialog);
1352     }
1353 
1354     /* Copy settings to local area to allow cancel to work */
1355     val_search_widget_update (trace);
1356 
1357     /* manage the popup on the screen */
1358     DManageChild (trace->value.dialog, trace, MC_NOKEYS);
1359 }
1360 
val_search_ok_cb(Widget w,Trace_t * trace,XmSelectionBoxCallbackStruct * cb)1361 void    val_search_ok_cb (
1362     Widget	w,
1363     Trace_t	*trace,
1364     XmSelectionBoxCallbackStruct *cb)
1365 {
1366     char	*strg;
1367     int		i;
1368     char	origstrg[MAXVALUELEN];
1369 
1370     if (DTPRINT_ENTRY) printf ("In val_search_ok_cb - trace=%p\n",trace);
1371 
1372     for (i=0; i<MAX_SRCH; i++) {
1373 	ValSearch_t *vs_ptr = &global->val_srch[i];
1374 
1375 	/* Update with current search enables */
1376 	vs_ptr->color = (XmToggleButtonGetState (trace->value.enable[i])) ? i+1 : 0;
1377 
1378 	/* Update with current cursor enables */
1379 	vs_ptr->cursor = (XmToggleButtonGetState (trace->value.cursor[i])) ? i+1 : 0;
1380 
1381 	/* Update with current search values */
1382 	val_to_string (vs_ptr->radix, origstrg, &vs_ptr->value, 0, FALSE, TRUE);
1383 	strg = XmTextGetString (trace->value.text[i]);
1384 	if (strcmp (origstrg, strg)) {
1385 	    /* Only update if it has changed, so that a search for a pattern */
1386 	    /* of X & U's won't disappear when rendered as a simple "X" string */
1387 	    string_to_value (&vs_ptr->radix, strg, &vs_ptr->value);
1388 	}
1389 
1390 	/* Update with current search values */
1391 	strg = XmTextGetString (trace->value.signal[i]);
1392 	strcpy (vs_ptr->signal, strg);
1393 
1394 	if (DTPRINT_SEARCH) {
1395 	    char strg2[MAXVALUELEN];
1396 	    val_to_string (global->radixs[0], strg2, &vs_ptr->value, 0, FALSE, TRUE);
1397 	    printf ("Search %d) %d  %s  '%s' -> '%s'\n", i, vs_ptr->color,
1398 		    vs_ptr->radix->name, strg, strg2);
1399 	}
1400     }
1401 
1402     XtUnmanageChild (trace->value.dialog);
1403 
1404     draw_needupd_val_search ();
1405     draw_all_needed ();
1406 }
1407 
val_search_apply_cb(Widget w,Trace_t * trace,XmSelectionBoxCallbackStruct * cb)1408 void    val_search_apply_cb (
1409     Widget	w,
1410     Trace_t	*trace,
1411     XmSelectionBoxCallbackStruct *cb)
1412 {
1413     if (DTPRINT_ENTRY) printf ("In val_search_apply_cb - trace=%p\n",trace);
1414 
1415     val_search_ok_cb (w,trace,cb);
1416     val_search_cb (trace->main);
1417 }
1418 
val_highlight_ev(Widget w,Trace_t * trace,XButtonPressedEvent * ev)1419 void    val_highlight_ev (
1420     Widget	w,
1421     Trace_t	*trace,
1422     XButtonPressedEvent	*ev)
1423 {
1424     DTime_t	time;
1425     Signal_t	*sig_ptr;
1426     Value_t	*cptr;
1427 
1428     if (DTPRINT_ENTRY) printf ("In val_highlight_ev - trace=%p\n",trace);
1429     if (ev->type != ButtonPress || ev->button!=1) return;
1430 
1431     time = posx_to_time (trace, ev->x);
1432     sig_ptr = posy_to_signal (trace, ev->y);
1433     if (!sig_ptr && time<=0) return;
1434     cptr = value_at_time (sig_ptr, time);
1435     if (!cptr) return;
1436 
1437     /* Change the color */
1438     if (global->highlight_color > 0) {
1439 	ValSearch_t *vs_ptr = &global->val_srch[global->highlight_color - 1];
1440 
1441 	val_copy (&vs_ptr->value, cptr);
1442 	vs_ptr->radix = sig_ptr->radix;
1443 	strcpy (vs_ptr->signal, sig_ptr->signame);
1444 	if (!vs_ptr->color && !vs_ptr->cursor ) {
1445 	    /* presume user really wants color if neither is on */
1446 	    vs_ptr->color = global->highlight_color;
1447 	    vs_ptr->cursor = global->highlight_color;
1448 	}
1449     }
1450 
1451     /* If search requester is on the screen, update it too */
1452     if (trace->value.dialog && XtIsManaged (trace->value.dialog)) {
1453 	val_search_widget_update (trace);
1454     }
1455 
1456     /* redraw the screen */
1457     draw_needupd_val_search ();
1458     draw_all_needed ();
1459 }
1460 
1461 
1462 /****************************** ANNOTATION ******************************/
1463 
val_annotate_cb(Widget w)1464 void    val_annotate_cb (
1465     Widget	w)
1466 {
1467     Trace_t *trace = widget_to_trace(w);
1468     Widget last;
1469     int i;
1470 
1471     if (DTPRINT_ENTRY) printf ("In val_annotate_cb - trace=%p\n",trace);
1472 
1473     if (!trace->annotate.dialog) {
1474 	XtSetArg (arglist[0], XmNdefaultPosition, TRUE);
1475 	XtSetArg (arglist[1], XmNdialogTitle, XmStringCreateSimple ("Annotate Menu"));
1476 	XtSetArg (arglist[2], XmNverticalSpacing, 7);
1477 	XtSetArg (arglist[3], XmNhorizontalSpacing, 10);
1478 	trace->annotate.dialog = XmCreateFormDialog (trace->work, "annotate",arglist,4);
1479 
1480 	/* create label widget for text widget */
1481 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("File Name") );
1482 	XtSetArg (arglist[1], XmNleftAttachment, XmATTACH_FORM );
1483 	XtSetArg (arglist[2], XmNtopAttachment, XmATTACH_FORM );
1484 	trace->annotate.label1 = XmCreateLabel (trace->annotate.dialog,"l1",arglist,3);
1485 	DManageChild (trace->annotate.label1, trace, MC_NOKEYS);
1486 
1487 	/* create the file name text widget */
1488 	XtSetArg (arglist[0], XmNrows, 1);
1489 	XtSetArg (arglist[1], XmNcolumns, 30);
1490 	XtSetArg (arglist[2], XmNleftAttachment, XmATTACH_FORM );
1491 	XtSetArg (arglist[3], XmNrightAttachment, XmATTACH_FORM );
1492 	XtSetArg (arglist[4], XmNtopAttachment, XmATTACH_WIDGET );
1493 	XtSetArg (arglist[5], XmNtopWidget, dmanage_last );
1494 	XtSetArg (arglist[6], XmNresizeHeight, FALSE);
1495 	XtSetArg (arglist[7], XmNeditMode, XmSINGLE_LINE_EDIT);
1496 	trace->annotate.text = XmCreateText (trace->annotate.dialog,"filename",arglist,8);
1497 	DManageChild (trace->annotate.text, trace, MC_NOKEYS);
1498 	DAddCallback (trace->annotate.text, XmNactivateCallback, val_annotate_ok_cb, trace);
1499 
1500 	/* Cursor enables */
1501 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("Include which user (solid) cursor colors:") );
1502 	XtSetArg (arglist[1], XmNleftAttachment, XmATTACH_FORM );
1503 	XtSetArg (arglist[2], XmNtopAttachment, XmATTACH_WIDGET );
1504 	XtSetArg (arglist[3], XmNtopWidget, dmanage_last );
1505 	trace->annotate.label2 = XmCreateLabel (trace->annotate.dialog,"l2",arglist,4);
1506 	DManageChild (trace->annotate.label2, trace, MC_NOKEYS);
1507 
1508 	last = trace->annotate.dialog;
1509 	for (i=0; i<=MAX_SRCH; i++) {
1510 	    /* enable button */
1511 	    XtSetArg (arglist[0], XmNx, 15+30*i);
1512 	    XtSetArg (arglist[1], XmNtopAttachment, XmATTACH_WIDGET );
1513 	    XtSetArg (arglist[2], XmNtopWidget, trace->annotate.label2 );
1514 	    XtSetArg (arglist[3], XmNselectColor, trace->xcolornums[i]);
1515 	    XtSetArg (arglist[4], XmNlabelString, XmStringCreateSimple (" "));
1516 	    trace->annotate.cursors[i] = XmCreateToggleButton (trace->annotate.dialog,"togglenc",arglist,5);
1517 	    DManageChild (trace->annotate.cursors[i], trace, MC_NOKEYS);
1518 	    last = trace->annotate.cursors[i];
1519 	}
1520 
1521 	/* Cursor enables */
1522 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("Include which auto (dotted) cursor colors:") );
1523 	XtSetArg (arglist[1], XmNleftAttachment, XmATTACH_FORM );
1524 	XtSetArg (arglist[2], XmNtopAttachment, XmATTACH_WIDGET );
1525 	XtSetArg (arglist[3], XmNtopWidget, trace->annotate.cursors[0] );
1526 	trace->annotate.label4 = XmCreateLabel (trace->annotate.dialog,"l4",arglist,4);
1527 	DManageChild (trace->annotate.label4, trace, MC_NOKEYS);
1528 
1529 	for (i=0; i<=MAX_SRCH; i++) {
1530 	    /* enable button */
1531 	    XtSetArg (arglist[0], XmNx, 15+30*i);
1532 	    XtSetArg (arglist[1], XmNtopAttachment, XmATTACH_WIDGET );
1533 	    XtSetArg (arglist[2], XmNtopWidget, trace->annotate.label4 );
1534 	    XtSetArg (arglist[3], XmNselectColor, trace->xcolornums[i]);
1535 	    XtSetArg (arglist[4], XmNlabelString, XmStringCreateSimple (" "));
1536 	    trace->annotate.cursors_dotted[i] = XmCreateToggleButton (trace->annotate.dialog,"togglencd",arglist,5);
1537 	    DManageChild (trace->annotate.cursors_dotted[i], trace, MC_NOKEYS);
1538 	}
1539 
1540 	/* Signal Enables */
1541 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("Include which signal colors:") );
1542 	XtSetArg (arglist[1], XmNleftAttachment, XmATTACH_FORM );
1543 	XtSetArg (arglist[2], XmNtopAttachment, XmATTACH_WIDGET );
1544 	XtSetArg (arglist[3], XmNtopWidget, trace->annotate.cursors_dotted[0] );
1545 	trace->annotate.label3 = XmCreateLabel (trace->annotate.dialog,"",arglist,4);
1546 	DManageChild (trace->annotate.label3, trace, MC_NOKEYS);
1547 
1548 	for (i=1; i<=MAX_SRCH; i++) {
1549 	    /* enable button */
1550 	    XtSetArg (arglist[0], XmNx, 15+30*i);
1551 	    XtSetArg (arglist[1], XmNtopAttachment, XmATTACH_WIDGET );
1552 	    XtSetArg (arglist[2], XmNtopWidget, trace->annotate.label3 );
1553 	    XtSetArg (arglist[3], XmNselectColor, trace->xcolornums[i]);
1554 	    XtSetArg (arglist[4], XmNlabelString, XmStringCreateSimple (" "));
1555 	    trace->annotate.signals[i] = XmCreateToggleButton (trace->annotate.dialog,"togglen",arglist,5);
1556 	    DManageChild (trace->annotate.signals[i], trace, MC_NOKEYS);
1557 	}
1558 
1559 	/* Label */
1560 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("Include signals from:") );
1561 	XtSetArg (arglist[1], XmNleftAttachment, XmATTACH_FORM );
1562 	XtSetArg (arglist[2], XmNtopAttachment, XmATTACH_WIDGET );
1563 	XtSetArg (arglist[3], XmNtopWidget, trace->annotate.signals[1]);
1564 	trace->annotate.trace_label = XmCreateLabel (trace->annotate.dialog,"",arglist,4);
1565 	DManageChild (trace->annotate.trace_label, trace, MC_NOKEYS);
1566 
1567 	/* Begin pulldown */
1568 	trace->annotate.trace_pulldown = XmCreatePulldownMenu (trace->annotate.dialog,"trace_pulldown",arglist,0);
1569 
1570 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("All Traces & Deleted") );
1571 	trace->annotate.trace_button[TRACESEL_ALLDEL] =
1572 	    XmCreatePushButtonGadget (trace->annotate.trace_pulldown,"pdbutton2",arglist,1);
1573 	DManageChild (trace->annotate.trace_button[TRACESEL_ALLDEL], trace, MC_NOKEYS);
1574 
1575 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("All Traces") );
1576 	trace->annotate.trace_button[TRACESEL_ALL] =
1577 	    XmCreatePushButtonGadget (trace->annotate.trace_pulldown,"pdbutton1",arglist,1);
1578 	DManageChild (trace->annotate.trace_button[TRACESEL_ALL], trace, MC_NOKEYS);
1579 
1580 	XtSetArg (arglist[0], XmNlabelString, XmStringCreateSimple ("This Trace") );
1581 	trace->annotate.trace_button[TRACESEL_THIS] =
1582 	    XmCreatePushButtonGadget (trace->annotate.trace_pulldown,"pdbutton0",arglist,1);
1583 	DManageChild (trace->annotate.trace_button[TRACESEL_THIS], trace, MC_NOKEYS);
1584 
1585 	XtSetArg (arglist[0], XmNsubMenuId, trace->annotate.trace_pulldown);
1586 	XtSetArg (arglist[1], XmNtopAttachment, XmATTACH_WIDGET );
1587 	XtSetArg (arglist[2], XmNtopWidget, trace->annotate.trace_label );
1588 	XtSetArg (arglist[3], XmNleftAttachment, XmATTACH_FORM );
1589 	trace->annotate.trace_option = XmCreateOptionMenu (trace->annotate.dialog,"options",arglist,4);
1590 	DManageChild (trace->annotate.trace_option, trace, MC_NOKEYS);
1591 
1592 	/* Ok/apply/cancel */
1593 	ok_apply_cancel (&trace->annotate.okapply, trace->annotate.dialog,
1594 			 dmanage_last,
1595 			 (XtCallbackProc)val_annotate_ok_cb, trace,
1596 			 (XtCallbackProc)val_annotate_apply_cb, trace,
1597 			 NULL,NULL,
1598 			 (XtCallbackProc)unmanage_cb, (Trace_t*)trace->annotate.dialog);
1599     }
1600 
1601     /* reset file name */
1602     XtSetArg (arglist[0], XmNvalue, global->anno_filename);
1603     XtSetValues (trace->annotate.text,arglist,1);
1604 
1605     /* Menu */
1606     XtSetArg (arglist[0], XmNmenuHistory,
1607 	      trace->annotate.trace_button[global->anno_traces]);
1608     XtSetValues (trace->annotate.trace_option, arglist, 1);
1609 
1610     /* reset enables */
1611     for (i=0; i<=MAX_SRCH; i++) {
1612 	XtSetArg (arglist[0], XmNset, (global->anno_ena_cursor[i] != 0));
1613 	XtSetValues (trace->annotate.cursors[i], arglist, 1);
1614 
1615 	XtSetArg (arglist[0], XmNset, (global->anno_ena_cursor_dotted[i] != 0));
1616 	XtSetValues (trace->annotate.cursors_dotted[i], arglist, 1);
1617     }
1618     for (i=1; i<=MAX_SRCH; i++) {
1619 	XtSetArg (arglist[0], XmNset, (global->anno_ena_signal[i] != 0));
1620 	XtSetValues (trace->annotate.signals[i], arglist, 1);
1621     }
1622 
1623     /* manage the popup on the screen */
1624     DManageChild (trace->annotate.dialog, trace, MC_NOKEYS);
1625 }
1626 
val_annotate_ok_cb(Widget w,Trace_t * trace,XmAnyCallbackStruct * cb)1627 void    val_annotate_ok_cb (
1628     Widget	w,
1629     Trace_t	*trace,
1630     XmAnyCallbackStruct *cb)
1631 {
1632     char	*strg;
1633     int		i;
1634     Widget	clicked;
1635 
1636     if (DTPRINT_ENTRY) printf ("In sig_search_ok_cb - trace=%p\n",trace);
1637 
1638     /* Update with current search enables */
1639     for (i=0; i<=MAX_SRCH; i++) {
1640 	global->anno_ena_cursor[i] = XmToggleButtonGetState (trace->annotate.cursors[i]);
1641 	global->anno_ena_cursor_dotted[i] = XmToggleButtonGetState (trace->annotate.cursors_dotted[i]);
1642     }
1643     for (i=1; i<=MAX_SRCH; i++) {
1644 	global->anno_ena_signal[i] = XmToggleButtonGetState (trace->annotate.signals[i]);
1645     }
1646 
1647     /* Update with current search values */
1648     strg = XmTextGetString (trace->annotate.text);
1649     strcpy (global->anno_filename, strg);
1650 
1651     XtSetArg (arglist[0], XmNmenuHistory, &clicked);
1652     XtGetValues (trace->annotate.trace_option, arglist, 1);
1653     for (i=0; i<3; i++) {
1654         if (clicked == trace->annotate.trace_button[i]) {
1655 	    global->anno_traces = (TraceSel_t)(i);
1656         }
1657     }
1658 
1659     global->anno_last_trace = trace;
1660 
1661     XtUnmanageChild (trace->annotate.dialog);
1662 
1663     val_annotate_do_cb (w,trace,cb);
1664 }
1665 
val_annotate_apply_cb(Widget w,Trace_t * trace,XmAnyCallbackStruct * cb)1666 void    val_annotate_apply_cb (
1667     Widget	w,
1668     Trace_t	*trace,
1669     XmAnyCallbackStruct	*cb)
1670 {
1671     if (DTPRINT_ENTRY) printf ("In sig_search_apply_cb - trace=%p\n",trace);
1672 
1673     val_annotate_ok_cb (w,trace,cb);
1674     val_annotate_cb (trace->main);
1675 }
1676 
val_print_quoted(FILE * fp,char * strg)1677 static void	val_print_quoted (
1678     FILE *fp,
1679     char *strg)
1680 {
1681     char *cp;
1682     for (cp=strg; *cp; cp++) {
1683 	if (*cp == '"') {
1684 	    fputc ('\\', fp);
1685 	}
1686 	fputc (*cp, fp);
1687     }
1688 }
1689 
val_annotate_do_cb(Widget w,Trace_t * trace,XmAnyCallbackStruct * cb)1690 void    val_annotate_do_cb (
1691     Widget	w,
1692     Trace_t	*trace,
1693     XmAnyCallbackStruct	*cb)
1694 {
1695     int		i;
1696     Signal_t	*sig_ptr;
1697     Trace_t	*trace_loop;
1698     Value_t	*cptr;
1699     FILE	*dump_fp;
1700     DCursor_t 	*csr_ptr;		/* Current cursor being printed */
1701     char	strg[1000];
1702     int		csr_num, csr_num_incl;
1703 
1704     if (DTPRINT_ENTRY) printf ("In val_annotate_cb - trace=%p  file=%s\n",trace,global->anno_filename);
1705 
1706     draw_update ();
1707 
1708     /* Socket connection */
1709 #if HAVE_SOCKETS
1710     socket_create ();
1711 #endif
1712 
1713     if (global->anno_last_trace == NULL) global->anno_last_trace = global->trace_head;
1714 
1715     if (! (dump_fp=fopen (global->anno_filename, "w"))) {
1716 	sprintf (message,"Bad Filename: %s\n", global->anno_filename);
1717 	dino_error_ack (trace,message);
1718 	return;
1719     }
1720 
1721     fprintf (dump_fp, "(setq dinotrace-program-version \"%s\")\n\n", DTVERSION);
1722 
1723     /* Socket info */
1724     if (!global->anno_socket[0] || strchr (global->anno_socket, '*') ) {
1725 	fprintf (dump_fp, "(setq dinotrace-socket-name nil)\n");
1726     }
1727     else {
1728 	fprintf (dump_fp, "(setq dinotrace-socket-name \"%s\")\n\n",
1729 		 global->anno_socket);
1730     }
1731 
1732     fprintf (dump_fp, "(setq dinotrace-hierarchy-separator \"%c\")\n\n",
1733 	     global->trace_head->dfile.hierarchy_separator);
1734 
1735     /* Trace info */
1736     fprintf (dump_fp, "(setq dinotrace-traces '(\n");
1737     for (trace = global->trace_head; trace; trace = trace->next_trace) {
1738 	if (trace->loaded) {
1739 	    fprintf (dump_fp, "	[\"%s\"\t\"%s\"]\n",
1740 		     trace->dfile.filename,
1741 		     date_string (trace->dfile.filestat.st_ctime));
1742 	}
1743     }
1744     fprintf (dump_fp, "\t))\n");
1745 
1746 #define colornum_to_name(_color_)  (((_color_)==0)?"":global->color_names[(_color_)])
1747     /* Cursor info */
1748     /* [time color-num color-name nil(font) note] */
1749     fprintf (dump_fp, "(setq dinotrace-cursors [\n");
1750     for (csr_ptr = global->cursor_head; csr_ptr; csr_ptr = csr_ptr->next) {
1751 	if ((csr_ptr->type==USER) ? global->anno_ena_cursor[csr_ptr->color] : global->anno_ena_cursor_dotted[csr_ptr->color] ) {
1752 	    time_to_string (global->trace_head, strg, csr_ptr->time, FALSE);
1753 	    fprintf (dump_fp, "\t[\"%s\"\t%d\t\"%s\"\tnil\t", strg,
1754 		     csr_ptr->color, colornum_to_name(csr_ptr->color));
1755 	    if (csr_ptr->note) fprintf (dump_fp, "\"%s\"", csr_ptr->note);
1756 	    else fprintf (dump_fp, "nil");
1757 	    fprintf (dump_fp, "]\n");
1758 	}
1759     }
1760     fprintf (dump_fp, "\t])\n");
1761 
1762     /* Value search info */
1763     /* [value color-num color-name] */
1764     fprintf (dump_fp, "(setq dinotrace-value-searches '(\n");
1765     for (i=1; i<=MAX_SRCH; i++) {
1766 	ValSearch_t *vs_ptr = &global->val_srch[i-1];
1767 	if (vs_ptr->color) {
1768 	    val_to_string (vs_ptr->radix, strg, &vs_ptr->value, 0, FALSE, FALSE);
1769 	    fprintf (dump_fp, "\t[\"");
1770 	    val_print_quoted (dump_fp, strg);
1771 	    fprintf (dump_fp, "\"\t%d\t\"%s\"]\n", i, colornum_to_name(i));
1772 	}
1773     }
1774     fprintf (dump_fp, "\t))\n");
1775 
1776     /* Signal color info */
1777     /* 0's never actually used, but needed in the array so aref will work in emacs */
1778     /* [color-num color-name] */
1779     fprintf (dump_fp, "(setq dinotrace-signal-colors [\n");
1780     for (i=0; i<=MAX_SRCH; i++) {
1781 	fprintf (dump_fp, "\t[%d\t\"%s\"\tnil]\n", i, (i==0 || !global->color_names[i])?"":global->color_names[i]);
1782     }
1783     fprintf (dump_fp, "\t])\n");
1784 
1785     /* Find number of cursors that will be included */
1786     csr_num_incl = 0;
1787     for (csr_ptr = global->cursor_head; csr_ptr; csr_ptr = csr_ptr->next) {
1788 	if ((csr_ptr->type==USER) ? global->anno_ena_cursor[csr_ptr->color] : global->anno_ena_cursor_dotted[csr_ptr->color] ) {
1789 	    csr_num_incl++;
1790 	}
1791     }
1792 
1793     /* Signal values */
1794     /* (basename [name color-num note values] nil(propertied)) */
1795     fprintf (dump_fp, "(setq dinotrace-signal-values '(\n");
1796     for (trace_loop = global->deleted_trace_head; trace_loop; trace_loop = trace_loop->next_trace) {
1797 	/* Process the deleted trace last, so visible values override deleted values */
1798 	trace = trace_loop->next_trace ? trace_loop->next_trace : global->deleted_trace_head;
1799         if ((   global->anno_traces == TRACESEL_THIS && trace!=global->anno_last_trace)
1800 	    || (global->anno_traces == TRACESEL_ALL && trace==global->deleted_trace_head)) {
1801 	    continue;
1802 	}
1803 
1804 	for (sig_ptr = trace->firstsig; sig_ptr; sig_ptr = sig_ptr->forward) {
1805 	    char *basename, *p;
1806 	    basename = strdup (sig_basename (trace, sig_ptr));
1807 	    p = strrchr (basename, '[');	/* Not vector_separator: it's standardized by here*/
1808 	    if (p) *p = '\0';
1809 	    fprintf (dump_fp, "\t(\"%s\"\t", basename);
1810 
1811 	    fprintf (dump_fp, "\t[\"%s\"\t", sig_ptr->signame);
1812 	    if (global->anno_ena_signal[sig_ptr->color]) fprintf (dump_fp, "%d\t", sig_ptr->color);
1813 	    else     fprintf (dump_fp, "nil\t");
1814 
1815 	    if (sig_ptr->note) fprintf (dump_fp, "\"%s\"\t", sig_ptr->note);
1816 	    else fprintf (dump_fp, "nil\t");
1817 
1818 	    fprintf (dump_fp, "(");
1819 	    csr_num=0;
1820 	    cptr = sig_ptr->cptr;
1821 	    for (csr_ptr = global->cursor_head; csr_ptr; csr_ptr = csr_ptr->next) {
1822 
1823 		if ((csr_ptr->type==USER) ? global->anno_ena_cursor[csr_ptr->color] : global->anno_ena_cursor_dotted[csr_ptr->color] ) {
1824 		    csr_num++;
1825 
1826 		    /* Note grabs value to right of cursor */
1827 		    while ( (CPTR_TIME(cptr) < csr_ptr->time)
1828 			    && (CPTR_TIME(cptr) != EOT)) {
1829 			cptr = CPTR_NEXT(cptr);
1830 		    }
1831 		    if ( (CPTR_TIME(cptr) > csr_ptr->time)
1832 			 && ( cptr > sig_ptr->bptr)) {
1833 			cptr = CPTR_PREV(cptr);
1834 		    }
1835 
1836 		    val_to_string (sig_ptr->radix, strg, cptr, sig_ptr->bits, FALSE, FALSE);
1837 
1838 		    /* First value must have `, last must have ', commas in middle */
1839 		    fprintf (dump_fp, "\"");
1840 		    if (csr_num==1) fprintf (dump_fp, "`");
1841 		    else  fprintf (dump_fp, ",");
1842 		    val_print_quoted (dump_fp, strg);
1843 		    if (csr_num==csr_num_incl) fprintf (dump_fp, "'");
1844 		    fprintf (dump_fp, "\"\t");
1845 		}
1846 	    }
1847 	    fprintf (dump_fp, ") nil])\n");
1848 	    free(basename);
1849 	}
1850     }
1851     fprintf (dump_fp, "\t))\n");
1852 
1853     fclose (dump_fp);
1854 }
1855 
1856