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