/**
 *
 * $Id: Mrm.c,v 1.3 1997/06/11 18:45:18 miers Exp $
 *
 * Copyright (C) 1995 Free Software Foundation, Inc.
 *
 * This file is part of the GNU LessTif Library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *
 *  Original author:  Geoffrey W. Ritchey
 *                    codesmit@southwind.net
 *
*/ 
#include <stdarg.h>
#include <stdlib.h>
#include <Mrm/MrmPublic.h>
#include <Xm/Text.h>
#include <Xm/RowColumn.h>
#include <Xm/MainW.h>
#include <Xm/PushB.h>
#include <Xm/BulletinB.h>
#include <Xm/Label.h>
#include <Xm/CascadeB.h>
#include <Xm/Separator.h>
#include <Xm/PanedW.h>
#include <Xm/Text.h>
#include <Xm/FileSB.h>
#include <Xm/ToggleB.h>
#include <Xm/Form.h>
#include <Xm/Frame.h>
#include <Xm/MessageB.h>
#include <XmI/XmXpm.h>
#include <X11/Xlibint.h>
#include <X11/Xlib.h>

#include "uil.h"
#include "lookup.h"
#include "misc.h"

#define MAX_ARGS 40
#define MAX_BUFFER 2048

Display *display = NULL;
Colormap colormap;
static Screen *theScreen;
static Window window;
static Widget parent;
static char *theName;
static char *theClass;

enum {GEO, LATE, ON_CREATE};
#define ANOTHER_WIDGET -1

typedef Widget (*CreateFunction)(Widget, String, ArgList, Cardinal);

typedef struct _CreateFunctionsType{
  char *Name;
  CreateFunction function;
} CreateFunctionsType;

typedef struct _MyHierStruct {
  char *CreateName;
  int CreateClass;
  Arg *args;
  int argCount;
  int SizeArgs;
} MyHierStruct;

extern CreateFunctionsType CreateFunctions[];

typedef struct _SymbolTable {
  struct _SymbolTable *Next;
  int type;
  int Index;
  char *Name;
  char *value;
  char Access;
} SymbolTableType;

typedef struct _callbackType {
  struct _callbackType *next;
  int id;
  int index;
  char *argName;
  char *functionName;
  SymbolTableType *Parameters;
} callbackType;
  
typedef struct _DummyWidget {
  char *Name;
  int  class;
  char managed;
  int  parent;
  int NumberOfInherit;
  int *inherit;
  int  NumberOfChildren;
  int *children;
  callbackType *callbacks;
  SymbolTableType *attributes;
} DummyWidget;

typedef struct _UilModuleType {
  char **Definitions;
  char **Names;
  int NumberOfWidgets;
  Widget *WidgetArray;
  DummyWidget *DummyWidgetArray;
  SymbolTableType *SymbolTable;
} UilModuleType;

typedef struct _GeoType {
  int module_id;
  int this_id;
  struct _GeoType *next;
  DummyWidget *DW;
} GeoType;

typedef struct _ColorTableType {
  char *Reference;
  int IsAddress;
  char *Color;
  char *StringXPM;
} ColorTableType;

typedef struct _ColorTableHeaderType {
  int NumColors;
  ColorTableType *ColorTable;
} ColorTableHeaderType;

typedef struct _FontTableType {
  FontSetType Tag;
  char *FontName;
} FontTableType;

typedef struct _FontTableHeaderType {
  int NumFonts;
  FontTableType *FontTable;
} FontTableHeaderType;

int GetSymbolTableValue(XtArgVal *,SymbolTableType *, int, SymbolTableType *);
SymbolTableType *GetSymbolTable(SymbolTableType *);
SymbolTableType *LookupValue(SymbolTableType *SymbolTable, char *name);
FILE *UILOpen(char *FileName,char *mode,FILE *old) ;
char *Substitute(char *buffer);
void ReadWidgetTree(UilModuleType *Module);
void PrintWidgetTree(UilModuleType *Module);
void PrintWidgets(UilModuleType *Module);
void MakePixmap(Display *d, Pixmap *pixmap, PixmapType *data, Pixel fg, Pixel bg);
void FreeSymbolTable(SymbolTableType *t);
void GetCallbacks(int fileno, int wid_id, DummyWidget *DW);
void GetCallbacks(int fileno, int wid_id, DummyWidget *DW);
void AddGeometryAttributes(GeoType **GeometryList, int module_id, int this_id,
		      DummyWidget *DW);
void SetGeometryAttributes(GeoType **GeometryList);
void ReadList(UilModuleType *Module);
void ReadWidgets(UilModuleType *Module);
void PrintArgs(SymbolTableType *Next);
void PrintControls(int count, int *ids, DummyWidget *Array);
void PrintCallbacks(callbackType *Next);
void PrintSymbolTable(SymbolTableType *SymbolTable);
SymbolTableType *LookUpAddr(char *temp, int module_id);
char *CreateFontListFromFontName(char *FontName);

GeoType *GeometryList = NULL;

SymbolTableType *ReadAttributes();
void ReadCallbacks(callbackType **last);
char *ReadType(int type);

SymbolTableType *GlobalSymbolTable = NULL;
int NumberFiles;    
String *FileList;

int MaxAttributes;

#define MAX_HIER 20
static int MaxHier;

UilModuleType UilModule[MAX_HIER];

int NumberRegisteredFunctions;
extern MrmRegisterArg *RegisteredFunctions;
XmString DecodeComplexString(StringType *value, int module_id, char *ascii);
void Xm_List(Widget parent_widget, DummyWidget *DW, int module_id);

void GetAttributes(Display *d,Window w, int module_id, 
		   int *n, Arg *args,
		   DummyWidget *DW, SymbolTableType 
		   *FormSymbolTable, int OnGeometry);

void MrmInitialize ()
{
}


#define MAX_DEF 2048
#define MAX_STR 256

Cardinal MrmCloseHierarchy(MrmHierarchy hierarchy_id)
{
  return MrmSUCCESS;
}

Cardinal MrmOpenHierarchy( MrmCount num_files , String *name_list , MrmOsOpenParamPtr *os_ext_list , MrmHierarchy *hierarchy_id_return )
{
  Exit(LOC, "Must replace MrmOpenHierarchy with MrmOpenHierarchyPerDisplay\nBecause I can't figure out how to get the display if you don't\n");
  return MrmFAILURE;
}

Cardinal MrmOpenHierarchyPerDisplay( Display *theDisplay, MrmCount num_files , String *name_list , MrmOsOpenParamPtr *os_ext_list , MrmHierarchy *hierarchy_id_return )
{
  int fileIndex;


  /*
     MrmSUCCESS     The function executed successfully.
     
     MrmFAILURE     The function failed.
     */
  display = theDisplay;
  window = DefaultRootWindow(theDisplay);
  theScreen = XDefaultScreenOfDisplay(theDisplay);
  colormap = DefaultColormapOfScreen(theScreen);

  XtGetApplicationNameAndClass(display, &theName, &theClass);

  NumberFiles = num_files;
  FileList = name_list;

  hierarchy_id_return = NULL;

  for (fileIndex = 0; fileIndex < num_files; fileIndex++) {
    if (NULL == UILOpen(FileList[fileIndex],"r",stdin)) {
      Exit(LOC, "Can't open %s\n", FileList[fileIndex]);
    }
    ReadWidgetTree(&UilModule[fileIndex]);
    if (1) {
      fprintf(stderr,"GLOBAL *******\n");
      PrintSymbolTable(GlobalSymbolTable);
      fprintf(stderr,"LOCAL  %d\n",fileIndex);
      PrintSymbolTable(UilModule[fileIndex].SymbolTable);
      PrintWidgetTree(&UilModule[fileIndex]);
    }
  }
  MaxHier = fileIndex;
  return MrmSUCCESS;
}

Cardinal MrmRegisterNames(MrmRegisterArglist reglist, MrmCount num_reg)
{
/*
       MrmSUCCESS     The function executed successfully.

       MrmFAILURE     The function failed.
*/
	NumberRegisteredFunctions = num_reg;
	RegisteredFunctions = reglist;
	return MrmSUCCESS;
}

Cardinal MrmFetchIconLiteral(MrmHierarchy hierarchy_id, String index,
			     Screen *scrn, Display *d, Pixel fg, Pixel bg, 
			     Pixmap *pixmap)
{
  SymbolTableType *symbol;

  for (symbol = GlobalSymbolTable; symbol; symbol = symbol->Next)
    if (strcmp(index, symbol->Name) == 0) {
      if (MrmRtypeXBitmapFile == symbol->type) {
	BitMapType *bm = (BitMapType *)symbol->value;

	*pixmap = XCreatePixmapFromBitmapData(d, window, bm->data, 
					     bm->width, bm->height,
					     fg,bg, 
					     DefaultDepth(display,0));
      }
      else
	MakePixmap(d, pixmap, (PixmapType *)symbol->value, fg, bg);
      return MrmSUCCESS;
    }
  return MrmNOT_FOUND;
}

void MakePixmap(Display *d, Pixmap *pixmap, PixmapType *data, Pixel fg, 
		Pixel bg)
{
  char *temp, *value;
  char buffer[256];
  int fileno;
  ColorTableHeaderType *ColorTableHeader;
  ColorTableType *ColorTable;
  XmXpmAttributes attributes;
  char Header[256];
  char **andrew = NULL;
  int NumColors;
  int i, j, k, Index;
  SymbolTableType *symbol;
  GC *GCTable;
  XColor exact, def;
  char *Image;
  ColorDefType *Color;

  attributes.valuemask = 0;
  temp = data->ColorTable;
  if (NULL == (symbol = LookupValue(GlobalSymbolTable, temp))){
    for (fileno = 0; fileno < NumberFiles; fileno++) { 
      if ( NULL != 
	  (symbol = LookupValue(UilModule[fileno].SymbolTable, temp)))
	break;
    }
    if (NULL == symbol)
      Exit(LOC, "Couldn't find %s in symbol tables\n",temp);
  }
  ColorTableHeader = (ColorTableHeaderType *)symbol->value;
  ColorTable = ColorTableHeader->ColorTable;
  NumColors = ColorTableHeader->NumColors;
  GCTable = (GC *) malloc(sizeof(GC) * NumColors);
  if (NULL == ColorTable[0].StringXPM) {
    long theColor;

    for (i = 0; i < NumColors; i++) {
      value = ColorTable[i].Color;
      if (ColorTable[i].IsAddress) {
	if (NULL == (symbol = LookupValue(GlobalSymbolTable, value))){
	  for (fileno = 0; fileno < MaxHier; fileno++) { 
	    if ( NULL != 
		(symbol =LookupValue(UilModule[fileno].SymbolTable,value)))
	      break;
	  }
	  if (NULL == symbol)
	    Exit(LOC, "Couldn't find %s in symbol tables\n",value);
	}
	value = symbol->value;
      }
      Color = (ColorDefType*)value;
      sprintf(buffer, "%s     c %s",ColorTable[i].Reference, Color->name);
      GCTable[i] = XCreateGC(d, window, 0, NULL);
      if (Color->name) {
	if (strcmp(Color->name, "_fg") == 0)
	  theColor = fg;
	else if (strcmp(Color->name, "_bg") == 0)
	  theColor = bg;
	else {
	  XAllocNamedColor(d, colormap, Color->name, &def, &exact);
	  theColor = def.pixel;
	}
      }
      else {
	def.red = Color->r;
	def.green = Color->g;
	def.blue = Color->b;
	if (XAllocColor(display, colormap, &def))
	  theColor = def.pixel;
	else
	  Exit(LOC, "Couldn't resolve color: %s\n",
	       Color->r, Color->g, Color->b);
      }
	
      XSetForeground(d, GCTable[i], theColor);
/*      ColorTable[i].StringXPM = Store(buffer); */
    }
  }
  andrew = (char **)malloc(sizeof(char *) * (1 + NumColors + data->width));
  sprintf(Header,"%d %d %d 1 -1 -1",data->width, data->height, NumColors);
  andrew[0] = Header;
  for (i = 0; i < NumColors; i++)
    andrew[i+1] = ColorTable[i].StringXPM;
  for (i = 0; i < data->width; i++)
    andrew[i+NumColors + 1] = &data->data[i*data->width];
  Image = data->data;

  /* the following is a total hack because I want to go to bed.  The Pixel
   * value in XmGetPixmapByDepth are totally made up. */
  *pixmap = XCreatePixmap(display, window, data->width, data->height, 
			  DefaultDepth(display,0));
  for (i = 0; i < data->height; i++) {
    for (j = 0; j < data->width; j++) {
      Index = -1;
      for (k = 0; k < NumColors; k++) {
	/* FIX ME  -- the following may need to compare more than one
	   byte in case each pixel of the image is wider
	   */
	if (strncmp(ColorTable[k].Reference, Image, 1) == 0) {
	  Index = k;
	  break;
	}
      }
      if (Index == -1)
	Exit(LOC, "Color Error\n");
      XDrawPoint(display, *pixmap, GCTable[Index], j, i);
      Image += 1;
    }
  }
#if 0
  if (_XmXpmCreateImageFromData(d, andrew, &im, &imshape, &attributes) ==
      XmXpmSuccess) {
    GC gc;

    *pixmap = XCreatePixmap(d, window, im->width, im->height, im->depth);

    gc = XCreateGC(d, window, 0, NULL);

    XPutImage(d, *pixmap, gc, im, 0, 0, 0, 0, im->width, im->height);

    XFreeGC(d, gc);

    /* this should probably be enabled */
#if 0
    XDestroyImage(im);
    if (imshape)
      XDestroyImage(imshape);
#endif

    _XmXpmFreeAttributes(&attributes);
  }
#endif

  free(andrew);
  free(GCTable);
}

Cardinal MrmFetchColorLiteral(MrmHierarchy hierarchy_id, String index,
			      Display *display, Colormap cmap,
			      Pixel *pixel_return)
{
/*
    XColor exact, def;
	SymbolTableType *value;
MrmCode type = 3;

  if (MrmSUCCESS == MrmMrmFetchLiteral(hierarchy_id, index, *display, (XtPointer *) value, &type)) {
    	XAllocNamedColor(display, cmap, value->value, &def, &exact);
	*pixel_return = (XtArgVal)def.pixel; 
	return MrmSUCCESS;
  }
*/
  return MrmFAILURE;
}

Cardinal MrmFetchLiteral(MrmHierarchy hierarchy_id, String index, Display *d, XtPointer *value, MrmCode *type)
{
  SymbolTableType *symbol;
/*
   MrmBAD_HIERARCHY
   MrmNOT_FOUND
   MrmWRONG_TYPE
   MrmFAILURE
*/
fprintf(stderr,"HEHE\n");
  for (symbol = GlobalSymbolTable; symbol; symbol = symbol->Next) {
    if (strcmp(index, symbol->Name) == 0) {
      *value = (XtPointer ) &symbol->value;
#if 0
      if (*type != symbol->type)
	return MrmWRONG_TYPE;
#endif
      return MrmSUCCESS;
    }
  }
  return MrmNOT_FOUND;
}
 
Cardinal MrmFetchWidgetOverride(MrmHierarchy hierarchy_id, String index, Widget parent_widget, String override_name, ArgList override_args, Cardinal override_num_args, Widget *widget, MrmType *class)
{
  Cardinal returnValue = 
    MrmFetchWidget(hierarchy_id, index, parent_widget, widget,class);
  XtSetValues(*widget,override_args,override_num_args);
  return returnValue;
}

static int FetchCount = 0;
SymbolTableType *InstantationSymbolTable = NULL;

Cardinal MrmFetchWidget(MrmHierarchy hierarchy_id, String index, Widget parent_widget, Widget *widget, MrmType *class)
{
  DummyWidget *DW = NULL;
  int this_id = -1, child_id = -1;  
  int i = 0;
  int k, n;
  int module_id = 0;
  Widget child;
  MrmType type;
  Bool Found = False;
  int file;
  Arg *args, ARGS[MAX_ARGS];
  int SizeArgs = 0;
  MyHierStruct *MyHier = (MyHierStruct *) hierarchy_id;
  char *CreateName;
  int CreateClass;

  FetchCount++;
  if (1 == FetchCount) {
    FreeSymbolTable(InstantationSymbolTable);
    InstantationSymbolTable = NULL;
  }
  parent = parent_widget;

  for (file = 0; !Found && (file < NumberFiles); file++) {
    for ( k = 0; k < UilModule[file].NumberOfWidgets; k++){
      if (strcmp(index,UilModule[file].DummyWidgetArray[k].Name) == 0) {
	module_id = file;
	Found = True;
	DW = &UilModule[file].DummyWidgetArray[k];
	this_id = k;
	break;
      }
    }
  }
  if (NULL == DW)
    Exit(LOC, "Looks like a corrupt uid file\n");

  if ((FetchCount != 1) && (NULL != hierarchy_id)) {
    args = MyHier->args;
    n = MyHier->argCount;
    SizeArgs = MyHier->SizeArgs;
    CreateName = MyHier->CreateName;
    CreateClass = MyHier->CreateClass;
  }
  else {
    CreateName = DW->Name;
    CreateClass = DW->class;
    n = 0;
    args = ARGS;
    SizeArgs = 0;
  }

  if (!Found) {
    fprintf(stderr,"Fetch return Not FOUND\n");
    FetchCount--;
    return (MrmNOT_FOUND);
  }

  GetAttributes(/*display*/ NULL, /*window*/ 0, 
		module_id, &n, args,
		DW, InstantationSymbolTable, ON_CREATE);

  if (DW->NumberOfInherit) {
    for (i = 0; i < DW->NumberOfInherit; i++) {
      char *index;
      int inherit_id;
      MyHierStruct *Hier;

      if (NULL == MyHier) {
	Hier = (MyHierStruct *) malloc(sizeof(MyHierStruct));
	Hier->CreateName = DW->Name;
	Hier->CreateClass = DW->class;
	Hier->args = args;
	Hier->argCount = n;
	Hier->SizeArgs = SizeArgs;
      }
      else
	Hier = MyHier;
      inherit_id = DW->inherit[i];
      index = UilModule[module_id].DummyWidgetArray[inherit_id-1].Name;

      MrmFetchWidget((MrmHierarchy)Hier, index, parent_widget, widget, class);
    }
  }
  else {
    if (XM_LIST_INDEX == CreateClass) {
      Xm_List(parent_widget, DW, module_id);
      *widget = NULL;
      FetchCount--;
      return MrmSUCCESS;
    }
  
    if (NULL == CreateFunctions[CreateClass].function) {
      char Name[20];
      strcpy(Name, &CreateFunctions[CreateClass].Name[2]);
      Name[0] = '*';
      *widget = XtNameToWidget(parent_widget, Name);
    }
    else {
      SymbolTableType *new =(SymbolTableType *)malloc(sizeof(SymbolTableType));
      
      *widget =CreateFunctions[CreateClass].function(parent_widget,
						     CreateName,args, n);
      new->value = (char *)*widget;
      new->Name = Store(CreateName);
      new->Next = InstantationSymbolTable;
      InstantationSymbolTable = new;
      new->type = ANOTHER_WIDGET;
    }
  }
  if (NULL == *widget){
    Exit(LOC, "Couldn't create widget %s",DW->Name);
  }
  UilModule[module_id].WidgetArray[this_id] = *widget;
  for (i = 0; i < DW->NumberOfChildren; i++) {
    Cardinal returnCode;
    DummyWidget *ChildDummy;

    child_id = DW->children[i];
    ChildDummy = &UilModule[module_id].DummyWidgetArray[child_id-1];

    if (MrmSUCCESS != 
	(returnCode = 
	 MrmFetchWidget(NULL, ChildDummy->Name,
			UilModule[module_id].WidgetArray[this_id],
				     &child, &type))) { 
      FetchCount--;
      return (returnCode); 
    }

    if ((0 == strcmp(CreateFunctions[DW->class].Name,"XmCascadeButton")) ||
	(0 == strcmp(CreateFunctions[DW->class].Name,"XmOptionMenu"))) {
      Arg args[1];

      XtSetArg(args[0], XmNsubMenuId, child);
      XtSetValues(UilModule[module_id].WidgetArray[this_id],args,1);
    }
    if (child && UilModule[module_id].DummyWidgetArray[child_id-1].managed) {
        XtManageChild(child); 
    }
  }

  n = 0;
  GetAttributes(/*display*/ NULL, /*window*/ 0, 
		module_id, &n, args,
		DW, InstantationSymbolTable, LATE);

  XtSetValues(*widget, args, n);
  GetCallbacks(module_id, this_id, DW);
  UilModule[module_id].WidgetArray[this_id] = *widget;
  AddGeometryAttributes(&GeometryList, module_id, this_id, DW);
  if (1 == FetchCount) {  /* Just before we return to initial caller do GEOM */
    SetGeometryAttributes(&GeometryList);
  } 
  FetchCount--;
  return MrmSUCCESS;
}

void AddGeometryAttributes(GeoType **GeometryList, int module_id, int this_id, 
		      DummyWidget *DW)
{
  GeoType *node = (GeoType *) malloc(sizeof(GeoType));
  node->module_id = module_id;
  node->this_id = this_id;
  node->next = *GeometryList;
  *GeometryList = node;
  node->DW = DW;
}

void SetGeometryAttributes(GeoType **GeometryList)
{
  GeoType *node = *GeometryList;
  GeoType *next;
  Arg args[MAX_ARGS];
  int n;
  Widget widget;

  while (node) {
    next = node->next;
    widget = UilModule[node->module_id].WidgetArray[node->this_id];
    n = 0;
    GetAttributes(/*display*/ NULL, /*window*/ 0, 
		  node->module_id, &n, args,
		  node->DW, InstantationSymbolTable, GEO);
    XtSetValues(widget, args, n); 
    free(node);
    node = next;
  }
  *GeometryList = NULL;
}
  
void GetCallbacks(int fileno, int wid_id, DummyWidget *DW)
{
  callbackType *Next = DW->callbacks;
  XtPointer ParameterValue;
  SymbolTableType *SymbolTable = NULL;
  Widget w = UilModule[fileno].WidgetArray[wid_id];

  while (Next) {
    if (Next->Parameters) {
      if (MrmRtypeAddrName == Next->Parameters->type) {
	char *temp;
	
	temp = Next->Parameters->value;
    	if ( 1 != LookUpPredefines(temp, (long *)&ParameterValue ))
	if ( NULL == 
	    (SymbolTable = LookupValue(UilModule[fileno].SymbolTable, temp))){
	  if (NULL == (SymbolTable = LookupValue(GlobalSymbolTable, temp))){
	    Exit(LOC, "Couldn't find %s in symbol tables\n",temp);
	  }
	}
      }
      else
	SymbolTable = (XtPointer) (Next->Parameters);
    }
    else
      ParameterValue = NULL;
    if (SymbolTable) {
      if (MrmRtypeInteger != SymbolTable->type)
	ParameterValue = (XtPointer) SymbolTable->value;
      else
	ParameterValue = (XtPointer) &( SymbolTable->value);
    }
    if (strcmp("createCallback", Next->argName) != 0)
      XtAddCallback(w, Next->argName,
		  (XtCallbackProc) LookUpFunction(Next->functionName),
		  ParameterValue);
    else
      ((XtCallbackProc)
	LookUpFunction(Next->functionName)) (w,ParameterValue,NULL);
    Next = Next->next;
  }
  return;
}

void GetAttributes(Display *d,Window w, int module_id, 
		   int *n, Arg *args,
		   DummyWidget *DW, SymbolTableType 
		   *FormSymbolTable, int State)
{
  int count = 0;
  XtArgVal value;
  SymbolTableType *Next = DW->attributes;
  int Do;
  
/*  *n = 0;   We will append to existing attributes - make sure n is 0 
              before calling this routine if that is intended 
*/
  while (Next) {
    if (Next->Access&S) {  /* Attribute can be set after widget creation */
      Do = (LATE == State);
    }
    else if (Next->Access&C) { /* Attribute must be set at creation time */
      Do = (ON_CREATE == State);
    }
    else {              /* Special '0' case - very late attribute setting*/
      Do = (GEO == State);
    }
    if (Do) {
      count = GetSymbolTableValue(&value, Next, module_id, FormSymbolTable);
      XtSetArg(args[*n], Next->Name, value);
      (*n)++;
      if (*n >= MAX_ARGS)
	Exit(LOC, "Too many args\n");
      if (count > 0) {        /* Certain attributes have a count associated */
	char buff[256];       /* with them.  This is a temporary(?) way to  */
	                      /* identify them and automatically include it */
	if (0 == strcmp(Next->Name,XmNitems))
	  strcpy(buff, XmNitemCount);
#if XmVERSION > 1
	else if (0 == strcmp(Next->Name,XmNdetail))
	  strcpy(buff, XmNdetailCount);
	else if (0 == strcmp(Next->Name,XmNdetailColumnHeading))
	  strcpy(buff, XmNdetailColumnHeadingCount);
	else if (0 == strcmp(Next->Name,XmNvalues))
	  strcpy(buff, XmNnumValues);
#endif
	else
	  Warn(LOC, "Can't find %s\n",Next->Name);
	XtSetArg(args[*n], buff, count); (*n)++;
	if (*n >= MAX_ARGS)
	  Exit(LOC, "You guessed it - Too many args\n");
      }
    }
    Next = Next->Next;
  }
}

int GetSymbolTableValue(XtArgVal *value, SymbolTableType *Next, 
			     int module_id, SymbolTableType *FormSymbolTable)
{
  int status = 0;
  char *temp;
  BitMapType *bitmap;
  SymbolTableType *SymbolTable;

  switch(Next->type) {
  case MrmRtypePixmapImage: {
    PixmapType *data;
    char *Image;
    Pixel fg,bg;
    Pixmap icon;

    data = (PixmapType *) Next->value;
    Image = data->data;
    XtVaGetValues(parent, XmNforeground, &fg, XmNbackground, &bg, NULL, NULL);
    MakePixmap(display, &icon, data, fg, bg);
    *value = (long) icon;

    break;
  }
  case MrmRtypeXBitmapFile: 
    bitmap = (BitMapType *) Next->value;;
    *value = (long)XCreateBitmapFromData(display,window, 
					bitmap->data,
					bitmap->width, bitmap->height);
    break;
  case MrmRtypeKeysym: {
    char *sym = (char *) Next->value;
    if ('~' == sym[0]) {
      temp = &sym[1];
      if ( NULL == 
	  (SymbolTable = LookupValue(UilModule[module_id].SymbolTable, temp))){
	if (NULL == (SymbolTable = LookupValue(GlobalSymbolTable, temp))){
	  if (NULL == (SymbolTable = LookupValue(FormSymbolTable,temp))) {
	    Exit(LOC, "Could not find %s\n", temp);
	  }
	}
      }
      *value = XStringToKeysym(SymbolTable->value);
    }
    else
      *value = XStringToKeysym(Next->value);
    break;
  }
  case MrmRtypeInteger:
  case MrmRtypeBoolean:
    *value = (long) Next->value;
    break;
  case MrmRtypeFont:{
    XFontStruct *theFont = XLoadQueryFont(display,Next->value);
    XmFontListEntry theEntry;

    if (NULL == theFont)
      Exit(LOC, "Can't load font %s\n", Next->value);
    theEntry = XmFontListEntryCreate(XmFONTLIST_DEFAULT_TAG,
				     XmFONT_IS_FONT, theFont);
    *value = (long) XmFontListAppendEntry(NULL, theEntry);
    break;
  }
  case MrmRtypeFontList: {
    int i;
    FontTableHeaderType *theHeader = (FontTableHeaderType *)Next->value;
    XmFontList theFontList = NULL;
    XmFontListEntry theEntry;
    char *FontName;
    char *TagName;
    SymbolTableType *symbolTable;

    for (i = 0; i < theHeader->NumFonts; i++) {
      FontName = theHeader->FontTable[i].FontName;
      TagName = theHeader->FontTable[i].Tag.name;
      if (0 == TagName[0])
	TagName = XmFONTLIST_DEFAULT_TAG;
      symbolTable = LookUpAddr(FontName, module_id);
fprintf(stderr,"LOOKUP FONT %s\n", FontName);
      if (NULL == symbolTable)
	Exit(LOC, "Can't find %s in the symbol tables\n", FontName);
      FontName = (char *) symbolTable->value;

/* RtoL = theHeader->FontTable[i].Tag.DirectionRtoL; */
/* WideChar = theHeader->FontTable[i].Tag.WideChar; */

      theEntry = XmFontListEntryLoad(display, FontName, XmFONT_IS_FONT,
				     TagName);
      theFontList = XmFontListAppendEntry(theFontList, theEntry);
      XmFontListEntryFree(&theEntry);
    }
    *value = (long) theFontList;
    break;
  }
  case MrmRtypeColor: {
    XColor exact, def;
    ColorDefType *Color = (ColorDefType *) (Next->value);
    
    if (Color->name) {
      if (XAllocNamedColor(display, colormap, Color->name, &def, &exact)) {
	*value = (XtArgVal)def.pixel; 
      }
      else
	Exit(LOC, "Couldn't resolve color: %s\n",Next->value);
    }
    else {
      def.red = Color->r;
      def.green = Color->g;
      def.blue = Color->b;
      if (XAllocColor(display, colormap, &def))
	*value = (XtArgVal)def.pixel;
      else
	Exit(LOC, "Couldn't resolve color: %s\n",Next->value);
    }
    break;
  }
  case MrmRtypeAddrName:
    temp = Next->value;
    if ( 1 == LookUpPredefines(temp, value))
	break;
    if ( NULL == 
	(SymbolTable = LookupValue(UilModule[module_id].SymbolTable, temp))){
      if (NULL == (SymbolTable = LookupValue(GlobalSymbolTable, temp))){
	if (NULL == (SymbolTable = LookupValue(FormSymbolTable,temp))) {
	  Exit(LOC, "Could not find %s\n", temp);
	}
      }
    }
    status=GetSymbolTableValue(value, SymbolTable, module_id, FormSymbolTable);
    break;
  case MrmRtypeChar8Vector:{
    XmString *strings;
    char **array;
    char **temparray;
    int i = 0;
    
    array = (char **) Next->value;
    for (temparray = array; *temparray; temparray++) i++;
    strings = (XmString *) malloc(i*sizeof(XmString*));
    for (i = 0; *array; array++,i++){
      char *sym;
      sym = *array;
      if ('~' == sym[0]) {
	temp = &sym[1];
	if ( NULL == 
	    (SymbolTable=LookupValue(UilModule[module_id].SymbolTable, temp))){
	  if (NULL == (SymbolTable = LookupValue(GlobalSymbolTable, temp))){
	    if (NULL == (SymbolTable = LookupValue(FormSymbolTable,temp))) {
	      Exit(LOC, "Could not find %s\n", temp);
	    }
	  }
	}
	strings[i] = XmStringCreate(SymbolTable->value,XmFONTLIST_DEFAULT_TAG);
      }
      else
	strings[i] = XmStringCreate(*array, XmFONTLIST_DEFAULT_TAG);
    }
    *value = (XtArgVal) strings;
    status = i;
    break;
  }
  case MrmRtypeChar8:
    *value = (XtArgVal) XmStringCreateSimple(Next->value); 
    break;
  case MrmRtypeCString:
    *value = (XtArgVal) 
      DecodeComplexString((StringType *)Next->value,module_id, NULL);
    break;
  case ANOTHER_WIDGET:  /* Another Widget */
    *value = (XtArgVal) (Next->value);
    break;
  default:
    Exit(LOC, "UNKNOWN ATTRIBUTE: %d\n", Next->type);
  }
  return status;
}

XmString DecodeComplexString(StringType *stringC, int module_id, char *ascii)
{   
  SymbolTableType *st;
  StringType *tempC; 
  XmString s = NULL;
  static char a[2048];
  
  a[0] = 0;
  for (;stringC;stringC = stringC->Next) {
    if (stringC->IsAddr) {
      tempC = stringC;
      st = LookUpAddr(stringC->theString, module_id);
      if (NULL == st)
	Exit(LOC, "Could not find %s\n", stringC->theString);
      tempC = (StringType *)st->value;
      s = XmStringConcat(s,DecodeComplexString(tempC, module_id, NULL));
    }
    else {
      s = XmStringConcat(s, XmStringCreate(stringC->theString, 
					   stringC->theFontSet));
      strncat(a,stringC->theString,2048);
      if (stringC->IsSeparator) {
	strcat(a,"\n");
	s = XmStringConcat(s, XmStringSeparatorCreate());
      }
    }
  }
  if (ascii != NULL)
    ascii = &a[0];
  return s;
}
  
SymbolTableType *GetSymbolTable(SymbolTableType *Table)
{
  char name[256], ch;
  int i;
  SymbolTableType *NewTable = NULL;
  SymbolTableType *LastTable = NULL;

  if (Table)
    for (LastTable = Table; LastTable->Next; LastTable = LastTable->Next)
      ;
  for (ch = getchar(); ch; ch = getchar()) {
    for (i = 0,name[i] = ch; name[i] != '"'; i++,name[i] = getchar()) 
      ;
    name[i] = 0;
    NewTable = (SymbolTableType *)malloc(sizeof(SymbolTableType));
    NewTable->Next = NULL;
    if (LastTable) {
      LastTable->Next = NewTable;
    }
    else if (NULL == Table)
      Table = NewTable;
    LastTable = NewTable;
    NewTable->Name = Store(name);
    NewTable->type = getchar();
    NewTable->value = ReadType(NewTable->type);
  }
      
  if (NULL == Table)
    return NewTable;
  else
    return Table;
}

SymbolTableType *
LookupValue(SymbolTableType *SymbolTable, char *name)
{
  while (SymbolTable) {
    if (0 == strcmp(SymbolTable->Name,name))
      return SymbolTable;
    else
      SymbolTable = SymbolTable->Next;
  }
  return NULL;
}

void PrintWidgetTree(UilModuleType *Module)
{
  PrintWidgets(Module);
}
/* LIST SYMBOL_TABLE(Global) SYMBOL_TABLE(local) WIDGETS */
void ReadWidgetTree(UilModuleType *Module)  
{
  ReadList(Module);
  GlobalSymbolTable = 
    GetSymbolTable(GlobalSymbolTable); 
  Module->SymbolTable = 
    GetSymbolTable(NULL);
  ReadWidgets(Module);
}

/* LIST = INT(count) NAMES  CHAR(0) */
void ReadList(UilModuleType *Module)
{
  int NumberOfWidgets;
  int i; 
  char c;

  fread(&NumberOfWidgets,sizeof(int), 1, stdin);  /* INT(widget count)  */
  fread(&MaxAttributes,sizeof(int), 1, stdin);    /* INT(max attributes)  */

  Module->NumberOfWidgets = NumberOfWidgets;
  Module->Definitions = (char **) malloc(sizeof(char *) * NumberOfWidgets);
  Module->WidgetArray = (Widget *) malloc(sizeof(Widget) * NumberOfWidgets);
  Module->DummyWidgetArray = (DummyWidget *) 
    malloc(sizeof(DummyWidget) * NumberOfWidgets);

  for (i = 0; (((c = getc(stdin)) != EOF) && c);i++) { /* NAMES CHAR(0)   */
    char string[MAX_STR];
    int j = 0;

    for(j = 0; (c != EOF) && (c != '"'); j++){ /* NAMES = NAME "  */
      string[j] = c;                                 /* NAME = [^"]*    */
      if (j >= MAX_STR)
	Exit(LOC, "String def too long\n");
      c = getc(stdin);
    }
    string[j] = 0;
    Module->DummyWidgetArray[i].Name = Store(string);
  }
  if (c) 
    Exit(LOC, "ERROR in header\n");
}

void PrintWidgets(UilModuleType *Module)
{
  DummyWidget *DW;
  int i;

  for (i = 0; i < Module->NumberOfWidgets; i++) {
    DW = &Module->DummyWidgetArray[i];
    fprintf(stderr,"oject %s: %s {\n",DW->Name,
	    CreateFunctions[DW->class].Name);
    PrintArgs(DW->attributes);
    PrintControls(DW->NumberOfChildren,DW->children, Module->DummyWidgetArray);
    PrintCallbacks(DW->callbacks);
    fprintf(stderr,"};\n");
  }
}

void PrintArgs(SymbolTableType *Next)
{
  fprintf(stderr,"\targuments {\n");
  while (Next) {
    switch (Next->type) {
    case MrmRtypeInteger:
    case MrmRtypeBoolean:
      fprintf(stderr,"\t\t%s = %d;\n",Next->Name,(int)Next->value);
      break;
    case MrmRtypeKeysym:
    case MrmRtypeChar8:
    case MrmRtypeAddrName:
      fprintf(stderr,"\t\t%s = \"%s\";\n",Next->Name,Next->value);
      break;
    case MrmRtypeCString:
      fprintf(stderr,"COMPLEX STRING\n");
      break;
    default:
      fprintf(stderr,"!  ????  %s \n",Next->Name);
      break;
    }
    Next = Next->Next;
  }
  fprintf(stderr,"\t};\n");
}

void PrintControls(int count, int *ids, DummyWidget *Array)
{
  int i; 
  DummyWidget *DW;

  fprintf(stderr,"\tcontrols {\n");
  for (i = 0; i < count; i++){
    DW = &Array[ids[i]-1];
    fprintf(stderr,"\t\t%s %s;\n", CreateFunctions[DW->class].Name, DW->Name);
  };
  fprintf(stderr,"\t}\n");
}

void PrintCallbacks(callbackType *Next)
{
  SymbolTableType *NextParam;

  fprintf(stderr,"\tcallbacks {\n");
  while (Next) {
    fprintf(stderr,"\t\t%s = procedure %s(",
	    Next->argName, Next->functionName);
    for (NextParam = Next->Parameters; NextParam; NextParam = NextParam->Next)
      switch (NextParam->type) {
      case MrmRtypeInteger:
      case MrmRtypeBoolean:
	fprintf(stderr,"%d",(int) NextParam->value);
	break;
      case MrmRtypeKeysym:
      case MrmRtypeAddrName:
      case MrmRtypeChar8:
	fprintf(stderr,"%s",NextParam->value);
	break;
      case MrmRtypeCString:
	fprintf(stderr,"COMPLEX STRING\n");
	break;
      default:
	break;
      }
    fprintf(stderr,");\n");
    Next = Next->next;
  };
  fprintf(stderr,"\t};\n");
}
/*
// WIDGETS = WIDGET WIDGETS
//         | NULL
*/
void ReadWidgets(UilModuleType *Module)
{
  char c;
  int WidgetIndex;
  DummyWidget *DW;
  int i, index, size;
  int this_id, child_id,inherit_id;
  char temp[256];

/*
   In the following definition:

   integer size = 4 bytes
   
   INT(0) - an integer sized zero to mark
   the end of a list  e.g. INHERIT is a list of inherited widgets but
   if a widget id of zero is read, we know we have come to the end of the list
   
   CHAR(MrmTypeClassRecName) - a byte sized value of 22 (MrmTypeClassRecName) 
   to indicate the start of a widget.
*/
  
/* WIDGET = CHAR(MrmTypeClassRecName) NAME(widget's name) " INT(id) INT(class) 
//           CHAR(managed) INT(parent) INHERIT INT(0) CHILDREN INT(0) 
//           CALLBACKS TABLE(attributes)
*/
  for (c = getc(stdin), WidgetIndex = 0;
       c == MrmRtypeClassRecName;
       c = getc(stdin),WidgetIndex++) {  /* CHAR(MrmTypeClassRecName) */
    for (i = 0,c = getchar(); c != '"'; c = getchar(),i++) { /* NAME " */
      temp[i] = c; 
    }
    temp[i] = 0;
    DW = &Module->DummyWidgetArray[WidgetIndex];
    DW->Name = Store(temp);
if (strcmp(DW->Name, "templatePick") == 0)
fprintf(stderr,"STOP\n");
    fread(&this_id, sizeof(this_id), 1, stdin);       /*INT(id)    */
    if (this_id != (WidgetIndex+1))
      Exit(LOC, "INDEX ERROR:widgets should be stored in file by id number\n");
    fread(&DW->class, sizeof(DW->class), 1, stdin);     /*INT(class) */
    fread(&DW->managed, sizeof(DW->managed), 1, stdin); /*CHAR(managed) */
    fread(&DW->parent, sizeof(DW->parent), 1, stdin);   /*INT(parent)*/
    DW->inherit = NULL;
    size = 0;
    index = 0;
    for (fread(&inherit_id,sizeof(inherit_id), 1, stdin); /*INHERIT = INT INH*/
	 inherit_id;                                      /*INT(0)  */
	 fread(&inherit_id,sizeof(inherit_id), 1, stdin)) {
      if (size <= index) {
	size += 10;
	DW->inherit = (int *) realloc(DW->inherit, size * sizeof(inherit_id));
      }
      DW->inherit[index] = inherit_id;
      index++;
    }
    DW->NumberOfInherit = index;
    DW->children = NULL, size = 0, index = 0;
    for (fread(&child_id, sizeof(child_id), 1, stdin);/*CHILDREN=INT CHILDREN*/
	 child_id;                                    /*INT(0) */
	 fread(&child_id, sizeof(child_id), 1, stdin)) {
      if (size <= index) {
	size += 10;
	if (DW->children)
		DW->children = 
			(int *)realloc(DW->children, size * sizeof(child_id));
	else
		DW->children = 
			(int *)malloc(size * sizeof(child_id));
      }
      DW->children[index] = child_id;
      index++;
    }
    DW->NumberOfChildren = index;
    ReadCallbacks(&(DW->callbacks));
    DW->attributes = ReadAttributes();
  }
}

/* CALLBACKS = CHAR(MrmRtypeCallback) INT(id) INT(index) NAME(argname) " 
//               NAME(function name) " CHAR(# of params) PARAMS CALLBACKS
//           | NULL
// PARAMS = CHAR(type) INT(value) PARAMS      integer,bool
//        | CHAR(type) STRING CHAR(0) PARAMS   AddrName,CString,String,keysym
*/
void ReadCallbacks(callbackType **first)
{
  char c,temp[MAX_BUFFER];
  int i;
  SymbolTableType **ParamPointer;
  char NumberOfParams;
  callbackType *last;
  callbackType *new;

  *first = last = NULL;
  c = getchar();
  for (; c == MrmRtypeCallback; c = getchar()) { /* CHAR(MrmRtypeCallback) */
    new = (callbackType *) malloc(sizeof(callbackType));
    new->Parameters = NULL;
    new->next = NULL;
    if (last)
      last->next = new;
    last = new;
    if (NULL == *first)
      *first = new;
    fread(&new->id, sizeof(new->id), 1, stdin);      /* INT(id)     */
    for (i = 0,c = getchar(); c != '"'; c = getchar())       /* NAME(argname)*/
      temp[i++] = c;
    temp[i] = 0;
    new->argName = Store(temp);
    for (i = 0,c = getchar(); c != '"'; c = getchar())/* NAME(function name) */
      temp[i++] = c;
    temp[i] = 0;
    new->functionName = Store(temp);
/* PARAMS = CHAR(type) INT(value) PARAMS      integer,bool       */
/*        | CHAR(type) STRING CHAR(0) PARAMS   AddrName,CString,String,keysym*/
    NumberOfParams = getchar();
    ParamPointer = &(new->Parameters);
    new->Parameters = NULL;
    for (i = 0; i < NumberOfParams; i++) {
      *ParamPointer = (SymbolTableType *) malloc(sizeof(SymbolTableType));
      (*ParamPointer)->type = getchar();
      (*ParamPointer)->value = ReadType((*ParamPointer)->type);
      (*ParamPointer)->Next = NULL;
      ParamPointer = &((*ParamPointer)->Next);
    }
  }
  ungetc(c,stdin);
}

/*  TABLE(attributes) = EXPRESSION TABLE(attributes)
//                    | NULL
*/
SymbolTableType *ReadAttributes()
{
  char c;
  SymbolTableType *Return = NULL, *Next, *Last = NULL;

fprintf(stderr,"READ ATTRIBUTES\n");
/* EXPRESSION = CHAR(MrmRtypeResource) NAME " CHAR(type) INT(value)
//        | CHAR(MrmRtypeResource) NAME " CHAR(type) NAME(string value) CHAR(0)
//        | CHAR(MrmRtypeResource) NAME " CHAR(type) NAME(bitmap value) CHAR(0)
//        | CHAR(MrmRtypeResource) NAME " CHAR(type) NAME(pixmap value) CHAR(0)
*/
  for (c = getchar(); 
       c == MrmRtypeResource; 
       c = getchar()) { /* CHAR(MrmRtypeResource) */
    Next = (SymbolTableType *) malloc(sizeof(SymbolTableType));
    Next->Next = NULL;
    if (NULL == Last)
      Return = Next;
    else
      Last->Next = Next;
    fread(&(Next->Index), sizeof(Next->Index), 1, stdin);
    GetArgValues(Next->Index, &Next->Name, &Next->Access);
    Next->type = getchar();                   /* CHAR(type) */
    Next->value = ReadType(Next->type);
    Last = Next;
  }
  ungetc(c,stdin);
  return Return;
}

char *ReadType(int type)
{
  int i,j;
  char buffer[MAX_BUFFER];
  char *temp;
  char *ReturnValue;
    
  switch(type) {
  case MrmRtypeInteger:
  case MrmRtypeBoolean:
    fread(&ReturnValue,sizeof(long), 1, stdin);
    break;
  case MrmRtypeXBitmapFile: {
    int SizeOfData;
    BitMapType *bitmap;
    
    bitmap = (BitMapType *)malloc(sizeof(BitMapType));
    fread(bitmap, sizeof(BitMapType)-sizeof(long), 1, stdin);
    SizeOfData = bitmap->width*bitmap->height>>3;
    bitmap->data = (char *)malloc(SizeOfData);
    fread(bitmap->data, sizeof(char), SizeOfData, stdin);
    ReturnValue = (char *) bitmap;
    break;
  }
  case MrmRtypeChar8Vector:{
    char *last;
    char **array = NULL;
    int size = 0;
    int index = 0;
    temp = last = &buffer[0];
    while ((*temp = getchar())) {
      if ('"' == *temp) {
	*temp = 0;
	if (size <= index) {
	  size += 10;
	  array = (char **)realloc(array, size * sizeof(char *));
	}
	array[index] = Store(last);
	index++;
	last = temp+1;
      }
      temp++;
    }
    array[index] = NULL;
    ReturnValue = (char *) array;
    break;
  }
  case MrmRtypeKeysym:
    temp = &buffer[0];
    while ((*temp++ = getchar()));
    ReturnValue = (char *) Store(buffer);
    break;
  case MrmRtypeChar8: {
    StringType *theString = (StringType *) malloc(sizeof(StringType));
    temp = &buffer[0];
    while ((*temp++ = getchar()));
    fprintf(stderr,"name = %s  ", buffer);
    theString->theString = (char *) Store(buffer);
    temp = &buffer[0];
    while ((*temp++ = getchar()));
    theString->theFontSet = Store(buffer);
    ReturnValue = (char *) theString;
    break;
  }
  case MrmRtypeCString: {
    StringType **handle;
    fprintf(stderr,"READING COMPLEX STRING\n");

    ReturnValue = NULL;
    handle = (StringType **)&ReturnValue;
    while (1) {
      for (i = 0; (i < MAX_BUFFER) && (buffer[i] = getchar()); i++);
      if (0 == i) {
	break;
      }
      if (MAX_BUFFER == i)
	Exit(LOC, "Static storage area exhausted\n");
      (*handle) = (StringType *) malloc(sizeof(StringType));
      (*handle)->theString = Store(buffer);
      
      for (i = 0; (i < MAX_BUFFER) && (buffer[i] = getchar()); i++);
      if (MAX_BUFFER == i)
	Exit(LOC, "Static storage area exhausted: %s\n",buffer);
      (*handle)->theFontSet = Store(buffer);
      (*handle)->IsAddr = getchar();
      (*handle)->IsSeparator = getchar();
      (*handle)->Next = NULL;
      handle = &((*handle)->Next);
    }
    fprintf(stderr,"COMPLEX DONE\n");
    break;
  }
  case MrmRtypeFontList: {  /* INT(size) FONT_TABLE */
    FontTableType *FontTable;
    FontTableHeaderType *FontTableHeader;
    int NumFonts;
    fread(&NumFonts,sizeof(int), 1, stdin);
    FontTable = (FontTableType *) malloc(sizeof(FontTableType) * NumFonts);
    FontTableHeader = (FontTableHeaderType *) malloc(sizeof(FontTableHeader));
    /*                     FONT_TABLE = FONT_SET FONT FONT_TABLE */
    /*                     FONT_SET = CHAR(MrmRtypeFontSet) NAME INT(dir)
			                 INT(wideChar)  */
    FontTableHeader->FontTable = FontTable;
    FontTableHeader->NumFonts = NumFonts;  
    for (j = 0; j < NumFonts; j++) {
      char tempType;

      fread(&tempType, sizeof(char), 1, stdin);
      if (tempType != MrmRtypeFontSet)
	Exit(LOC, "There may be an internal bug with font table decoding. "
	     "%d read != %d from header.\n",tempType, MrmRtypeFontSet);
      for (i = 0; (i < MAX_BUFFER) && (buffer[i] = getchar()); i++);
      if (MAX_BUFFER == i)
	Exit(LOC, "Static storage area exhausted\n");
      FontTable[j].Tag.name = Store(buffer);
      fread(&FontTable[j].Tag.DirectionRtoL, sizeof(int), 1, stdin);
      fread(&FontTable[j].Tag.WideChar, sizeof(int), 1, stdin);

      /*                   FONT = CHAR(MrmTypeFont) NAME   */
      fread(&tempType, sizeof(char), 1, stdin);
      if (tempType != MrmRtypeFont)
	Exit(LOC, "There may be an internal bug with font table decoding\n");
      for (i = 0; (i < MAX_BUFFER) && (buffer[i] = getchar()); i++);
      if (MAX_BUFFER == i)
	Exit(LOC, "Static storage area exhausted\n");
      FontTable[j].FontName = Store(buffer);
    }
    ReturnValue = (char *) FontTableHeader;
    break;
  }
  case MrmRtypeColorTable: {
    ColorTableType *ColorTable;
    ColorTableHeaderType *ColorTableHeader;
    int NumColors;
    char type; 
    fread(&NumColors,sizeof(int), 1, stdin);
    ColorTable = (ColorTableType *)malloc(sizeof(ColorTableType)*NumColors);
    ColorTableHeader =(ColorTableHeaderType *)
          malloc(sizeof(ColorTableHeaderType));
    ColorTableHeader->ColorTable = ColorTable;
    ColorTableHeader->NumColors = NumColors;
    for (j = 0; j < NumColors; j++) {
      for (i = 0; (i < MAX_BUFFER) && (buffer[i] = getchar()); i++);
      if (MAX_BUFFER == i)
	Exit(LOC, "Static storage area exhausted\n");
      ColorTable[j].Reference = Store(buffer);
      fread(&type,sizeof(type), 1, stdin);  
      ColorTable[j].IsAddress = (MrmRtypeAddrName == type);
      ColorTable[j].StringXPM = NULL;
      for (i = 0; (i < MAX_BUFFER) && (buffer[i] = getchar()); i++);
      if (MAX_BUFFER == i)
	Exit(LOC, "Static storage area exhausted\n");
      ColorTable[j].Color = Store(buffer);
    }
    ReturnValue = (char *)ColorTableHeader;
    break;
  }
  case MrmRtypeColor: {
    ColorDefType *Color = (ColorDefType *) malloc(sizeof(ColorDefType));
    for (i = 0; (i < MAX_BUFFER) && (buffer[i] = getchar()); i++);
    if (MAX_BUFFER == i)
      Exit(LOC, "Static storage area exhausted\n");
    if (0 == i) {
      Color->name = NULL;
      fread(&Color->r, sizeof(int), 1, stdin);
      fread(&Color->g, sizeof(int), 1, stdin);
      fread(&Color->b, sizeof(int), 1, stdin);
    }
    else {
      Color->name = Store(buffer);
    }
    ReturnValue = (char *) Color;
    break;
  }
  case MrmRtypeFont:
    for (i = 0; (i < MAX_BUFFER) && (buffer[i] = getchar()); i++);
    if (MAX_BUFFER == i)
      Exit(LOC, "Static storage area exhausted\n");
    ReturnValue = Store(buffer);
    break;
  case MrmRtypePixmapImage: {
    PixmapType *pixmap;
    int SizeOfData;
    int i;
    
    pixmap = (PixmapType *)malloc(sizeof(PixmapType));
    fread(&pixmap->width, sizeof(int), 1, stdin);
    fread(&pixmap->height, sizeof(int), 1, stdin);
    SizeOfData = pixmap->width*pixmap->height;
    for (i = 0; (i < MAX_BUFFER) && (buffer[i] = getchar()); i++);
    if (MAX_BUFFER == i)
      Exit(LOC, "Static storage area exhausted\n");
    pixmap->ColorTable = Store(buffer);
    pixmap->data = (char *)malloc(SizeOfData);
    fread(pixmap->data, sizeof(char), SizeOfData, stdin);
    ReturnValue = (char *) pixmap;
    break;
  }
  case MrmRtypeAddrName:
    for (i = 0; (i < MAX_BUFFER) && (buffer[i] = getchar()); i++);
    if (MAX_BUFFER == i)
      Exit(LOC, "Static storage area exhausted\n");
    ReturnValue = Store(buffer);
    break;
  default:
    Exit(LOC, "UNKNOWN ATTRIBUTE: code = %d\n",type);
  }

  return ReturnValue;
#if 0


  char *ReturnValue;

  switch(Next->type) {
  case MrmRtypePixmapImage: {
    int SizeOfData;
    PixmapType *pixmap;
    char temp[MAX_BUFFER];
    int i;
    
    pixmap = (PixmapType *) malloc(sizeof(PixmapType));
    fread(pixmap, sizeof(PixmapType)-sizeof(long), 1, stdin);/*NAME(pixmap)*/
    for (i = 0; (i < MAX_BUFFER) && (temp[i] = getchar()); i++);  /*NAME(colortab*/
    if (2048 == i)
      Exit(LOC, "Static storage area exhausted\n");
    pixmap->ColorTable = Store(temp);
    SizeOfData = pixmap->width*pixmap->height;
      pixmap->data = (char *) malloc(SizeOfData);
    fread(pixmap->data, sizeof(char), SizeOfData, stdin);  /* image data */
    return((char *)pixmap);
    break;
  }
  case MrmRtypeXBitmapFile: {
    int SizeOfData;
    BitMapType *bitmap;
    
    bitmap = (BitMapType *)malloc(sizeof(BitMapType));
    fread(bitmap, sizeof(BitMapType)-sizeof(long), 1, stdin);/*NAME(bitmap)*/
    SizeOfData = bitmap->width*bitmap->height>>3;
    bitmap->data = (char *)malloc(SizeOfData);
    fread(bitmap->data, sizeof(char), SizeOfData, stdin);
    return ((char *) bitmap);
    break;
  }
  case MrmRtypeInteger:
  case MrmRtypeBoolean:
    fread(&ReturnValue, sizeof(ReturnValue), 1, stdin);    /* INT(value)*/
    return(ReturnValue);
    break;
  case MrmRtypeCString:
  case MrmRtypeChar8:
    i = 0;                   /* NAME(value) CHAR(0) */
    while ((i < MAX_BUFFER) && (temp[i++] = getchar()));   
    if (MAX_BUFFER == i) {
      temp[256] = 0;
      Exit(LOC, "String too complex: %s",temp);
    }
    temp[i] = 0;
    ReturnValue = Store(temp);  
    i = 0;                   /* NAME(tag) CHAR(0) */
    while ((i < MAX_BUFFER) && (temp[i++] = getchar()));   
    if (MAX_BUFFER == i) {
      temp[256] = 0;
      Exit(LOC, "String too complex: %s",temp);
    }
    temp[i] = 0;
    fprintf(stderr,"TAG = %s\n", temp);
    return (ReturnValue);
    break;
  case MrmRtypeKeysym:
  case MrmRtypeColor:
  case MrmRtypeAddrName:
    i = 0;                   /* NAME(value) CHAR(0) */
    while ((i < MAX_BUFFER) && (temp[i++] = getchar()));   
    if (MAX_BUFFER == i) {
      temp[256] = 0;
      Exit(LOC, "String too complex: %s",temp);
    }
    temp[i] = 0;
    return(Store(temp));  
    break;
  default:
    Exit(LOC, "Unknown Attribute type: %d\n",c);
  }
#endif

}

void Xm_List(Widget parent_widget, DummyWidget *DW, int module_id)
{
  Arg args[10];
  int n = 0;
  int i;
  int ListCount = 0;
  SymbolTableType *Next;
  XtArgVal value;
  char *temp;
  SymbolTableType *SymbolTable;
  XmString *ListItem;

  
  for (Next = DW->attributes; Next; Next = Next->Next) {
    switch(Next->type) {
    case MrmRtypeInteger:
      value = (long) Next->value;
      break;
    case MrmRtypeAddrName:
      temp = Next->value;
      if ( NULL == (SymbolTable = LookUpAddr(temp,module_id))) {
	LookUpPredefines(temp, &value);
	break;
      }
      if (0 == strcmp(Next->Name,"items")) {
	char **strings = (char **) SymbolTable->value;

	while (*strings++) 
	  ListCount++;
	ListItem = (XmString *) malloc(ListCount * sizeof(XmString));
	strings = (char **) SymbolTable->value;
	for (i = 0; i < ListCount; i++) {
	  char *sym = strings[i];
	  char s[256];

	  if ('~' == sym[0]) {
	    temp = &sym[1];
	    if ( NULL == 
		(SymbolTable= LookupValue(UilModule[module_id].SymbolTable, 
					  temp))){
	      if (NULL ==(SymbolTable =LookupValue(GlobalSymbolTable, temp))){
		Exit(LOC, "Could not find %s\n", temp);
	      }
	    }
	    strcpy(s, SymbolTable->value);
	    ListItem[i] = XmStringCreate(s, XmFONTLIST_DEFAULT_TAG);
	  }
	  else
	    ListItem[i] = XmStringCreate(strings[i], XmFONTLIST_DEFAULT_TAG);
	}
	value = (XtArgVal) ListItem;
      }
      else
	value = (XtArgVal) SymbolTable->value;
      break;
    default:
      Exit(LOC, "UNKNOWN ATTRIBUTE\n");
    }
    XtSetArg(args[n], Next->Name, value); n++;
  };
  XtSetArg(args[n], XmNitemCount, ListCount); n++;
  XtSetValues(XtNameToWidget(parent_widget,"*List"), args, n);
}


FILE *UILOpen(char *tFileName,char *mode,FILE *old) 
{
  FILE *Return = NULL;
  int i,j;
  char *theBase;
  char buffer[256];
  static char Eval = 0;
  char *Base[] = {
    "$HOME",
    "/usr/X11/lib/X11"
  };
  char *Paths[] = {
    "%L/uid/%N/%U%S",        
    "%l/uid/%N/%U%S",
    "uid/%N/%U%S",
    "%L/uid/%U%S",
    "%l/uid/%U%S",
    "uid/%U%S",
    "%U%S",
    "%T",
  };
  static int BaseSize = sizeof(Base)/sizeof(Base[0]);
  static int PathSize = sizeof(Paths)/sizeof(Paths[0]);
  char *UILPath;
  char FileName[256];
  
  for (i = 0; *tFileName; i++)
    FileName[i] = *tFileName++;
  FileName[i] = 0;
  if ((i < 4) || (strcmp(&FileName[i-4], ".uid") != 0))
    strcat(FileName,".uid");

  if (NULL != (Return = freopen(FileName,mode,old))) {
    fprintf(stderr,"Opening %s\n", FileName);
    return Return;
  }
  if (!Eval) {
    Eval = 1;
    for (j = 0; j < BaseSize; j++) {
      theBase = Base[j];
      if ('$' == theBase[0])
	Base[j] = getenv(&theBase[1]);
      fprintf(stderr,"Base %d = %s\n",j, Base[j]);
    }
  }
  UILPath = getenv("UILPATH");
  if (NULL != UILPath) {
    for (i = j = 0; ;j++, i++) {
      if ((':' == UILPath[i]) || (0 == UILPath[i])) {
	buffer[j++] = '/';
	strcpy(&buffer[j],FileName);
	j = -1;
	if (NULL != (Return = freopen(Substitute(buffer),mode,old))) {
	  Warn(LOC,"Opening %s\n", buffer);
	  return Return;
	}
	if (0 == UILPath[i])
	  break;
      }
      else
	buffer[j] = UILPath[i];
    }
  }
  for (j = 1; (NULL == Return) && (j < BaseSize); j++)
    if (Base[j])
      for(i = 0, sprintf(buffer,"%s/%s/%s", Base[j], Paths[i], FileName);
	  (NULL == (Return = freopen(Substitute(buffer),mode,old))) &&
	  ( i < PathSize);
	  i++,sprintf(buffer,"%s/%s/%s", Base[j], Paths[i], FileName)) {
      };
  if (NULL != Return)
    Warn(LOC, "Opening %s\n",buffer);
  return Return;
}

char *Substitute(char *buffer)
{
  static char buffer2[256];
  char *string = buffer2;
  
  while (*buffer) {
    if ('%' == *buffer) {
      buffer++;
      switch (*buffer++) {
      case 'N':
	strcpy(string,theName);
	string += strlen(theName);
	break;
      case 'U':
	strcpy(string,"FROM_LIST");   /* FIX ME */
	string += 9;
	break;
      case 'T':
	strcpy(string,"uid");
	string += 3;
	break;
      case 'S':
	strcpy(string,".uid");
	string += 4;
	break;
      case 'L':
	strcpy(string,"LANG");    /* FIX ME */
	string+=4;
	break;
      case 'l':
	strcpy(string,"lang");    /* FIX ME */
	string+= 4;
	break;
      default:
	Exit(LOC, "Unknown format\n");
      }
    }
    else {
      *string++ = *buffer++;
    }
  }
  *string = 0;
  return buffer2;
}

void PrintSymbolTable(SymbolTableType *SymbolTable)
{
  for (; SymbolTable; SymbolTable = SymbolTable->Next)
    fprintf(stderr,"      %s\n",SymbolTable->Name);
}


void FreeSymbolTable(SymbolTableType *t)
{
  SymbolTableType *n;

  while (t) {
    n = t->Next;
    free(t);
    t = n;
  }
}

SymbolTableType *LookUpAddr(char *temp, int module_id)
{
  SymbolTableType *SymbolTable;

  SymbolTable = LookupValue(UilModule[module_id].SymbolTable, temp);
  if (NULL == SymbolTable) {
    SymbolTable = LookupValue(GlobalSymbolTable, temp);
  }
  return SymbolTable;
}

