]> git.saurik.com Git - wxWidgets.git/blame - src/motif/utils.cpp
*** empty log message ***
[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
750b78ba 37#if defined(__SOLARIS__) || 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{
750b78ba 64#if defined(__SOLARIS__) || 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);
750b78ba 494#if defined(__SOLARIS__) || 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();
ad813b00
JS
559 if (!xwin)
560 return;
561
2d120f83
JS
562 XSetWindowAttributes attrs;
563
564 if (cursor)
a4294b78 565 {
2d120f83 566 attrs.cursor = (Cursor) cursor->GetXCursor(display);
a4294b78 567 }
2d120f83 568 else
a4294b78 569 {
2d120f83
JS
570 // Restore old cursor
571 if (win->GetCursor()->Ok())
572 attrs.cursor = (Cursor) win->GetCursor()->GetXCursor(display);
573 else
574 attrs.cursor = None;
a4294b78 575 }
2d120f83
JS
576 if (xwin)
577 XChangeWindowAttributes (display, xwin, CWCursor, &attrs);
578
579 XFlush (display);
580
581 for(wxNode *node = win->GetChildren().First (); node; node = node->Next())
582 {
a4294b78 583 wxWindow *child = (wxWindow *) node->Data ();
2d120f83
JS
584 wxXSetBusyCursor (child, cursor);
585 }
a4294b78
JS
586}
587
4bb6408c
JS
588// Set the cursor to the busy cursor for all windows
589void wxBeginBusyCursor(wxCursor *cursor)
590{
2d120f83
JS
591 wxBusyCursorCount++;
592 if (wxBusyCursorCount == 1)
a4294b78 593 {
2d120f83
JS
594 for(wxNode *node = wxTopLevelWindows.First (); node; node = node->Next())
595 {
596 wxWindow *win = (wxWindow *) node->Data ();
597 wxXSetBusyCursor (win, cursor);
598 }
a4294b78 599 }
4bb6408c
JS
600}
601
602// Restore cursor to normal
603void wxEndBusyCursor()
604{
2d120f83
JS
605 if (wxBusyCursorCount == 0)
606 return;
607
608 wxBusyCursorCount--;
609 if (wxBusyCursorCount == 0)
610 {
611 for(wxNode *node = wxTopLevelWindows.First (); node; node = node->Next())
612 {
613 wxWindow *win = (wxWindow *) node->Data ();
614 wxXSetBusyCursor (win, NULL);
615 }
616 }
4bb6408c
JS
617}
618
619// TRUE if we're between the above two calls
620bool wxIsBusy()
621{
2d120f83 622 return (wxBusyCursorCount > 0);
4bb6408c
JS
623}
624
55acd85e
JS
625const char* wxGetHomeDir( wxString *home )
626{
2d120f83
JS
627 *home = wxGetUserHome( wxString() );
628 if (home->IsNull()) *home = "/";
629 return *home;
55acd85e
JS
630};
631
4bb6408c
JS
632char *wxGetUserHome (const wxString& user)
633{
a4294b78 634#ifdef VMS
2d120f83 635 return(NULL);
a4294b78 636#else
2d120f83
JS
637 struct passwd *who = NULL;
638
639 if (user == "") {
640 register char *ptr;
641
642 if ((ptr = getenv("HOME")) != NULL)
643 return ptr;
644 if ((ptr = getenv("USER")) != NULL ||
645 (ptr = getenv("LOGNAME")) != NULL)
646 {
647 who = getpwnam( ptr );
648 }
649 // We now make sure the the user exists!
650 if (who == NULL)
651 who = getpwuid( getuid() );
652 } else
653 who = getpwnam ((const char*) user);
654
655 return who ? who->pw_dir : (char*) NULL;
a4294b78 656#endif
2d120f83 657 // ifdef VMS
4bb6408c
JS
658}
659
660// Check whether this window wants to process messages, e.g. Stop button
661// in long calculations.
662bool wxCheckForInterrupt(wxWindow *wnd)
663{
2d120f83
JS
664 if(wnd){
665 Display *dpy=(Display*) wnd->GetXDisplay();
666 Window win=(Window) wnd->GetXWindow();
667 XEvent event;
668 XFlush(dpy);
669 if(wnd->GetMainWidget()){
670 XmUpdateDisplay((Widget)(wnd->GetMainWidget()));
671 }
672 while(XCheckMaskEvent(dpy,
673 ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|
674 PointerMotionMask|KeyPressMask|KeyReleaseMask,
675 &event)){
676 if(event.xany.window==win)
677 XtDispatchEvent(&event);
678 // else
679 // XBell(dpy,50);
680 }
681 return TRUE;//*** temporary?
682 }
683 else{
684 wxMessageBox("wnd==NULL !!!");
685 return FALSE;//*** temporary?
686 }
4bb6408c
JS
687}
688
689void wxGetMousePosition( int* x, int* y )
690{
a4294b78
JS
691 XMotionEvent xev;
692 Window root, child;
693 XQueryPointer((Display*) wxGetDisplay(),
2d120f83
JS
694 DefaultRootWindow((Display*) wxGetDisplay()), &root, &child,
695 &(xev.x_root), &(xev.y_root),
696 &(xev.x), &(xev.y),
697 &(xev.state));
a4294b78
JS
698 *x = xev.x_root;
699 *y = xev.y_root;
4bb6408c
JS
700};
701
702// Return TRUE if we have a colour display
703bool wxColourDisplay()
704{
dfc54541 705 Display *dpy = (Display*) wxGetDisplay();
2d120f83 706
dfc54541 707 if (DefaultDepth (dpy, DefaultScreen (dpy)) < 2)
2d120f83 708 return FALSE;
dfc54541 709 else
2d120f83 710 return TRUE;
4bb6408c
JS
711}
712
713// Returns depth of screen
714int wxDisplayDepth()
715{
dfc54541
JS
716 Display *dpy = (Display*) wxGetDisplay();
717 return DefaultDepth (dpy, DefaultScreen (dpy));
4bb6408c
JS
718}
719
720// Get size of display
721void wxDisplaySize(int *width, int *height)
722{
2d120f83
JS
723 Display *dpy = (Display*) wxGetDisplay();
724
725 *width = DisplayWidth (dpy, DefaultScreen (dpy));
726 *height = DisplayHeight (dpy, DefaultScreen (dpy));
4bb6408c
JS
727}
728
729/* Configurable display in Motif */
730static WXDisplay *gs_currentDisplay = NULL;
731static wxString gs_displayName;
732
733WXDisplay *wxGetDisplay()
734{
2d120f83
JS
735 if (gs_currentDisplay)
736 return gs_currentDisplay;
737
738 if (wxTheApp && wxTheApp->GetTopLevelWidget())
739 return XtDisplay ((Widget) wxTheApp->GetTopLevelWidget());
740 else if (wxTheApp)
741 return wxTheApp->GetInitialDisplay();
742 else
743 return (WXDisplay*) NULL;
4bb6408c
JS
744}
745
746bool wxSetDisplay(const wxString& display_name)
747{
2d120f83
JS
748 gs_displayName = display_name;
749
750 if (display_name.IsNull() || display_name.IsEmpty())
751 {
752 gs_currentDisplay = NULL;
753 return TRUE;
754 }
755 else
756 {
757 Cardinal argc = 0;
758
759 Display *display = XtOpenDisplay((XtAppContext) wxTheApp->GetAppContext(),
760 (const char*) display_name,
761 (const char*) wxTheApp->GetAppName(),
762 (const char*) wxTheApp->GetClassName(),
763 NULL,
4bb6408c 764# if XtSpecificationRelease < 5
2d120f83 765 0, &argc, NULL);
4bb6408c 766# else
2d120f83 767 0, (int *)&argc, NULL);
4bb6408c 768# endif
2d120f83
JS
769
770 if (display)
771 {
772 gs_currentDisplay = (WXDisplay*) display;
773 return TRUE;
774 } else
775 return FALSE;
776 }
777 return FALSE;
4bb6408c
JS
778}
779
780wxString wxGetDisplayName()
781{
2d120f83 782 return gs_displayName;
4bb6408c 783}
50414e24
JS
784
785// Find the letter corresponding to the mnemonic, for Motif
786char wxFindMnemonic (const char *s)
787{
2d120f83
JS
788 char mnem = 0;
789 int len = strlen (s);
790 int i;
791 for (i = 0; i < len; i++)
50414e24 792 {
2d120f83
JS
793 if (s[i] == '&')
794 {
795 // Carefully handle &&
796 if ((i + 1) <= len && s[i + 1] == '&')
797 i++;
798 else
799 {
800 mnem = s[i + 1];
801 break;
802 }
803 }
50414e24 804 }
2d120f83 805 return mnem;
50414e24
JS
806}
807
808char * wxFindAccelerator (char *s)
809{
2d120f83
JS
810 // The accelerator text is after the \t char.
811 while (*s && *s != '\t')
812 s++;
813 if (*s == '\0')
814 return (NULL);
50414e24 815 s++;
2d120f83
JS
816 /*
817 Now we need to format it as X standard:
818
819 input output
820
821 F7 --> <Key>F7
822 Ctrl+N --> Ctrl<Key>N
823 Alt+k --> Meta<Key>k
824 Ctrl+Shift+A --> Ctrl Shift<Key>A
825
826 */
827
828 wxBuffer[0] = '\0';
829 char *tmp = copystring (s);
830 s = tmp;
831 char *p = s;
832
833 while (1)
50414e24 834 {
2d120f83
JS
835 while (*p && *p != '+')
836 p++;
837 if (*p)
838 {
839 *p = '\0';
840 if (wxBuffer[0])
841 strcat (wxBuffer, " ");
842 if (strcmp (s, "Alt"))
843 strcat (wxBuffer, s);
844 else
845 strcat (wxBuffer, "Meta");
846 s = p + 1;
847 p = s;
848 }
849 else
850 {
851 strcat (wxBuffer, "<Key>");
852 strcat (wxBuffer, s);
853 break;
854 }
50414e24 855 }
2d120f83
JS
856 delete[]tmp;
857 return wxBuffer;
50414e24
JS
858}
859
860XmString wxFindAcceleratorText (char *s)
861{
2d120f83
JS
862 // The accelerator text is after the \t char.
863 while (*s && *s != '\t')
864 s++;
865 if (*s == '\0')
866 return (NULL);
50414e24 867 s++;
2d120f83
JS
868 XmString text = XmStringCreateSimple (s);
869 return text;
50414e24
JS
870}
871
872#include <X11/keysym.h>
873
874int wxCharCodeXToWX(KeySym keySym)
875{
2d120f83
JS
876 int id;
877 switch (keySym) {
50414e24
JS
878 case XK_Shift_L:
879 case XK_Shift_R:
2d120f83 880 id = WXK_SHIFT; break;
50414e24
JS
881 case XK_Control_L:
882 case XK_Control_R:
2d120f83 883 id = WXK_CONTROL; break;
50414e24 884 case XK_BackSpace:
2d120f83 885 id = WXK_BACK; break;
50414e24 886 case XK_Delete:
2d120f83 887 id = WXK_DELETE; break;
50414e24 888 case XK_Clear:
2d120f83 889 id = WXK_CLEAR; break;
50414e24 890 case XK_Tab:
2d120f83 891 id = WXK_TAB; break;
50414e24 892 case XK_numbersign:
2d120f83 893 id = '#'; break;
50414e24 894 case XK_Return:
2d120f83 895 id = WXK_RETURN; break;
50414e24 896 case XK_Escape:
2d120f83 897 id = WXK_ESCAPE; break;
50414e24
JS
898 case XK_Pause:
899 case XK_Break:
2d120f83 900 id = WXK_PAUSE; break;
50414e24 901 case XK_Num_Lock:
2d120f83 902 id = WXK_NUMLOCK; break;
50414e24 903 case XK_Scroll_Lock:
2d120f83
JS
904 id = WXK_SCROLL; break;
905
50414e24 906 case XK_Home:
2d120f83 907 id = WXK_HOME; break;
50414e24 908 case XK_End:
2d120f83 909 id = WXK_END; break;
50414e24 910 case XK_Left:
2d120f83 911 id = WXK_LEFT; break;
50414e24 912 case XK_Right:
2d120f83 913 id = WXK_RIGHT; break;
50414e24 914 case XK_Up:
2d120f83 915 id = WXK_UP; break;
50414e24 916 case XK_Down:
2d120f83 917 id = WXK_DOWN; break;
50414e24 918 case XK_Next:
2d120f83 919 id = WXK_NEXT; break;
50414e24 920 case XK_Prior:
2d120f83 921 id = WXK_PRIOR; break;
50414e24 922 case XK_Menu:
2d120f83 923 id = WXK_MENU; break;
50414e24 924 case XK_Select:
2d120f83 925 id = WXK_SELECT; break;
50414e24 926 case XK_Cancel:
2d120f83 927 id = WXK_CANCEL; break;
50414e24 928 case XK_Print:
2d120f83 929 id = WXK_PRINT; break;
50414e24 930 case XK_Execute:
2d120f83 931 id = WXK_EXECUTE; break;
50414e24 932 case XK_Insert:
2d120f83 933 id = WXK_INSERT; break;
50414e24 934 case XK_Help:
2d120f83
JS
935 id = WXK_HELP; break;
936
50414e24 937 case XK_KP_Multiply:
2d120f83 938 id = WXK_MULTIPLY; break;
50414e24 939 case XK_KP_Add:
2d120f83 940 id = WXK_ADD; break;
50414e24 941 case XK_KP_Subtract:
2d120f83 942 id = WXK_SUBTRACT; break;
50414e24 943 case XK_KP_Divide:
2d120f83 944 id = WXK_DIVIDE; break;
50414e24 945 case XK_KP_Decimal:
2d120f83 946 id = WXK_DECIMAL; break;
50414e24 947 case XK_KP_Equal:
2d120f83 948 id = '='; break;
50414e24 949 case XK_KP_Space:
2d120f83 950 id = ' '; break;
50414e24 951 case XK_KP_Tab:
2d120f83 952 id = WXK_TAB; break;
50414e24 953 case XK_KP_Enter:
2d120f83 954 id = WXK_RETURN; break;
50414e24 955 case XK_KP_0:
2d120f83 956 id = WXK_NUMPAD0; break;
50414e24 957 case XK_KP_1:
2d120f83 958 id = WXK_NUMPAD1; break;
50414e24 959 case XK_KP_2:
2d120f83 960 id = WXK_NUMPAD2; break;
50414e24 961 case XK_KP_3:
2d120f83 962 id = WXK_NUMPAD3; break;
50414e24 963 case XK_KP_4:
2d120f83 964 id = WXK_NUMPAD4; break;
50414e24 965 case XK_KP_5:
2d120f83 966 id = WXK_NUMPAD5; break;
50414e24 967 case XK_KP_6:
2d120f83 968 id = WXK_NUMPAD6; break;
50414e24 969 case XK_KP_7:
2d120f83 970 id = WXK_NUMPAD7; break;
50414e24 971 case XK_KP_8:
2d120f83 972 id = WXK_NUMPAD8; break;
50414e24 973 case XK_KP_9:
2d120f83 974 id = WXK_NUMPAD9; break;
50414e24 975 case XK_F1:
2d120f83 976 id = WXK_F1; break;
50414e24 977 case XK_F2:
2d120f83 978 id = WXK_F2; break;
50414e24 979 case XK_F3:
2d120f83 980 id = WXK_F3; break;
50414e24 981 case XK_F4:
2d120f83 982 id = WXK_F4; break;
50414e24 983 case XK_F5:
2d120f83 984 id = WXK_F5; break;
50414e24 985 case XK_F6:
2d120f83 986 id = WXK_F6; break;
50414e24 987 case XK_F7:
2d120f83 988 id = WXK_F7; break;
50414e24 989 case XK_F8:
2d120f83 990 id = WXK_F8; break;
50414e24 991 case XK_F9:
2d120f83 992 id = WXK_F9; break;
50414e24 993 case XK_F10:
2d120f83 994 id = WXK_F10; break;
50414e24 995 case XK_F11:
2d120f83 996 id = WXK_F11; break;
50414e24 997 case XK_F12:
2d120f83 998 id = WXK_F12; break;
50414e24 999 case XK_F13:
2d120f83 1000 id = WXK_F13; break;
50414e24 1001 case XK_F14:
2d120f83 1002 id = WXK_F14; break;
50414e24 1003 case XK_F15:
2d120f83 1004 id = WXK_F15; break;
50414e24 1005 case XK_F16:
2d120f83 1006 id = WXK_F16; break;
50414e24 1007 case XK_F17:
2d120f83 1008 id = WXK_F17; break;
50414e24 1009 case XK_F18:
2d120f83 1010 id = WXK_F18; break;
50414e24 1011 case XK_F19:
2d120f83 1012 id = WXK_F19; break;
50414e24 1013 case XK_F20:
2d120f83 1014 id = WXK_F20; break;
50414e24 1015 case XK_F21:
2d120f83 1016 id = WXK_F21; break;
50414e24 1017 case XK_F22:
2d120f83 1018 id = WXK_F22; break;
50414e24 1019 case XK_F23:
2d120f83 1020 id = WXK_F23; break;
50414e24 1021 case XK_F24:
2d120f83 1022 id = WXK_F24; break;
50414e24 1023 default:
2d120f83 1024 id = (keySym <= 255) ? (int)keySym : -1;
50414e24
JS
1025 } // switch
1026 return id;
1027}
1028
1029KeySym wxCharCodeWXToX(int id)
1030{
2d120f83
JS
1031 KeySym keySym;
1032
1033 switch (id) {
50414e24
JS
1034 case WXK_CANCEL: keySym = XK_Cancel; break;
1035 case WXK_BACK: keySym = XK_BackSpace; break;
1036 case WXK_TAB: keySym = XK_Tab; break;
1037 case WXK_CLEAR: keySym = XK_Clear; break;
1038 case WXK_RETURN: keySym = XK_Return; break;
1039 case WXK_SHIFT: keySym = XK_Shift_L; break;
1040 case WXK_CONTROL: keySym = XK_Control_L; break;
1041 case WXK_MENU : keySym = XK_Menu; break;
1042 case WXK_PAUSE: keySym = XK_Pause; break;
1043 case WXK_ESCAPE: keySym = XK_Escape; break;
1044 case WXK_SPACE: keySym = ' '; break;
1045 case WXK_PRIOR: keySym = XK_Prior; break;
1046 case WXK_NEXT : keySym = XK_Next; break;
1047 case WXK_END: keySym = XK_End; break;
1048 case WXK_HOME : keySym = XK_Home; break;
1049 case WXK_LEFT : keySym = XK_Left; break;
1050 case WXK_UP: keySym = XK_Up; break;
1051 case WXK_RIGHT: keySym = XK_Right; break;
1052 case WXK_DOWN : keySym = XK_Down; break;
1053 case WXK_SELECT: keySym = XK_Select; break;
1054 case WXK_PRINT: keySym = XK_Print; break;
1055 case WXK_EXECUTE: keySym = XK_Execute; break;
1056 case WXK_INSERT: keySym = XK_Insert; break;
1057 case WXK_DELETE: keySym = XK_Delete; break;
1058 case WXK_HELP : keySym = XK_Help; break;
1059 case WXK_NUMPAD0: keySym = XK_KP_0; break;
1060 case WXK_NUMPAD1: keySym = XK_KP_1; break;
1061 case WXK_NUMPAD2: keySym = XK_KP_2; break;
1062 case WXK_NUMPAD3: keySym = XK_KP_3; break;
1063 case WXK_NUMPAD4: keySym = XK_KP_4; break;
1064 case WXK_NUMPAD5: keySym = XK_KP_5; break;
1065 case WXK_NUMPAD6: keySym = XK_KP_6; break;
1066 case WXK_NUMPAD7: keySym = XK_KP_7; break;
1067 case WXK_NUMPAD8: keySym = XK_KP_8; break;
1068 case WXK_NUMPAD9: keySym = XK_KP_9; break;
1069 case WXK_MULTIPLY: keySym = XK_KP_Multiply; break;
1070 case WXK_ADD: keySym = XK_KP_Add; break;
1071 case WXK_SUBTRACT: keySym = XK_KP_Subtract; break;
1072 case WXK_DECIMAL: keySym = XK_KP_Decimal; break;
1073 case WXK_DIVIDE: keySym = XK_KP_Divide; break;
1074 case WXK_F1: keySym = XK_F1; break;
1075 case WXK_F2: keySym = XK_F2; break;
1076 case WXK_F3: keySym = XK_F3; break;
1077 case WXK_F4: keySym = XK_F4; break;
1078 case WXK_F5: keySym = XK_F5; break;
1079 case WXK_F6: keySym = XK_F6; break;
1080 case WXK_F7: keySym = XK_F7; break;
1081 case WXK_F8: keySym = XK_F8; break;
1082 case WXK_F9: keySym = XK_F9; break;
1083 case WXK_F10: keySym = XK_F10; break;
1084 case WXK_F11: keySym = XK_F11; break;
1085 case WXK_F12: keySym = XK_F12; break;
1086 case WXK_F13: keySym = XK_F13; break;
1087 case WXK_F14: keySym = XK_F14; break;
1088 case WXK_F15: keySym = XK_F15; break;
1089 case WXK_F16: keySym = XK_F16; break;
1090 case WXK_F17: keySym = XK_F17; break;
1091 case WXK_F18: keySym = XK_F18; break;
1092 case WXK_F19: keySym = XK_F19; break;
1093 case WXK_F20: keySym = XK_F20; break;
1094 case WXK_F21: keySym = XK_F21; break;
1095 case WXK_F22: keySym = XK_F22; break;
1096 case WXK_F23: keySym = XK_F23; break;
1097 case WXK_F24: keySym = XK_F24; break;
1098 case WXK_NUMLOCK: keySym = XK_Num_Lock; break;
1099 case WXK_SCROLL: keySym = XK_Scroll_Lock; break;
1100 default: keySym = id <= 255 ? (KeySym)id : 0;
2d120f83
JS
1101 } // switch
1102 return keySym;
50414e24 1103}
a4294b78
JS
1104
1105// Read $HOME for what it says is home, if not
1106// read $USER or $LOGNAME for user name else determine
1107// the Real User, then determine the Real home dir.
1108static char * GetIniFile (char *dest, const char *filename)
1109{
2d120f83
JS
1110 char *home = NULL;
1111 if (filename && wxIsAbsolutePath(filename))
1112 {
1113 strcpy(dest, filename);
1114 }
1115 else if ((home = wxGetUserHome("")) != NULL)
1116 {
1117 strcpy(dest, home);
1118 if (dest[strlen(dest) - 1] != '/')
1119 strcat (dest, "/");
1120 if (filename == NULL)
1121 {
1122 if ((filename = getenv ("XENVIRONMENT")) == NULL)
1123 filename = ".Xdefaults";
1124 }
1125 else if (*filename != '.')
1126 strcat (dest, ".");
1127 strcat (dest, filename);
1128 } else
1129 {
1130 dest[0] = '\0';
1131 }
1132 return dest;
a4294b78
JS
1133}
1134
1135/*
2d120f83
JS
1136* Some colour manipulation routines
1137*/
1138
a4294b78 1139void wxHSVToXColor(wxHSV *hsv,XColor *rgb)
2d120f83
JS
1140{
1141 int h = hsv->h;
1142 int s = hsv->s;
1143 int v = hsv->v;
1144 int r, g, b;
1145 int i, f;
1146 int p, q, t;
1147 s = (s * wxMAX_RGB) / wxMAX_SV;
1148 v = (v * wxMAX_RGB) / wxMAX_SV;
1149 if (h == 360) h = 0;
1150 if (s == 0) { h = 0; r = g = b = v; }
1151 i = h / 60;
1152 f = h % 60;
1153 p = v * (wxMAX_RGB - s) / wxMAX_RGB;
1154 q = v * (wxMAX_RGB - s * f / 60) / wxMAX_RGB;
1155 t = v * (wxMAX_RGB - s * (60 - f) / 60) / wxMAX_RGB;
1156 switch (i)
1157 {
1158 case 0: r = v, g = t, b = p; break;
1159 case 1: r = q, g = v, b = p; break;
1160 case 2: r = p, g = v, b = t; break;
1161 case 3: r = p, g = q, b = v; break;
1162 case 4: r = t, g = p, b = v; break;
1163 case 5: r = v, g = p, b = q; break;
1164 }
1165 rgb->red = r << 8;
1166 rgb->green = g << 8;
1167 rgb->blue = b << 8;
1168}
a4294b78
JS
1169
1170void wxXColorToHSV(wxHSV *hsv,XColor *rgb)
2d120f83
JS
1171{
1172 int r = rgb->red >> 8;
1173 int g = rgb->green >> 8;
1174 int b = rgb->blue >> 8;
1175 int maxv = wxMax3(r, g, b);
1176 int minv = wxMin3(r, g, b);
1177 int h, s, v;
1178 v = maxv;
1179 if (maxv) s = (maxv - minv) * wxMAX_RGB / maxv;
1180 else s = 0;
1181 if (s == 0) h = 0;
1182 else
1183 {
1184 int rc, gc, bc, hex;
1185 rc = (maxv - r) * wxMAX_RGB / (maxv - minv);
1186 gc = (maxv - g) * wxMAX_RGB / (maxv - minv);
1187 bc = (maxv - b) * wxMAX_RGB / (maxv - minv);
1188 if (r == maxv) { h = bc - gc, hex = 0; }
1189 else if (g == maxv) { h = rc - bc, hex = 2; }
1190 else if (b == maxv) { h = gc - rc, hex = 4; }
1191 h = hex * 60 + (h * 60 / wxMAX_RGB);
1192 if (h < 0) h += 360;
1193 }
1194 hsv->h = h;
1195 hsv->s = (s * wxMAX_SV) / wxMAX_RGB;
1196 hsv->v = (v * wxMAX_SV) / wxMAX_RGB;
1197}
a4294b78
JS
1198
1199void wxAllocNearestColor(Display *d,Colormap cmp,XColor *xc)
2d120f83
JS
1200{
1201 int llp;
1202
1203 int screen = DefaultScreen(d);
1204 int num_colors = DisplayCells(d,screen);
1205
1206 XColor *color_defs = new XColor[num_colors];
1207 for(llp = 0;llp < num_colors;llp++) color_defs[llp].pixel = llp;
1208 XQueryColors(d,cmp,color_defs,num_colors);
1209
1210 wxHSV hsv_defs, hsv;
1211 wxXColorToHSV(&hsv,xc);
1212
1213 int diff, min_diff, pixel = 0;
1214
1215 for(llp = 0;llp < num_colors;llp++)
1216 {
1217 wxXColorToHSV(&hsv_defs,&color_defs[llp]);
1218 diff = wxSIGN(wxH_WEIGHT * (hsv.h - hsv_defs.h)) +
1219 wxSIGN(wxS_WEIGHT * (hsv.s - hsv_defs.s)) +
1220 wxSIGN(wxV_WEIGHT * (hsv.v - hsv_defs.v));
1221 if (llp == 0) min_diff = diff;
1222 if (min_diff > diff) { min_diff = diff; pixel = llp; }
1223 if (min_diff == 0) break;
1224 }
1225
1226 xc -> red = color_defs[pixel].red;
1227 xc -> green = color_defs[pixel].green;
1228 xc -> blue = color_defs[pixel].blue;
1229 xc -> flags = DoRed | DoGreen | DoBlue;
1230 if (!XAllocColor(d,cmp,xc))
a4294b78 1231 cout << "wxAllocNearestColor : Warning : Cannot find nearest color !\n";
2d120f83
JS
1232
1233 delete[] color_defs;
1234}
a4294b78
JS
1235
1236void wxAllocColor(Display *d,Colormap cmp,XColor *xc)
2d120f83
JS
1237{
1238 if (!XAllocColor(d,cmp,xc))
1239 {
1240 // cout << "wxAllocColor : Warning : Can not allocate color, attempt find nearest !\n";
1241 wxAllocNearestColor(d,cmp,xc);
1242 }
1243}
a4294b78
JS
1244
1245
94b49b93
JS
1246// These functions duplicate those in wxWindow, but are needed
1247// for use outside of wxWindow (e.g. wxMenu, wxMenuBar).
1248
1249// Change a widget's foreground and background colours.
1250
1251void wxDoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour)
1252{
2d120f83
JS
1253 // When should we specify the foreground, if it's calculated
1254 // by wxComputeColours?
1255 // Solution: say we start with the default (computed) foreground colour.
1256 // If we call SetForegroundColour explicitly for a control or window,
1257 // then the foreground is changed.
1258 // Therefore SetBackgroundColour computes the foreground colour, and
1259 // SetForegroundColour changes the foreground colour. The ordering is
1260 // important.
1261
1262 XtVaSetValues ((Widget) widget,
1263 XmNforeground, foregroundColour.AllocColour(XtDisplay((Widget) widget)),
1264 NULL);
94b49b93
JS
1265}
1266
1267void wxDoChangeBackgroundColour(WXWidget widget, wxColour& backgroundColour, bool changeArmColour)
1268{
2d120f83
JS
1269 wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
1270 (wxColour*) NULL);
1271
94b49b93 1272 XtVaSetValues ((Widget) widget,
2d120f83
JS
1273 XmNbackground, g_itemColors[wxBACK_INDEX].pixel,
1274 XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel,
1275 XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel,
1276 XmNforeground, g_itemColors[wxFORE_INDEX].pixel,
1277 NULL);
1278
1279 if (changeArmColour)
1280 XtVaSetValues ((Widget) widget,
1281 XmNarmColor, g_itemColors[wxSELE_INDEX].pixel,
1282 NULL);
94b49b93
JS
1283}
1284
1285