Files
wxWidgets/src/motif/utils.cpp
Vadim Zeitlin 3f66f6a5b3 Remove all lines containing cvs/svn "$Id$" keyword.
This keyword is not expanded by Git which means it's not replaced with the
correct revision value in the releases made using git-based scripts and it's
confusing to have lines with unexpanded "$Id$" in the released files. As
expanding them with Git is not that simple (it could be done with git archive
and export-subst attribute) and there are not many benefits in having them in
the first place, just remove all these lines.

If nothing else, this will make an eventual transition to Git simpler.

Closes #14487.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2013-07-26 16:02:46 +00:00

714 lines
20 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: src/motif/utils.cpp
// Purpose: Various utilities
// Author: Julian Smart
// Modified by:
// Created: 17/09/98
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#include "wx/utils.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/dcmemory.h"
#include "wx/bitmap.h"
#endif
#include "wx/apptrait.h"
#include "wx/evtloop.h"
#include "wx/private/eventloopsourcesmanager.h"
#include "wx/motif/private/timer.h"
#include <string.h>
#if (defined(__SUNCC__) || defined(__CLCC__))
#include <sysent.h>
#endif
#ifdef __VMS__
#pragma message disable nosimpint
#endif
#include <Xm/Xm.h>
#include <Xm/Frame.h>
#include "wx/motif/private.h"
#include "X11/Xutil.h"
#ifdef __VMS__
#pragma message enable nosimpint
#endif
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// async event processing
// ----------------------------------------------------------------------------
// Consume all events until no more left
void wxFlushEvents(WXDisplay* wxdisplay)
{
Display *display = (Display*)wxdisplay;
wxEventLoop evtLoop;
XSync (display, False);
while (evtLoop.Pending())
{
XFlush (display);
evtLoop.Dispatch();
}
}
#if wxUSE_EVENTLOOP_SOURCE
extern "C"
{
static
void
wxMotifInputHandler(XtPointer data,
int* WXUNUSED(fd),
XtInputId* WXUNUSED(inputId))
{
wxEventLoopSourceHandler * const
handler = static_cast<wxEventLoopSourceHandler *>(data);
handler->OnReadWaiting();
}
}
// This class exists just to call XtRemoveInput() in its dtor, the real work of
// dispatching events on the file descriptor to the handler is done by
// wxMotifInputHandler callback above.
class wxMotifEventLoopSource : public wxEventLoopSource
{
public:
wxMotifEventLoopSource(XtInputId inputId,
wxEventLoopSourceHandler *handler,
int flags)
: wxEventLoopSource(handler, flags),
m_inputId(inputId)
{
}
virtual ~wxMotifEventLoopSource()
{
XtRemoveInput(m_inputId);
}
private:
const XtInputId m_inputId;
wxDECLARE_NO_COPY_CLASS(wxMotifEventLoopSource);
};
class wxMotifEventLoopSourcesManager : public wxEventLoopSourcesManagerBase
{
public:
wxEventLoopSource *
AddSourceForFD(int fd, wxEventLoopSourceHandler* handler, int flags)
{
wxCHECK_MSG( wxTheApp, NULL, "Must create wxTheApp first" );
// The XtInputXXXMask values cannot be combined (hence "Mask" is a
// complete misnomer), and supporting those would make the code more
// complicated and we don't need them for now.
wxCHECK_MSG( !(flags & (wxEVENT_SOURCE_OUTPUT |
wxEVENT_SOURCE_EXCEPTION)),
NULL,
"Monitoring FDs for output/errors not supported" );
wxCHECK_MSG( flags & wxEVENT_SOURCE_INPUT,
NULL,
"Should be monitoring for input" );
XtInputId inputId = XtAppAddInput
(
(XtAppContext) wxTheApp->GetAppContext(),
fd,
(XtPointer) XtInputReadMask,
wxMotifInputHandler,
handler
);
if ( inputId < 0 )
return 0;
return new wxMotifEventLoopSource(inputId, handler, flags);
}
};
wxEventLoopSourcesManagerBase* wxGUIAppTraits::GetEventLoopSourcesManager()
{
static wxMotifEventLoopSourcesManager s_eventLoopSourcesManager;
return &s_eventLoopSourcesManager;
}
#endif // wxUSE_EVENTLOOP_SOURCE
// ----------------------------------------------------------------------------
// misc
// ----------------------------------------------------------------------------
// Emit a beeeeeep
void wxBell()
{
// Use current setting for the bell
XBell (wxGlobalDisplay(), 0);
}
wxPortId wxGUIAppTraits::GetToolkitVersion(int *verMaj, int *verMin) const
{
// XmVERSION and XmREVISION are defined in Xm/Xm.h
if ( verMaj )
*verMaj = XmVERSION;
if ( verMin )
*verMin = XmREVISION;
return wxPORT_MOTIF;
}
wxEventLoopBase* wxGUIAppTraits::CreateEventLoop()
{
return new wxEventLoop;
}
wxTimerImpl* wxGUIAppTraits::CreateTimerImpl(wxTimer* timer)
{
return new wxMotifTimerImpl(timer);
}
// ----------------------------------------------------------------------------
// display info
// ----------------------------------------------------------------------------
void wxGetMousePosition( int* x, int* y )
{
#if wxUSE_NANOX
// TODO
*x = 0;
*y = 0;
#else
XMotionEvent xev;
Window root, child;
XQueryPointer(wxGlobalDisplay(),
DefaultRootWindow(wxGlobalDisplay()),
&root, &child,
&(xev.x_root), &(xev.y_root),
&(xev.x), &(xev.y),
&(xev.state));
*x = xev.x_root;
*y = xev.y_root;
#endif
}
// Return true if we have a colour display
bool wxColourDisplay()
{
return wxDisplayDepth() > 1;
}
// Returns depth of screen
int wxDisplayDepth()
{
Display *dpy = wxGlobalDisplay();
return DefaultDepth (dpy, DefaultScreen (dpy));
}
// Get size of display
void wxDisplaySize(int *width, int *height)
{
Display *dpy = wxGlobalDisplay();
if ( width )
*width = DisplayWidth (dpy, DefaultScreen (dpy));
if ( height )
*height = DisplayHeight (dpy, DefaultScreen (dpy));
}
void wxDisplaySizeMM(int *width, int *height)
{
Display *dpy = wxGlobalDisplay();
if ( width )
*width = DisplayWidthMM(dpy, DefaultScreen (dpy));
if ( height )
*height = DisplayHeightMM(dpy, DefaultScreen (dpy));
}
// Configurable display in wxX11 and wxMotif
static WXDisplay *gs_currentDisplay = NULL;
static wxString gs_displayName;
WXDisplay *wxGetDisplay()
{
if (gs_currentDisplay)
return gs_currentDisplay;
else if (wxTheApp)
return wxTheApp->GetInitialDisplay();
return NULL;
}
bool wxSetDisplay(const wxString& display_name)
{
gs_displayName = display_name;
if ( display_name.empty() )
{
gs_currentDisplay = NULL;
return true;
}
else
{
Cardinal argc = 0;
Display *display = XtOpenDisplay((XtAppContext) wxTheApp->GetAppContext(),
display_name.c_str(),
wxTheApp->GetAppName().c_str(),
wxTheApp->GetClassName().c_str(),
NULL,
#if XtSpecificationRelease < 5
0, &argc,
#else
0, (int *)&argc,
#endif
NULL);
if (display)
{
gs_currentDisplay = (WXDisplay*) display;
return true;
}
else
return false;
}
}
wxString wxGetDisplayName()
{
return gs_displayName;
}
wxWindow* wxFindWindowAtPoint(const wxPoint& pt)
{
return wxGenericFindWindowAtPoint(pt);
}
// ----------------------------------------------------------------------------
// Some colour manipulation routines
// ----------------------------------------------------------------------------
void wxHSVToXColor(wxHSV *hsv,XColor *rgb)
{
int h = hsv->h;
int s = hsv->s;
int v = hsv->v;
int r = 0, g = 0, b = 0;
int i, f;
int p, q, t;
s = (s * wxMAX_RGB) / wxMAX_SV;
v = (v * wxMAX_RGB) / wxMAX_SV;
if (h == 360) h = 0;
if (s == 0) { h = 0; r = g = b = v; }
i = h / 60;
f = h % 60;
p = v * (wxMAX_RGB - s) / wxMAX_RGB;
q = v * (wxMAX_RGB - s * f / 60) / wxMAX_RGB;
t = v * (wxMAX_RGB - s * (60 - f) / 60) / wxMAX_RGB;
switch (i)
{
case 0: r = v, g = t, b = p; break;
case 1: r = q, g = v, b = p; break;
case 2: r = p, g = v, b = t; break;
case 3: r = p, g = q, b = v; break;
case 4: r = t, g = p, b = v; break;
case 5: r = v, g = p, b = q; break;
}
rgb->red = (unsigned short)(r << 8);
rgb->green = (unsigned short)(g << 8);
rgb->blue = (unsigned short)(b << 8);
}
void wxXColorToHSV(wxHSV *hsv,XColor *rgb)
{
int r = rgb->red >> 8;
int g = rgb->green >> 8;
int b = rgb->blue >> 8;
int maxv = wxMax3(r, g, b);
int minv = wxMin3(r, g, b);
int h = 0, s, v;
v = maxv;
if (maxv) s = (maxv - minv) * wxMAX_RGB / maxv;
else s = 0;
if (s == 0) h = 0;
else
{
int rc, gc, bc, hex = 0;
rc = (maxv - r) * wxMAX_RGB / (maxv - minv);
gc = (maxv - g) * wxMAX_RGB / (maxv - minv);
bc = (maxv - b) * wxMAX_RGB / (maxv - minv);
if (r == maxv) { h = bc - gc, hex = 0; }
else if (g == maxv) { h = rc - bc, hex = 2; }
else if (b == maxv) { h = gc - rc, hex = 4; }
h = hex * 60 + (h * 60 / wxMAX_RGB);
if (h < 0) h += 360;
}
hsv->h = h;
hsv->s = (s * wxMAX_SV) / wxMAX_RGB;
hsv->v = (v * wxMAX_SV) / wxMAX_RGB;
}
void wxAllocNearestColor(Display *d,Colormap cmp,XColor *xc)
{
#if !wxUSE_NANOX
int llp;
int screen = DefaultScreen(d);
int num_colors = DisplayCells(d,screen);
XColor *color_defs = new XColor[num_colors];
for(llp = 0;llp < num_colors;llp++) color_defs[llp].pixel = llp;
XQueryColors(d,cmp,color_defs,num_colors);
wxHSV hsv_defs, hsv;
wxXColorToHSV(&hsv,xc);
int diff, min_diff = 0, pixel = 0;
for(llp = 0;llp < num_colors;llp++)
{
wxXColorToHSV(&hsv_defs,&color_defs[llp]);
diff = wxSIGN(wxH_WEIGHT * (hsv.h - hsv_defs.h)) +
wxSIGN(wxS_WEIGHT * (hsv.s - hsv_defs.s)) +
wxSIGN(wxV_WEIGHT * (hsv.v - hsv_defs.v));
if (llp == 0) min_diff = diff;
if (min_diff > diff) { min_diff = diff; pixel = llp; }
if (min_diff == 0) break;
}
xc -> red = color_defs[pixel].red;
xc -> green = color_defs[pixel].green;
xc -> blue = color_defs[pixel].blue;
xc -> flags = DoRed | DoGreen | DoBlue;
/* FIXME, TODO
if (!XAllocColor(d,cmp,xc))
cout << "wxAllocNearestColor : Warning : Cannot find nearest color !\n";
*/
delete[] color_defs;
#endif
}
void wxAllocColor(Display *d,Colormap cmp,XColor *xc)
{
if (!XAllocColor(d,cmp,xc))
{
// cout << "wxAllocColor : Warning : cannot allocate color, attempt find nearest !\n";
wxAllocNearestColor(d,cmp,xc);
}
}
wxString wxGetXEventName(XEvent& event)
{
#if wxUSE_NANOX
wxString str(wxT("(some event)"));
return str;
#else
int type = event.xany.type;
static char* event_name[] = {
wxMOTIF_STR(""), wxMOTIF_STR("unknown(-)"), // 0-1
wxMOTIF_STR("KeyPress"), wxMOTIF_STR("KeyRelease"), wxMOTIF_STR("ButtonPress"), wxMOTIF_STR("ButtonRelease"), // 2-5
wxMOTIF_STR("MotionNotify"), wxMOTIF_STR("EnterNotify"), wxMOTIF_STR("LeaveNotify"), wxMOTIF_STR("FocusIn"), // 6-9
wxMOTIF_STR("FocusOut"), wxMOTIF_STR("KeymapNotify"), wxMOTIF_STR("Expose"), wxMOTIF_STR("GraphicsExpose"), // 10-13
wxMOTIF_STR("NoExpose"), wxMOTIF_STR("VisibilityNotify"), wxMOTIF_STR("CreateNotify"), // 14-16
wxMOTIF_STR("DestroyNotify"), wxMOTIF_STR("UnmapNotify"), wxMOTIF_STR("MapNotify"), wxMOTIF_STR("MapRequest"),// 17-20
wxMOTIF_STR("ReparentNotify"), wxMOTIF_STR("ConfigureNotify"), wxMOTIF_STR("ConfigureRequest"), // 21-23
wxMOTIF_STR("GravityNotify"), wxMOTIF_STR("ResizeRequest"), wxMOTIF_STR("CirculateNotify"), // 24-26
wxMOTIF_STR("CirculateRequest"), wxMOTIF_STR("PropertyNotify"), wxMOTIF_STR("SelectionClear"), // 27-29
wxMOTIF_STR("SelectionRequest"), wxMOTIF_STR("SelectionNotify"), wxMOTIF_STR("ColormapNotify"), // 30-32
wxMOTIF_STR("ClientMessage"), wxMOTIF_STR("MappingNotify"), // 33-34
wxMOTIF_STR("unknown(+)")}; // 35
type = wxMin(35, type); type = wxMax(1, type);
wxString str(event_name[type]);
return str;
#endif
}
// ----------------------------------------------------------------------------
// accelerators
// ----------------------------------------------------------------------------
// Find the letter corresponding to the mnemonic, for Motif
char wxFindMnemonic (const char *s)
{
char mnem = 0;
int len = strlen (s);
int i;
for (i = 0; i < len; i++)
{
if (s[i] == '&')
{
// Carefully handle &&
if ((i + 1) <= len && s[i + 1] == '&')
i++;
else
{
mnem = s[i + 1];
break;
}
}
}
return mnem;
}
char* wxFindAccelerator( const char *s )
{
#if 1
wxUnusedVar(s);
// VZ: this function returns incorrect keysym which completely breaks kbd
// handling
return NULL;
#else
// The accelerator text is after the \t char.
s = strchr( s, '\t' );
if( !s ) return NULL;
/*
Now we need to format it as X standard:
input output
F7 --> <Key>F7
Ctrl+N --> Ctrl<Key>N
Alt+k --> Meta<Key>k
Ctrl+Shift+A --> Ctrl Shift<Key>A
and handle Ctrl-N & similia
*/
static char buf[256];
buf[0] = '\0';
wxString tmp = s + 1; // skip TAB
size_t index = 0;
while( index < tmp.length() )
{
size_t plus = tmp.find( '+', index );
size_t minus = tmp.find( '-', index );
// neither '+' nor '-', add <Key>
if( plus == wxString::npos && minus == wxString::npos )
{
strcat( buf, "<Key>" );
strcat( buf, tmp.c_str() + index );
return buf;
}
// OK: npos is big and positive
size_t sep = wxMin( plus, minus );
wxString mod = tmp.substr( index, sep - index );
// Ctrl -> Ctrl
// Shift -> Shift
// Alt -> Meta
if( mod == "Alt" )
mod = "Meta";
if( buf[0] )
strcat( buf, " " );
strcat( buf, mod.c_str() );
index = sep + 1;
}
return NULL;
#endif
}
XmString wxFindAcceleratorText (const char *s)
{
#if 1
wxUnusedVar(s);
// VZ: this function returns incorrect keysym which completely breaks kbd
// handling
return NULL;
#else
// The accelerator text is after the \t char.
s = strchr( s, '\t' );
if( !s ) return NULL;
return wxStringToXmString( s + 1 ); // skip TAB!
#endif
}
// Change a widget's foreground and background colours.
void wxDoChangeForegroundColour(WXWidget widget, wxColour& foregroundColour)
{
if (!foregroundColour.IsOk())
return;
// When should we specify the foreground, if it's calculated
// by wxComputeColours?
// Solution: say we start with the default (computed) foreground colour.
// If we call SetForegroundColour explicitly for a control or window,
// then the foreground is changed.
// Therefore SetBackgroundColour computes the foreground colour, and
// SetForegroundColour changes the foreground colour. The ordering is
// important.
XtVaSetValues ((Widget) widget,
XmNforeground, foregroundColour.AllocColour(XtDisplay((Widget) widget)),
NULL);
}
void wxDoChangeBackgroundColour(WXWidget widget, const wxColour& backgroundColour, bool changeArmColour)
{
if (!backgroundColour.IsOk())
return;
wxComputeColours (XtDisplay((Widget) widget), & backgroundColour,
NULL);
XtVaSetValues ((Widget) widget,
XmNbackground, g_itemColors[wxBACK_INDEX].pixel,
XmNtopShadowColor, g_itemColors[wxTOPS_INDEX].pixel,
XmNbottomShadowColor, g_itemColors[wxBOTS_INDEX].pixel,
XmNforeground, g_itemColors[wxFORE_INDEX].pixel,
NULL);
if (changeArmColour)
XtVaSetValues ((Widget) widget,
XmNarmColor, g_itemColors[wxSELE_INDEX].pixel,
NULL);
}
extern void wxDoChangeFont(WXWidget widget, const wxFont& font)
{
// Lesstif 0.87 hangs here, but 0.93 does not; MBN: sometimes it does
#if !wxCHECK_LESSTIF() // || wxCHECK_LESSTIF_VERSION( 0, 93 )
Widget w = (Widget)widget;
XtVaSetValues( w,
wxFont::GetFontTag(), font.GetFontTypeC( XtDisplay(w) ),
NULL );
#else
wxUnusedVar(widget);
wxUnusedVar(font);
#endif
}
wxString wxXmStringToString( const XmString& xmString )
{
char *txt;
if( XmStringGetLtoR( xmString, XmSTRING_DEFAULT_CHARSET, &txt ) )
{
wxString str(txt);
XtFree (txt);
return str;
}
return wxEmptyString;
}
XmString wxStringToXmString( const char* str )
{
return XmStringCreateLtoR((char *)str, XmSTRING_DEFAULT_CHARSET);
}
// ----------------------------------------------------------------------------
// wxBitmap utility functions
// ----------------------------------------------------------------------------
// Creates a bitmap with transparent areas drawn in
// the given colour.
wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, const wxColour& colour)
{
wxBitmap newBitmap(bitmap.GetWidth(),
bitmap.GetHeight(),
bitmap.GetDepth());
wxMemoryDC destDC;
wxMemoryDC srcDC;
srcDC.SelectObjectAsSource(bitmap);
destDC.SelectObject(newBitmap);
wxBrush brush(colour, wxSOLID);
destDC.SetBackground(brush);
destDC.Clear();
destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(),
&srcDC, 0, 0, wxCOPY, true);
return newBitmap;
}
// ----------------------------------------------------------------------------
// Miscellaneous functions
// ----------------------------------------------------------------------------
WXWidget wxCreateBorderWidget( WXWidget parent, long style )
{
Widget borderWidget = (Widget)NULL, parentWidget = (Widget)parent;
if (style & wxSIMPLE_BORDER)
{
borderWidget = XtVaCreateManagedWidget
(
"simpleBorder",
xmFrameWidgetClass, parentWidget,
XmNshadowType, XmSHADOW_ETCHED_IN,
XmNshadowThickness, 1,
NULL
);
}
else if ((style & wxSUNKEN_BORDER) || (style & wxBORDER_THEME))
{
borderWidget = XtVaCreateManagedWidget
(
"sunkenBorder",
xmFrameWidgetClass, parentWidget,
XmNshadowType, XmSHADOW_IN,
NULL
);
}
else if (style & wxRAISED_BORDER)
{
borderWidget = XtVaCreateManagedWidget
(
"raisedBorder",
xmFrameWidgetClass, parentWidget,
XmNshadowType, XmSHADOW_OUT,
NULL
);
}
return borderWidget;
}