]> git.saurik.com Git - wxWidgets.git/blob - src/os2/utilsgui.cpp
Bugfix (comparision vs. assignment).
[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 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // License: wxWindows licence
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
28 #include "wx/utils.h"
29 #include "wx/app.h"
30 #include "wx/cursor.h"
31 #include "wx/font.h"
32 #include "wx/timer.h"
33 #endif //WX_PRECOMP
34
35 #include "wx/apptrait.h"
36
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.
48 static bool inTimer = false;
49
50 class wxSleepTimer: public wxTimer
51 {
52 public:
53 inline void Notify()
54 {
55 inTimer = false;
56 Stop();
57 }
58 };
59
60 // ---------------------------------------------------------------------------
61 // helper functions for showing a "busy" cursor
62 // ---------------------------------------------------------------------------
63
64 HCURSOR gs_wxBusyCursor = 0; // new, busy cursor
65 HCURSOR gs_wxBusyCursorOld = 0; // old cursor
66 static int gs_wxBusyCursorCount = 0;
67
68 // Set the cursor to the busy cursor for all windows
69 void wxBeginBusyCursor(const wxCursor* pCursor)
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
80 void 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
93 // true if we're between the above two calls
94 bool 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.
101 bool wxCheckForInterrupt( wxWindow* pWnd )
102 {
103 if(pWnd)
104 {
105 QMSG vMsg;
106 HAB hab = 0;
107 HWND hwndFilter = NULLHANDLE;
108
109 while(::WinPeekMsg(hab, &vMsg, hwndFilter, 0, 0, PM_REMOVE))
110 {
111 ::WinDispatchMsg(hab, &vMsg);
112 }
113 return true;//*** temporary?
114 }
115 else
116 {
117 wxFAIL_MSG(_T("pWnd==NULL !!!"));
118 return false;//*** temporary?
119 }
120 }
121
122 // ----------------------------------------------------------------------------
123 // get display info
124 // ----------------------------------------------------------------------------
125
126 // See also the wxGetMousePosition in window.cpp
127 // Deprecated: use wxPoint wxGetMousePosition() instead
128 void 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
140 // Return true if we have a colour display
141 bool 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
155 return true;
156 #endif
157 }
158
159 // Returns depth of screen
160 int 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
184 void 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 }
203 if (pWidth)
204 *pWidth = (int)lWidth;
205 if (pHeight)
206 *pHeight = (int)lHeight;
207 }
208
209 void 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
236 void 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
247 void wxGUIAppTraits::InitializeGui(unsigned long &ulHab)
248 {
249 ulHab = ::WinInitialize(0);
250 }
251
252 void wxGUIAppTraits::TerminateGui(unsigned long ulHab)
253 {
254 ::WinTerminate(ulHab);
255 }
256
257 wxPortId wxGUIAppTraits::GetToolkitVersion(int *verMaj, int *verMin) const
258 {
259 // How to get version of PM ? I guess, just reusing the OS version is OK.
260 (void) wxGetOsVersion(verMaj, verMin);
261 return wxPORT_OS2;
262 }
263
264
265 // ---------------------------------------------------------------------------
266 // window information functions
267 // ---------------------------------------------------------------------------
268
269 wxString WXDLLEXPORT wxGetWindowText( WXHWND hWnd )
270 {
271 wxString vStr;
272
273 if ( hWnd )
274 {
275 long lLen = ::WinQueryWindowTextLength((HWND)hWnd) + 1;
276 ::WinQueryWindowText((HWND)hWnd, lLen, (PSZ)(wxChar*)wxStringBuffer(vStr, lLen));
277 }
278
279 return vStr;
280 }
281
282 wxString WXDLLEXPORT wxGetWindowClass( WXHWND hWnd )
283 {
284 wxString vStr;
285 if ( hWnd )
286 {
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 }
303 }
304 }
305 return vStr;
306 }
307
308 WXWORD WXDLLEXPORT wxGetWindowId(
309 WXHWND hWnd
310 )
311 {
312 return ::WinQueryWindowUShort((HWND)hWnd, QWS_ID);
313 }
314
315 void 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
554 void 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 // ---------------------------------------------------------------------------
643 wxBitmap 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 //
694 // Bitmap must be in a double-word aligned address so we may
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
856 COLORREF wxColourToRGB(
857 const wxColour& rColor
858 )
859 {
860 return(OS2RGB(rColor.Red(), rColor.Green(), rColor.Blue()));
861 } // end of wxColourToRGB