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