]> git.saurik.com Git - wxWidgets.git/blame - src/os2/utilsgui.cpp
don't try to access empty wxIconBundle in gtk_frame_realized_callback
[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// ---------------------------------------------------------------------------
61// helper functions for showing a "busy" cursor
62// ---------------------------------------------------------------------------
63
64HCURSOR gs_wxBusyCursor = 0; // new, busy cursor
65HCURSOR gs_wxBusyCursorOld = 0; // old cursor
66static int gs_wxBusyCursorCount = 0;
67
68// Set the cursor to the busy cursor for all windows
f516d986 69void wxBeginBusyCursor(const wxCursor* pCursor)
bd3b171d
SN
70{
71 if ( gs_wxBusyCursorCount++ == 0 )
72 {
73 gs_wxBusyCursor = (HCURSOR)pCursor->GetHCURSOR();
74 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursor);
75 }
76 //else: nothing to do, already set
77}
78
79// Restore cursor to normal
80void wxEndBusyCursor()
81{
82 wxCHECK_RET( gs_wxBusyCursorCount > 0
83 ,_T("no matching wxBeginBusyCursor() for wxEndBusyCursor()")
84 );
85
86 if (--gs_wxBusyCursorCount == 0)
87 {
88 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursorOld);
89 gs_wxBusyCursorOld = 0;
90 }
91}
92
c0badb70 93// true if we're between the above two calls
bd3b171d
SN
94bool wxIsBusy()
95{
96 return (gs_wxBusyCursorCount > 0);
97}
98
99// Check whether this window wants to process messages, e.g. Stop button
100// in long calculations.
c0badb70 101bool wxCheckForInterrupt( wxWindow* pWnd )
bd3b171d
SN
102{
103 if(pWnd)
104 {
c0badb70
WS
105 QMSG vMsg;
106 HAB hab = 0;
107 HWND hwndFilter = NULLHANDLE;
bd3b171d
SN
108
109 while(::WinPeekMsg(hab, &vMsg, hwndFilter, 0, 0, PM_REMOVE))
110 {
111 ::WinDispatchMsg(hab, &vMsg);
112 }
c0badb70 113 return true;//*** temporary?
bd3b171d
SN
114 }
115 else
116 {
117 wxFAIL_MSG(_T("pWnd==NULL !!!"));
c0badb70 118 return false;//*** temporary?
bd3b171d
SN
119 }
120}
121
122// ----------------------------------------------------------------------------
123// get display info
124// ----------------------------------------------------------------------------
125
126// See also the wxGetMousePosition in window.cpp
127// Deprecated: use wxPoint wxGetMousePosition() instead
128void wxGetMousePosition(
129 int* pX
130, int* pY
131)
132{
133 POINTL vPt;
134
135 ::WinQueryPointerPos(HWND_DESKTOP, &vPt);
136 *pX = vPt.x;
137 *pY = vPt.y;
138};
139
c0badb70 140// Return true if we have a colour display
bd3b171d
SN
141bool wxColourDisplay()
142{
143#if 0
144 HPS hpsScreen;
145 HDC hdcScreen;
146 LONG lColors;
147
148 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
149 hdcScreen = ::GpiQueryDevice(hpsScreen);
150 ::DevQueryCaps(hdcScreen, CAPS_COLORS, 1L, &lColors);
151 return(lColors > 1L);
152#else
153 // I don't see how the PM display could not be color. Besides, this
154 // was leaking DCs and PSs!!! MN
c0badb70 155 return true;
bd3b171d
SN
156#endif
157}
158
159// Returns depth of screen
160int wxDisplayDepth()
161{
162 HPS hpsScreen;
163 HDC hdcScreen;
164 LONG lPlanes;
165 LONG lBitsPerPixel;
166 static LONG nDepth = 0;
167
168 // The screen colordepth ain't gonna change. No reason to query
169 // it over and over!
170 if (!nDepth) {
171 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
172 hdcScreen = ::GpiQueryDevice(hpsScreen);
173 ::DevQueryCaps(hdcScreen, CAPS_COLOR_PLANES, 1L, &lPlanes);
174 ::DevQueryCaps(hdcScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitsPerPixel);
175
176 nDepth = (int)(lPlanes * lBitsPerPixel);
177 ::DevCloseDC(hdcScreen);
178 ::WinReleasePS(hpsScreen);
179 }
180 return (nDepth);
181}
182
183// Get size of display
184void wxDisplaySize(
185 int* pWidth
186, int* pHeight
187)
188{
189 HPS hpsScreen;
190 HDC hdcScreen;
191 static LONG lWidth = 0;
192 static LONG lHeight = 0;
193
194 // The screen size ain't gonna change either so just cache the values
195 if (!lWidth) {
196 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
197 hdcScreen = ::GpiQueryDevice(hpsScreen);
198 ::DevQueryCaps(hdcScreen, CAPS_WIDTH, 1L, &lWidth);
199 ::DevQueryCaps(hdcScreen, CAPS_HEIGHT, 1L, &lHeight);
200 ::DevCloseDC(hdcScreen);
201 ::WinReleasePS(hpsScreen);
202 }
42782237
SN
203 if (pWidth)
204 *pWidth = (int)lWidth;
205 if (pHeight)
206 *pHeight = (int)lHeight;
bd3b171d
SN
207}
208
209void wxDisplaySizeMM(
210 int* pWidth
211, int* pHeight
212)
213{
214 HPS hpsScreen;
215 HDC hdcScreen;
216
217 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
218 hdcScreen = ::GpiQueryDevice(hpsScreen);
219
220 if (pWidth)
221 ::DevQueryCaps( hdcScreen
222 ,CAPS_HORIZONTAL_RESOLUTION
223 ,1L
224 ,(PLONG)pWidth
225 );
226 if (pHeight)
227 ::DevQueryCaps( hdcScreen
228 ,CAPS_VERTICAL_RESOLUTION
229 ,1L
230 ,(PLONG)pHeight
231 );
232 ::DevCloseDC(hdcScreen);
233 ::WinReleasePS(hpsScreen);
234}
235
236void wxClientDisplayRect(int *x, int *y, int *width, int *height)
237{
238 // This is supposed to return desktop dimensions minus any window
239 // manager panels, menus, taskbars, etc. If there is a way to do that
240 // for this platform please fix this function, otherwise it defaults
241 // to the entire desktop.
242 if (x) *x = 0;
243 if (y) *y = 0;
244 wxDisplaySize(width, height);
245}
246
8329e6c7
SN
247void wxGUIAppTraits::InitializeGui(unsigned long &ulHab)
248{
249 ulHab = ::WinInitialize(0);
250}
251
252void wxGUIAppTraits::TerminateGui(unsigned long ulHab)
253{
254 ::WinTerminate(ulHab);
255}
256
930a9efa 257wxPortId wxGUIAppTraits::GetToolkitVersion(int *verMaj, int *verMin) const
621ccd8a 258{
930a9efa
SN
259 // How to get version of PM ? I guess, just reusing the OS version is OK.
260 (void) wxGetOsVersion(verMaj, verMin);
8bb6b2c0 261 return wxPORT_OS2;
621ccd8a
SN
262}
263
8bb6b2c0 264
bd3b171d
SN
265// ---------------------------------------------------------------------------
266// window information functions
267// ---------------------------------------------------------------------------
268
521bf4ff 269wxString WXDLLEXPORT wxGetWindowText( WXHWND hWnd )
bd3b171d 270{
521bf4ff 271 wxString vStr;
bd3b171d 272
2461cfa0
SN
273 if ( hWnd )
274 {
521bf4ff
WS
275 long lLen = ::WinQueryWindowTextLength((HWND)hWnd) + 1;
276 ::WinQueryWindowText((HWND)hWnd, lLen, (PSZ)(wxChar*)wxStringBuffer(vStr, lLen));
2461cfa0 277 }
bd3b171d
SN
278
279 return vStr;
280}
281
521bf4ff 282wxString WXDLLEXPORT wxGetWindowClass( WXHWND hWnd )
bd3b171d 283{
521bf4ff 284 wxString vStr;
2461cfa0 285 if ( hWnd )
bd3b171d 286 {
521bf4ff
WS
287 int nLen = 256; // some starting value
288
289 for ( ;; )
290 {
291 int nCount = ::WinQueryClassName((HWND)hWnd, nLen, (PSZ)(wxChar*)wxStringBuffer(vStr, nLen));
292
293 if (nCount == nLen )
294 {
295 // the class name might have been truncated, retry with larger
296 // buffer
297 nLen *= 2;
298 }
299 else
300 {
301 break;
302 }
bd3b171d
SN
303 }
304 }
305 return vStr;
306}
307
308WXWORD WXDLLEXPORT wxGetWindowId(
309 WXHWND hWnd
310)
311{
312 return ::WinQueryWindowUShort((HWND)hWnd, QWS_ID);
313}
314
315void wxDrawBorder(
316 HPS hPS
317, RECTL& rRect
318, WXDWORD dwStyle
319)
320{
321 POINTL vPoint[2];
322
323 vPoint[0].x = rRect.xLeft;
324 vPoint[0].y = rRect.yBottom;
325 ::GpiMove(hPS, &vPoint[0]);
326 if (dwStyle & wxSIMPLE_BORDER ||
327 dwStyle & wxSTATIC_BORDER)
328 {
329 vPoint[1].x = rRect.xRight - 1;
330 vPoint[1].y = rRect.yTop - 1;
331 ::GpiBox( hPS
332 ,DRO_OUTLINE
333 ,&vPoint[1]
334 ,0L
335 ,0L
336 );
337 }
338 if (dwStyle & wxSUNKEN_BORDER)
339 {
340 LINEBUNDLE vLineBundle;
341
342 vLineBundle.lColor = 0x00FFFFFF; // WHITE
343 vLineBundle.usMixMode = FM_OVERPAINT;
344 vLineBundle.fxWidth = 2;
345 vLineBundle.lGeomWidth = 2;
346 vLineBundle.usType = LINETYPE_SOLID;
347 vLineBundle.usEnd = 0;
348 vLineBundle.usJoin = 0;
349 ::GpiSetAttrs( hPS
350 ,PRIM_LINE
351 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
352 ,0L
353 ,&vLineBundle
354 );
355 vPoint[1].x = rRect.xRight - 1;
356 vPoint[1].y = rRect.yTop - 1;
357 ::GpiBox( hPS
358 ,DRO_OUTLINE
359 ,&vPoint[1]
360 ,0L
361 ,0L
362 );
363 vPoint[0].x = rRect.xLeft + 1;
364 vPoint[0].y = rRect.yBottom + 1;
365 ::GpiMove(hPS, &vPoint[0]);
366 vPoint[1].x = rRect.xRight - 2;
367 vPoint[1].y = rRect.yTop - 2;
368 ::GpiBox( hPS
369 ,DRO_OUTLINE
370 ,&vPoint[1]
371 ,0L
372 ,0L
373 );
374
375 vLineBundle.lColor = 0x00000000; // BLACK
376 vLineBundle.usMixMode = FM_OVERPAINT;
377 vLineBundle.fxWidth = 2;
378 vLineBundle.lGeomWidth = 2;
379 vLineBundle.usType = LINETYPE_SOLID;
380 vLineBundle.usEnd = 0;
381 vLineBundle.usJoin = 0;
382 ::GpiSetAttrs( hPS
383 ,PRIM_LINE
384 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
385 ,0L
386 ,&vLineBundle
387 );
388 vPoint[0].x = rRect.xLeft + 2;
389 vPoint[0].y = rRect.yBottom + 2;
390 ::GpiMove(hPS, &vPoint[0]);
391 vPoint[1].x = rRect.xLeft + 2;
392 vPoint[1].y = rRect.yTop - 3;
393 ::GpiLine(hPS, &vPoint[1]);
394 vPoint[1].x = rRect.xRight - 3;
395 vPoint[1].y = rRect.yTop - 3;
396 ::GpiLine(hPS, &vPoint[1]);
397
398 vPoint[0].x = rRect.xLeft + 3;
399 vPoint[0].y = rRect.yBottom + 3;
400 ::GpiMove(hPS, &vPoint[0]);
401 vPoint[1].x = rRect.xLeft + 3;
402 vPoint[1].y = rRect.yTop - 4;
403 ::GpiLine(hPS, &vPoint[1]);
404 vPoint[1].x = rRect.xRight - 4;
405 vPoint[1].y = rRect.yTop - 4;
406 ::GpiLine(hPS, &vPoint[1]);
407 }
408 if (dwStyle & wxDOUBLE_BORDER)
409 {
410 LINEBUNDLE vLineBundle;
411
412 vLineBundle.lColor = 0x00FFFFFF; // WHITE
413 vLineBundle.usMixMode = FM_OVERPAINT;
414 vLineBundle.fxWidth = 2;
415 vLineBundle.lGeomWidth = 2;
416 vLineBundle.usType = LINETYPE_SOLID;
417 vLineBundle.usEnd = 0;
418 vLineBundle.usJoin = 0;
419 ::GpiSetAttrs( hPS
420 ,PRIM_LINE
421 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
422 ,0L
423 ,&vLineBundle
424 );
425 vPoint[1].x = rRect.xRight - 1;
426 vPoint[1].y = rRect.yTop - 1;
427 ::GpiBox( hPS
428 ,DRO_OUTLINE
429 ,&vPoint[1]
430 ,0L
431 ,0L
432 );
433 vLineBundle.lColor = 0x00000000; // WHITE
434 vLineBundle.usMixMode = FM_OVERPAINT;
435 vLineBundle.fxWidth = 2;
436 vLineBundle.lGeomWidth = 2;
437 vLineBundle.usType = LINETYPE_SOLID;
438 vLineBundle.usEnd = 0;
439 vLineBundle.usJoin = 0;
440 ::GpiSetAttrs( hPS
441 ,PRIM_LINE
442 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
443 ,0L
444 ,&vLineBundle
445 );
446 vPoint[0].x = rRect.xLeft + 2;
447 vPoint[0].y = rRect.yBottom + 2;
448 ::GpiMove(hPS, &vPoint[0]);
449 vPoint[1].x = rRect.xRight - 2;
450 vPoint[1].y = rRect.yTop - 2;
451 ::GpiBox( hPS
452 ,DRO_OUTLINE
453 ,&vPoint[1]
454 ,0L
455 ,0L
456 );
457 vLineBundle.lColor = 0x00FFFFFF; // BLACK
458 vLineBundle.usMixMode = FM_OVERPAINT;
459 vLineBundle.fxWidth = 2;
460 vLineBundle.lGeomWidth = 2;
461 vLineBundle.usType = LINETYPE_SOLID;
462 vLineBundle.usEnd = 0;
463 vLineBundle.usJoin = 0;
464 ::GpiSetAttrs( hPS
465 ,PRIM_LINE
466 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
467 ,0L
468 ,&vLineBundle
469 );
470 vPoint[0].x = rRect.xLeft + 3;
471 vPoint[0].y = rRect.yBottom + 3;
472 ::GpiMove(hPS, &vPoint[0]);
473 vPoint[1].x = rRect.xRight - 3;
474 vPoint[1].y = rRect.yTop - 3;
475 ::GpiBox( hPS
476 ,DRO_OUTLINE
477 ,&vPoint[1]
478 ,0L
479 ,0L
480 );
481 }
482 if (dwStyle & wxRAISED_BORDER)
483 {
484 LINEBUNDLE vLineBundle;
485
486 vLineBundle.lColor = 0x00000000; // BLACK
487 vLineBundle.usMixMode = FM_OVERPAINT;
488 vLineBundle.fxWidth = 2;
489 vLineBundle.lGeomWidth = 2;
490 vLineBundle.usType = LINETYPE_SOLID;
491 vLineBundle.usEnd = 0;
492 vLineBundle.usJoin = 0;
493 ::GpiSetAttrs( hPS
494 ,PRIM_LINE
495 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
496 ,0L
497 ,&vLineBundle
498 );
499 vPoint[1].x = rRect.xRight - 1;
500 vPoint[1].y = rRect.yTop - 1;
501 ::GpiBox( hPS
502 ,DRO_OUTLINE
503 ,&vPoint[1]
504 ,0L
505 ,0L
506 );
507 vPoint[0].x = rRect.xLeft + 1;
508 vPoint[0].y = rRect.yBottom + 1;
509 ::GpiMove(hPS, &vPoint[0]);
510 vPoint[1].x = rRect.xRight - 2;
511 vPoint[1].y = rRect.yTop - 2;
512 ::GpiBox( hPS
513 ,DRO_OUTLINE
514 ,&vPoint[1]
515 ,0L
516 ,0L
517 );
518
519 vLineBundle.lColor = 0x00FFFFFF; // WHITE
520 vLineBundle.usMixMode = FM_OVERPAINT;
521 vLineBundle.fxWidth = 2;
522 vLineBundle.lGeomWidth = 2;
523 vLineBundle.usType = LINETYPE_SOLID;
524 vLineBundle.usEnd = 0;
525 vLineBundle.usJoin = 0;
526 ::GpiSetAttrs( hPS
527 ,PRIM_LINE
528 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
529 ,0L
530 ,&vLineBundle
531 );
532 vPoint[0].x = rRect.xLeft + 2;
533 vPoint[0].y = rRect.yBottom + 2;
534 ::GpiMove(hPS, &vPoint[0]);
535 vPoint[1].x = rRect.xLeft + 2;
536 vPoint[1].y = rRect.yTop - 3;
537 ::GpiLine(hPS, &vPoint[1]);
538 vPoint[1].x = rRect.xRight - 3;
539 vPoint[1].y = rRect.yTop - 3;
540 ::GpiLine(hPS, &vPoint[1]);
541
542 vPoint[0].x = rRect.xLeft + 3;
543 vPoint[0].y = rRect.yBottom + 3;
544 ::GpiMove(hPS, &vPoint[0]);
545 vPoint[1].x = rRect.xLeft + 3;
546 vPoint[1].y = rRect.yTop - 4;
547 ::GpiLine(hPS, &vPoint[1]);
548 vPoint[1].x = rRect.xRight - 4;
549 vPoint[1].y = rRect.yTop - 4;
550 ::GpiLine(hPS, &vPoint[1]);
551 }
552} // end of wxDrawBorder
553
554void wxOS2SetFont(
555 HWND hWnd
556, const wxFont& rFont
557)
558{
559 char zFont[128];
560 char zFacename[30];
561 char zWeight[30];
562 char zStyle[30];
563
564 if (hWnd == NULLHANDLE)
565 return;
566
567 //
568 // The fonts available for Presentation Params are just a few
569 // outline fonts, the rest are available to the GPI, so we must
570 // map the families to one of these three
571 //
572 switch(rFont.GetFamily())
573 {
574 case wxSCRIPT:
575 strcpy(zFacename, "Script");
576 break;
577
578 case wxDECORATIVE:
579 strcpy(zFacename, "WarpSans");
580 break;
581
582 case wxROMAN:
583 strcpy(zFacename,"Times New Roman");
584 break;
585
586 case wxTELETYPE:
587 strcpy(zFacename, "Courier New");
588 break;
589
590 case wxMODERN:
591 strcpy(zFacename, "Courier New");
592 break;
593
594 case wxDEFAULT:
595 default:
596 case wxSWISS:
597 strcpy(zFacename, "Helvetica");
598 break;
599 }
600
601 switch(rFont.GetWeight())
602 {
603 default:
604 case wxNORMAL:
605 case wxLIGHT:
606 zWeight[0] = '\0';
607 break;
608
609 case wxBOLD:
610 case wxFONTWEIGHT_MAX:
611 strcpy(zWeight, "Bold");
612 break;
613 }
614
615 switch(rFont.GetStyle())
616 {
617 case wxITALIC:
618 case wxSLANT:
619 strcpy(zStyle, "Italic");
620 break;
621
622 default:
623 zStyle[0] = '\0';
624 break;
625 }
626 sprintf(zFont, "%d.%s", rFont.GetPointSize(), zFacename);
627 if (zWeight[0] != '\0')
628 {
629 strcat(zFont, " ");
630 strcat(zFont, zWeight);
631 }
632 if (zStyle[0] != '\0')
633 {
634 strcat(zFont, " ");
635 strcat(zFont, zStyle);
636 }
637 ::WinSetPresParam(hWnd, PP_FONTNAMESIZE, strlen(zFont) + 1, (PVOID)zFont);
638} // end of wxOS2SetFont
639
640// ---------------------------------------------------------------------------
641// Helper for taking a regular bitmap and giving it a disabled look
642// ---------------------------------------------------------------------------
643wxBitmap wxDisableBitmap(
644 const wxBitmap& rBmp
645, long lColor
646)
647{
648 wxMask* pMask = rBmp.GetMask();
649
650 if (!pMask)
651 return(wxNullBitmap);
652
653 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
654 SIZEL vSize = {0, 0};
655 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
656 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
657 BITMAPINFOHEADER2 vHeader;
658 BITMAPINFO2 vInfo;
659 ERRORID vError;
660 wxString sError;
661 HBITMAP hBitmap = (HBITMAP)rBmp.GetHBITMAP();
662 HBITMAP hOldBitmap = NULLHANDLE;
663 HBITMAP hOldMask = NULLHANDLE;
664 HBITMAP hMask = (HBITMAP)rBmp.GetMask()->GetMaskBitmap();
665 unsigned char* pucBits; // buffer that will contain the bitmap data
666 unsigned char* pucData; // pointer to use to traverse bitmap data
667 unsigned char* pucBitsMask; // buffer that will contain the mask data
668 unsigned char* pucDataMask; // pointer to use to traverse mask data
669 LONG lScans = 0L;
670 LONG lScansSet = 0L;
671 bool bpp16 = (wxDisplayDepth() == 16);
672
673 memset(&vHeader, '\0', 16);
674 vHeader.cbFix = 16;
675
676 memset(&vInfo, '\0', 16);
677 vInfo.cbFix = 16;
678 vInfo.cx = (ULONG)rBmp.GetWidth();
679 vInfo.cy = (ULONG)rBmp.GetHeight();
680 vInfo.cPlanes = 1;
681 vInfo.cBitCount = 24; // Set to desired count going in
682
683 //
684 // Create the buffers for data....all wxBitmaps are 24 bit internally
685 //
686 int nBytesPerLine = rBmp.GetWidth() * 3;
687 int nSizeDWORD = sizeof(DWORD);
688 int nLineBoundary = nBytesPerLine % nSizeDWORD;
689 int nPadding = 0;
690 int i;
691 int j;
692
693 //
d6922577 694 // Bitmap must be in a double-word aligned address so we may
bd3b171d
SN
695 // have some padding to worry about
696 //
697 if (nLineBoundary > 0)
698 {
699 nPadding = nSizeDWORD - nLineBoundary;
700 nBytesPerLine += nPadding;
701 }
702 pucBits = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
703 memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight()));
704 pucBitsMask = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
705 memset(pucBitsMask, '\0', (nBytesPerLine * rBmp.GetHeight()));
706
707 //
708 // Extract the bitmap and mask data
709 //
710 if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR)
711 {
712 vError = ::WinGetLastError(vHabmain);
713 sError = wxPMErrorToStr(vError);
714 }
715 ::GpiQueryBitmapInfoHeader(hBitmap, &vHeader);
716 vInfo.cBitCount = 24;
717 if ((lScans = ::GpiQueryBitmapBits( hPS
718 ,0L
719 ,(LONG)rBmp.GetHeight()
720 ,(PBYTE)pucBits
721 ,&vInfo
722 )) == GPI_ALTERROR)
723 {
724 vError = ::WinGetLastError(vHabmain);
725 sError = wxPMErrorToStr(vError);
726 }
727 if ((hOldMask = ::GpiSetBitmap(hPS, hMask)) == HBM_ERROR)
728 {
729 vError = ::WinGetLastError(vHabmain);
730 sError = wxPMErrorToStr(vError);
731 }
732 ::GpiQueryBitmapInfoHeader(hMask, &vHeader);
733 vInfo.cBitCount = 24;
734 if ((lScans = ::GpiQueryBitmapBits( hPS
735 ,0L
736 ,(LONG)rBmp.GetHeight()
737 ,(PBYTE)pucBitsMask
738 ,&vInfo
739 )) == GPI_ALTERROR)
740 {
741 vError = ::WinGetLastError(vHabmain);
742 sError = wxPMErrorToStr(vError);
743 }
744 if (( hMask = ::GpiSetBitmap(hPS, hOldMask)) == HBM_ERROR)
745 {
746 vError = ::WinGetLastError(vHabmain);
747 sError = wxPMErrorToStr(vError);
748 }
749 pucData = pucBits;
750 pucDataMask = pucBitsMask;
751
752 //
753 // Get the mask value
754 //
755 for (i = 0; i < rBmp.GetHeight(); i++)
756 {
757 for (j = 0; j < rBmp.GetWidth(); j++)
758 {
759 // Byte 1
760 if (bpp16 && *pucDataMask == 0xF8) // 16 bit display gobblygook
761 {
762 *pucData = 0x7F;
763 pucData++;
764 }
765 else if (*pucDataMask == 0xFF) // set to grey
766 {
767 *pucData = 0x7F;
768 pucData++;
769 }
770 else
771 {
772 *pucData = ((unsigned char)(lColor >> 16));
773 pucData++;
774 }
775
776 // Byte 2
777 if (bpp16 && *(pucDataMask + 1) == 0xFC) // 16 bit display gobblygook
778 {
779 *pucData = 0x7F;
780 pucData++;
781 }
782 else if (*(pucDataMask + 1) == 0xFF) // set to grey
783 {
784 *pucData = 0x7F;
785 pucData++;
786 }
787 else
788 {
789 *pucData = ((unsigned char)(lColor >> 8));
790 pucData++;
791 }
792
793 // Byte 3
794 if (bpp16 && *(pucDataMask + 2) == 0xF8) // 16 bit display gobblygook
795 {
796 *pucData = 0x7F;
797 pucData++;
798 }
799 else if (*(pucDataMask + 2) == 0xFF) // set to grey
800 {
801 *pucData = 0x7F;
802 pucData++;
803 }
804 else
805 {
806 *pucData = ((unsigned char)lColor);
807 pucData++;
808 }
809 pucDataMask += 3;
810 }
811 for (j = 0; j < nPadding; j++)
812 {
813 pucData++;
814 pucDataMask++;
815 }
816 }
817
818 //
819 // Create a new bitmap and set the modified bits
820 //
821 wxBitmap vNewBmp( rBmp.GetWidth()
822 ,rBmp.GetHeight()
823 ,24
824 );
825 HBITMAP hNewBmp = (HBITMAP)vNewBmp.GetHBITMAP();
826
827 if ((hOldBitmap = ::GpiSetBitmap(hPS, hNewBmp)) == HBM_ERROR)
828 {
829 vError = ::WinGetLastError(vHabmain);
830 sError = wxPMErrorToStr(vError);
831 }
832 if ((lScansSet = ::GpiSetBitmapBits( hPS
833 ,0L
834 ,(LONG)rBmp.GetHeight()
835 ,(PBYTE)pucBits
836 ,&vInfo
837 )) == GPI_ALTERROR)
838
839 {
840 vError = ::WinGetLastError(vHabmain);
841 sError = wxPMErrorToStr(vError);
842 }
843 wxMask* pNewMask;
844
845 pNewMask = new wxMask(pMask->GetMaskBitmap());
846 vNewBmp.SetMask(pNewMask);
847 free(pucBits);
848 ::GpiSetBitmap(hPS, NULLHANDLE);
849 ::GpiDestroyPS(hPS);
850 ::DevCloseDC(hDC);
851 if (vNewBmp.Ok())
852 return(vNewBmp);
853 return(wxNullBitmap);
854} // end of wxDisableBitmap
855
856COLORREF wxColourToRGB(
857 const wxColour& rColor
858)
859{
860 return(OS2RGB(rColor.Red(), rColor.Green(), rColor.Blue()));
861} // end of wxColourToRGB