/***********************************************************************
 *
 *	Blox
 *
 *	Standardized, portable GUI widgets available for various window
 *	systems.
 *
 ***********************************************************************/

/***********************************************************************
 *
 * Copyright (C) 1994, 1995 Free Software Foundation, Inc.
 * Written by Steve Byrne.
 *
 * This file is part of GNU Smalltalk.
 *
 * GNU Smalltalk is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 1, or (at your option) any later 
 * version.
 * 
 * GNU Smalltalk 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 General Public License for
 * more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
 * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
 *
 ***********************************************************************/

/*
 *    Change Log
 * ============================================================================
 * Author      Date       Change 
 * sbb	      4 Jul 95	  Updated for new naming scheme.
 *
 * sbb	      4 Jul 94	  Created back in Feb or so.  Serious hacking this
 *			  weekend to make it work properly.
 * brd	      26 Sep 95  Added support for Dialog and Form widgets. Extended
 Text and List widget support. Corrected minor bugs.
 *
 */
#include <varargs.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/Label.h>
*/
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/MenuButton.h>
#include <X11/Xaw/Scrollbar.h>
#include <X11/Xaw/List.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Text.h>
#include <X11/Xaw/TextSrc.h>
#include <X11/Xaw/TextSink.h>
#include <X11/Xaw/AsciiSrc.h>
#include <X11/Xaw/AsciiSink.h>

#include <X11/Xaw/SmeBSB.h>
#include <X11/Xaw/SmeLine.h>

#include <X11/Xaw/Toggle.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Dialog.h>
#include <X11/Xaw/Form.h>

/* #include "mstcallin.h"
/* #include "mstcint.h" */
#include "gstpub.h"
#if STDC_HEADERS
#include <stdlib.h>
#endif /* STDC_HEADERS */
#include <stdio.h>

#define DEFAULT_LIST_HEIGHT 50
#define DEFAULT_LIST_WIDTH 100

/*#define USE_MALLOC */

typedef struct {
  OOP		receiver;
  char*		message;
} ButtonCallback;

typedef ButtonCallback ToggleCallback;

/* Right now, these two could be merged together */
typedef struct {
  OOP		receiver;
  char*		message;
} ListCallback;

typedef struct {
  OOP		receiver;
	int index;
} DlogButtonCallback;

typedef struct {
  OOP		receiver;
  char*		message;
	OOP   argument;
} MenuCallback;

typedef struct {
  unsigned short	red;
  unsigned short	green;
  unsigned short	blue;
} ColorDef;

typedef struct {
  Widget		menuButton;
  Widget		simpleMenu;
} MenuStruct;

typedef struct {
  Widget		viewport;
  Widget		list;
} ScrollListStruct;

typedef struct {
  Widget		container;
  Widget		widgetId;
  unsigned long		index;
} RadioGroupStruct;

typedef struct {
  char			isTopLevel;
  Widget		widget;
} WindowStruct;

typedef struct {
  OOP		receiver;
  char*		message;
  WindowStruct* window;
} WindowCallback;

static void bloxInit(),
	beginDispatchingEvents(),
	setHeight(), setWidth(), setX(), setY(),
	setEnabled(), setForegroundColor(), setBackgroundColor(), 
	destroyWidget(), terminateMainLoop(), positionInForm();

static long getHeight(), getWidth(), getX(), getY();
static int  getEnabled();
static ColorDef *getForegroundColor(), *getBackgroundColor();

static Widget getContainerObject();
static Widget getConnectedObject();

static voidPtr createColor();
static unsigned long allocateColor();

/* Button operations */

static Widget createButton();

static void setButtonCallback();

/* Container operations */

static Widget  createContainer();
static void setContainerLayout();

/* Form operations */

static Widget createForm();

/* Dialog operations */

static Widget createDialog();
static void dialogLoop();
static char* getDialogText();
static void addDialogButton();
static void addDialogButtonMessage();

/* Label operations */

static Widget createLabel();


/* List operations */

static ScrollListStruct *createList(); 

static void setListX(), setListY(), setListWidth(), setListHeight(),
	setListCallback(),
	setListContents(), 
	setListForegroundColor(), setListBackgroundColor(),
	setListEnabled(), destroyListWidget(),

	setRowSpacing(), setColumnSpacing(),
        setNumberOfColumns(),
	setVerticalLayout(),
        listHighlight(), listUnhighlight();

static long numberOfStrings();

static long getListHeight(), getListWidth(), getListX(), getListY();
static int  getListEnabled();
static ColorDef *getListForegroundColor(), *getListBackgroundColor();


static Widget getContainerListObject(), getViewportObject();

/* Menu bar operations */

static Widget createMenuBar();
static void addMenu(), removeMenu();

/* Menu operations */

static MenuStruct *createMenu(), *createPopupMenu();

static void addMenuItem(), removeMenuItem(),
	setMenuItemCallback(),
        setMenuItemKeywordCallback(),
	setMenuX(), setMenuY(), setMenuHeight(), setMenuWidth(),
	setMenuBackgroundColor(), setMenuForegroundColor(),
	setMenuEnabled(), destroyMenuWidget();

static long getMenuHeight(), getMenuWidth(), getMenuX(), getMenuY();
static int  getMenuEnabled();
static ColorDef *getMenuForegroundColor(), *getMenuBackgroundColor();


static Widget getContainerMenuObject();
static Widget getConnectedMenuObject();

/* Menu item operations */

static Widget createMenuItemLine(), createMenuItem();


/* Radio group operations */

static RadioGroupStruct* createRadioGroup();

static void
	setRadioGroupX(), setRadioGroupY(), setRadioGroupWidth(),
	setRadioGroupHeight(), setRadioGroupBackgroundColor(),
	setRadioGroupEnabled(),
	destroyRadioGroupWidget(),
	addRadioButton(), removeRadioButton();

static long
	getRadioGroupHeight(), getRadioGroupWidth(),
	getRadioGroupX(), getRadioGroupY();
static int
	getRadioGroupEnabled();
static ColorDef
	*getRadioGroupBackgroundColor();

static Widget getContainerRadioGroupObject();

/* Radio button operations */

static Widget createRadioButton();


/* Text operations */

static Widget createText();

static char *getContents(), *getSelection();
static long getSelectionStart(), getSelectionEnd();

static void setContents(),
	insertAfterSelection(), insertSelectionAfterSelection(),
	insertSelectionAfterCursor(), insertAtEnd(),
	replaceSelection(), setTextCursorPosition(),
        setTextCallback();

static mst_Boolean searchString(), gotoLine();


/* Toggle operations */

static Widget createToggle();

static mst_Boolean getToggleValue();

static void setToggleCallback(), setToggleValue(); 

/* Window operations */

static WindowStruct *createToplevelWindow();
static Widget getContainerWindowObject();
static void  mapWindow(), destroyWindowWidget(),
	setWindowHeight(), setWindowWidth(), setWindowX(), setWindowY(),
	setWindowEnabled(), setWindowBackgroundColor(), setDestroyWindowCallback();
	
	
static int
	getWindowEnabled();
static long getWindowHeight(), getWindowWidth(), getWindowX(), getWindowY();
static ColorDef *getWindowBackgroundColor();

/* Misc */
static WindowStruct *createTransientShell();
static void mstFlash();


/* File scoped globals */

static XtAppContext appContext;

static int	toolkitInitialized = False;
static int	appInitialized = False;
static int	appExitedCleanly = True;
static int	toplevelWindowCreated = False;
static int	exitMainLoop = False;
static Display	*appDisplay = NULL;
static Widget	mainTopLevelShell = NULL;
static int   dialogButtonHit = False;

/* This function allows for multiple names to be given for the same
 * actual function.  It's used so that several functions can share the
 * same implementation in a particular case (like X), but still have
 * separable identities.
 */
static void
defineCFuncList(funcAddr, va_alist)
void	(*funcAddr)();
va_dcl
{
  va_list nameList;
  char *name;

  va_start(nameList);

  while ((name = va_arg(nameList, char *)) != NULL) {
    defineCFunc(name, funcAddr);
  }
}

void
initBlox()
{
  defineCFunc("beginDispatchingEvents", beginDispatchingEvents);
  defineCFunc("bloxInit", bloxInit);

  defineCFunc("createColor", createColor);
  defineCFunc("terminateMainLoop", terminateMainLoop);
  defineCFunc("positionInForm", positionInForm);


  defineCFuncList(getX, "getButtonX",
		  "getContainerX",
		  "getFormX",
		  "getDialogX",
		  "getMenuBarX", 
		  "getMenuItemX",
		  "getLabelX", 
		  "getTextX", "getToggleX",
		  "getRadioButtonX", 
		  NULL);

  defineCFuncList(getY, "getButtonY",
		  "getContainerY",
		  "getFormY",
		  "getDialogY",
		  "getMenuBarY", 
		  "getMenuItemY",
		  "getLabelY", 
		  "getTextY", "getToggleY",
		  "getRadioButtonY", 
		  NULL);

  defineCFuncList(getWidth, "getButtonWidth",
		  "getContainerWidth", 
		  "getFormWidth",
		  "getDialogWidth",
		  "getMenuBarWidth",
		  "getMenuItemWidth",
		  "getLabelWidth",
		  "getTextWidth", "getToggleWidth",
		  "getRadioButtonWidth", 
		  NULL);


  defineCFuncList(getHeight, "getButtonHeight",
		  "getContainerHeight",
		  "getFormHeight",
		  "getDialogHeight",
		  "getMenuBarHeight",
		  "getMenuItemHeight",
		  "getLabelHeight", 
		  "getTextHeight", "getToggleHeight",
		  "getRadioButtonHeight", 
		  NULL);


  defineCFuncList(getEnabled, "getButtonEnabled",
		  "getContainerEnabled", 
		  "getFormEnabled", 
		  "getDialogEnabled", 
		  "getMenuBarEnabled",
		  "getMenuItemEnabled",
		  "getLabelEnabled",
		  "getTextEnabled", "getToggleEnabled", 
		  "getRadioButtonEnabled", 
		  NULL);


  defineCFuncList(getForegroundColor, "getButtonForegroundColor",
		  "getMenuItemForegroundColor",
		  "getLabelForegroundColor",
		  "getTextForegroundColor",
		  "getToggleForegroundColor", 
		  "getRadioButtonForegroundColor", 
		  NULL);

  defineCFuncList(getBackgroundColor, "getButtonBackgroundColor",
		  "getContainerBackgroundColor",
		  "getFormBackgroundColor",
		  "getFailogBackgroundColor",
		  "getMenuBarBackgroundColor", 
		  "getLabelBackgroundColor",
		  "getTextBackgroundColor", "getToggleBackgroundColor",
		  "getRadioButtonBackgroundColor", 
		  NULL);


  defineCFuncList(setX, "setButtonX",
		  "setContainerX",
		  "setFormX",
		  "setDialogX",
		  "setMenuBarX", 
		  "setMenuItemX",
		  "setLabelX", 
		  "setTextX", "setToggleX",
		  "setRadioButtonX", 
		  NULL);

  defineCFuncList(setY, "setButtonY",
		  "setContainerY",
		  "setFormY",
		  "setDialogY",
		  "setMenuBarY", 
		  "setMenuItemY",
		  "setLabelY", 
		  "setTextY", "setToggleY",
		  "setRadioButtonY", 
		  NULL);

  defineCFuncList(setWidth, "setButtonWidth",
		  "setContainerWidth", 
		  "setFormWidth", 
		  "setDialogWidth", 
		  "setMenuBarWidth",
		  "setMenuItemWidth",
		  "setLabelWidth",
		  "setTextWidth", "setToggleWidth",
		  "setRadioButtonWidth", 
		  NULL);


  defineCFuncList(setHeight, "setButtonHeight",
		  "setContainerHeight",
		  "setFormHeight",
		  "setDialogHeight",
		  "setMenuBarHeight",
		  "setMenuItemHeight",
		  "setLabelHeight", 
		  "setTextHeight", "setToggleHeight",
		  "setRadioButtonHeight", 
		  NULL);


  defineCFuncList(setEnabled, "setButtonEnabled",
		  "setContainerEnabled", 
		  "setFormEnabled", 
		  "setDialogEnabled", 
		  "setMenuBarEnabled",
		  "setMenuItemEnabled",
		  "setLabelEnabled",
		  "setTextEnabled", "setToggleEnabled", 
		  "setRadioButtonEnabled", 
		  NULL);


  defineCFuncList(setForegroundColor, "setButtonForegroundColor",
		  "setMenuItemForegroundColor",
		  "setLabelForegroundColor",
		  "setTextForegroundColor",
		  "setToggleForegroundColor", 
		  "setRadioButtonForegroundColor", 
		  NULL);

  defineCFuncList(setBackgroundColor, "setButtonBackgroundColor",
		  "setContainerBackgroundColor",
		  "setFormBackgroundColor",
		  "setDialogBackgroundColor",
		  "setMenuBarBackgroundColor", 
		  "setLabelBackgroundColor",
		  "setTextBackgroundColor", "setToggleBackgroundColor",
		  "setRadioButtonBackgroundColor", 
		  NULL);


  defineCFuncList(destroyWidget, "destroyButtonWidget",
		  "destroyContainerWidget",
		  "destroyFormWidget",
		  "destroyDialogWidget",
		  "destroyMenuBarWidget", 
		  "destroyMenuItemWidget",
		  "destroyLabelWidget",
		  "destroyTextWidget", "destroyToggleWidget",
		  "destroyRadioButtonWidget", 
		  NULL);


  defineCFuncList(getContainerObject, "getContainerButtonObject",
		  "getContainerContainerObject",
		  "getContainerFormObject",
		  "getContainerDialogObject",
		  "getContainerMenuBarObject", 
		  "getContainerMenuItemObject",
		  "getContainerLabelObject",
		  "getContainerTextObject",
		  "getContainerToggleObject",
		  "getContainerRadioButtonObject", 
		  NULL);


  defineCFuncList(getConnectedObject, "getConnectedButtonObject",
		  "getConnectedContainerObject",
		  "getConnectedFormObject",
		  "getConnectedDialogObject",
		  "getConnectedMenuBarObject", 
		  "getConnectedMenuItemObject",
		  "getConnectedLabelObject",
		  "getConnectedTextObject",
		  "getConnectedToggleObject",
		  "getConnectedRadioButtonObject", 
		  NULL);


  defineCFuncList(setToggleCallback, "setToggleCallback",
		  "setRadioButtonCallback", NULL);


  /* Button functions */

  defineCFunc("createButton", createButton);
  defineCFunc("setButtonCallback", setButtonCallback);

  /* Container functions */

  defineCFunc("createContainer", createContainer);
  defineCFunc("setContainerLayout", setContainerLayout);
 
  /* Form functions */

  defineCFunc("createForm", createForm);

  /* Dialog functions */

  defineCFunc("createDialog", createDialog);
  defineCFunc("addDialogButton", addDialogButton);
  defineCFunc("addDialogButtonMessage", addDialogButtonMessage);
  defineCFunc("getDialogText", getDialogText);
  defineCFunc("dialogLoop", dialogLoop);

  /* Label functions */

  defineCFunc("createLabel", createLabel);

  /* List functions */

  defineCFunc("createList", createList);
  defineCFunc("getListX", getListX);
  defineCFunc("getListY", getListY);
  defineCFunc("getListWidth", getListWidth);
  defineCFunc("getListHeight", getListHeight);
  defineCFunc("getListBackgroundColor", getListBackgroundColor);
  defineCFunc("getListForegroundColor", getListForegroundColor);
  defineCFunc("getListEnabled", getListEnabled);

  defineCFunc("setListCallback", setListCallback);
  defineCFunc("setListContents", setListContents);
  defineCFunc("setListX", setListX);
  defineCFunc("setListY", setListY);
  defineCFunc("setListWidth", setListWidth);
  defineCFunc("setListHeight", setListHeight);
  defineCFunc("setListBackgroundColor", setListBackgroundColor);
  defineCFunc("setListForegroundColor", setListForegroundColor);
  defineCFunc("setListEnabled", setListEnabled);
  defineCFunc("destroyListWidget", destroyListWidget);

  defineCFunc("numberOfStrings", numberOfStrings);
  defineCFunc("setRowSpacing", setRowSpacing);
  defineCFunc("setColumnSpacing", setColumnSpacing);
  defineCFunc("setNumberOfColumns", setNumberOfColumns);
  defineCFunc("setVerticalLayout", setVerticalLayout);
  defineCFunc("listHighlight", listHighlight);
  defineCFunc("listUnhighlight", listUnhighlight);

  
  defineCFuncList(getContainerListObject, "getContainerListObject", 
		  "getConnectedListObject", NULL);
  defineCFunc("getViewportObject", getViewportObject);

  /* Menu bar functions */

  defineCFunc("createMenuBar", createMenuBar);
  defineCFunc("addMenu", addMenu);
  defineCFunc("removeMenu", removeMenu);

  /* Menu functions */

  defineCFunc("createMenu", createMenu);
  defineCFunc("createPopupMenu", createPopupMenu);

  defineCFunc("getMenuX", getMenuX);
  defineCFunc("getMenuY", getMenuY);
  defineCFunc("getMenuWidth", getMenuWidth);
  defineCFunc("getMenuHeight", getMenuHeight);
  defineCFunc("getMenuBackgroundColor", getMenuBackgroundColor);
  defineCFunc("getMenuForegroundColor", getMenuForegroundColor);
  defineCFunc("getMenuEnabled", getMenuEnabled);

  defineCFunc("setMenuX", setMenuX);
  defineCFunc("setMenuY", setMenuY);
  defineCFunc("setMenuWidth", setMenuWidth);
  defineCFunc("setMenuHeight", setMenuHeight);
  defineCFunc("setMenuBackgroundColor", setMenuBackgroundColor);
  defineCFunc("setMenuForegroundColor", setMenuForegroundColor);
  defineCFunc("setMenuEnabled", setMenuEnabled);
  defineCFunc("destroyMenuWidget", destroyMenuWidget);

  defineCFunc("addMenuItem", addMenuItem);
  defineCFunc("removeMenuItem", removeMenuItem);

  defineCFunc("getContainerMenuObject", getContainerMenuObject);
  defineCFunc("getConnectedMenuObject", getConnectedMenuObject);



  /* Menu item functions */

  defineCFunc("createMenuItem", createMenuItem);
  defineCFunc("createMenuItemLine", createMenuItemLine);
  defineCFunc("setMenuItemCallback", setMenuItemCallback);
  defineCFunc("setMenuItemKeywordCallback", setMenuItemKeywordCallback);

  /* Radio group functions */

  defineCFunc("createRadioGroup", createRadioGroup);

  defineCFunc("getRadioGroupX", getRadioGroupX);
  defineCFunc("getRadioGroupY", getRadioGroupY);
  defineCFunc("getRadioGroupWidth", getRadioGroupWidth);
  defineCFunc("getRadioGroupHeight", getRadioGroupHeight);
  defineCFunc("getRadioGroupBackgroundColor", getRadioGroupBackgroundColor);
  /* no foreground color ! */
  defineCFunc("getRadioGroupEnabled", getRadioGroupEnabled);

  defineCFunc("setRadioGroupX", setRadioGroupX);
  defineCFunc("setRadioGroupY", setRadioGroupY);
  defineCFunc("setRadioGroupWidth", setRadioGroupWidth);
  defineCFunc("setRadioGroupHeight", setRadioGroupHeight);
  defineCFunc("setRadioGroupBackgroundColor", setRadioGroupBackgroundColor);
  /* no foreground color ! */
  defineCFunc("setRadioGroupEnabled", setRadioGroupEnabled);
  defineCFunc("destroyRadioGroupWidget", destroyRadioGroupWidget);

  defineCFunc("addRadioButton", addRadioButton);
  defineCFunc("removeRadioButton", removeRadioButton);

  defineCFuncList(getContainerRadioGroupObject,"getContainerRadioGroupObject",
		  "getConnectedRadioGroupObject", NULL);


  /* Radio button functions */

  defineCFunc("createRadioButton", createRadioButton);

  /* Text functions */

  defineCFunc("createText", createText);

  defineCFunc("setTextCallback", setTextCallback);
  defineCFunc("searchString", searchString);
  defineCFunc("gotoLine", gotoLine);

  defineCFunc("getContents", getContents);
  defineCFunc("setContents", setContents);
  defineCFunc("getSelection", getSelection);
  defineCFunc("replaceSelection", replaceSelection);
  defineCFunc("getSelectionStart", getSelectionStart);
  defineCFunc("getSelectionEnd", getSelectionEnd);
  defineCFunc("insertAfterSelection", insertAfterSelection);
  defineCFunc("insertSelectionAfterSelection", insertSelectionAfterSelection);
  defineCFunc("insertSelectionAfterCursor", insertSelectionAfterCursor);
	defineCFunc("insertAtEnd", insertAtEnd);
  defineCFunc("setTextCursorPosition", setTextCursorPosition);

  /* Toggle functions */

  defineCFunc("createToggle", createToggle);
  defineCFunc("getToggleValue", getToggleValue);
  defineCFunc("setToggleValue", setToggleValue);

  /* Window functions */
  defineCFunc("createToplevelWindow", createToplevelWindow);
  defineCFunc("mapWindow", mapWindow);

  defineCFunc("getWindowX", getWindowX);
  defineCFunc("getWindowY", getWindowY);
  defineCFunc("getWindowWidth", getWindowWidth);
  defineCFunc("getWindowHeight", getWindowHeight);
  defineCFunc("getWindowBackgroundColor", getWindowBackgroundColor);
  /* no foreground color ! */
  defineCFunc("getWindowEnabled", getWindowEnabled);

  defineCFunc("setWindowX", setWindowX);
  defineCFunc("setWindowY", setWindowY);
  defineCFunc("setWindowWidth", setWindowWidth);
  defineCFunc("setWindowHeight", setWindowHeight);
  defineCFunc("setWindowBackgroundColor", setWindowBackgroundColor);
  /* no foreground color ! */
  defineCFunc("setWindowEnabled", setWindowEnabled);
  defineCFunc("destroyWindowWidget", destroyWindowWidget);

  defineCFuncList(getContainerWindowObject, "getContainerWindowObject",
		  "getConnectedWindowObject", NULL);
			
  defineCFunc("setDestroyWindowCallback", setDestroyWindowCallback);
  defineCFunc("mstFlash", mstFlash);

/* TransientShell functions */
  defineCFunc("createTransientShell", createTransientShell);



  /* Prototype building blocks.  Substitute type name for <> 
  defineCFunc("get<>X", get<>X);
  defineCFunc("get<>Y", get<>Y);
  defineCFunc("get<>Width", get<>Width);
  defineCFunc("get<>Height", get<>Height);
  defineCFunc("get<>BackgroundColor", get<>BackgroundColor);
  defineCFunc("get<>ForegroundColor", get<>ForegroundColor);
  defineCFunc("get<>Enabled", get<>Enabled);

  defineCFunc("set<>X", set<>X);
  defineCFunc("set<>Y", set<>Y);
  defineCFunc("set<>Width", set<>Width);
  defineCFunc("set<>Height", set<>Height);
  defineCFunc("set<>BackgroundColor", set<>BackgroundColor);
  defineCFunc("set<>ForegroundColor", set<>ForegroundColor);
  defineCFunc("set<>Enabled", set<>Enabled);
  defineCFunc("destroy<>Widget", destroy<>Widget);
  */
}

static void
terminateMainLoop()
{
  exitMainLoop++;
}

/* ARGSUSED */
void
buttonCallback(w, byteArrayOOP, call_data)
Widget w;
OOP  byteArrayOOP;
XtPointer call_data;
{
  void *result;
  char message[256];
	ButtonCallback* bc;
  
	dialogButtonHit = True;

  bc = (ButtonCallback *)mstGetCdata(byteArrayOOP); 
  sprintf(message, "%%v %%o %s", mstGetCdata(bc->message));

  msgSendf(&result, message, bc->receiver);
}

/* ARGSUSED */
void
dlogButtonCallback(w, byteArrayOOP, call_data)
Widget w;
OOP  byteArrayOOP;
XtPointer call_data;
{
  void *result;
  char message[256];
	DlogButtonCallback* dc;
  
	dialogButtonHit = True;

  dc = (DlogButtonCallback *)mstGetCdata(byteArrayOOP); 
  sprintf(message, "%%v %%o %s %%i", "dispatch:");
	
  msgSendf(&result, message, dc->receiver, dc->index);
}

/* ARGSUSED */
void
menuCallback(w, client_data, call_data)
Widget w;
MenuCallback* client_data;
XtPointer call_data;
{
  void *result;
  char message[256];

  sprintf(message, "%%v %%o %s %%o", client_data->message);
  
	msgSendf(&result, message, client_data->receiver, client_data->argument);
}


static void
bloxInit()
{
#ifdef apparently_not_used /* Tue Jul 11 23:46:27 1995 */
/**/  Widget toplevel, box, quit, label, menulabel, menubox, list, text, tog,
/**/  	vp, simpleMenu, form, testMenu, pane,
/**/  	menupane[10];
/**/  Widget rad1, rad2, localbox;
#endif /* apparently_not_used Tue Jul 11 23:46:27 1995 */

#ifdef apparently_not_used /* Tue Jul 11 23:46:56 1995 */
/**/  Widget classNames, categoryNames, methodNames;
/**/  int i;
/**/  String buf[50];
#endif /* apparently_not_used Tue Jul 11 23:46:56 1995 */
  int argc = 1;
  char *argv[2];
  argv[0] = "";
  argv[1] = NULL;

  exitMainLoop = 0;

  /* Yet Another O'Rielly Bug: _Xdebug = True; */

  if (!toolkitInitialized) {
    /* should not matter whether this uses appContext or NULL */
    XtSetLanguageProc(NULL, (XtLanguageProc)NULL, NULL);
    XtToolkitInitialize();
    toolkitInitialized = True;
    printf("creating app context\n");
    appContext = XtCreateApplicationContext();
    /* We have no default resources, so we pass NULL here */
    XtAppSetFallbackResources(appContext, NULL);
    
  }


#ifdef out_for_testing /* Mon Jul  4 09:38:56 1994 */
/**/  if (!appExitedCleanly) {
/**/    printf("destroying previous app context\n");
/**/    XtDestroyApplicationContext(appContext);
/**/  }
#endif /* out_for_testing Mon Jul  4 09:38:56 1994 */

#ifdef out_for_testing /* Mon Jul  4 09:39:16 1994 */
/**/  printf("creating app context\n");
/**/  appContext = XtCreateApplicationContext();
#endif /* out_for_testing Mon Jul  4 09:39:16 1994 */

  appExitedCleanly = False;

    /* may want to:
       XtAppSetErrorMsgHandler(appContext, msg_handler)
       (see XtErrorMsgHandler for signature)
       ...other error handler
       XtAppSetErrorHandler(appContext, XtErrorHandler handler);
       default is _XtDefaultError. Must exit, or at least not invoke
       any more intrinsics because the behavior is undefined 
       */

#ifdef out_for_testing /* Mon Jul  4 09:39:34 1994 */
/**/  /* We have no default resources, so we pass NULL here */
/**/  XtAppSetFallbackResources(appContext, NULL);
/**/    
#endif /* out_for_testing Mon Jul  4 09:39:34 1994 */
  /* printf("opengin displzy\n"); */
  appDisplay = XtOpenDisplay(appContext, /*DisplayName*/NULL,
			     /*ApplicationName*/NULL,
			     /*ApplicationClass*/"Blox",
			     /*extra cmd line Options*/NULL,
			     /*optionsVecCount*/0,
			     &argc, argv);
  /* XSynchronize(appDisplay, 1); */
  /* printf("finished displzy\n"); */

  mainTopLevelShell = NULL;
  appInitialized = TRUE;
}

static Widget
createContainer(parent)
Widget parent;
{
  Widget result;
  /* printf("creating container\n"); */
  result = XtVaCreateManagedWidget(
			      "box",
			      boxWidgetClass,
			      parent,
			      NULL);
  /* printf("finished container\n"); */
  return result;
}

static void
setContainerLayout(container, isVertical)
Widget container;
int isVertical;
{
  XtVaSetValues(container, XtNorientation, isVertical ? XtorientVertical :
		XtorientHorizontal);
}

static voidPtr 
createColor(red, green, blue)
unsigned short red, green, blue;
{
  ColorDef *color;

  color = (ColorDef*)malloc(sizeof(ColorDef));

  color->red = red;
  color->green = green;
  color->blue = blue;

  return color;
}

static ColorDef*
colorFromPixel(w, pixel)
Widget w;
unsigned long pixel;
{
  Display *display;
  Colormap cmap;
  XColor colorcell;
  ColorDef *color;

  /* printf("getting color\n"); */
  display = XtDisplayOfObject(w);

  XtVaGetValues(w, XtNcolormap, &cmap, NULL);

  XQueryColor(display, cmap, &colorcell);

  /* printf("finished with color\n"); */

  color = (ColorDef*)malloc(sizeof(ColorDef));

  color->red = colorcell.red;
  color->green = colorcell.green;
  color->blue = colorcell.blue;

  return color;
}


static ColorDef*
getForegroundColor(w)
Widget w;
{
  unsigned long pixel;

  XtVaGetValues(w, XtNforeground, &pixel, NULL);
  
  return colorFromPixel(w, pixel);
}

static ColorDef*
getBackgroundColor(w)
Widget w;
{
  unsigned long pixel;

  XtVaGetValues(w, XtNbackground, &pixel, NULL);
  
  return colorFromPixel(w, pixel);
}

static void
setForegroundColor(w, color)
Widget w;
ColorDef *color;
{
  unsigned long pixel;
  pixel = allocateColor(w, color);

  XtVaSetValues(w, XtNforeground, pixel, NULL);
}


static void
setBackgroundColor(w, color)
Widget w;
ColorDef *color;
{
  unsigned long pixel;
  pixel = allocateColor(w, color);

  XtVaSetValues(w, XtNbackground, pixel, NULL);
}

static unsigned long
allocateColor(w, color)
Widget w;
ColorDef *color;
{
  Display *display;
  Colormap cmap;
  XColor colorcell;

  display = XtDisplayOfObject(w);
  XtVaGetValues(w, XtNcolormap, &cmap, NULL);

  colorcell.red = color->red;
  colorcell.green = color->green;
  colorcell.blue = color->blue;

  colorcell.flags = DoRed | DoGreen | DoBlue;

  if (!XAllocColor(display, cmap, &colorcell)) {
    /* !!! make this smart and use white if it's closer */
    colorcell.pixel = BlackPixel(display, DefaultScreen(display));
  }

  return colorcell.pixel;
}

static void
positionInForm(w, w1, w2)
Widget w, w1, w2;
{
  XtVaSetValues( w,
		XtNfromHoriz, w1,
		XtNfromVert, w2,
		NULL);
}
	
/* ******************** Form ******************** */

static Widget
createForm(parent)
Widget parent;
{
  Widget result;
  result = XtVaCreateManagedWidget(
			      "form",
			      formWidgetClass,
			      parent,
			      NULL);
  return result;
}

/* ******************** Dialog support ******************** */

static Widget
createDialog(parent, label, text)
Widget parent;
char *label;
char *text;
{
  Widget result;

  result = XtVaCreateManagedWidget(
			      "dialog",
			      dialogWidgetClass,
			      parent,
			      XtNlabel, label,
			      XtNvalue, text,
			      NULL);
  return result;
}

static void
addDialogButton(w, label, receiver,  index)
Widget w;
char* label;
OOP receiver;
int index;
{
  DlogButtonCallback* dc;
  OOP byteArrayOOP;

	byteArrayOOP = mstMalloc(receiver, sizeof(DlogButtonCallback));
  dc = (DlogButtonCallback *)mstGetCdata(byteArrayOOP); 

  dc->receiver = receiver;
	dc->index = index;
  
  XawDialogAddButton(w, label, dlogButtonCallback, byteArrayOOP);
}

static void
addDialogButtonMessage(w, label, receiver,  message)
Widget w;
char* label;
OOP receiver;
char* message;
{
  ButtonCallback* bc;
  OOP byteArrayOOP;
  int msgLen;

	msgLen = strlen(message);
	byteArrayOOP = mstMalloc(receiver, sizeof(ButtonCallback));
  bc = (ButtonCallback *)mstGetCdata(byteArrayOOP);

  bc->receiver = receiver;
  bc->message = (char *)mstMalloc(receiver, msgLen + 1);
  strcpy(mstGetCdata(bc->message), message);

  
  XawDialogAddButton(w, label, buttonCallback, byteArrayOOP);
}

static char *
getDialogText(w)
Widget w;
{
	return(XawDialogGetValueString(w));
}

static void
dialogLoop(dialog)	
Widget dialog;
{
  XEvent event;
  dialogButtonHit = False;

#define dialog_event_filter

#ifndef dialog_event_filter
  while (!dialogButtonHit) {
      XtAppNextEvent( appContext, &event);
      XtDispatchEvent(&event); 
    }
#endif

#ifdef dialog_event_filter
    while (!dialogButtonHit) {
      XtAppNextEvent( appContext, &event);
			if ((event.type == ButtonPress) || (event.type == ButtonRelease) || (event.type == MotionNotify ) || (event.type == KeyPress) || (event.type == KeyRelease)) { 
			if (XtParent(XtWindowToWidget(appDisplay, event.xany.window)) == dialog)
				XtDispatchEvent(&event); 
			else
				XBell(appDisplay, 50);
			}
		else
			XtDispatchEvent(&event); 
	 }
#endif
}

/* ******************** Menu Bar Support ******************** */

static void
addMenu(container, menu)
Widget container;
MenuStruct *menu;
{
  /* A Noop with our Xt-based notion of Menu bars  */

}

static void
removeMenu(container, element)
Widget container;		/* NOTUSED */
Widget element;
{
  XtDestroyWidget(element);
}



static Widget
createMenuBar(parent)
Widget parent;
{
  Widget result;
  /* printf("create menu bar\n"); */
  result = XtVaCreateManagedWidget("menuBar",
				 boxWidgetClass,
				 parent,
				 XtNorientation, XtorientHorizontal,
				 NULL);


  /* printf("finished menu bar\n"); */

  return result;
}

/* ******************** Menu support ******************** */

static MenuStruct *
createMenu(container, label)
Widget container;
char *label;
{
  MenuStruct *menu;
  char *myLabel, *labelSuffix;

  labelSuffix = "-popupMenu";

  myLabel = (char *)malloc(strlen(label)+strlen(labelSuffix)+1);
  strcpy(myLabel, label);
  strcat(myLabel, labelSuffix);

  menu = (MenuStruct *)malloc(sizeof(MenuStruct));

  /* printf("creating menu\n"); */
  menu->simpleMenu = XtVaCreatePopupShell(myLabel,
					  simpleMenuWidgetClass,
					  container,
					  NULL);

  menu->menuButton = XtVaCreateManagedWidget(label,
					     menuButtonWidgetClass,
					     container,
					     XtNmenuName, myLabel,
					     NULL);
  /* printf("finished creating menu\n"); */

  return menu;
}

static long
getMenuX(menu)
MenuStruct *menu;
{
  long x;

  XtVaGetValues(menu->menuButton, XtNx, &x, NULL);
  return x;
}

static long
getMenuY(menu)
MenuStruct *menu;
{
  long y;

  XtVaGetValues(menu->menuButton, XtNy, &y, NULL);
  return y;
}

/* Again, not clear what this applys to -- we make it apply to the button */
static long
getMenuWidth(menu)
MenuStruct *menu;
{
  long width;

  XtVaGetValues(menu->menuButton, XtNwidth, &width, NULL);
  return width;
}

/* Again, not clear what this applys to -- we make it apply to the button */
static long
getMenuHeight(menu)
MenuStruct *menu;
{
  long height;

  XtVaGetValues(menu->menuButton, XtNheight, &height, NULL);
  return height;
}

/* It's not clear what this should apply to.  For now, it works for both*/
static ColorDef*
getMenuForegroundColor(menu)
MenuStruct *menu;
{
  unsigned long pixel;

  XtVaGetValues(menu->simpleMenu, XtNforeground, &pixel, NULL);
  return colorFromPixel(menu->simpleMenu, pixel);
}

static ColorDef*
getMenuBackgroundColor(menu)
MenuStruct *menu;
{
  unsigned long pixel;

  XtVaGetValues(menu->simpleMenu, XtNbackground, &pixel, NULL);
  return colorFromPixel(menu->simpleMenu, pixel);
}

static int
getMenuEnabled(menu)
MenuStruct *menu;
{
  int state;

  XtVaGetValues(menu->menuButton, XtNsensitive, &state, NULL);
  return state;
}

static void
setMenuX(menu, x)
MenuStruct *menu;
long x;
{
  XtVaSetValues(menu->menuButton,
		XtNx, x,
		NULL);
}

static void
setMenuY(menu, y)
MenuStruct *menu;
long y;
{
  XtVaSetValues(menu->menuButton,
		XtNy, y,
		NULL);
}

/* Again, not clear what this applys to -- we make it apply to the button */
static void
setMenuWidth(menu, width)
MenuStruct *menu;
long width;
{
  XtVaSetValues(menu->menuButton,
		XtNwidth, width,
		NULL);
}

/* Again, not clear what this applys to -- we make it apply to the button */
static void
setMenuHeight(menu, height)
MenuStruct *menu;
long height;
{
  XtVaSetValues(menu->menuButton,
		XtNheight, height,
		NULL);
}

/* It's not clear what this should apply to.  For now, it works for both*/
static void
setMenuForegroundColor(menu, color)
MenuStruct *menu;
ColorDef *color;
{
  unsigned long pixel;
  /* printf("setting menu foregroup color\n"); */
  pixel = allocateColor(menu->simpleMenu, color);

  /* printf("setting menu foregroup color\n"); */
  if (menu->menuButton) {
    XtVaSetValues(menu->menuButton, XtNforeground, pixel, NULL);
  }
  XtVaSetValues(menu->simpleMenu, XtNforeground, pixel, NULL);
  /* printf("finished menu foregroup color\n"); */
}

static void
setMenuBackgroundColor(menu, color)
MenuStruct *menu;
ColorDef *color;
{
  unsigned long pixel;
  /* printf("setting menu background color\n"); */
  pixel = allocateColor(menu->simpleMenu, color);

  /* printf("setting menu background color\n"); */
  if (menu->menuButton) {
    XtVaSetValues(menu->menuButton, XtNbackground, pixel, NULL);
  }
  XtVaSetValues(menu->simpleMenu, XtNbackground, pixel, NULL);
  /* printf("finished setting menu background color\n"); */
}



static void
setMenuEnabled(menu, state)
MenuStruct *menu;
mst_Boolean state;
{
  XtVaSetValues(menu->menuButton, XtNsensitive, state, NULL);
}

static void
destroyMenuWidget(menu)
MenuStruct *menu;
{
  XtDestroyWidget(menu->menuButton);
  XtDestroyWidget(menu->simpleMenu);
  free(menu);		/* good idea??? */
}

static void
addMenuItem(container, element)
Widget container;		/* NOTUSED */
Widget element;			/* NOTUSED */
{
  /* A Noop with Xt */
}

static void
removeMenuItem(container, element)
MenuStruct *container;		/* NOTUSED */
Widget element;
{
  XtDestroyWidget(element);
}

/* Return a suitable parent for popup menus (!) */
static Widget
getContainerMenuObject(menu)
MenuStruct *menu;
{
  return menu->simpleMenu;
}

static Widget
getConnectedMenuObject(menu)
MenuStruct *menu;
{
  return menu->menuButton;
}


/* ******************** Popup Menu support ******************** */

static MenuStruct *
createPopupMenu(container, label)
Widget container;
char *label;
{
  XtTranslations translations;
  MenuStruct *menu;
  char *myLabel, *labelSuffix, translateBuffer[200];

  labelSuffix = "-popupMenu";

  myLabel = (char *)malloc(strlen(label)+strlen(labelSuffix)+1);
  strcpy(myLabel, label);
  strcat(myLabel, labelSuffix);

  menu = (MenuStruct *)malloc(sizeof(MenuStruct));

  /* printf("createing popup menu\n"); */
  menu->simpleMenu = XtVaCreatePopupShell(myLabel,
					  simpleMenuWidgetClass,
					  container,
					  NULL);

  menu->menuButton = NULL;


  sprintf(translateBuffer,
	  "<Btn3Down>: XawPositionSimpleMenu(%s) XtMenuPopup(%s)",
	  myLabel, myLabel);

  translations = XtParseTranslationTable(translateBuffer);

  XtOverrideTranslations(container, translations);

  /* printf("finished createing popup menu\n"); */
  return menu;
}


/* ******************** Menu Item support ******************** */

static Widget
createMenuItemLine(menu)
MenuStruct *menu;
{
  Widget result;
  /* printf("createing menu item line\n"); */
  result = XtVaCreateManagedWidget("menuLine", smeLineObjectClass,
			  menu->simpleMenu,
			  NULL);
  /* printf("finishe dcreateing menu item line\n"); */
  return result;
}

static Widget
createMenuItem(menu, label)
MenuStruct *menu;
char *label;
{
  Widget result;
  /* printf("creating menu itme\n"); */
  result = XtVaCreateManagedWidget(label, smeBSBObjectClass,
				 menu->simpleMenu,
				 /* XtNlabel, label, */
				 NULL);
  /* printf("finsihed creating menu itme\n"); */
  return result;
}

static void
setMenuItemCallback(w, receiver, message)
Widget w;
OOP receiver;
char *message;
{
  /* the implementation is the same, so we can share! */
  setButtonCallback(w, receiver, message);
}

static void
setMenuItemKeywordCallback(w, receiver, message, argument)
Widget w;
OOP receiver;
char *message;
OOP argument;
{
  MenuCallback* mc;
  int msgLen;

  msgLen = strlen(message);
	
  mc = (MenuCallback *)malloc(sizeof(MenuCallback));

  mc->receiver = receiver;
  mc->argument = argument;
  mc->message = (char *)malloc(msgLen + 1);
  strcpy(mc->message, message);

  /* should probably be a remove first */
  XtAddCallback(w, XtNcallback, menuCallback, mc);
}


/* ******************** Button support ******************** */


static Widget
createButton(parent, label)
Widget parent;
char *label;
{
  Widget button;
  /* printf("creating button\n"); */
  button = XtVaCreateManagedWidget("button",
				   commandWidgetClass,
				   parent,
				   XtNlabel, label,
				   /* XtNresize, False, */
				   NULL);
  /* printf("finished creating button\n"); */
  return button;
}

static void
setButtonCallback(w, receiver, message)
Widget w;
OOP receiver;
char *message;
{
  ButtonCallback* bc;
  OOP byteArrayOOP;
  int msgLen;

  msgLen = strlen(message);
	byteArrayOOP = mstMalloc(receiver, sizeof(ButtonCallback));
  bc = (ButtonCallback *)mstGetCdata(byteArrayOOP); 

  bc->receiver = receiver;
  bc->message = (char *)mstMalloc(receiver, msgLen + 1);
  strcpy(mstGetCdata(bc->message), message);

  /* should probably be a remove first */
  XtAddCallback(w, XtNcallback, buttonCallback, byteArrayOOP);
}


/* ******************** Label support ******************** */

static Widget
createLabel(parent, label)
Widget parent;
char *label;
{
  Widget result;
  /* printf("creating label [%s]\n", label); */
  result = XtVaCreateManagedWidget("label",
				 labelWidgetClass,
				 parent,
				 XtNlabel, label,
				 XtNborderWidth, 0,
				 NULL);
  /* printf("finished label\n"); */
  return result;
}

/* ******************** List support ******************** */

static ScrollListStruct *
createList(parent)
Widget parent;
{
  ScrollListStruct *scrollList;
  static char *nullList[1];

  nullList[0] = "";

  scrollList = (ScrollListStruct *)malloc(sizeof(ScrollListStruct));

  scrollList->viewport = XtVaCreateManagedWidget("viewport",
					   viewportWidgetClass,
					   parent,
					   XtNallowVert, TRUE, /*
					   XtNallowHoriz, TRUE, */
					   XtNheight, DEFAULT_LIST_HEIGHT,
					   XtNwidth, DEFAULT_LIST_WIDTH,
					   NULL);


  scrollList->list = XtVaCreateManagedWidget("list",
					     listWidgetClass,
					     scrollList->viewport,
					     XtNnumberStrings, 1,
					     XtNlist, nullList,

					     XtNdefaultColumns, 1,
					     XtNforceColumns, TRUE,
					     XtNverticalList,TRUE, 

					     NULL);

  return scrollList;
}

static long
getListX(scrollList)
ScrollListStruct *scrollList;
{
  long x;
  XtVaGetValues(scrollList->viewport,
		XtNx, &x,
		NULL);
  return x;
}

static long
getListY(scrollList)
ScrollListStruct *scrollList;
{
  long y;
  XtVaGetValues(scrollList->viewport,
		XtNy, &y,
		NULL);

  return y;
}

static long
getListWidth(scrollList)
ScrollListStruct *scrollList;
{
  unsigned long width;
  XtVaGetValues(scrollList->viewport,
		XtNwidth, &width,
		NULL);

  return width;
}

static long
getListHeight(scrollList)
ScrollListStruct *scrollList;
{
  unsigned long height;
  XtVaGetValues(scrollList->viewport,
		XtNheight, &height,
		NULL);

  return height;
}

static ColorDef*
getListForegroundColor(scrollList)
ScrollListStruct *scrollList;
{
  unsigned long pixel;

  XtVaGetValues(scrollList->list, XtNforeground, &pixel, NULL);
  
  return colorFromPixel(scrollList->list, pixel);
}

static ColorDef*
getListBackgroundColor(scrollList)
ScrollListStruct *scrollList;
{
  unsigned long pixel;

  XtVaGetValues(scrollList->list, XtNbackground, &pixel, NULL);
  
  return colorFromPixel(scrollList->list, pixel);
}

static int
getListEnabled(scrollList)
ScrollListStruct *scrollList;
{
  int state;
  XtVaGetValues(scrollList->viewport, XtNsensitive, &state, NULL);

  return state;
}



static void
setListX(scrollList, x)
ScrollListStruct *scrollList;
long x;
{
  XtVaSetValues(scrollList->viewport,
		XtNx, x,
		NULL);
}

static void
setListY(scrollList, y)
ScrollListStruct *scrollList;
long y;
{
  XtVaSetValues(scrollList->viewport,
		XtNy, y,
		NULL);
}

static void
setListWidth(scrollList, width)
ScrollListStruct *scrollList;
unsigned long width;
{
  XtVaSetValues(scrollList->viewport,
		XtNwidth, width,
		NULL);
}

static void
setListHeight(scrollList, height)
ScrollListStruct *scrollList;
unsigned long height;
{
  XtVaSetValues(scrollList->viewport,
		XtNheight, height,
		NULL);
}

static void
setListForegroundColor(scrollList, color)
ScrollListStruct *scrollList;
ColorDef *color;
{
  unsigned long pixel;
  pixel = allocateColor(scrollList->list, color);

  XtVaSetValues(scrollList->list, XtNforeground, pixel, NULL);
}

static void
setListBackgroundColor(scrollList, color)
ScrollListStruct *scrollList;
ColorDef *color;
{
  unsigned long pixel;
  pixel = allocateColor(scrollList->list, color);

  XtVaSetValues(scrollList->list,
		XtNbackground, pixel,
		NULL);
}

static void
setListEnabled(scrollList, state)
ScrollListStruct *scrollList;
mst_Boolean state;
{
  XtVaSetValues(scrollList->viewport, XtNsensitive, state, NULL);
}

static void
destroyListWidget(scrollList)
ScrollListStruct *scrollList;
{
  XtDestroyWidget(scrollList->viewport); /* I hope this frees both */
  free(scrollList);		/* good idea??? */
}


/* ARGSUSED */
static void
listCallback(w, byteArrayOOP, call_data)
Widget w;
OOP byteArrayOOP;
XawListReturnStruct* call_data;
{
  void *result;
  char message[256];
	ListCallback* client_data;

  client_data = (ListCallback *)mstGetCdata(byteArrayOOP); 
  sprintf(message, "%%v %%o %s %%i", mstGetCdata(client_data->message));

  msgSendf(&result, message, client_data->receiver, call_data->list_index);


#ifdef old_code /* Mon Jun 13 16:53:19 1994 */
/**/  void *result;
/**/  msgSendf(&result, "%v %o itemSelected: %i label: %s ", client_data,
/**/	   call_data->list_index, call_data->string);
#endif /* old_code Mon Jun 13 16:53:19 1994 */
}

static void
setListCallback(scrollList, receiver, message)
ScrollListStruct *scrollList;
OOP receiver;
char *message;
{
  ListCallback* lc;
	OOP byteArrayOOP;
  int msgLen;

  msgLen = strlen(message);
	byteArrayOOP = mstMalloc(receiver, sizeof(ListCallback));
  lc = (ListCallback *)mstGetCdata(byteArrayOOP);

  lc->receiver = receiver;
  lc->message = (char *)mstMalloc(receiver, msgLen + 1);
  strcpy(mstGetCdata(lc->message), message);

  /* should probably be a remove first */
  XtAddCallback(scrollList->list, XtNcallback, listCallback, byteArrayOOP);
}

static void
setListContents(scrollList, list)
ScrollListStruct *scrollList;
String *list;			/* must be NULL terminated */
{
      Dimension width, height;

      XtVaGetValues(scrollList->viewport,
		    XtNwidth, &width,
		    XtNheight, &height,
		    NULL);

      XtVaSetValues(scrollList->list,
		    XtNnumberStrings, 0,
		    XtNlist, list,
		    NULL);

      XtVaSetValues(scrollList->viewport,
		    XtNwidth, width,
		    XtNheight, height,
		    NULL);
		    
}

static void
setRowSpacing(w, space)
Widget w;
long space;
{
  XtVaSetValues(w, XtNrowSpacing, space, NULL);
}

static void
setColumnSpacing(w, space)
Widget w;
long space;
{
  XtVaSetValues(w, XtNcolumnSpacing, space, NULL);
}

static void
setNumberOfColumns(scrollList, numCols)
ScrollListStruct *scrollList;
long numCols;
{
  XtVaSetValues(scrollList->list,
		XtNdefaultColumns, numCols,
		XtNforceColumns, TRUE,
		NULL);
}

/* !!! Poor choice of names */
static void
setVerticalLayout(scrollList, doVertical)
ScrollListStruct *scrollList;
mst_Boolean doVertical;
{
  XtVaSetValues(scrollList->list, XtNverticalList, doVertical, NULL);
}


static long
numberOfStrings(scrollList)
ScrollListStruct *scrollList;
{
  int result;

  XtVaGetValues(scrollList->list, XtNnumberStrings, &result, NULL);

  return result;
}


static Widget
getViewportObject(scrollList)
ScrollListStruct *scrollList;
{
  return (scrollList->viewport);
}

static Widget
getContainerListObject(scrollList)
ScrollListStruct *scrollList;
{
  return (scrollList->list);
}

static void
listHighlight(scrollList, item)
ScrollListStruct *scrollList;
int item;
{
	XawListHighlight(scrollList->list, item);
}

static void
listUnhighlight(scrollList)
ScrollListStruct *scrollList;
{
	XawListUnhighlight(scrollList->list);
}

/* ******************** Toggle (checkbox) support ******************** */

static Widget
createToggle(parent, label)
Widget parent;
char *label;
{
  return XtVaCreateManagedWidget("toggle",
				toggleWidgetClass,
				parent,
				XtNlabel, label,
				NULL);
}

#ifdef apparently_not_used /* Tue Jul 11 23:42:03 1995 */
/**/static mst_Boolean
/**/getToggleState(w)
/**/Widget w;
/**/{
/**/  char	state;
/**/  XtVaGetValues(w, XtNstate, &state, NULL);
/**/  return state;
/**/}
/**/
/**/static mst_Boolean
/**/setToggleState(w, state)
/**/Widget w;
/**/mst_Boolean state;
/**/{
/**/  XtVaSetValues(w, XtNstate, state, NULL);
/**/  return true;
/**/}
#endif /* apparently_not_used Tue Jul 11 23:42:03 1995 */

/* ******************** Radio Group operations ******************** */

/* !!! allow for setting orientation !!! */

static RadioGroupStruct*
createRadioGroup(parent)
Widget parent;
{
  RadioGroupStruct* group;

  group = (RadioGroupStruct*)malloc(sizeof(RadioGroupStruct));

 /* group->container = XtVaCreateManagedWidget("radioGroup",
					     boxWidgetClass,
					     parent,
					     XtNorientation, XtorientHorizontal,
					     XtNborderWidth, 0,
					     XtNhSpace, 0,
					     XtNvSpace, 0,
					     NULL);*/
  group->container = XtVaCreateManagedWidget("radioGroup",
					     formWidgetClass,
					     parent,
					     XtNborderWidth, 0,
					     XtNhorizDistance, 0,
					     XtNvertDistance, 0,
					     NULL);
  group->widgetId = NULL;
  group->index = 1;

  return group;
}


static long
getRadioGroupX(group)
RadioGroupStruct *group;
{
  long x;
  XtVaGetValues(group->container,
		XtNx, &x,
		NULL);
  return x;
}

static long
getRadioGroupY(group)
RadioGroupStruct *group;
{
  long y;
  XtVaGetValues(group->container,
		XtNy, &y,
		NULL);
  return y;
}

static long
getRadioGroupWidth(group)
RadioGroupStruct *group;
{
  long width;
  XtVaGetValues(group->container,
		XtNwidth, &width,
		NULL);
  return width;
}

static long
getRadioGroupHeight(group)
RadioGroupStruct *group;
{
  long height;

  XtVaGetValues(group->container,
		XtNheight, &height,
		NULL);
  return height;
}

static ColorDef*
getRadioGroupBackgroundColor(group)
RadioGroupStruct *group;
{
  unsigned long pixel;
  XtVaGetValues(group->container, XtNbackground, &pixel, NULL);

  return colorFromPixel(group->container, pixel);
}

static int
getRadioGroupEnabled(group)
RadioGroupStruct *group;
{
  int state;
  XtVaGetValues(group->container, XtNsensitive, &state, NULL);
  return state;
}



static void
setRadioGroupX(group, x)
RadioGroupStruct *group;
long x;
{
  XtVaSetValues(group->container,
		XtNx, x,
		NULL);
}

static void
setRadioGroupY(group, y)
RadioGroupStruct *group;
long y;
{
  XtVaSetValues(group->container,
		XtNy, y,
		NULL);
}

static void
setRadioGroupWidth(group, width)
RadioGroupStruct *group;
unsigned long width;
{
  XtVaSetValues(group->container,
		XtNwidth, width,
		NULL);
}

static void
setRadioGroupHeight(group, height)
RadioGroupStruct *group;
unsigned long height;
{
  XtVaSetValues(group->container,
		XtNheight, height,
		NULL);
}

static void
setRadioGroupBackgroundColor(group, color)
RadioGroupStruct *group;
ColorDef *color;
{
  unsigned long pixel;
  pixel = allocateColor(group->container, color);

  XtVaSetValues(group->container,
		XtNbackground, pixel,
		NULL);
}

static void
setRadioGroupEnabled(group, state)
RadioGroupStruct *group;
mst_Boolean state;
{
  XtVaSetValues(group->container, XtNsensitive, state, NULL);
}

static void
destroyRadioGroupWidget(group)
RadioGroupStruct *group;
{
  XtDestroyWidget(group->container); /* I hope this frees contents */
  free(group);		/* good idea??? */
}


static void
addRadioButton(group, element)
RadioGroupStruct *group;
Widget element;
{
  /* A Noop with Xt */
}

static void
removeRadioButton(group, element)
RadioGroupStruct *group;		/* NOTUSED */
Widget element;
{
  XtDestroyWidget(element);
}


static Widget
getContainerRadioGroupObject(group)
RadioGroupStruct *group;
{
  return (group->container);
}



/* !!! get currently selected one
   set currently selected one
*/

/* ******************** Radio Button operations ******************** */

static Widget
createRadioButton(parent, label)
RadioGroupStruct* parent;
char *label;
{
  Widget button;

  button = XtVaCreateManagedWidget("radioButton",
				toggleWidgetClass,
				parent->container,
				XtNlabel, label,
				NULL);

  if (parent->widgetId == NULL) {
    parent->widgetId = button;
  } else {
    XtVaSetValues(button, XtNradioGroup, parent->widgetId,
		  XtNradioData, parent->index++, NULL);
  }

  return button;
}


/* ******************** Text operations ******************** */

static Widget
createText(parent, editable)
Widget parent;
mst_Boolean editable;
{
  XawTextEditType editType;
	
	editType = editable ? XawtextEdit : XawtextRead;
  return XtVaCreateManagedWidget("text",
				 asciiTextWidgetClass,
				 parent,
				 XtNeditType, editType,
				 XtNwrap, XawtextWrapWord,
				 XtNscrollVertical, XawtextScrollWhenNeeded,
				 NULL);
}

static char *
getContents(w)
Widget w;
{
  char *str;
  XtVaGetValues(w, XtNstring, &str, NULL);
  return (str);
}


static void
setContents(w, contents)
Widget w;
char *contents;
{
  XtVaSetValues(w, XtNstring, contents, NULL);
}

static void
setTextCallback(w, receiver, message)
Widget w;
OOP receiver;
char *message;
{
  ButtonCallback* bc;
	Widget textw;
  OOP byteArrayOOP;
  int msgLen;

  msgLen = strlen(message);
	byteArrayOOP = mstMalloc(receiver, sizeof(ButtonCallback));
  bc = (ButtonCallback *)mstGetCdata(byteArrayOOP); 
  bc->receiver = receiver;
  bc->message = (char *)mstMalloc(receiver, msgLen + 1);
  strcpy(mstGetCdata(bc->message), message);

  /* should probably be a remove first */
	XtVaGetValues(w, XtNtextSource, &textw, NULL);
	XtAddCallback(textw, XtNcallback, buttonCallback, byteArrayOOP);
}

static mst_Boolean
searchString(w, searchString)
Widget w;
char *searchString;
{
  XawTextBlock block;
  XawTextPosition position;

  block.firstPos = 0;
  block.length = strlen(searchString);
  block.ptr = searchString;
  block.format = FMT8BIT;
  position = XawTextSearch(w, XawsdRight, &block);
  if (position != XawTextSearchError)
    {
      XawTextSetSelection(w, position, position + strlen(searchString));
      XawTextSetInsertionPoint(w, position);
      return(True);
    }
  return(False);
}

/*	mst_Boolean gotoLine(text_w, line, endOfLine)
 *
 * Description
 *
 *   Set insertion point at line number indicated by line.
 *   If endOfLine is true, position cursor at end of line;
 *   otherwise, position cursor at beginning of line.
 *    
 *
 * Inputs
 *
 *  text_w
 *    Text widget.
 * 
 *  line
 *    Scroll to line number. 
 *
 *  endOfLine
 *    If true, position cursor at end of line.
 */
mst_Boolean gotoLine(text_w, line, endOfLine)
     Widget text_w; 
     int line; 
     mst_Boolean endOfLine;
{
  char *p, *string;
  XawTextPosition pos;
  int  linesScrolled = 0;
  Boolean found = False;
  
  
  string = getContents(text_w);
	p = string;
  /* If cursor is positioned at beginning of line, decrement line number */
  if (!endOfLine)
    found = !(--line);
  /* Scroll *line* lines or to end of text   */
  if (!found)
    /* Start searching at beginning */
    for (p = string; p = strchr(p, '\n'); p++)
      {
				found = ++linesScrolled == line;
				if ( found ) {
					if (!endOfLine)
						p++;
					break;
				}
      }
  
  /* If last line, compute position of last character */
  if (!found && endOfLine && (linesScrolled == line - 1) ) {
    p = string + strlen(string);
    found = True;
  }
  /* If line within text range (found is true), set cursor at "pos" */
  if (found) {
    pos = (XawTextPosition)(p - string);        
    XawTextSetInsertionPoint(text_w, pos);
  }
 /* XawAsciiSourceFreeString((void *)string); */
  return(found);
}


static char *
getSelection(w)
Widget w;
{
  XawTextPosition begin, end;
  char *str;
  XawTextGetSelectionPos(w, &begin, &end);
  XtVaGetValues(w, XtNstring, &str, NULL);
  str[end] = '\0';		/* null terminate substring */
  return (&str[begin]);
}

static void
replaceSelection(w, newContents)
Widget w;
char *newContents;
{
  XawTextBlock block;
  XawTextPosition begin, end;
  XawTextGetSelectionPos(w, &begin, &end);

  block.firstPos = 0;
  block.length = strlen(newContents);
  block.ptr = newContents;
  block.format = FMT8BIT;
  XawTextReplace(w, begin, end, &block);
}

static long
getSelectionStart(w)
Widget w;
{
  XawTextPosition start, end;
  XawTextGetSelectionPos(w, &start, &end);
  return (start);
}

static long
getSelectionEnd(w)
Widget w;
{
  XawTextPosition begin, end;
  XawTextGetSelectionPos(w, &begin, &end);
  return (end);
}

static void
insertAfterSelection(w, string)
Widget w;
char *string;
{
  XawTextBlock block;
  XawTextPosition begin, end;
  XawTextGetSelectionPos(w, &begin, &end);

  block.firstPos = 0;
  block.length = strlen(string);
  block.ptr = string;
  block.format = FMT8BIT;
  XawTextReplace(w, end, end, &block);
}

static void
insertSelectionAfterCursor(w, string)
Widget w;
char *string;
{
  XawTextBlock block;
  XawTextPosition /* begin, */ end;
  end = XawTextGetInsertionPoint(w);

  block.firstPos = 0;
  block.length = strlen(string);
  block.ptr = string;
  block.format = FMT8BIT;
  XawTextReplace(w, end, end, &block);
  XawTextSetSelection(w, end, end + strlen(string));
}

static void
insertSelectionAfterSelection(w, string)
Widget w;
char *string;
{
  XawTextBlock block;
  XawTextPosition begin, end;
  XawTextGetSelectionPos(w, &begin, &end);

  block.firstPos = 0;
  block.length = strlen(string);
  block.ptr = string;
  block.format = FMT8BIT;
  XawTextReplace(w, end, end, &block);
  XawTextSetInsertionPoint(w, end);
  XawTextSetSelection(w, end, end + strlen(string));
}

static void
insertAtEnd(w, string)
Widget w;
char *string;
{
#ifdef does_nothing /* Tue Jul 12 23:34:54 1994 */
/**/  int length;
/**/
/**/
/**/  XawTextBlock block;
/**/  XawTextPosition begin, end;
/**/
/**/  XtVaGetValues(w, Xt
/**/
/**/
/**/  XawTextGetSelectionPos(w, &begin, &end);
/**/
/**/  block.firstPos = 0;
/**/  block.length = strlen(string);
/**/  block.ptr = string;
/**/  block.format = FMT8BIT;
/**/  XawTextReplace(w, end, end, &block);
#endif /* does_nothing Tue Jul 12 23:34:54 1994 */
}

static void
setTextCursorPosition(w, pos)
Widget w;
long pos;
{
  XtVaSetValues(w, XtNinsertPosition, pos, NULL);
}


/* -------------------- Scrollbar (slider) operations -------------------- */

#ifdef apparently_not_used /* Tue Jul 11 23:45:20 1995 */
/**/static Widget
/**/createScrollbar(parent)
/**/Widget parent;
/**/{
/**/  return XtVaCreateManagedWidget("scrollbar",
/**/				 scrollbarWidgetClass,
/**/				 parent,
/**/				 NULL);
/**/}
/**/
/**/static void
/**/setScrollbarOrientation(w, isVertical)
/**/Widget w;
/**/mst_Boolean isVertical;
/**/{
/**/  XtVaSetValues(w, XtNorientation, isVertical? XtorientVertical : XtorientHorizontal,
/**/		NULL);
/**/}
/**/
#endif /* apparently_not_used Tue Jul 11 23:45:20 1995 */

/* get scroll value
   set scroll value
   get/set range ?
   percentage in thumb?
 */


/* ARGSUSED */
static void
toggleCallback(w, byteArrayOOP, call_data)
Widget w;
OOP byteArrayOOP;
XtPointer call_data;
{
  void *result;
  char message[256];
	ToggleCallback* client_data;

  client_data = (ToggleCallback *)mstGetCdata(byteArrayOOP);
  sprintf(message, "%%v %%o %s %%b", mstGetCdata(client_data->message));

  msgSendf(&result, message, client_data->receiver, getToggleValue(w));
}


static void
setToggleCallback(w, receiver, message)
Widget w;
OOP receiver;
char *message;
{
  ToggleCallback* tc;
	OOP byteArrayOOP;
  int msgLen;

  msgLen = strlen(message);
	byteArrayOOP = mstMalloc(receiver, sizeof(ToggleCallback));
	tc = (ToggleCallback *)mstGetCdata(byteArrayOOP);
	
  tc->receiver = receiver;
  tc->message = (char *)mstMalloc(receiver, msgLen + 1);
  strcpy(mstGetCdata(tc->message), message);

  /* should probably be a remove first */
  XtAddCallback(w, XtNcallback, toggleCallback, byteArrayOOP);
}

static mst_Boolean
getToggleValue(w)
Widget w;
{
  char value;
  XtVaGetValues(w, XtNstate, &value, NULL);

  return value;
}

static void
setToggleValue(w, value)
Widget w;
mst_Boolean value;
{
  XtVaSetValues(w, XtNstate, value, NULL);
}


/* Generic operations */

static long
getHeight(w)
Widget w;
{
  long height;
  XtVaGetValues(w, XtNheight, &height, NULL);

  return height;
}

static long
getWidth(w)
Widget w;
{
  long width;
  XtVaGetValues(w, XtNwidth, &width, NULL);

  return width;
}

static long
getX(w)
Widget w;
{
  long x;
  XtVaGetValues(w, XtNx, &x, NULL);

  return x;
}

static long
getY(w)
Widget w;
{
  int y;
  XtVaGetValues(w, XtNy, &y, NULL);

  return y;
}

static int
getEnabled(w)
Widget w;
{
  int state;
  XtVaGetValues(w, XtNsensitive, &state, NULL);

  return state;
}



static void
setHeight(w, height)
Widget w;
int height;
{
  XtVaSetValues(w, XtNheight, height, NULL);
}

static void
setWidth(w, width)
Widget w;
int width;
{
  XtVaSetValues(w, XtNwidth, width, NULL);
}

static void
setX(w, x)
Widget w;
int x;
{
  XtVaSetValues(w, XtNx, x, NULL);
}

static void
setY(w, y)
Widget w;
int y;
{
  XtVaSetValues(w, XtNy, y, NULL);
}

static void
setEnabled(w, state)
Widget w;
mst_Boolean state;
{
  XtVaSetValues(w, XtNsensitive, state, NULL);
}

static void
destroyWidget(w)
Widget w;
{
  XtDestroyWidget(w);
}


static Widget
getContainerObject(w)
Widget w;
{
  return w;
}

static Widget
getConnectedObject(w)
Widget w;
{
  return w;
}

/* ******************** Window operations ******************** */

/*	void destroyWindowCallback(widget, client_data, cbs)
 */
void destroyWindowCallback(widget, client_data, cbs)
     Widget widget;
     WindowCallback* client_data;
     XtPointer cbs;
{
  mst_Boolean *result;
  char message[256];

  sprintf(message, "%%b %%o %s", client_data->message);

  msgSendf(&result, message, client_data->receiver);
	
	if (result) {
		destroyWindowWidget(client_data->window);
		free(client_data);
	}
}

static void
setDestroyWindowCallback(w, receiver, message, window)
Widget w;
OOP receiver;
char *message;
WindowStruct* window;
{
  WindowCallback* wcb;
  int msgLen;

  msgLen = strlen(message);
  wcb = (WindowCallback *)malloc(sizeof(WindowCallback));

  wcb->receiver = receiver;
  wcb->message = (char *)malloc(msgLen + 1);
  strcpy(wcb->message, message);
  wcb->window = window;

  /* should probably be a remove first */
  XtAddCallback(w, XtNcallback, setDestroyWindowCallback, wcb);
}

static WindowStruct *
createToplevelWindow(label)
char *label;
{
  WindowStruct* window;
/*	WindowCallback wcb; */

  window = (WindowStruct*)malloc(sizeof(WindowStruct));

  if (mainTopLevelShell == NULL) {
    window->isTopLevel = True;
    /* printf("creating typ level window\n"); */
    mainTopLevelShell = XtVaAppCreateShell(/*AppName*/label,
			    /*ClassName*/"Blox",
			    applicationShellWidgetClass,
			    appDisplay,
			    NULL);
    /* printf("done\n"); */
    window->widget = mainTopLevelShell;
  } else {
    window->isTopLevel = False;
    /* printf("creating popup level window\n"); */
    window->widget = XtVaCreatePopupShell(/*AppName*/label,
				topLevelShellWidgetClass,
				mainTopLevelShell,
				NULL);
    /* printf("done popup level window\n"); */
  }
  return window;

#ifdef old_code /* Sun Jul  3 12:50:11 1994 */
/**/  return XtVaAppInitialize(    &appContext,
/**/			       "Blox",
/**/			       NULL, 0,
/**/			       &argc, 0, /* &argc, argv, */
/**/			       NULL,
/**/			       NULL);
#endif /* old_code Sun Jul  3 12:50:11 1994 */
}

static WindowStruct *
createTransientShell(label, parent)
char *label;
Widget parent;
{
  WindowStruct* window;
/* 	WindowCallback wcb; */

#ifdef pos_in_win_center
  long x, y, width, height;
  
  XtVaGetValues(parent, XtNx, &x, 
		XtNy, &y, XtNwidth, &width, 
		XtNheight, &height, NULL);
  x = ceil(x + width / 2);
  y = ceil(y + height /2);
#endif

  window = (WindowStruct*)malloc(sizeof(WindowStruct));

	window->isTopLevel = False;
	/* printf("creating popup level window\n"); */
	window->widget = XtVaCreatePopupShell(/*AppName*/label,
			transientShellWidgetClass,
			parent,
			XtNtransientFor, parent,
			XtNx, WidthOfScreen(XtScreen(parent)) / 2,
			XtNy, HeightOfScreen(XtScreen(parent)) / 2,
			NULL);
	/* printf("done popup level window\n"); */
  return window;

}


static void
mapWindow(window)		/* perhaps there is a better name for this */
WindowStruct *window;
{
  if (window->isTopLevel) {
    XtRealizeWidget(window->widget);
  } else {
    XtPopup(window->widget, XtGrabNone);
  }
}

static long
getWindowX(window)
WindowStruct *window;
{
  long x;
  XtVaGetValues(window->widget,
		XtNx, &x,
		NULL);
  return x;
}

static long
getWindowY(window)
WindowStruct *window;
{
  long y;
  XtVaGetValues(window->widget,
		XtNy, &y,
		NULL);
  return y;
}

static long
getWindowWidth(window)
WindowStruct *window;
{
  long width;
  XtVaGetValues(window->widget,
		XtNwidth, &width,
		NULL);
  return width;
}

static long
getWindowHeight(window)
WindowStruct *window;
{
  long height;

  XtVaGetValues(window->widget,
		XtNheight, &height,
		NULL);
  return height;
}

static ColorDef*
getWindowBackgroundColor(window)
WindowStruct *window;
{
  unsigned long pixel;
  XtVaGetValues(window->widget, XtNbackground, &pixel, NULL);

  return colorFromPixel(window->widget, pixel);
}

static int
getWindowEnabled(window)
WindowStruct *window;
{
  int state;
  XtVaGetValues(window->widget, XtNsensitive, &state, NULL);
  return state;
}



static void
setWindowX(window, x)
WindowStruct *window;
long x;
{
  XtVaSetValues(window->widget, XtNx, x, NULL);
}

static void
setWindowY(window, y)
WindowStruct *window;
long y;
{
  XtVaSetValues(window->widget, XtNy, y, NULL);
}

static void
setWindowWidth(window, width)
WindowStruct *window;
unsigned long width;
{
  XtVaSetValues(window->widget, XtNwidth, width, NULL);
}

static void
setWindowHeight(window, height)
WindowStruct *window;
unsigned long height;
{
  XtVaSetValues(window->widget, XtNheight, height, NULL);
}

static void
setWindowBackgroundColor(window, color)
WindowStruct *window;
ColorDef *color;
{
  unsigned long pixel;
  pixel = allocateColor(window->widget, color);

  XtVaSetValues(window->widget,
		XtNbackground, pixel,
		NULL);
}

static void
setWindowEnabled(window, state)
WindowStruct *window;
mst_Boolean state;
{
  XtVaSetValues(window->widget, XtNsensitive, state, NULL);
}

static void
destroyWindowWidget(window)
WindowStruct *window;
{
  XtDestroyWidget(window->widget); /* I hope this frees contents */
  free(window);		/* good idea??? */
}


static Widget 
getContainerWindowObject(window)
WindowStruct *window;
{
  return window->widget;
}

static void
beginDispatchingEvents()
{
  
  XEvent event;
  while (!exitMainLoop) {
    XtAppNextEvent(appContext, &event);
    XtDispatchEvent(&event);
  }

  XtCloseDisplay(appDisplay);
  appExitedCleanly = True;
  appInitialized = False;
  toplevelWindowCreated = False;
}

/*	void mstFlash(widget)
 *
 * Description
 *
 *   Ring bell to notify user of an error. 
 *
 */
static void mstFlash()
{
  XBell(appDisplay, 100);
}

