]> git.saurik.com Git - wxWidgets.git/blame - src/motif/utils.cpp
Doc mods, sash window bug
[wxWidgets.git] / src / motif / utils.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: utils.cpp
3// Purpose: Various utilities
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13// Note: this is done in utilscmn.cpp now.
14// #pragma implementation
15// #pragma implementation "utils.h"
16#endif
17
18#include "wx/setup.h"
19#include "wx/utils.h"
20#include "wx/app.h"
a4294b78
JS
21#include "wx/msgdlg.h"
22#include "wx/cursor.h"
4bb6408c
JS
23
24#include <ctype.h>
4bb6408c 25#include <stdarg.h>
a4294b78
JS
26#include <dirent.h>
27#include <string.h>
28#include <sys/stat.h>
29#include <sys/types.h>
30#include <unistd.h>
31#include <sys/wait.h>
32#include <pwd.h>
33#include <errno.h>
34#include <netdb.h>
35#include <signal.h>
36
5dcf05ae 37#if defined(__SVR4__) && !defined(__HPUX__)
a4294b78
JS
38#include <sys/systeminfo.h>
39#endif
4bb6408c 40
5dcf05ae
JS
41#if (defined(__SUNCC__) || defined(__CLCC__))
42#include <sysent.h>
43#endif
44
4bb6408c
JS
45#include <Xm/Xm.h>
46
50414e24
JS
47#include "wx/motif/private.h"
48
a4294b78
JS
49// Yuck this is really BOTH site and platform dependent
50// so we should use some other strategy!
51#ifdef sun
52# define DEFAULT_XRESOURCE_DIR "/usr/openwin/lib/app-defaults"
53#else
54# define DEFAULT_XRESOURCE_DIR "/usr/lib/X11/app-defaults"
55#endif
56
57static char *GetIniFile (char *dest, const char *filename);
58
59extern wxList wxTopLevelWindows;
60
4bb6408c
JS
61// Get full hostname (eg. DoDo.BSn-Germany.crg.de)
62bool wxGetHostName(char *buf, int maxSize)
63{
5dcf05ae 64#if defined(__SVR4__) && !defined(__HPUX__)
2d120f83 65 return (sysinfo (SI_HOSTNAME, buf, maxSize) != -1);
a4294b78 66#else /* BSD Sockets */
2d120f83
JS
67 char name[255];
68 struct hostent *h;
69
70 // Get hostname
71 if (gethostname (name, sizeof (name) / sizeof (char) - 1) == -1)
72 return FALSE;
73 // Get official full name of host
74 strncpy (buf
75 ,(h = gethostbyname (name)) != NULL ? h->h_name : name
76 ,maxSize - 1);
77 return TRUE;
a4294b78 78#endif
4bb6408c
JS
79}
80
81// Get user ID e.g. jacs
82bool wxGetUserId(char *buf, int maxSize)
83{
a4294b78 84#ifdef VMS
2d120f83
JS
85 *buf = '\0'; // return empty string
86 return FALSE;
a4294b78 87#else
2d120f83
JS
88 struct passwd *who;
89
90 if ((who = getpwuid (getuid ())) != NULL)
a4294b78 91 {
2d120f83
JS
92 strncpy (buf, who->pw_name, maxSize - 1);
93 return TRUE;
a4294b78 94 }
2d120f83 95 return FALSE;
a4294b78 96#endif
4bb6408c
JS
97}
98
99// Get user name e.g. Julian Smart
100bool wxGetUserName(char *buf, int maxSize)
101{
a4294b78 102#ifdef VMS
2d120f83
JS
103 *buf = '\0'; // return empty string
104 return FALSE;
a4294b78 105#else
2d120f83
JS
106 struct passwd *who;
107
108 if ((who = getpwuid (getuid ())) != NULL)
a4294b78 109 {
2d120f83
JS
110 strncpy (buf, who->pw_gecos, maxSize - 1);
111 return TRUE;
a4294b78 112 }
2d120f83 113 return FALSE;
a4294b78 114#endif
4bb6408c
JS
115}
116
117int wxKill(long pid, int sig)
118{
2d120f83
JS
119 int unixSignal = 0;
120 switch (sig)
121 {
a4294b78
JS
122 case wxSIGTERM:
123 default:
2d120f83
JS
124 unixSignal = SIGTERM;
125 }
126 return kill( (int)pid, unixSignal);
4bb6408c
JS
127}
128
129//
130// Execute a program in an Interactive Shell
131//
132bool wxShell(const wxString& command)
133{
a4294b78 134#ifdef VMS
2d120f83 135 return(FALSE);
a4294b78
JS
136#else
137#if defined(sun) || defined(__ultrix) || defined(__bsdi__)
2d120f83 138 pid_t pid = vfork ();
a4294b78 139#else
2d120f83 140 pid_t pid = fork ();
a4294b78 141#endif
2d120f83 142 switch( pid ) {
a4294b78 143 case -1: /* error */
2d120f83 144 return(FALSE);
a4294b78 145 case 0: /* child */
2d120f83
JS
146 // Generic X windows terminal window
147 if (command != "")
148 execlp("xterm", "-e", (char *) (const char*) command, NULL);
149 else
150 execlp("xterm", NULL);
151 _exit(127);
152 }
153 return TRUE;
a4294b78 154#endif
2d120f83 155 // End VMS
4bb6408c
JS
156}
157
158// Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
159long wxGetFreeMemory()
160{
a4294b78 161 return -1;
4bb6408c
JS
162}
163
164void wxSleep(int nSecs)
165{
2d120f83 166 sleep(nSecs);
4bb6408c
JS
167}
168
169// Consume all events until no more left
170void wxFlushEvents()
171{
2d120f83
JS
172 Display *display = (Display*) wxGetDisplay();
173
174 XSync (display, FALSE);
175 XEvent event;
176 // XtAppPending returns availability of events AND timers/inputs, which
177 // are processed via callbacks, so XtAppNextEvent will not return if
178 // there are no events. So added '& XtIMXEvent' - Sergey.
179 while (XtAppPending ((XtAppContext) wxTheApp->GetAppContext()) & XtIMXEvent)
a4294b78 180 {
2d120f83
JS
181 XFlush (XtDisplay ((Widget) wxTheApp->GetTopLevelWidget()));
182 // Jan Lessner: works better when events are non-X events
183 XtAppProcessEvent((XtAppContext) wxTheApp->GetAppContext(), XtIMXEvent);
a4294b78 184 }
4bb6408c
JS
185}
186
187// Output a debug message, in a system dependent fashion.
188void wxDebugMsg(const char *fmt ...)
189{
2d120f83
JS
190 va_list ap;
191 char buffer[BUFSIZ];
192
193 if (!wxTheApp->GetWantDebugOutput())
194 return ;
195
196 va_start (ap, fmt);
197
198 vsprintf (buffer, fmt, ap);
199 cerr << buffer;
200
201 va_end (ap);
4bb6408c
JS
202}
203
204// Non-fatal error: pop up message box and (possibly) continue
205void wxError(const wxString& msg, const wxString& title)
206{
2d120f83 207 cerr << (const char*) title << ": " << (const char*) msg << "\n";
4bb6408c
JS
208}
209
210// Fatal error: pop up message box and abort
211void wxFatalError(const wxString& msg, const wxString& title)
212{
2d120f83
JS
213 cerr << (const char*) title << ": " << (const char*) msg << "\n";
214 exit (1);
4bb6408c
JS
215}
216
217// Emit a beeeeeep
218void wxBell()
219{
2d120f83
JS
220 // Use current setting for the bell
221 XBell ((Display*) wxGetDisplay(), 0);
4bb6408c
JS
222}
223
224int wxGetOsVersion(int *majorVsn, int *minorVsn)
225{
226 // TODO
2d120f83
JS
227 // This code is WRONG!! Does NOT return the
228 // Motif version of the libs but the X protocol
229 // version! @@@@@ Fix ME!!!!!!!!!
230 Display *display = XtDisplay ((Widget) wxTheApp->GetTopLevelWidget());
231 if (majorVsn)
232 *majorVsn = ProtocolVersion (display);
233 if (minorVsn)
234 *minorVsn = ProtocolRevision (display);
235 return wxMOTIF_X;
4bb6408c
JS
236}
237
238// Reading and writing resources (eg WIN.INI, .Xdefaults)
47d67540 239#if wxUSE_RESOURCES
a4294b78
JS
240
241static char *GetResourcePath(char *buf, const char *name, bool create = FALSE)
242{
2d120f83
JS
243 if (create && wxFileExists (name) ) {
244 strcpy(buf, name);
245 return buf; // Exists so ...
246 }
247
248 if (*name == '/')
249 strcpy(buf, name);
250 else {
251 // Put in standard place for resource files if not absolute
252 strcpy (buf, DEFAULT_XRESOURCE_DIR);
253 strcat (buf, "/");
254 strcat (buf, (const char*) wxFileNameFromPath (name));
255 }
256
257 if (create) {
258 // Touch the file to create it
259 FILE *fd = fopen (buf, "w");
260 if (fd) fclose (fd);
261 }
262 return buf;
a4294b78
JS
263}
264
265/*
2d120f83
JS
266* We have a cache for writing different resource files,
267* which will only get flushed when we call wxFlushResources().
268* Build up a list of resource databases waiting to be written.
269*
270*/
a4294b78
JS
271
272wxList wxResourceCache (wxKEY_STRING);
273
274void
275wxFlushResources (void)
276{
2d120f83
JS
277 char nameBuffer[512];
278
279 wxNode *node = wxResourceCache.First ();
280 while (node)
a4294b78 281 {
2d120f83
JS
282 const char *file = node->GetKeyString();
283 // If file doesn't exist, create it first.
284 (void)GetResourcePath(nameBuffer, file, TRUE);
285
286 XrmDatabase database = (XrmDatabase) node->Data ();
287 XrmPutFileDatabase (database, nameBuffer);
288 XrmDestroyDatabase (database);
289 wxNode *next = node->Next ();
290 delete node;
291 node = next;
a4294b78
JS
292 }
293}
294
295static XrmDatabase wxResourceDatabase = 0;
296
297void wxXMergeDatabases (wxApp * theApp, Display * display);
298
4bb6408c
JS
299bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file)
300{
2d120f83
JS
301 char buffer[500];
302
303 (void) GetIniFile (buffer, file);
304
305 XrmDatabase database;
306 wxNode *node = wxResourceCache.Find (buffer);
307 if (node)
308 database = (XrmDatabase) node->Data ();
309 else
a4294b78 310 {
2d120f83
JS
311 database = XrmGetFileDatabase (buffer);
312 wxResourceCache.Append (buffer, (wxObject *) database);
a4294b78 313 }
2d120f83
JS
314
315 char resName[300];
316 strcpy (resName, (const char*) section);
317 strcat (resName, ".");
318 strcat (resName, (const char*) entry);
319
320 XrmPutStringResource (&database, resName, value);
321 return TRUE;
4bb6408c
JS
322}
323
324bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file)
325{
2d120f83
JS
326 char buf[50];
327 sprintf(buf, "%.4f", value);
328 return wxWriteResource(section, entry, buf, file);
4bb6408c
JS
329}
330
331bool wxWriteResource(const wxString& section, const wxString& entry, long value, const wxString& file)
332{
2d120f83
JS
333 char buf[50];
334 sprintf(buf, "%ld", value);
335 return wxWriteResource(section, entry, buf, file);
4bb6408c
JS
336}
337
338bool wxWriteResource(const wxString& section, const wxString& entry, int value, const wxString& file)
339{
2d120f83
JS
340 char buf[50];
341 sprintf(buf, "%d", value);
342 return wxWriteResource(section, entry, buf, file);
4bb6408c
JS
343}
344
345bool wxGetResource(const wxString& section, const wxString& entry, char **value, const wxString& file)
346{
2d120f83 347 if (!wxResourceDatabase)
a4294b78 348 {
2d120f83
JS
349 Display *display = (Display*) wxGetDisplay();
350 wxXMergeDatabases (wxTheApp, display);
a4294b78 351 }
2d120f83
JS
352
353 XrmDatabase database;
354
355 if (file != "")
a4294b78 356 {
2d120f83
JS
357 char buffer[500];
358
359 // Is this right? Trying to get it to look in the user's
360 // home directory instead of current directory -- JACS
361 (void) GetIniFile (buffer, file);
362
363 wxNode *node = wxResourceCache.Find (buffer);
364 if (node)
365 database = (XrmDatabase) node->Data ();
366 else
367 {
368 database = XrmGetFileDatabase (buffer);
369 wxResourceCache.Append (buffer, (wxObject *) database);
370 }
a4294b78 371 }
2d120f83
JS
372 else
373 database = wxResourceDatabase;
374
375 XrmValue xvalue;
376 char *str_type[20];
377 char buf[150];
378 strcpy (buf, section);
379 strcat (buf, ".");
380 strcat (buf, entry);
381
382 Bool success = XrmGetResource (database, buf, "*", str_type,
383 &xvalue);
384 // Try different combinations of upper/lower case, just in case...
385 if (!success)
a4294b78 386 {
2d120f83
JS
387 buf[0] = (isupper (buf[0]) ? tolower (buf[0]) : toupper (buf[0]));
388 success = XrmGetResource (database, buf, "*", str_type,
389 &xvalue);
390 }
391 if (success)
392 {
393 if (*value)
394 delete[] *value;
395
396 *value = new char[xvalue.size + 1];
397 strncpy (*value, xvalue.addr, (int) xvalue.size);
398 return TRUE;
a4294b78 399 }
2d120f83 400 return FALSE;
4bb6408c
JS
401}
402
403bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file)
404{
2d120f83
JS
405 char *s = NULL;
406 bool succ = wxGetResource(section, entry, (char **)&s, file);
407 if (succ)
408 {
409 *value = (float)strtod(s, NULL);
410 delete[] s;
411 return TRUE;
412 }
413 else return FALSE;
4bb6408c
JS
414}
415
416bool wxGetResource(const wxString& section, const wxString& entry, long *value, const wxString& file)
417{
2d120f83
JS
418 char *s = NULL;
419 bool succ = wxGetResource(section, entry, (char **)&s, file);
420 if (succ)
421 {
422 *value = strtol(s, NULL, 10);
423 delete[] s;
424 return TRUE;
425 }
426 else return FALSE;
4bb6408c
JS
427}
428
429bool wxGetResource(const wxString& section, const wxString& entry, int *value, const wxString& file)
430{
2d120f83
JS
431 char *s = NULL;
432 bool succ = wxGetResource(section, entry, (char **)&s, file);
433 if (succ)
434 {
435 // Handle True, False here
436 // True, Yes, Enables, Set or Activated
437 if (*s == 'T' || *s == 'Y' || *s == 'E' || *s == 'S' || *s == 'A')
438 *value = TRUE;
439 // False, No, Disabled, Reset, Cleared, Deactivated
440 else if (*s == 'F' || *s == 'N' || *s == 'D' || *s == 'R' || *s == 'C')
441 *value = FALSE;
442 // Handle as Integer
443 else
444 *value = (int) strtol (s, NULL, 10);
a4294b78
JS
445 delete[] s;
446 return TRUE;
2d120f83
JS
447 }
448 else
449 return FALSE;
a4294b78
JS
450}
451
452void wxXMergeDatabases (wxApp * theApp, Display * display)
453{
2d120f83
JS
454 XrmDatabase homeDB, serverDB, applicationDB;
455 char filenamebuf[1024];
456
457 char *filename = &filenamebuf[0];
458 char *environment;
459 wxString classname = theApp->GetClassName();
460 char name[256];
461 (void) strcpy (name, "/usr/lib/X11/app-defaults/");
462 (void) strcat (name, (const char*) classname);
463
464 /* Get application defaults file, if any */
465 applicationDB = XrmGetFileDatabase (name);
466 (void) XrmMergeDatabases (applicationDB, &wxResourceDatabase);
467
468 /* Merge server defaults, created by xrdb, loaded as a property of the root
469 * window when the server initializes and loaded into the display
470 * structure on XOpenDisplay;
471 * if not defined, use .Xdefaults
472 */
473
474 if (XResourceManagerString (display) != NULL)
a4294b78 475 {
2d120f83 476 serverDB = XrmGetStringDatabase (XResourceManagerString (display));
a4294b78 477 }
2d120f83 478 else
a4294b78 479 {
2d120f83
JS
480 (void) GetIniFile (filename, NULL);
481 serverDB = XrmGetFileDatabase (filename);
a4294b78 482 }
2d120f83
JS
483 XrmMergeDatabases (serverDB, &wxResourceDatabase);
484
485 /* Open XENVIRONMENT file, or if not defined, the .Xdefaults,
486 * and merge into existing database
487 */
488
489 if ((environment = getenv ("XENVIRONMENT")) == NULL)
a4294b78 490 {
2d120f83
JS
491 size_t len;
492 environment = GetIniFile (filename, NULL);
493 len = strlen (environment);
5dcf05ae 494#if defined(__SVR4__) && !defined(__HPUX__)
2d120f83 495 (void) sysinfo (SI_HOSTNAME, environment + len, 1024 - len);
a4294b78 496#else
2d120f83 497 (void) gethostname (environment + len, 1024 - len);
a4294b78
JS
498#endif
499 }
2d120f83
JS
500 homeDB = XrmGetFileDatabase (environment);
501 XrmMergeDatabases (homeDB, &wxResourceDatabase);
a4294b78
JS
502}
503
504#if 0
505
506/*
2d120f83
JS
507* Not yet used but may be useful.
508*
509*/
a4294b78
JS
510void
511wxSetDefaultResources (const Widget w, const char **resourceSpec, const char *name)
512{
2d120f83
JS
513 int i;
514 Display *dpy = XtDisplay (w); // Retrieve the display pointer
515
516 XrmDatabase rdb = NULL; // A resource data base
517
518 // Create an empty resource database
519 rdb = XrmGetStringDatabase ("");
520
521 // Add the Component resources, prepending the name of the component
522
523 i = 0;
524 while (resourceSpec[i] != NULL)
a4294b78 525 {
2d120f83
JS
526 char buf[1000];
527
528 sprintf (buf, "*%s%s", name, resourceSpec[i++]);
529 XrmPutLineResource (&rdb, buf);
a4294b78 530 }
2d120f83
JS
531
532 // Merge them into the Xt database, with lowest precendence
533
534 if (rdb)
a4294b78
JS
535 {
536#if (XlibSpecificationRelease>=5)
2d120f83
JS
537 XrmDatabase db = XtDatabase (dpy);
538 XrmCombineDatabase (rdb, &db, FALSE);
a4294b78 539#else
2d120f83
JS
540 XrmMergeDatabases (dpy->db, &rdb);
541 dpy->db = rdb;
a4294b78
JS
542#endif
543 }
4bb6408c 544}
a4294b78 545#endif
2d120f83 546// 0
a4294b78 547
47d67540 548#endif // wxUSE_RESOURCES
4bb6408c
JS
549
550static int wxBusyCursorCount = 0;
551
a4294b78
JS
552// Helper function
553static void
554wxXSetBusyCursor (wxWindow * win, wxCursor * cursor)
555{
2d120f83
JS
556 Display *display = (Display*) win->GetXDisplay();
557
558 Window xwin = (Window) win->GetXWindow();
559 XSetWindowAttributes attrs;
560
561 if (cursor)
a4294b78 562 {
2d120f83 563 attrs.cursor = (Cursor) cursor->GetXCursor(display);
a4294b78 564 }
2d120f83 565 else
a4294b78 566 {
2d120f83
JS
567 // Restore old cursor
568 if (win->GetCursor()->Ok())
569 attrs.cursor = (Cursor) win->GetCursor()->GetXCursor(display);
570 else
571 attrs.cursor = None;
a4294b78 572 }
2d120f83
JS
573 if (xwin)
574 XChangeWindowAttributes (display, xwin, CWCursor, &attrs);
575
576 XFlush (display);
577
578 for(wxNode *node = win->GetChildren().First (); node; node = node->Next())
579 {
a4294b78 580 wxWindow *child = (wxWindow *) node->Data ();
2d120f83
JS
581 wxXSetBusyCursor (child, cursor);
582 }
a4294b78
JS
583}
584
4bb6408c
JS
585// Set the cursor to the busy cursor for all windows
586void wxBeginBusyCursor(wxCursor *cursor)
587{
2d120f83
JS
588 wxBusyCursorCount++;
589 if (wxBusyCursorCount == 1)
a4294b78 590 {
2d120f83
JS
591 for(wxNode *node = wxTopLevelWindows.First (); node; node = node->Next())
592 {
593 wxWindow *win = (wxWindow *) node->Data ();
594 wxXSetBusyCursor (win, cursor);
595 }
a4294b78 596 }
4bb6408c
JS
597}
598
599// Restore cursor to normal
600void wxEndBusyCursor()
601{
2d120f83
JS
602 if (wxBusyCursorCount == 0)
603 return;
604
605 wxBusyCursorCount--;
606 if (wxBusyCursorCount == 0)
607 {
608 for(wxNode *node = wxTopLevelWindows.First (); node; node = node->Next())
609 {
610 wxWindow *win = (wxWindow *) node->Data ();
611 wxXSetBusyCursor (win, NULL);
612 }
613 }
4bb6408c
JS
614}
615
616// TRUE if we're between the above two calls
617bool wxIsBusy()
618{
2d120f83 619 return (wxBusyCursorCount > 0);
4bb6408c
JS
620}
621
55acd85e
JS
622const char* wxGetHomeDir( wxString *home )
623{
2d120f83
JS
624 *home = wxGetUserHome( wxString() );
625 if (home->IsNull()) *home = "/";
626 return *home;
55acd85e
JS
627};
628
4bb6408c
JS
629char *wxGetUserHome (const wxString& user)
630{
a4294b78 631#ifdef VMS
2d120f83 632 return(NULL);
a4294b78 633#else
2d120f83
JS
634 struct passwd *who = NULL;
635
636 if (user == "") {
637 register char *ptr;
638
639 if ((ptr = getenv("HOME")) != NULL)
640 return ptr;
641 if ((ptr = getenv("USER")) != NULL ||
642 (ptr = getenv("LOGNAME")) != NULL)
643 {
644 who = getpwnam( ptr );
645 }
646 // We now make sure the the user exists!
647 if (who == NULL)
648 who = getpwuid( getuid() );
649 } else
650 who = getpwnam ((const char*) user);
651
652 return who ? who->pw_dir : (char*) NULL;
a4294b78 653#endif
2d120f83 654 // ifdef VMS
4bb6408c
JS
655}
656
657// Check whether this window wants to process messages, e.g. Stop button
658// in long calculations.
659bool wxCheckForInterrupt(wxWindow *wnd)
660{
2d120f83
JS
661 if(wnd){
662 Display *dpy=(Display*) wnd->GetXDisplay();
663 Window win=(Window) wnd->GetXWindow();
664 XEvent event;
665 XFlush(dpy);
666 if(wnd->GetMainWidget()){
667 XmUpdateDisplay((Widget)(wnd->GetMainWidget()));
668 }
669 while(XCheckMaskEvent(dpy,
670 ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|
671 PointerMotionMask|KeyPressMask|KeyReleaseMask,
672 &event)){
673 if(event.xany.window==win)
674 XtDispatchEvent(&event);
675 // else
676 // XBell(dpy,50);
677 }
678 return TRUE;//*** temporary?
679 }
680 else{
681 wxMessageBox("wnd==NULL !!!");
682 return FALSE;//*** temporary?
683 }
4bb6408c
JS
684}
685
686void wxGetMousePosition( int* x, int* y )
687{
a4294b78
JS
688 XMotionEvent xev;
689 Window root, child;
690 XQueryPointer((Display*) wxGetDisplay(),
2d120f83
JS
691 DefaultRootWindow((Display*) wxGetDisplay()), &root, &child,
692 &(xev.x_root), &(xev.y_root),
693 &(xev.x), &(xev.y),
694 &(xev.state));
a4294b78
JS
695 *x = xev.x_root;
696 *y = xev.y_root;
4bb6408c
JS
697};
698
699// Return TRUE if we have a colour display
700bool wxColourDisplay()
701{
dfc54541 702 Display *dpy = (Display*) wxGetDisplay();
2d120f83 703
dfc54541 704 if (DefaultDepth (dpy, DefaultScreen (dpy)) < 2)
2d120f83 705 return FALSE;
dfc54541 706 else
2d120f83 707 return TRUE;
4bb6408c
JS
708}
709
710// Returns depth of screen
711int wxDisplayDepth()
712{
dfc54541
JS
713 Display *dpy = (Display*) wxGetDisplay();
714 return DefaultDepth (dpy, DefaultScreen (dpy));
4bb6408c
JS
715}
716
717// Get size of display
718void wxDisplaySize(int *width, int *height)
719{
2d120f83
JS
720 Display *dpy = (Display*) wxGetDisplay();
721
722 *width = DisplayWidth (dpy, DefaultScreen (dpy));
723 *height = DisplayHeight (dpy, DefaultScreen (dpy));
4bb6408c
JS
724}
725
726/* Configurable display in Motif */
727static WXDisplay *gs_currentDisplay = NULL;
728static wxString gs_displayName;
729
730WXDisplay *wxGetDisplay()
731{
2d120f83
JS
732 if (gs_currentDisplay)
733 return gs_currentDisplay;
734
735 if (wxTheApp && wxTheApp->GetTopLevelWidget())
736 return XtDisplay ((Widget) wxTheApp->GetTopLevelWidget());
737 else if (wxTheApp)
738 return wxTheApp->GetInitialDisplay();
739 else
740 return (WXDisplay*) NULL;
4bb6408c
JS
741}
742
743bool wxSetDisplay(const wxString& display_name)
744{
2d120f83
JS
745 gs_displayName = display_name;
746
747 if (display_name.IsNull() || display_name.IsEmpty())
748 {
749 gs_currentDisplay = NULL;
750 return TRUE;
751 }
752 else
753 {
754 Cardinal argc = 0;
755
756 Display *display = XtOpenDisplay((XtAppContext) wxTheApp->GetAppContext(),
757 (const char*) display_name,
758 (const char*) wxTheApp->GetAppName(),
759 (const char*) wxTheApp->GetClassName(),
760 NULL,
4bb6408c 761# if XtSpecificationRelease < 5
2d120f83 762 0, &argc, NULL);
4bb6408c 763# else
2d120f83 764 0, (int *)&argc, NULL);
4bb6408c 765# endif
2d120f83
JS
766
767 if (display)
768 {
769 gs_currentDisplay = (WXDisplay*) display;
770 return TRUE;
771 } else
772 return FALSE;
773 }
774 return FALSE;
4bb6408c
JS
775}
776
777wxString wxGetDisplayName()
778{
2d120f83 779 return gs_displayName;
4bb6408c 780}
50414e24
JS
781
782// Find the letter corresponding to the mnemonic, for Motif
783char wxFindMnemonic (const char *s)
784{
2d120f83
JS
785 char mnem = 0;
786 int len = strlen (s);
787 int i;
788 for (i = 0; i < len; i++)
50414e24 789 {
2d120f83
JS
790 if (s[i] == '&')
791 {
792 // Carefully handle &&
793 if ((i + 1) <= len && s[i + 1] == '&')
794 i++;
795 else
796 {
797 mnem = s[i + 1];
798 break;
799 }
800 }
50414e24 801 }
2d120f83 802 return mnem;
50414e24
JS
803}
804
805char * wxFindAccelerator (char *s)
806{
2d120f83
JS
807 // The accelerator text is after the \t char.
808 while (*s && *s != '\t')
809 s++;
810 if (*s == '\0')
811 return (NULL);
50414e24 812 s++;
2d120f83
JS
813 /*
814 Now we need to format it as X standard:
815
816 input output
817
818 F7 --> <Key>F7
819 Ctrl+N --> Ctrl<Key>N
820 Alt+k --> Meta<Key>k
821 Ctrl+Shift+A --> Ctrl Shift<Key>A
822
823 */
824
825 wxBuffer[0] = '\0';
826 char *tmp = copystring (s);
827 s = tmp;
828 char *p = s;
829
830 while (1)
50414e24 831 {
2d120f83
JS
832 while (*p && *p != '+')
833 p++;
834 if (*p)
835 {
836 *p = '\0';
837 if (wxBuffer[0])
838 strcat (wxBuffer, " ");
839 if (strcmp (s, "Alt"))
840 strcat (wxBuffer, s);
841 else
842 strcat (wxBuffer, "Meta");
843 s = p + 1;
844 p = s;
845 }
846 else
847 {
848 strcat (wxBuffer, "<Key>");
849 strcat (wxBuffer, s);
850 break;
851 }
50414e24 852 }
2d120f83
JS
853 delete[]tmp;
854 return wxBuffer;
50414e24
JS
855}
856
857XmString wxFindAcceleratorText (char *s)
858{
2d120f83
JS
859 // The accelerator text is after the \t char.
860 while (*s && *s != '\t')
861 s++;
862 if (*s == '\0')
863 return (NULL);
50414e24 864 s++;
2d120f83
JS
865 XmString text = XmStringCreateSimple (s);
866 return text;
50414e24
JS
867}
868
869#include <X11/keysym.h>
870
871int wxCharCodeXToWX(KeySym keySym)
872{
2d120f83
JS
873 int id;
874 switch (keySym) {
50414e24
JS
875 case XK_Shift_L:
876 case XK_Shift_R:
2d120f83 877 id = WXK_SHIFT; break;
50414e24
JS
878 case XK_Control_L:
879 case XK_Control_R:
2d120f83 880 id = WXK_CONTROL; break;
50414e24 881 case XK_BackSpace:
2d120f83 882 id = WXK_BACK; break;
50414e24 883 case XK_Delete:
2d120f83 884 id = WXK_DELETE; break;
50414e24 885 case XK_Clear:
2d120f83 886 id = WXK_CLEAR; break;
50414e24 887 case XK_Tab:
2d120f83 888 id = WXK_TAB; break;
50414e24 889 case XK_numbersign:
2d120f83 890 id = '#'; break;
50414e24 891 case XK_Return:
2d120f83 892 id = WXK_RETURN; break;
50414e24 893 case XK_Escape:
2d120f83 894 id = WXK_ESCAPE; break;
50414e24
JS
895 case XK_Pause:
896 case XK_Break:
2d120f83 897 id = WXK_PAUSE; break;
50414e24 898 case XK_Num_Lock:
2d120f83 899 id = WXK_NUMLOCK; break;
50414e24 900 case XK_Scroll_Lock:
2d120f83
JS
901 id = WXK_SCROLL; break;
902
50414e24 903 case XK_Home:
2d120f83 904 id = WXK_HOME; break;
50414e24 905 case XK_End:
2d120f83 906 id = WXK_END; break;
50414e24 907 case XK_Left:
2d120f83 908 id = WXK_LEFT; break;
50414e24 909 case XK_Right:
2d120f83 910 id = WXK_RIGHT; break;
50414e24 911 case XK_Up:
2d120f83 912 id = WXK_UP; break;
50414e24 913 case XK_Down:
2d120f83 914 id = WXK_DOWN; break;
50414e24 915 case XK_Next:
2d120f83 916 id = WXK_NEXT; break;
50414e24 917 case XK_Prior:
2d120f83 918 id = WXK_PRIOR; break;
50414e24 919 case XK_Menu:
2d120f83 920 id = WXK_MENU; break;
50414e24 921 case XK_Select:
2d120f83 922 id = WXK_SELECT; break;
50414e24 923 case XK_Cancel:
2d120f83 924 id = WXK_CANCEL; break;
50414e24 925 case XK_Print:
2d120f83 926 id = WXK_PRINT; break;
50414e24 927 case XK_Execute:
2d120f83 928 id = WXK_EXECUTE; break;
50414e24 929 case XK_Insert:
2d120f83 930 id = WXK_INSERT; break;
50414e24 931 case XK_Help:
2d120f83
JS
932 id = WXK_HELP; break;
933
50414e24 934 case XK_KP_Multiply:
2d120f83 935 id = WXK_MULTIPLY; break;
50414e24 936 case XK_KP_Add:
2d120f83 937 id = WXK_ADD; break;
50414e24 938 case XK_KP_Subtract:
2d120f83 939 id = WXK_SUBTRACT; break;
50414e24 940 case XK_KP_Divide:
2d120f83 941 id = WXK_DIVIDE; break;
50414e24 942 case XK_KP_Decimal:
2d120f83 943 id = WXK_DECIMAL; break;
50414e24 944 case XK_KP_Equal:
2d120f83 945 id = '='; break;
50414e24 946 case XK_KP_Space:
2d120f83 947 id = ' '; break;
50414e24 948 case XK_KP_Tab:
2d120f83 949 id = WXK_TAB; break;
50414e24 950 case XK_KP_Enter:
2d120f83 951 id = WXK_RETURN; break;
50414e24 952 case XK_KP_0:
2d120f83 953 id = WXK_NUMPAD0; break;
50414e24 954 case XK_KP_1:
2d120f83 955 id = WXK_NUMPAD1; break;
50414e24 956 case XK_KP_2:
2d120f83 957 id = WXK_NUMPAD2; break;
50414e24 958 case XK_KP_3:
2d120f83 959 id = WXK_NUMPAD3; break;
50414e24 960 case XK_KP_4:
2d120f83 961 id = WXK_NUMPAD4; break;
50414e24 962 case XK_KP_5:
2d120f83 963 id = WXK_NUMPAD5; break;
50414e24 964 case XK_KP_6:
2d120f83 965 id = WXK_NUMPAD6; break;
50414e24 966 case XK_KP_7:
2d120f83 967 id = WXK_NUMPAD7; break;
50414e24 968 case XK_KP_8:
2d120f83 969 id = WXK_NUMPAD8; break;
50414e24 970 case XK_KP_9:
2d120f83 971 id = WXK_NUMPAD9; break;
50414e24 972 case XK_F1:
2d120f83 973 id = WXK_F1; break;
50414e24 974 case XK_F2:
2d120f83 975 id = WXK_F2; break;
50414e24 976 case XK_F3:
2d120f83 977 id = WXK_F3; break;
50414e24 978 case XK_F4:
2d120f83 979 id = WXK_F4; break;
50414e24 980 case XK_F5:
2d120f83 981 id = WXK_F5; break;
50414e24 982 case XK_F6:
2d120f83 983 id = WXK_F6; break;
50414e24 984 case XK_F7:
2d120f83 985 id = WXK_F7; break;
50414e24 986 case XK_F8:
2d120f83 987 id = WXK_F8; break;
50414e24 988 case XK_F9:
2d120f83 989 id = WXK_F9; break;
50414e24 990 case XK_F10:
2d120f83 991 id = WXK_F10; break;
50414e24 992 case XK_F11:
2d120f83 993 id = WXK_F11; break;
50414e24 994 case XK_F12:
2d120f83 995 id = WXK_F12; break;
50414e24 996 case XK_F13:
2d120f83 997 id = WXK_F13; break;
50414e24 998 case XK_F14:
2d120f83 999 id = WXK_F14; break;
50414e24 1000 case XK_F15:
2d120f83 1001 id = WXK_F15; break;
50414e24 1002 case XK_F16:
2d120f83 1003 id = WXK_F16; break;
50414e24 1004 case XK_F17:
2d120f83 1005 id = WXK_F17; break;
50414e24 1006 case XK_F18:
2d120f83 1007 id = WXK_F18; break;
50414e24 1008 case XK_F19:
2d120f83 1009 id = WXK_F19; break;
50414e24 1010 case XK_F20:
2d120f83 1011 id = WXK_F20; break;
50414e24 1012 case XK_F21:
2d120f83 1013 id = WXK_F21; break;
50414e24 1014 case XK_F22:
2d120f83 1015 id = WXK_F22; break;
50414e24 1016 case XK_F23:
2d120f83 1017 id = WXK_F23; break;
50414e24 1018 case XK_F24:
2d120f83 1019 id = WXK_F24; break;
50414e24 1020 default:
2d120f83 1021 id = (keySym <= 255) ? (int)keySym : -1;
50414e24
JS
1022 } // switch
1023 return id;
1024}
1025
1026KeySym wxCharCodeWXToX(int id)
1027{
2d120f83
JS
1028 KeySym keySym;
1029
1030 switch (id) {
50414e24
JS
1031 case WXK_CANCEL: keySym = XK_Cancel; break;
1032 case WXK_BACK: keySym = XK_BackSpace; break;
1033 case WXK_TAB: keySym = XK_Tab; break;
1034 case WXK_CLEAR: keySym = XK_Clear; break;
1035 case WXK_RETURN: keySym = XK_Return; break;
1036 case WXK_SHIFT: keySym = XK_Shift_L; break;
1037 case WXK_CONTROL: keySym = XK_Control_L; break;
1038 case WXK_MENU : keySym = XK_Menu; break;
1039 case WXK_PAUSE: keySym = XK_Pause; break;
1040 case WXK_ESCAPE: keySym = XK_Escape; break;
1041 case WXK_SPACE: keySym = ' '; break;
1042 case WXK_PRIOR: keySym = XK_Prior; break;
1043 case WXK_NEXT : keySym = XK_Next; break;
1044 case WXK_END: keySym = XK_End; break;
1045 case WXK_HOME : keySym = XK_Home; break;
1046 case WXK_LEFT : keySym = XK_Left; break;
1047 case WXK_UP: keySym = XK_Up; break;
1048 case WXK_RIGHT: keySym = XK_Right; break;
1049 case WXK_DOWN : keySym = XK_Down; break;
1050 case WXK_SELECT: keySym = XK_Select; break;
1051 case WXK_PRINT: keySym = XK_Print; break;
1052 case WXK_EXECUTE: keySym = XK_Execute; break;
1053 case WXK_INSERT: keySym = XK_Insert; break;
1054 case WXK_DELETE: keySym = XK_Delete; break;
1055 case WXK_HELP : keySym = XK_Help; break;
1056 case WXK_NUMPAD0: keySym = XK_KP_0; break;
1057 case WXK_NUMPAD1: keySym = XK_KP_1; break;
1058 case WXK_NUMPAD2: keySym = XK_KP_2; break;
1059 case WXK_NUMPAD3: keySym = XK_KP_3; break;
1060 case WXK_NUMPAD4: keySym = XK_KP_4; break;
1061 case WXK_NUMPAD5: keySym = XK_KP_5; break;
1062 case WXK_NUMPAD6: keySym = XK_KP_6; break;
1063 case WXK_NUMPAD7: keySym = XK_KP_7; break;
1064 case WXK_NUMPAD8: keySym = XK_KP_8; break;
1065 case WXK_NUMPAD9: keySym = XK_KP_9; break;
1066 case WXK_MULTIPLY: keySym = XK_KP_Multiply; break;
1067 case WXK_ADD: keySym = XK_KP_Add; break;
1068 case WXK_SUBTRACT: keySym = XK_KP_Subtract; break;
1069 case WXK_DECIMAL: keySym = XK_KP_Decimal; break;
1070 case WXK_DIVIDE: keySym = XK_KP_Divide; break;
1071 case WXK_F1: keySym = XK_F1; break;
1072 case WXK_F2: keySym = XK_F2; break;
1073 case WXK_F3: keySym = XK_F3; break;
1074 case WXK_F4: keySym = XK_F4; break;
1075 case WXK_F5: keySym = XK_F5; break;
1076 case WXK_F6: keySym = XK_F6; break;
1077 case WXK_F7: keySym = XK_F7; break;
1078 case WXK_F8: keySym = XK_F8; break;
1079 case WXK_F9: keySym = XK_F9; break;
1080 case WXK_F10: keySym = XK_F10; break;
1081 case WXK_F11: keySym = XK_F11; break;
1082 case WXK_F12: keySym = XK_F12; break;
1083 case WXK_F13: keySym = XK_F13; break;
1084 case WXK_F14: keySym = XK_F14; break;
1085 case WXK_F15: keySym = XK_F15; break;
1086 case WXK_F16: keySym = XK_F16; break;
1087 case WXK_F17: keySym = XK_F17; break;
1088 case WXK_F18: keySym = XK_F18; break;
1089 case WXK_F19: keySym = XK_F19; break;
1090 case WXK_F20: keySym = XK_F20; break;
1091 case WXK_F21: keySym = XK_F21; break;
1092 case WXK_F22: keySym = XK_F22; break;
1093 case WXK_F23: keySym = XK_F23; break;
1094 case WXK_F24: keySym = XK_F24; break;
1095 case WXK_NUMLOCK: keySym = XK_Num_Lock; break;
1096 case WXK_SCROLL: keySym = XK_Scroll_Lock; break;
1097 default: keySym = id <= 255 ? (KeySym)id : 0;
2d120f83
JS
1098 } // switch
1099 return keySym;
50414e24 1100}
a4294b78
JS
1101
1102// Read $HOME for what it says is home, if not
1103// read $USER or $LOGNAME for user name else determine
1104// the Real User, then determine the Real home dir.
1105static char * GetIniFile (char *dest, const char *filename)
1106{
2d120f83
JS
1107 char *home = NULL;
1108 if (filename && wxIsAbsolutePath(filename))
1109 {
1110 strcpy(dest, filename);
1111 }
1112 else if ((home = wxGetUserHome("")) != NULL)
1113 {
1114 strcpy(dest, home);
1115 if (dest[strlen(dest) - 1] != '/')
1116 strcat (dest, "/");
1117 if (filename == NULL)
1118 {
1119 if ((filename = getenv ("XENVIRONMENT")) == NULL)
1120 filename = ".Xdefaults";
1121 }
1122 else if (*filename != '.')
1123 strcat (dest, ".");
1124 strcat (dest, filename);
1125 } else
1126 {
1127 dest[0] = '\0';
1128 }
1129 return dest;
a4294b78
JS
1130}
1131
1132/*
2d120f83
JS
1133* Some colour manipulation routines
1134*/
1135
a4294b78 1136void wxHSVToXColor(wxHSV *hsv,XColor *rgb)
2d120f83
JS
1137{
1138 int h = hsv->h;
1139 int s = hsv->s;
1140 int v = hsv->v;
1141 int r, g, b;
1142 int i, f;
1143 int p, q, t;
1144 s = (s * wxMAX_RGB) / wxMAX_SV;
1145 v = (v * wxMAX_RGB) / wxMAX_SV;
1146 if (h == 360) h = 0;
1147 if (s == 0) { h = 0; r = g = b = v; }
1148 i = h / 60;
1149 f = h % 60;
1150 p = v * (wxMAX_RGB - s) / wxMAX_RGB;
1151 q = v * (wxMAX_RGB - s * f / 60) / wxMAX_RGB;
1152 t = v * (wxMAX_RGB - s * (60 - f) / 60) / wxMAX_RGB;
1153 switch (i)
1154 {
1155 case 0: r = v, g = t, b = p; break;
1156 case 1: r = q, g = v, b = p; break;
1157 case 2: r = p, g = v, b = t; break;
1158 case 3: r = p, g = q, b = v; break;
1159 case 4: r = t, g = p, b = v; break;
1160 case 5: r = v, g = p, b = q; break;
1161 }
1162 rgb->red = r << 8;
1163 rgb->green = g << 8;
1164 rgb->blue = b << 8;
1165}
a4294b78
JS
1166
1167void wxXColorToHSV(wxHSV *hsv,XColor *rgb)
2d120f83
JS
1168{
1169 int r = rgb->red >> 8;
1170 int g = rgb->green >> 8;
1171 int b = rgb->blue >> 8;
1172 int maxv = wxMax3(r, g, b);
1173 int minv = wxMin3(r, g, b);
1174 int h, s, v;
1175 v = maxv;
1176 if (maxv) s = (maxv - minv) * wxMAX_RGB / maxv;
1177 else s = 0;
1178 if (s == 0) h = 0;
1179 else
1180 {
1181 int rc, gc, bc, hex;
1182 rc = (maxv - r) * wxMAX_RGB / (maxv - minv);
1183 gc = (maxv - g) * wxMAX_RGB / (maxv - minv);
1184 bc = (maxv - b) * wxMAX_RGB / (maxv - minv);
1185 if (r == maxv) { h = bc - gc, hex = 0; }
1186 else if (g == maxv) { h = rc - bc, hex = 2; }
1187 else if (b == maxv) { h = gc - rc, hex = 4; }
1188 h = hex * 60 + (h * 60 / wxMAX_RGB);
1189 if (h < 0) h += 360;
1190 }
1191 hsv->h = h;
1192 hsv->s = (s * wxMAX_SV) / wxMAX_RGB;
1193 hsv->v = (v * wxMAX_SV) / wxMAX_RGB;
1194}
a4294b78
JS
1195
1196void wxAllocNearestColor(Display *d,Colormap cmp,XColor *xc)
2d120f83
JS
1197{
1198 int llp;
1199
1200 int screen = DefaultScreen(d);
1201 int num_colors = DisplayCells(d,screen);
1202
1203 XColor *color_defs = new XColor[num_colors];
1204 for(llp = 0;llp < num_colors;llp++) color_defs[llp].pixel = llp;
1205 XQueryColors(d,cmp,color_defs,num_colors);
1206
1207 wxHSV hsv_defs, hsv;
1208 wxXColorToHSV(&hsv,xc);
1209
1210 int diff, min_diff, pixel = 0;
1211
1212 for(llp = 0;llp < num_colors;llp++)
1213 {
1214 wxXColorToHSV(&hsv_defs,&color_defs[llp]);
1215 diff = wxSIGN(wxH_WEIGHT * (hsv.h - hsv_defs.h)) +
1216 wxSIGN(wxS_WEIGHT * (hsv.s - hsv_defs.s)) +
1217 wxSIGN(wxV_WEIGHT * (hsv.v - hsv_defs.v));
1218 if (llp == 0) min_diff = diff;
1219 if (min_diff > diff) { min_diff = diff; pixel = llp; }
1220 if (min_diff == 0) break;
1221 }
1222
1223 xc -> red = color_defs[pixel].red;
1224 xc -> green = color_defs[pixel].green;
1225 xc -> blue = color_defs[pixel].blue;
1226 xc -> flags = DoRed | DoGreen | DoBlue;
1227 if (!XAllocColor(d,cmp,xc))
a4294b78 1228 cout << "wxAllocNearestColor : Warning : Cannot find nearest color !\n";
2d120f83
JS
1229
1230 delete[] color_defs;
1231}
a4294b78
JS
1232
1233void wxAllocColor(Display *d,Colormap cmp,XColor *xc)
2d120f83
JS
1234{
1235 if (!XAllocColor(d,cmp,xc))
1236 {
1237 // cout << "wxAllocColor : Warning : Can not allocate color, attempt find nearest !\n";
1238 wxAllocNearestColor(d,cmp,xc);
1239 }
1240}
a4294b78
JS
1241
1242
94b49b93
JS
1243// These functions duplicate those in wxWindow, but are needed
1244// for use outside of wxWindow (e.g. wxMenu, wxMenuBar).
1245
1246// Change a widget's foreground and background colours.
1247
1248void wxDoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour)
1249{
2d120f83
JS
1250 // When should we specify the foreground, if it's calculated
1251 // by wxComputeColours?
1252 // Solution: say we start with the default (computed) foreground colour.
1253 // If we call SetForegroundColour explicitly for a control or window,
1254 // then the foreground is changed.
1255 // Therefore SetBackgroundColour computes the foreground colour, and
1256 // SetForegroundColour changes the foreground colour. The ordering is
1257 // important.
1258
1259 XtVaSetValues ((Widget) widget,
1260 XmNforeground, foregroundColour.AllocColour(XtDisplay((Widget) widget)),
1261 NULL);
94b49b93
JS
1262}
1263
1264void wxDoChangeBackgroundColour(WXWidget widget, wxColour& backgroundColour, bool changeArmColour)
1265{
2d120f83
JS
1266 wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
1267 (wxColour*) NULL);
1268
94b49b93 1269 XtVaSetValues ((Widget) widget,
2d120f83
JS
1270 XmNbackground, g_itemColors[wxBACK_INDEX].pixel,
1271 XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel,
1272 XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel,
1273 XmNforeground, g_itemColors[wxFORE_INDEX].pixel,
1274 NULL);
1275
1276 if (changeArmColour)
1277 XtVaSetValues ((Widget) widget,
1278 XmNarmColor, g_itemColors[wxSELE_INDEX].pixel,
1279 NULL);
94b49b93
JS
1280}
1281
1282