+#endif
+
+#include "wx/setup.h"
+#include "wx/utils.h"
+#include "wx/apptrait.h"
+#include "wx/app.h"
+#include "wx/dcmemory.h"
+#include "wx/bitmap.h"
+#include "wx/evtloop.h"
+
+#include <string.h>
+
+#if (defined(__SUNCC__) || defined(__CLCC__))
+ #include <sysent.h>
+#endif
+
+#ifdef __VMS__
+#pragma message disable nosimpint
+#endif
+
+#include "wx/unix/execute.h"
+
+#include <Xm/Xm.h>
+#include <Xm/Frame.h>
+
+#include "wx/motif/private.h"
+
+#if wxUSE_RESOURCES
+#include "X11/Xresource.h"
+#endif
+
+#include "X11/Xutil.h"
+
+#ifdef __VMS__
+#pragma message enable nosimpint
+#endif
+
+// ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
+// Yuck this is really BOTH site and platform dependent
+// so we should use some other strategy!
+#ifdef sun
+ #define DEFAULT_XRESOURCE_DIR "/usr/openwin/lib/app-defaults"
+#else
+ #define DEFAULT_XRESOURCE_DIR "/usr/lib/X11/app-defaults"
+#endif
+
+#if wxUSE_RESOURCES
+static char *GetIniFile (char *dest, const char *filename);
+#endif
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// async event processing
+// ----------------------------------------------------------------------------
+
+// Consume all events until no more left
+void wxFlushEvents(WXDisplay* wxdisplay)
+{
+ Display *display = (Display*)wxdisplay;
+ wxEventLoop evtLoop;
+
+ XSync (display, False);
+
+ while (evtLoop.Pending())
+ {
+ XFlush (display);
+ evtLoop.Dispatch();
+ }
+}
+
+// ----------------------------------------------------------------------------
+// wxExecute stuff
+// ----------------------------------------------------------------------------
+
+static void xt_notify_end_process(XtPointer data, int *WXUNUSED(fid),
+ XtInputId *id)
+{
+ wxEndProcessData *proc_data = (wxEndProcessData *)data;
+
+ wxHandleProcessTermination(proc_data);
+
+ // VZ: I think they should be the same...
+ wxASSERT( (int)*id == proc_data->tag );
+
+ XtRemoveInput(*id);
+}
+
+int wxAddProcessCallback(wxEndProcessData *proc_data, int fd)
+{
+ XtInputId id = XtAppAddInput((XtAppContext) wxTheApp->GetAppContext(),
+ fd,
+ (XtPointer *) XtInputReadMask,
+ (XtInputCallbackProc) xt_notify_end_process,
+ (XtPointer) proc_data);
+
+ return (int)id;
+}
+
+// ----------------------------------------------------------------------------
+// misc
+// ----------------------------------------------------------------------------
+
+// Emit a beeeeeep
+#ifndef __EMX__
+// on OS/2, we use the wxBell from wxBase library (src/os2/utils.cpp)
+void wxBell()
+{
+ // Use current setting for the bell
+ XBell (wxGlobalDisplay(), 0);
+}
+#endif
+
+wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
+{
+ static wxToolkitInfo info;
+
+ info.shortName = _T("motif");
+ info.name = _T("wxMotif");
+#ifdef __WXUNIVERSAL__
+ info.shortName << _T("univ");
+ info.name << _T("/wxUniversal");
+#endif
+ // FIXME TODO
+ // This code is WRONG!! Does NOT return the
+ // Motif version of the libs but the X protocol
+ // version!
+ Display *display = wxGlobalDisplay();
+ if (display)
+ {
+ info.versionMajor = ProtocolVersion (display);
+ info.versionMinor = ProtocolRevision (display);
+ }
+ info.os = wxMOTIF_X;
+ return info;
+}
+
+// ----------------------------------------------------------------------------
+// Reading and writing resources (eg WIN.INI, .Xdefaults)
+// ----------------------------------------------------------------------------
+
+#if wxUSE_RESOURCES
+
+// Read $HOME for what it says is home, if not
+// read $USER or $LOGNAME for user name else determine
+// the Real User, then determine the Real home dir.
+static char * GetIniFile (char *dest, const char *filename)
+{
+ char *home = NULL;
+ if (filename && wxIsAbsolutePath(filename))
+ {
+ strcpy(dest, filename);
+ }
+ else if ((home = wxGetUserHome()) != NULL)
+ {
+ strcpy(dest, home);
+ if (dest[strlen(dest) - 1] != '/')
+ strcat (dest, "/");
+ if (filename == NULL)
+ {
+ if ((filename = getenv ("XENVIRONMENT")) == NULL)
+ filename = ".Xdefaults";
+ }
+ else if (*filename != '.')
+ strcat (dest, ".");
+ strcat (dest, filename);
+ } else
+ {
+ dest[0] = '\0';
+ }
+ return dest;
+}
+
+static char *GetResourcePath(char *buf, const char *name, bool create = false)
+{
+ if (create && wxFileExists (name) ) {
+ strcpy(buf, name);
+ return buf; // Exists so ...
+ }
+
+ if (*name == '/')
+ strcpy(buf, name);
+ else {
+ // Put in standard place for resource files if not absolute
+ strcpy (buf, DEFAULT_XRESOURCE_DIR);
+ strcat (buf, "/");
+ strcat (buf, wxFileNameFromPath (name).c_str());
+ }
+
+ if (create) {
+ // Touch the file to create it
+ FILE *fd = fopen (buf, "w");
+ if (fd) fclose (fd);
+ }
+ return buf;
+}
+
+/*
+* We have a cache for writing different resource files,
+* which will only get flushed when we call wxFlushResources().
+* Build up a list of resource databases waiting to be written.
+*
+*/
+
+wxList wxResourceCache (wxKEY_STRING);
+
+void
+wxFlushResources (void)
+{
+ char nameBuffer[512];
+
+ wxNode *node = wxResourceCache.First ();
+ while (node)
+ {
+ const char *file = node->GetKeyString();
+ // If file doesn't exist, create it first.
+ (void)GetResourcePath(nameBuffer, file, true);
+
+ XrmDatabase database = (XrmDatabase) node->Data ();
+ XrmPutFileDatabase (database, nameBuffer);
+ XrmDestroyDatabase (database);
+ wxNode *next = node->Next ();
+ delete node;
+ node = next;
+ }
+}
+
+static XrmDatabase wxResourceDatabase = 0;
+
+void wxXMergeDatabases (wxApp * theApp, Display * display);
+
+bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file)
+{
+ char buffer[500];
+
+ (void) GetIniFile (buffer, file);
+
+ XrmDatabase database;
+ wxNode *node = wxResourceCache.Find (buffer);
+ if (node)
+ database = (XrmDatabase) node->Data ();
+ else
+ {
+ database = XrmGetFileDatabase (buffer);
+ wxResourceCache.Append (buffer, (wxObject *) database);
+ }
+
+ char resName[300];
+ strcpy (resName, section.c_str());
+ strcat (resName, ".");
+ strcat (resName, entry.c_str());
+
+ XrmPutStringResource (&database, resName, value);
+ return true;
+}
+
+bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file)
+{
+ char buf[50];
+ sprintf(buf, "%.4f", value);
+ return wxWriteResource(section, entry, buf, file);
+}
+
+bool wxWriteResource(const wxString& section, const wxString& entry, long value, const wxString& file)
+{
+ char buf[50];
+ sprintf(buf, "%ld", value);
+ return wxWriteResource(section, entry, buf, file);
+}
+
+bool wxWriteResource(const wxString& section, const wxString& entry, int value, const wxString& file)
+{
+ char buf[50];
+ sprintf(buf, "%d", value);
+ return wxWriteResource(section, entry, buf, file);
+}
+
+bool wxGetResource(const wxString& section, const wxString& entry, char **value, const wxString& file)
+{
+ if (!wxResourceDatabase)
+ {
+ Display *display = wxGlobalDisplay();
+ wxXMergeDatabases (wxTheApp, display);
+ }
+
+ XrmDatabase database;
+
+ if (!file.empty())
+ {
+ char buffer[500];
+
+ // Is this right? Trying to get it to look in the user's
+ // home directory instead of current directory -- JACS
+ (void) GetIniFile (buffer, file);
+
+ wxNode *node = wxResourceCache.Find (buffer);
+ if (node)
+ database = (XrmDatabase) node->Data ();
+ else
+ {
+ database = XrmGetFileDatabase (buffer);
+ wxResourceCache.Append (buffer, (wxObject *) database);
+ }
+ }
+ else
+ database = wxResourceDatabase;
+
+ XrmValue xvalue;
+ char *str_type[20];
+ char buf[150];
+ strcpy (buf, section);
+ strcat (buf, ".");
+ strcat (buf, entry);
+
+ Bool success = XrmGetResource (database, buf, "*", str_type,
+ &xvalue);
+ // Try different combinations of upper/lower case, just in case...
+ if (!success)
+ {
+ buf[0] = (isupper (buf[0]) ? tolower (buf[0]) : toupper (buf[0]));
+ success = XrmGetResource (database, buf, "*", str_type,
+ &xvalue);
+ }
+ if (success)
+ {
+ if (*value)
+ delete[] *value;
+
+ *value = new char[xvalue.size + 1];
+ strncpy (*value, xvalue.addr, (int) xvalue.size);
+ return true;
+ }
+ return false;
+}
+
+bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file)
+{
+ char *s = NULL;
+ bool succ = wxGetResource(section, entry, (char **)&s, file);
+ if (succ)
+ {
+ *value = (float)strtod(s, NULL);
+ delete[] s;
+ return true;
+ }
+ else return false;
+}
+
+bool wxGetResource(const wxString& section, const wxString& entry, long *value, const wxString& file)
+{
+ char *s = NULL;
+ bool succ = wxGetResource(section, entry, (char **)&s, file);
+ if (succ)
+ {
+ *value = strtol(s, NULL, 10);
+ delete[] s;
+ return true;
+ }
+ else return false;
+}
+
+bool wxGetResource(const wxString& section, const wxString& entry, int *value, const wxString& file)
+{
+ char *s = NULL;
+ bool succ = wxGetResource(section, entry, (char **)&s, file);
+ if (succ)
+ {
+ // Handle True, False here
+ // True, Yes, Enables, Set or Activated
+ if (*s == 'T' || *s == 'Y' || *s == 'E' || *s == 'S' || *s == 'A')
+ *value = true;
+ // False, No, Disabled, Reset, Cleared, Deactivated
+ else if (*s == 'F' || *s == 'N' || *s == 'D' || *s == 'R' || *s == 'C')
+ *value = false;
+ // Handle as Integer
+ else
+ *value = (int) strtol (s, NULL, 10);
+ delete[] s;
+ return true;
+ }
+ else
+ return false;
+}
+
+void wxXMergeDatabases (wxApp * theApp, Display * display)
+{
+ XrmDatabase homeDB, serverDB, applicationDB;
+ char filenamebuf[1024];
+
+ char *filename = &filenamebuf[0];
+ char *environment;
+ wxString classname = theApp->GetClassName();
+ char name[256];
+ (void) strcpy (name, "/usr/lib/X11/app-defaults/");
+ (void) strcat (name, classname.c_str());
+
+ /* Get application defaults file, if any */
+ applicationDB = XrmGetFileDatabase (name);
+ (void) XrmMergeDatabases (applicationDB, &wxResourceDatabase);
+
+ /* Merge server defaults, created by xrdb, loaded as a property of the root
+ * window when the server initializes and loaded into the display
+ * structure on XOpenDisplay;
+ * if not defined, use .Xdefaults
+ */
+
+ if (XResourceManagerString (display) != NULL)
+ {
+ serverDB = XrmGetStringDatabase (XResourceManagerString (display));
+ }
+ else
+ {
+ (void) GetIniFile (filename, NULL);
+ serverDB = XrmGetFileDatabase (filename);
+ }
+ XrmMergeDatabases (serverDB, &wxResourceDatabase);
+
+ /* Open XENVIRONMENT file, or if not defined, the .Xdefaults,
+ * and merge into existing database
+ */
+
+ if ((environment = getenv ("XENVIRONMENT")) == NULL)
+ {
+ size_t len;
+ environment = GetIniFile (filename, NULL);
+ len = strlen (environment);
+ wxString hostname = wxGetHostName();
+ if ( !hostname.empty() )
+ strncat(environment, hostname, 1024 - len);
+ }
+ homeDB = XrmGetFileDatabase (environment);
+ XrmMergeDatabases (homeDB, &wxResourceDatabase);
+}
+
+#if 0
+
+/*
+* Not yet used but may be useful.
+*
+*/
+void
+wxSetDefaultResources (const Widget w, const char **resourceSpec, const char *name)
+{
+ int i;
+ Display *dpy = XtDisplay (w); // Retrieve the display pointer
+
+ XrmDatabase rdb = NULL; // A resource data base
+
+ // Create an empty resource database
+ rdb = XrmGetStringDatabase ("");
+
+ // Add the Component resources, prepending the name of the component
+
+ i = 0;
+ while (resourceSpec[i] != NULL)
+ {
+ char buf[1000];
+
+ sprintf (buf, "*%s%s", name, resourceSpec[i++]);
+ XrmPutLineResource (&rdb, buf);
+ }
+
+ // Merge them into the Xt database, with lowest precendence
+
+ if (rdb)
+ {
+#if (XlibSpecificationRelease>=5)
+ XrmDatabase db = XtDatabase (dpy);
+ XrmCombineDatabase (rdb, &db, False);