Include order is wxprec.h=>defs.h=>platform.h=>setup.h so remove explicit setup.h...
[wxWidgets.git] / src / motif / utils.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/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 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __VMS
24 #define XtDisplay XTDISPLAY
25 #endif
26
27 #include "wx/utils.h"
28 #include "wx/apptrait.h"
29 #include "wx/app.h"
30 #include "wx/dcmemory.h"
31 #include "wx/bitmap.h"
32 #include "wx/evtloop.h"
33
34 #include <string.h>
35
36 #if (defined(__SUNCC__) || defined(__CLCC__))
37 #include <sysent.h>
38 #endif
39
40 #ifdef __VMS__
41 #pragma message disable nosimpint
42 #endif
43
44 #include "wx/unix/execute.h"
45
46 #include <Xm/Xm.h>
47 #include <Xm/Frame.h>
48
49 #include "wx/motif/private.h"
50
51 #if wxUSE_RESOURCES
52 #include "X11/Xresource.h"
53 #endif
54
55 #include "X11/Xutil.h"
56
57 #ifdef __VMS__
58 #pragma message enable nosimpint
59 #endif
60
61 // ----------------------------------------------------------------------------
62 // private functions
63 // ----------------------------------------------------------------------------
64
65 // Yuck this is really BOTH site and platform dependent
66 // so we should use some other strategy!
67 #ifdef sun
68 #define DEFAULT_XRESOURCE_DIR "/usr/openwin/lib/app-defaults"
69 #else
70 #define DEFAULT_XRESOURCE_DIR "/usr/lib/X11/app-defaults"
71 #endif
72
73 #if wxUSE_RESOURCES
74 static char *GetIniFile (char *dest, const char *filename);
75 #endif
76
77 // ============================================================================
78 // implementation
79 // ============================================================================
80
81 // ----------------------------------------------------------------------------
82 // async event processing
83 // ----------------------------------------------------------------------------
84
85 // Consume all events until no more left
86 void wxFlushEvents(WXDisplay* wxdisplay)
87 {
88 Display *display = (Display*)wxdisplay;
89 wxEventLoop evtLoop;
90
91 XSync (display, False);
92
93 while (evtLoop.Pending())
94 {
95 XFlush (display);
96 evtLoop.Dispatch();
97 }
98 }
99
100 // ----------------------------------------------------------------------------
101 // wxExecute stuff
102 // ----------------------------------------------------------------------------
103
104 static void xt_notify_end_process(XtPointer data, int *WXUNUSED(fid),
105 XtInputId *id)
106 {
107 wxEndProcessData *proc_data = (wxEndProcessData *)data;
108
109 wxHandleProcessTermination(proc_data);
110
111 // VZ: I think they should be the same...
112 wxASSERT( (int)*id == proc_data->tag );
113
114 XtRemoveInput(*id);
115 }
116
117 int wxAddProcessCallback(wxEndProcessData *proc_data, int fd)
118 {
119 XtInputId id = XtAppAddInput((XtAppContext) wxTheApp->GetAppContext(),
120 fd,
121 (XtPointer *) XtInputReadMask,
122 (XtInputCallbackProc) xt_notify_end_process,
123 (XtPointer) proc_data);
124
125 return (int)id;
126 }
127
128 // ----------------------------------------------------------------------------
129 // misc
130 // ----------------------------------------------------------------------------
131
132 // Emit a beeeeeep
133 #ifndef __EMX__
134 // on OS/2, we use the wxBell from wxBase library (src/os2/utils.cpp)
135 void wxBell()
136 {
137 // Use current setting for the bell
138 XBell (wxGlobalDisplay(), 0);
139 }
140 #endif
141
142 wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
143 {
144 static wxToolkitInfo info;
145
146 info.shortName = _T("motif");
147 info.name = _T("wxMotif");
148 #ifdef __WXUNIVERSAL__
149 info.shortName << _T("univ");
150 info.name << _T("/wxUniversal");
151 #endif
152 // FIXME TODO
153 // This code is WRONG!! Does NOT return the
154 // Motif version of the libs but the X protocol
155 // version!
156 Display *display = wxGlobalDisplay();
157 if (display)
158 {
159 info.versionMajor = ProtocolVersion (display);
160 info.versionMinor = ProtocolRevision (display);
161 }
162 info.os = wxMOTIF_X;
163 return info;
164 }
165
166 // ----------------------------------------------------------------------------
167 // Reading and writing resources (eg WIN.INI, .Xdefaults)
168 // ----------------------------------------------------------------------------
169
170 #if wxUSE_RESOURCES
171
172 // Read $HOME for what it says is home, if not
173 // read $USER or $LOGNAME for user name else determine
174 // the Real User, then determine the Real home dir.
175 static char * GetIniFile (char *dest, const char *filename)
176 {
177 char *home = NULL;
178 if (filename && wxIsAbsolutePath(filename))
179 {
180 strcpy(dest, filename);
181 }
182 else if ((home = wxGetUserHome()) != NULL)
183 {
184 strcpy(dest, home);
185 if (dest[strlen(dest) - 1] != '/')
186 strcat (dest, "/");
187 if (filename == NULL)
188 {
189 if ((filename = getenv ("XENVIRONMENT")) == NULL)
190 filename = ".Xdefaults";
191 }
192 else if (*filename != '.')
193 strcat (dest, ".");
194 strcat (dest, filename);
195 } else
196 {
197 dest[0] = '\0';
198 }
199 return dest;
200 }
201
202 static char *GetResourcePath(char *buf, const char *name, bool create = false)
203 {
204 if (create && wxFileExists (name) ) {
205 strcpy(buf, name);
206 return buf; // Exists so ...
207 }
208
209 if (*name == '/')
210 strcpy(buf, name);
211 else {
212 // Put in standard place for resource files if not absolute
213 strcpy (buf, DEFAULT_XRESOURCE_DIR);
214 strcat (buf, "/");
215 strcat (buf, wxFileNameFromPath (name).c_str());
216 }
217
218 if (create) {
219 // Touch the file to create it
220 FILE *fd = fopen (buf, "w");
221 if (fd) fclose (fd);
222 }
223 return buf;
224 }
225
226 /*
227 * We have a cache for writing different resource files,
228 * which will only get flushed when we call wxFlushResources().
229 * Build up a list of resource databases waiting to be written.
230 *
231 */
232
233 wxList wxResourceCache (wxKEY_STRING);
234
235 void
236 wxFlushResources (void)
237 {
238 char nameBuffer[512];
239
240 wxNode *node = wxResourceCache.First ();
241 while (node)
242 {
243 const char *file = node->GetKeyString();
244 // If file doesn't exist, create it first.
245 (void)GetResourcePath(nameBuffer, file, true);
246
247 XrmDatabase database = (XrmDatabase) node->Data ();
248 XrmPutFileDatabase (database, nameBuffer);
249 XrmDestroyDatabase (database);
250 wxNode *next = node->Next ();
251 delete node;
252 node = next;
253 }
254 }
255
256 static XrmDatabase wxResourceDatabase = 0;
257
258 void wxXMergeDatabases (wxApp * theApp, Display * display);
259
260 bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file)
261 {
262 char buffer[500];
263
264 (void) GetIniFile (buffer, file);
265
266 XrmDatabase database;
267 wxNode *node = wxResourceCache.Find (buffer);
268 if (node)
269 database = (XrmDatabase) node->Data ();
270 else
271 {
272 database = XrmGetFileDatabase (buffer);
273 wxResourceCache.Append (buffer, (wxObject *) database);
274 }
275
276 char resName[300];
277 strcpy (resName, section.c_str());
278 strcat (resName, ".");
279 strcat (resName, entry.c_str());
280
281 XrmPutStringResource (&database, resName, value);
282 return true;
283 }
284
285 bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file)
286 {
287 char buf[50];
288 sprintf(buf, "%.4f", value);
289 return wxWriteResource(section, entry, buf, file);
290 }
291
292 bool wxWriteResource(const wxString& section, const wxString& entry, long value, const wxString& file)
293 {
294 char buf[50];
295 sprintf(buf, "%ld", value);
296 return wxWriteResource(section, entry, buf, file);
297 }
298
299 bool wxWriteResource(const wxString& section, const wxString& entry, int value, const wxString& file)
300 {
301 char buf[50];
302 sprintf(buf, "%d", value);
303 return wxWriteResource(section, entry, buf, file);
304 }
305
306 bool wxGetResource(const wxString& section, const wxString& entry, char **value, const wxString& file)
307 {
308 if (!wxResourceDatabase)
309 {
310 Display *display = wxGlobalDisplay();
311 wxXMergeDatabases (wxTheApp, display);
312 }
313
314 XrmDatabase database;
315
316 if (!file.empty())
317 {
318 char buffer[500];
319
320 // Is this right? Trying to get it to look in the user's
321 // home directory instead of current directory -- JACS
322 (void) GetIniFile (buffer, file);
323
324 wxNode *node = wxResourceCache.Find (buffer);
325 if (node)
326 database = (XrmDatabase) node->Data ();
327 else
328 {
329 database = XrmGetFileDatabase (buffer);
330 wxResourceCache.Append (buffer, (wxObject *) database);
331 }
332 }
333 else
334 database = wxResourceDatabase;
335
336 XrmValue xvalue;
337 char *str_type[20];
338 char buf[150];
339 strcpy (buf, section);
340 strcat (buf, ".");
341 strcat (buf, entry);
342
343 Bool success = XrmGetResource (database, buf, "*", str_type,
344 &xvalue);
345 // Try different combinations of upper/lower case, just in case...
346 if (!success)
347 {
348 buf[0] = (isupper (buf[0]) ? tolower (buf[0]) : toupper (buf[0]));
349 success = XrmGetResource (database, buf, "*", str_type,
350 &xvalue);
351 }
352 if (success)
353 {
354 if (*value)
355 delete[] *value;
356
357 *value = new char[xvalue.size + 1];
358 strncpy (*value, xvalue.addr, (int) xvalue.size);
359 return true;
360 }
361 return false;
362 }
363
364 bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file)
365 {
366 char *s = NULL;
367 bool succ = wxGetResource(section, entry, (char **)&s, file);
368 if (succ)
369 {
370 *value = (float)strtod(s, NULL);
371 delete[] s;
372 return true;
373 }
374 else return false;
375 }
376
377 bool wxGetResource(const wxString& section, const wxString& entry, long *value, const wxString& file)
378 {
379 char *s = NULL;
380 bool succ = wxGetResource(section, entry, (char **)&s, file);
381 if (succ)
382 {
383 *value = strtol(s, NULL, 10);
384 delete[] s;
385 return true;
386 }
387 else return false;
388 }
389
390 bool wxGetResource(const wxString& section, const wxString& entry, int *value, const wxString& file)
391 {
392 char *s = NULL;
393 bool succ = wxGetResource(section, entry, (char **)&s, file);
394 if (succ)
395 {
396 // Handle True, False here
397 // True, Yes, Enables, Set or Activated
398 if (*s == 'T' || *s == 'Y' || *s == 'E' || *s == 'S' || *s == 'A')
399 *value = true;
400 // False, No, Disabled, Reset, Cleared, Deactivated
401 else if (*s == 'F' || *s == 'N' || *s == 'D' || *s == 'R' || *s == 'C')
402 *value = false;
403 // Handle as Integer
404 else
405 *value = (int) strtol (s, NULL, 10);
406 delete[] s;
407 return true;
408 }
409 else
410 return false;
411 }
412
413 void wxXMergeDatabases (wxApp * theApp, Display * display)
414 {
415 XrmDatabase homeDB, serverDB, applicationDB;
416 char filenamebuf[1024];
417
418 char *filename = &filenamebuf[0];
419 char *environment;
420 wxString classname = theApp->GetClassName();
421 char name[256];
422 (void) strcpy (name, "/usr/lib/X11/app-defaults/");
423 (void) strcat (name, classname.c_str());
424
425 /* Get application defaults file, if any */
426 applicationDB = XrmGetFileDatabase (name);
427 (void) XrmMergeDatabases (applicationDB, &wxResourceDatabase);
428
429 /* Merge server defaults, created by xrdb, loaded as a property of the root
430 * window when the server initializes and loaded into the display
431 * structure on XOpenDisplay;
432 * if not defined, use .Xdefaults
433 */
434
435 if (XResourceManagerString (display) != NULL)
436 {
437 serverDB = XrmGetStringDatabase (XResourceManagerString (display));
438 }
439 else
440 {
441 (void) GetIniFile (filename, NULL);
442 serverDB = XrmGetFileDatabase (filename);
443 }
444 XrmMergeDatabases (serverDB, &wxResourceDatabase);
445
446 /* Open XENVIRONMENT file, or if not defined, the .Xdefaults,
447 * and merge into existing database
448 */
449
450 if ((environment = getenv ("XENVIRONMENT")) == NULL)
451 {
452 size_t len;
453 environment = GetIniFile (filename, NULL);
454 len = strlen (environment);
455 wxString hostname = wxGetHostName();
456 if ( !hostname.empty() )
457 strncat(environment, hostname, 1024 - len);
458 }
459 homeDB = XrmGetFileDatabase (environment);
460 XrmMergeDatabases (homeDB, &wxResourceDatabase);
461 }
462
463 #if 0
464
465 /*
466 * Not yet used but may be useful.
467 *
468 */
469 void
470 wxSetDefaultResources (const Widget w, const char **resourceSpec, const char *name)
471 {
472 int i;
473 Display *dpy = XtDisplay (w); // Retrieve the display pointer
474
475 XrmDatabase rdb = NULL; // A resource data base
476
477 // Create an empty resource database
478 rdb = XrmGetStringDatabase ("");
479
480 // Add the Component resources, prepending the name of the component
481
482 i = 0;
483 while (resourceSpec[i] != NULL)
484 {
485 char buf[1000];
486
487 sprintf (buf, "*%s%s", name, resourceSpec[i++]);
488 XrmPutLineResource (&rdb, buf);
489 }
490
491 // Merge them into the Xt database, with lowest precendence
492
493 if (rdb)
494 {
495 #if (XlibSpecificationRelease>=5)
496 XrmDatabase db = XtDatabase (dpy);
497 XrmCombineDatabase (rdb, &db, False);
498 #else
499 XrmMergeDatabases (dpy->db, &rdb);
500 dpy->db = rdb;
501 #endif
502 }
503 }
504 #endif
505 // 0
506
507 #endif // wxUSE_RESOURCES
508
509 // ----------------------------------------------------------------------------
510 // display info
511 // ----------------------------------------------------------------------------
512
513 void wxGetMousePosition( int* x, int* y )
514 {
515 #if wxUSE_NANOX
516 // TODO
517 *x = 0;
518 *y = 0;
519 #else
520 XMotionEvent xev;
521 Window root, child;
522 XQueryPointer(wxGlobalDisplay(),
523 DefaultRootWindow(wxGlobalDisplay()),
524 &root, &child,
525 &(xev.x_root), &(xev.y_root),
526 &(xev.x), &(xev.y),
527 &(xev.state));
528 *x = xev.x_root;
529 *y = xev.y_root;
530 #endif
531 }
532
533 // Return true if we have a colour display
534 bool wxColourDisplay()
535 {
536 return wxDisplayDepth() > 1;
537 }
538
539 // Returns depth of screen
540 int wxDisplayDepth()
541 {
542 Display *dpy = wxGlobalDisplay();
543
544 return DefaultDepth (dpy, DefaultScreen (dpy));
545 }
546
547 // Get size of display
548 void wxDisplaySize(int *width, int *height)
549 {
550 Display *dpy = wxGlobalDisplay();
551
552 if ( width )
553 *width = DisplayWidth (dpy, DefaultScreen (dpy));
554 if ( height )
555 *height = DisplayHeight (dpy, DefaultScreen (dpy));
556 }
557
558 void wxDisplaySizeMM(int *width, int *height)
559 {
560 Display *dpy = wxGlobalDisplay();
561
562 if ( width )
563 *width = DisplayWidthMM(dpy, DefaultScreen (dpy));
564 if ( height )
565 *height = DisplayHeightMM(dpy, DefaultScreen (dpy));
566 }
567
568 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
569 {
570 // This is supposed to return desktop dimensions minus any window
571 // manager panels, menus, taskbars, etc. If there is a way to do that
572 // for this platform please fix this function, otherwise it defaults
573 // to the entire desktop.
574 if (x) *x = 0;
575 if (y) *y = 0;
576 wxDisplaySize(width, height);
577 }
578
579
580 // Configurable display in wxX11 and wxMotif
581 static WXDisplay *gs_currentDisplay = NULL;
582 static wxString gs_displayName;
583
584 WXDisplay *wxGetDisplay()
585 {
586 if (gs_currentDisplay)
587 return gs_currentDisplay;
588 else if (wxTheApp)
589 return wxTheApp->GetInitialDisplay();
590 return NULL;
591 }
592
593 bool wxSetDisplay(const wxString& display_name)
594 {
595 gs_displayName = display_name;
596
597 if ( display_name.empty() )
598 {
599 gs_currentDisplay = NULL;
600
601 return true;
602 }
603 else
604 {
605 Cardinal argc = 0;
606
607 Display *display = XtOpenDisplay((XtAppContext) wxTheApp->GetAppContext(),
608 display_name.c_str(),
609 wxTheApp->GetAppName().c_str(),
610 wxTheApp->GetClassName().c_str(),
611 NULL,
612 #if XtSpecificationRelease < 5
613 0, &argc,
614 #else
615 0, (int *)&argc,
616 #endif
617 NULL);
618
619 if (display)
620 {
621 gs_currentDisplay = (WXDisplay*) display;
622 return true;
623 }
624 else
625 return false;
626 }
627 }
628
629 wxString wxGetDisplayName()
630 {
631 return gs_displayName;
632 }
633
634 wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
635 {
636 return wxGenericFindWindowAtPoint(pt);
637 }
638
639 // ----------------------------------------------------------------------------
640 // Some colour manipulation routines
641 // ----------------------------------------------------------------------------
642
643 void wxHSVToXColor(wxHSV *hsv,XColor *rgb)
644 {
645 int h = hsv->h;
646 int s = hsv->s;
647 int v = hsv->v;
648 int r = 0, g = 0, b = 0;
649 int i, f;
650 int p, q, t;
651 s = (s * wxMAX_RGB) / wxMAX_SV;
652 v = (v * wxMAX_RGB) / wxMAX_SV;
653 if (h == 360) h = 0;
654 if (s == 0) { h = 0; r = g = b = v; }
655 i = h / 60;
656 f = h % 60;
657 p = v * (wxMAX_RGB - s) / wxMAX_RGB;
658 q = v * (wxMAX_RGB - s * f / 60) / wxMAX_RGB;
659 t = v * (wxMAX_RGB - s * (60 - f) / 60) / wxMAX_RGB;
660 switch (i)
661 {
662 case 0: r = v, g = t, b = p; break;
663 case 1: r = q, g = v, b = p; break;
664 case 2: r = p, g = v, b = t; break;
665 case 3: r = p, g = q, b = v; break;
666 case 4: r = t, g = p, b = v; break;
667 case 5: r = v, g = p, b = q; break;
668 }
669 rgb->red = (unsigned short)(r << 8);
670 rgb->green = (unsigned short)(g << 8);
671 rgb->blue = (unsigned short)(b << 8);
672 }
673
674 void wxXColorToHSV(wxHSV *hsv,XColor *rgb)
675 {
676 int r = rgb->red >> 8;
677 int g = rgb->green >> 8;
678 int b = rgb->blue >> 8;
679 int maxv = wxMax3(r, g, b);
680 int minv = wxMin3(r, g, b);
681 int h = 0, s, v;
682 v = maxv;
683 if (maxv) s = (maxv - minv) * wxMAX_RGB / maxv;
684 else s = 0;
685 if (s == 0) h = 0;
686 else
687 {
688 int rc, gc, bc, hex = 0;
689 rc = (maxv - r) * wxMAX_RGB / (maxv - minv);
690 gc = (maxv - g) * wxMAX_RGB / (maxv - minv);
691 bc = (maxv - b) * wxMAX_RGB / (maxv - minv);
692 if (r == maxv) { h = bc - gc, hex = 0; }
693 else if (g == maxv) { h = rc - bc, hex = 2; }
694 else if (b == maxv) { h = gc - rc, hex = 4; }
695 h = hex * 60 + (h * 60 / wxMAX_RGB);
696 if (h < 0) h += 360;
697 }
698 hsv->h = h;
699 hsv->s = (s * wxMAX_SV) / wxMAX_RGB;
700 hsv->v = (v * wxMAX_SV) / wxMAX_RGB;
701 }
702
703 void wxAllocNearestColor(Display *d,Colormap cmp,XColor *xc)
704 {
705 #if !wxUSE_NANOX
706 int llp;
707
708 int screen = DefaultScreen(d);
709 int num_colors = DisplayCells(d,screen);
710
711 XColor *color_defs = new XColor[num_colors];
712 for(llp = 0;llp < num_colors;llp++) color_defs[llp].pixel = llp;
713 XQueryColors(d,cmp,color_defs,num_colors);
714
715 wxHSV hsv_defs, hsv;
716 wxXColorToHSV(&hsv,xc);
717
718 int diff, min_diff = 0, pixel = 0;
719
720 for(llp = 0;llp < num_colors;llp++)
721 {
722 wxXColorToHSV(&hsv_defs,&color_defs[llp]);
723 diff = wxSIGN(wxH_WEIGHT * (hsv.h - hsv_defs.h)) +
724 wxSIGN(wxS_WEIGHT * (hsv.s - hsv_defs.s)) +
725 wxSIGN(wxV_WEIGHT * (hsv.v - hsv_defs.v));
726 if (llp == 0) min_diff = diff;
727 if (min_diff > diff) { min_diff = diff; pixel = llp; }
728 if (min_diff == 0) break;
729 }
730
731 xc -> red = color_defs[pixel].red;
732 xc -> green = color_defs[pixel].green;
733 xc -> blue = color_defs[pixel].blue;
734 xc -> flags = DoRed | DoGreen | DoBlue;
735
736 /* FIXME, TODO
737 if (!XAllocColor(d,cmp,xc))
738 cout << "wxAllocNearestColor : Warning : Cannot find nearest color !\n";
739 */
740
741 delete[] color_defs;
742 #endif
743 }
744
745 void wxAllocColor(Display *d,Colormap cmp,XColor *xc)
746 {
747 if (!XAllocColor(d,cmp,xc))
748 {
749 // cout << "wxAllocColor : Warning : Can not allocate color, attempt find nearest !\n";
750 wxAllocNearestColor(d,cmp,xc);
751 }
752 }
753
754 #ifdef __WXDEBUG__
755 wxString wxGetXEventName(XEvent& event)
756 {
757 #if wxUSE_NANOX
758 wxString str(wxT("(some event)"));
759 return str;
760 #else
761 int type = event.xany.type;
762 static char* event_name[] = {
763 wxMOTIF_STR(""), wxMOTIF_STR("unknown(-)"), // 0-1
764 wxMOTIF_STR("KeyPress"), wxMOTIF_STR("KeyRelease"), wxMOTIF_STR("ButtonPress"), wxMOTIF_STR("ButtonRelease"), // 2-5
765 wxMOTIF_STR("MotionNotify"), wxMOTIF_STR("EnterNotify"), wxMOTIF_STR("LeaveNotify"), wxMOTIF_STR("FocusIn"), // 6-9
766 wxMOTIF_STR("FocusOut"), wxMOTIF_STR("KeymapNotify"), wxMOTIF_STR("Expose"), wxMOTIF_STR("GraphicsExpose"), // 10-13
767 wxMOTIF_STR("NoExpose"), wxMOTIF_STR("VisibilityNotify"), wxMOTIF_STR("CreateNotify"), // 14-16
768 wxMOTIF_STR("DestroyNotify"), wxMOTIF_STR("UnmapNotify"), wxMOTIF_STR("MapNotify"), wxMOTIF_STR("MapRequest"),// 17-20
769 wxMOTIF_STR("ReparentNotify"), wxMOTIF_STR("ConfigureNotify"), wxMOTIF_STR("ConfigureRequest"), // 21-23
770 wxMOTIF_STR("GravityNotify"), wxMOTIF_STR("ResizeRequest"), wxMOTIF_STR("CirculateNotify"), // 24-26
771 wxMOTIF_STR("CirculateRequest"), wxMOTIF_STR("PropertyNotify"), wxMOTIF_STR("SelectionClear"), // 27-29
772 wxMOTIF_STR("SelectionRequest"), wxMOTIF_STR("SelectionNotify"), wxMOTIF_STR("ColormapNotify"), // 30-32
773 wxMOTIF_STR("ClientMessage"), wxMOTIF_STR("MappingNotify"), // 33-34
774 wxMOTIF_STR("unknown(+)")}; // 35
775 type = wxMin(35, type); type = wxMax(1, type);
776 wxString str(event_name[type]);
777 return str;
778 #endif
779 }
780 #endif
781
782 // ----------------------------------------------------------------------------
783 // accelerators
784 // ----------------------------------------------------------------------------
785
786 // Find the letter corresponding to the mnemonic, for Motif
787 char wxFindMnemonic (const char *s)
788 {
789 char mnem = 0;
790 int len = strlen (s);
791 int i;
792
793 for (i = 0; i < len; i++)
794 {
795 if (s[i] == '&')
796 {
797 // Carefully handle &&
798 if ((i + 1) <= len && s[i + 1] == '&')
799 i++;
800 else
801 {
802 mnem = s[i + 1];
803 break;
804 }
805 }
806 }
807 return mnem;
808 }
809
810 char* wxFindAccelerator( const char *s )
811 {
812 #if 1
813 wxUnusedVar(s);
814 // VZ: this function returns incorrect keysym which completely breaks kbd
815 // handling
816 return NULL;
817 #else
818 // The accelerator text is after the \t char.
819 s = strchr( s, '\t' );
820
821 if( !s ) return NULL;
822
823 /*
824 Now we need to format it as X standard:
825
826 input output
827
828 F7 --> <Key>F7
829 Ctrl+N --> Ctrl<Key>N
830 Alt+k --> Meta<Key>k
831 Ctrl+Shift+A --> Ctrl Shift<Key>A
832
833 and handle Ctrl-N & similia
834 */
835
836 static char buf[256];
837
838 buf[0] = '\0';
839 wxString tmp = s + 1; // skip TAB
840 size_t index = 0;
841
842 while( index < tmp.length() )
843 {
844 size_t plus = tmp.find( '+', index );
845 size_t minus = tmp.find( '-', index );
846
847 // neither '+' nor '-', add <Key>
848 if( plus == wxString::npos && minus == wxString::npos )
849 {
850 strcat( buf, "<Key>" );
851 strcat( buf, tmp.c_str() + index );
852
853 return buf;
854 }
855
856 // OK: npos is big and positive
857 size_t sep = wxMin( plus, minus );
858 wxString mod = tmp.substr( index, sep - index );
859
860 // Ctrl -> Ctrl
861 // Shift -> Shift
862 // Alt -> Meta
863 if( mod == "Alt" )
864 mod = "Meta";
865
866 if( buf[0] )
867 strcat( buf, " " );
868
869 strcat( buf, mod.c_str() );
870
871 index = sep + 1;
872 }
873
874 return NULL;
875 #endif
876 }
877
878 XmString wxFindAcceleratorText (const char *s)
879 {
880 #if 1
881 wxUnusedVar(s);
882 // VZ: this function returns incorrect keysym which completely breaks kbd
883 // handling
884 return NULL;
885 #else
886 // The accelerator text is after the \t char.
887 s = strchr( s, '\t' );
888
889 if( !s ) return NULL;
890
891 return wxStringToXmString( s + 1 ); // skip TAB!
892 #endif
893 }
894
895 // Change a widget's foreground and background colours.
896 void wxDoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour)
897 {
898 // When should we specify the foreground, if it's calculated
899 // by wxComputeColours?
900 // Solution: say we start with the default (computed) foreground colour.
901 // If we call SetForegroundColour explicitly for a control or window,
902 // then the foreground is changed.
903 // Therefore SetBackgroundColour computes the foreground colour, and
904 // SetForegroundColour changes the foreground colour. The ordering is
905 // important.
906
907 XtVaSetValues ((Widget) widget,
908 XmNforeground, foregroundColour.AllocColour(XtDisplay((Widget) widget)),
909 NULL);
910 }
911
912 void wxDoChangeBackgroundColour(WXWidget widget, wxColour& backgroundColour, bool changeArmColour)
913 {
914 wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
915 (wxColour*) NULL);
916
917 XtVaSetValues ((Widget) widget,
918 XmNbackground, g_itemColors[wxBACK_INDEX].pixel,
919 XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel,
920 XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel,
921 XmNforeground, g_itemColors[wxFORE_INDEX].pixel,
922 NULL);
923
924 if (changeArmColour)
925 XtVaSetValues ((Widget) widget,
926 XmNarmColor, g_itemColors[wxSELE_INDEX].pixel,
927 NULL);
928 }
929
930 extern void wxDoChangeFont(WXWidget widget, const wxFont& font)
931 {
932 // Lesstif 0.87 hangs here, but 0.93 does not; MBN: sometimes it does
933 #if !wxCHECK_LESSTIF() // || wxCHECK_LESSTIF_VERSION( 0, 93 )
934 Widget w = (Widget)widget;
935 XtVaSetValues( w,
936 wxFont::GetFontTag(), font.GetFontTypeC( XtDisplay(w) ),
937 NULL );
938 #else
939 wxUnusedVar(widget);
940 wxUnusedVar(font);
941 #endif
942
943 }
944
945 wxString wxXmStringToString( const XmString& xmString )
946 {
947 char *txt;
948 if( XmStringGetLtoR( xmString, XmSTRING_DEFAULT_CHARSET, &txt ) )
949 {
950 wxString str(txt);
951 XtFree (txt);
952 return str;
953 }
954
955 return wxEmptyString;
956 }
957
958 XmString wxStringToXmString( const wxString& str )
959 {
960 return XmStringCreateLtoR((char *)str.c_str(), XmSTRING_DEFAULT_CHARSET);
961 }
962
963 XmString wxStringToXmString( const char* str )
964 {
965 return XmStringCreateLtoR((char *)str, XmSTRING_DEFAULT_CHARSET);
966 }
967
968 // ----------------------------------------------------------------------------
969 // wxBitmap utility functions
970 // ----------------------------------------------------------------------------
971
972 // Creates a bitmap with transparent areas drawn in
973 // the given colour.
974 wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, const wxColour& colour)
975 {
976 wxBitmap newBitmap(bitmap.GetWidth(),
977 bitmap.GetHeight(),
978 bitmap.GetDepth());
979 wxMemoryDC destDC;
980 wxMemoryDC srcDC;
981
982 srcDC.SelectObject(bitmap);
983 destDC.SelectObject(newBitmap);
984
985 wxBrush brush(colour, wxSOLID);
986 destDC.SetBackground(brush);
987 destDC.Clear();
988 destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(),
989 &srcDC, 0, 0, wxCOPY, true);
990
991 return newBitmap;
992 }
993
994 // ----------------------------------------------------------------------------
995 // Miscellaneous functions
996 // ----------------------------------------------------------------------------
997
998 WXWidget wxCreateBorderWidget( WXWidget parent, long style )
999 {
1000 Widget borderWidget = (Widget)NULL, parentWidget = (Widget)parent;
1001
1002 if (style & wxSIMPLE_BORDER)
1003 {
1004 borderWidget = XtVaCreateManagedWidget
1005 (
1006 "simpleBorder",
1007 xmFrameWidgetClass, parentWidget,
1008 XmNshadowType, XmSHADOW_ETCHED_IN,
1009 XmNshadowThickness, 1,
1010 NULL
1011 );
1012 }
1013 else if (style & wxSUNKEN_BORDER)
1014 {
1015 borderWidget = XtVaCreateManagedWidget
1016 (
1017 "sunkenBorder",
1018 xmFrameWidgetClass, parentWidget,
1019 XmNshadowType, XmSHADOW_IN,
1020 NULL
1021 );
1022 }
1023 else if (style & wxRAISED_BORDER)
1024 {
1025 borderWidget = XtVaCreateManagedWidget
1026 (
1027 "raisedBorder",
1028 xmFrameWidgetClass, parentWidget,
1029 XmNshadowType, XmSHADOW_OUT,
1030 NULL
1031 );
1032 }
1033
1034 return borderWidget;
1035 }