[comp.sources.x] v08i110: xdbx -- Dbx for X11, Part06/07

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, &regs) >= 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, &regs)>=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.