]> git.saurik.com Git - wxWidgets.git/blame - src/motif/utils.cpp
Applied patch [ 1427626 ] Fix wxFileConfig so that it still works after DeleteAll()
[wxWidgets.git] / src / motif / utils.cpp
CommitLineData
4bb6408c 1/////////////////////////////////////////////////////////////////////////////
355b4d3d 2// Name: src/motif/utils.cpp
4bb6408c
JS
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
65571936 9// Licence: wxWindows licence
4bb6408c
JS
10/////////////////////////////////////////////////////////////////////////////
11
518b5d2f
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
4bb6408c 19
1248b41f
MB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
bcd055ae
JJ
23#ifdef __VMS
24#define XtDisplay XTDISPLAY
2b5f62a0 25#endif
1248b41f 26
2b5f62a0 27#include "wx/utils.h"
d48568a5 28#include "wx/apptrait.h"
2b5f62a0 29#include "wx/app.h"
1eb1eae7
MB
30#include "wx/dcmemory.h"
31#include "wx/bitmap.h"
eb6fa4b4 32#include "wx/evtloop.h"
2b5f62a0 33
2b5f62a0 34#include <string.h>
2b5f62a0
VZ
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
2b5f62a0 46#include <Xm/Xm.h>
6769d0cb
MB
47#include <Xm/Frame.h>
48
2b5f62a0 49#include "wx/motif/private.h"
2b5f62a0
VZ
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"
4b37e99a 69#else
2b5f62a0
VZ
70 #define DEFAULT_XRESOURCE_DIR "/usr/lib/X11/app-defaults"
71#endif
72
fd304d98 73#if wxUSE_RESOURCES
2b5f62a0 74static char *GetIniFile (char *dest, const char *filename);
fd304d98 75#endif
2b5f62a0
VZ
76
77// ============================================================================
78// implementation
79// ============================================================================
80
81// ----------------------------------------------------------------------------
82// async event processing
83// ----------------------------------------------------------------------------
84
85// Consume all events until no more left
eb6fa4b4 86void wxFlushEvents(WXDisplay* wxdisplay)
2b5f62a0 87{
eb6fa4b4
MB
88 Display *display = (Display*)wxdisplay;
89 wxEventLoop evtLoop;
2b5f62a0 90
96be256b 91 XSync (display, False);
2b5f62a0 92
eb6fa4b4 93 while (evtLoop.Pending())
2b5f62a0 94 {
eb6fa4b4
MB
95 XFlush (display);
96 evtLoop.Dispatch();
2b5f62a0 97 }
2b5f62a0
VZ
98}
99
2b5f62a0
VZ
100// ----------------------------------------------------------------------------
101// wxExecute stuff
102// ----------------------------------------------------------------------------
b229c8a9 103
2b5f62a0
VZ
104static 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}
2b5f62a0
VZ
116
117int wxAddProcessCallback(wxEndProcessData *proc_data, int fd)
118{
2b5f62a0
VZ
119 XtInputId id = XtAppAddInput((XtAppContext) wxTheApp->GetAppContext(),
120 fd,
121 (XtPointer *) XtInputReadMask,
122 (XtInputCallbackProc) xt_notify_end_process,
123 (XtPointer) proc_data);
bcd055ae 124
2b5f62a0 125 return (int)id;
2b5f62a0
VZ
126}
127
128// ----------------------------------------------------------------------------
129// misc
130// ----------------------------------------------------------------------------
131
132// Emit a beeeeeep
189d1ae7
SN
133#ifndef __EMX__
134// on OS/2, we use the wxBell from wxBase library (src/os2/utils.cpp)
2b5f62a0
VZ
135void wxBell()
136{
137 // Use current setting for the bell
eb6fa4b4 138 XBell (wxGlobalDisplay(), 0);
2b5f62a0 139}
189d1ae7 140#endif
2b5f62a0 141
324899f6 142wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
2b5f62a0 143{
f9788a11
MB
144 static wxToolkitInfo info;
145
a8eaaeb2
VS
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
2b5f62a0
VZ
152 // FIXME TODO
153 // This code is WRONG!! Does NOT return the
154 // Motif version of the libs but the X protocol
155 // version!
eb6fa4b4 156 Display *display = wxGlobalDisplay();
8da782ef
MB
157 if (display)
158 {
159 info.versionMajor = ProtocolVersion (display);
160 info.versionMinor = ProtocolRevision (display);
161 }
a8eaaeb2 162 info.os = wxMOTIF_X;
324899f6 163 return info;
2b5f62a0
VZ
164}
165
166// ----------------------------------------------------------------------------
167// Reading and writing resources (eg WIN.INI, .Xdefaults)
168// ----------------------------------------------------------------------------
169
fd304d98
MB
170#if wxUSE_RESOURCES
171
2b5f62a0
VZ
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.
175static char * GetIniFile (char *dest, const char *filename)
176{
177 char *home = NULL;
178 if (filename && wxIsAbsolutePath(filename))
179 {
180 strcpy(dest, filename);
181 }
355b4d3d 182 else if ((home = wxGetUserHome()) != NULL)
2b5f62a0
VZ
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
96be256b 202static char *GetResourcePath(char *buf, const char *name, bool create = false)
2b5f62a0
VZ
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, "/");
3e2d47e1 215 strcat (buf, wxFileNameFromPath (name).c_str());
2b5f62a0
VZ
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
233wxList wxResourceCache (wxKEY_STRING);
234
235void
236wxFlushResources (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.
96be256b 245 (void)GetResourcePath(nameBuffer, file, true);
2b5f62a0
VZ
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
256static XrmDatabase wxResourceDatabase = 0;
257
258void wxXMergeDatabases (wxApp * theApp, Display * display);
259
260bool 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];
3e2d47e1 277 strcpy (resName, section.c_str());
2b5f62a0 278 strcat (resName, ".");
3e2d47e1 279 strcat (resName, entry.c_str());
2b5f62a0
VZ
280
281 XrmPutStringResource (&database, resName, value);
ea76a6a5 282 return true;
2b5f62a0
VZ
283}
284
285bool 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
292bool 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
299bool 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
306bool wxGetResource(const wxString& section, const wxString& entry, char **value, const wxString& file)
307{
308 if (!wxResourceDatabase)
309 {
eb6fa4b4 310 Display *display = wxGlobalDisplay();
2b5f62a0
VZ
311 wxXMergeDatabases (wxTheApp, display);
312 }
313
314 XrmDatabase database;
315
355b4d3d 316 if (!file.empty())
2b5f62a0
VZ
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);
ea76a6a5 359 return true;
2b5f62a0 360 }
96be256b 361 return false;
2b5f62a0
VZ
362}
363
364bool 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;
ea76a6a5 372 return true;
2b5f62a0 373 }
96be256b 374 else return false;
2b5f62a0
VZ
375}
376
377bool 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;
ea76a6a5 385 return true;
2b5f62a0 386 }
96be256b 387 else return false;
2b5f62a0
VZ
388}
389
390bool 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')
96be256b 399 *value = true;
2b5f62a0
VZ
400 // False, No, Disabled, Reset, Cleared, Deactivated
401 else if (*s == 'F' || *s == 'N' || *s == 'D' || *s == 'R' || *s == 'C')
96be256b 402 *value = false;
2b5f62a0
VZ
403 // Handle as Integer
404 else
405 *value = (int) strtol (s, NULL, 10);
406 delete[] s;
ea76a6a5 407 return true;
2b5f62a0
VZ
408 }
409 else
96be256b 410 return false;
2b5f62a0
VZ
411}
412
413void 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/");
3e2d47e1 423 (void) strcat (name, classname.c_str());
2b5f62a0
VZ
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();
355b4d3d 456 if ( !hostname.empty() )
2b5f62a0
VZ
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*/
469void
470wxSetDefaultResources (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);
96be256b 497 XrmCombineDatabase (rdb, &db, False);
2b5f62a0
VZ
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
513void 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;
eb6fa4b4
MB
522 XQueryPointer(wxGlobalDisplay(),
523 DefaultRootWindow(wxGlobalDisplay()),
2b5f62a0
VZ
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
e933b5bc 531}
2b5f62a0 532
ea76a6a5 533// Return true if we have a colour display
2b5f62a0
VZ
534bool wxColourDisplay()
535{
536 return wxDisplayDepth() > 1;
537}
538
539// Returns depth of screen
540int wxDisplayDepth()
541{
eb6fa4b4 542 Display *dpy = wxGlobalDisplay();
2b5f62a0
VZ
543
544 return DefaultDepth (dpy, DefaultScreen (dpy));
545}
546
547// Get size of display
548void wxDisplaySize(int *width, int *height)
549{
eb6fa4b4 550 Display *dpy = wxGlobalDisplay();
2b5f62a0
VZ
551
552 if ( width )
553 *width = DisplayWidth (dpy, DefaultScreen (dpy));
554 if ( height )
555 *height = DisplayHeight (dpy, DefaultScreen (dpy));
556}
557
558void wxDisplaySizeMM(int *width, int *height)
559{
eb6fa4b4 560 Display *dpy = wxGlobalDisplay();
2b5f62a0
VZ
561
562 if ( width )
563 *width = DisplayWidthMM(dpy, DefaultScreen (dpy));
564 if ( height )
565 *height = DisplayHeightMM(dpy, DefaultScreen (dpy));
566}
567
568void 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
581static WXDisplay *gs_currentDisplay = NULL;
582static wxString gs_displayName;
583
584WXDisplay *wxGetDisplay()
585{
586 if (gs_currentDisplay)
587 return gs_currentDisplay;
2b5f62a0
VZ
588 else if (wxTheApp)
589 return wxTheApp->GetInitialDisplay();
590 return NULL;
2b5f62a0
VZ
591}
592
593bool wxSetDisplay(const wxString& display_name)
594{
595 gs_displayName = display_name;
596
ea76a6a5 597 if ( display_name.empty() )
2b5f62a0
VZ
598 {
599 gs_currentDisplay = NULL;
600
ea76a6a5 601 return true;
2b5f62a0
VZ
602 }
603 else
604 {
2b5f62a0
VZ
605 Cardinal argc = 0;
606
607 Display *display = XtOpenDisplay((XtAppContext) wxTheApp->GetAppContext(),
3e2d47e1
MB
608 display_name.c_str(),
609 wxTheApp->GetAppName().c_str(),
610 wxTheApp->GetClassName().c_str(),
2b5f62a0
VZ
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;
ea76a6a5 622 return true;
2b5f62a0
VZ
623 }
624 else
96be256b 625 return false;
2b5f62a0
VZ
626 }
627}
628
629wxString wxGetDisplayName()
630{
631 return gs_displayName;
632}
633
634wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
635{
636 return wxGenericFindWindowAtPoint(pt);
637}
638
2b5f62a0
VZ
639// ----------------------------------------------------------------------------
640// Some colour manipulation routines
641// ----------------------------------------------------------------------------
642
643void 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 }
355b4d3d
WS
669 rgb->red = (unsigned short)(r << 8);
670 rgb->green = (unsigned short)(g << 8);
671 rgb->blue = (unsigned short)(b << 8);
2b5f62a0
VZ
672}
673
674void 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
703void 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
745void 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__
755wxString 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;
ea76a6a5 762 static char* event_name[] = {
f1db433a
VZ
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
ea76a6a5
WS
775 type = wxMin(35, type); type = wxMax(1, type);
776 wxString str(event_name[type]);
777 return str;
2b5f62a0
VZ
778#endif
779}
780#endif
781
2b5f62a0
VZ
782// ----------------------------------------------------------------------------
783// accelerators
784// ----------------------------------------------------------------------------
785
786// Find the letter corresponding to the mnemonic, for Motif
787char wxFindMnemonic (const char *s)
788{
789 char mnem = 0;
790 int len = strlen (s);
791 int i;
eb6fa4b4 792
2b5f62a0
VZ
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
eb6fa4b4 810char* wxFindAccelerator( const char *s )
2b5f62a0 811{
eb6fa4b4 812#if 1
355b4d3d 813 wxUnusedVar(s);
2b5f62a0
VZ
814 // VZ: this function returns incorrect keysym which completely breaks kbd
815 // handling
816 return NULL;
eb6fa4b4
MB
817#else
818 // The accelerator text is after the \t char.
819 s = strchr( s, '\t' );
820
821 if( !s ) return NULL;
2b5f62a0 822
2b5f62a0
VZ
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
eb6fa4b4 833 and handle Ctrl-N & similia
2b5f62a0
VZ
834 */
835
836 static char buf[256];
eb6fa4b4 837
2b5f62a0 838 buf[0] = '\0';
eb6fa4b4
MB
839 wxString tmp = s + 1; // skip TAB
840 size_t index = 0;
2b5f62a0 841
eb6fa4b4 842 while( index < tmp.length() )
2b5f62a0 843 {
eb6fa4b4
MB
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 )
2b5f62a0 849 {
eb6fa4b4
MB
850 strcat( buf, "<Key>" );
851 strcat( buf, tmp.c_str() + index );
852
853 return buf;
2b5f62a0 854 }
eb6fa4b4
MB
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;
2b5f62a0 872 }
eb6fa4b4
MB
873
874 return NULL;
2b5f62a0
VZ
875#endif
876}
877
878XmString wxFindAcceleratorText (const char *s)
879{
eb6fa4b4 880#if 1
355b4d3d 881 wxUnusedVar(s);
2b5f62a0
VZ
882 // VZ: this function returns incorrect keysym which completely breaks kbd
883 // handling
884 return NULL;
eb6fa4b4
MB
885#else
886 // The accelerator text is after the \t char.
887 s = strchr( s, '\t' );
2b5f62a0 888
eb6fa4b4
MB
889 if( !s ) return NULL;
890
891 return wxStringToXmString( s + 1 ); // skip TAB!
2b5f62a0
VZ
892#endif
893}
894
2b5f62a0 895// Change a widget's foreground and background colours.
2b5f62a0
VZ
896void 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
912void 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
fbfb8bcc 930extern void wxDoChangeFont(WXWidget widget, const wxFont& font)
e1aae528 931{
101b4778
MB
932 // Lesstif 0.87 hangs here, but 0.93 does not; MBN: sometimes it does
933#if !wxCHECK_LESSTIF() // || wxCHECK_LESSTIF_VERSION( 0, 93 )
e1aae528 934 Widget w = (Widget)widget;
e1aae528 935 XtVaSetValues( w,
73608949 936 wxFont::GetFontTag(), font.GetFontTypeC( XtDisplay(w) ),
e1aae528 937 NULL );
355b4d3d
WS
938#else
939 wxUnusedVar(widget);
940 wxUnusedVar(font);
e1aae528
MB
941#endif
942
943}
944
e1aae528
MB
945wxString 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
3e2d47e1
MB
958XmString wxStringToXmString( const wxString& str )
959{
960 return XmStringCreateLtoR((char *)str.c_str(), XmSTRING_DEFAULT_CHARSET);
961}
962
963XmString wxStringToXmString( const char* str )
964{
965 return XmStringCreateLtoR((char *)str, XmSTRING_DEFAULT_CHARSET);
966}
aae0472b
MB
967
968// ----------------------------------------------------------------------------
969// wxBitmap utility functions
970// ----------------------------------------------------------------------------
971
972// Creates a bitmap with transparent areas drawn in
973// the given colour.
fbfb8bcc 974wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, const wxColour& colour)
aae0472b
MB
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);
aae0472b
MB
986 destDC.SetBackground(brush);
987 destDC.Clear();
988 destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(),
ea76a6a5 989 &srcDC, 0, 0, wxCOPY, true);
aae0472b
MB
990
991 return newBitmap;
992}
6769d0cb
MB
993
994// ----------------------------------------------------------------------------
995// Miscellaneous functions
996// ----------------------------------------------------------------------------
997
998WXWidget 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}