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