/*
 * Copyright 1990 by Baylor College of Medicine ALL RIGHTS RESERVED. 
 *
 * This program is subject to a license agreement between 
 * Baylor College of Medicine and MIT. Any use inconsistent with
 * said license and any use by persons other than the faculty, 
 * students and staff at MIT or any use on a computer not operated 
 * as part of the Athena Computing Environment (ACE) is expressly 
 * prohibited.
 */
#include <stdio.h>
#include <string.h>
#include <X11/StringDefs.h>
#include <X11/IntrinsicP.h>
#include <X11/Intrinsic.h>
#include <Xw/Xw.h>
#include <Xw/XwP.h>
#include <Xw/SText.h>
#include <Xw/STextP.h>

#include "Dynamic.h"
#include "DynamicP.h"

#include <stdio.h>

static XtResource resources[] = {
#define offset(field) XtOffset(DynamicWidget, dynamic.field)

    { XtNcommand, XtCCommand, XtRString, 
          sizeof(String), offset(command), XtRString, (char *) NULL },

#undef offset
};

static void Destroy(), Initialize();
static Boolean SetValues();

extern XwStaticTextClassRec XwstatictextClassRec;

DynamicClassRec dynamicClassRec = {
  { /* core fields */
    /* superclass		*/      (WidgetClass) &XwstatictextClassRec,
    /* class_name		*/	"Dynamic",
    /* widget_size		*/	sizeof(DynamicRec), 
    /* class_initialize		*/	(XtProc) NULL, 
    /* class_part_initialize	*/	(XtWidgetClassProc) NULL,
    /* class_inited		*/	FALSE,
    /* initialize		*/	Initialize,
    /* initialize_hook		*/	NULL,
    /* realize			*/	XtInheritRealize,
    /* actions			*/	NULL,
    /* num_actions		*/	0,
    /* resources		*/	resources,
    /* num_resources		*/	XtNumber(resources),
    /* xrm_class		*/	NULLQUARK,
    /* compress_motion		*/	TRUE,
    /* compress_exposure	*/	TRUE,
    /* compress_enterleave	*/	TRUE,
    /* visible_interest		*/	FALSE,
    /* destroy			*/	Destroy,
    /* resize			*/	XtInheritResize,
    /* expose			*/	XtInheritExpose,
    /* set_values		*/	SetValues,
    /* set_values_hook		*/	NULL,
    /* set_values_almost	*/	XtInheritSetValuesAlmost,
    /* get_values_hook		*/	NULL,
    /* accept_focus		*/	NULL,
    /* version			*/	XtVersion,
    /* callback_private		*/	NULL,
    /* tm_table			*/	NULL,
    /* query_geometry		*/	XtInheritQueryGeometry,
    /* display_accelerator	*/	XtInheritDisplayAccelerator,
    /* extension		*/	NULL
  },
  /* primitive fields */
  {
     NULL,
     NULL,
     NULL,
     NULL,
     NULL,
     NULL
  },
  /* static text fields */
  {
    /* foo                      */      0
  },
  { /* dynamic fields */
    /* mumble			*/	0
  }
};

WidgetClass dynamicWidgetClass = (WidgetClass)&dynamicClassRec;

static void Initialize(request, new)
   Widget request, new;
{

#define AMT 50

   DynamicRec *dn  = (DynamicRec *) new;
   FILE *pipe;
   char *buf;
   int nread, size = 0;
   Boolean no_command = False;
   Arg arg;

   if (dn->dynamic.command != NULL)
   {
      pipe = popen(dn->dynamic.command, "r");
      if (pipe == NULL)
      {
          XtAppWarning(XtWidgetToApplicationContext(new),
			"Dynamic: could not execute command.");
          no_command = True;
      }
      else 
      {

         buf = XtMalloc((Cardinal)AMT);
         nread = fread(buf, 1, AMT, pipe);
         size  = nread;

         while (nread == AMT)
         {
            buf = XtRealloc(buf,(Cardinal)(size + AMT));
            nread = fread(buf + size, 1, AMT, pipe);
            size += nread;
         }

         buf[size] = 0;

         dn->dynamic.command = XtNewString(dn->dynamic.command);
      }
   }
   else
      no_command = True;

   if (no_command)
   {
      buf = XtNewString("");
      dn->dynamic.command = NULL;
   }

   XtSetArg(arg, XtNstring, buf);
   XtSetValues(new, &arg, 1);
   XtFree(buf);
}


static Boolean SetValues(current, request, new)
   Widget current, request, new;
{
   DynamicRec *dc = (DynamicRec *) current;
   DynamicRec *dn = (DynamicRec *) new;

   if (dc->dynamic.command && dn->dynamic.command)
   {
      if (strcmp(dc->dynamic.command, dn->dynamic.command))
      {
         XtFree(dc->dynamic.command);
         Initialize(request, new);
         return True;
      }
   }

   /* if I get here, strcmp won't work because at least 1 ptr is NULL */

   else if (dn->dynamic.command)
   {
      Initialize(request, new);
      return True;
   }

   else if (dc->dynamic.command)
   {
       XtFree(dc->dynamic.command);
       Initialize(request, new);
       return True;
   }

   else 
      /* both are NULL, no change */
      return False;
}

static void Destroy(w)
  Widget w;
{
  DynamicRec *dw = (DynamicRec *) w;

  if (dw->dynamic.command)
     XtFree(dw->dynamic.command);
}
