]> git.saurik.com Git - wxWidgets.git/blame - src/motif/utils.cpp
Committing in .
[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"
670f9935
WS
28
29#ifndef WX_PRECOMP
30 #include "wx/app.h"
f38924e8 31 #include "wx/dcmemory.h"
0bca0373 32 #include "wx/bitmap.h"
670f9935
WS
33#endif
34
d48568a5 35#include "wx/apptrait.h"
eb6fa4b4 36#include "wx/evtloop.h"
2b5f62a0 37
2b5f62a0 38#include <string.h>
2b5f62a0
VZ
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
2b5f62a0 50#include <Xm/Xm.h>
6769d0cb
MB
51#include <Xm/Frame.h>
52
2b5f62a0 53#include "wx/motif/private.h"
2b5f62a0
VZ
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"
4b37e99a 73#else
2b5f62a0
VZ
74 #define DEFAULT_XRESOURCE_DIR "/usr/lib/X11/app-defaults"
75#endif
76
fd304d98 77#if wxUSE_RESOURCES
2b5f62a0 78static char *GetIniFile (char *dest, const char *filename);
fd304d98 79#endif
2b5f62a0
VZ
80
81// ============================================================================
82// implementation
83// ============================================================================
84
85// ----------------------------------------------------------------------------
86// async event processing
87// ----------------------------------------------------------------------------
88
89// Consume all events until no more left
eb6fa4b4 90void wxFlushEvents(WXDisplay* wxdisplay)
2b5f62a0 91{
eb6fa4b4
MB
92 Display *display = (Display*)wxdisplay;
93 wxEventLoop evtLoop;
2b5f62a0 94
96be256b 95 XSync (display, False);
2b5f62a0 96
eb6fa4b4 97 while (evtLoop.Pending())
2b5f62a0 98 {
eb6fa4b4
MB
99 XFlush (display);
100 evtLoop.Dispatch();
2b5f62a0 101 }
2b5f62a0
VZ
102}
103
2b5f62a0
VZ
104// ----------------------------------------------------------------------------
105// wxExecute stuff
106// ----------------------------------------------------------------------------
b229c8a9 107
2b5f62a0
VZ
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}
2b5f62a0
VZ
120
121int wxAddProcessCallback(wxEndProcessData *proc_data, int fd)
122{
2b5f62a0
VZ
123 XtInputId id = XtAppAddInput((XtAppContext) wxTheApp->GetAppContext(),
124 fd,
125 (XtPointer *) XtInputReadMask,
126 (XtInputCallbackProc) xt_notify_end_process,
127 (XtPointer) proc_data);
bcd055ae 128
2b5f62a0 129 return (int)id;
2b5f62a0
VZ
130}
131
132// ----------------------------------------------------------------------------
133// misc
134// ----------------------------------------------------------------------------
135
136// Emit a beeeeeep
189d1ae7
SN
137#ifndef __EMX__
138// on OS/2, we use the wxBell from wxBase library (src/os2/utils.cpp)
2b5f62a0
VZ
139void wxBell()
140{
141 // Use current setting for the bell
eb6fa4b4 142 XBell (wxGlobalDisplay(), 0);
2b5f62a0 143}
189d1ae7 144#endif
2b5f62a0 145
324899f6 146wxToolkitInfo& wxGUIAppTraits::GetToolkitInfo()
2b5f62a0 147{
f9788a11
MB
148 static wxToolkitInfo info;
149
a8eaaeb2
VS
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
2b5f62a0
VZ
156 // FIXME TODO
157 // This code is WRONG!! Does NOT return the
158 // Motif version of the libs but the X protocol
159 // version!
eb6fa4b4 160 Display *display = wxGlobalDisplay();
8da782ef
MB
161 if (display)
162 {
163 info.versionMajor = ProtocolVersion (display);
164 info.versionMinor = ProtocolRevision (display);
165 }
a8eaaeb2 166 info.os = wxMOTIF_X;
324899f6 167 return info;
2b5f62a0
VZ
168}
169
170// ----------------------------------------------------------------------------
171// Reading and writing resources (eg WIN.INI, .Xdefaults)
172// ----------------------------------------------------------------------------
173
fd304d98
MB
174#if wxUSE_RESOURCES
175
2b5f62a0
VZ
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 }
355b4d3d 186 else if ((home = wxGetUserHome()) != NULL)
2b5f62a0
VZ
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
96be256b 206static char *GetResourcePath(char *buf, const char *name, bool create = false)
2b5f62a0
VZ
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, "/");
3e2d47e1 219 strcat (buf, wxFileNameFromPath (name).c_str());
2b5f62a0
VZ
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.
96be256b 249 (void)GetResourcePath(nameBuffer, file, true);
2b5f62a0
VZ
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];
3e2d47e1 281 strcpy (resName, section.c_str());
2b5f62a0 282 strcat (resName, ".");
3e2d47e1 283 strcat (resName, entry.c_str());
2b5f62a0
VZ
284
285 XrmPutStringResource (&database, resName, value);
ea76a6a5 286 return true;
2b5f62a0
VZ
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 {
eb6fa4b4 314 Display *display = wxGlobalDisplay();
2b5f62a0
VZ
315 wxXMergeDatabases (wxTheApp, display);
316 }
317
318 XrmDatabase database;
319
355b4d3d 320 if (!file.empty())
2b5f62a0
VZ
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);
ea76a6a5 363 return true;
2b5f62a0 364 }
96be256b 365 return false;
2b5f62a0
VZ
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;
ea76a6a5 376 return true;
2b5f62a0 377 }
96be256b 378 else return false;
2b5f62a0
VZ
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;
ea76a6a5 389 return true;
2b5f62a0 390 }
96be256b 391 else return false;
2b5f62a0
VZ
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')
96be256b 403 *value = true;
2b5f62a0
VZ
404 // False, No, Disabled, Reset, Cleared, Deactivated
405 else if (*s == 'F' || *s == 'N' || *s == 'D' || *s == 'R' || *s == 'C')
96be256b 406 *value = false;
2b5f62a0
VZ
407 // Handle as Integer
408 else
409 *value = (int) strtol (s, NULL, 10);
410 delete[] s;
ea76a6a5 411 return true;
2b5f62a0
VZ
412 }
413 else
96be256b 414 return false;
2b5f62a0
VZ
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/");
3e2d47e1 427 (void) strcat (name, classname.c_str());
2b5f62a0
VZ
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();
355b4d3d 460 if ( !hostname.empty() )
2b5f62a0
VZ
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);
96be256b 501 XrmCombineDatabase (rdb, &db, False);
2b5f62a0
VZ
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;
eb6fa4b4
MB
526 XQueryPointer(wxGlobalDisplay(),
527 DefaultRootWindow(wxGlobalDisplay()),
2b5f62a0
VZ
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
e933b5bc 535}
2b5f62a0 536
ea76a6a5 537// Return true if we have a colour display
2b5f62a0
VZ
538bool wxColourDisplay()
539{
540 return wxDisplayDepth() > 1;
541}
542
543// Returns depth of screen
544int wxDisplayDepth()
545{
eb6fa4b4 546 Display *dpy = wxGlobalDisplay();
2b5f62a0
VZ
547
548 return DefaultDepth (dpy, DefaultScreen (dpy));
549}
550
551// Get size of display
552void wxDisplaySize(int *width, int *height)
553{
eb6fa4b4 554 Display *dpy = wxGlobalDisplay();
2b5f62a0
VZ
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{
eb6fa4b4 564 Display *dpy = wxGlobalDisplay();
2b5f62a0
VZ
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;
2b5f62a0
VZ
592 else if (wxTheApp)
593 return wxTheApp->GetInitialDisplay();
594 return NULL;
2b5f62a0
VZ
595}
596
597bool wxSetDisplay(const wxString& display_name)
598{
599 gs_displayName = display_name;
600
ea76a6a5 601 if ( display_name.empty() )
2b5f62a0
VZ
602 {
603 gs_currentDisplay = NULL;
604
ea76a6a5 605 return true;
2b5f62a0
VZ
606 }
607 else
608 {
2b5f62a0
VZ
609 Cardinal argc = 0;
610
611 Display *display = XtOpenDisplay((XtAppContext) wxTheApp->GetAppContext(),
3e2d47e1
MB
612 display_name.c_str(),
613 wxTheApp->GetAppName().c_str(),
614 wxTheApp->GetClassName().c_str(),
2b5f62a0
VZ
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;
ea76a6a5 626 return true;
2b5f62a0
VZ
627 }
628 else
96be256b 629 return false;
2b5f62a0
VZ
630 }
631}
632
633wxString wxGetDisplayName()
634{
635 return gs_displayName;
636}
637
638wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
639{
640 return wxGenericFindWindowAtPoint(pt);
641}
642
2b5f62a0
VZ
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 }
355b4d3d
WS
673 rgb->red = (unsigned short)(r << 8);
674 rgb->green = (unsigned short)(g << 8);
675 rgb->blue = (unsigned short)(b << 8);
2b5f62a0
VZ
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;
ea76a6a5 766 static char* event_name[] = {
f1db433a
VZ
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
ea76a6a5
WS
779 type = wxMin(35, type); type = wxMax(1, type);
780 wxString str(event_name[type]);
781 return str;
2b5f62a0
VZ
782#endif
783}
784#endif
785
2b5f62a0
VZ
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;
eb6fa4b4 796
2b5f62a0
VZ
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
eb6fa4b4 814char* wxFindAccelerator( const char *s )
2b5f62a0 815{
eb6fa4b4 816#if 1
355b4d3d 817 wxUnusedVar(s);
2b5f62a0
VZ
818 // VZ: this function returns incorrect keysym which completely breaks kbd
819 // handling
820 return NULL;
eb6fa4b4
MB
821#else
822 // The accelerator text is after the \t char.
823 s = strchr( s, '\t' );
824
825 if( !s ) return NULL;
2b5f62a0 826
2b5f62a0
VZ
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
eb6fa4b4 837 and handle Ctrl-N & similia
2b5f62a0
VZ
838 */
839
840 static char buf[256];
eb6fa4b4 841
2b5f62a0 842 buf[0] = '\0';
eb6fa4b4
MB
843 wxString tmp = s + 1; // skip TAB
844 size_t index = 0;
2b5f62a0 845
eb6fa4b4 846 while( index < tmp.length() )
2b5f62a0 847 {
eb6fa4b4
MB
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 )
2b5f62a0 853 {
eb6fa4b4
MB
854 strcat( buf, "<Key>" );
855 strcat( buf, tmp.c_str() + index );
856
857 return buf;
2b5f62a0 858 }
eb6fa4b4
MB
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;
2b5f62a0 876 }
eb6fa4b4
MB
877
878 return NULL;
2b5f62a0
VZ
879#endif
880}
881
882XmString wxFindAcceleratorText (const char *s)
883{
eb6fa4b4 884#if 1
355b4d3d 885 wxUnusedVar(s);
2b5f62a0
VZ
886 // VZ: this function returns incorrect keysym which completely breaks kbd
887 // handling
888 return NULL;
eb6fa4b4
MB
889#else
890 // The accelerator text is after the \t char.
891 s = strchr( s, '\t' );
2b5f62a0 892
eb6fa4b4
MB
893 if( !s ) return NULL;
894
895 return wxStringToXmString( s + 1 ); // skip TAB!
2b5f62a0
VZ
896#endif
897}
898
2b5f62a0 899// Change a widget's foreground and background colours.
2b5f62a0
VZ
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
f516d986 916void wxDoChangeBackgroundColour(WXWidget widget, const wxColour& backgroundColour, bool changeArmColour)
2b5f62a0
VZ
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
fbfb8bcc 934extern void wxDoChangeFont(WXWidget widget, const wxFont& font)
e1aae528 935{
101b4778
MB
936 // Lesstif 0.87 hangs here, but 0.93 does not; MBN: sometimes it does
937#if !wxCHECK_LESSTIF() // || wxCHECK_LESSTIF_VERSION( 0, 93 )
e1aae528 938 Widget w = (Widget)widget;
e1aae528 939 XtVaSetValues( w,
73608949 940 wxFont::GetFontTag(), font.GetFontTypeC( XtDisplay(w) ),
e1aae528 941 NULL );
355b4d3d
WS
942#else
943 wxUnusedVar(widget);
944 wxUnusedVar(font);
e1aae528
MB
945#endif
946
947}
948
e1aae528
MB
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
3e2d47e1
MB
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}
aae0472b
MB
971
972// ----------------------------------------------------------------------------
973// wxBitmap utility functions
974// ----------------------------------------------------------------------------
975
976// Creates a bitmap with transparent areas drawn in
977// the given colour.
fbfb8bcc 978wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, const wxColour& colour)
aae0472b
MB
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);
aae0472b
MB
990 destDC.SetBackground(brush);
991 destDC.Clear();
992 destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(),
ea76a6a5 993 &srcDC, 0, 0, wxCOPY, true);
aae0472b
MB
994
995 return newBitmap;
996}
6769d0cb
MB
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}