]> git.saurik.com Git - wxWidgets.git/blame - src/os2/utilsgui.cpp
don't call SelectObject() twice in SetBrush() nor SetFont() neither
[wxWidgets.git] / src / os2 / utilsgui.cpp
CommitLineData
bd3b171d
SN
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
ceb8f94a
SN
34#include "wx/apptrait.h"
35#include "wx/timer.h"
36
bd3b171d
SN
37#include "wx/os2/private.h" // includes <windows.h>
38
39// ============================================================================
40// implementation
41// ============================================================================
42
43// ----------------------------------------------------------------------------
44// functions to work with .INI files
45// ----------------------------------------------------------------------------
46
47// Sleep for nSecs seconds. Attempt a Windows implementation using timers.
48static bool inTimer = FALSE;
49
50class wxSleepTimer: public wxTimer
51{
52public:
53 inline void Notify()
54 {
55 inTimer = FALSE;
56 Stop();
57 }
58};
59
60static wxTimer* wxTheSleepTimer = NULL;
61
62// Reading and writing resources (eg WIN.INI, .Xdefaults)
63#if wxUSE_RESOURCES
64bool 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
95bool 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
112bool 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
129bool 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
146bool 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
198bool 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
227bool 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
256bool 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
290HCURSOR gs_wxBusyCursor = 0; // new, busy cursor
291HCURSOR gs_wxBusyCursorOld = 0; // old cursor
292static int gs_wxBusyCursorCount = 0;
293
294// Set the cursor to the busy cursor for all windows
295void 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
308void 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
322bool 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.
329bool 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
359void 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
372bool 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
391int 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
415void 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
438void 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
465void 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
8329e6c7
SN
476void wxGUIAppTraits::InitializeGui(unsigned long &ulHab)
477{
478 ulHab = ::WinInitialize(0);
479}
480
481void wxGUIAppTraits::TerminateGui(unsigned long ulHab)
482{
483 ::WinTerminate(ulHab);
484}
485
621ccd8a
SN
486wxToolkitInfo & 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
bd3b171d
SN
512// ---------------------------------------------------------------------------
513// window information functions
514// ---------------------------------------------------------------------------
515
516wxString 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
529wxString 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
555WXWORD WXDLLEXPORT wxGetWindowId(
556 WXHWND hWnd
557)
558{
559 return ::WinQueryWindowUShort((HWND)hWnd, QWS_ID);
560}
561
562void 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
801void 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// ---------------------------------------------------------------------------
890wxBitmap 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
1103COLORREF wxColourToRGB(
1104 const wxColour& rColor
1105)
1106{
1107 return(OS2RGB(rColor.Red(), rColor.Green(), rColor.Blue()));
1108} // end of wxColourToRGB