]> git.saurik.com Git - wxWidgets.git/blame - src/motif/utils.cpp
Define WXBUILDING in Xcode projects.
[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
2b5f62a0 23#include "wx/utils.h"
670f9935
WS
24
25#ifndef WX_PRECOMP
26 #include "wx/app.h"
f38924e8 27 #include "wx/dcmemory.h"
0bca0373 28 #include "wx/bitmap.h"
670f9935
WS
29#endif
30
d48568a5 31#include "wx/apptrait.h"
eb6fa4b4 32#include "wx/evtloop.h"
c2ca375c 33#include "wx/motif/private/timer.h"
2b5f62a0 34
2b5f62a0 35#include <string.h>
2b5f62a0
VZ
36
37#if (defined(__SUNCC__) || defined(__CLCC__))
38 #include <sysent.h>
39#endif
40
41#ifdef __VMS__
42#pragma message disable nosimpint
43#endif
44
2b5f62a0 45#include <Xm/Xm.h>
6769d0cb
MB
46#include <Xm/Frame.h>
47
2b5f62a0 48#include "wx/motif/private.h"
2b5f62a0 49
2b5f62a0
VZ
50#include "X11/Xutil.h"
51
52#ifdef __VMS__
53#pragma message enable nosimpint
54#endif
55
2b5f62a0
VZ
56
57// ============================================================================
58// implementation
59// ============================================================================
60
61// ----------------------------------------------------------------------------
62// async event processing
63// ----------------------------------------------------------------------------
64
65// Consume all events until no more left
eb6fa4b4 66void wxFlushEvents(WXDisplay* wxdisplay)
2b5f62a0 67{
eb6fa4b4
MB
68 Display *display = (Display*)wxdisplay;
69 wxEventLoop evtLoop;
2b5f62a0 70
96be256b 71 XSync (display, False);
2b5f62a0 72
eb6fa4b4 73 while (evtLoop.Pending())
2b5f62a0 74 {
eb6fa4b4
MB
75 XFlush (display);
76 evtLoop.Dispatch();
2b5f62a0 77 }
2b5f62a0
VZ
78}
79
2b5f62a0
VZ
80// ----------------------------------------------------------------------------
81// misc
82// ----------------------------------------------------------------------------
83
84// Emit a beeeeeep
85void wxBell()
86{
87 // Use current setting for the bell
eb6fa4b4 88 XBell (wxGlobalDisplay(), 0);
2b5f62a0
VZ
89}
90
8bb6b2c0 91wxPortId wxGUIAppTraits::GetToolkitVersion(int *verMaj, int *verMin) const
2b5f62a0 92{
8bb6b2c0
VZ
93 // XmVERSION and XmREVISION are defined in Xm/Xm.h
94 if ( verMaj )
95 *verMaj = XmVERSION;
96 if ( verMin )
97 *verMin = XmREVISION;
f9788a11 98
8bb6b2c0 99 return wxPORT_MOTIF;
2b5f62a0
VZ
100}
101
2ddff00c 102wxEventLoopBase* wxGUIAppTraits::CreateEventLoop()
b46b1d59
VZ
103{
104 return new wxEventLoop;
105}
106
c2ca375c
VZ
107wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer* timer)
108{
109 return new wxMotifTimerImpl(timer);
110}
111
2b5f62a0
VZ
112// ----------------------------------------------------------------------------
113// display info
114// ----------------------------------------------------------------------------
115
116void wxGetMousePosition( int* x, int* y )
117{
118#if wxUSE_NANOX
119 // TODO
120 *x = 0;
121 *y = 0;
122#else
123 XMotionEvent xev;
124 Window root, child;
eb6fa4b4
MB
125 XQueryPointer(wxGlobalDisplay(),
126 DefaultRootWindow(wxGlobalDisplay()),
2b5f62a0
VZ
127 &root, &child,
128 &(xev.x_root), &(xev.y_root),
129 &(xev.x), &(xev.y),
130 &(xev.state));
131 *x = xev.x_root;
132 *y = xev.y_root;
133#endif
e933b5bc 134}
2b5f62a0 135
ea76a6a5 136// Return true if we have a colour display
2b5f62a0
VZ
137bool wxColourDisplay()
138{
139 return wxDisplayDepth() > 1;
140}
141
142// Returns depth of screen
143int wxDisplayDepth()
144{
eb6fa4b4 145 Display *dpy = wxGlobalDisplay();
2b5f62a0
VZ
146
147 return DefaultDepth (dpy, DefaultScreen (dpy));
148}
149
150// Get size of display
151void wxDisplaySize(int *width, int *height)
152{
eb6fa4b4 153 Display *dpy = wxGlobalDisplay();
2b5f62a0
VZ
154
155 if ( width )
156 *width = DisplayWidth (dpy, DefaultScreen (dpy));
157 if ( height )
158 *height = DisplayHeight (dpy, DefaultScreen (dpy));
159}
160
161void wxDisplaySizeMM(int *width, int *height)
162{
eb6fa4b4 163 Display *dpy = wxGlobalDisplay();
2b5f62a0
VZ
164
165 if ( width )
166 *width = DisplayWidthMM(dpy, DefaultScreen (dpy));
167 if ( height )
168 *height = DisplayHeightMM(dpy, DefaultScreen (dpy));
169}
170
2b5f62a0
VZ
171// Configurable display in wxX11 and wxMotif
172static WXDisplay *gs_currentDisplay = NULL;
173static wxString gs_displayName;
174
175WXDisplay *wxGetDisplay()
176{
177 if (gs_currentDisplay)
178 return gs_currentDisplay;
2b5f62a0
VZ
179 else if (wxTheApp)
180 return wxTheApp->GetInitialDisplay();
181 return NULL;
2b5f62a0
VZ
182}
183
184bool wxSetDisplay(const wxString& display_name)
185{
186 gs_displayName = display_name;
187
ea76a6a5 188 if ( display_name.empty() )
2b5f62a0
VZ
189 {
190 gs_currentDisplay = NULL;
191
ea76a6a5 192 return true;
2b5f62a0
VZ
193 }
194 else
195 {
2b5f62a0
VZ
196 Cardinal argc = 0;
197
198 Display *display = XtOpenDisplay((XtAppContext) wxTheApp->GetAppContext(),
3e2d47e1
MB
199 display_name.c_str(),
200 wxTheApp->GetAppName().c_str(),
201 wxTheApp->GetClassName().c_str(),
2b5f62a0
VZ
202 NULL,
203#if XtSpecificationRelease < 5
204 0, &argc,
205#else
206 0, (int *)&argc,
207#endif
208 NULL);
209
210 if (display)
211 {
212 gs_currentDisplay = (WXDisplay*) display;
ea76a6a5 213 return true;
2b5f62a0
VZ
214 }
215 else
96be256b 216 return false;
2b5f62a0
VZ
217 }
218}
219
220wxString wxGetDisplayName()
221{
222 return gs_displayName;
223}
224
225wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
226{
227 return wxGenericFindWindowAtPoint(pt);
228}
229
2b5f62a0
VZ
230// ----------------------------------------------------------------------------
231// Some colour manipulation routines
232// ----------------------------------------------------------------------------
233
234void wxHSVToXColor(wxHSV *hsv,XColor *rgb)
235{
236 int h = hsv->h;
237 int s = hsv->s;
238 int v = hsv->v;
239 int r = 0, g = 0, b = 0;
240 int i, f;
241 int p, q, t;
242 s = (s * wxMAX_RGB) / wxMAX_SV;
243 v = (v * wxMAX_RGB) / wxMAX_SV;
244 if (h == 360) h = 0;
245 if (s == 0) { h = 0; r = g = b = v; }
246 i = h / 60;
247 f = h % 60;
248 p = v * (wxMAX_RGB - s) / wxMAX_RGB;
249 q = v * (wxMAX_RGB - s * f / 60) / wxMAX_RGB;
250 t = v * (wxMAX_RGB - s * (60 - f) / 60) / wxMAX_RGB;
251 switch (i)
252 {
253 case 0: r = v, g = t, b = p; break;
254 case 1: r = q, g = v, b = p; break;
255 case 2: r = p, g = v, b = t; break;
256 case 3: r = p, g = q, b = v; break;
257 case 4: r = t, g = p, b = v; break;
258 case 5: r = v, g = p, b = q; break;
259 }
355b4d3d
WS
260 rgb->red = (unsigned short)(r << 8);
261 rgb->green = (unsigned short)(g << 8);
262 rgb->blue = (unsigned short)(b << 8);
2b5f62a0
VZ
263}
264
265void wxXColorToHSV(wxHSV *hsv,XColor *rgb)
266{
267 int r = rgb->red >> 8;
268 int g = rgb->green >> 8;
269 int b = rgb->blue >> 8;
270 int maxv = wxMax3(r, g, b);
271 int minv = wxMin3(r, g, b);
272 int h = 0, s, v;
273 v = maxv;
274 if (maxv) s = (maxv - minv) * wxMAX_RGB / maxv;
275 else s = 0;
276 if (s == 0) h = 0;
277 else
278 {
279 int rc, gc, bc, hex = 0;
280 rc = (maxv - r) * wxMAX_RGB / (maxv - minv);
281 gc = (maxv - g) * wxMAX_RGB / (maxv - minv);
282 bc = (maxv - b) * wxMAX_RGB / (maxv - minv);
283 if (r == maxv) { h = bc - gc, hex = 0; }
284 else if (g == maxv) { h = rc - bc, hex = 2; }
285 else if (b == maxv) { h = gc - rc, hex = 4; }
286 h = hex * 60 + (h * 60 / wxMAX_RGB);
287 if (h < 0) h += 360;
288 }
289 hsv->h = h;
290 hsv->s = (s * wxMAX_SV) / wxMAX_RGB;
291 hsv->v = (v * wxMAX_SV) / wxMAX_RGB;
292}
293
294void wxAllocNearestColor(Display *d,Colormap cmp,XColor *xc)
295{
296#if !wxUSE_NANOX
297 int llp;
298
299 int screen = DefaultScreen(d);
300 int num_colors = DisplayCells(d,screen);
301
302 XColor *color_defs = new XColor[num_colors];
303 for(llp = 0;llp < num_colors;llp++) color_defs[llp].pixel = llp;
304 XQueryColors(d,cmp,color_defs,num_colors);
305
306 wxHSV hsv_defs, hsv;
307 wxXColorToHSV(&hsv,xc);
308
309 int diff, min_diff = 0, pixel = 0;
310
311 for(llp = 0;llp < num_colors;llp++)
312 {
313 wxXColorToHSV(&hsv_defs,&color_defs[llp]);
314 diff = wxSIGN(wxH_WEIGHT * (hsv.h - hsv_defs.h)) +
315 wxSIGN(wxS_WEIGHT * (hsv.s - hsv_defs.s)) +
316 wxSIGN(wxV_WEIGHT * (hsv.v - hsv_defs.v));
317 if (llp == 0) min_diff = diff;
318 if (min_diff > diff) { min_diff = diff; pixel = llp; }
319 if (min_diff == 0) break;
320 }
321
322 xc -> red = color_defs[pixel].red;
323 xc -> green = color_defs[pixel].green;
324 xc -> blue = color_defs[pixel].blue;
325 xc -> flags = DoRed | DoGreen | DoBlue;
326
327/* FIXME, TODO
328 if (!XAllocColor(d,cmp,xc))
329 cout << "wxAllocNearestColor : Warning : Cannot find nearest color !\n";
330*/
331
332 delete[] color_defs;
333#endif
334}
335
336void wxAllocColor(Display *d,Colormap cmp,XColor *xc)
337{
338 if (!XAllocColor(d,cmp,xc))
339 {
4c51a665 340 // cout << "wxAllocColor : Warning : cannot allocate color, attempt find nearest !\n";
2b5f62a0
VZ
341 wxAllocNearestColor(d,cmp,xc);
342 }
343}
344
2b5f62a0
VZ
345wxString wxGetXEventName(XEvent& event)
346{
347#if wxUSE_NANOX
348 wxString str(wxT("(some event)"));
349 return str;
350#else
351 int type = event.xany.type;
ea76a6a5 352 static char* event_name[] = {
f1db433a
VZ
353 wxMOTIF_STR(""), wxMOTIF_STR("unknown(-)"), // 0-1
354 wxMOTIF_STR("KeyPress"), wxMOTIF_STR("KeyRelease"), wxMOTIF_STR("ButtonPress"), wxMOTIF_STR("ButtonRelease"), // 2-5
355 wxMOTIF_STR("MotionNotify"), wxMOTIF_STR("EnterNotify"), wxMOTIF_STR("LeaveNotify"), wxMOTIF_STR("FocusIn"), // 6-9
356 wxMOTIF_STR("FocusOut"), wxMOTIF_STR("KeymapNotify"), wxMOTIF_STR("Expose"), wxMOTIF_STR("GraphicsExpose"), // 10-13
357 wxMOTIF_STR("NoExpose"), wxMOTIF_STR("VisibilityNotify"), wxMOTIF_STR("CreateNotify"), // 14-16
358 wxMOTIF_STR("DestroyNotify"), wxMOTIF_STR("UnmapNotify"), wxMOTIF_STR("MapNotify"), wxMOTIF_STR("MapRequest"),// 17-20
359 wxMOTIF_STR("ReparentNotify"), wxMOTIF_STR("ConfigureNotify"), wxMOTIF_STR("ConfigureRequest"), // 21-23
360 wxMOTIF_STR("GravityNotify"), wxMOTIF_STR("ResizeRequest"), wxMOTIF_STR("CirculateNotify"), // 24-26
361 wxMOTIF_STR("CirculateRequest"), wxMOTIF_STR("PropertyNotify"), wxMOTIF_STR("SelectionClear"), // 27-29
362 wxMOTIF_STR("SelectionRequest"), wxMOTIF_STR("SelectionNotify"), wxMOTIF_STR("ColormapNotify"), // 30-32
363 wxMOTIF_STR("ClientMessage"), wxMOTIF_STR("MappingNotify"), // 33-34
364 wxMOTIF_STR("unknown(+)")}; // 35
ea76a6a5
WS
365 type = wxMin(35, type); type = wxMax(1, type);
366 wxString str(event_name[type]);
367 return str;
2b5f62a0
VZ
368#endif
369}
2b5f62a0 370
2b5f62a0
VZ
371// ----------------------------------------------------------------------------
372// accelerators
373// ----------------------------------------------------------------------------
374
375// Find the letter corresponding to the mnemonic, for Motif
376char wxFindMnemonic (const char *s)
377{
378 char mnem = 0;
379 int len = strlen (s);
380 int i;
eb6fa4b4 381
2b5f62a0
VZ
382 for (i = 0; i < len; i++)
383 {
384 if (s[i] == '&')
385 {
386 // Carefully handle &&
387 if ((i + 1) <= len && s[i + 1] == '&')
388 i++;
389 else
390 {
391 mnem = s[i + 1];
392 break;
393 }
394 }
395 }
396 return mnem;
397}
398
eb6fa4b4 399char* wxFindAccelerator( const char *s )
2b5f62a0 400{
eb6fa4b4 401#if 1
355b4d3d 402 wxUnusedVar(s);
2b5f62a0
VZ
403 // VZ: this function returns incorrect keysym which completely breaks kbd
404 // handling
405 return NULL;
eb6fa4b4
MB
406#else
407 // The accelerator text is after the \t char.
408 s = strchr( s, '\t' );
409
410 if( !s ) return NULL;
2b5f62a0 411
2b5f62a0
VZ
412 /*
413 Now we need to format it as X standard:
414
415 input output
416
417 F7 --> <Key>F7
418 Ctrl+N --> Ctrl<Key>N
419 Alt+k --> Meta<Key>k
420 Ctrl+Shift+A --> Ctrl Shift<Key>A
421
eb6fa4b4 422 and handle Ctrl-N & similia
2b5f62a0
VZ
423 */
424
425 static char buf[256];
eb6fa4b4 426
2b5f62a0 427 buf[0] = '\0';
eb6fa4b4
MB
428 wxString tmp = s + 1; // skip TAB
429 size_t index = 0;
2b5f62a0 430
eb6fa4b4 431 while( index < tmp.length() )
2b5f62a0 432 {
eb6fa4b4
MB
433 size_t plus = tmp.find( '+', index );
434 size_t minus = tmp.find( '-', index );
435
436 // neither '+' nor '-', add <Key>
437 if( plus == wxString::npos && minus == wxString::npos )
2b5f62a0 438 {
eb6fa4b4
MB
439 strcat( buf, "<Key>" );
440 strcat( buf, tmp.c_str() + index );
441
442 return buf;
2b5f62a0 443 }
eb6fa4b4
MB
444
445 // OK: npos is big and positive
446 size_t sep = wxMin( plus, minus );
447 wxString mod = tmp.substr( index, sep - index );
448
449 // Ctrl -> Ctrl
450 // Shift -> Shift
451 // Alt -> Meta
452 if( mod == "Alt" )
453 mod = "Meta";
454
455 if( buf[0] )
456 strcat( buf, " " );
457
458 strcat( buf, mod.c_str() );
459
460 index = sep + 1;
2b5f62a0 461 }
eb6fa4b4
MB
462
463 return NULL;
2b5f62a0
VZ
464#endif
465}
466
467XmString wxFindAcceleratorText (const char *s)
468{
eb6fa4b4 469#if 1
355b4d3d 470 wxUnusedVar(s);
2b5f62a0
VZ
471 // VZ: this function returns incorrect keysym which completely breaks kbd
472 // handling
473 return NULL;
eb6fa4b4
MB
474#else
475 // The accelerator text is after the \t char.
476 s = strchr( s, '\t' );
2b5f62a0 477
eb6fa4b4
MB
478 if( !s ) return NULL;
479
480 return wxStringToXmString( s + 1 ); // skip TAB!
2b5f62a0
VZ
481#endif
482}
483
2b5f62a0 484// Change a widget's foreground and background colours.
2b5f62a0
VZ
485void wxDoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour)
486{
a1b806b9 487 if (!foregroundColour.IsOk())
105fbe1f
MB
488 return;
489
2b5f62a0
VZ
490 // When should we specify the foreground, if it's calculated
491 // by wxComputeColours?
492 // Solution: say we start with the default (computed) foreground colour.
493 // If we call SetForegroundColour explicitly for a control or window,
494 // then the foreground is changed.
495 // Therefore SetBackgroundColour computes the foreground colour, and
496 // SetForegroundColour changes the foreground colour. The ordering is
497 // important.
498
499 XtVaSetValues ((Widget) widget,
500 XmNforeground, foregroundColour.AllocColour(XtDisplay((Widget) widget)),
501 NULL);
502}
503
f516d986 504void wxDoChangeBackgroundColour(WXWidget widget, const wxColour& backgroundColour, bool changeArmColour)
2b5f62a0 505{
a1b806b9 506 if (!backgroundColour.IsOk())
105fbe1f
MB
507 return;
508
2b5f62a0 509 wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
d3b9f782 510 NULL);
2b5f62a0
VZ
511
512 XtVaSetValues ((Widget) widget,
513 XmNbackground, g_itemColors[wxBACK_INDEX].pixel,
514 XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel,
515 XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel,
516 XmNforeground, g_itemColors[wxFORE_INDEX].pixel,
517 NULL);
518
519 if (changeArmColour)
520 XtVaSetValues ((Widget) widget,
521 XmNarmColor, g_itemColors[wxSELE_INDEX].pixel,
522 NULL);
523}
524
fbfb8bcc 525extern void wxDoChangeFont(WXWidget widget, const wxFont& font)
e1aae528 526{
101b4778
MB
527 // Lesstif 0.87 hangs here, but 0.93 does not; MBN: sometimes it does
528#if !wxCHECK_LESSTIF() // || wxCHECK_LESSTIF_VERSION( 0, 93 )
e1aae528 529 Widget w = (Widget)widget;
e1aae528 530 XtVaSetValues( w,
73608949 531 wxFont::GetFontTag(), font.GetFontTypeC( XtDisplay(w) ),
e1aae528 532 NULL );
355b4d3d
WS
533#else
534 wxUnusedVar(widget);
535 wxUnusedVar(font);
e1aae528
MB
536#endif
537
538}
539
e1aae528
MB
540wxString wxXmStringToString( const XmString& xmString )
541{
542 char *txt;
543 if( XmStringGetLtoR( xmString, XmSTRING_DEFAULT_CHARSET, &txt ) )
544 {
545 wxString str(txt);
546 XtFree (txt);
547 return str;
548 }
549
550 return wxEmptyString;
551}
552
3e2d47e1
MB
553XmString wxStringToXmString( const char* str )
554{
555 return XmStringCreateLtoR((char *)str, XmSTRING_DEFAULT_CHARSET);
556}
aae0472b
MB
557
558// ----------------------------------------------------------------------------
559// wxBitmap utility functions
560// ----------------------------------------------------------------------------
561
562// Creates a bitmap with transparent areas drawn in
563// the given colour.
fbfb8bcc 564wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, const wxColour& colour)
aae0472b
MB
565{
566 wxBitmap newBitmap(bitmap.GetWidth(),
567 bitmap.GetHeight(),
568 bitmap.GetDepth());
569 wxMemoryDC destDC;
570 wxMemoryDC srcDC;
571
f536319d 572 srcDC.SelectObjectAsSource(bitmap);
aae0472b
MB
573 destDC.SelectObject(newBitmap);
574
575 wxBrush brush(colour, wxSOLID);
aae0472b
MB
576 destDC.SetBackground(brush);
577 destDC.Clear();
578 destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(),
ea76a6a5 579 &srcDC, 0, 0, wxCOPY, true);
aae0472b
MB
580
581 return newBitmap;
582}
6769d0cb
MB
583
584// ----------------------------------------------------------------------------
585// Miscellaneous functions
586// ----------------------------------------------------------------------------
587
588WXWidget wxCreateBorderWidget( WXWidget parent, long style )
589{
590 Widget borderWidget = (Widget)NULL, parentWidget = (Widget)parent;
591
592 if (style & wxSIMPLE_BORDER)
593 {
594 borderWidget = XtVaCreateManagedWidget
595 (
596 "simpleBorder",
597 xmFrameWidgetClass, parentWidget,
598 XmNshadowType, XmSHADOW_ETCHED_IN,
599 XmNshadowThickness, 1,
600 NULL
601 );
602 }
cce69fec 603 else if ((style & wxSUNKEN_BORDER) || (style & wxBORDER_THEME))
6769d0cb
MB
604 {
605 borderWidget = XtVaCreateManagedWidget
606 (
607 "sunkenBorder",
608 xmFrameWidgetClass, parentWidget,
609 XmNshadowType, XmSHADOW_IN,
610 NULL
611 );
612 }
613 else if (style & wxRAISED_BORDER)
614 {
615 borderWidget = XtVaCreateManagedWidget
616 (
617 "raisedBorder",
618 xmFrameWidgetClass, parentWidget,
619 XmNshadowType, XmSHADOW_OUT,
620 NULL
621 );
622 }
623
624 return borderWidget;
625}