Some stubs corrections; Motif corrections incl. busy cursor fix; doc corrections
[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 if (!xwin)
560 return;
561
562 XSetWindowAttributes attrs;
563
564 if (cursor)
565 {
566 attrs.cursor = (Cursor) cursor->GetXCursor(display);
567 }
568 else
569 {
570 // Restore old cursor
571 if (win->GetCursor()->Ok())
572 attrs.cursor = (Cursor) win->GetCursor()->GetXCursor(display);
573 else
574 attrs.cursor = None;
575 }
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 {
583 wxWindow *child = (wxWindow *) node->Data ();
584 wxXSetBusyCursor (child, cursor);
585 }
586 }
587
588 // Set the cursor to the busy cursor for all windows
589 void wxBeginBusyCursor(wxCursor *cursor)
590 {
591 wxBusyCursorCount++;
592 if (wxBusyCursorCount == 1)
593 {
594 for(wxNode *node = wxTopLevelWindows.First (); node; node = node->Next())
595 {
596 wxWindow *win = (wxWindow *) node->Data ();
597 wxXSetBusyCursor (win, cursor);
598 }
599 }
600 }
601
602 // Restore cursor to normal
603 void wxEndBusyCursor()
604 {
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 }
617 }
618
619 // TRUE if we're between the above two calls
620 bool wxIsBusy()
621 {
622 return (wxBusyCursorCount > 0);
623 }
624
625 const char* wxGetHomeDir( wxString *home )
626 {
627 *home = wxGetUserHome( wxString() );
628 if (home->IsNull()) *home = "/";
629 return *home;
630 };
631
632 char *wxGetUserHome (const wxString& user)
633 {
634 #ifdef VMS
635 return(NULL);
636 #else
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;
656 #endif
657 // ifdef VMS
658 }
659
660 // Check whether this window wants to process messages, e.g. Stop button
661 // in long calculations.
662 bool wxCheckForInterrupt(wxWindow *wnd)
663 {
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 }
687 }
688
689 void wxGetMousePosition( int* x, int* y )
690 {
691 XMotionEvent xev;
692 Window root, child;
693 XQueryPointer((Display*) wxGetDisplay(),
694 DefaultRootWindow((Display*) wxGetDisplay()), &root, &child,
695 &(xev.x_root), &(xev.y_root),
696 &(xev.x), &(xev.y),
697 &(xev.state));
698 *x = xev.x_root;
699 *y = xev.y_root;
700 };
701
702 // Return TRUE if we have a colour display
703 bool wxColourDisplay()
704 {
705 Display *dpy = (Display*) wxGetDisplay();
706
707 if (DefaultDepth (dpy, DefaultScreen (dpy)) < 2)
708 return FALSE;
709 else
710 return TRUE;
711 }
712
713 // Returns depth of screen
714 int wxDisplayDepth()
715 {
716 Display *dpy = (Display*) wxGetDisplay();
717 return DefaultDepth (dpy, DefaultScreen (dpy));
718 }
719
720 // Get size of display
721 void wxDisplaySize(int *width, int *height)
722 {
723 Display *dpy = (Display*) wxGetDisplay();
724
725 *width = DisplayWidth (dpy, DefaultScreen (dpy));
726 *height = DisplayHeight (dpy, DefaultScreen (dpy));
727 }
728
729 /* Configurable display in Motif */
730 static WXDisplay *gs_currentDisplay = NULL;
731 static wxString gs_displayName;
732
733 WXDisplay *wxGetDisplay()
734 {
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;
744 }
745
746 bool wxSetDisplay(const wxString& display_name)
747 {
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,
764 # if XtSpecificationRelease < 5
765 0, &argc, NULL);
766 # else
767 0, (int *)&argc, NULL);
768 # endif
769
770 if (display)
771 {
772 gs_currentDisplay = (WXDisplay*) display;
773 return TRUE;
774 } else
775 return FALSE;
776 }
777 return FALSE;
778 }
779
780 wxString wxGetDisplayName()
781 {
782 return gs_displayName;
783 }
784
785 // Find the letter corresponding to the mnemonic, for Motif
786 char wxFindMnemonic (const char *s)
787 {
788 char mnem = 0;
789 int len = strlen (s);
790 int i;
791 for (i = 0; i < len; i++)
792 {
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 }
804 }
805 return mnem;
806 }
807
808 char * wxFindAccelerator (char *s)
809 {
810 // The accelerator text is after the \t char.
811 while (*s && *s != '\t')
812 s++;
813 if (*s == '\0')
814 return (NULL);
815 s++;
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)
834 {
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 }
855 }
856 delete[]tmp;
857 return wxBuffer;
858 }
859
860 XmString wxFindAcceleratorText (char *s)
861 {
862 // The accelerator text is after the \t char.
863 while (*s && *s != '\t')
864 s++;
865 if (*s == '\0')
866 return (NULL);
867 s++;
868 XmString text = XmStringCreateSimple (s);
869 return text;
870 }
871
872 #include <X11/keysym.h>
873
874 int wxCharCodeXToWX(KeySym keySym)
875 {
876 int id;
877 switch (keySym) {
878 case XK_Shift_L:
879 case XK_Shift_R:
880 id = WXK_SHIFT; break;
881 case XK_Control_L:
882 case XK_Control_R:
883 id = WXK_CONTROL; break;
884 case XK_BackSpace:
885 id = WXK_BACK; break;
886 case XK_Delete:
887 id = WXK_DELETE; break;
888 case XK_Clear:
889 id = WXK_CLEAR; break;
890 case XK_Tab:
891 id = WXK_TAB; break;
892 case XK_numbersign:
893 id = '#'; break;
894 case XK_Return:
895 id = WXK_RETURN; break;
896 case XK_Escape:
897 id = WXK_ESCAPE; break;
898 case XK_Pause:
899 case XK_Break:
900 id = WXK_PAUSE; break;
901 case XK_Num_Lock:
902 id = WXK_NUMLOCK; break;
903 case XK_Scroll_Lock:
904 id = WXK_SCROLL; break;
905
906 case XK_Home:
907 id = WXK_HOME; break;
908 case XK_End:
909 id = WXK_END; break;
910 case XK_Left:
911 id = WXK_LEFT; break;
912 case XK_Right:
913 id = WXK_RIGHT; break;
914 case XK_Up:
915 id = WXK_UP; break;
916 case XK_Down:
917 id = WXK_DOWN; break;
918 case XK_Next:
919 id = WXK_NEXT; break;
920 case XK_Prior:
921 id = WXK_PRIOR; break;
922 case XK_Menu:
923 id = WXK_MENU; break;
924 case XK_Select:
925 id = WXK_SELECT; break;
926 case XK_Cancel:
927 id = WXK_CANCEL; break;
928 case XK_Print:
929 id = WXK_PRINT; break;
930 case XK_Execute:
931 id = WXK_EXECUTE; break;
932 case XK_Insert:
933 id = WXK_INSERT; break;
934 case XK_Help:
935 id = WXK_HELP; break;
936
937 case XK_KP_Multiply:
938 id = WXK_MULTIPLY; break;
939 case XK_KP_Add:
940 id = WXK_ADD; break;
941 case XK_KP_Subtract:
942 id = WXK_SUBTRACT; break;
943 case XK_KP_Divide:
944 id = WXK_DIVIDE; break;
945 case XK_KP_Decimal:
946 id = WXK_DECIMAL; break;
947 case XK_KP_Equal:
948 id = '='; break;
949 case XK_KP_Space:
950 id = ' '; break;
951 case XK_KP_Tab:
952 id = WXK_TAB; break;
953 case XK_KP_Enter:
954 id = WXK_RETURN; break;
955 case XK_KP_0:
956 id = WXK_NUMPAD0; break;
957 case XK_KP_1:
958 id = WXK_NUMPAD1; break;
959 case XK_KP_2:
960 id = WXK_NUMPAD2; break;
961 case XK_KP_3:
962 id = WXK_NUMPAD3; break;
963 case XK_KP_4:
964 id = WXK_NUMPAD4; break;
965 case XK_KP_5:
966 id = WXK_NUMPAD5; break;
967 case XK_KP_6:
968 id = WXK_NUMPAD6; break;
969 case XK_KP_7:
970 id = WXK_NUMPAD7; break;
971 case XK_KP_8:
972 id = WXK_NUMPAD8; break;
973 case XK_KP_9:
974 id = WXK_NUMPAD9; break;
975 case XK_F1:
976 id = WXK_F1; break;
977 case XK_F2:
978 id = WXK_F2; break;
979 case XK_F3:
980 id = WXK_F3; break;
981 case XK_F4:
982 id = WXK_F4; break;
983 case XK_F5:
984 id = WXK_F5; break;
985 case XK_F6:
986 id = WXK_F6; break;
987 case XK_F7:
988 id = WXK_F7; break;
989 case XK_F8:
990 id = WXK_F8; break;
991 case XK_F9:
992 id = WXK_F9; break;
993 case XK_F10:
994 id = WXK_F10; break;
995 case XK_F11:
996 id = WXK_F11; break;
997 case XK_F12:
998 id = WXK_F12; break;
999 case XK_F13:
1000 id = WXK_F13; break;
1001 case XK_F14:
1002 id = WXK_F14; break;
1003 case XK_F15:
1004 id = WXK_F15; break;
1005 case XK_F16:
1006 id = WXK_F16; break;
1007 case XK_F17:
1008 id = WXK_F17; break;
1009 case XK_F18:
1010 id = WXK_F18; break;
1011 case XK_F19:
1012 id = WXK_F19; break;
1013 case XK_F20:
1014 id = WXK_F20; break;
1015 case XK_F21:
1016 id = WXK_F21; break;
1017 case XK_F22:
1018 id = WXK_F22; break;
1019 case XK_F23:
1020 id = WXK_F23; break;
1021 case XK_F24:
1022 id = WXK_F24; break;
1023 default:
1024 id = (keySym <= 255) ? (int)keySym : -1;
1025 } // switch
1026 return id;
1027 }
1028
1029 KeySym wxCharCodeWXToX(int id)
1030 {
1031 KeySym keySym;
1032
1033 switch (id) {
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;
1101 } // switch
1102 return keySym;
1103 }
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.
1108 static char * GetIniFile (char *dest, const char *filename)
1109 {
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;
1133 }
1134
1135 /*
1136 * Some colour manipulation routines
1137 */
1138
1139 void wxHSVToXColor(wxHSV *hsv,XColor *rgb)
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 }
1169
1170 void wxXColorToHSV(wxHSV *hsv,XColor *rgb)
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 }
1198
1199 void wxAllocNearestColor(Display *d,Colormap cmp,XColor *xc)
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))
1231 cout << "wxAllocNearestColor : Warning : Cannot find nearest color !\n";
1232
1233 delete[] color_defs;
1234 }
1235
1236 void wxAllocColor(Display *d,Colormap cmp,XColor *xc)
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 }
1244
1245
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
1251 void wxDoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour)
1252 {
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);
1265 }
1266
1267 void wxDoChangeBackgroundColour(WXWidget widget, wxColour& backgroundColour, bool changeArmColour)
1268 {
1269 wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
1270 (wxColour*) NULL);
1271
1272 XtVaSetValues ((Widget) widget,
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);
1283 }
1284
1285