/* treat me like a -*- c -*- program */

#define MAX_ITEM_LENGTH 200

/* KLUDGE KLUDGE KLUDGE for callbacks provided via resource mechanisms */
#define setQuark(resName,quark) \
    XtVaGetValues(newWidget, (resName), &callbackList, NULL); \
    if (callbackList && \
	callbackList->callback == (XtCallbackProc)wafeExecCallbackProc) \
	*(XrmQuark *)callbackList->closure = (quark)

XrmQuark qcallback;
XrmQuark qjumpProc;
XrmQuark qscrollProc;



/****************************************************************************
 *    FUNCTION:  name2Sink, name2Source
 *                                                                          
 *    Arguments: string containing an instance's name
 *    Returns:   source/sink widget of named text widget
 *                                                                          
 *****************************************************************************/

static Widget 
name2Sink(string)
char * string;
    {
    Widget localVar1, sink = NULL;

    if (!(localVar1 = name2Widget(string)))
	{
	wafeConvError("name2Sink","1",string,"Widget");
	return(NULL);
	}

    XtVaGetValues(localVar1, XtNtextSink, &sink, NULL);
    return(sink);
    }

/*
static Widget 
name2Source(string)
char * string;
    {
    Widget localVar1, source = NULL;

    if (!(localVar1 = name2Widget(string)))
	{
	wafeConvError("name2Source","1",string,"Widget");
	return(NULL);
	}

    XtVaGetValues(localVar1, XtNtextSource, &source, NULL);
    return(source);
    }
*/



/************** list widget support routines ******/
#include <X11/Xaw/List.h>

static int
listChange(w, widgetName, nitems, longest, resize, argc, argv)
Widget     w;
String     widgetName;
int        nitems;
int        longest;
int        resize;
int           argc;
char        **argv;
    {
    FILE    *fp;
    int      i, size=0;
    char   **list, **count, *offset;
    char     buffer [MAX_ITEM_LENGTH];

    DBUG_ENTER("listChange");
    
    if (!strcmp(argv[0], "List"))
	{
	  if (argc != 2)
	      {
	      fprintf(stderr, "Wafe(listChange): Wrong # of Args");
	      DBUG_RETURN(TCL_ERROR);
	      }

	  if (Tcl_SplitList(wafeInterpreter,argv[1], &nitems, &list) != TCL_OK)
	      {
	      fprintf(stderr, "Wafe(listChange): %s\n", 
		      wafeInterpreter->result);
	      DBUG_RETURN(TCL_ERROR);
	      }
	  }
    else 
    if (!strcmp(argv[0], "Arg"))
	{
        for (i = 1; i < argc; i++) 
	    size += strlen(argv[i])+1;
	
	list = count = (char **)XtMalloc((argc)*sizeof(char *)+size); 
	offset = (char *)list + (argc)*sizeof(char *);

	for (i = 1; i < argc; i++)
	    {
	    *count = offset;
	    strcpy(offset,argv[i]);
	    offset += strlen(argv[i])+1;
	    count++;
	    }

	*count = NULL;
	}
    else
    if (!strcmp(argv[0], "File"))
	{
	char **tmpList, **saveStart;

	if (argc != 2)
	    {
	    fprintf(stderr, "Wafe(listChange): Wrong # of Args");
	    DBUG_RETURN(TCL_ERROR);
	    }

	if (!(fp = fopen(argv[1], "r")))
	    {
	    fprintf(stderr, "Wafe(listChange): Couldn't open File %s",
		    argv[1]);
	    DBUG_RETURN(TCL_ERROR);
	    }

	saveStart = tmpList = count = (char **)XtMalloc(10*sizeof(char *));
	i = 0;

	while (fgets(buffer, 200, fp))
	    {
	    *count = XtNewString(buffer);
	    size += strlen(buffer)+1;
	    *(*count + strlen(buffer)-1) = '\0';
	    count++; i++;
	    if (!(i % 10))
		{
		DBUG_PRINT("list", ("Realloc"));
		saveStart = tmpList = (char**)XtRealloc((char *)tmpList,
						(i + 10)* sizeof(char *));
		count = tmpList + i;
		}
	    }
	*count = NULL;

	/* make it the list a single memory chunk to be 
         * compatible with the rest 
         */
	list = count = (char **)XtMalloc((i+1)*sizeof(char *)+size); 
	offset = (char *)list + (i+1)*sizeof(char *);

	while (*tmpList)
	    {
	    *count = offset;
	    strcpy(offset,*tmpList);
	    offset += strlen(*tmpList)+1;
	    XtFree(*tmpList);
	    tmpList++;
	    count++;
	    }
	*count = NULL;

        XtFree((char*)saveStart);
	}

    XawListChange(w, list, nitems, longest, resize);
    wafeMMreplace(wafeMMgetAttribList(w,True), qPointer, (char *)list,XtFree);

    DBUG_RETURN(TCL_OK);
    }

  
static void
listAppend(list, argc, argv)
Widget        list;
int           argc;
char        **argv;
    {
    char   **srcPtr, **trgtPtr;
    char   **newArray, **oldArray;
    int      nitems = 0;
    int      count;
    Boolean  resize;
    DBUG_ENTER("listAppend");
 
    XtVaGetValues(list, XtNlist, &oldArray, NULL);
    XtVaGetValues(list, XtNresize, &resize, NULL);
     
    for (srcPtr = oldArray; *srcPtr != NULL; srcPtr++)
	{
	nitems++;
	DBUG_PRINT("list", ("Checking %d", nitems));
	}

    newArray = (char **)XtMalloc((nitems * sizeof(char*)) + argc + 1);

    for(srcPtr = oldArray, trgtPtr = newArray; 
	*srcPtr != NULL; 
	srcPtr++, trgtPtr++)
	{          
	*trgtPtr = XtNewString(*srcPtr);
	DBUG_PRINT("list", ("Copied: >%s<\n", *trgtPtr));
	XtFree(*srcPtr);
	}

    XtFree((char *)oldArray);

    for (count = 0; count < argc; count++)
	{
	*trgtPtr = XtNewString(argv[count]);
	DBUG_PRINT("list", ("Added: >%s<", *trgtPtr));
	trgtPtr++;
	}

    *trgtPtr = NULL;

    XawListChange(list, newArray, 0, 0, resize);
    }


static Widget
listCreate(father, name, args, numArgs)
Widget   father;
char     *name;
ArgList  args;
Cardinal numArgs;
    {
    XtCallbackList callbackList = NULL;
    Widget newWidget = XtCreateWidget(name, listWidgetClass, 
				      father, args, numArgs);

    setQuark("callback",qcallback);

    return(newWidget);
    }

/******************** strip chart specific code ***************/
#include <X11/Xaw/StripChart.h>

typedef struct _scInfo
     {
     double            value;
     Widget            widget;
     struct _scInfo   *next;
     } scInfo, *scInfoPtr;

static scInfoPtr scBegin = NULL;

static void 
stripChartSet(sCWidget, value)
Widget  sCWidget;
double  value;
     {
     scInfoPtr   countPtr;

     if (!scBegin)         /* No Stripchart widgets exists yet*/
          {
          fprintf(stderr, "Wafe(scSet): No stripChart widget exists yet!\n");
          return;
          }

     for (countPtr = scBegin; 
          countPtr->widget != sCWidget && countPtr->next != NULL;
          countPtr = countPtr->next);

     if ((countPtr->next == NULL) && countPtr->widget != sCWidget)
          {
          fprintf(stderr, "Wafe(scSet): stripChart widget %s unknown\n", 
		  XtName(sCWidget));
          return;
          }

     DBUG_PRINT("sc",("Setting = %s to %f\n", 
		      XtName(countPtr->widget),value));

     countPtr->value = value;
     }


static void
scQueryProc(w, clientData, value)
Widget    w;
XtPointer clientData;
XtPointer value;
     {
     scInfoPtr   countPtr;

     DBUG_ENTER("Query");

     for (countPtr = scBegin; countPtr->widget != w;
          countPtr = countPtr->next);

     DBUG_PRINT("sc",("Name = %s, value = %f", 
		      XtName(countPtr->widget), countPtr->value));
/*
      fprintf(stderr,"float = %f\n",countPtr->value);
 */
     *((double*)value) = countPtr->value;

     DBUG_VOID_RETURN;
     }

static Widget
stripChartCreate(father, name, args, numArgs)
Widget   father;
char     *name;
ArgList  args;
Cardinal numArgs;
    {
    Widget newWidget;
    
    scInfoPtr  countPtr = (scInfoPtr)XtNew(scInfo);
    countPtr->next   = scBegin;
    countPtr->value  = 0.0;  /* default value */
    countPtr->widget = 
      newWidget = 
	XtCreateWidget(name, stripChartWidgetClass, father, args, numArgs);
    scBegin = countPtr;
    XtAddCallback(newWidget, "getValue", scQueryProc, NULL);  

    return(newWidget);
    }


/************** scrollbar widget support routines ******/
#include <X11/Xaw/Scrollbar.h>

static Widget
scrollbarCreate(father, name, args, numArgs)
Widget   father;
char     *name;
ArgList  args;
Cardinal numArgs;
    {
    XtCallbackList callbackList = NULL;
    Widget newWidget = XtCreateWidget(name, scrollbarWidgetClass, 
				      father, args, numArgs);

    setQuark("jumpProc",qjumpProc);
    setQuark("scrollProc",qscrollProc);

    return(newWidget);
    }

