cheung%SW.MCC.COM@MCC.COM (Po Cheung) (08/28/90)
Submitted-by: cheung%SW.MCC.COM@MCC.COM (Po Cheung) Posting-number: Volume 8, Issue 110 Archive-name: xdbx/part06 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 6 (of 7)." # Contents: datadpy.c # Wrapped by cheung@espresso.sw.mcc.com on Fri Aug 24 03:24:52 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'datadpy.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'datadpy.c'\" else echo shar: Extracting \"'datadpy.c'\" \(19682 characters\) sed "s/^X//" >'datadpy.c' <<'END_OF_FILE' X/***************************************************************************** X * X * xdbx - X Window System interface to the dbx debugger X * X * Copyright 1989 The University of Texas at Austin X * Copyright 1990 Microelectronics and Computer Technology Corporation X * X * Permission to use, copy, modify, and distribute this software and its X * documentation for any purpose and without fee is hereby granted, X * provided that the above copyright notice appear in all copies and that X * both that copyright notice and this permission notice appear in X * supporting documentation, and that the name of The University of Texas X * and Microelectronics and Computer Technology Corporation (MCC) not be X * used in advertising or publicity pertaining to distribution of X * the software without specific, written prior permission. The X * University of Texas and MCC makes no representations about the X * suitability of this software for any purpose. It is provided "as is" X * without express or implied warranty. X * X * THE UNIVERSITY OF TEXAS AND MCC DISCLAIMS ALL WARRANTIES WITH REGARD TO X * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND X * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TEXAS OR MCC BE LIABLE FOR X * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER X * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF X * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN X * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X * X * Author: Po Cheung X * Created: March 10, 1989 X * X *****************************************************************************/ X X/* dataDpy.c: X * X * Provide graphical display of C pointers and structures. X * X * BuildLinePos(): Construct an array indexing the character position of X * each line. X * PositionToLine(): Return the character position of a given line. X * SelectPointer(): Action proc for double click on a pointer value, X * CreateDataPopup(): Create a popup to display the object pointed to by a X * pointer. X * UpdateDataPopup(): Update an unused popupshell to display data. X * AppendList(): Append a popup to the list. X * DeleteList(): Delete a popup from the list. X * pop_down(): pop down the popup and free storage. X * DestroyDataPopup():event handler for destroying a popup, call DeleteList() X * and pop_down(). X * MovePopup(): Position the popup. X * print_handler(): Action handler for displaying pointers and structures. X */ X X#include "global.h" X#include "regex.h" X#include "datadpy.h" X X#define MAXLEVELS 20 /* max level of indentation */ X#define INDENT 8 /* # of spaces for each indentation */ X#define EMPTY 0 X#define UNUSED 1 X#define USED 2 X#define LEFT_MARGIN 10 X#define SCROLLBAR_WIDTH 15 X Xstatic DataDpyRec **dataDpyTable; Xstatic int dataDpyTableSize = 0; Xstatic DataDpyRec *Parent = NULL; Xstatic DataDpyList *TopParentList = NULL; Xstatic int font_height, font_width; Xstatic void DestroyDataPopup(); X X/* X * Build an array which gives the starting text position of each line. X * Very similar to the routine in source.c. X */ Xstatic void BuildLinePos(dataDpy) XDataDpyRec *dataDpy; X{ X char *p; X int line, nlines; X int max=0; X X nlines = MAX(1, dataDpy->buflen/CHARS_PER_LINE); X dataDpy->linepos = (XawTextPosition *) X XtMalloc ((nlines+2) * sizeof(XawTextPosition)); X p = dataDpy->buf; X line = 0; X dataDpy->linepos[line++] = 0; X dataDpy->linepos[line++] = 0; X while (*p) { X if (*p++ == '\n') { X if (line == nlines) { /* buffer full, need more memory */ X dataDpy->linepos = (XawTextPosition *)XtRealloc(dataDpy->linepos, X (nlines + ADD_LINES) * sizeof(XawTextPosition)); X nlines += ADD_LINES; X } X dataDpy->linepos[line] = p - dataDpy->buf; X AssignMax(max, dataDpy->linepos[line] - dataDpy->linepos[line-1]); X line++; X } X } X dataDpy->numlines = line - 2; X dataDpy->maxLineLength = max; X /* shrink to min size */ X dataDpy->linepos = (XawTextPosition *) XtRealloc X (dataDpy->linepos, line * sizeof(XawTextPosition)); X} X X/* X * Return the line number for the specified text position. X */ Xstatic int PositionToLine(dataDpy, pos) XDataDpyRec *dataDpy; XXawTextPosition pos; X{ X int line; X X if (dataDpy && pos >= 0) { X for (line = 1; pos >= dataDpy->linepos[line]; line++); X return (line-1); X } X else X return (0); X} X X/* ARGSUSED */ X/* X * Called by double click of pointer button. X * If the selected text is a valid pointer, this routine parses the data X * output to obtain the full qualified name of the pointer, and asks X * dbx to print the value of the object the pointer is pointing to. X */ Xstatic void SelectPointer(w, event, params, num_params) X Widget w; X XEvent *event; X String *params; X Cardinal *num_params; X{ X struct re_registers regs; X XawTextPosition left, right; X char *selection, *p, *field[MAXLEVELS]; X DataDpyRec *dataDpy; X int fromLine, line; X int i, n, nbytes, r, level, newlevel; X char name[LINESIZ], command[LINESIZ]; X X /* Find out which data display output does the selection belong to */ X dataDpy = NULL; X for (i=0; dataDpyTable[i]; i++) X if ((Widget) w == (Widget) dataDpyTable[i]->dataDpyWindow) { X dataDpy = dataDpyTable[i]; X Parent = dataDpy; X break; X } X if (!dataDpy) return; X X /* Get the selection and check if it's a pointer value, 0x???? */ X selection = XFetchBytes(display, &nbytes); X if (re_match(dataPattern[D_POINTER].buf, selection, strlen(selection), 0, 0) X < 0) { X Parent = NULL; X return; X } X X /* Parse the output to get the fully qualified name of the pointer */ X XawTextGetSelectionPos(w, &left, &right); X fromLine = PositionToLine(dataDpy, left); X p = dataDpy->buf + dataDpy->linepos[fromLine]; X X if (re_match(dataPattern[D_FIELD].buf, p, strlen(p), 0, ®s) >= 0) { X r = dataPattern[D_FIELD].reg_token[TK_POINTER]; X if (strncmp(selection, p+regs.start[r], regs.end[r]-regs.start[r])) X return; X r = dataPattern[D_FIELD].reg_token[TK_INDENT]; X level = regs.end[r]/INDENT; X field[level+1] = NULL; X X r = dataPattern[D_FIELD].reg_token[TK_FIELD]; X n = regs.end[r] - regs.start[r]; X field[level] = (char *) XtMalloc ((n+1) * sizeof(char)); X strncpy(field[level], p+regs.start[r], n); X field[level][n] = '\0'; X X for (line = fromLine-1; line > 0; line--) { X p = dataDpy->buf + dataDpy->linepos[line]; X if (re_match(dataPattern[D_STRUCT].buf, p, strlen(p), 0, ®s)>=0){ X r = dataPattern[D_STRUCT].reg_token[TK_INDENT]; X newlevel = regs.end[r]/INDENT; X if (newlevel == level-1) { X level--; X r = dataPattern[D_STRUCT].reg_token[TK_FIELD]; X n = regs.end[r] - regs.start[r]; X field[level] = (char *) XtMalloc ((n+1) * sizeof(char)); X strncpy(field[level], p+regs.start[r], n); X field[level][n] = '\0'; X } X } X } X if (*field[0] == '*' && field[1]) X sprintf(name, "(%s)", field[0]+1); X else X strcpy(name, field[0]); X for (i=1; field[i]; i++) { X strcat(name, "."); X strcat(name, field[i]); X } X sprintf(command, "print *(%s)\n", name); X PopupMode = True; X query_dbx(command); X } X} X X X/* X * Create a data display with a label. X * The popupshell has a form widget which consists of a label and a text X * widget. X */ Xstatic void CreateDataPopup(dataDpy, label) XDataDpyRec *dataDpy; Xchar *label; X{ X Arg args[MAXARGS]; X Cardinal n; X Dimension dataDpyHeight, dataDpyWidth; X XFontStruct *text_font; X X static XtActionsRec datadpy_actions[] = { X {"SelectPointer", (XtActionProc) SelectPointer}, X {NULL, NULL} X }; X X static String translations = "#override \n\ X <Btn1Down>: SelectStart() SelectWord() SelectPointer() \n\ X <Btn1Up>: SelectEnd() \n\ X "; X X n = 0; X dataDpy->popupshell = XtCreatePopupShell("Data Popup", X transientShellWidgetClass, toplevel, args, n); X X n = 0; X XtSetArg(args[n], XtNdefaultDistance, 0); n++; X dataDpy->popup = XtCreateManagedWidget("popup", formWidgetClass, X dataDpy->popupshell, args, n); X X /* Create the label */ X n = 0; X XtSetArg(args[n], XtNtop, (XtArgVal) XawChainTop); n++; X XtSetArg(args[n], XtNbottom, (XtArgVal) XawChainTop); n++; X XtSetArg(args[n], XtNright, (XtArgVal) XawChainRight); n++; X XtSetArg(args[n], XtNleft, (XtArgVal) XawChainLeft); n++; X XtSetArg(args[n], XtNlabel, (XtArgVal) label); n++; X XtSetArg(args[n], XtNresize, (XtArgVal) False); n++; X XtSetArg(args[n], XtNjustify, (XtArgVal) XtJustifyCenter); n++; X dataDpy->label = XtCreateManagedWidget("label", labelWidgetClass, X dataDpy->popup, args, n); X XtAddEventHandler(dataDpy->label, (EventMask) ButtonPressMask, False, X DestroyDataPopup, dataDpy); X X /* Create the text window */ X n = 0; X XtSetArg(args[n], XtNfromVert, (XtArgVal) dataDpy->label); n++; X XtSetArg(args[n], XtNtop, (XtArgVal) XawChainTop); n++; X XtSetArg(args[n], XtNbottom, (XtArgVal) XawChainBottom); n++; X XtSetArg(args[n], XtNright, (XtArgVal) XawChainRight); n++; X XtSetArg(args[n], XtNleft, (XtArgVal) XawChainLeft); n++; X X XtSetArg(args[n], XtNleftMargin, (XtArgVal) LEFT_MARGIN); n++; X XtSetArg(args[n], XtNuseStringInPlace, (XtArgVal) True); n++; X XtSetArg(args[n], XtNstring, (XtArgVal) dataDpy->buf); n++; X XtSetArg(args[n], XtNlength, (XtArgVal) dataDpy->buflen); n++; X XtSetArg(args[n], XtNeditType, (XtArgVal) XawtextRead); n++; X XtSetArg(args[n], XtNscrollHorizontal, XawtextScrollWhenNeeded); n++; X XtSetArg(args[n], XtNscrollVertical, XawtextScrollWhenNeeded); n++; X XtSetArg(args[n], XtNtranslations, XtParseTranslationTable(translations)); X n++; X dataDpy->dataDpyWindow = XtCreateManagedWidget("dataDpyWindow", X asciiTextWidgetClass, dataDpy->popup, args, n); X XtAppAddActions(app_context, datadpy_actions, XtNumber(datadpy_actions)); X X /* Get the text font */ X n = 0; X XtSetArg(args[n], XtNfont, &text_font); n++; X XtGetValues(dataDpy->dataDpyWindow, args, n); X X /* Estimate the size of the text widget, dataDpyWindow, with the number X of lines and the maximum length of a line. Assume fixed font width. X */ X font_height = text_font->ascent + text_font->descent; X font_width = text_font->max_bounds.width; X dataDpyHeight = dataDpy->numlines * font_height + 5; X dataDpyWidth = dataDpy->maxLineLength * font_width + LEFT_MARGIN; X if (dataDpyHeight > app_resources.dataDpyMaxHeight) X dataDpyWidth += SCROLLBAR_WIDTH; X AssignMin(dataDpyHeight, app_resources.dataDpyMaxHeight); X AssignMin(dataDpyWidth, app_resources.dataDpyMaxWidth); X X n = 0; X XtSetArg(args[n], XtNheight, (XtArgVal) dataDpyHeight); n++; X XtSetArg(args[n], XtNwidth, (XtArgVal) dataDpyWidth); n++; X XtSetValues(dataDpy->dataDpyWindow, args, n); X X n = 0; X XtSetArg(args[n], XtNwidth, (XtArgVal) dataDpyWidth); n++; X XtSetValues(dataDpy->label, args, n); X} X X/* X * Instead of creating a new popupshell, this routine uses an already X * existing popupshell for data display. X * It changes the label, calculates the size of the popupshell, X * and sets the source of the text window to that of the new data. X */ Xstatic void UpdateDataPopup(dataDpy, label) XDataDpyRec *dataDpy; Xchar *label; X{ X Arg args[MAXARGS]; X Cardinal n; X Dimension popupHeight, popupWidth, dataDpyHeight, dataDpyWidth, X labelHeight, labelBorderWidth, dataDpyBorderWidth; X X /* Update the label */ X n = 0; X XtSetArg(args[n], XtNlabel, (XtArgVal) label); n++; X XtSetValues(dataDpy->label, args, n); X X /* Calculate the size of popupshell */ X dataDpyHeight = dataDpy->numlines * font_height + 5; X dataDpyWidth = dataDpy->maxLineLength * font_width + 2*10; X AssignMin(dataDpyHeight, app_resources.dataDpyMaxHeight); X AssignMin(dataDpyWidth, app_resources.dataDpyMaxWidth); X X n = 0; X XtSetArg(args[n], XtNheight, (XtArgVal) &labelHeight); n++; X XtSetArg(args[n], XtNborderWidth, (XtArgVal) &labelBorderWidth); n++; X XtGetValues(dataDpy->label, args, n); X n = 0; X XtSetArg(args[n], XtNborderWidth, (XtArgVal) &dataDpyBorderWidth); n++; X XtGetValues(dataDpy->dataDpyWindow, args, n); X X popupHeight = dataDpyHeight + labelHeight + 2*labelBorderWidth + X 2*dataDpyBorderWidth; X popupWidth = dataDpyWidth; X n = 0; X XtSetArg(args[n], XtNheight, (XtArgVal) popupHeight); n++; X XtSetArg(args[n], XtNwidth, (XtArgVal) popupWidth); n++; X XtSetValues(dataDpy->popupshell, args, n); X X /* Set the text source */ X n = 0; X XtSetArg(args[n], XtNstring, (XtArgVal) dataDpy->buf); n++; X XtSetArg(args[n], XtNlength, (XtArgVal) dataDpy->buflen); n++; X XawTextSetSource(dataDpy->dataDpyWindow, X XtCreateWidget("textsrc", asciiSrcObjectClass, X dataDpy->dataDpyWindow, args, n), X 0); X} X X/* X * Append dataDpy to a DataDpyList pointed to by head. X */ Xstatic void AppendList(head, dataDpy) XDataDpyList **head; XDataDpyRec *dataDpy; X{ X DataDpyList *p, *q, *r; X X p = (DataDpyList *) XtNew (DataDpyList); X p->dataDpy = dataDpy; X p->next = NULL; X q = *head; X if (!q) X *head = p; X else { X while (r = q->next) X q = r; X q->next = p; X } X} X X/* X * Removes a dataDpy from its parent's list of children. X */ Xstatic void DeleteList(head, dataDpy) XDataDpyList **head; XDataDpyRec *dataDpy; X{ X DataDpyList *p, *q; X X if (p = *head) { X if (p->dataDpy == dataDpy) X *head = p->next; X else { X for (q = p->next; q && q->dataDpy != dataDpy;) { X p = q; X q = p->next; X } X if (q) p->next = q->next; X } X } X} X X/* X * Pop down a dataDpy and all its descendants, freeing storage and X * reinitializing fields. X */ Xstatic void pop_down(dataDpy) XDataDpyRec *dataDpy; X{ X DataDpyList *p, *q; X X XtPopdown(dataDpy->popupshell); X XtFree(dataDpy->linepos); X XtFree(dataDpy->buf); X dataDpy->buf = NULL; X dataDpy->buflen = 0; X dataDpy->linepos = NULL; X dataDpy->state = UNUSED; X dataDpy->parent = NULL; X for (p = dataDpy->childlist; p;) { X pop_down(p->dataDpy); X q = p; X p = p->next; X XtFree(q); X } X dataDpy->childlist = NULL; X} X X/* X * Invoked by a ButtonPress event on the label of a data display to X * pop down itself and its descendants. X */ X/* ARGSUSED */ Xstatic void DestroyDataPopup(w, dataDpy, event) X Widget w; X DataDpyRec *dataDpy; X XEvent *event; X{ X if (!dataDpy->parent) X DeleteList(&TopParentList, dataDpy); X else X DeleteList(&dataDpy->parent->childlist, dataDpy); X pop_down(dataDpy); X} X X/* X * Position the data display on the screen to reflect the parent-child X * relationship. X */ Xstatic void MovePopup(dataDpy) XDataDpyRec *dataDpy; X{ X Arg args[MAXARGS]; X Cardinal n; X Screen *screen; X int popupHeight, popupWidth, screenHeight, screenWidth; X Position x, y; X Dimension dataDpyWidth, dataDpyHeight, dataDpyBorderWidth, X labelHeight, labelBorderWidth, width, height, borderWidth; X DataDpyList *p, *q; X X Parent = NULL; X if (!dataDpy->parent) X p = TopParentList; X else X p = dataDpy->parent->childlist; X X /* Look for its previous sibling */ X for (q = p->next; q && q->dataDpy != dataDpy;) { X p = q; X q = q->next; X } X /* If a sibling exists, place the new popup right next to it */ X if (q) { X n = 0; X XtSetArg(args[n], XtNwidth, (XtArgVal) &width); n++; X XtSetArg(args[n], XtNborderWidth, (XtArgVal) &borderWidth); n++; X XtGetValues(p->dataDpy->popupshell, args, n); X XtTranslateCoords(p->dataDpy->popupshell, 0, 0, &x, &y); X x += width; X y -= borderWidth; X } X else { /* no siblings */ X /* this is the very first popup */ X if (!dataDpy->parent) { X x = 0; X y = 0; X } X /* place it under its parent */ X else { X n = 0; X XtSetArg(args[n], XtNheight, (XtArgVal) &height); n++; X XtGetValues(dataDpy->parent->popupshell, args, n); X XtTranslateCoords(dataDpy->parent->popupshell, 30, (Position)height, X &x, &y); X } X } X X /* Make sure the popup does not go outside of the screen */ X n = 0; X XtSetArg(args[n], XtNwidth, (XtArgVal) &dataDpyWidth); n++; X XtSetArg(args[n], XtNheight, (XtArgVal) &dataDpyHeight); n++; X XtSetArg(args[n], XtNborderWidth, (XtArgVal) &dataDpyBorderWidth); n++; X XtGetValues(dataDpy->dataDpyWindow, args, n); X X n = 0; X XtSetArg(args[n], XtNheight, (XtArgVal) &labelHeight); n++; X XtSetArg(args[n], XtNborderWidth, (XtArgVal) &labelBorderWidth); n++; X XtGetValues(dataDpy->label, args, n); X X popupHeight = dataDpyHeight + labelHeight + 2*labelBorderWidth + X 2*dataDpyBorderWidth; X popupWidth = dataDpyWidth; X X screen = XtScreen(toplevel); X screenHeight = XHeightOfScreen(screen); X screenWidth = XWidthOfScreen(screen); X X if (x + popupWidth > screenWidth && y + popupHeight > screenHeight) { X x = screenWidth - popupWidth; X y = screenHeight - popupHeight; X } X else if (x + popupWidth > screenWidth) X x = screenWidth - popupWidth; X else if (y + popupHeight > screenHeight) X y = screenHeight - popupHeight; X X n = 0; X XtSetArg(args[n], XtNx, x); n++; X XtSetArg(args[n], XtNy, y); n++; X XtSetValues(dataDpy->popupshell, args, n); X} X X/* X * Handler procedure called by parse(). X * The main function to popup a data display. X */ Xvoid print_handler(output) Xchar *output; X{ X DataDpyRec *dataDpy; X int i, j; X X if (!output) return; X if (!PopupMode) return; X PopupMode = False; X XDefineCursor(display, XtWindow(toplevel), watch); X if (Parent) X XDefineCursor(display, XtWindow(Parent->dataDpyWindow), watch); X UpdateMessageWindow("Click the label to pop down the data popup"); X X /* Searches the table for an unused or empty slot */ X for (i=0; dataDpyTable && dataDpyTable[i] && dataDpyTable[i]->state == USED X && i < dataDpyTableSize; i++); X if (i == dataDpyTableSize) { /* Table full */ X dataDpyTableSize += ADD_SIZE; X dataDpyTable = (DataDpyRec **) XtRealloc (dataDpyTable, X dataDpyTableSize * sizeof(DataDpyRec *)); X for (j=i; j<dataDpyTableSize; j++) X dataDpyTable[j] = NULL; X } X X /* Empty slot found, allocate a data structure and initializes some X of the fields. */ X if (dataDpyTable[i] == NULL) { X dataDpyTable[i] = (DataDpyRec *) XtMalloc (sizeof(DataDpyRec)); X dataDpyTable[i]->state = EMPTY; X dataDpyTable[i]->parent = NULL; X dataDpyTable[i]->childlist = NULL; X } X X dataDpy = dataDpyTable[i]; X dataDpy->id = i; /* not needed */ X dataDpy->buf = XtNewString(output); X dataDpy->buflen = strlen(output); X BuildLinePos(dataDpy); X X if (dataDpy->state == EMPTY) X CreateDataPopup(dataDpy, Token.mesg); X else if (dataDpy->state == UNUSED) X UpdateDataPopup(dataDpy, Token.mesg); X X dataDpy->state = USED; /* mark it used */ X if (dataDpy->parent = Parent) X AppendList(&Parent->childlist, dataDpy); X else X AppendList(&TopParentList, dataDpy); X X MovePopup(dataDpy); X XtPopup(dataDpy->popupshell, XtGrabNone); X if (dataDpy->parent) X XUndefineCursor(display, XtWindow(dataDpy->parent->dataDpyWindow)); X XUndefineCursor(display, XtWindow(toplevel)); X} END_OF_FILE if test 19682 -ne `wc -c <'datadpy.c'`; then echo shar: \"'datadpy.c'\" unpacked with wrong size! fi # end of 'datadpy.c' fi echo shar: End of archive 6 \(of 7\). cp /dev/null ark6isdone MISSING="" for I in 1 2 3 4 5 6 7 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 7 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.