/****************************************************************************/
/*   xmObject.h - Xm++ main header file - (03/30/1992) 03/31/1993           */
/****************************************************************************/
/*                                                                          */
/*   Copyright (c) 1992, 1993 Bernhard Strassl                              */
/*       Vienna User Interface Group                                        */
/*       Institute for Applied Computer Science and Information Systems     */
/*       University of Vienna, Austria                                      */
/*                                                                          */
/*   See file COPYRIGHT in this directory for details. If this file is      */
/*   missing please mail to xmpp@ani.univie.ac.at                           */
/****************************************************************************/

#ifndef XmObject_included
#define XmObject_included 1

#ifndef XAW
#define AW 1
#else
#define AW 0
#endif

#include <string.h>	
#include <stream.h>		// for debugging...

#ifdef XMPP_DVLP

#include <X11/Xlib.h>
#include <X11/Xos.h> 
#include <X11/keysym.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h> 
#include <X11/Xatom.h>
#include <X11/StringDefs.h>
#include <X11/Core.h>
#include <X11/Shell.h>

#ifdef XAW
typedef char* XmString;
#else
#include <X11/Xm/Xm.h>
#endif

typedef String XString;

#else

#ifdef XAW
#include "XawDefs.h"
#else
#include "MotifDefs.h"
#endif

typedef char* XString;

#endif

#include "xmStyles.h"

#ifndef NULL
#define NULL 0
#endif

#define MAGIC_OBJECT_CONST 123456

#ifdef TRUE
#undef TRUE
#endif

#ifdef FALSE
#undef FALSE
#endif

#ifdef XmObject
#undef XmObject
#endif

#ifndef BOOL_DEFINED
typedef enum bool { TRUE = 1, FALSE = 0 };
#define BOOL_DEFINED
#endif

class XmObject;

extern void translateWindowStyles(xmStyle, long&, long&);

class XmApp
{
	Display* display;
	Screen* screen;
	XrmDatabase rscDb;
	int appArgc;
	char** appArgv;
	XtAppContext appContext;
	XmObject* appShell;
	unsigned char unitType;
	bool active;

	void error(char*);
public:
	XmApp(int, char**);
	~XmApp();

	void setScreenUnitType(unsigned char);
	unsigned char getScreenUnitType()	{ return(unitType); }

	void initialize();		// to be implemented by user...

	void run();

	char* getName()						{ return(appArgv[0]); }
	Display* getDisplay()				{ return(display); }
	Screen* getScreen()					{ return(screen); }
	XrmDatabase getResourceDatabase()	{ return(rscDb); }
	XtAppContext getAppContext()		{ return(appContext); }
	char* getCmdArg(int);
	Widget getMainWindow();
	Widget newMainWindow(XmObject*, char* = NULL, int = 0, int = 0, xmStyle = 0);
	void removeMainWindow(XmObject*);
	bool isXok()						{ return(display ? TRUE : FALSE); }
	bool isActive()						{ return(active); }

	char* xmPlusPlusVersion()			{ return("0.5"); }
};

extern char* XmImageDir;
extern XmApp* App;

#define display App->getDisplay()
#define screen App->getScreen()
#define mainWindow App->getMainWindow()

#ifndef SUN
#ifndef XAW
#define cb(a) XmN##a##Callback
#else
#define cb(a) XtN##a##Callback
#endif
#endif

extern Pixmap _createXmPixmap(char*, int, int);
#define getRuntimeImage(n) _createXmPixmap(n, 0, 0)
#ifndef SUN
#define getCompiledImage(n) _createXmPixmap(n##_bits, n##_width, n##_height)
#else
#define getCompiledImage(n, w, h) _createXmPixmap(n, w, h)
#endif

class XmRootClass { };

typedef void (XmRootClass::*cbProc)(void*);

#ifdef AIX // for IBM's xlC compiler...
#define validProc(p) (p != (cbProc )NULL)
#else
#define validProc(p) p
#endif

class XmManager;

struct cb_data
{
	cbProc callback;
	XmManager* object;
	void* client_data;
};

#define CB_NO_DATA ((void* )0L)
#define CB_XM_DATA ((void* )1L)
#define CB_XM_HANDLE ((void* )2L)
#define CB_OBJ_NAME ((void* )3L)
#define CB_OBJ_PTR ((void* )4L)

typedef enum objType { SystemDialog, UserDialog, WindowObj, DialogWindow, Menu, Control };

class XmObject;
class XmWindow;
class XmDialogWindow;

class XmManager : public XmRootClass
{
protected:
	XmManager* manager;
	XmObject** objects;
	int maxObjects, objectCount;
friend class XmObject;
friend class XmDialogWindow;
friend class XmUserDialog;
	bool addObject(XmObject*, objType);
	bool removeObject(XmObject*);
	XmObject* findObject(char*, objType);
public:
	XmManager()								{ manager = NULL; objects = NULL; maxObjects = objectCount = 0; }
	virtual ~XmManager();

	XmWindow* window(char* n)				{ return((XmWindow* )findObject(n, WindowObj)); }
	XmUserDialog* dialog(char* n)			{ return((XmUserDialog* )findObject(n, UserDialog)); }
	XmDialogWindow* dialogWindow(char* n)	{ return((XmDialogWindow* )findObject(n, DialogWindow)); }

	void changed(char*, XmObject* = NULL);
};

class XmObject : public XmManager
{
protected:
friend class XmManager;
	long magic;
	XmObject* basePtr;
	XmObject* parent;
    Widget wid;
    Window win;
	char* wname;
    Arg wargs[20];
    int wargcount;
	GC gc;
    int inputMask;
	bool destroyWidget;

	XmObject()						{ init(NULL, NULL); }
	XmObject(char* n, XmObject* p)	{ init(n, p); }
	~XmObject();

	void init(char*, XmObject*);
	virtual char* hookedCb()		{ return(NULL); }
	virtual bool setCbFor(Widget, char*, XmObject*, cbProc, bool, void*);
	char parse(char*);
friend class XmControlPane;
friend class XmDialogPane;
friend class XmGroupBox;
friend class XmControl;
friend class XmWindow;
friend class XmStatusBar;
#ifdef __GNUG__
friend class XmComboBox;
#endif
    void addArg(XString s, XtArgVal v)	{ wargs[wargcount].name = s; wargs[wargcount].value = v; wargcount++; } 
    void changeArg(XString, XtArgVal);
    void changeArg(XString s, void* v)	{ changeArg(s, (XtArgVal )v); }
    void forceArg(XString, XtArgVal);
    void forceArg(XString s, void* v)	{ forceArg(s, (XtArgVal )v); }
    void getArg(XString s)				{ wargs[wargcount].name = s; wargs[wargcount].value = (XtArgVal )&(wargs[wargcount].value); wargcount++; }
	int argIndex(XString s);
	bool hasArg(XString s)				{ return(argIndex(s) != -1 ? TRUE : FALSE); }

	virtual XmUserDialog* asDialog()	{ return(NULL); }

	void syscall(char*);
	void error(char*);
public:
	char* getResourcePath(bool = FALSE);
	XmObject* getBase()					{ return(basePtr); }
	XmObject* getParent()				{ return(parent); }
	const char* getName()				{ return(wname); }
	bool isNamed(char* n)				{ return(strcmp(wname, n) == 0 ? TRUE : FALSE); }
	Widget handle()						{ return(wid); }
	virtual Widget topHandle()			{ return(wid); }
	bool valid()						{ return((bool )(magic == MAGIC_OBJECT_CONST)); }

	bool checkResource(char*);
	virtual objType objectType()=0;
	virtual char* defaultAction()		{ return(NULL); }
	virtual bool realize();
	virtual bool destroy();
	bool destroyOnDelete()				{ return(destroyWidget = TRUE); }

	bool hide();
	bool show();

	virtual bool move(int, int);
	virtual bool resize(int, int);
	virtual bool reframe(int, int, int, int);
protected:
	bool setCallback(cbProc cbCode, bool setOrReset = TRUE, void* data = CB_OBJ_PTR)												{ return(setCbFor(wid, defaultAction(), this, cbCode, setOrReset, data)); }
	bool setCallback(char* cbName, cbProc cbCode, bool setOrReset = TRUE, void* data = CB_OBJ_PTR)									{ return(setCbFor(wid, cbName, this, cbCode, setOrReset, data)); }
public:
	bool setCallback(XmObject* receiver, cbProc cbCode, bool setOrReset = TRUE, void* data = CB_OBJ_PTR)							{ return(setCbFor(wid, defaultAction(), receiver, cbCode, setOrReset, data)); }
	bool setCallback(char* cbName, XmObject* receiver, cbProc cbCode, bool setOrReset = TRUE, void* data = CB_OBJ_PTR)				{ return(setCbFor(wid, cbName, receiver, cbCode, setOrReset, data)); }
	bool setCallback(Widget w, char* cbName, XmObject* receiver, cbProc cbCode, bool setOrReset = TRUE, void* data = CB_OBJ_PTR)	{ return(setCbFor(w, cbName, receiver, cbCode, setOrReset, data)); }

	virtual void update(char*)			{ }
};

struct Entry
{
	cbProc callback;
	XmManager* receiver;
	void* client_data;
	char* text;

	Entry()													{ text = NULL; receiver = NULL; callback = NULL; client_data = NULL; }
	Entry(char* t, cbProc c, void* cd = NULL)				{ text = t; receiver = NULL; callback = c; client_data = cd; }
	Entry(char* t, XmObject* o, cbProc c, void* cd = NULL)	{ text = t; receiver = o; callback = c; client_data = cd; }
};

#define CB(x) ((cbProc )&x)
#define NULLENTRY Entry()

#define MAX_SUB_MENUES 10

class XmMenu : public XmObject
{
friend class XmSubMenu;
friend int locateItem(Widget);
	int nextItemPos;
	XmSubMenu* submenues[MAX_SUB_MENUES];
	Widget subHandles[MAX_SUB_MENUES];
	int numSubmenues;
protected:
	XmMenu(char*, XmObject*);
	~XmMenu();

	virtual Widget getCurrentLabel()	{ return((Widget )NULL); }
	XmObject* parentOfMenu();
	bool checkMenuResource(char*);
public:
	objType objectType()				{ return(Menu); }

	bool resize(int, int)				{ return(FALSE); }
	bool reframe(int, int, int, int)	{ return(FALSE); }

	void insertItemPos(int pos)			{ nextItemPos = pos; } 
	bool addSeparator(char* = (char* )NULL);
	bool removeSeparator(char* = (char* )NULL);
	bool addItem(Entry e)				{ return(addItems(e, Entry())); }
	bool addItems(Entry, ...);
	bool removeItem(char* n)			{ return(removeItems(n, NULL)); }
	bool removeItems(char*, ...);
	bool enableItem(char* n)			{ return(enableItems(n, NULL)); }
	bool enableItems(char*, ...);
	bool disableItem(char* n)			{ return(disableItems(n, NULL)); }
	bool disableItems(char*, ...);
	XmSubMenu* addSubmenu(char*);
	XmSubMenu* submenuAt(char*);
	bool removeSubmenu(char*);

	bool changeItemText(char*, char*);
};

class XmPopupMenu : public XmMenu
{
friend class XmDialogWindow;
	XmPopupMenu(char*, XmObject*);
	Widget getCurrentLabel()			{ return(wid); }
public:
	bool setLabel(char*);
};

#ifndef MAX_DROPDOWN_LABELS
#define MAX_DROPDOWN_LABELS 10
#endif

class XmDropdownMenu : public XmMenu
{
friend int locateLabel(Widget);
	Widget dropdowns[MAX_DROPDOWN_LABELS];
	Widget currentLabel;
	int numDropdowns;
	int nextLabelPos;
friend class XmDialogWindow;
	XmDropdownMenu(char*, XmObject*);

	Widget getCurrentLabel()			{ return(currentLabel); }
public:
	void insertLabelPos(int pos)		{ nextLabelPos = pos; }
	bool addLabel(char* n)				{ return(addLabels(n, NULL)); }
	bool addLabels(char*, ...);
	bool removeLabel(char* n)			{ return(removeLabels(n, NULL)); }
	bool removeLabels(char*, ...);
	bool setCurrentLabel(char*);

	bool changeLabelText(char*, char*);
	bool changeItemText(char* l, char* i, char* txt)	{ return((bool )(setCurrentLabel(l) && XmMenu::changeItemText(i, txt))); }
};

class XmSubMenu : public XmMenu
{
friend class XmMenu;
	XmSubMenu(char*, XmMenu*);
	~XmSubMenu();

	Widget getCurrentLabel()			{ return(wid); }
};

typedef enum dlgType { FORM, MESSAGE, PROMPT, SELECTION, FILES };
typedef enum rscMode { INTERNAL, EXTERNAL };

#ifdef __GNUG__
class XmDialog : virtual public XmObject
#else
class XmDialog : public XmObject
#endif
{
	bool completed, returned;
protected:
	xmStyle dlgStyle;

	XmDialog()							{ dlgStyle = XmSdlgModeless; }
	XmDialog(char*, XmObject*, xmStyle = 0);
	~XmDialog();

	bool setLabelAndMode(char*);
	bool run();
private:
friend class XmMsgBox;
	void ok(void*);
	void cancel(void*);
	void close(void*);
};

typedef enum msgButton { OK, CANCEL, HELP };

class XmSystemDialog : public XmDialog
{
protected:
	XmSystemDialog(char*, XmObject*, xmStyle = 0);

	objType objectType()				{ return(SystemDialog); }
};

class XmMsgBox : public XmSystemDialog
{
protected:
	XmMsgBox(char*, XmObject*, xmStyle);

	void setDefaultButtonProcs(XmObject*, cbProc);
public:
	XmMsgBox(char*, char*, xmStyle = XmSmboxInfo, XmObject* = (XmObject* )NULL, cbProc = NULL);

	bool showMsg();
	bool setButtonText(msgButton, char*);
};

class XmPrompter : public XmMsgBox
{
protected:
	XmPrompter(char*, XmObject*, xmStyle);
public:
	XmPrompter(char*, char*, char*, xmStyle = XmSmboxOption, XmObject* = (XmObject* )NULL, cbProc = NULL);

	char* prompt();
	bool setText(char*);
	char* getText();
};

class XmListPrompter : public XmPrompter
{
public:
	XmListPrompter(char**, char*, char*, char*, xmStyle = XmSmboxOption, XmObject* = (XmObject* )NULL, cbProc = NULL);

	int promptIndex();
	XmListPrompter* selectText(char*);
	XmListPrompter* selectIndex(int);

	int getIndex();
};

class XmFileSelector : public XmPrompter
{
public:
	XmFileSelector(char*, char* = NULL, xmStyle = XmSmboxOption, XmObject* = (XmObject* )NULL, cbProc = NULL);

	char* promptFile();
	bool setPath(char*);
	char* getPath();
};


#ifndef MAX_DLG_CONTROLS
#define MAX_DLG_CONTROLS 100
#endif

class XmControl;
class XmGroupBox;
class XmStaticText;
class XmStaticImage;
class XmPushButton;
class XmCheckBox;
class XmRadioButton;
class XmEdit;
class XmScrollBar;
class XmListBox;
class XmComboBox;

// class XmCheckBoxGroup;
// class XmRadioButtonGroup;

#undef PushButton
#undef CheckBox

typedef enum ctrlType { 	GroupBox, StaticText, StaticImage, PushButton,
							CheckBox, RadioButton, Edit, ScrollBar, ListBox,
							ComboBox, Drawing, Pane, PaneArea, ToolBar   };
class XmDrawing;
class XmDialogWindow;

class XmControlPane
{
public:
	virtual const char* getName()=0;
	virtual Widget handle()=0;
	virtual XmObject* asObject()=0;
};

class XmDialogPane : public XmControlPane
{
friend class XmControl;
friend class XmUserDialog;
friend class XmWindow;
friend class XmStatusBar;
	XmRadioButton* curRadio;
	XmControl* controls[MAX_DLG_CONTROLS];
	int controlCount;
	XmControl* lastFocus;

	int controlIndex(XmControl*);
protected:
	virtual XmControl* findControl(ctrlType, char*, bool = TRUE);
	virtual XmGroupBox* nextGroup(int&);
	virtual void getFocus(Widget);

	XmDialogPane()								{ curRadio = NULL; controlCount = 0; lastFocus = NULL; }
	virtual ~XmDialogPane();
public:
	virtual bool add(XmControl*, XmObject* = NULL, cbProc = NULL, void* = CB_OBJ_PTR);
	bool add(XmComboBox* c, XmObject* o = NULL, cbProc p = NULL, void* cd = CB_OBJ_PTR)	{ return(add((XmControl* )((void* )c), o, p, cd)); }
	virtual bool remove(char*);
	XmControl* find(char*);

#ifndef __GNUG__
	XmGroupBox* groupBox(char* n)				{ return((XmGroupBox* )findControl(GroupBox, n)); }
	XmStaticText* staticText(char* n)			{ return((XmStaticText* )findControl(StaticText, n)); }
	XmStaticImage* staticImage(char* n)			{ return((XmStaticImage* )findControl(StaticImage, n)); }
	XmPushButton* pushButton(char* n)			{ return((XmPushButton* )findControl(PushButton, n)); }
	XmRadioButton* radioButton(char* n)			{ return((XmRadioButton* )findControl(RadioButton, n)); }
	XmCheckBox* checkBox(char* n)				{ return((XmCheckBox* )findControl(CheckBox, n)); }
	XmEdit* edit(char* n)						{ return((XmEdit* )findControl(Edit, n)); }
	XmScrollBar* scrollBar(char* n)				{ return((XmScrollBar* )findControl(ScrollBar, n)); }
	XmListBox* listBox(char* n)					{ return((XmListBox* )findControl(ListBox, n)); }
	XmComboBox* comboBox(char* n)				{ return((XmComboBox* )findControl(ComboBox, n)); }
	XmDrawing* drawing(char* n)					{ return((XmDrawing* )findControl(Drawing, n)); }
#else
	// avoid calling virtual (gcc bug?), may cause incorrect results
	// in some subclasses - workaround: more steps...
	XmGroupBox* groupBox(char* n)				{ return((XmGroupBox* )XmDialogPane::findControl(GroupBox, n)); }
	XmStaticText* staticText(char* n)			{ return((XmStaticText* )XmDialogPane::findControl(StaticText, n)); }
	XmStaticImage* staticImage(char* n)			{ return((XmStaticImage* )XmDialogPane::findControl(StaticImage, n)); }
	XmPushButton* pushButton(char* n)			{ return((XmPushButton* )XmDialogPane::findControl(PushButton, n)); }
	XmRadioButton* radioButton(char* n)			{ return((XmRadioButton* )XmDialogPane::findControl(RadioButton, n)); }
	XmCheckBox* checkBox(char* n)				{ return((XmCheckBox* )XmDialogPane::findControl(CheckBox, n)); }
	XmEdit* edit(char* n)						{ return((XmEdit* )XmDialogPane::findControl(Edit, n)); }
	XmScrollBar* scrollBar(char* n)				{ return((XmScrollBar* )XmDialogPane::findControl(ScrollBar, n)); }
	XmListBox* listBox(char* n)					{ return((XmListBox* )XmDialogPane::findControl(ListBox, n)); }
	XmComboBox* comboBox(char* n)				{ return((XmComboBox* )XmDialogPane::findControl(ComboBox, n)); }
	XmDrawing* drawing(char* n)					{ return((XmDrawing* )XmDialogPane::findControl(Drawing, n)); }

	// these virtuals come from the XmUserDialog class, gcc doesn't handle them there... 
	virtual bool initWindowSize(int&, int&, int&, int&)		{ return(FALSE); }
	virtual void initialize()					{ createContents(); initContents(); }
	virtual void createContents()				{ }
	virtual void initContents()					{ }
#endif
	bool disable(char**);
	bool disable(char*, ...);
	bool enable(char**);
	bool enable(char*, ...);
	bool hideAll(char**);
	bool hideAll(char*, ...);
	bool showAll(char**);
	bool showAll(char*, ...);
};

class XmUserDialog : public XmDialog, public XmDialogPane
{
friend class XmDialogWindow;
friend class XmWindow;
	Position ix, iy;
	Dimension iw, ih;

	void initDialog(char*, XmObject*, xmStyle);
	void getFocusCb(void*);
	void destroyCb(void*);
public:
	XmUserDialog(char*, XmObject* = NULL, xmStyle = 0);
	XmUserDialog(char*, XmObject*, XmManager*, xmStyle = 0);
	~XmUserDialog();

	virtual bool initWindowSize(int&, int&, int&, int&)		{ return(FALSE); }

	virtual void initialize()					{ createContents(); initContents(); }
	virtual void createContents()				{ }
	virtual void initContents()					{ }

#ifndef __GNUG__
	Widget handle()								{ return(XmObject::handle()); }
#else
	Widget handle()								{ return(wid); }
#endif
	const char* getName()						{ return(wname); }
	XmObject* asObject()						{ return(this); }

	objType objectType()						{ return(UserDialog); }
	XmUserDialog* asDialog()					{ return(this); }

	void setInitWindowSize(int x, int y, int w, int h)		{ ix = x; iy = y; iw = w; ih = h; }

	bool open()									{ initialize(); return(realize()); }
	bool realize();
	bool setLabel(char*);

	bool setFocus(char*);
	bool setDefaultButton(char*);
};

#define isAn(t) isA(t)

class XmControl : public XmObject
{
protected:
friend class XmDialogWindow;
friend class XmWindow;
friend class XmControlPane;
friend class XmDialogPane;
friend class XmPane;
friend class XmUserDialog;
friend class XmGroupBox;
friend class XmPaneArea;
friend class XmToolBar;
	Position cx, cy;
	Dimension cw, ch;
	xmStyle style;
	Entry userData;

	virtual bool createControl(XmControlPane*)=0;
	virtual char* defaultCallback()=0;
	virtual ctrlType controlType()=0;

	bool setCbFor(Widget, char*, XmObject*, cbProc, bool, void*);

	virtual void makeRelativeTo(XmGroupBox*);
	virtual void realized()							{ }
	virtual void cleanup()							{ }
	virtual bool hasWidget(Widget w)				{ return((wid == w) ? TRUE : FALSE); }
	void initTabstop(bool = FALSE);
	char* currentLabel();
	void setLabelAndMnemonic();

	XmControl(char*, int, int, int, int, xmStyle);
public:
	XmUserDialog* getDialog();

	objType objectType()							{ return(Control); }
	char* defaultAction()							{ return(defaultCallback()); }
	bool isA(ctrlType t)							{ return((bool )(controlType() == t)); }
	void setUserData(XmObject* rec, cbProc code)	{ userData.receiver = rec; userData.callback = code; }

	xmStyle getStyle()								{ return(style); }
	bool changeStyle(xmStyle s)						{ style = s; return(wid ? FALSE : TRUE); }
	bool move(int, int);
	bool resize(int, int);
	bool reframe(int, int, int, int);
	bool updateDimensions();

	virtual XmControl* setText(char*);
	virtual XmControl* setFont(char*);
	virtual char* getText();
	virtual XmControl* setImage(Pixmap);
	virtual XmControl* setFocus();
	virtual XmControl* disable();
	virtual XmControl* enable();
};

class XmGroupBox : public XmControl, public XmDialogPane
{
	XmRadioButton* curRadio;
friend class XmComboBox;
	bool createControl(XmControlPane*);
	char* defaultCallback()							{ return(NULL); }
	ctrlType controlType()							{ return(GroupBox); };

	void getFocusCb(void*);
public:
	XmGroupBox(char* name, int x, int y, int w, int h, xmStyle s = 0) : XmControl(name, x, y, w, h, s)	{ curRadio = NULL; }

	const char* getName()							{ return(wname); }
	Widget handle()									{ return(XmObject::handle()); }
	XmObject* asObject()							{ return(getBase()); }
	XmUserDialog* asDialog()						{ return(((XmUserDialog* )((void* )parent))->asDialog()); }

	bool addAbs(XmControl*, XmObject* = NULL, cbProc = NULL, void* = CB_OBJ_PTR);
	bool addAbs(XmComboBox* c, XmObject* o = NULL, cbProc p = NULL, void* cd = CB_OBJ_PTR)	{ return(addAbs((XmControl* )((void* )c), o, p, cd)); }
	bool remove(char*);

	bool parentFor(XmControl*);
};

class XmPane : public XmControl, public XmControlPane
{
friend class XmPaneArea;
	Widget hLabel;
	XmControl* contents;

	const char* getName()							{ return(wname); }
	Widget handle()									{ return(XmObject::handle()); }
	XmObject* asObject()							{ return(getBase()); }

	bool createControl(XmControlPane*);
	char* defaultCallback()							{ return(NULL); }
	ctrlType controlType()							{ return(Pane); };

	XmPane(char* name, int x, int y, int w, int h) : XmControl(name, x, y, w, h, 0)	{ contents = NULL; }

	bool setContents(XmControl*, XmObject* = NULL, cbProc = NULL);
	bool changeLabel(char*);
public:
	XmControl* getControl(ctrlType t, char* n)		{ return((contents && contents->isA(t) && !strcmp(contents->getName(), n)) ? contents : NULL); }
};

class XmPaneArea : public XmGroupBox
{
	int subPaneCount;

	bool createControl(XmControlPane*);
	char* defaultCallback()							{ return(NULL); }
	ctrlType controlType()							{ return(PaneArea); };

	bool add(XmControl*, XmObject* = NULL, cbProc = NULL, void* = CB_OBJ_PTR);
	bool remove(char*);

	void changed(void*);
public:
	XmPaneArea(char* name, int x, int y, int w, int h) : XmGroupBox(name, x, y, w, h)	{ subPaneCount = 0; }

	int numSubpanes()								{ return(subPaneCount); }

	bool addSubpane(XmControl*, char* = NULL, XmObject* = NULL, cbProc = NULL);
	bool removeSubpane(char* name)					{ return(remove(name)); }

	bool changeSubpaneLabel(char*, char*);
};

class XmToolBar : public XmGroupBox
{
	int rows;
friend class XmStatusBar;
	bool createControl(XmControlPane*);
	char* defaultCallback()							{ return(NULL); }
	ctrlType controlType()							{ return(ToolBar); };
public:
	XmToolBar(char* name, xmStyle s = XmShorizontal) : XmGroupBox(name, 0, 0, 0, 0, s)	{ rows = 1; }

	bool setRows(int n)								{ rows = n; return(wid ? FALSE : TRUE); }

	bool add(XmControl*, XmObject* = NULL, cbProc = NULL, void* = CB_OBJ_PTR);
	bool disableAll(char** l)						{ return(XmDialogPane::disable(l)); }
	bool enableAll(char** l)						{ return(XmDialogPane::enable(l)); }
};

class XmStatusBar : public XmGroupBox
{
	XmEdit* statusLine;

	bool createControl(XmControlPane*);
public:
	XmStatusBar(char* name) : XmGroupBox(name, 0, 0, 0, 0)		{ statusLine = NULL; }

	bool add(XmControl*, XmObject* = NULL, cbProc = NULL, void* = CB_OBJ_PTR);
	bool remove(char*);

	bool setMessage(char*);
};

class XmStaticText : public XmControl
{
	bool createControl(XmControlPane*);
	char* defaultCallback()							{ return(NULL); }
	ctrlType controlType()							{ return(StaticText); };
public:
	XmStaticText(char* name, int x = 0, int y = 0, int w = 0, int h = 0, xmStyle s = 0) : XmControl(name, x, y, w, h, s)	{ }
};

class XmStaticImage : public XmControl
{
	bool createControl(XmControlPane*);
	char* defaultCallback()							{ return(NULL); }
	ctrlType controlType()							{ return(StaticImage); };
public:
	XmStaticImage(char* name, int x = 0, int y = 0, int w = 0, int h = 0, xmStyle s = 0) : XmControl(name, x, y, w, h, s)	{ }
};

class XmPushButton : public XmControl
{
	bool createControl(XmControlPane*);
#ifdef XAW
	char* defaultCallback()							{ return(XtNcallback); }
#else
	char* defaultCallback()							{ return(XmNactivateCallback); }
#endif
	ctrlType controlType()							{ return(PushButton); };
public:
	XmPushButton(char* name, int x = 0, int y = 0, int w = 0, int h = 0, xmStyle s = 0) : XmControl(name, x, y, w, h, s)	{ }
};

class XmCheckBox : public XmControl
{
friend class XmRadioButton;
	bool createControl(XmControlPane*);
#ifdef XAW
	char* defaultCallback()							{ return(XtNcallback); }
#else
	char* defaultCallback()							{ return(XmNvalueChangedCallback); }
#endif
	ctrlType controlType()							{ return(CheckBox); };
public:
	XmCheckBox(char* name, int x = 0, int y = 0, int w = 0, int h = 0, xmStyle s = 0) : XmControl(name, x, y, w, h, s)	{ }

	virtual bool setState(bool);
	bool getState();
};

class XmRadioButton : public XmCheckBox
{
friend class XmDialogPane;
friend class XmUserDialog;
friend class XmGroupBox;
	XmRadioButton* prev, *next;

	bool createControl(XmControlPane*);
	void chainTo(XmRadioButton* n)					{ next = n; n->prev = this; }
#ifdef XAW
	char* hookedCb()								{ return(XtNcallback); }
#else
	char* hookedCb()								{ return(XmNvalueChangedCallback); }
#endif
	ctrlType controlType()							{ return(RadioButton); };

	void selected(void*);
	void reset(bool);
public:
	XmRadioButton(char* name, int x = 0, int y = 0, int w = 0, int h = 0, xmStyle s = 0) : XmCheckBox(name, x, y, w, h, s)	{ prev = next = NULL; }

	bool setState(bool);
};

class XmEdit : public XmControl
{
friend class XmComboBox;
	bool multiLine;
	bool hScroll, vScroll;
	char* pasteBuffer, * lastVersion;

	bool createControl(XmControlPane*);
#ifdef XAW
	char* hookedCb()								{ return(XtNcallback); }
	char* defaultCallback()							{ return(XtNcallback); }
#else
	char* hookedCb()								{ return(XmNvalueChangedCallback); }
	char* defaultCallback()							{ return(XmNvalueChangedCallback); }
#endif
	ctrlType controlType()							{ return(Edit); };

	void changed(void*);
public:
	XmEdit(char* name, int x = 0, int y = 0, int w = 0, int h = 0, xmStyle s = 0) : XmControl(name, x, y, w, h, s)	{ multiLine = hScroll = vScroll = FALSE; pasteBuffer = lastVersion = NULL; }
	~XmEdit();

	Widget topHandle()								{ return((vScroll || hScroll) ? (wid ? XtParent(wid) : NULL) : wid); }
	bool resize(int, int);
	bool reframe(int, int, int, int);

	bool enableMultipleLines()						{ style |= XmSmultiLine; return(wid ? FALSE : TRUE); }
	bool enableHScroll()							{ style |= XmSautovscroll; return(wid ? FALSE : TRUE); }
	bool enableVScroll()							{ style |= XmSautohscroll; return(wid ? FALSE : TRUE); }

	XmControl* setText(char*);
	char* getText();

	long getInsertPosition(int* = NULL, int* = NULL);

	char* getSelection();
	bool setSelection(int, int);
	bool clearSelection();

	bool cut();
	bool copy();
	bool paste();
};

class XmListBox : public XmControl
{
friend class XmComboBox;
	bool multiSel;

	bool createControl(XmControlPane*);
#ifdef XAW
	char* defaultCallback()							{ return(XtNcallback); }
#else
	char* defaultCallback()							{ return(multiSel ? XmNextendedSelectionCallback : XmNbrowseSelectionCallback); }
#endif
	ctrlType controlType()							{ return(ListBox); };
	void cleanup();
public:
	XmListBox(char* name, int x = 0, int y = 0, int w = 0, int h = 0, xmStyle s = 0) : XmControl(name, x, y, w, h, s)	{ multiSel = (s & XmSmultipleSel ? TRUE : FALSE); }

	Widget topHandle()								{ return(wid ? XtParent(wid) : NULL); }
	bool resize(int, int);
	bool reframe(int, int, int, int);

	XmListBox* add(char* n)							{ return(addAll(n, NULL)); }
	XmListBox* insert(int i, char* n)				{ return(insertAll(i, n, NULL)); }
	bool remove(char* n)							{ return(removeAll(n, NULL)); }
	bool remove(int i)								{ return(removeAll(i, NULL)); }
	bool change(char*, char*);
	bool change(int, char*);

	XmListBox* addAll(char**);
	XmListBox* addAll(char*,...);
	XmListBox* insertAll(int, char**);
	XmListBox* insertAll(int, char*,...);
	bool removeAll(char**);
	bool removeAll(char*,...);
	bool removeAll(int*);
	bool removeAll(int,...);

	bool clear();

	bool selectText(char*, bool = FALSE);
	bool selectIndex(int, bool = FALSE);
	bool deselectText(char*);
	bool deselectIndex(int);
	bool deselectAll();

	bool setDoubleClickProc(XmObject*, cbProc);

	int selectedCount();
	char* selectedItem()		{ char** all = selectedItems(); char* it = all[0]; delete all; return(it); }
	char** selectedItems();
	int selectedIndex()			{ int* all = selectedIndices(); int it = all[0]; delete all; return(it); }
	int* selectedIndices();
};

typedef enum comboType { SIMPLE, DROPDOWN, DROPDOWNLIST };

class XmComboBox : public XmGroupBox, public XmPushButton, public XmListBox, public XmEdit
{
	Widget popup;
	comboType cbStyle;
	bool lbMapped;

	bool createControl(XmControlPane*);
#ifdef XAW
	char* hookedCb()								{ return(XtNcallback); }
	char* defaultCallback()							{ return(XtNcallback); }
#else
	char* hookedCb()								{ return(XmNvalueChangedCallback); }
	char* defaultCallback()							{ return(XmNvalueChangedCallback); }
#endif
	ctrlType controlType()							{ return(ComboBox); }

	void makeRelativeTo(XmGroupBox*);
	void cleanup();

	void selectArrow(void*);
	void changeText(void*);
	void selectInList(void*);
	void cleanupCb(void*);
public:
	XmComboBox(char* name, int x = 0, int y = 0, int w = 35, int h = 35, xmStyle s = 0);
	~XmComboBox();

	operator XmControl* ()							{ return((XmGroupBox* )this); }

	Widget topHandle()								{ return(XmGroupBox::handle()); }
	bool move(int, int);
	bool resize(int, int);
	bool reframe(int, int, int, int);

	bool realize();
	const char* getName()							{ return(XmGroupBox::getName()); }
	XmUserDialog* getDialog()						{ return(XmGroupBox::getDialog()); }

	XmControl* setText(char* txt)					{ return(XmEdit::setText(txt)); }
	char* getText()									{ return(XmEdit::getText()); }

	XmControl* setFocus();
	XmControl* disable();
	XmControl* enable();
};

class XmToolObject : public XmObject
{
	bool orientation;

};

class XmDialogWindow : public XmUserDialog
{
friend class XmWindow;
friend class XmToolBox;
	xmStyle style;
	XmPopupMenu* popup;
	XmDropdownMenu* dropdown;

	bool initWindowSize(int&, int&, int&, int&)		{ return(FALSE); }
	virtual void menuSet()							{ }
protected:
	XmControl* findControl(ctrlType, char*, bool = TRUE);
public:
	XmDialogWindow(char*, XmObject* = NULL, xmStyle = 0);
	XmDialogWindow(char*, XmObject*, XmManager*, xmStyle = 0);
	~XmDialogWindow();

	objType objectType()					{ return(DialogWindow); }
	void initialize()						{ }
	bool realize();

	bool add(XmControl*, XmObject* = NULL, cbProc = NULL, void* = CB_OBJ_PTR);
	bool add(XmComboBox* c, XmObject* o = NULL, cbProc p = NULL, void* cd = CB_OBJ_PTR)	{ return(add((XmControl* )((void* )c), o, p, cd)); }

	XmPopupMenu* createPopupMenu(char* n = "&Menu")	{ popup = new XmPopupMenu(n, this); menuSet(); return(popup); }
	XmDropdownMenu* createDropdownMenu()			{ dropdown = new XmDropdownMenu("dropdown", this); /* menuSet(); */ return(dropdown); }
	XmPopupMenu* getPopup()					{ return(popup); }
	XmDropdownMenu* getDropdown()			{ return(dropdown); }
};

class XmWindow : public XmDialogWindow
{
friend class XmStatusBar;
	XmPaneArea* panes;
	XmToolBar* toolbars[4];
	XmStatusBar* statusbar;

	void initWindowContents(char*);
	void checkLayout();
	void menuSet();

	XmControl* findControl(ctrlType t, char* n, bool w = TRUE)		{ return(panes->findControl(t, n, w)); }
public:
	XmWindow(char* n, XmObject* par = NULL, xmStyle s = 0) : XmDialogWindow(n, par, s) { initWindowContents(n); }
	XmWindow(char* n, XmObject* par, XmManager* m, xmStyle s = 0) : XmDialogWindow(n, par, m, s) { initWindowContents(n); }
#ifdef __GNUG__
	bool initWindowSize(int&, int&, int&, int&)		{ return(FALSE); }
	void initialize()								{ }
#endif
	objType objectType()							{ return(WindowObj); }
	bool realize();

	bool addSubpane(ctrlType, char*, char* = NULL, int = 0, int = 0, XmObject* = NULL, cbProc = NULL);
	bool addSubpane(XmControl* c, char* l = NULL, XmObject* rec = NULL, cbProc cbk = NULL)	{ return(panes->addSubpane(c, l, rec, cbk)); }
	bool removeSubpane(char* name)					{ return(panes->removeSubpane(name)); }
	bool changeSubpaneLabel(char* n, char* l)		{ return(panes->changeSubpaneLabel(n, l)); }

	XmToolBar* addToolbar(xmStyle);
	bool removeToolbar(XmToolBar*);
	XmToolBar* toolbar(xmStyle);

	XmStatusBar* createStatusBar();
	XmStatusBar* getStatusBar()						{ return(statusbar); }
};

#ifndef __GNUG__

class XmToolBox : public XmDialogWindow, public XmToolBar
{
public:
	XmToolBox(char*, XmObject*, xmStyle = XmSvertical, int = 1);
	XmToolBox(char*, XmObject*, XmManager*, xmStyle = XmSvertical, int = 1);

	bool move(int x, int y)						{ return(XmDialogWindow::move(x, y)); }
	bool resize(int x, int y)					{ return(XmDialogWindow::resize(x, y)); }
	bool reframe(int x, int y, int w, int h)	{ return(XmDialogWindow::reframe(x, y, w, h)); }
	char* defaultAction()						{ return(XmToolBar::defaultAction()); }
	objType objectType()						{ return(XmDialogWindow::objectType()); }
	bool setCbFor(Widget w, char* n, XmObject* r, cbProc cbk, bool sr, void* cd)	{ return(XmDialogWindow::setCbFor(w, n, r, cbk, sr, cd)); }
	XmUserDialog* asDialog()					{ return(XmDialogWindow::asDialog()); }

	bool realize()								{ return(XmUserDialog::realize()); }
};

#endif

#endif
