"Fossies" - the Fresh Open Source Software Archive 
Member "xxgdb-1.12/datadpy.c" (29 Apr 1994, 29957 Bytes) of package /linux/misc/old/xxgdb-1.12.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
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 * xxgdb - X Window System interface to the gdb debugger
34 *
35 * Copyright 1990,1993 Thomson Consumer Electronics, Inc.
36 *
37 * Permission to use, copy, modify, and distribute this software and its
38 * documentation for any purpose and without fee is hereby granted,
39 * provided that the above copyright notice appear in all copies and that
40 * both that copyright notice and this permission notice appear in
41 * supporting documentation, and that the name of Thomson Consumer
42 * Electronics (TCE) not be used in advertising or publicity pertaining
43 * to distribution of the software without specific, written prior
44 * permission. TCE makes no representations about the suitability of
45 * this software for any purpose. It is provided "as is" without express
46 * or implied warranty.
47 *
48 * TCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
49 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
50 * SHALL TCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
51 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
52 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
53 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
54 * SOFTWARE.
55 *
56 * Adaptation to GDB: Pierre Willard
57 * XXGDB Created: December, 1990
58 *
59 *****************************************************************************/
60
61 /* dataDpy.c:
62 *
63 * Provide graphical display of C pointers and structures.
64 *
65 * BuildLinePos(): Construct an array indexing the character position of
66 * each line.
67 * PositionToLine(): Return the character position of a given line.
68 * SelectPointer(): Action proc for double click on a pointer value,
69 * CreateDataPopup(): Create a popup to display the object pointed to by a
70 * pointer.
71 * UpdateDataPopup(): Update an unused popupshell to display data.
72 * AppendList(): Append a popup to the list.
73 * DeleteList(): Delete a popup from the list.
74 * pop_down(): pop down the popup and free storage.
75 * DestroyDataPopup():event handler for destroying a popup, call DeleteList()
76 * and pop_down() (CRL mod 25)
77 * MovePopup(): Position the popup.
78 * print_handler(): Action handler for displaying pointers and structures.
79 */
80
81 /*
82 * 01FEB94: bugs fixed (klamer)
83 * xxgdb does not allow the graphically displaying of members of parents
84 * from a class.
85 * xxgdb does not allow the graphically displaying of data through a
86 * reference.
87 */
88
89 #include <string.h>
90 #include "global.h"
91 #include "regex.h"
92 #include "datadpy.h"
93
94 #define MAXLEVELS 20 /* max level of indentation */
95 #ifdef GDB
96 #define INDENT 2 /* # of spaces for each indentation */
97 #else
98 #define INDENT 8 /* # of spaces for each indentation */
99 #endif /* GDB */
100 #define EMPTY 0
101 #define UNUSED 1
102 #define USED 2
103 #define LEFT_MARGIN 10
104 #define SCROLLBAR_WIDTH 15
105
106
107 static DataDpyRec **dataDpyTable;
108 static int dataDpyTableSize = 0;
109 static DataDpyRec *Parent = NULL;
110 static DataDpyList *TopParentList = NULL;
111 static int font_height, font_width;
112
113 #ifdef OBSOLETE
114 static void DestroyDataPopup();
115 #else
116 /* CRL mod 25 4/12/91 GWC - changed label widget to command widget in popups */
117 static void DestroyDataCallback();
118 #endif
119
120 /*
121 * Build an array which gives the starting text position of each line.
122 * Very similar to the routine in source.c.
123 */
124 static void BuildLinePos(dataDpy)
125 DataDpyRec *dataDpy;
126 {
127 char *p;
128 int line, nlines;
129 int max=0;
130
131 nlines = MAX(1, dataDpy->buflen/CHARS_PER_LINE);
132 dataDpy->linepos = (XawTextPosition *)
133 XtMalloc ((nlines+2) * sizeof(XawTextPosition));
134 p = dataDpy->buf;
135 line = 0;
136 dataDpy->linepos[line++] = 0;
137 dataDpy->linepos[line++] = 0;
138 while (*p) {
139 if (*p++ == '\n') {
140 if (line == nlines) { /* buffer full, need more memory */
141 dataDpy->linepos = (XawTextPosition *)XtRealloc( (void*)dataDpy->linepos,
142 (nlines + ADD_LINES) * sizeof(XawTextPosition));
143 nlines += ADD_LINES;
144 }
145 dataDpy->linepos[line] = p - dataDpy->buf;
146 AssignMax(max, dataDpy->linepos[line] - dataDpy->linepos[line-1]);
147 line++;
148 }
149 }
150 dataDpy->numlines = line - 2;
151 dataDpy->maxLineLength = max;
152 /* shrink to min size */
153 dataDpy->linepos = (XawTextPosition *) XtRealloc
154 ((void*)dataDpy->linepos, line * sizeof(XawTextPosition));
155 }
156
157 /*
158 * Return the line number for the specified text position.
159 */
160 static int PositionToLine(dataDpy, pos)
161 DataDpyRec *dataDpy;
162 XawTextPosition pos;
163 {
164 int line;
165
166 if (dataDpy && pos >= 0) {
167 for (line = 1; pos >= dataDpy->linepos[line]; line++);
168 return (line-1);
169 }
170 else
171 return (0);
172 }
173
174 /* ARGSUSED */
175 /*
176 * Called by double click of pointer button.
177 * If the selected text is a valid pointer, this routine parses the data
178 * output to obtain the full qualified name of the pointer, and asks
179 * dbx to print the value of the object the pointer is pointing to.
180 */
181 static void SelectPointer(w, event, params, num_params)
182 Widget w;
183 XEvent *event;
184 String *params;
185 Cardinal *num_params;
186 {
187 #ifndef GDB
188 struct re_registers regs;
189 char *field[MAXLEVELS];
190 int line, n, r, level, newlevel;
191 char name[LINESIZ];
192 #endif
193 XawTextPosition left, right;
194 char *selection, *p;
195 DataDpyRec *dataDpy;
196 int fromLine;
197 int i, nbytes;
198 char command[LINESIZ];
199
200 /* Find out which data display output does the selection belong to */
201 dataDpy = NULL;
202 for (i=0; dataDpyTable[i]; i++)
203 if ((Widget) w == (Widget) dataDpyTable[i]->dataDpyWindow) {
204 dataDpy = dataDpyTable[i];
205 Parent = dataDpy;
206 break;
207 }
208 if (!dataDpy) return;
209
210 /* Get the selection and check if it's a pointer value, 0x???? */
211 selection = XFetchBytes(display, &nbytes);
212 if (re_match(dataPattern[D_POINTER].buf, selection, strlen(selection), 0, 0)
213 < 0) {
214 Parent = NULL;
215 return;
216 }
217
218 /* Parse the output to get the fully qualified name of the pointer */
219 XawTextGetSelectionPos(w, &left, &right);
220 fromLine = PositionToLine(dataDpy, left);
221 p = dataDpy->buf + dataDpy->linepos[fromLine];
222
223 #ifdef GDB /* (PW) we now use a new parser which should work better,
224 in particular for arrays */
225 {
226 char *parse_gdb_print();
227 char *newcommand;
228
229 newcommand = parse_gdb_print(command, dataDpy->buf, dataDpy->buf + left );
230 if (*newcommand)
231 {
232 if (strchr(selection, '@'))
233 {
234 char *p = strchr(newcommand, '*');
235 if (p != 0)
236 *p = ' ';
237 }
238 PopupMode = True;
239 query_gdb(newcommand, PARSE_ON | ECHO_OFF | FILTER_OFF);
240 }
241 }
242 #else /* not GDB */
243
244 if (re_match(dataPattern[D_FIELD].buf, p, strlen(p), 0, ®s) >= 0) {
245 r = dataPattern[D_FIELD].reg_token[TK_POINTER];
246 if (strncmp(selection, p+regs.start[r], regs.end[r]-regs.start[r]))
247 return;
248 r = dataPattern[D_FIELD].reg_token[TK_INDENT];
249 level = regs.end[r]/INDENT;
250 field[level+1] = NULL;
251
252 r = dataPattern[D_FIELD].reg_token[TK_FIELD];
253 n = regs.end[r] - regs.start[r];
254 field[level] = (char *) XtMalloc ((n+1) * sizeof(char));
255 strncpy(field[level], p+regs.start[r], n);
256 field[level][n] = '\0';
257
258 for (line = fromLine-1; line > 0; line--) {
259 p = dataDpy->buf + dataDpy->linepos[line];
260 if (re_match(dataPattern[D_STRUCT].buf, p, strlen(p), 0, ®s)>=0){
261 r = dataPattern[D_STRUCT].reg_token[TK_INDENT];
262 newlevel = regs.end[r]/INDENT;
263 if (newlevel == level-1) {
264 level--;
265 r = dataPattern[D_STRUCT].reg_token[TK_FIELD];
266 n = regs.end[r] - regs.start[r];
267 field[level] = (char *) XtMalloc ((n+1) * sizeof(char));
268 strncpy(field[level], p+regs.start[r], n);
269 field[level][n] = '\0';
270 }
271 }
272 }
273 if (*field[0] == '*' && field[1])
274 sprintf(name, "(%s)", field[0]+1);
275 else
276 strcpy(name, field[0]);
277
278 for (i=1; field[i]; i++) {
279 strcat(name, ".");
280 strcat(name, field[i]);
281 }
282 sprintf(command, "print *(%s)\n", name);
283 PopupMode = True;
284 #ifdef GDB
285 query_gdb(command, PARSE_ON | ECHO_OFF | FILTER_OFF);
286 #else
287 query_dbx(command);
288 #endif /* GDB */
289 }
290 #endif /* GDB */
291 }
292
293
294 /*
295 * Create a data display with a label.
296 * The popupshell has a form widget which consists of a label and a text
297 * widget.
298 */
299 static void CreateDataPopup(dataDpy, label)
300 DataDpyRec *dataDpy;
301 char *label;
302 {
303 Arg args[MAXARGS];
304 Cardinal n;
305 Dimension dataDpyHeight, dataDpyWidth;
306 XFontStruct *text_font;
307
308 static XtActionsRec datadpy_actions[] = {
309 {"SelectPointer", (XtActionProc) SelectPointer},
310 {NULL, NULL}
311 };
312
313 static String translations = "#override \n\
314 <Btn1Down>: SelectStart() SelectWord() SelectPointer() \n\
315 <Btn1Up>: SelectEnd() \n\
316 ";
317
318 n = 0;
319 dataDpy->popupshell = XtCreatePopupShell("Data Popup",
320 transientShellWidgetClass, toplevel, args, n);
321
322 n = 0;
323 XtSetArg(args[n], XtNdefaultDistance, 0); n++;
324 dataDpy->popup = XtCreateManagedWidget("popup", formWidgetClass,
325 dataDpy->popupshell, args, n);
326
327 /* Create the label */
328 n = 0;
329 XtSetArg(args[n], XtNtop, (XtArgVal) XawChainTop); n++;
330 XtSetArg(args[n], XtNbottom, (XtArgVal) XawChainTop); n++;
331 XtSetArg(args[n], XtNright, (XtArgVal) XawChainRight); n++;
332 XtSetArg(args[n], XtNleft, (XtArgVal) XawChainLeft); n++;
333 XtSetArg(args[n], XtNlabel, (XtArgVal) label); n++;
334 XtSetArg(args[n], XtNresize, (XtArgVal) False); n++;
335 XtSetArg(args[n], XtNjustify, (XtArgVal) XtJustifyCenter); n++;
336
337 #ifdef OBSOLETE
338 dataDpy->label = XtCreateManagedWidget("label", labelWidgetClass,
339 dataDpy->popup, args, n);
340 /* GWC says it is better to use ButtonReleaseMask instead of ButtonPressMask.*/
341 XtAddEventHandler(dataDpy->label, (EventMask) ButtonPressMask, False,
342 DestroyDataPopup, dataDpy);
343 #else
344 /* CRL mod 25 4/12/91 GWC - changed label widget to command widget in
345 popups */
346 dataDpy->label = XtCreateManagedWidget("command", commandWidgetClass,
347 dataDpy->popup, args, n);
348 XtAddCallback(dataDpy->label, XtNcallback, DestroyDataCallback, dataDpy);
349 #endif
350
351 /* Create the text window */
352 n = 0;
353 XtSetArg(args[n], XtNfromVert, (XtArgVal) dataDpy->label); n++;
354 XtSetArg(args[n], XtNtop, (XtArgVal) XawChainTop); n++;
355 XtSetArg(args[n], XtNbottom, (XtArgVal) XawChainBottom); n++;
356 XtSetArg(args[n], XtNright, (XtArgVal) XawChainRight); n++;
357 XtSetArg(args[n], XtNleft, (XtArgVal) XawChainLeft); n++;
358
359 XtSetArg(args[n], XtNleftMargin, (XtArgVal) LEFT_MARGIN); n++;
360 XtSetArg(args[n], XtNuseStringInPlace, (XtArgVal) True); n++;
361 XtSetArg(args[n], XtNstring, (XtArgVal) dataDpy->buf); n++;
362 XtSetArg(args[n], XtNlength, (XtArgVal) dataDpy->buflen); n++;
363 XtSetArg(args[n], XtNeditType, (XtArgVal) XawtextRead); n++;
364 XtSetArg(args[n], XtNscrollHorizontal, XawtextScrollWhenNeeded); n++;
365 XtSetArg(args[n], XtNscrollVertical, XawtextScrollWhenNeeded); n++;
366 XtSetArg(args[n], XtNtranslations, XtParseTranslationTable(translations));
367 n++;
368 dataDpy->dataDpyWindow = XtCreateManagedWidget("dataDpyWindow",
369 asciiTextWidgetClass, dataDpy->popup, args, n);
370 XtAppAddActions(app_context, datadpy_actions, XtNumber(datadpy_actions));
371
372 /* Get the text font */
373 n = 0;
374 XtSetArg(args[n], XtNfont, &text_font); n++;
375 XtGetValues(dataDpy->dataDpyWindow, args, n);
376
377 /* Estimate the size of the text widget, dataDpyWindow, with the number
378 of lines and the maximum length of a line. Assume fixed font width.
379 */
380 font_height = text_font->ascent + text_font->descent;
381 font_width = text_font->max_bounds.width;
382 dataDpyHeight = dataDpy->numlines * font_height + 5;
383 dataDpyWidth = dataDpy->maxLineLength * font_width + LEFT_MARGIN;
384 if (dataDpyHeight > app_resources.dataDpyMaxHeight)
385 dataDpyWidth += SCROLLBAR_WIDTH;
386
387 #if 1 /*(PW)17DEC90 : bug ! */
388 #define SCROLLBAR_HEIGHT 15
389 if (dataDpyWidth > app_resources.dataDpyMaxWidth)
390 dataDpyHeight += SCROLLBAR_HEIGHT;
391 #endif
392
393 AssignMin(dataDpyHeight, app_resources.dataDpyMaxHeight);
394 AssignMin(dataDpyWidth, app_resources.dataDpyMaxWidth);
395
396 n = 0;
397 XtSetArg(args[n], XtNheight, (XtArgVal) dataDpyHeight); n++;
398 XtSetArg(args[n], XtNwidth, (XtArgVal) dataDpyWidth); n++;
399 XtSetValues(dataDpy->dataDpyWindow, args, n);
400
401 n = 0;
402 XtSetArg(args[n], XtNwidth, (XtArgVal) dataDpyWidth); n++;
403 XtSetValues(dataDpy->label, args, n);
404 }
405
406 /*
407 * Instead of creating a new popupshell, this routine uses an already
408 * existing popupshell for data display.
409 * It changes the label, calculates the size of the popupshell,
410 * and sets the source of the text window to that of the new data.
411 */
412 static void UpdateDataPopup(dataDpy, label)
413 DataDpyRec *dataDpy;
414 char *label;
415 {
416 Arg args[MAXARGS];
417 Cardinal n;
418 Dimension popupHeight, popupWidth, dataDpyHeight, dataDpyWidth,
419 labelHeight, labelBorderWidth, dataDpyBorderWidth;
420
421 /* Update the label */
422 n = 0;
423 XtSetArg(args[n], XtNlabel, (XtArgVal) label); n++;
424 XtSetValues(dataDpy->label, args, n);
425
426 /* Calculate the size of popupshell */
427 dataDpyHeight = dataDpy->numlines * font_height + 5;
428 dataDpyWidth = dataDpy->maxLineLength * font_width + 2*10;
429
430 #if 1 /*(PW)18DEC90 : bug ! */
431 if (dataDpyHeight > app_resources.dataDpyMaxHeight)
432 dataDpyWidth += SCROLLBAR_WIDTH;
433
434 if (dataDpyWidth > app_resources.dataDpyMaxWidth)
435 dataDpyHeight += SCROLLBAR_HEIGHT;
436 #endif
437
438 AssignMin(dataDpyHeight, app_resources.dataDpyMaxHeight);
439 AssignMin(dataDpyWidth, app_resources.dataDpyMaxWidth);
440
441 n = 0;
442 XtSetArg(args[n], XtNheight, (XtArgVal) &labelHeight); n++;
443 XtSetArg(args[n], XtNborderWidth, (XtArgVal) &labelBorderWidth); n++;
444 XtGetValues(dataDpy->label, args, n);
445 n = 0;
446 XtSetArg(args[n], XtNborderWidth, (XtArgVal) &dataDpyBorderWidth); n++;
447 XtGetValues(dataDpy->dataDpyWindow, args, n);
448
449 popupHeight = dataDpyHeight + labelHeight + 2*labelBorderWidth +
450 2*dataDpyBorderWidth;
451 popupWidth = dataDpyWidth;
452
453 n = 0;
454 XtSetArg(args[n], XtNheight, (XtArgVal) popupHeight); n++;
455 XtSetArg(args[n], XtNwidth, (XtArgVal) popupWidth); n++;
456 XtSetValues(dataDpy->popupshell, args, n);
457
458 /* Set the text source */
459 n = 0;
460 XtSetArg(args[n], XtNstring, (XtArgVal) dataDpy->buf); n++;
461 XtSetArg(args[n], XtNlength, (XtArgVal) dataDpy->buflen); n++;
462 XawTextSetSource(dataDpy->dataDpyWindow,
463 XtCreateWidget("textsrc", asciiSrcObjectClass,
464 dataDpy->dataDpyWindow, args, n),
465 0);
466 }
467
468 /*
469 * Append dataDpy to a DataDpyList pointed to by head.
470 */
471 static void AppendList(head, dataDpy)
472 DataDpyList **head;
473 DataDpyRec *dataDpy;
474 {
475 DataDpyList *p, *q, *r;
476
477 p = (DataDpyList *) XtNew (DataDpyList);
478 p->dataDpy = dataDpy;
479 p->next = NULL;
480 q = *head;
481 if (!q)
482 *head = p;
483 else {
484 while ((r = q->next))
485 q = r;
486 q->next = p;
487 }
488 }
489
490 /*
491 * Removes a dataDpy from its parent's list of children.
492 */
493 static void DeleteList(head, dataDpy)
494 DataDpyList **head;
495 DataDpyRec *dataDpy;
496 {
497 DataDpyList *p, *q;
498
499 if ((p = *head)) {
500 if (p->dataDpy == dataDpy)
501 *head = p->next;
502 else {
503 for (q = p->next; q && q->dataDpy != dataDpy;) {
504 p = q;
505 q = p->next;
506 }
507 if (q) p->next = q->next;
508 }
509 }
510 }
511
512 /*
513 * Pop down a dataDpy and all its descendants, freeing storage and
514 * reinitializing fields.
515 */
516 static void pop_down(dataDpy)
517 DataDpyRec *dataDpy;
518 {
519 DataDpyList *p, *q;
520
521 XtPopdown(dataDpy->popupshell);
522 XtFree((void*)dataDpy->linepos);
523 XtFree(dataDpy->buf);
524 dataDpy->buf = NULL;
525 dataDpy->buflen = 0;
526 dataDpy->linepos = NULL;
527 dataDpy->state = UNUSED;
528 dataDpy->parent = NULL;
529 for (p = dataDpy->childlist; p;) {
530 pop_down(p->dataDpy);
531 q = p;
532 p = p->next;
533 XtFree((void*)q);
534 }
535 dataDpy->childlist = NULL;
536 }
537
538 /*
539 * Invoked by a ButtonPress event on the label of a data display to
540 * pop down itself and its descendants.
541 */
542 /* ARGSUSED */
543
544 #ifdef OBSOLETE
545 static void DestroyDataPopup(w, dataDpy, event)
546 Widget w;
547 DataDpyRec *dataDpy;
548 XEvent *event;
549 #else
550 /* CRL mod 25 4/12/91 GWC - changed label widget to command widget */
551 static void DestroyDataCallback(w, dataDpy, call_data)
552 Widget w;
553 DataDpyRec *dataDpy;
554 caddr_t call_data;
555 #endif
556 {
557 if (!dataDpy->parent)
558 DeleteList(&TopParentList, dataDpy);
559 else
560 DeleteList(&dataDpy->parent->childlist, dataDpy);
561 pop_down(dataDpy);
562 }
563
564 /*
565 * Position the data display on the screen to reflect the parent-child
566 * relationship.
567 */
568 static void MovePopup(dataDpy)
569 DataDpyRec *dataDpy;
570 {
571 Arg args[MAXARGS];
572 Cardinal n;
573 Screen *screen;
574 int popupHeight, popupWidth, screenHeight, screenWidth;
575 Position x, y;
576 Dimension dataDpyWidth, dataDpyHeight, dataDpyBorderWidth,
577 labelHeight, labelBorderWidth, width, height, borderWidth;
578 DataDpyList *p, *q;
579
580 Parent = NULL;
581 if (!dataDpy->parent)
582 p = TopParentList;
583 else
584 p = dataDpy->parent->childlist;
585
586 /* Look for its previous sibling */
587 for (q = p->next; q && q->dataDpy != dataDpy;) {
588 p = q;
589 q = q->next;
590 }
591 /* If a sibling exists, place the new popup right next to it */
592 if (q) {
593 n = 0;
594 XtSetArg(args[n], XtNwidth, (XtArgVal) &width); n++;
595 XtSetArg(args[n], XtNborderWidth, (XtArgVal) &borderWidth); n++;
596 XtGetValues(p->dataDpy->popupshell, args, n);
597 XtTranslateCoords(p->dataDpy->popupshell, 0, 0, &x, &y);
598 x += width;
599 y -= borderWidth;
600 }
601 else { /* no siblings */
602 /* this is the very first popup */
603 if (!dataDpy->parent) {
604 x = 0;
605 y = 0;
606 }
607 /* place it under its parent */
608 else {
609 n = 0;
610 XtSetArg(args[n], XtNheight, (XtArgVal) &height); n++;
611 XtGetValues(dataDpy->parent->popupshell, args, n);
612 XtTranslateCoords(dataDpy->parent->popupshell, 30, (Position)height,
613 &x, &y);
614 }
615 }
616
617 /* Make sure the popup does not go outside of the screen */
618 n = 0;
619 XtSetArg(args[n], XtNwidth, (XtArgVal) &dataDpyWidth); n++;
620 XtSetArg(args[n], XtNheight, (XtArgVal) &dataDpyHeight); n++;
621 XtSetArg(args[n], XtNborderWidth, (XtArgVal) &dataDpyBorderWidth); n++;
622 XtGetValues(dataDpy->dataDpyWindow, args, n);
623
624 n = 0;
625 XtSetArg(args[n], XtNheight, (XtArgVal) &labelHeight); n++;
626 XtSetArg(args[n], XtNborderWidth, (XtArgVal) &labelBorderWidth); n++;
627 XtGetValues(dataDpy->label, args, n);
628
629 popupHeight = dataDpyHeight + labelHeight + 2*labelBorderWidth +
630 2*dataDpyBorderWidth;
631 popupWidth = dataDpyWidth;
632
633 screen = XtScreen(toplevel);
634 screenHeight = XHeightOfScreen(screen);
635 screenWidth = XWidthOfScreen(screen);
636
637 if (x + popupWidth > screenWidth && y + popupHeight > screenHeight) {
638 x = screenWidth - popupWidth;
639 y = screenHeight - popupHeight;
640 }
641 else if (x + popupWidth > screenWidth)
642 x = screenWidth - popupWidth;
643 else if (y + popupHeight > screenHeight)
644 y = screenHeight - popupHeight;
645
646 n = 0;
647 XtSetArg(args[n], XtNx, x); n++;
648 XtSetArg(args[n], XtNy, y); n++;
649 XtSetValues(dataDpy->popupshell, args, n);
650 }
651
652 /*
653 * Handler procedure called by parse().
654 * The main function to popup a data display.
655 */
656 void print_handler(output)
657 char *output;
658 {
659 DataDpyRec *dataDpy;
660 int i, j;
661
662 if (!output) return;
663 if (!PopupMode) return;
664 PopupMode = False;
665 XDefineCursor(display, XtWindow(toplevel), watch);
666 if (Parent)
667 XDefineCursor(display, XtWindow(Parent->dataDpyWindow), watch);
668 UpdateMessageWindow("Click the label to pop down the data popup",NULL);
669
670 /* Searches the table for an unused or empty slot */
671 /* (PW)17OCT91 : test i < dataDpyTableSize first (else segment violation)*/
672 for (i=0; dataDpyTable && i < dataDpyTableSize && dataDpyTable[i]
673 && dataDpyTable[i]->state == USED ; i++);
674 if (i == dataDpyTableSize) { /* Table full */
675 dataDpyTableSize += ADD_SIZE;
676 dataDpyTable = (DataDpyRec **) XtRealloc ((void*)dataDpyTable,
677 dataDpyTableSize * sizeof(DataDpyRec *));
678 for (j=i; j<dataDpyTableSize; j++)
679 dataDpyTable[j] = NULL;
680 }
681
682 /* Empty slot found, allocate a data structure and initializes some
683 of the fields. */
684 if (dataDpyTable[i] == NULL) {
685 dataDpyTable[i] = (DataDpyRec *) XtMalloc (sizeof(DataDpyRec));
686 dataDpyTable[i]->state = EMPTY;
687 dataDpyTable[i]->parent = NULL;
688 dataDpyTable[i]->childlist = NULL;
689 }
690
691 dataDpy = dataDpyTable[i];
692 dataDpy->id = i; /* not needed */
693 dataDpy->buf = XtNewString(output);
694 dataDpy->buflen = strlen(output);
695 BuildLinePos(dataDpy);
696
697 if (dataDpy->state == EMPTY)
698 CreateDataPopup(dataDpy, Token.mesg);
699 else if (dataDpy->state == UNUSED)
700 UpdateDataPopup(dataDpy, Token.mesg);
701
702 dataDpy->state = USED; /* mark it used */
703 if ((dataDpy->parent = Parent))
704 AppendList(&Parent->childlist, dataDpy);
705 else
706 AppendList(&TopParentList, dataDpy);
707
708 MovePopup(dataDpy);
709 XtPopup(dataDpy->popupshell, XtGrabNone);
710 if (dataDpy->parent)
711 XUndefineCursor(display, XtWindow(dataDpy->parent->dataDpyWindow));
712 XUndefineCursor(display, XtWindow(toplevel));
713 }
714
715
716 #ifdef GDB
717 #define GOODCHARNAME(c) \
718 ( (((c) >='a') && ((c) <= 'z')) \
719 || (((c) >='A') && ((c) <= 'Z')) \
720 || (((c) >='0') && ((c) <= '9')) \
721 || ((c) == '_') \
722 || ((c) == '$') \
723 )
724
725 static char *result; /* start of result buffer */
726 static int result_index; /* current index in result buffer */
727 static char *start_txt; /* pointer 1st char of output to parse */
728 static char *curr_txt; /* current pointer in output to parse */
729
730 /*--------------------------------------------------------------------------+
731 | |
732 | Store a character into the buffer. |
733 | |
734 | Note that characters are added to the buffer RIGHT TO LEFT ! |
735 | This is because we parse the output from right to left. |
736 | |
737 | If the result buffer is full, we set result to "". |
738 | |
739 +--------------------------------------------------------------------------*/
740 static void add_char(c)
741 char c;
742 {
743 if (result_index == 0) /* buffer full */
744 {
745 *result = 0;
746 return;
747 }
748
749 if ((c == '.') && (result[result_index] == '.'))
750 return; /* To prevent $1..name for pointers in
751 g++ parents */
752
753 result_index--;
754 *(result+result_index) = c;
755 }
756
757 /*--------------------------------------------------------------------------+
758 | |
759 | Store a string into the buffer. |
760 | |
761 +--------------------------------------------------------------------------*/
762 static void add_string(s)
763 char *s;
764 {
765 int nbchar;
766
767 nbchar = strlen(s);
768
769 /* copy number from last digit */
770
771 while (nbchar > 0)
772 add_char(*(s + (--nbchar)));
773 }
774
775 /*--------------------------------------------------------------------------+
776 | |
777 | Store a number into the buffer. |
778 | |
779 +--------------------------------------------------------------------------*/
780 static void add_num(number)
781 int number;
782 {
783 char tmpnum[128];
784
785 sprintf(tmpnum,"%d",number);
786 add_string(tmpnum);
787 }
788
789 /*--------------------------------------------------------------------------+
790 | |
791 | Init buffer. |
792 | |
793 | Store a NULL character (as end of string). |
794 | |
795 +--------------------------------------------------------------------------*/
796 static void init_result(buffer,buflen)
797 char *buffer;
798 int buflen;
799 {
800 result = buffer;
801 result_index = buflen;
802 add_char(0); /* end result by null char */
803 }
804
805 /*--------------------------------------------------------------------------+
806 | |
807 | Store the current variable or struct name. |
808 | |
809 | input : curr_txt points to '=' character, |
810 | start_txt points to beginning of the parse string. |
811 | |
812 | output : curr_txt points to character before 1st character of |
813 | name. |
814 | |
815 | Note : we have to test for the beginning of the parse string, |
816 | because add_name() is called also for adding the "$n" name |
817 | of the gdb output. |
818 | |
819 +--------------------------------------------------------------------------*/
820 static void add_name ()
821 {
822 curr_txt--; /* point before '=' */
823 while (*curr_txt == ' ') curr_txt--; /* skip spaces */
824
825 /* loop over name */
826 while ((curr_txt >= start_txt) && GOODCHARNAME(*curr_txt))
827 add_char(*curr_txt--);
828 }
829
830 /*--------------------------------------------------------------------------+
831 | |
832 | Skip all previous characters until corresponding " or ' character. |
833 | |
834 | input : curr_txt points before ' or " character |
835 | |
836 | output : curr_txt points before corresponding ' or " character. |
837 | |
838 +--------------------------------------------------------------------------*/
839 void search_char(c)
840 char c;
841 {
842 while(1)
843 {
844 while(c != *(curr_txt--));
845
846 /* make sure there is not a '\' just before */
847
848 if (*curr_txt != '\\')
849 return;
850 }
851 }
852
853 /*--------------------------------------------------------------------------+
854 | |
855 | Skip all previous characters until previous corresponding '{'. |
856 | All "{...}" sequences are skip. |
857 | Return the array item number (if applicable) |
858 | |
859 | input : curr_txt points to string. |
860 | |
861 | output : curr_txt points to character before '{' |
862 | return number of commas |
863 | |
864 +--------------------------------------------------------------------------*/
865 static int skip_level()
866 {
867 int nbcommas;
868 char c;
869
870 nbcommas = 0;
871
872 while(1)
873 {
874 switch (c = *(curr_txt--))
875 {
876 case '{' :
877 return nbcommas;
878
879 case ',' :
880 nbcommas++;
881 break;
882
883 case '}' :
884 skip_level();
885 break;
886
887 case '"' :
888 case '\'' :
889 search_char(c);
890 break;
891
892 default:
893 break;
894 }
895 }
896 }
897
898 /*--------------------------------------------------------------------------+
899 | |
900 | Function to parse an output of a gdb print from |
901 | a pointer (0x...) and return a command line to |
902 | print *(0x...) |
903 | |
904 | input : command line pointer (LINESIZ size), |
905 | pointer print output, |
906 | pointer 0x... |
907 | |
908 | output : command line (stored RIGHT justified in commandline) |
909 | |
910 | example |
911 | |
912 | start = "$1 = { (struct foo *) 0x1224}" |
913 | current points to 0x1224 in start, |
914 | |
915 | commandline = "print *($1)" |
916 | |
917 +--------------------------------------------------------------------------*/
918 char *parse_gdb_print (commandline, start, current)
919 char *commandline;
920 char *start;
921 char *current;
922 {
923 char *begin;
924
925 start_txt = start; /* in static variables */
926 curr_txt = current;
927
928 begin = strchr(start,'='); /* find '=' in "$n =" */
929
930 if (!begin)
931 return NULL;
932
933 init_result(commandline,LINESIZ);
934
935 add_string(")\n");
936
937 while (begin <= curr_txt)
938 {
939 switch (*curr_txt)
940 {
941 case '=':
942 add_name();
943
944 /* stop now if we just parsed the '=' in "$n =" */
945 if (curr_txt >= start_txt)
946 {
947 add_char('.');
948 skip_level();
949 }
950 break;
951
952 case ',':
953 case '{':
954 add_char(']');
955 add_num(skip_level());
956 add_char('[');
957 break;
958
959 default:
960 curr_txt--;
961 }
962 }
963
964 add_string("print *(");
965
966 if (debug)
967 fprintf(stderr,"datadpy=%s\n",result+result_index);
968
969 return result+result_index;
970 }
971
972 #endif /* GDB */