]> git.saurik.com Git - wxWidgets.git/blame - src/os2/utilsgui.cpp
Added extra hit test style for more accurate reporting
[wxWidgets.git] / src / os2 / utilsgui.cpp
CommitLineData
bd3b171d 1///////////////////////////////////////////////////////////////////////////////
521bf4ff 2// Name: src/os2/utilsgui.cpp
bd3b171d
SN
3// Purpose: Various utility functions only available in GUI
4// Author: David Webster
5// Modified by:
6// Created: 20.08.2003 (extracted from os2/utils.cpp)
7// RCS-ID: $Id$
8// Copyright: (c) David Webster
65571936 9// License: wxWindows licence
bd3b171d
SN
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// for compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
bd3b171d
SN
28 #include "wx/utils.h"
29 #include "wx/app.h"
30 #include "wx/cursor.h"
ec9f5895 31 #include "wx/font.h"
c0badb70 32 #include "wx/timer.h"
bd3b171d
SN
33#endif //WX_PRECOMP
34
ceb8f94a 35#include "wx/apptrait.h"
ceb8f94a 36
bd3b171d
SN
37#include "wx/os2/private.h" // includes <windows.h>
38
39// ============================================================================
40// implementation
41// ============================================================================
42
43// ----------------------------------------------------------------------------
44// functions to work with .INI files
45// ----------------------------------------------------------------------------
46
47// Sleep for nSecs seconds. Attempt a Windows implementation using timers.
c0badb70 48static bool inTimer = false;
bd3b171d
SN
49
50class wxSleepTimer: public wxTimer
51{
52public:
53 inline void Notify()
54 {
c0badb70 55 inTimer = false;
bd3b171d
SN
56 Stop();
57 }
58};
59
bd3b171d
SN
60// Reading and writing resources (eg WIN.INI, .Xdefaults)
61#if wxUSE_RESOURCES
c0badb70
WS
62bool wxWriteResource( const wxString& rSection,
63 const wxString& rEntry,
64 const wxString& rValue,
65 const wxString& rFile )
bd3b171d 66{
c0badb70
WS
67 HAB hab = 0;
68 HINI hIni = 0;
bd3b171d 69
521bf4ff 70 if (!rFile.empty())
bd3b171d
SN
71 {
72 hIni = ::PrfOpenProfile(hab, (PSZ)WXSTRINGCAST rFile);
73 if (hIni != 0L)
74 {
75 return (::PrfWriteProfileString( hIni
76 ,(PSZ)WXSTRINGCAST rSection
77 ,(PSZ)WXSTRINGCAST rEntry
78 ,(PSZ)WXSTRINGCAST rValue
79 ));
80 }
81 }
82 else
83 return (::PrfWriteProfileString( HINI_PROFILE
84 ,(PSZ)WXSTRINGCAST rSection
85 ,(PSZ)WXSTRINGCAST rEntry
86 ,(PSZ)WXSTRINGCAST rValue
87 ));
c0badb70 88 return false;
bd3b171d
SN
89}
90
91bool wxWriteResource(
92 const wxString& rSection
93, const wxString& rEntry
94, float fValue
95, const wxString& rFile
96)
97{
98 wxChar zBuf[50];
99
100 wxSprintf(zBuf, "%.4f", fValue);
101 return wxWriteResource( rSection
102 ,rEntry
103 ,zBuf
104 ,rFile
105 );
106}
107
108bool wxWriteResource(
109 const wxString& rSection
110, const wxString& rEntry
111, long lValue
112, const wxString& rFile
113)
114{
115 wxChar zBuf[50];
116
117 wxSprintf(zBuf, "%ld", lValue);
118 return wxWriteResource( rSection
119 ,rEntry
120 ,zBuf
121 ,rFile
122 );
123}
124
c0badb70
WS
125bool wxWriteResource( const wxString& rSection,
126 const wxString& rEntry,
127 int lValue,
128 const wxString& rFile )
bd3b171d 129{
c0badb70 130 wxChar zBuf[50];
bd3b171d
SN
131
132 wxSprintf(zBuf, "%d", lValue);
c0badb70 133 return wxWriteResource( rSection, rEntry, zBuf, rFile );
bd3b171d
SN
134}
135
c0badb70
WS
136bool wxGetResource( const wxString& rSection,
137 const wxString& rEntry,
138 wxChar** ppValue,
139 const wxString& rFile )
bd3b171d 140{
c0badb70
WS
141 HAB hab = 0;
142 HINI hIni = 0;
143 wxChar zDefunkt[] = _T("$$default");
144 char zBuf[1000];
bd3b171d 145
521bf4ff 146 if (!rFile.empty())
bd3b171d
SN
147 {
148 hIni = ::PrfOpenProfile(hab, (PSZ)WXSTRINGCAST rFile);
149 if (hIni != 0L)
150 {
151 ULONG n = ::PrfQueryProfileString( hIni
152 ,(PSZ)WXSTRINGCAST rSection
153 ,(PSZ)WXSTRINGCAST rEntry
154 ,(PSZ)zDefunkt
155 ,(PVOID)zBuf
156 ,1000
157 );
158 if (zBuf == NULL)
c0badb70 159 return false;
bd3b171d 160 if (n == 0L || wxStrcmp(zBuf, zDefunkt) == 0)
c0badb70 161 return false;
bd3b171d
SN
162 zBuf[n-1] = '\0';
163 }
164 else
c0badb70 165 return false;
bd3b171d
SN
166 }
167 else
168 {
169 ULONG n = ::PrfQueryProfileString( HINI_PROFILE
170 ,(PSZ)WXSTRINGCAST rSection
171 ,(PSZ)WXSTRINGCAST rEntry
172 ,(PSZ)zDefunkt
173 ,(PVOID)zBuf
174 ,1000
175 );
176 if (zBuf == NULL)
c0badb70 177 return false;
bd3b171d 178 if (n == 0L || wxStrcmp(zBuf, zDefunkt) == 0)
c0badb70 179 return false;
bd3b171d
SN
180 zBuf[n-1] = '\0';
181 }
182 strcpy((char*)*ppValue, zBuf);
c0badb70 183 return true;
bd3b171d
SN
184}
185
c0badb70
WS
186bool wxGetResource( const wxString& rSection,
187 const wxString& rEntry,
188 float* pValue,
189 const wxString& rFile )
bd3b171d 190{
c0badb70 191 wxChar* zStr = NULL;
bd3b171d
SN
192
193 zStr = new wxChar[1000];
c0badb70 194 bool bSucc = wxGetResource( rSection, rEntry, (wxChar **)&zStr, rFile );
bd3b171d
SN
195
196 if (bSucc)
197 {
198 *pValue = (float)wxStrtod(zStr, NULL);
bd3b171d 199 }
c0badb70
WS
200
201 delete[] zStr;
202 return bSucc;
bd3b171d
SN
203}
204
c0badb70
WS
205bool wxGetResource( const wxString& rSection,
206 const wxString& rEntry,
207 long* pValue,
208 const wxString& rFile )
bd3b171d 209{
c0badb70 210 wxChar* zStr = NULL;
bd3b171d
SN
211
212 zStr = new wxChar[1000];
c0badb70 213 bool bSucc = wxGetResource( rSection, rEntry, (wxChar **)&zStr, rFile );
bd3b171d
SN
214
215 if (bSucc)
216 {
217 *pValue = wxStrtol(zStr, NULL, 10);
bd3b171d 218 }
c0badb70
WS
219
220 delete[] zStr;
221 return bSucc;
bd3b171d
SN
222}
223
c0badb70
WS
224bool wxGetResource( const wxString& rSection,
225 const wxString& rEntry,
226 int* pValue,
227 const wxString& rFile )
bd3b171d 228{
c0badb70 229 wxChar* zStr = NULL;
bd3b171d
SN
230
231 zStr = new wxChar[1000];
c0badb70 232 bool bSucc = wxGetResource( rSection, rEntry, (wxChar **)&zStr, rFile );
bd3b171d
SN
233
234 if (bSucc)
235 {
236 *pValue = (int)wxStrtol(zStr, NULL, 10);
bd3b171d 237 }
c0badb70
WS
238
239 delete[] zStr;
240 return bSucc;
bd3b171d
SN
241}
242#endif // wxUSE_RESOURCES
243
244// ---------------------------------------------------------------------------
245// helper functions for showing a "busy" cursor
246// ---------------------------------------------------------------------------
247
248HCURSOR gs_wxBusyCursor = 0; // new, busy cursor
249HCURSOR gs_wxBusyCursorOld = 0; // old cursor
250static int gs_wxBusyCursorCount = 0;
251
252// Set the cursor to the busy cursor for all windows
f516d986 253void wxBeginBusyCursor(const wxCursor* pCursor)
bd3b171d
SN
254{
255 if ( gs_wxBusyCursorCount++ == 0 )
256 {
257 gs_wxBusyCursor = (HCURSOR)pCursor->GetHCURSOR();
258 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursor);
259 }
260 //else: nothing to do, already set
261}
262
263// Restore cursor to normal
264void wxEndBusyCursor()
265{
266 wxCHECK_RET( gs_wxBusyCursorCount > 0
267 ,_T("no matching wxBeginBusyCursor() for wxEndBusyCursor()")
268 );
269
270 if (--gs_wxBusyCursorCount == 0)
271 {
272 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursorOld);
273 gs_wxBusyCursorOld = 0;
274 }
275}
276
c0badb70 277// true if we're between the above two calls
bd3b171d
SN
278bool wxIsBusy()
279{
280 return (gs_wxBusyCursorCount > 0);
281}
282
283// Check whether this window wants to process messages, e.g. Stop button
284// in long calculations.
c0badb70 285bool wxCheckForInterrupt( wxWindow* pWnd )
bd3b171d
SN
286{
287 if(pWnd)
288 {
c0badb70
WS
289 QMSG vMsg;
290 HAB hab = 0;
291 HWND hwndFilter = NULLHANDLE;
bd3b171d
SN
292
293 while(::WinPeekMsg(hab, &vMsg, hwndFilter, 0, 0, PM_REMOVE))
294 {
295 ::WinDispatchMsg(hab, &vMsg);
296 }
c0badb70 297 return true;//*** temporary?
bd3b171d
SN
298 }
299 else
300 {
301 wxFAIL_MSG(_T("pWnd==NULL !!!"));
c0badb70 302 return false;//*** temporary?
bd3b171d
SN
303 }
304}
305
306// ----------------------------------------------------------------------------
307// get display info
308// ----------------------------------------------------------------------------
309
310// See also the wxGetMousePosition in window.cpp
311// Deprecated: use wxPoint wxGetMousePosition() instead
312void wxGetMousePosition(
313 int* pX
314, int* pY
315)
316{
317 POINTL vPt;
318
319 ::WinQueryPointerPos(HWND_DESKTOP, &vPt);
320 *pX = vPt.x;
321 *pY = vPt.y;
322};
323
c0badb70 324// Return true if we have a colour display
bd3b171d
SN
325bool wxColourDisplay()
326{
327#if 0
328 HPS hpsScreen;
329 HDC hdcScreen;
330 LONG lColors;
331
332 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
333 hdcScreen = ::GpiQueryDevice(hpsScreen);
334 ::DevQueryCaps(hdcScreen, CAPS_COLORS, 1L, &lColors);
335 return(lColors > 1L);
336#else
337 // I don't see how the PM display could not be color. Besides, this
338 // was leaking DCs and PSs!!! MN
c0badb70 339 return true;
bd3b171d
SN
340#endif
341}
342
343// Returns depth of screen
344int wxDisplayDepth()
345{
346 HPS hpsScreen;
347 HDC hdcScreen;
348 LONG lPlanes;
349 LONG lBitsPerPixel;
350 static LONG nDepth = 0;
351
352 // The screen colordepth ain't gonna change. No reason to query
353 // it over and over!
354 if (!nDepth) {
355 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
356 hdcScreen = ::GpiQueryDevice(hpsScreen);
357 ::DevQueryCaps(hdcScreen, CAPS_COLOR_PLANES, 1L, &lPlanes);
358 ::DevQueryCaps(hdcScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitsPerPixel);
359
360 nDepth = (int)(lPlanes * lBitsPerPixel);
361 ::DevCloseDC(hdcScreen);
362 ::WinReleasePS(hpsScreen);
363 }
364 return (nDepth);
365}
366
367// Get size of display
368void wxDisplaySize(
369 int* pWidth
370, int* pHeight
371)
372{
373 HPS hpsScreen;
374 HDC hdcScreen;
375 static LONG lWidth = 0;
376 static LONG lHeight = 0;
377
378 // The screen size ain't gonna change either so just cache the values
379 if (!lWidth) {
380 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
381 hdcScreen = ::GpiQueryDevice(hpsScreen);
382 ::DevQueryCaps(hdcScreen, CAPS_WIDTH, 1L, &lWidth);
383 ::DevQueryCaps(hdcScreen, CAPS_HEIGHT, 1L, &lHeight);
384 ::DevCloseDC(hdcScreen);
385 ::WinReleasePS(hpsScreen);
386 }
42782237
SN
387 if (pWidth)
388 *pWidth = (int)lWidth;
389 if (pHeight)
390 *pHeight = (int)lHeight;
bd3b171d
SN
391}
392
393void wxDisplaySizeMM(
394 int* pWidth
395, int* pHeight
396)
397{
398 HPS hpsScreen;
399 HDC hdcScreen;
400
401 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
402 hdcScreen = ::GpiQueryDevice(hpsScreen);
403
404 if (pWidth)
405 ::DevQueryCaps( hdcScreen
406 ,CAPS_HORIZONTAL_RESOLUTION
407 ,1L
408 ,(PLONG)pWidth
409 );
410 if (pHeight)
411 ::DevQueryCaps( hdcScreen
412 ,CAPS_VERTICAL_RESOLUTION
413 ,1L
414 ,(PLONG)pHeight
415 );
416 ::DevCloseDC(hdcScreen);
417 ::WinReleasePS(hpsScreen);
418}
419
420void wxClientDisplayRect(int *x, int *y, int *width, int *height)
421{
422 // This is supposed to return desktop dimensions minus any window
423 // manager panels, menus, taskbars, etc. If there is a way to do that
424 // for this platform please fix this function, otherwise it defaults
425 // to the entire desktop.
426 if (x) *x = 0;
427 if (y) *y = 0;
428 wxDisplaySize(width, height);
429}
430
8329e6c7
SN
431void wxGUIAppTraits::InitializeGui(unsigned long &ulHab)
432{
433 ulHab = ::WinInitialize(0);
434}
435
436void wxGUIAppTraits::TerminateGui(unsigned long ulHab)
437{
438 ::WinTerminate(ulHab);
439}
440
930a9efa 441wxPortId wxGUIAppTraits::GetToolkitVersion(int *verMaj, int *verMin) const
621ccd8a 442{
930a9efa
SN
443 // How to get version of PM ? I guess, just reusing the OS version is OK.
444 (void) wxGetOsVersion(verMaj, verMin);
8bb6b2c0 445 return wxPORT_OS2;
621ccd8a
SN
446}
447
8bb6b2c0 448
bd3b171d
SN
449// ---------------------------------------------------------------------------
450// window information functions
451// ---------------------------------------------------------------------------
452
521bf4ff 453wxString WXDLLEXPORT wxGetWindowText( WXHWND hWnd )
bd3b171d 454{
521bf4ff 455 wxString vStr;
bd3b171d 456
2461cfa0
SN
457 if ( hWnd )
458 {
521bf4ff
WS
459 long lLen = ::WinQueryWindowTextLength((HWND)hWnd) + 1;
460 ::WinQueryWindowText((HWND)hWnd, lLen, (PSZ)(wxChar*)wxStringBuffer(vStr, lLen));
2461cfa0 461 }
bd3b171d
SN
462
463 return vStr;
464}
465
521bf4ff 466wxString WXDLLEXPORT wxGetWindowClass( WXHWND hWnd )
bd3b171d 467{
521bf4ff 468 wxString vStr;
2461cfa0 469 if ( hWnd )
bd3b171d 470 {
521bf4ff
WS
471 int nLen = 256; // some starting value
472
473 for ( ;; )
474 {
475 int nCount = ::WinQueryClassName((HWND)hWnd, nLen, (PSZ)(wxChar*)wxStringBuffer(vStr, nLen));
476
477 if (nCount == nLen )
478 {
479 // the class name might have been truncated, retry with larger
480 // buffer
481 nLen *= 2;
482 }
483 else
484 {
485 break;
486 }
bd3b171d
SN
487 }
488 }
489 return vStr;
490}
491
492WXWORD WXDLLEXPORT wxGetWindowId(
493 WXHWND hWnd
494)
495{
496 return ::WinQueryWindowUShort((HWND)hWnd, QWS_ID);
497}
498
499void wxDrawBorder(
500 HPS hPS
501, RECTL& rRect
502, WXDWORD dwStyle
503)
504{
505 POINTL vPoint[2];
506
507 vPoint[0].x = rRect.xLeft;
508 vPoint[0].y = rRect.yBottom;
509 ::GpiMove(hPS, &vPoint[0]);
510 if (dwStyle & wxSIMPLE_BORDER ||
511 dwStyle & wxSTATIC_BORDER)
512 {
513 vPoint[1].x = rRect.xRight - 1;
514 vPoint[1].y = rRect.yTop - 1;
515 ::GpiBox( hPS
516 ,DRO_OUTLINE
517 ,&vPoint[1]
518 ,0L
519 ,0L
520 );
521 }
522 if (dwStyle & wxSUNKEN_BORDER)
523 {
524 LINEBUNDLE vLineBundle;
525
526 vLineBundle.lColor = 0x00FFFFFF; // WHITE
527 vLineBundle.usMixMode = FM_OVERPAINT;
528 vLineBundle.fxWidth = 2;
529 vLineBundle.lGeomWidth = 2;
530 vLineBundle.usType = LINETYPE_SOLID;
531 vLineBundle.usEnd = 0;
532 vLineBundle.usJoin = 0;
533 ::GpiSetAttrs( hPS
534 ,PRIM_LINE
535 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
536 ,0L
537 ,&vLineBundle
538 );
539 vPoint[1].x = rRect.xRight - 1;
540 vPoint[1].y = rRect.yTop - 1;
541 ::GpiBox( hPS
542 ,DRO_OUTLINE
543 ,&vPoint[1]
544 ,0L
545 ,0L
546 );
547 vPoint[0].x = rRect.xLeft + 1;
548 vPoint[0].y = rRect.yBottom + 1;
549 ::GpiMove(hPS, &vPoint[0]);
550 vPoint[1].x = rRect.xRight - 2;
551 vPoint[1].y = rRect.yTop - 2;
552 ::GpiBox( hPS
553 ,DRO_OUTLINE
554 ,&vPoint[1]
555 ,0L
556 ,0L
557 );
558
559 vLineBundle.lColor = 0x00000000; // BLACK
560 vLineBundle.usMixMode = FM_OVERPAINT;
561 vLineBundle.fxWidth = 2;
562 vLineBundle.lGeomWidth = 2;
563 vLineBundle.usType = LINETYPE_SOLID;
564 vLineBundle.usEnd = 0;
565 vLineBundle.usJoin = 0;
566 ::GpiSetAttrs( hPS
567 ,PRIM_LINE
568 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
569 ,0L
570 ,&vLineBundle
571 );
572 vPoint[0].x = rRect.xLeft + 2;
573 vPoint[0].y = rRect.yBottom + 2;
574 ::GpiMove(hPS, &vPoint[0]);
575 vPoint[1].x = rRect.xLeft + 2;
576 vPoint[1].y = rRect.yTop - 3;
577 ::GpiLine(hPS, &vPoint[1]);
578 vPoint[1].x = rRect.xRight - 3;
579 vPoint[1].y = rRect.yTop - 3;
580 ::GpiLine(hPS, &vPoint[1]);
581
582 vPoint[0].x = rRect.xLeft + 3;
583 vPoint[0].y = rRect.yBottom + 3;
584 ::GpiMove(hPS, &vPoint[0]);
585 vPoint[1].x = rRect.xLeft + 3;
586 vPoint[1].y = rRect.yTop - 4;
587 ::GpiLine(hPS, &vPoint[1]);
588 vPoint[1].x = rRect.xRight - 4;
589 vPoint[1].y = rRect.yTop - 4;
590 ::GpiLine(hPS, &vPoint[1]);
591 }
592 if (dwStyle & wxDOUBLE_BORDER)
593 {
594 LINEBUNDLE vLineBundle;
595
596 vLineBundle.lColor = 0x00FFFFFF; // WHITE
597 vLineBundle.usMixMode = FM_OVERPAINT;
598 vLineBundle.fxWidth = 2;
599 vLineBundle.lGeomWidth = 2;
600 vLineBundle.usType = LINETYPE_SOLID;
601 vLineBundle.usEnd = 0;
602 vLineBundle.usJoin = 0;
603 ::GpiSetAttrs( hPS
604 ,PRIM_LINE
605 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
606 ,0L
607 ,&vLineBundle
608 );
609 vPoint[1].x = rRect.xRight - 1;
610 vPoint[1].y = rRect.yTop - 1;
611 ::GpiBox( hPS
612 ,DRO_OUTLINE
613 ,&vPoint[1]
614 ,0L
615 ,0L
616 );
617 vLineBundle.lColor = 0x00000000; // WHITE
618 vLineBundle.usMixMode = FM_OVERPAINT;
619 vLineBundle.fxWidth = 2;
620 vLineBundle.lGeomWidth = 2;
621 vLineBundle.usType = LINETYPE_SOLID;
622 vLineBundle.usEnd = 0;
623 vLineBundle.usJoin = 0;
624 ::GpiSetAttrs( hPS
625 ,PRIM_LINE
626 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
627 ,0L
628 ,&vLineBundle
629 );
630 vPoint[0].x = rRect.xLeft + 2;
631 vPoint[0].y = rRect.yBottom + 2;
632 ::GpiMove(hPS, &vPoint[0]);
633 vPoint[1].x = rRect.xRight - 2;
634 vPoint[1].y = rRect.yTop - 2;
635 ::GpiBox( hPS
636 ,DRO_OUTLINE
637 ,&vPoint[1]
638 ,0L
639 ,0L
640 );
641 vLineBundle.lColor = 0x00FFFFFF; // BLACK
642 vLineBundle.usMixMode = FM_OVERPAINT;
643 vLineBundle.fxWidth = 2;
644 vLineBundle.lGeomWidth = 2;
645 vLineBundle.usType = LINETYPE_SOLID;
646 vLineBundle.usEnd = 0;
647 vLineBundle.usJoin = 0;
648 ::GpiSetAttrs( hPS
649 ,PRIM_LINE
650 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
651 ,0L
652 ,&vLineBundle
653 );
654 vPoint[0].x = rRect.xLeft + 3;
655 vPoint[0].y = rRect.yBottom + 3;
656 ::GpiMove(hPS, &vPoint[0]);
657 vPoint[1].x = rRect.xRight - 3;
658 vPoint[1].y = rRect.yTop - 3;
659 ::GpiBox( hPS
660 ,DRO_OUTLINE
661 ,&vPoint[1]
662 ,0L
663 ,0L
664 );
665 }
666 if (dwStyle & wxRAISED_BORDER)
667 {
668 LINEBUNDLE vLineBundle;
669
670 vLineBundle.lColor = 0x00000000; // BLACK
671 vLineBundle.usMixMode = FM_OVERPAINT;
672 vLineBundle.fxWidth = 2;
673 vLineBundle.lGeomWidth = 2;
674 vLineBundle.usType = LINETYPE_SOLID;
675 vLineBundle.usEnd = 0;
676 vLineBundle.usJoin = 0;
677 ::GpiSetAttrs( hPS
678 ,PRIM_LINE
679 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
680 ,0L
681 ,&vLineBundle
682 );
683 vPoint[1].x = rRect.xRight - 1;
684 vPoint[1].y = rRect.yTop - 1;
685 ::GpiBox( hPS
686 ,DRO_OUTLINE
687 ,&vPoint[1]
688 ,0L
689 ,0L
690 );
691 vPoint[0].x = rRect.xLeft + 1;
692 vPoint[0].y = rRect.yBottom + 1;
693 ::GpiMove(hPS, &vPoint[0]);
694 vPoint[1].x = rRect.xRight - 2;
695 vPoint[1].y = rRect.yTop - 2;
696 ::GpiBox( hPS
697 ,DRO_OUTLINE
698 ,&vPoint[1]
699 ,0L
700 ,0L
701 );
702
703 vLineBundle.lColor = 0x00FFFFFF; // WHITE
704 vLineBundle.usMixMode = FM_OVERPAINT;
705 vLineBundle.fxWidth = 2;
706 vLineBundle.lGeomWidth = 2;
707 vLineBundle.usType = LINETYPE_SOLID;
708 vLineBundle.usEnd = 0;
709 vLineBundle.usJoin = 0;
710 ::GpiSetAttrs( hPS
711 ,PRIM_LINE
712 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
713 ,0L
714 ,&vLineBundle
715 );
716 vPoint[0].x = rRect.xLeft + 2;
717 vPoint[0].y = rRect.yBottom + 2;
718 ::GpiMove(hPS, &vPoint[0]);
719 vPoint[1].x = rRect.xLeft + 2;
720 vPoint[1].y = rRect.yTop - 3;
721 ::GpiLine(hPS, &vPoint[1]);
722 vPoint[1].x = rRect.xRight - 3;
723 vPoint[1].y = rRect.yTop - 3;
724 ::GpiLine(hPS, &vPoint[1]);
725
726 vPoint[0].x = rRect.xLeft + 3;
727 vPoint[0].y = rRect.yBottom + 3;
728 ::GpiMove(hPS, &vPoint[0]);
729 vPoint[1].x = rRect.xLeft + 3;
730 vPoint[1].y = rRect.yTop - 4;
731 ::GpiLine(hPS, &vPoint[1]);
732 vPoint[1].x = rRect.xRight - 4;
733 vPoint[1].y = rRect.yTop - 4;
734 ::GpiLine(hPS, &vPoint[1]);
735 }
736} // end of wxDrawBorder
737
738void wxOS2SetFont(
739 HWND hWnd
740, const wxFont& rFont
741)
742{
743 char zFont[128];
744 char zFacename[30];
745 char zWeight[30];
746 char zStyle[30];
747
748 if (hWnd == NULLHANDLE)
749 return;
750
751 //
752 // The fonts available for Presentation Params are just a few
753 // outline fonts, the rest are available to the GPI, so we must
754 // map the families to one of these three
755 //
756 switch(rFont.GetFamily())
757 {
758 case wxSCRIPT:
759 strcpy(zFacename, "Script");
760 break;
761
762 case wxDECORATIVE:
763 strcpy(zFacename, "WarpSans");
764 break;
765
766 case wxROMAN:
767 strcpy(zFacename,"Times New Roman");
768 break;
769
770 case wxTELETYPE:
771 strcpy(zFacename, "Courier New");
772 break;
773
774 case wxMODERN:
775 strcpy(zFacename, "Courier New");
776 break;
777
778 case wxDEFAULT:
779 default:
780 case wxSWISS:
781 strcpy(zFacename, "Helvetica");
782 break;
783 }
784
785 switch(rFont.GetWeight())
786 {
787 default:
788 case wxNORMAL:
789 case wxLIGHT:
790 zWeight[0] = '\0';
791 break;
792
793 case wxBOLD:
794 case wxFONTWEIGHT_MAX:
795 strcpy(zWeight, "Bold");
796 break;
797 }
798
799 switch(rFont.GetStyle())
800 {
801 case wxITALIC:
802 case wxSLANT:
803 strcpy(zStyle, "Italic");
804 break;
805
806 default:
807 zStyle[0] = '\0';
808 break;
809 }
810 sprintf(zFont, "%d.%s", rFont.GetPointSize(), zFacename);
811 if (zWeight[0] != '\0')
812 {
813 strcat(zFont, " ");
814 strcat(zFont, zWeight);
815 }
816 if (zStyle[0] != '\0')
817 {
818 strcat(zFont, " ");
819 strcat(zFont, zStyle);
820 }
821 ::WinSetPresParam(hWnd, PP_FONTNAMESIZE, strlen(zFont) + 1, (PVOID)zFont);
822} // end of wxOS2SetFont
823
824// ---------------------------------------------------------------------------
825// Helper for taking a regular bitmap and giving it a disabled look
826// ---------------------------------------------------------------------------
827wxBitmap wxDisableBitmap(
828 const wxBitmap& rBmp
829, long lColor
830)
831{
832 wxMask* pMask = rBmp.GetMask();
833
834 if (!pMask)
835 return(wxNullBitmap);
836
837 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
838 SIZEL vSize = {0, 0};
839 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
840 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
841 BITMAPINFOHEADER2 vHeader;
842 BITMAPINFO2 vInfo;
843 ERRORID vError;
844 wxString sError;
845 HBITMAP hBitmap = (HBITMAP)rBmp.GetHBITMAP();
846 HBITMAP hOldBitmap = NULLHANDLE;
847 HBITMAP hOldMask = NULLHANDLE;
848 HBITMAP hMask = (HBITMAP)rBmp.GetMask()->GetMaskBitmap();
849 unsigned char* pucBits; // buffer that will contain the bitmap data
850 unsigned char* pucData; // pointer to use to traverse bitmap data
851 unsigned char* pucBitsMask; // buffer that will contain the mask data
852 unsigned char* pucDataMask; // pointer to use to traverse mask data
853 LONG lScans = 0L;
854 LONG lScansSet = 0L;
855 bool bpp16 = (wxDisplayDepth() == 16);
856
857 memset(&vHeader, '\0', 16);
858 vHeader.cbFix = 16;
859
860 memset(&vInfo, '\0', 16);
861 vInfo.cbFix = 16;
862 vInfo.cx = (ULONG)rBmp.GetWidth();
863 vInfo.cy = (ULONG)rBmp.GetHeight();
864 vInfo.cPlanes = 1;
865 vInfo.cBitCount = 24; // Set to desired count going in
866
867 //
868 // Create the buffers for data....all wxBitmaps are 24 bit internally
869 //
870 int nBytesPerLine = rBmp.GetWidth() * 3;
871 int nSizeDWORD = sizeof(DWORD);
872 int nLineBoundary = nBytesPerLine % nSizeDWORD;
873 int nPadding = 0;
874 int i;
875 int j;
876
877 //
d6922577 878 // Bitmap must be in a double-word aligned address so we may
bd3b171d
SN
879 // have some padding to worry about
880 //
881 if (nLineBoundary > 0)
882 {
883 nPadding = nSizeDWORD - nLineBoundary;
884 nBytesPerLine += nPadding;
885 }
886 pucBits = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
887 memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight()));
888 pucBitsMask = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
889 memset(pucBitsMask, '\0', (nBytesPerLine * rBmp.GetHeight()));
890
891 //
892 // Extract the bitmap and mask data
893 //
894 if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR)
895 {
896 vError = ::WinGetLastError(vHabmain);
897 sError = wxPMErrorToStr(vError);
898 }
899 ::GpiQueryBitmapInfoHeader(hBitmap, &vHeader);
900 vInfo.cBitCount = 24;
901 if ((lScans = ::GpiQueryBitmapBits( hPS
902 ,0L
903 ,(LONG)rBmp.GetHeight()
904 ,(PBYTE)pucBits
905 ,&vInfo
906 )) == GPI_ALTERROR)
907 {
908 vError = ::WinGetLastError(vHabmain);
909 sError = wxPMErrorToStr(vError);
910 }
911 if ((hOldMask = ::GpiSetBitmap(hPS, hMask)) == HBM_ERROR)
912 {
913 vError = ::WinGetLastError(vHabmain);
914 sError = wxPMErrorToStr(vError);
915 }
916 ::GpiQueryBitmapInfoHeader(hMask, &vHeader);
917 vInfo.cBitCount = 24;
918 if ((lScans = ::GpiQueryBitmapBits( hPS
919 ,0L
920 ,(LONG)rBmp.GetHeight()
921 ,(PBYTE)pucBitsMask
922 ,&vInfo
923 )) == GPI_ALTERROR)
924 {
925 vError = ::WinGetLastError(vHabmain);
926 sError = wxPMErrorToStr(vError);
927 }
928 if (( hMask = ::GpiSetBitmap(hPS, hOldMask)) == HBM_ERROR)
929 {
930 vError = ::WinGetLastError(vHabmain);
931 sError = wxPMErrorToStr(vError);
932 }
933 pucData = pucBits;
934 pucDataMask = pucBitsMask;
935
936 //
937 // Get the mask value
938 //
939 for (i = 0; i < rBmp.GetHeight(); i++)
940 {
941 for (j = 0; j < rBmp.GetWidth(); j++)
942 {
943 // Byte 1
944 if (bpp16 && *pucDataMask == 0xF8) // 16 bit display gobblygook
945 {
946 *pucData = 0x7F;
947 pucData++;
948 }
949 else if (*pucDataMask == 0xFF) // set to grey
950 {
951 *pucData = 0x7F;
952 pucData++;
953 }
954 else
955 {
956 *pucData = ((unsigned char)(lColor >> 16));
957 pucData++;
958 }
959
960 // Byte 2
961 if (bpp16 && *(pucDataMask + 1) == 0xFC) // 16 bit display gobblygook
962 {
963 *pucData = 0x7F;
964 pucData++;
965 }
966 else if (*(pucDataMask + 1) == 0xFF) // set to grey
967 {
968 *pucData = 0x7F;
969 pucData++;
970 }
971 else
972 {
973 *pucData = ((unsigned char)(lColor >> 8));
974 pucData++;
975 }
976
977 // Byte 3
978 if (bpp16 && *(pucDataMask + 2) == 0xF8) // 16 bit display gobblygook
979 {
980 *pucData = 0x7F;
981 pucData++;
982 }
983 else if (*(pucDataMask + 2) == 0xFF) // set to grey
984 {
985 *pucData = 0x7F;
986 pucData++;
987 }
988 else
989 {
990 *pucData = ((unsigned char)lColor);
991 pucData++;
992 }
993 pucDataMask += 3;
994 }
995 for (j = 0; j < nPadding; j++)
996 {
997 pucData++;
998 pucDataMask++;
999 }
1000 }
1001
1002 //
1003 // Create a new bitmap and set the modified bits
1004 //
1005 wxBitmap vNewBmp( rBmp.GetWidth()
1006 ,rBmp.GetHeight()
1007 ,24
1008 );
1009 HBITMAP hNewBmp = (HBITMAP)vNewBmp.GetHBITMAP();
1010
1011 if ((hOldBitmap = ::GpiSetBitmap(hPS, hNewBmp)) == HBM_ERROR)
1012 {
1013 vError = ::WinGetLastError(vHabmain);
1014 sError = wxPMErrorToStr(vError);
1015 }
1016 if ((lScansSet = ::GpiSetBitmapBits( hPS
1017 ,0L
1018 ,(LONG)rBmp.GetHeight()
1019 ,(PBYTE)pucBits
1020 ,&vInfo
1021 )) == GPI_ALTERROR)
1022
1023 {
1024 vError = ::WinGetLastError(vHabmain);
1025 sError = wxPMErrorToStr(vError);
1026 }
1027 wxMask* pNewMask;
1028
1029 pNewMask = new wxMask(pMask->GetMaskBitmap());
1030 vNewBmp.SetMask(pNewMask);
1031 free(pucBits);
1032 ::GpiSetBitmap(hPS, NULLHANDLE);
1033 ::GpiDestroyPS(hPS);
1034 ::DevCloseDC(hDC);
1035 if (vNewBmp.Ok())
1036 return(vNewBmp);
1037 return(wxNullBitmap);
1038} // end of wxDisableBitmap
1039
1040COLORREF wxColourToRGB(
1041 const wxColour& rColor
1042)
1043{
1044 return(OS2RGB(rColor.Red(), rColor.Green(), rColor.Blue()));
1045} // end of wxColourToRGB