1 /*****************************************************************************
2  *
3  *  xdbx - X Window System interface to the dbx debugger
4  *
5  *  Copyright 1989 The University of Texas at Austin
6  *  Copyright 1990 Microelectronics and Computer Technology Corporation
7  *
8  *  Permission to use, copy, modify, and distribute this software and its
9  *  documentation for any purpose and without fee is hereby granted,
10  *  provided that the above copyright notice appear in all copies and that
11  *  both that copyright notice and this permission notice appear in
12  *  supporting documentation, and that the name of The University of Texas
13  *  and Microelectronics and Computer Technology Corporation (MCC) not be
14  *  used in advertising or publicity pertaining to distribution of
15  *  the software without specific, written prior permission.  The
16  *  University of Texas and MCC makes no representations about the
17  *  suitability of this software for any purpose.  It is provided "as is"
18  *  without express or implied warranty.
19  *
20  *  THE UNIVERSITY OF TEXAS AND MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO
21  *  THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
22  *  FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TEXAS OR MCC BE LIABLE FOR
23  *  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
24  *  RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
25  *  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
26  *  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27  *
28  *  Author:  	Po Cheung
29  *  Created:   	March 10, 1989
30  *
31  *****************************************************************************/
32 
33 /*  signs.c
34  *
35  *  This file contains all the routines for the creation and manipulation of
36  *  symbols used in xdbx.  There are 3 different signs:
37  *    arrow  - a solid right arrow to indicate the current execution point.
38  *    updown - an outlined right arrow to indicate position in stack trace.
39  *    stop   - a stop hand symbol to indicate a breakpoint is set.
40  *    bomb  - a bomb symbol to indicate the point of segmentation fault.
41  *
42  *  To display a sign on a given line in the source window, it is first
43  *  created and mapped.  To undisplay it, the sign is unmapped.  It can
44  *  be mapped again when the sign is needed.  Note that the sign is never
45  *  moved, so that there can be as many signs created (but not mapped) as
46  *  the number of lines in the source window.
47  *  For arrow and updown, there can be at most one of each mapped at a time.
48  *  For stop, there can be more than one mapped at the same time.
49  */
50 
51 #include "global.h"
52 #include "bitmaps.h"
53 
54 #define MAXSTOPS        256             /* max number of stops */
55 #define MAXSIGNS        256             /* max number of signs */
56 #define OFFSET	        2             	/* offset for displaying signs */
57 
58 typedef struct {
59     Widget      w;
60     Boolean     mapped;
61 } ArrowSign;
62 
63 typedef struct {
64     Widget      w;
65     Boolean     mapped;
66 } UpdownSign;
67 
68 typedef struct {
69     Widget      w;
70     Boolean     mapped;
71 } StopSign;
72 
73 typedef struct {
74     Widget      w;
75     Boolean     mapped;
76 } BombSign;
77 
78 static ArrowSign 	arrowsign[MAXSIGNS];
79 static UpdownSign 	updownsign[MAXSIGNS];
80 static StopSign		stopsign[MAXSIGNS];
81 static BombSign 	bombsign[MAXSIGNS];
82 
83 Arrow 		arrow;
84 Updown 		updown;
85 Stops		stops[MAXSTOPS];	/* array of stops */
86 Bomb 		bomb;
87 Cardinal	nstops;			/* number of stops */
88 
89 /* Initialize data structures */
90 
signs_init()91 void signs_init()
92 {
93     int i;
94 
95     for (i=0; i<MAXSIGNS; i++) {
96 	arrowsign[i].w = NULL;
97 	arrowsign[i].mapped = FALSE;
98     }
99     for (i=0; i<MAXSIGNS; i++) {
100 	stopsign[i].w = NULL;
101 	stopsign[i].mapped = FALSE;
102     }
103     arrow.i = 0;
104     arrow.line = 0;
105     strcpy(arrow.file, "");
106     updown.i = 0;
107     updown.line = 0;
108     strcpy(updown.file, "");
109     nstops = 0;
110     bomb.i = 0;
111     bomb.line = 0;
112     strcpy(bomb.file, "");
113 }
114 
115 
116 /*  Create an arrow symbol, updown symbol or stop symbol:
117  *    calculate the position of the symbol based on i, the number of lines
118  *    from the top line.
119  *    create the pixmap of the symbol
120  *    display the symbol as a bitmap in a label widget.
121  */
CreateSign(parent,sign,i)122 static Widget CreateSign(parent, sign, i)
123     Widget	parent;
124     char	*sign;
125     Cardinal 	i;
126 {
127     TextWidget 	ctx = (TextWidget) sourceWindow;
128     Arg 	args[15];
129     Cardinal 	n;
130     Dimension 	source_height, height, width;
131     char	*bits;
132     Pixel       fg, bg;
133     int 	horizDistance, vertDistance, height_per_line;
134     int         screen;
135     Dimension	vbar_width = 0;
136     Dimension	border_width = 0;
137 
138     if (displayedFile == NULL) return NULL;
139 
140     /* Get height and background pixel values of parent window */
141     n = 0;
142     XtSetArg(args[n], XtNheight, &source_height);			n++;
143     XtSetArg(args[n], XtNbackground, &bg);				n++;
144     XtGetValues(parent, args, n);
145 
146     height_per_line = source_height/displayedFile->lines;
147     vertDistance = OFFSET + (i * height_per_line);
148 
149     screen = DefaultScreen(display);
150 
151     if (sign && !strcmp(sign, "arrow")) {
152 	bits = arrow_bits;
153 	width = arrow_width;
154 	height = arrow_height;
155 	horizDistance = 0;
156 	fg = app_resources.arrow_color;
157     }
158     else if (sign && !strcmp(sign, "updown")) {
159 	bits = updown_bits;
160 	width = updown_width;
161 	height = updown_height;
162 	horizDistance = 0;
163 	fg = app_resources.updown_color;
164     }
165     else if (sign && !strcmp(sign, "stop")) {
166 	bits = stop_bits;
167 	width = stop_width;
168 	height = stop_height;
169 	horizDistance = arrow_width;
170 	fg = app_resources.stop_color;
171     }
172     else if (sign && !strcmp(sign, "bomb")) {
173 	bits = bomb_bits;
174 	width = bomb_width;
175 	height = bomb_height;
176 	horizDistance = 0;
177 	fg = app_resources.bomb_color;
178     } else {
179 		return NULL;
180 	}
181 
182     if( ctx->text.vbar != NULL )
183     {
184 	    n = 0;
185 	    XtSetArg(args[n], XtNwidth, &vbar_width); 			n++;
186 	    XtSetArg(args[n], XtNborderWidth, &border_width);		n++;
187 	    XtGetValues(ctx->text.vbar, args, n);
188 	    vbar_width += (border_width * 2);
189     }
190 
191     n = 0;
192     XtSetArg(args[n], XtNborderWidth, 0);				n++;
193     XtSetArg(args[n], XtNwidth, (XtArgVal) width);			n++;
194     XtSetArg(args[n], XtNheight, (XtArgVal) height);			n++;
195     XtSetArg(args[n], XtNresize, (XtArgVal) False);			n++;
196     XtSetArg(args[n], XtNmappedWhenManaged, (XtArgVal) False);		n++;
197     XtSetArg(args[n], XtNbitmap, XCreatePixmapFromBitmapData (
198         display, DefaultRootWindow(display), bits, width, height,
199         fg, bg, DefaultDepth(display, screen)));			n++;
200 
201     XtSetArg(args[n], XtNfromVert, (XtArgVal) NULL);			n++;
202     XtSetArg(args[n], XtNfromHoriz, (XtArgVal) NULL);			n++;
203     XtSetArg(args[n], XtNhorizDistance, (XtArgVal) horizDistance+vbar_width);
204 									n++;
205     XtSetArg(args[n], XtNvertDistance, (XtArgVal) vertDistance);	n++;
206     XtSetArg(args[n], XtNtop, (XtArgVal) XawChainTop);			n++;
207     XtSetArg(args[n], XtNleft, (XtArgVal) XawChainLeft);		n++;
208     XtSetArg(args[n], XtNbottom, (XtArgVal) XawChainTop);		n++;
209     XtSetArg(args[n], XtNright, (XtArgVal) XawChainLeft);		n++;
210 
211     return XtCreateManagedWidget(sign, labelWidgetClass, parent, args, n);
212 }
213 
214 /*
215  *  Given a line number, displays a stop sign if that line is viewable.
216  *  If the stop widget for that line does not exist, create one and map it.
217  *  If the stop widget exists but not mapped, map it.
218  */
DisplayStop(file,line)219 void DisplayStop(file, line)
220 FileRec *file;
221 int	line;
222 {
223     Cardinal i;
224 
225     if (line >= file->topline && line <= file->bottomline) {
226 	i = line - file->topline;
227 	if (stopsign[i].w == NULL) {	/* widget does not exist */
228 	    stopsign[i].w = CreateSign(sourceForm, "stop", i);
229 	    XtMapWidget(stopsign[i].w);
230 	    stopsign[i].mapped = 1;
231 	}
232 	else if (!stopsign[i].mapped) { /* widget not mapped */
233 	    XtMapWidget(stopsign[i].w);
234 	    stopsign[i].mapped = 1;
235 	}
236     }
237 }
238 
239 /*
240  *  Unmap all stop signs and then display only those stops that are viewable.
241  */
UpdateStops(file)242 void UpdateStops(file)
243 FileRec *file;
244 {
245     Cardinal i;
246     int	 line;
247 
248     if (file == NULL) return;
249     for (i=0; i<file->lines; i++)
250 	if (stopsign[i].w && stopsign[i].mapped) {
251 	    XtUnmapWidget(stopsign[i].w);
252 	    stopsign[i].mapped = 0;
253 	}
254 
255     for (i=1; i<=nstops; i++)
256 	if (stops[i].file && !strcmp(stops[i].file, file->pathname) &&
257 	    (line=stops[i].line) && line >= file->topline &&
258 	    line <= file->bottomline) {
259 	    DisplayStop(file, line);
260 	}
261 }
262 
263 /*
264  * Given a line number, unmap the stop sign associated with that line.
265  */
RemoveStop(line)266 void RemoveStop(line)
267 int line;
268 {
269     Cardinal i;
270 
271     if (displayedFile && line >= displayedFile->topline &&
272 			 line <= displayedFile->bottomline) {
273 	i = line - displayedFile->topline;
274 	if (stopsign[i].w && stopsign[i].mapped) {
275 	    XtUnmapWidget(stopsign[i].w);
276 	    stopsign[i].mapped = 0;
277 	}
278     }
279 }
280 
ClearStops()281 void ClearStops()
282 {
283     int i;
284 
285     for (i=1; i<=nstops; i++) {
286 	stops[i].file = NULL;
287 	stops[i].line = 0;
288     }
289 }
290 
291 /*  Unmap the current arrow sign.
292  *  Display a new arrow sign if it is viewable.
293  */
UpdateArrow(file)294 void UpdateArrow(file)
295 FileRec *file;
296 {
297     Cardinal i;
298     int	     line;
299 
300     if (file == NULL) return;
301     i = arrow.i;
302     if (i>=0 && i<file->lines)
303 	if (arrowsign[i].w && arrowsign[i].mapped) {
304 	    XtUnmapWidget(arrowsign[i].w);
305 	    arrowsign[i].mapped = 0;
306 	}
307     line = arrow.line;
308     if (arrow.file && !strcmp(arrow.file, file->pathname) &&
309     	line >= file->topline && line <= file->bottomline) {
310         i = line - file->topline;
311 	arrow.i = i;
312 	if (arrowsign[i].w == NULL) {
313 	    arrowsign[i].w = CreateSign(sourceForm, "arrow", i);
314 	    XtMapWidget(arrowsign[i].w);
315 	    arrowsign[i].mapped = TRUE;
316 	}
317 	else if (!arrowsign[i].mapped) {
318 	    XtMapWidget(arrowsign[i].w);
319 	    arrowsign[i].mapped = TRUE;
320 	}
321     }
322 }
323 
324 
325 /*  If the new updown is on the same line as the arrow, remove the updown.
326  *  Unmap current updown sign.
327  *  Display the updown if it is viewable.
328  */
UpdateUpdown(file)329 void UpdateUpdown(file)
330 FileRec *file;
331 {
332     Cardinal i;
333     int	     line;
334 
335     if (file == NULL) return;
336 
337 /* (PW)9JULY91 : add test line else it prevents up/down when a function calls itself */
338     if (updown.file && !strcmp(updown.file, arrow.file) &&
339 	!strcmp(updown.func, arrow.func) && (updown.line == arrow.line)) {
340 	updown.line = 0;
341 	strcpy(updown.file, "");
342     }
343 
344     i = updown.i;
345     if (i>=0 && i<file->lines)
346 	if (updownsign[i].w && updownsign[i].mapped) {
347 	    XtUnmapWidget(updownsign[i].w);
348 	    updownsign[i].mapped = 0;
349 	}
350     line = updown.line;
351     if (updown.file && !strcmp(updown.file, file->pathname) &&
352     	line >= file->topline && line <= file->bottomline) {
353         i = line - file->topline;
354 	updown.i = i;
355 	if (updownsign[i].w == NULL) {
356 	    updownsign[i].w = CreateSign(sourceForm, "updown", i);
357 	    XtMapWidget(updownsign[i].w);
358 	    updownsign[i].mapped = TRUE;
359 	}
360 	else if (!updownsign[i].mapped) {
361 	    XtMapWidget(updownsign[i].w);
362 	    updownsign[i].mapped = TRUE;
363 	}
364     }
365 }
366 
367 /*  Unmap the current bomb sign, if any.
368  *  Display a new bomb sign.
369  */
UpdateBomb(file)370 void UpdateBomb(file)
371 FileRec *file;
372 {
373     Cardinal i;
374     int	     line;
375 
376     if (file == NULL) return;
377     i = bomb.i;
378     if (i>=0 && i<file->lines)
379 	if (bombsign[i].w && bombsign[i].mapped) {
380 	    XtUnmapWidget(bombsign[i].w);
381 	    bombsign[i].mapped = 0;
382 	}
383     line = bomb.line;
384     if (bomb.file && !strcmp(bomb.file, file->pathname) &&
385     	line >= file->topline && line <= file->bottomline) {
386         i = line - file->topline;
387 	bomb.i = i;
388 	if (bombsign[i].w == NULL) {
389 	    bombsign[i].w = CreateSign(sourceForm, "bomb", i);
390 	    XtMapWidget(bombsign[i].w);
391 	    bombsign[i].mapped = TRUE;
392 	}
393 	else if (!bombsign[i].mapped) {
394 	    XtMapWidget(bombsign[i].w);
395 	    bombsign[i].mapped = TRUE;
396 	}
397     }
398 }
399