/*
 * This file contains routines to draw and update the screen.
 *
 * Copyright 1990 by the Massachusetts Institute of Technology.
 *
 * For copying and distribution information, please see the file
 * <mit-copyright.h>.
 *
 * Tom Coppeto
 * MIT Network Services
 * 8 August 1990
 *
 *    $Source: /afs/net.mit.edu/tools/src/xport/RCS/xstuff.c,v $
 *    $Author: tom $
 *    $Locker: tom $
 *    $Log:     xstuff.c,v $
 * Revision 1.2  90/08/19  16:19:18  tom
 * *** empty log message ***
 *
 * Revision 1.1  90/08/15  01:13:17  tom
 * Initial revision
 *
 */

#ifndef lint
static char *rcsid = "$Header: /afs/net.mit.edu/tools/src/xport/RCS/xstuff.c,v 1.2 90/08/19 16:19:18 tom Exp Locker: tom $";
#endif

#include <X11/Xatom.h>
#include <X11/IntrinsicP.h>
#include <X11/CompositeP.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Toggle.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/StripChart.h>
#include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/cursorfont.h>
#include <X11/Xaw/Dialog.h>
#include <X11/cursorfont.h>
#include <X11/Xaw/MenuButton.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/Sme.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/Xaw/Repeater.h>
#include <X11/Xaw/ScrollbarP.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xtw/Rolo.h>

#include "xrmonwatch.h"

extern XtAppContext app_con;
extern Widget toplevel;
static Widget IPpopup = (Widget) NULL;
static Widget ATpopup = (Widget) NULL;

static void create_row();
static Widget create_box();
static Widget create_form();
static void make_resource();

struct TABLE *parse_table();

static XtResource tableResources[] = 
{
  {"tableEtherTypes", XtCString, XtRString, sizeof(String),
     0, XtRString, NULL},
  {"tableEtherVendors", XtCString, XtRString, sizeof(String),
     sizeof(char *), XtRString, NULL},
  {"tableEtherMCasts", XtCString, XtRString, sizeof(String),
     2 * sizeof(char *), XtRString, NULL},
};


display_init()
{
  XtResource *resources;
  int n = 0, i = 0;
  int nr = 0;
  char *res_tables[3];         /* array for raw tables via resources */

  while(pieces[n++].resource);
  resources = (XtResource *) malloc(sizeof(XtResource) * n * 6);
  parts  = (struct PART *) malloc(sizeof(struct PART) * n);
  if(!resources || !parts)
    {
      fprintf("unable to allocate memory in display_init()\n");
      exit(1);
    }

  bzero(parts, sizeof(struct PART) * n);
  bzero(resources, 6 * n);

  i = 1;
  while(pieces[i].resource)
    {
      if(pieces[i].index)
	*(pieces[i].index) = i;
      parts[i].resource  = pieces[i].resource;
      if(pieces[i].base)
	parts[i].base      = *(pieces[i].base);

      make_resource(&resources[nr++], pieces[i].resource, "State", XtCState, 
		    XtRBoolean, sizeof(Boolean), 
		    (unsigned int) &(parts[i].state) - (unsigned int) parts,
		    XtRString, "off"); 
      make_resource(&resources[nr++],pieces[i].resource,"Color", XtCForeground,
		    XtRPixel, sizeof(Pixel),
		    (unsigned int) &(parts[i].color) - (unsigned int) parts,
		    XtRString, "white");
      make_resource(&resources[nr++],pieces[i].resource,"Highlight", 
		    XtCForeground,
		    XtRPixel, sizeof(Pixel),
		    (unsigned int) &(parts[i].highlight) -(unsigned int) parts,
		    XtRString, "white");
      make_resource(&resources[nr++],pieces[i].resource, "LLength", XtCLength, 
		    XtRInt, sizeof(int),
		    (unsigned int) &(parts[i].llength) - (unsigned int) parts,
		    XtRImmediate, (caddr_t) 0); 
      make_resource(&resources[nr++], pieces[i].resource, "SLabel", XtCLabel, 
		    XtRString, sizeof(String), 
		    (unsigned int) &(parts[i].slabel) - (unsigned int) parts,
		    XtRString, ""); 
      make_resource(&resources[nr++], pieces[i].resource, "Label", XtCString, 
		    XtRString, sizeof(String), 
		    (unsigned int) &(parts[i].label) - (unsigned int) parts,
		    XtRString, ""); 
      ++i;
    }
  
  XtGetApplicationResources(toplevel, parts, resources, 400, NULL, 0);
  XtGetApplicationResources(toplevel, parts, &resources[400], 400, NULL, 0);
  XtGetApplicationResources(toplevel, parts, &resources[800], nr-800, NULL, 0);
  XtGetApplicationResources(toplevel, res_tables, tableResources, 
			    XtNumber(tableResources), NULL, 0);

  ether_types  = parse_table(res_tables[0]);
  ether_addrs  = parse_table(res_tables[1]);
  ether_mcasts = parse_table(res_tables[2]);
}


static void
make_resource(resource, name, op, class, type, size, offset, deftype, defaddr)
     XtResource *resource;
     char *name;
     char *op;
     char *class;
     char *type;
     int size;
     int offset;
     char *deftype;
     caddr_t defaddr;
{
  char buf[100];
  char *save_string();

  sprintf(buf, "%s%s", name, op);
  resource->resource_name   = save_string(buf);  
  resource->resource_class  = class;
  resource->resource_type   = type;
  resource->default_type    = deftype;
  resource->default_addr    = defaddr;
  resource->resource_size   = size;
  resource->resource_offset = offset;
}


struct TABLE *
parse_table(s)
     char *s;
{
  struct TABLE *t;
  char *value;
  int i = 0;
  int page = 10;
  char *type;

  if(!s)
    return((struct TABLE *) NULL);
  if(!(t = (struct TABLE *) malloc((page + 1) * sizeof(struct TABLE))))
    return((struct TABLE *) NULL);
  
  while(*s)
    {
      if(i == 0)
	{
	  while(isspace(*s))
	    ++s;
	  if(!*s)
	    break;
	  type = s;
	  while(!isspace(*s))
	    ++s;
	  if(!*s)
	    break;
	  *s++ = '\0';
	}
      while(isspace(*s))
	++s;
      if(!*s)
	break;
      value = s;
      while(!isspace(*s))
	++s;
      if(!*s)
	break;
      *s++ = '\0';
      while(isspace(*s))
	++s;
      if(!*s)
	break;
      t[i].name = s;
      while(*s != ':')
	++s;
      if(!*s)
	break;
      *s++ = '\0';
      while(isspace(*s))
	++s;
      if(!*s)
	break;
      t[i].sname = s;
      while(*s != ':')
	++s;
      if(!*s)
	break;
      *s++ = '\0';

      t[i].value = 0;
      t[i].svalue = (char *) NULL;

      if(strncasecmp(type, "integer", strlen(type)) == 0)
	t[i].value = atoi(value);
      if(strncasecmp(type, "hexadecmial", strlen(type)) == 0)
	sscanf(value, "0x%x", &t[i].value);
      if(strncasecmp(type, "string", strlen(type)) == 0)
	t[i].svalue = value;

      if(++i >= page)
	{
	  page += 10;
	  if(!(t = (struct TABLE *) realloc(t, (page+1) * sizeof(struct TABLE))))
	    return((struct TABLE *) NULL);
	}  
    }

  t[i].name  = (char *) NULL;
  t[i].value = 0;
  return(t);
}


display_ip_panel(w)
{
  Widget box;
  Widget form;

  if(IPpopup)
    {
      XtMapWidget(IPpopup);
      XRaiseWindow(XtDisplay(IPpopup), XtWindow(IPpopup));
      return;
    }

  IPpopup= XtCreatePopupShell("dpyPopup", 
			      topLevelShellWidgetClass, 
			      toplevel, NULL, 0);

  form = create_form(IPpopup, "dpyTCPIP");

  /*
   * Ethernet box
   */

  box = create_box(form,  &parts[R_Ethernet]);
  create_row(box, &parts[R_EthernetType],        &parts[R_EthernetLength]);
  create_row(box, &parts[R_EthernetSrcAddress],  &parts[R_EthernetDstAddress]);
  create_row(box, &parts[R_EthernetSrcVendor],   &parts[R_EthernetDstVendor]);
  create_row(box, &parts[R_EthernetVersion],     &parts[R_EthernetMulticast]);
  
  /*
   * 802.2
   */

  box = create_box(form,  &parts[R_LLC]);
  create_row(box, &parts[R_LLCType],             &parts[R_LLCClass]);
  create_row(box, &parts[R_LLCFormat],           &parts[R_LLCCommand]);
  create_row(box, &parts[R_LLCSrcAddress],       &parts[R_LLCDstAddress]);
  create_row(box, &parts[R_LLCSrcAddrDesig],     &parts[R_LLCDstAddrDesig]);
  create_row(box, &parts[R_LLCSendSequence],     &parts[R_LLCRecvSequence]);
  create_row(box, &parts[R_LLCPFBit],            &parts[R_LLCCRIdentifier]);
  create_row(box, &parts[R_LLCSupervisoryBit],   &parts[R_LLCInformation]);

  /*
   * SNAP
   */

  box = create_box(form,  &parts[R_SNAP]);
  create_row(box, &parts[R_SNAPAddress],         &parts[R_SNAPNull]);

  /*
   * ARP
   */

  box = create_box(form,  &parts[R_ARP]);
  create_row(box, &parts[R_ARPSrcPhysicalAddress], 
	     &parts[R_ARPTargetPhysicalAddress]);
  create_row(box, &parts[R_ARPSrcProtocolAddress],
	     &parts[R_ARPTargetProtocolAddress]);
  create_row(box, &parts[R_ARPSrcName],
	     &parts[R_ARPTargetName]);


  /*
   * IP
   */

  box = create_box(form,  &parts[R_IP]);
  create_row(box, &parts[R_IPVersion],           &parts[R_IPHeaderLength]);
  create_row(box, &parts[R_IPType],              &parts[R_IPLength]);
  create_row(box, &parts[R_IPFlags],	         &parts[R_IPFragmentOffset]);
  create_row(box, &parts[R_IPIdentification],    &parts[R_IPTTL]);
  create_row(box, &parts[R_IPProtocol],	         &parts[R_IPChecksum]);
  create_row(box, &parts[R_IPSrcAddress],        &parts[R_IPDstAddress]);
  create_row(box, &parts[R_IPSrcName],           &parts[R_IPDstName]);


  /*
   *  ICMP
   */
  
  box = create_box(form,  &parts[R_ICMP]);
  create_row(box, &parts[R_ICMPType],	         &parts[R_ICMPCode]);
  create_row(box, &parts[R_ICMPChecksum],	 &parts[R_ICMPIPHeader]);
  create_row(box, &parts[R_ICMPPointer],         &parts[R_ICMPGateway]);
  create_row(box, &parts[R_ICMPIdentifier],	 &parts[R_ICMPSequence]);
  create_row(box, &parts[R_ICMPOriginateTimestamp],
	     &parts[R_ICMPReceiveTimestamp]);
  create_row(box, &parts[R_ICMPTransmitTimestamp], &parts[R_ICMPData]);


  /*
   *  UDP
   */

  box = create_box(form,  &parts[R_UDP]);
  create_row(box, &parts[R_UDPChecksum],         &parts[R_UDPLength]);
  create_row(box, &parts[R_UDPSrcPort],          &parts[R_UDPDstPort]);
  create_row(box, &parts[R_UDPSrcPortName],      &parts[R_UDPDstPortName]);
                        

  /*
   *  Zephyr
   */

#ifdef ZEPHYR
  box = create_box(form,  &parts[R_Zephyr]);
  create_row(box, &parts[R_ZPacket],             &parts[R_ZVersion]);
  create_row(box, &parts[R_ZKind],               &parts[R_ZNull]);
  create_row(box, &parts[R_ZSender],             &parts[R_ZRecipient]);
  create_row(box, &parts[R_ZClass],              &parts[R_ZInstance]);
  create_row(box, &parts[R_ZOpcode],             &parts[R_ZNull]);
#endif /* ZEPHYR */
  
  /*
   *  TCP
   */

  box = create_box(form,  &parts[R_TCP]);
  create_row(box, &parts[R_TCPChecksum],	 &parts[R_TCPAck]);
  create_row(box, &parts[R_TCPSequence],	 &parts[R_TCPWindow]);
  create_row(box, &parts[R_TCPOffset],	         &parts[R_TCPUrgent]);
  create_row(box, &parts[R_TCPSrcPort],          &parts[R_TCPDstPort]);
  create_row(box, &parts[R_TCPSrcPortName],      &parts[R_TCPDstPortName]);
  create_row(box, &parts[R_TCPFlags],	         &parts[R_TCPNull]);
  XtPopup(IPpopup, XtGrabNone);
  return;
}



display_at_panel(w)
{
  Widget form;
  Widget box;

  if(ATpopup)
    {
      XtMapWidget(ATpopup);
      XRaiseWindow(XtDisplay(ATpopup), XtWindow(ATpopup));
      return;
    }

  ATpopup= XtCreatePopupShell("dpyPopup", 
			      topLevelShellWidgetClass, 
			      toplevel, NULL, 0);
  
  form = create_form(ATpopup, "dpyAT");


  /*
   * Ethernet box
   */

  box = create_box(form,  &parts[R_Ethernet]);
  create_row(box, &parts[R_EthernetType],        &parts[R_EthernetLength]);
  create_row(box, &parts[R_EthernetSrcAddress],  &parts[R_EthernetDstAddress]);
  create_row(box, &parts[R_EthernetSrcVendor],   &parts[R_EthernetDstVendor]);
  create_row(box, &parts[R_EthernetVersion],     &parts[R_EthernetMulticast]);

  /*
   * 802.2
   */

  box = create_box(form,  &parts[R_LLC]);
  create_row(box, &parts[R_LLCType],             &parts[R_LLCClass]);
  create_row(box, &parts[R_LLCFormat],           &parts[R_LLCCommand]);
  create_row(box, &parts[R_LLCSrcAddress],       &parts[R_LLCDstAddress]);
  create_row(box, &parts[R_LLCSrcAddrDesig],     &parts[R_LLCDstAddrDesig]);
  create_row(box, &parts[R_LLCSendSequence],     &parts[R_LLCRecvSequence]);
  create_row(box, &parts[R_LLCPFBit],            &parts[R_LLCCRIdentifier]);
  create_row(box, &parts[R_LLCSupervisoryBit],   &parts[R_LLCInformation]);


  /*
   * SNAP
   */

  box = create_box(form,  &parts[R_SNAP]);
  create_row(box, &parts[R_SNAPAddress],         &parts[R_SNAPNull]);

  
  /*
   * AARP
   */

  box = create_box(form,  &parts[R_AARP]);
  create_row(box, &parts[R_AARPType],            &parts[R_AARPNull]);
  create_row(box, &parts[R_AARPHardwareType],	 &parts[R_AARPProtocolType]);
  create_row(box, &parts[R_AARPHardwareLength],  &parts[R_AARPProtocolLength]);
  create_row(box, &parts[R_AARPSrcHardwareAddress], 
	     &parts[R_AARPDstHardwareAddress]);
  create_row(box, &parts[R_AARPSrcProtocolAddress], 
	     &parts[R_AARPDstProtocolAddress]);



  /*
   * DDP
   */

  box = create_box(form,  &parts[R_DDP]);
  create_row(box, &parts[R_DDPLength],	         &parts[R_DDPHopCount]);
  create_row(box, &parts[R_DDPType],   	         &parts[R_DDPChecksum]);
  create_row(box, &parts[R_DDPSrcNetwork],	 &parts[R_DDPDstNetwork]);
  create_row(box, &parts[R_DDPSrcNode],	         &parts[R_DDPDstNode]);
  create_row(box, &parts[R_DDPSrcSocket],	 &parts[R_DDPDstSocket]);
  create_row(box, &parts[R_DDPSrcName],	         &parts[R_DDPDstName]);
  create_row(box, &parts[R_DDPSrcType],	         &parts[R_DDPDstType]);
  create_row(box, &parts[R_DDPSrcZone],	         &parts[R_DDPDstZone]);


  /*
   *  RTMP
   */

  box = create_box(form,  &parts[R_RTMP]);
  create_row(box, &parts[R_RTMPVersion],         &parts[R_RTMPFunction]);
  create_row(box, &parts[R_RTMPSrcNetwork],      &parts[R_RTMPSrcNode]);
  create_row(box, &parts[R_RTMPRangeStart],      &parts[R_RTMPRangeEnd]);
  create_row(box, &parts[R_RTMPDistance],        &parts[R_RTMPHops]);
  create_row(box, &parts[R_RTMPSrcNodeLength],   &parts[R_RTMPNetwork]);

  /*
   *  AEP
   */

  box = create_box(form,  &parts[R_AEP]);
  create_row(box, &parts[R_AEPType],	         &parts[R_AEPNull]);


  /*
   *  NBP
   */

  box = create_box(form,  &parts[R_NBP]);
  create_row(box, &parts[R_NBPType],	         &parts[R_NBPIdentification]);
  create_row(box, &parts[R_NBPTupleCount],       &parts[R_NBPNetwork]);
  create_row(box, &parts[R_NBPNode],             &parts[R_NBPSocket]);
  create_row(box, &parts[R_NBPObjectLength],     &parts[R_NBPObjectEntity]);
  create_row(box, &parts[R_NBPTypeLength],       &parts[R_NBPTypeEntity]);
  create_row(box, &parts[R_NBPZoneLength],       &parts[R_NBPZoneEntity]);
  create_row(box, &parts[R_NBPEnumerator],       &parts[R_NBPNull]);

  /*
   * ZIP
   */

  box = create_box(form,  &parts[R_ZIP]);
  create_row(box, &parts[R_ZIPNetworkCount],     &parts[R_ZIPNetwork]);
  create_row(box, &parts[R_ZIPZoneLength],       &parts[R_ZIPZone]);
  create_row(box, &parts[R_ZIPType],	         &parts[R_ZIPNull]);

  /*
   * ADSP
   */

  box = create_box(form,  &parts[R_ADSP]);
  create_row(box, &parts[R_ADSPConnId],          &parts[R_ADSPControlCode]);
  create_row(box, &parts[R_ADSPFirstSeq],        &parts[R_ADSPNextSeq]);
  create_row(box, &parts[R_ADSPWindow],          &parts[R_ADSPDescriptor]);


  XtPopup(ATpopup, XtGrabNone);
  return;
}


new_header()
{
  

}




/*
 * for creating widgets
 */

static void
create_row(parent, left, right)
     Widget parent;
     struct PART *left;
     struct PART *right;
{
  Arg carg;
  Widget w;
  Widget t;
  char buf[100];

  sprintf(buf, "%sForm",   left->resource);
  w = XtCreateManagedWidget(buf, formWidgetClass, parent, NULL, 0);
  sprintf(buf, "%sLabel",  left->resource);
  XtCreateManagedWidget(buf, labelWidgetClass,  w, NULL, 0);

  XtSetArg(carg, XtNstate, left->state);
  sprintf(buf, "%sToggle", left->resource);
  t = XtCreateManagedWidget(buf, toggleWidgetClass, w, &carg, 1);    
  XtAddCallback(t, XtNcallback, cb_chdisplay, &(left->state));

  XtSetArg(carg, XtNstate, right->state);   
  sprintf(buf, "%sToggle", right->resource);
  t = XtCreateManagedWidget(buf, toggleWidgetClass, w, &carg, 1);
  XtAddCallback(t, XtNcallback, cb_chdisplay, &(right->state));

  sprintf(buf, "%sLabel",  right->resource);
  XtCreateManagedWidget(buf, labelWidgetClass,  w, NULL, 0);  
}


static Widget
create_box(parent, box)
     Widget parent;
     struct PART *box;
{
  Widget w;
  char buf[100];
  Arg args[2];

  XtSetArg(args[0], XtNlabel, box->label);
  w = XtCreateManagedWidget("dpyForm", formWidgetClass, parent, args, 1);
  sprintf(buf, "%sLabel",  box->resource);
  XtCreateManagedWidget(buf, labelWidgetClass, w, NULL, 0);
  return(w);
}


static Widget
create_form(parent, name)  
     Widget parent;
     char  *name;
{
  Widget w;
  char buf[100];
  Arg arg;

  sprintf(buf, "%sRolo",  name);
  w = XtCreateManagedWidget(buf, roloWidgetClass, parent, NULL, 0);
  return(w);
}



char *
save_string(s)
     char *s;
{
  char *c;

  if(!s)
    return(s);

  if(!(c = (char * ) malloc(strlen(s) + 1)))
    {
      perror("");
      return((char *) NULL);
    }

  strcpy(c, s);
  return(c);
}
