/* This code is designed to plot snmp datas in a file with a specified format. 
 * "e40-rtr-dungeon.eth" has the format used for this code. 
 * This code is implemented athena toolkit intrinsics.
 * aplot.c is the original template of this code.
 */

#include <stdio.h> 
#include <stdlib.h>
#ifdef POSIX 
#include <string.h>
#else
#include <strings.h> 
#endif
#include <ctype.h> 

#include <X11/Intrinsic.h> 
#include <X11/StringDefs.h> 
#include <X11/Shell.h> 

#include <X11/Xaw/Command.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Dialog.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/List.h>

#include <X11/Xaw/MenuButton.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/SmeBSB.h>

#include <X11/At/Plotter.h>
#include <X11/At/XYAxis.h>
#include <X11/At/XYLinePlot.h>

#define ROWNUM 94 /* number of rows in the data file */
#define COLUMN 23 /* number of columns in the first line of the data file */ 

struct point {
  double xval;
  double yval;
}; /* each point has x and y coordinates */

typedef struct point points[ROWNUM]; /* each curve has ROWNUM(94) points */
points curve[COLUMN]; /* COLUMN(23) curves are to be plotted */

static int num_line=0;  /* number of lines to be plotted */
static int del_num;

Widget d_menu; /* made global in order to incorporate delete option */

char *snmp_names[COLUMN]; /* array storing snmp names */ 

int b_linenum;                 /* temporary buffer variables to store        */
Widget b_line, b_linename;     /* the members of the structure defined below */

struct linked_lines {  
  int linenum;                  /* for identification */
  Widget line;                  /* line widget */
  Widget linename;              /* name of line widget */
  struct linked_lines *prev;    /* link to the previous element of the list */
  struct linked_lines *next;    /* link to the next element of the list */
};
  
typedef struct linked_lines lines;  /* defining the pointers */
typedef lines *line_ptr;            /* to the element        */
line_ptr perm_ptr;        /* permanent storage for the lines */
line_ptr temp_ptr;        /* temporary storage for the new line 
			   * this will be attached to perm_ptr 
			   */

void ReadFirstline()     
/*
 *   Read the first line of the data file, and store it into an array. 
 */
{  
  FILE *fp;              /* pointer to a file */
  char line1[BUFSIZ];    /* the first line of the data file */
  char *firstline, *ptr; /* pointers used to access snmp names in the first
			    line of the data file */
  int x; /* loop counting variable */
  

  /* this part should be modified so that the application can read in
   * any files of this format.
   */

  if(!(fp = fopen("e40-rtr-dungeon.eth","r")))
    {
      perror("file name does not exist or it's in incorrect mode.");
      exit(1);
    }
  
  fgets(line1, sizeof(line1), fp);  /* reads the first line 
				       and stores it into an array */
  
  firstline = line1;
  x=0; /* initialize the loop counter */
  
  while (ptr = (char *)index(firstline, ' '))  /* puts names into 
						  snmp_names[COLUMN] */
    {
      *ptr++ = '\0';  /* fill the empty space with a null character */

      if(!(snmp_names[x] = (char *) malloc((strlen(firstline) + 1) * sizeof(char))))
        {
          perror("file is in incorrect format, cannot read the first line.");
          exit(1);
        }

      strcpy(snmp_names[x], firstline); /* copies characters upto the null 
					   character into array snmp */
      firstline = ptr; /* moves the pointer to the next 
                          entry in the first line */
      ++x;
    }
  
  fclose(fp);
}


/*
 *  Attaching the new line to the existing linked list of lines
 */
void attach_line(old_line, new_line)
     line_ptr old_line;
     line_ptr new_line;
{ 
  if (old_line -> next == NULL)      /* check if the element is the last one
				        in the linked list */
    { new_line -> prev = old_line;   /* attach the new element to the end */
      old_line -> next = new_line; } /* of the linked list by setting the */
                                     /* pointers appropriately            */
  else 
    attach_line(old_line->next, new_line); /* go to the next element of the
					      linked list */
}


/*
 * Prints out the linked list in human-readable form.
 */

void print_lines(head)
     line_ptr head;
{ 
  if (head == NULL)
    printf("NULL");
  else {
    printf("line_id: %d -->", head -> linenum);
    print_lines(head -> next);
  }
  printf("\n");
}

static Widget plotter;

/* stores the chosen line's identification number */
static void MenuSelectD(w, client_data, garbage)
     Widget w;
     XtPointer client_data;
     XtPointer garbage;  /* call_data */
{
  del_num = (int) client_data; /* stores the id number of line to be deleted */
  printf("\ndel_num in menuselectd: %d, %s is to be deleted.\n",
	 del_num, XtName(w));
}


/*
 *  Reads in the data from the file
 *  Creates line widget and attach the data onto the line
 *  Attaches the newly created line to the existing linked lists of lines
 */

void MakeData(x_axis, y_axis)
     int x_axis, y_axis; /* column number of the data to be plotted 
			  * at x axis and y axis.
			  */
{ 
  FILE *fp;
  char *newline, nline[BUFSIZ]; /* pointers used to handle datas */
  int line_num, column_num, point_num = 0;
  char *data, *ptr;
  char *line_name;
  char tempbuf[50];

  fp = fopen("e40-rtr-dungeon.eth","r");
  fgets(nline, sizeof(nline), fp);  /* skips the first line of the file */
  
  x_axis = x_axis + 1;
  y_axis = y_axis + 1;   /* subpane counts from 0; colum start at 1 */
  
  line_num = num_line - 1;
  
  while (fgets(nline, sizeof(nline), fp))/*gets a new line from the data file*/
    {
      column_num = 1; /* column number */
      newline = nline; 
      
      while (ptr = (char *)index(newline, ' '))  /* gets name */
        {
          *ptr++ = '\0';
          data = newline;
          
          /* attach the data to x - axis */
          if ( column_num == x_axis ) {
	    curve[line_num][point_num].xval = atoi(data);
	    /* printf("curve[%d][%d].xval:%3f y=%2d \n",
		   line_num,point_num,
		   curve[line_num][point_num].xval,point_num); */
	  }
	  
          /* attach the data to y - axis */
	  
	  if (column_num == y_axis) {
	    curve[line_num][point_num].yval = atoi(data);
	  }
	  
	 
          if (column_num == COLUMN) 
            ++point_num; /* increment y each time a new line is read */
	  
          newline = ptr;
          ++column_num;
        }
    }

  fclose(fp);
  
  /* 
   * makes a string for the line name with the snmp names stored in
   * ReadFirstline()
   */
  line_name = malloc(sizeof(char)*
		     ((strlen(snmp_names[x_axis-1])+
		       strlen(snmp_names[y_axis-1]))+5));
  sprintf(line_name, "%s%s%s", snmp_names[x_axis-1],
	  " .vs ",snmp_names[y_axis-1]);
  printf("%s\n", line_name);


  /* line widgets */ 
  temp_ptr = malloc(sizeof(lines));

  sprintf(tempbuf, "line%d", num_line);
  b_linenum = num_line;
  b_line = XtVaCreateWidget(tempbuf,
			    atXYLinePlotWidgetClass, plotter,
			    XtNlegendName, line_name,
			    XtNplotLineType, AtLineDOTTED, /* line type */
			    NULL);
  
  /* sme widgets for deletion menu */
  sprintf(tempbuf, "del_line%d", num_line);
  b_linename = XtVaCreateManagedWidget
    (tempbuf, smeBSBObjectClass, d_menu,
     XtNlabel, line_name,
     NULL);
  
  XtAddCallback(b_linename, 
		XtNcallback, MenuSelectD, (XtPointer) (num_line-1));

  /*
   *      Attach the data to the lines 
   */
  
  printf("num_line: %d\n",num_line);
 

  AtXYLinePlotAttachData(b_line,
			 (XtPointer)&curve[num_line-1][0].xval, 
			 AtDouble, sizeof(struct point),
			 (XtPointer)&curve[num_line-1][0].yval, 
			 AtDouble, sizeof(struct point),
			 1, ROWNUM);

  temp_ptr -> prev = NULL;
  temp_ptr -> linenum = b_linenum;
  temp_ptr -> line = b_line;
  temp_ptr -> linename = b_linename;
  temp_ptr -> next = NULL;

  attach_line(perm_ptr, temp_ptr);

  print_lines(perm_ptr); 

}

/*
 *      The plotter widgets
 */

static Widget xaxis, yaxis;
char *xname, *yname;

/*
 *      Create the plotter, the axes and the lines
 */

void select_callback(widget, client_data, call_data) /* ARGSUSED */
     Widget widget;
     XtPointer client_data;
     AtSelectCallbackData *call_data;
{
  char *r, *w;

  if(call_data->reason == AtSelectSELECTED) {
    r = "SELECTED";
    w = XtName(call_data->widget);
  }
  else {
    r = "DESELECTED";
    w = "-----";
  }
  printf("Select callback: widget: %s, reason: %s\n", w, r);
}

/*
 *      The button callbacks
 */
 
static Widget addshell, deleteshell, addbutton, deletebutton;

void quit_callback()
{
  exit(0);
}

/*ARGSUSED*/

static int x, y;

static void MenuSelectX(w, client_data, garbage) /* ARGSUSED */
     Widget w;
     XtPointer client_data;
     XtPointer garbage;  /* call_data */
{
  x = (int) client_data;  
  printf("Menu item %s has been selected.\n", XtName(w));
}

static void MenuSelectY(w, client_data, garbage) /* ARGSUSED */
     Widget w;
     XtPointer client_data;
     XtPointer garbage;  /* call_data */
{
  y = (int) client_data;  
  printf("Menu item %s has been selected.\n", XtName(w));
}

void PopupAddForm(w, client_data, call_data) /* ARGSUSED */
     Widget w;
     XtPointer client_data; /* cast to topLevel */
     XtPointer call_data;
{
  Widget topLevel = (Widget) client_data;
  Position x, y;
  Dimension width, height;
  
  /*
   * get the coordinates of the middle of topLevel widget.
   */
  XtVaGetValues(topLevel, 
		XtNwidth, &width,
		XtNheight, &height,
		NULL);
  
  /*
   * translate coordinates in application top-level window
   * into coordinates from root window origin.
   */  
  XtTranslateCoords(topLevel,                /* Widget */
		    (Position) 0,        /* x */
		    (Position) 0,       /* y */
		    &x, &y);          /* coords on root window */
  
  /* move popup shell to this position (it's not visible yet) */
  XtVaSetValues(addshell, 
		XtNx, x,
		XtNy, y,
		NULL);
  
  /*
   * Indicate to user that no other application functions are
   * valid while dialog is popped up...
   */
  XtSetSensitive(addbutton, FALSE);
  XtPopup(addshell, XtGrabNonexclusive);
}

/*ARGSUSED*/

void AddOK(w, client_data, call_data) /* ARGSUSED */
Widget w;
XtPointer client_data; /* cast to dialog */
XtPointer call_data;
{
  Widget dialog = (Widget) client_data;
  XtPopdown(addshell);
  XtSetSensitive(addbutton, TRUE);
  printf("x: %d, y: %d\n", x, y);
  num_line = num_line + 1; 
  MakeData(x, y);
}

void AddformDone(w, client_data, call_data) /* ARGSUSED */
Widget w;
XtPointer client_data; /* cast to dialog */
XtPointer call_data;
{
  Widget dialog = (Widget) client_data;
  XtPopdown(addshell);
  XtSetSensitive(addbutton, TRUE);
}

void PopupDeleteForm(w, client_data, call_data) /* ARGSUSED */
Widget w;
XtPointer client_data; /* cast to topLevel */
XtPointer call_data;
{
  Widget topLevel = (Widget) client_data;
  Position x, y;
  Dimension width, height;
  
  /*
   * get the coordinates of the middle of topLevel widget.
   */
  XtVaGetValues(topLevel, 
		XtNwidth, &width,
		XtNheight, &height,
		NULL);
  
  /*
   * translate coordinates in application top-level window
   * into coordinates from root window origin.
   */
  XtTranslateCoords(topLevel,            /* Widget */
		    (Position) 0,        /* x */
		    (Position) 0,        /* y */
		    &x, &y);             /* coords on root window */
  
  /* move popup shell to this position (it's not visible yet) */
  XtVaSetValues(deleteshell, 
		XtNx, x,
		XtNy, y,
		NULL);
  
  /*
   * Indicate to user that no other application functions are
   * valid while dialog is popped up...
   */
  
  XtSetSensitive(deletebutton, FALSE);
  XtPopup(deleteshell, XtGrabNonexclusive);
}

/*
 * Deleting a line data
 * Removes the line data from the link
 * sets the pointers of the previous and next elements
 */
void delete_data(head)
     line_ptr head;
{
 if (head -> linenum == (del_num + 1)) /* if the line id matches to the id
					* of the line to be deleted */
   {
     if ((!(head -> next == NULL))&(!( head -> prev == NULL)))
       { head -> prev -> next = head -> next;
	 head -> next -> prev = head -> prev;
	 XtDestroyWidget(head -> line);
	 XtDestroyWidget(head -> linename);
         free(head); /* freeing the memory resource */
       }
     else { if ((head -> prev == NULL)&(!(head -> next == NULL)))
	      /* if the line to be deleted is the first element of the link */
	      { head -> next -> prev = NULL;
                XtDestroyWidget(head -> line);
		XtDestroyWidget(head -> linename);
		free(head);}
     else { head -> prev -> next = NULL;
	    /* if the line to be deleted is the last element of the link */
	    XtDestroyWidget(head -> line);
	    XtDestroyWidget(head -> linename);
	    free(head); /* freeing the memory resource */
 	  }}}
 else{
   printf("\n linenum: %d", head-> linenum);
   delete_data(head -> next); }
}



/*ARGSUSED*/
void DeleteOK(w, client_data, call_data)
     Widget w;
     XtPointer client_data; /* cast to dialog */
     XtPointer call_data;
{
  Widget dialog = (Widget) client_data;
  XtPopdown(deleteshell);
  XtSetSensitive(deletebutton, TRUE);

  delete_data(perm_ptr);

}

void DeleteformDone(w, client_data, call_data) /* ARGSUSED */
     Widget w;
     XtPointer client_data; /* cast to dialog */
     XtPointer call_data;
{
  Widget dialog = (Widget) client_data;
  XtPopdown(deleteshell);
  XtSetSensitive(deletebutton, TRUE);
}

void list_callback(w, client_data, call_data)/* ARGSUSED */
     Widget w;
     XtPointer client_data, call_data;
{
  XawListReturnStruct *list_struct = (XawListReturnStruct *) call_data;
  printf("Item number: %d %s.\n", list_struct->list_index,
	 list_struct->string);
}

void print_callback()
{
  AtPlotterGeneratePostscript("aplot.ps", (AtPlotterWidget) plotter,
			      "aplot.ps", 50, 50, 520, 400, False);
  printf("Print callback: Plot dumped to aplot.ps\n");
}

void legend_callback()
{
  Arg args[2];
  Boolean f;

  XtVaGetValues(plotter, XtNshowLegend, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNshowLegend, f);
  XtSetValues(plotter, args, 1);
}

void grid_callback()
{
  Arg args[2];
  Boolean f;

  XtVaGetValues(xaxis, XtNdrawGrid, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNdrawGrid, f);
  XtSetValues(xaxis, args, 1);
  XtSetValues(yaxis, args, 1);
}

void subgrid_callback()
{
  Arg args[2];
  Boolean f;

  XtVaGetValues(xaxis, XtNdrawSubgrid, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNdrawSubgrid, f);
  XtSetValues(xaxis, args, 1);
  XtSetValues(yaxis, args, 1);
}

void origin_callback()
{
  Arg args[2];
  Boolean f;

  XtVaGetValues(xaxis, XtNdrawOrigin, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNdrawOrigin, f);
  XtSetValues(xaxis, args, 1);
  XtSetValues(yaxis, args, 1);
}

void frame_callback()
{
  Arg args[2];
  Boolean f;

  XtVaGetValues(xaxis, XtNdrawFrame, &f, NULL);
  f = f ? False : True;
  XtSetArg(args[0], XtNdrawFrame, f);
  XtSetValues(xaxis, args, 1);
  XtSetValues(yaxis, args, 1);
}

void get_motion_callback(widget, client_data, call_data)/* ARGSUSED */
  Widget widget;
  XtPointer client_data;
  AtPointCallbackData *call_data;
{
  double x, y;

  x = call_data->x1;
  y = call_data->y1;
  printf("Get motion callback: x=%lf y=%lf\n", x, y);
}

void motion_callback()
{
  Arg args[2];
  static int t = 0;

  if(t) {
    XtRemoveAllCallbacks(plotter, XtNmotionCallback);
    printf("Motion callback: get motion 1 -> 0\n");
    t = 0;
  }
  else {
    XtAddCallback(plotter, XtNmotionCallback, get_motion_callback, NULL);
    printf("Motion callback: get motion 0 -> 1\n");
    t = 1;
  }
}

static double oldxmin, oldxmax, oldymin, oldymax;

void get_drag_callback(widget, client_data, call_data)/* ARGSUSED */
  Widget widget;
  XtPointer client_data;
  AtRectangleCallbackData *call_data;
{
  Arg args[4];
  int n;
  static double x1, y1, x2, y2;
  AtTransform tx, ty;

  tx = AtAxisGetTransform((AtAxisCoreWidget) xaxis);
  ty = AtAxisGetTransform((AtAxisCoreWidget) yaxis);
  x1 = call_data->x11;
  x2 = call_data->x12;
  y1 = call_data->y11;
  y2 = call_data->y12;
  
  n = 0;
  XtSetArg(args[n], XtNmin, &x1);             n++;
  XtSetArg(args[n], XtNmax, &x2);             n++;
  XtSetArg(args[n], XtNautoScale, False);     n++;
  XtSetValues(xaxis, args, n);

  n = 0;
  XtSetArg(args[n], XtNmin, &y1);             n++;
  XtSetArg(args[n], XtNmax, &y2);             n++;
  XtSetArg(args[n], XtNautoScale, False);     n++;
  XtSetValues(yaxis, args, n);
  printf("Get drag callback: tx=%d x1=%lf x2=%lf ty=%d y1=%lf y2=%lf\n",
	  tx, x1, x2, ty, y1, y2);
}

void drag_callback()
{
  Arg args[4];
  int n;
  static int t = 0;

  if(t) {
    n = 0;
    XtSetArg(args[n], XtNmin, &oldxmin);       n++;
    XtSetArg(args[n], XtNmax, &oldxmax);       n++;
    XtSetArg(args[n], XtNautoScale, True);     n++;
    XtSetValues(xaxis, args, n);

    n = 0;
    XtSetArg(args[n], XtNmin, &oldymin);       n++;
    XtSetArg(args[n], XtNmax, &oldymax);       n++;
    XtSetArg(args[n], XtNautoScale, True);     n++;
    XtSetValues(yaxis, args, n);
    XtRemoveAllCallbacks(plotter, XtNdragCallback);
    printf("Drag callback: get drag 1 -> 0\n");
    t = 0;
  }
  else {
    XtVaGetValues(xaxis, XtNmin, &oldxmin, XtNmax, &oldxmax, NULL);
    XtVaGetValues(yaxis, XtNmin, &oldymin, XtNmax, &oldymax, NULL);
    XtAddCallback(plotter, XtNdragCallback, get_drag_callback, NULL);
    printf("Drag callback: get drag 0 -> 1\n");
    t = 1;
  }
}

/*
 *      Create form, buttons, plotter(without datas attached)
 */

void MakeForm(parent)
  Widget parent;
 
{ int i;
  Arg args[16];
  Arg arglist[1];
  int n;
  int x, y; /* column numbers in the data file 
	     * these are to be used to select datas to be placed in
	     * x and y axis 
	     */
  char tempbuf[50];
  Widget form, box, w;
  Widget addform, a_okbutton, a_donebutton, a_sublabel, a_subbox1, a_subbox2; 
  Widget x_button, y_button, x_menu, y_menu, entry, d_button;/*, d_menu; */
  Widget deleteform, d_okbutton, d_donebutton, d_sublabel;
  Widget d_subbox1, d_subbox2;
  Widget xlist, ylist;

  form = XtCreateManagedWidget("form", formWidgetClass, parent, NULL, 0);
  box = XtCreateManagedWidget("commandBox", boxWidgetClass, form, NULL, 0);
 
  addbutton = XtCreateManagedWidget
    ("addCommand",           /* widget name   */
     commandWidgetClass,     /* widget class */
     box,                    /* parent widget*/
     NULL, 0);      
  
  /* add axis - and widgets*/

  addshell = XtCreatePopupShell
    ("addshell",
     transientShellWidgetClass,
     parent,
     NULL, 0);
  
  addform = XtCreateManagedWidget
    ("addform",               /* widget name   */
     formWidgetClass,         /* widget class */
     addshell,                /* parent widget*/
     NULL, 0);

  XtAddCallback(addbutton, XtNcallback, PopupAddForm, parent);
    
  /*
   *  Widgets inside the addform window
   */

  a_sublabel = XtCreateManagedWidget("a_sublabel", labelWidgetClass, 
				     addform, NULL, 0); 

  a_subbox1 = XtCreateManagedWidget("a_subbox1", boxWidgetClass, 
				    addform, NULL, 0);
  
  x_button = XtCreateManagedWidget("x_button", 
				   menuButtonWidgetClass, a_subbox1,
				   arglist, (Cardinal) 0);
  
  y_button = XtCreateManagedWidget("y_button", 
				   menuButtonWidgetClass, a_subbox1,
				   arglist, (Cardinal) 0);
  
  x_menu = XtCreatePopupShell("menu", simpleMenuWidgetClass, 
			      x_button, NULL, 0);
  
  y_menu = XtCreatePopupShell("menu", simpleMenuWidgetClass, 
			      y_button, NULL, 0);
  
  for (i = 0; i < COLUMN ; i++) {
    sprintf(tempbuf, "xitem%d", i);
    entry = XtCreateManagedWidget(tempbuf, smeBSBObjectClass, 
				  x_menu, NULL, 0);
    XtAddCallback(entry, XtNcallback, MenuSelectX, (XtPointer) i);
  }
  
  for (i = 0; i < COLUMN ; i++) {
    sprintf(tempbuf, "yitem%d", i);
    entry = XtCreateManagedWidget(tempbuf, smeBSBObjectClass, 
				  y_menu, NULL, 0);
    XtAddCallback(entry, XtNcallback, MenuSelectY, (XtPointer) i);
  }
  
  a_subbox2 = XtCreateManagedWidget("a_subbox2", boxWidgetClass, 
				    addform, NULL, 0);
  
  a_okbutton = XtCreateManagedWidget
    ("a_okbutton",           /* widget name   */
     commandWidgetClass,     /* widget class */
     a_subbox2,              /* parent widget*/
     NULL, 0);
  
  XtAddCallback(a_okbutton, XtNcallback, 
		AddOK,  /* the function the widget is to call */
		0       /* data to be passed to the callback function */
		);
  
  a_donebutton = XtCreateManagedWidget
    ("a_donebutton",           /* widget name   */
     commandWidgetClass,       /* widget class */
     a_subbox2,                /* parent widget*/
     NULL, 0); 
  
  XtAddCallback(a_donebutton, XtNcallback, AddformDone, addform);
  
  /* end of addform  widgets*/
    
  /* delete axis - and widgets */
  deletebutton = XtCreateManagedWidget
    ("deleteCommand",        /* widget name   */
     commandWidgetClass,     /* widget class */
     box,                    /* parent widget*/
     NULL, 0);
  
  deleteshell = XtCreatePopupShell
    ("deleteshell",
     transientShellWidgetClass,
     parent,
     NULL, 0);
  
  deleteform = XtCreateManagedWidget
    ("deleteform",               /* widget name   */
     formWidgetClass,            /* widget class */
     deleteshell,                /* parent widget*/
     NULL, 0);
  
  XtAddCallback(deletebutton, XtNcallback, PopupDeleteForm, parent);
  
  /*
   *  Widgets inside the deleteform window
   */  
  
  d_sublabel = XtCreateManagedWidget("d_sublabel", labelWidgetClass, 
                                     deleteform, NULL, 0); 
  
  d_subbox1 = XtCreateManagedWidget("d_subbox1", boxWidgetClass, 
                                    deleteform, NULL, 0);
  
  d_button = XtCreateManagedWidget("d_button", 
				   menuButtonWidgetClass, d_subbox1,
				   arglist, (Cardinal) 0);
  
  d_menu = XtCreatePopupShell("menu", simpleMenuWidgetClass, 
			      d_button, NULL, 0);
  
  d_subbox2 = XtCreateManagedWidget("d_subbox2", boxWidgetClass, 
                                    deleteform, NULL, 0);
  
  d_okbutton = XtCreateManagedWidget
    ("d_okbutton",           /* widget name   */
     commandWidgetClass,     /* widget class */
     d_subbox2,              /* parent widget*/
     NULL, 0);
  
  XtAddCallback(d_okbutton, XtNcallback, DeleteOK, deleteform);
  
  d_donebutton = XtCreateManagedWidget
    ("d_donebutton",            /* widget name   */
     commandWidgetClass,        /* widget class */
     d_subbox2,                 /* parent widget*/
     NULL, 0); 
  
  XtAddCallback(d_donebutton, XtNcallback, DeleteformDone, deleteform);
  
  /* end of deleteform  widgets*/
  
  w = XtCreateManagedWidget("printCommand", commandWidgetClass, box, NULL, 0);
  XtAddCallback(w, XtNcallback, print_callback, NULL);
  
  w = XtCreateManagedWidget("legendCommand", commandWidgetClass, box,NULL, 0);
  XtAddCallback(w, XtNcallback, legend_callback, NULL);
  
  w = XtCreateManagedWidget("gridCommand", commandWidgetClass, box, NULL, 0);
  XtAddCallback(w, XtNcallback, grid_callback, NULL);

  w= XtCreateManagedWidget("subgridCommand", commandWidgetClass, box, NULL, 0);
  XtAddCallback(w, XtNcallback, subgrid_callback, NULL);
  
  w= XtCreateManagedWidget("originCommand", commandWidgetClass, box, NULL, 0); 
  XtAddCallback(w, XtNcallback, origin_callback, NULL);
  
  w= XtCreateManagedWidget("frameCommand", commandWidgetClass, box, NULL, 0);
  XtAddCallback(w, XtNcallback, frame_callback, NULL);

  w= XtCreateManagedWidget("motionCommand", commandWidgetClass, box, NULL, 0);
  XtAddCallback(w, XtNcallback, motion_callback, NULL);
  
  w= XtCreateManagedWidget("dragCommand", commandWidgetClass, box, NULL, 0); 
  XtAddCallback(w, XtNcallback, drag_callback, NULL);
  
  w= XtCreateManagedWidget("quitCommand", commandWidgetClass, box, NULL, 0);
  XtAddCallback(w, XtNcallback, quit_callback, NULL); 
  
  
  /* Create the plotter */
  n = 0;
  XtSetArg(args[n], XtNtitle,"e40-rtr-dungeon.eth"); n++; 
  plotter = XtCreateManagedWidget("plotter", atPlotterWidgetClass,
                                  form, args, n);
  XtAddCallback(plotter, XtNselectCallback, select_callback, NULL);
  
  /* Create the x and y axes */
  n = 0;
  XtSetArg(args[n], XtNlabel, "xaxis"); n++;
  xaxis = XtCreateWidget("xaxis", atXYAxisWidgetClass, plotter, args, n);

  n = 0;
  XtSetArg(args[n], XtNlabel, "yaxis"); n++; 
  yaxis = XtCreateWidget("yaxis", atXYAxisWidgetClass, plotter, args, n);
  
  /* Attach the axes */
  n = 0;
  XtSetArg(args[n], XtNxAxis, xaxis); n++;
  XtSetArg(args[n], XtNyAxis, yaxis); n++;
  XtSetValues(plotter, args, n);


   
}


/*
 *      Main
 */ 

main(argc, argv)
     int argc;
     char **argv;
{ 
  int i;
  Widget appShell;
  XtAppContext app; 
  
  
  ReadFirstline();
  appShell = XtAppInitialize(&app, "SNMP1.res", NULL, 0, 
			     &argc, argv, NULL, NULL, 0);

  /* initialization of the pointer to widget list */
  perm_ptr = malloc(sizeof(lines));
  perm_ptr -> linenum = 0;
  perm_ptr -> prev = NULL;
  perm_ptr -> next = NULL;


 MakeForm(appShell);  
  XtRealizeWidget(appShell);
  XtAppMainLoop(app); 
  
  exit(0); 
}


