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