]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/motif/utils.cpp
build fix
[wxWidgets.git] / src / motif / utils.cpp
... / ...
CommitLineData
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#endif
33
34#include "wx/apptrait.h"
35#include "wx/bitmap.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
78static 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
90void 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
108static 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
121int 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)
139void wxBell()
140{
141 // Use current setting for the bell
142 XBell (wxGlobalDisplay(), 0);
143}
144#endif
145
146wxToolkitInfo& 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.
179static 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
206static 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
237wxList wxResourceCache (wxKEY_STRING);
238
239void
240wxFlushResources (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
260static XrmDatabase wxResourceDatabase = 0;
261
262void wxXMergeDatabases (wxApp * theApp, Display * display);
263
264bool 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
289bool 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
296bool 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
303bool 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
310bool 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
368bool 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
381bool 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
394bool 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
417void 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*/
473void
474wxSetDefaultResources (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
517void 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
538bool wxColourDisplay()
539{
540 return wxDisplayDepth() > 1;
541}
542
543// Returns depth of screen
544int wxDisplayDepth()
545{
546 Display *dpy = wxGlobalDisplay();
547
548 return DefaultDepth (dpy, DefaultScreen (dpy));
549}
550
551// Get size of display
552void 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
562void 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
572void 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
585static WXDisplay *gs_currentDisplay = NULL;
586static wxString gs_displayName;
587
588WXDisplay *wxGetDisplay()
589{
590 if (gs_currentDisplay)
591 return gs_currentDisplay;
592 else if (wxTheApp)
593 return wxTheApp->GetInitialDisplay();
594 return NULL;
595}
596
597bool 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
633wxString wxGetDisplayName()
634{
635 return gs_displayName;
636}
637
638wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
639{
640 return wxGenericFindWindowAtPoint(pt);
641}
642
643// ----------------------------------------------------------------------------
644// Some colour manipulation routines
645// ----------------------------------------------------------------------------
646
647void 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
678void 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
707void 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
749void 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__
759wxString 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
791char 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
814char* 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
882XmString 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.
900void 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
916void 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
934extern 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
949wxString 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
962XmString wxStringToXmString( const wxString& str )
963{
964 return XmStringCreateLtoR((char *)str.c_str(), XmSTRING_DEFAULT_CHARSET);
965}
966
967XmString 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.
978wxBitmap 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
1002WXWidget 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}