Cured some small doc typos; some WIN16 fixes; transferred DLL WinMain to
[wxWidgets.git] / src / motif / utils.cpp
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"
21 #include "wx/msgdlg.h"
22 #include "wx/cursor.h"
23
24 #include <ctype.h>
25 #include <stdarg.h>
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
37 #if defined(__SOLARIS__) || defined(__SVR4__) && !defined(__HPUX__)
38 #include <sys/systeminfo.h>
39 #endif
40
41 #if (defined(__SUNCC__) || defined(__CLCC__))
42 #include <sysent.h>
43 #endif
44
45 #include <Xm/Xm.h>
46
47 #include "wx/motif/private.h"
48
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
57 static char *GetIniFile (char *dest, const char *filename);
58
59 extern wxList wxTopLevelWindows;
60
61 // Get full hostname (eg. DoDo.BSn-Germany.crg.de)
62 bool wxGetHostName(char *buf, int maxSize)
63 {
64 #if defined(__SOLARIS__) || defined(__SVR4__) && !defined(__HPUX__)
65 return (sysinfo (SI_HOSTNAME, buf, maxSize) != -1);
66 #else /* BSD Sockets */
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;
78 #endif
79 }
80
81 // Get user ID e.g. jacs
82 bool wxGetUserId(char *buf, int maxSize)
83 {
84 #ifdef VMS
85 *buf = '\0'; // return empty string
86 return FALSE;
87 #else
88 struct passwd *who;
89
90 if ((who = getpwuid (getuid ())) != NULL)
91 {
92 strncpy (buf, who->pw_name, maxSize - 1);
93 return TRUE;
94 }
95 return FALSE;
96 #endif
97 }
98
99 // Get user name e.g. Julian Smart
100 bool wxGetUserName(char *buf, int maxSize)
101 {
102 #ifdef VMS
103 *buf = '\0'; // return empty string
104 return FALSE;
105 #else
106 struct passwd *who;
107
108 if ((who = getpwuid (getuid ())) != NULL)
109 {
110 strncpy (buf, who->pw_gecos, maxSize - 1);
111 return TRUE;
112 }
113 return FALSE;
114 #endif
115 }
116
117 int wxKill(long pid, int sig)
118 {
119 int unixSignal = 0;
120 switch (sig)
121 {
122 case wxSIGTERM:
123 default:
124 unixSignal = SIGTERM;
125 }
126 return kill( (int)pid, unixSignal);
127 }
128
129 //
130 // Execute a program in an Interactive Shell
131 //
132 bool wxShell(const wxString& command)
133 {
134 #ifdef VMS
135 return(FALSE);
136 #else
137 #if defined(sun) || defined(__ultrix) || defined(__bsdi__)
138 pid_t pid = vfork ();
139 #else
140 pid_t pid = fork ();
141 #endif
142 switch( pid ) {
143 case -1: /* error */
144 return(FALSE);
145 case 0: /* child */
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;
154 #endif
155 // End VMS
156 }
157
158 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
159 long wxGetFreeMemory()
160 {
161 return -1;
162 }
163
164 void wxSleep(int nSecs)
165 {
166 sleep(nSecs);
167 }
168
169 // Consume all events until no more left
170 void wxFlushEvents()
171 {
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)
180 {
181 XFlush (XtDisplay ((Widget) wxTheApp->GetTopLevelWidget()));
182 // Jan Lessner: works better when events are non-X events
183 XtAppProcessEvent((XtAppContext) wxTheApp->GetAppContext(), XtIMXEvent);
184 }
185 }
186
187 // Output a debug message, in a system dependent fashion.
188 void wxDebugMsg(const char *fmt ...)
189 {
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);
202 }
203
204 // Non-fatal error: pop up message box and (possibly) continue
205 void wxError(const wxString& msg, const wxString& title)
206 {
207 cerr << (const char*) title << ": " << (const char*) msg << "\n";
208 }
209
210 // Fatal error: pop up message box and abort
211 void wxFatalError(const wxString& msg, const wxString& title)
212 {
213 cerr << (const char*) title << ": " << (const char*) msg << "\n";
214 exit (1);
215 }
216
217 // Emit a beeeeeep
218 void wxBell()
219 {
220 // Use current setting for the bell
221 XBell ((Display*) wxGetDisplay(), 0);
222 }
223
224 int wxGetOsVersion(int *majorVsn, int *minorVsn)
225 {
226 // TODO
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;
236 }
237
238 // Reading and writing resources (eg WIN.INI, .Xdefaults)
239 #if wxUSE_RESOURCES
240
241 static char *GetResourcePath(char *buf, const char *name, bool create = FALSE)
242 {
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;
263 }
264
265 /*
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 */
271
272 wxList wxResourceCache (wxKEY_STRING);
273
274 void
275 wxFlushResources (void)
276 {
277 char nameBuffer[512];
278
279 wxNode *node = wxResourceCache.First ();
280 while (node)
281 {
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;
292 }
293 }
294
295 static XrmDatabase wxResourceDatabase = 0;
296
297 void wxXMergeDatabases (wxApp * theApp, Display * display);
298
299 bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file)
300 {
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
310 {
311 database = XrmGetFileDatabase (buffer);
312 wxResourceCache.Append (buffer, (wxObject *) database);
313 }
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;
322 }
323
324 bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file)
325 {
326 char buf[50];
327 sprintf(buf, "%.4f", value);
328 return wxWriteResource(section, entry, buf, file);
329 }
330
331 bool wxWriteResource(const wxString& section, const wxString& entry, long value, const wxString& file)
332 {
333 char buf[50];
334 sprintf(buf, "%ld", value);
335 return wxWriteResource(section, entry, buf, file);
336 }
337
338 bool wxWriteResource(const wxString& section, const wxString& entry, int value, const wxString& file)
339 {
340 char buf[50];
341 sprintf(buf, "%d", value);
342 return wxWriteResource(section, entry, buf, file);
343 }
344
345 bool wxGetResource(const wxString& section, const wxString& entry, char **value, const wxString& file)
346 {
347 if (!wxResourceDatabase)
348 {
349 Display *display = (Display*) wxGetDisplay();
350 wxXMergeDatabases (wxTheApp, display);
351 }
352
353 XrmDatabase database;
354
355 if (file != "")
356 {
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 }
371 }
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)
386 {
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;
399 }
400 return FALSE;
401 }
402
403 bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file)
404 {
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;
414 }
415
416 bool wxGetResource(const wxString& section, const wxString& entry, long *value, const wxString& file)
417 {
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;
427 }
428
429 bool wxGetResource(const wxString& section, const wxString& entry, int *value, const wxString& file)
430 {
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);
445 delete[] s;
446 return TRUE;
447 }
448 else
449 return FALSE;
450 }
451
452 void wxXMergeDatabases (wxApp * theApp, Display * display)
453 {
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)
475 {
476 serverDB = XrmGetStringDatabase (XResourceManagerString (display));
477 }
478 else
479 {
480 (void) GetIniFile (filename, NULL);
481 serverDB = XrmGetFileDatabase (filename);
482 }
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)
490 {
491 size_t len;
492 environment = GetIniFile (filename, NULL);
493 len = strlen (environment);
494 #if defined(__SOLARIS__) || defined(__SVR4__) && !defined(__HPUX__)
495 (void) sysinfo (SI_HOSTNAME, environment + len, 1024 - len);
496 #else
497 (void) gethostname (environment + len, 1024 - len);
498 #endif
499 }
500 homeDB = XrmGetFileDatabase (environment);
501 XrmMergeDatabases (homeDB, &wxResourceDatabase);
502 }
503
504 #if 0
505
506 /*
507 * Not yet used but may be useful.
508 *
509 */
510 void
511 wxSetDefaultResources (const Widget w, const char **resourceSpec, const char *name)
512 {
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)
525 {
526 char buf[1000];
527
528 sprintf (buf, "*%s%s", name, resourceSpec[i++]);
529 XrmPutLineResource (&rdb, buf);
530 }
531
532 // Merge them into the Xt database, with lowest precendence
533
534 if (rdb)
535 {
536 #if (XlibSpecificationRelease>=5)
537 XrmDatabase db = XtDatabase (dpy);
538 XrmCombineDatabase (rdb, &db, FALSE);
539 #else
540 XrmMergeDatabases (dpy->db, &rdb);
541 dpy->db = rdb;
542 #endif
543 }
544 }
545 #endif
546 // 0
547
548 #endif // wxUSE_RESOURCES
549
550 static int wxBusyCursorCount = 0;
551
552 // Helper function
553 static void
554 wxXSetBusyCursor (wxWindow * win, wxCursor * cursor)
555 {
556 Display *display = (Display*) win->GetXDisplay();
557
558 Window xwin = (Window) win->GetXWindow();
559 XSetWindowAttributes attrs;
560
561 if (cursor)
562 {
563 attrs.cursor = (Cursor) cursor->GetXCursor(display);
564 }
565 else
566 {
567 // Restore old cursor
568 if (win->GetCursor()->Ok())
569 attrs.cursor = (Cursor) win->GetCursor()->GetXCursor(display);
570 else
571 attrs.cursor = None;
572 }
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 {
580 wxWindow *child = (wxWindow *) node->Data ();
581 wxXSetBusyCursor (child, cursor);
582 }
583 }
584
585 // Set the cursor to the busy cursor for all windows
586 void wxBeginBusyCursor(wxCursor *cursor)
587 {
588 wxBusyCursorCount++;
589 if (wxBusyCursorCount == 1)
590 {
591 for(wxNode *node = wxTopLevelWindows.First (); node; node = node->Next())
592 {
593 wxWindow *win = (wxWindow *) node->Data ();
594 wxXSetBusyCursor (win, cursor);
595 }
596 }
597 }
598
599 // Restore cursor to normal
600 void wxEndBusyCursor()
601 {
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 }
614 }
615
616 // TRUE if we're between the above two calls
617 bool wxIsBusy()
618 {
619 return (wxBusyCursorCount > 0);
620 }
621
622 const char* wxGetHomeDir( wxString *home )
623 {
624 *home = wxGetUserHome( wxString() );
625 if (home->IsNull()) *home = "/";
626 return *home;
627 };
628
629 char *wxGetUserHome (const wxString& user)
630 {
631 #ifdef VMS
632 return(NULL);
633 #else
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;
653 #endif
654 // ifdef VMS
655 }
656
657 // Check whether this window wants to process messages, e.g. Stop button
658 // in long calculations.
659 bool wxCheckForInterrupt(wxWindow *wnd)
660 {
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 }
684 }
685
686 void wxGetMousePosition( int* x, int* y )
687 {
688 XMotionEvent xev;
689 Window root, child;
690 XQueryPointer((Display*) wxGetDisplay(),
691 DefaultRootWindow((Display*) wxGetDisplay()), &root, &child,
692 &(xev.x_root), &(xev.y_root),
693 &(xev.x), &(xev.y),
694 &(xev.state));
695 *x = xev.x_root;
696 *y = xev.y_root;
697 };
698
699 // Return TRUE if we have a colour display
700 bool wxColourDisplay()
701 {
702 Display *dpy = (Display*) wxGetDisplay();
703
704 if (DefaultDepth (dpy, DefaultScreen (dpy)) < 2)
705 return FALSE;
706 else
707 return TRUE;
708 }
709
710 // Returns depth of screen
711 int wxDisplayDepth()
712 {
713 Display *dpy = (Display*) wxGetDisplay();
714 return DefaultDepth (dpy, DefaultScreen (dpy));
715 }
716
717 // Get size of display
718 void wxDisplaySize(int *width, int *height)
719 {
720 Display *dpy = (Display*) wxGetDisplay();
721
722 *width = DisplayWidth (dpy, DefaultScreen (dpy));
723 *height = DisplayHeight (dpy, DefaultScreen (dpy));
724 }
725
726 /* Configurable display in Motif */
727 static WXDisplay *gs_currentDisplay = NULL;
728 static wxString gs_displayName;
729
730 WXDisplay *wxGetDisplay()
731 {
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;
741 }
742
743 bool wxSetDisplay(const wxString& display_name)
744 {
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,
761 # if XtSpecificationRelease < 5
762 0, &argc, NULL);
763 # else
764 0, (int *)&argc, NULL);
765 # endif
766
767 if (display)
768 {
769 gs_currentDisplay = (WXDisplay*) display;
770 return TRUE;
771 } else
772 return FALSE;
773 }
774 return FALSE;
775 }
776
777 wxString wxGetDisplayName()
778 {
779 return gs_displayName;
780 }
781
782 // Find the letter corresponding to the mnemonic, for Motif
783 char wxFindMnemonic (const char *s)
784 {
785 char mnem = 0;
786 int len = strlen (s);
787 int i;
788 for (i = 0; i < len; i++)
789 {
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 }
801 }
802 return mnem;
803 }
804
805 char * wxFindAccelerator (char *s)
806 {
807 // The accelerator text is after the \t char.
808 while (*s && *s != '\t')
809 s++;
810 if (*s == '\0')
811 return (NULL);
812 s++;
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)
831 {
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 }
852 }
853 delete[]tmp;
854 return wxBuffer;
855 }
856
857 XmString wxFindAcceleratorText (char *s)
858 {
859 // The accelerator text is after the \t char.
860 while (*s && *s != '\t')
861 s++;
862 if (*s == '\0')
863 return (NULL);
864 s++;
865 XmString text = XmStringCreateSimple (s);
866 return text;
867 }
868
869 #include <X11/keysym.h>
870
871 int wxCharCodeXToWX(KeySym keySym)
872 {
873 int id;
874 switch (keySym) {
875 case XK_Shift_L:
876 case XK_Shift_R:
877 id = WXK_SHIFT; break;
878 case XK_Control_L:
879 case XK_Control_R:
880 id = WXK_CONTROL; break;
881 case XK_BackSpace:
882 id = WXK_BACK; break;
883 case XK_Delete:
884 id = WXK_DELETE; break;
885 case XK_Clear:
886 id = WXK_CLEAR; break;
887 case XK_Tab:
888 id = WXK_TAB; break;
889 case XK_numbersign:
890 id = '#'; break;
891 case XK_Return:
892 id = WXK_RETURN; break;
893 case XK_Escape:
894 id = WXK_ESCAPE; break;
895 case XK_Pause:
896 case XK_Break:
897 id = WXK_PAUSE; break;
898 case XK_Num_Lock:
899 id = WXK_NUMLOCK; break;
900 case XK_Scroll_Lock:
901 id = WXK_SCROLL; break;
902
903 case XK_Home:
904 id = WXK_HOME; break;
905 case XK_End:
906 id = WXK_END; break;
907 case XK_Left:
908 id = WXK_LEFT; break;
909 case XK_Right:
910 id = WXK_RIGHT; break;
911 case XK_Up:
912 id = WXK_UP; break;
913 case XK_Down:
914 id = WXK_DOWN; break;
915 case XK_Next:
916 id = WXK_NEXT; break;
917 case XK_Prior:
918 id = WXK_PRIOR; break;
919 case XK_Menu:
920 id = WXK_MENU; break;
921 case XK_Select:
922 id = WXK_SELECT; break;
923 case XK_Cancel:
924 id = WXK_CANCEL; break;
925 case XK_Print:
926 id = WXK_PRINT; break;
927 case XK_Execute:
928 id = WXK_EXECUTE; break;
929 case XK_Insert:
930 id = WXK_INSERT; break;
931 case XK_Help:
932 id = WXK_HELP; break;
933
934 case XK_KP_Multiply:
935 id = WXK_MULTIPLY; break;
936 case XK_KP_Add:
937 id = WXK_ADD; break;
938 case XK_KP_Subtract:
939 id = WXK_SUBTRACT; break;
940 case XK_KP_Divide:
941 id = WXK_DIVIDE; break;
942 case XK_KP_Decimal:
943 id = WXK_DECIMAL; break;
944 case XK_KP_Equal:
945 id = '='; break;
946 case XK_KP_Space:
947 id = ' '; break;
948 case XK_KP_Tab:
949 id = WXK_TAB; break;
950 case XK_KP_Enter:
951 id = WXK_RETURN; break;
952 case XK_KP_0:
953 id = WXK_NUMPAD0; break;
954 case XK_KP_1:
955 id = WXK_NUMPAD1; break;
956 case XK_KP_2:
957 id = WXK_NUMPAD2; break;
958 case XK_KP_3:
959 id = WXK_NUMPAD3; break;
960 case XK_KP_4:
961 id = WXK_NUMPAD4; break;
962 case XK_KP_5:
963 id = WXK_NUMPAD5; break;
964 case XK_KP_6:
965 id = WXK_NUMPAD6; break;
966 case XK_KP_7:
967 id = WXK_NUMPAD7; break;
968 case XK_KP_8:
969 id = WXK_NUMPAD8; break;
970 case XK_KP_9:
971 id = WXK_NUMPAD9; break;
972 case XK_F1:
973 id = WXK_F1; break;
974 case XK_F2:
975 id = WXK_F2; break;
976 case XK_F3:
977 id = WXK_F3; break;
978 case XK_F4:
979 id = WXK_F4; break;
980 case XK_F5:
981 id = WXK_F5; break;
982 case XK_F6:
983 id = WXK_F6; break;
984 case XK_F7:
985 id = WXK_F7; break;
986 case XK_F8:
987 id = WXK_F8; break;
988 case XK_F9:
989 id = WXK_F9; break;
990 case XK_F10:
991 id = WXK_F10; break;
992 case XK_F11:
993 id = WXK_F11; break;
994 case XK_F12:
995 id = WXK_F12; break;
996 case XK_F13:
997 id = WXK_F13; break;
998 case XK_F14:
999 id = WXK_F14; break;
1000 case XK_F15:
1001 id = WXK_F15; break;
1002 case XK_F16:
1003 id = WXK_F16; break;
1004 case XK_F17:
1005 id = WXK_F17; break;
1006 case XK_F18:
1007 id = WXK_F18; break;
1008 case XK_F19:
1009 id = WXK_F19; break;
1010 case XK_F20:
1011 id = WXK_F20; break;
1012 case XK_F21:
1013 id = WXK_F21; break;
1014 case XK_F22:
1015 id = WXK_F22; break;
1016 case XK_F23:
1017 id = WXK_F23; break;
1018 case XK_F24:
1019 id = WXK_F24; break;
1020 default:
1021 id = (keySym <= 255) ? (int)keySym : -1;
1022 } // switch
1023 return id;
1024 }
1025
1026 KeySym wxCharCodeWXToX(int id)
1027 {
1028 KeySym keySym;
1029
1030 switch (id) {
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;
1098 } // switch
1099 return keySym;
1100 }
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.
1105 static char * GetIniFile (char *dest, const char *filename)
1106 {
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;
1130 }
1131
1132 /*
1133 * Some colour manipulation routines
1134 */
1135
1136 void wxHSVToXColor(wxHSV *hsv,XColor *rgb)
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 }
1166
1167 void wxXColorToHSV(wxHSV *hsv,XColor *rgb)
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 }
1195
1196 void wxAllocNearestColor(Display *d,Colormap cmp,XColor *xc)
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))
1228 cout << "wxAllocNearestColor : Warning : Cannot find nearest color !\n";
1229
1230 delete[] color_defs;
1231 }
1232
1233 void wxAllocColor(Display *d,Colormap cmp,XColor *xc)
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 }
1241
1242
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
1248 void wxDoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour)
1249 {
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);
1262 }
1263
1264 void wxDoChangeBackgroundColour(WXWidget widget, wxColour& backgroundColour, bool changeArmColour)
1265 {
1266 wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
1267 (wxColour*) NULL);
1268
1269 XtVaSetValues ((Widget) widget,
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);
1280 }
1281
1282