]> git.saurik.com Git - wxWidgets.git/blob - src/os2/utilsgui.cpp
Warning fix.
[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 // Reading and writing resources (eg WIN.INI, .Xdefaults)
61 #if wxUSE_RESOURCES
62 bool wxWriteResource( const wxString& rSection,
63                       const wxString& rEntry,
64                       const wxString& rValue,
65                       const wxString& rFile )
66 {
67     HAB  hab = 0;
68     HINI hIni = 0;
69
70     if (!rFile.empty())
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                                        ));
88     return false;
89 }
90
91 bool 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
108 bool 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
125 bool wxWriteResource( const wxString& rSection,
126                       const wxString& rEntry,
127                       int lValue,
128                       const wxString& rFile )
129 {
130     wxChar zBuf[50];
131
132     wxSprintf(zBuf, "%d", lValue);
133     return wxWriteResource( rSection, rEntry, zBuf, rFile );
134 }
135
136 bool wxGetResource( const wxString& rSection,
137                     const wxString& rEntry,
138                     wxChar** ppValue,
139                     const wxString& rFile )
140 {
141     HAB    hab = 0;
142     HINI   hIni = 0;
143     wxChar zDefunkt[] = _T("$$default");
144     char   zBuf[1000];
145
146     if (!rFile.empty())
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)
159                 return false;
160             if (n == 0L || wxStrcmp(zBuf, zDefunkt) == 0)
161                 return false;
162             zBuf[n-1] = '\0';
163         }
164         else
165             return false;
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)
177             return false;
178         if (n == 0L || wxStrcmp(zBuf, zDefunkt) == 0)
179             return false;
180         zBuf[n-1] = '\0';
181     }
182     strcpy((char*)*ppValue, zBuf);
183     return true;
184 }
185
186 bool wxGetResource( const wxString& rSection,
187                     const wxString& rEntry,
188                     float* pValue,
189                     const wxString& rFile )
190 {
191     wxChar* zStr = NULL;
192
193     zStr = new wxChar[1000];
194     bool bSucc = wxGetResource( rSection, rEntry, (wxChar **)&zStr, rFile );
195
196     if (bSucc)
197     {
198         *pValue = (float)wxStrtod(zStr, NULL);
199     }
200
201     delete[] zStr;
202     return bSucc;
203 }
204
205 bool wxGetResource( const wxString& rSection,
206                     const wxString& rEntry,
207                     long* pValue,
208                     const wxString& rFile )
209 {
210     wxChar* zStr = NULL;
211
212     zStr = new wxChar[1000];
213     bool bSucc = wxGetResource( rSection, rEntry, (wxChar **)&zStr, rFile );
214
215     if (bSucc)
216     {
217         *pValue = wxStrtol(zStr, NULL, 10);
218     }
219
220     delete[] zStr;
221     return bSucc;
222 }
223
224 bool wxGetResource( const wxString& rSection,
225                     const wxString& rEntry,
226                     int* pValue,
227                     const wxString& rFile )
228 {
229     wxChar* zStr = NULL;
230
231     zStr = new wxChar[1000];
232     bool bSucc = wxGetResource( rSection, rEntry, (wxChar **)&zStr, rFile );
233
234     if (bSucc)
235     {
236         *pValue = (int)wxStrtol(zStr, NULL, 10);
237     }
238
239     delete[] zStr;
240     return bSucc;
241 }
242 #endif // wxUSE_RESOURCES
243
244 // ---------------------------------------------------------------------------
245 // helper functions for showing a "busy" cursor
246 // ---------------------------------------------------------------------------
247
248 HCURSOR gs_wxBusyCursor = 0;     // new, busy cursor
249 HCURSOR gs_wxBusyCursorOld = 0;  // old cursor
250 static int gs_wxBusyCursorCount = 0;
251
252 // Set the cursor to the busy cursor for all windows
253 void wxBeginBusyCursor(const wxCursor* pCursor)
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
264 void 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
277 // true if we're between the above two calls
278 bool 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.
285 bool wxCheckForInterrupt( wxWindow* pWnd )
286 {
287     if(pWnd)
288     {
289         QMSG vMsg;
290         HAB  hab = 0;
291         HWND hwndFilter = NULLHANDLE;
292
293         while(::WinPeekMsg(hab, &vMsg, hwndFilter, 0, 0, PM_REMOVE))
294         {
295             ::WinDispatchMsg(hab, &vMsg);
296         }
297         return true;//*** temporary?
298     }
299     else
300     {
301         wxFAIL_MSG(_T("pWnd==NULL !!!"));
302         return false;//*** temporary?
303     }
304 }
305
306 // ----------------------------------------------------------------------------
307 // get display info
308 // ----------------------------------------------------------------------------
309
310 // See also the wxGetMousePosition in window.cpp
311 // Deprecated: use wxPoint wxGetMousePosition() instead
312 void 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
324 // Return true if we have a colour display
325 bool 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
339     return true;
340 #endif
341 }
342
343 // Returns depth of screen
344 int 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
368 void 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     }
387     if (pWidth)
388         *pWidth = (int)lWidth;
389     if (pHeight)
390         *pHeight = (int)lHeight;
391 }
392
393 void 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
420 void 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
431 void wxGUIAppTraits::InitializeGui(unsigned long &ulHab)
432 {
433     ulHab = ::WinInitialize(0);
434 }
435
436 void wxGUIAppTraits::TerminateGui(unsigned long ulHab)
437 {
438     ::WinTerminate(ulHab);
439 }
440
441 wxPortId wxGUIAppTraits::GetToolkitVersion(int *verMaj, int *verMin) const
442 {
443     // How to get version of PM ? I guess, just reusing the OS version is OK.
444     (void) wxGetOsVersion(verMaj, verMin);
445     return wxPORT_OS2;
446 }
447
448
449 // ---------------------------------------------------------------------------
450 // window information functions
451 // ---------------------------------------------------------------------------
452
453 wxString WXDLLEXPORT wxGetWindowText( WXHWND hWnd )
454 {
455     wxString vStr;
456
457     if ( hWnd )
458     {
459         long lLen = ::WinQueryWindowTextLength((HWND)hWnd) + 1;
460         ::WinQueryWindowText((HWND)hWnd, lLen, (PSZ)(wxChar*)wxStringBuffer(vStr, lLen));
461     }
462
463     return vStr;
464 }
465
466 wxString WXDLLEXPORT wxGetWindowClass( WXHWND hWnd )
467 {
468     wxString vStr;
469     if ( hWnd )
470     {
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         }
487         }
488     }
489     return vStr;
490 }
491
492 WXWORD WXDLLEXPORT wxGetWindowId(
493   WXHWND                            hWnd
494 )
495 {
496     return ::WinQueryWindowUShort((HWND)hWnd, QWS_ID);
497 }
498
499 void 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
738 void 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 // ---------------------------------------------------------------------------
827 wxBitmap 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     //
878     // Bitmap must be in a double-word aligned address so we may
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
1040 COLORREF wxColourToRGB(
1041   const wxColour&                   rColor
1042 )
1043 {
1044     return(OS2RGB(rColor.Red(), rColor.Green(), rColor.Blue()));
1045 } // end of wxColourToRGB