Xm++ Bugs and Limitiations using the gnu c++ Compiler
-----------------------------------------------------

Xm++ was developed using HP C++ (as it was shipped with HP-UX 8.07, improved
version of an AT&T v2.X compiler) and seems to work without changes with the
original AT&T C++ since v2.1 (v2.0 had a nasty varargs bug).

Xm++ uses multiple inheritance in many cases (take a look at the class tree
in lib/classes.gif). When porting the stuff to compile with g++ 2.3.3, I had
a lot of troubles, all of them caused by multiple inheritance. I dont't know
whether there are bugs in AT&T C++ that it accepts my dirty code (everything
works fine in this case) or there are bugs in g++. Regardless of the reason
I had to find workarounds. 
The first problem was, that Superclass1::methodOrVariable expressions to
access ambigous members do not work, the value returned in case of variables
or non virtual functions are not from Superclass1 (but from an arbitrary other
subpart of the object). ((Superclass1*)this)->methodOrVariable solved this.
Unlike the above (which should not concern a normal framework user) the
remaining problems bring some restrictions to the g++ user:

- The XmToolBox class is not available due an internal g++ failure when
trying to compile it ('warning: internal consistency check failed, please
report'), use toolbars or, if necessary, a normal userDialog as a replacement.

- A lot of virtual functions do not work correctly; in g++ 2.3.2 they caused
an 'illegal instruction' error, g++ 2.3.3 simply ignores them by calling the
usually empty superclass function. You have to define your own non-virtual
replacements for them or to use the ThisClass::myVirtualFunction() expression
to disable the virtual mechanism. There are only a few functions where you
have to care about this:

1) bool initWindowSize(int& x, int& y, int& width, int& height)
Is called when realizing a main window or dialog box, should answer true if
something was assigned to the integer references. This way of getting the
window coordinates may look funny but makes sense when using the dialog
editor, which generates the definition of this function - the user has not
to care about it even when re-editing the dialog. As this feature does not
work with g++, you have to invoke an active function
setInitWindowSize(x, y, w, h) in your dialog's constructor or initialize()
function - this parameters have to be updated after changing the dialog size.

2) initialize(), createContents(), initContents() and open()
These functions provide automated initialization of main window or dialog
box:
initialize() in case of a main window has to be implemented by the user
  and should create and initialize all the menues, toolbars and subpanes
  (in the usersGuide.txt examples this is done in the window's constructor,
  although it works, it is not correct - look at the samples).
initialize() in case of a user dialog calls createContents() and
  initContents() in order. createContents() is generated by the dialog
  editor and creates and adds all the controls to the dialog. initContents()
  can be implemented by the user to perform the initial setting of control
  states and values.
open() simply calls initialize() and realize() which displays the object.

Example: the statement (new MyWindowOrDialog)->open(); performs anything
necessary to create, initialize and display a window by calling the
respective virtual functions - the MyWindowOrDialog's constructor may be
empty.
But, sorry, this is not true for g++ users yet because all the nice virtual
functions do not work (though I hope, that I can solve this problem in the
future). For gnu you need a workaround:

Implement everything as the virtuals were working and then specify an
additional inline function to your window or dialog class - in case of a
main window

void gnuInit() {
   setInitWindowSize(0, 0, ???, ???);
   MyWindowClass::initialize();
}

in case of a user dialog (this is contained in the class template generated
by the dialog editor, you only need to copy it into your header file)

void gnuOpen() {
   setInitWindowSize(0, 0, ???, ???);
   MyDialogClass::createContents();
   MyDialogClass::initContents();
   realize();
}

The only thing left is to call the workaround function instead of the
original initialize or open function in the rest of the application:

(new MyWindow)->gnuInit();    // initialize();  ...commented out...
(new MyDialog)->gnuOpen();    // open();


A few words of wisdom: there should be no more limitations beside the ones
described above, and - when compiling all this workarounds with an AT&T
compiler you should have no problems. Maybe, that for one of you c++ gurus
out there the solution needs less time than I needed to write this - if
so, please let me know! (e-mail addr. in the main README file)
