1 /******************************************************************************
2  * DESCRIPTION: Dinotrace source: cursor requestors, events, etc
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 "functions.h"
60 
61 #include <assert.h>
62 
63 /****************************** UTILITIES ******************************/
64 
cur_free(DCursor_t * csr_ptr)65 void    cur_free (
66     DCursor_t	*csr_ptr)	/* Cursor to remove */
67 {
68     DFree (csr_ptr->note);
69     DFree (csr_ptr);
70 }
71 
cur_remove(DCursor_t * csr_ptr)72 void    cur_remove (
73     /* Cursor is removed from list, but not freed! */
74     DCursor_t	*csr_ptr)	/* Cursor to remove */
75 {
76     DCursor_t	*next_csr_ptr, *prev_csr_ptr;
77 
78     if (DTPRINT_ENTRY) printf ("In cur_remove\n");
79 
80     /* redirect the next pointer */
81     prev_csr_ptr = csr_ptr->prev;
82     if (prev_csr_ptr) {
83 	prev_csr_ptr->next = csr_ptr->next;
84     }
85 
86     /* if not the last cursors redirect the prev pointer */
87     next_csr_ptr = csr_ptr->next;
88     if ( next_csr_ptr != NULL ) {
89 	next_csr_ptr->prev = csr_ptr->prev;
90     }
91 
92     /* if this is the first cursor, change the head */
93     if ( csr_ptr == global->cursor_head ) {
94         global->cursor_head = csr_ptr->next;
95     }
96 }
97 
cur_delete(DCursor_t * csr_ptr)98 void cur_delete (
99     DCursor_t *csr_ptr
100     )
101 {
102     if (csr_ptr->type == SIMVIEW) {
103 	/* Pass this event to SimView. */
104 	simview_cur_delete (csr_ptr->simview_id);
105     }
106 
107     /* Delete it, unless this is a SimView cursor and a SimView response will delete it. */
108     if (csr_ptr->type != SIMVIEW || global->simview_info_ptr->handshake == FALSE) {
109 	cur_remove (csr_ptr);
110 	cur_free (csr_ptr);
111     }
112 }
113 
cur_add(DTime_t ctime,ColorNum_t color,CursorType_t type,const char * note)114 DCursor_t *cur_add (
115     /* Add a cursor, or replace an existing one at the same time as long as neither is
116        a SIMVIEW type.  Return the new or conflicting cursor. */
117     DTime_t	ctime,
118     ColorNum_t	color,
119     CursorType_t	type,
120     const char *note)
121 {
122     DCursor_t *new_csr_ptr;
123     DCursor_t *prev_csr_ptr, *csr_ptr;
124 
125     if (DTPRINT_ENTRY) printf ("In cur_add - time=%d\n",ctime);
126 
127     /* No SIMVIEW cursors unless SimView is enabled. */
128     assert (type != SIMVIEW || global->simview_info_ptr);
129 
130     new_csr_ptr = DNewCalloc (DCursor_t);
131     new_csr_ptr->time = ctime;
132     new_csr_ptr->color = color;
133     new_csr_ptr->type = type;
134     if (note && note[0]) new_csr_ptr->note = strdup(note);
135 
136     prev_csr_ptr = NULL;
137     for (csr_ptr = global->cursor_head;
138 	 csr_ptr && ( csr_ptr->time < new_csr_ptr->time );
139 	 csr_ptr = csr_ptr->next) {
140 	prev_csr_ptr = csr_ptr;
141     }
142 
143     /* Same as an existing cursor?  SimView cursors may overlap others (is this ok?) */
144     if ((csr_ptr && csr_ptr->time == new_csr_ptr->time) &&
145         (new_csr_ptr->type != SIMVIEW && csr_ptr->type != SIMVIEW)) {
146         /* Do not create a new cursor */
147 	if ((new_csr_ptr->type == USER) || (csr_ptr->type != USER)) {
148 	    /* Auto over auto or user over user is OK */
149 	    csr_ptr->time = ctime;
150 	    csr_ptr->color = color;
151 	    csr_ptr->type = type;
152 	    if (note && note[0]) csr_ptr->note = strdup(note);
153 	}
154 	/* else Don't go over existing user one */
155 	/* Don't need new structure */
156 	cur_free (new_csr_ptr);
157         return (csr_ptr);
158     }
159     else {
160 	/* Insert into first position? */
161 	if (!prev_csr_ptr) {
162 	    global->cursor_head = new_csr_ptr;
163 	}
164 	else {
165 	    prev_csr_ptr->next = new_csr_ptr;
166 	}
167 
168 	new_csr_ptr->next = csr_ptr;
169 	new_csr_ptr->prev = prev_csr_ptr;
170 	if (csr_ptr) csr_ptr->prev = new_csr_ptr;
171         return (new_csr_ptr);
172     }
173 }
174 
175 /* Create new cursor and handle simview cursors */
cur_new(DTime_t ctime,ColorNum_t color,CursorType_t type,const char * note)176 void cur_new (
177     DTime_t ctime,
178     ColorNum_t color,
179     CursorType_t type,
180     const char *note
181     )
182 {
183     DCursor_t *csr_ptr;
184     static int simview_cur_id = 0;
185 
186     /* Add cursor, unless this is a SimView cursor, and a response from SimView will add it. */
187     if (type != SIMVIEW || global->simview_info_ptr->handshake == FALSE) {
188 	csr_ptr = cur_add (ctime, color, type, note);
189 	/* Set cursor's id. */
190 	if (type == SIMVIEW) {
191 	    csr_ptr->simview_id = simview_cur_id;
192 	}
193     }
194 
195     if (type == SIMVIEW) {
196 	/* Pass this event to SimView. */
197 	simview_cur_create (simview_cur_id, time_to_cyc_num(ctime), (int)color, global->color_names[color]);
198 	simview_cur_id++;
199     }
200 }
201 
cur_move(DCursor_t * csr_ptr,DTime_t new_time)202 void cur_move (
203     DCursor_t *csr_ptr,
204     DTime_t new_time
205     )
206 {
207     DCursor_t *new_csr_ptr;
208 
209     /* Don't move if this is a SimView cursor and a SimView response will move it. */
210     if (csr_ptr->type != SIMVIEW || global->simview_info_ptr->handshake == FALSE) {
211 
212 	/* Move by removing, and adding. */
213 	cur_remove (csr_ptr);
214 	new_csr_ptr = cur_add (new_time, csr_ptr->color, ((csr_ptr->type == SIMVIEW) ? SIMVIEW : USER), csr_ptr->note);
215 	if (csr_ptr->type == SIMVIEW) {
216 	    new_csr_ptr->simview_id = csr_ptr->simview_id;
217 	}
218 
219 	/* A SIMVIEW cursor is the one added if and only if it was intended to be added. */
220 	assert ((csr_ptr->type == SIMVIEW) ^ (new_csr_ptr->type != SIMVIEW));
221 
222 	cur_free (csr_ptr);
223     } else {
224 	new_csr_ptr = csr_ptr;
225     }
226     if (new_csr_ptr->type == SIMVIEW) {
227 	/* Pass this event to SimView. */
228 	simview_cur_move (new_csr_ptr->simview_id, time_to_cyc_num(new_time));
229     }
230 }
231 
232 
cur_note(DCursor_t * csr_ptr,const char * note)233 void    cur_note (
234     DCursor_t*		csr_ptr,
235     const char*		note)
236 {
237     DFree(csr_ptr->note);
238     csr_ptr->note = strdup(note);
239 }
240 
241 
cur_delete_of_type(CursorType_t type)242 void cur_delete_of_type (
243     CursorType_t	type)
244 {
245     DCursor_t	*csr_ptr,*new_csr_ptr;
246 
247     for (csr_ptr = global->cursor_head; csr_ptr; ) {
248 	new_csr_ptr = csr_ptr;
249 	csr_ptr = csr_ptr->next;
250 	if (new_csr_ptr->type==type) {
251 	    cur_delete (new_csr_ptr);
252 	}
253     }
254 }
255 
256 /* Get a SIMVIEW cursor by its id number. */
cur_id_to_cursor(int id)257 DCursor_t *cur_id_to_cursor (int id) {
258     DCursor_t *cur;
259 
260     cur = global->cursor_head;
261     while (cur && (cur->type != SIMVIEW || cur->simview_id != id)) {
262 	cur = cur->next;
263     }
264 
265     return (cur);
266 }
267 
cur_write(FILE * writefp,const char * c)268 void cur_write (FILE *writefp, const char *c)
269 {
270     DCursor_t	*csr_ptr;
271     char strg[MAXTIMELEN];
272 
273     for (csr_ptr = global->cursor_head; csr_ptr; csr_ptr = csr_ptr->next) {
274 	time_to_string (global->trace_head, strg, csr_ptr->time, FALSE);
275 	switch (csr_ptr->type) {
276 	case USER:
277 	    fprintf (writefp, "%scursor_add %s %d -user",c, strg, csr_ptr->color);
278 	    if (csr_ptr->note && csr_ptr->note[0]) fprintf (writefp, " \"%s\"", csr_ptr->note);
279 	    fprintf (writefp, "\n");
280 	    break;
281 	case CONFIG:
282 	    fprintf (writefp, "%scursor_add %s %d",c, strg, csr_ptr->color);
283 	    if (csr_ptr->note && csr_ptr->note[0]) fprintf (writefp, " \"%s\"", csr_ptr->note);
284 	    fprintf (writefp, "\n");
285 	    break;
286 	default:
287 	    break;
288 	}
289     }
290 }
291 
cur_time_first(const Trace_t * trace)292 DTime_t cur_time_first (
293     const Trace_t 	*trace)
294     /* Return time of the first cursor, or BOT if none */
295 {
296     DCursor_t	*csr_ptr;
297 
298     csr_ptr = global->cursor_head;
299     if (csr_ptr) {
300 	return (csr_ptr->time);
301     }
302     else {
303 	return (trace->start_time);
304     }
305 }
306 
cur_time_last(const Trace_t * trace)307 DTime_t cur_time_last (
308     const Trace_t 	*trace)
309     /* Return time of the last cursor, or EOT if none */
310 {
311     DCursor_t	*csr_ptr;
312 
313     for (csr_ptr = global->cursor_head; csr_ptr && csr_ptr->next; csr_ptr = csr_ptr->next) ;
314     if (csr_ptr) {
315 	return (csr_ptr->time);
316     }
317     else {
318 	return (trace->end_time);
319     }
320 }
321 
322 /* Used only by cur_step.  This steps one cursor.
323  * Only USER and SIMVIEW cursors are moved.
324  * (Note that SIMVIEW cursors may only notify SimView that a move is requested without
325  *  performing the move.) */
cur_step_one(DTime_t step,DCursor_t * csr_ptr)326 static void cur_step_one (
327     DTime_t       step,
328     DCursor_t     *csr_ptr
329     )
330 {
331     if (csr_ptr->type == USER || csr_ptr->type == SIMVIEW) {
332         if (step >= 0 || csr_ptr->time >= -step) {
333             cur_move (csr_ptr, csr_ptr->time + step);
334         } else {
335             cur_delete (csr_ptr);
336         }
337     }
338 }
339 
cur_step(DTime_t step)340 void cur_step (
341     DTime_t	step
342     )
343     /* Move all USER and SIMVIEW cursors the specified distance */
344 {
345     DCursor_t	*csr_ptr;
346     DCursor_t	*nxt_csr_ptr;
347 
348     /* Since the cursor list changes as we step through it, we step
349      * through it forward if cursors are moving back, and backward
350      * if cursors are moving forward.  This ensures that we hit
351      * every cursor exactly once.
352      */
353 
354     if (DTPRINT_ENTRY) printf ("In cur_step %d\n", step);
355 
356     if (step < 0) {
357         /* Step forward through cursors */
358         for (csr_ptr = global->cursor_head; csr_ptr; csr_ptr = nxt_csr_ptr) {
359 	    nxt_csr_ptr = csr_ptr->next;
360             cur_step_one (step, csr_ptr);
361         }
362     } else {
363         /* Step backward through cursors */
364         if (global->cursor_head) {
365             /* Find last cursor */
366             for (csr_ptr = global->cursor_head; csr_ptr->next; csr_ptr = csr_ptr->next) {
367             }
368             /* Step backward through cursors */
369             for (; csr_ptr; csr_ptr = nxt_csr_ptr) {
370                 nxt_csr_ptr = csr_ptr->prev;
371                 cur_step_one (step, csr_ptr);
372             }
373         }
374     }
375     draw_all_needed ();
376 }
377 
cur_highlight(DCursor_t * csr_ptr,ColorNum_t color)378 void cur_highlight (
379     /* Set the highlight color for a cursor.  Communicate the change to SimView if necessary. */
380     DCursor_t	*csr_ptr,
381     ColorNum_t      color
382     )
383 {
384     csr_ptr->color = color;
385 
386     if (csr_ptr->type == SIMVIEW) {
387 	/* Pass this event to SimView. (note that highlights are always */
388 	/* controlled by Dinotrace, not SimView, and no handshaking is done). */
389 	simview_cur_highlight (csr_ptr->simview_id, color, global->color_names[color]);
390     }
391 }
392 
393 /****************************** EXAMINE ******************************/
394 
cur_examine_string(Trace_t * trace,DCursor_t * csr_ptr)395 char *cur_examine_string (
396     /* Return string with examine information in it */
397     Trace_t	*trace,
398     DCursor_t	*csr_ptr)
399 {
400     static char	strg[2000];
401     char	strg2[2000];
402 
403     if (DTPRINT_ENTRY) printf ("val_examine_popup_csr_string\n");
404 
405     strcpy (strg, "Cursor at Time ");
406     time_to_string (trace, strg2, csr_ptr->time, FALSE);
407     strcat (strg, strg2);
408     strcat (strg, "\n");
409 
410     switch (csr_ptr->type) {
411     case USER:
412 	strcat (strg, "Placed by you\n");
413 	break;
414     case SEARCH:
415 	strcat (strg, "Placed by Value Search\n");
416 	break;
417     case CONFIG:
418 	strcat (strg, "Placed by .dino file or Emacs\n");
419 	break;
420     case SIMVIEW:
421 	strcat (strg, "Placed by simview\n");
422 	break;
423     case SEARCHOLD:
424 	break;
425     }
426     if (csr_ptr->note) {
427         strcat (strg, csr_ptr->note);
428         strcat (strg, "\n");
429     }
430     return (strg);
431 }
432 
433 
434 /****************************** MENU OPTIONS ******************************/
435 
cur_add_internal(Widget w,CursorType_t type,ColorNum_t colorOverride)436 static void    cur_add_internal (
437     Widget		w,
438     CursorType_t	type,
439     ColorNum_t		colorOverride
440     )
441 {
442     Trace_t *trace = widget_to_trace(w);
443     if (DTPRINT_ENTRY) printf ("In cur_add_internal - trace=%p\n",trace);
444 
445     global->selected_curtype = type;
446 
447     /* Grab color number from the menu button pointer */
448     global->highlight_color = submenu_to_color
449 	(trace, w, colorOverride,
450 	 (type == SIMVIEW) ? trace->menu.cur_add_simview_pds : trace->menu.cur_add_pds);
451 
452     /* process all subsequent button presses as cursor adds */
453     remove_all_events (trace);
454     set_cursor (DC_CUR_ADD);
455     add_event (ButtonPressMask, cur_add_ev);
456 }
457 
cur_add_cb(Widget w)458 void    cur_add_cb (
459     Widget		w)
460 {
461     cur_add_internal (w, USER, 0);
462 }
463 
cur_add_current_cb(Widget w)464 void    cur_add_current_cb (
465     Widget		w)
466 {
467     cur_add_internal (w, USER, COLOR_CURRENT);
468 }
469 
cur_add_next_cb(Widget w)470 void    cur_add_next_cb (
471     Widget		w)
472 {
473     cur_add_internal (w, USER, COLOR_NEXT);
474 }
475 
cur_add_simview_cb(Widget w)476 void    cur_add_simview_cb (
477     Widget		w)
478 {
479     cur_add_internal (w, SIMVIEW, 0);
480 }
481 
cur_mov_cb(Widget w)482 void    cur_mov_cb (
483     Widget		w)
484 {
485     Trace_t *trace = widget_to_trace(w);
486 
487     if (DTPRINT_ENTRY) printf ("In cur_mov_cb - trace=%p\n",trace);
488 
489     /* process all subsequent button presses as cursor moves */
490     remove_all_events (trace);
491     set_cursor (DC_CUR_MOVE);
492     add_event (ButtonPressMask, cur_move_ev);
493 }
494 
cur_del_cb(Widget w)495 void    cur_del_cb (
496     Widget		w)
497 {
498     Trace_t *trace = widget_to_trace(w);
499 
500     if (DTPRINT_ENTRY) printf ("In cur_del_cb - trace=%p\n",trace);
501 
502     /* process all subsequent button presses as cursor deletes */
503     remove_all_events (trace);
504     set_cursor (DC_CUR_DELETE);
505     add_event (ButtonPressMask, cur_delete_ev);
506 }
507 
cur_clr_cb(Widget w)508 void    cur_clr_cb (
509     Widget		w)
510 {
511     Trace_t *trace = widget_to_trace(w);
512     DCursor_t	*csr_ptr, *next;
513 
514     if (DTPRINT_ENTRY) printf ("In cur_clr_cb.\n");
515 
516     /* delete every cursor */
517     for (csr_ptr = global->cursor_head; csr_ptr != NULL; csr_ptr = next) {
518 	next = csr_ptr->next;
519 	cur_delete (csr_ptr);  /* Note, this may not delete the cursor if it is
520 				* a SimView cursor with handshaking. */
521     }
522 
523     /* cancel the button actions */
524     remove_all_events (trace);
525 
526     draw_all_needed ();
527 }
528 
cur_highlight_cb(Widget w)529 void    cur_highlight_cb (
530     Widget		w)
531 {
532     Trace_t *trace = widget_to_trace(w);
533     if (DTPRINT_ENTRY) printf ("In cur_highlight_cb - trace=%p\n",trace);
534 
535     /* Grab color number from the menu button pointer */
536     global->highlight_color = submenu_to_color (trace, w, 0, trace->menu.cur_highlight_pds);
537 
538     /* process all subsequent button presses as signal highlights */
539     remove_all_events (trace);
540     set_cursor (DC_CUR_HIGHLIGHT);
541     add_event (ButtonPressMask, cur_highlight_ev);
542 }
543 
cur_step_fwd_cb(Widget w)544 void    cur_step_fwd_cb (
545     Widget		w)
546 {
547     Trace_t *trace = widget_to_trace(w);
548     if (DTPRINT_ENTRY) printf ("In cur_step_fwd_cb.\n");
549     cur_step (grid_primary_period (trace));
550 }
551 
cur_step_back_cb(Widget w)552 void    cur_step_back_cb (
553     Widget		w)
554 {
555     Trace_t *trace = widget_to_trace(w);
556     if (DTPRINT_ENTRY) printf ("In cur_step_back_cb.\n");
557     cur_step ( - grid_primary_period (trace));
558 }
559 
cur_note_cb(Widget w)560 void    cur_note_cb (
561     Widget		w)
562 {
563     Trace_t *trace = widget_to_trace(w);
564 
565     if (DTPRINT_ENTRY) printf ("In cur_note_cb - trace=%p\n",trace);
566 
567     /* process all subsequent button presses as cursor moves */
568     remove_all_events (trace);
569     set_cursor (DC_CUR_NOTE);
570     add_event (ButtonPressMask, cur_note_ev);
571 }
572 
573 /****************************** EVENTS ******************************/
574 
cur_add_ev(Widget w,Trace_t * trace,XButtonPressedEvent * ev)575 void    cur_add_ev (
576     Widget		w,
577     Trace_t		*trace,
578     XButtonPressedEvent	*ev)
579 {
580     DTime_t	time;
581 
582     if (DTPRINT_ENTRY) printf ("In cur_add_ev - trace=%p x=%d y=%d\n",trace,ev->x,ev->y);
583     if (ev->type != ButtonPress || ev->button!=1) return;
584 
585     /* convert x value to a time value */
586     time = posx_to_time_edge (trace, ev->x, ev->y);
587     if (time<0) return;
588 
589     /* make the cursor */
590     cur_new (time, global->highlight_color, global->selected_curtype, NULL);
591 
592     draw_all_needed ();
593 }
594 
cur_move_ev(Widget w,Trace_t * trace,XButtonPressedEvent * ev)595 void    cur_move_ev (
596     Widget		w,
597     Trace_t		*trace,
598     XButtonPressedEvent	*ev)
599 {
600     DTime_t	time;
601     Position	x1,x2,y1,y2;
602     static	int last_x = 0;
603     XEvent	event;
604     DCursor_t	*csr_ptr;
605     XMotionEvent *em;
606     XButtonEvent *eb;
607 
608     if (DTPRINT_ENTRY) printf ("In cursor_mov\n");
609     if (ev->type != ButtonPress || ev->button!=1) return;
610 
611     csr_ptr = posx_to_cursor (trace, ev->x);
612     if (!csr_ptr) return;
613 
614     /* csr_ptr is the cursor to be moved - calculate starting x */
615     last_x = TIME_TO_XPOS (csr_ptr->time);
616 
617     /* not sure why this has to be done but it must be done */
618     XUngrabPointer (XtDisplay (trace->work),CurrentTime);
619 
620     /* select the events the widget will respond to */
621     XSelectInput (XtDisplay (trace->work),XtWindow (trace->work),
622 		 ButtonReleaseMask|PointerMotionMask|StructureNotifyMask|ExposureMask);
623 
624     /* change the GC function to drag the cursor */
625     xgcv.function = GXinvert;
626     XChangeGC (global->display,trace->gc,GCFunction,&xgcv);
627     XSync (global->display,0);
628 
629     /* draw the first line */
630     y1 = 25;
631     y2 = trace->height - trace->ystart + global->sighgt;
632     x1 = x2 = last_x = ev->x;
633     XDrawLine (global->display,trace->wind,trace->gc,x1,y1,x2,y2);
634 
635     /* loop and service events until button is released */
636     while ( 1 )
637 	{
638 	/* wait for next event */
639 	XNextEvent (XtDisplay (trace->work),&event);
640 
641 	/* if the pointer moved, erase previous line and draw new one */
642 	if (event.type == MotionNotify)
643 	    {
644 	    XSetForeground (global->display, trace->gc, trace->xcolornums[csr_ptr->color]);
645 	    em = (XMotionEvent *)&event;
646 	    x1 = x2 = last_x;
647 	    y1 = 25;
648 	    y2 = trace->height - trace->ystart + global->sighgt;
649 	    XDrawLine (global->display,trace->wind,trace->gc,x1,y1,x2,y2);
650 	    x1 = x2 = em->x;
651 	    XDrawLine (global->display,trace->wind,trace->gc,x1,y1,x2,y2);
652 	    last_x = em->x;
653 	    XSetForeground (global->display, trace->gc, trace->xcolornums[0]);
654 	    }
655 
656 	/* if window was exposed, must redraw it */
657 	if (event.type == Expose) win_expose_cb (0,trace);
658 	/* if window was resized, must redraw it */
659 	if (event.type == ConfigureNotify) win_resize_cb (0,trace);
660 
661 	/* button released - calculate cursor position and leave the loop */
662 	if (event.type == ButtonRelease || event.type == ButtonPress) {
663 	    /* ButtonPress in case user is freaking out, some strange X behavior caused the ButtonRelease to be lost */
664 	    eb = (XButtonReleasedEvent *)&event;
665 	    time = posx_to_time_edge (trace, eb->x, eb->y);
666 	    break;
667 	}
668 
669 	if (global->redraw_needed && !XtAppPending (global->appcontext)) {
670 	    /* change the GC function back to its default */
671 	    xgcv.function = GXcopy;
672 	    XChangeGC (global->display,trace->gc,GCFunction,&xgcv);
673 	    draw_perform();
674 	    /* change the GC function to drag the cursor */
675 	    xgcv.function = GXinvert;
676 	    XChangeGC (global->display,trace->gc,GCFunction,&xgcv);
677 	}
678 	}
679 
680     /* reset the events the widget will respond to */
681     XSelectInput (XtDisplay (trace->work),XtWindow (trace->work),
682 		 ButtonPressMask|StructureNotifyMask|ExposureMask);
683 
684     /* change the GC function back to its default */
685     xgcv.function = GXcopy;
686     XChangeGC (global->display,trace->gc,GCFunction,&xgcv);
687 
688     /* move the cursor */
689     cur_move (csr_ptr, time);
690 
691     draw_all_needed ();
692 }
693 
cur_delete_ev(Widget w,Trace_t * trace,XButtonPressedEvent * ev)694 void    cur_delete_ev (
695     Widget		w,
696     Trace_t		*trace,
697     XButtonPressedEvent	*ev)
698 {
699     DCursor_t	*csr_ptr;
700 
701     if (DTPRINT_ENTRY) printf ("In cur_delete_ev - trace=%p x=%d y=%d\n",trace,ev->x,ev->y);
702     if (ev->type != ButtonPress || ev->button!=1) return;
703 
704     csr_ptr = posx_to_cursor (trace, ev->x);
705     if (!csr_ptr) return;
706 
707     /* delete the cursor */
708     cur_delete (csr_ptr);
709 
710     draw_all_needed ();
711 }
712 
cur_highlight_ev(Widget w,Trace_t * trace,XButtonPressedEvent * ev)713 void    cur_highlight_ev (
714     Widget		w,
715     Trace_t		*trace,
716     XButtonPressedEvent	*ev)
717 {
718     DCursor_t	*csr_ptr;
719 
720     if (DTPRINT_ENTRY) printf ("In cur_highlight_ev - trace=%p x=%d y=%d\n",trace,ev->x,ev->y);
721     if (ev->type != ButtonPress || ev->button!=1) return;
722 
723     csr_ptr = posx_to_cursor (trace, ev->x);
724     if (!csr_ptr) return;
725 
726     /* change color */
727     cur_highlight (csr_ptr, global->highlight_color);
728 
729     draw_all_needed ();
730 }
731 
cur_note_ev(Widget w,Trace_t * trace,XButtonPressedEvent * ev)732 void    cur_note_ev (
733     Widget		w,
734     Trace_t		*trace,
735     XButtonPressedEvent	*ev)
736 {
737     DCursor_t	*csr_ptr;
738 
739     if (DTPRINT_ENTRY) printf ("In cur_note_ev - trace=%p x=%d y=%d\n",trace,ev->x,ev->y);
740     if (ev->type != ButtonPress || ev->button!=1) return;
741 
742     csr_ptr = posx_to_cursor (trace, ev->x);
743     if (!csr_ptr) return;
744 
745     /* change cursor note */
746     global->selected_cursor = csr_ptr;
747     win_note(trace, "Note for Cursor", "", csr_ptr->note, TRUE);
748 }
749 
750 /**********************************************************************/
751 /**********************************************************************/
752 /**********************************************************************/
753 /* Hooks for SimView */
754 /**********************************************************************/
755 
756 /* These hooks were added for a proprietary tool of Compaq Computer Corp. called SimView.
757  * The hooks may be useful for other tools that wish to be controlled by Dinotrace cursors.
758  */
759 
760 #if !HAVE_SIMVIEW
761 
762 /* Call at initialization when "-simview" arg is processed. */
simview_init(char * arg)763 void simview_init (char *arg) {
764     printf ("The SimView library is not available, \"-simview\" should not be used.\n");
765 }
766 /* Call when a simview cursor is created/moved/etc. */
simview_cur_create(int cur_num,double cyc_num,ColorNum_t color,char * color_name)767 void simview_cur_create (int cur_num, double cyc_num, ColorNum_t color, char *color_name) {}
simview_cur_move(int cur_num,double cyc_num)768 void simview_cur_move (int cur_num, double cyc_num) {}
simview_cur_highlight(int cur_num,ColorNum_t color,char * color_name)769 void simview_cur_highlight (int cur_num, ColorNum_t color, char *color_name) {}
simview_cur_delete(int cur_num)770 void simview_cur_delete (int cur_num) {}
771 
772 #endif
773