Olly Betts' typo patch
[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 *pWidth = (int)lWidth;
432 *pHeight = (int)lHeight;
433 }
434
435 void wxDisplaySizeMM(
436 int* pWidth
437 , int* pHeight
438 )
439 {
440 HPS hpsScreen;
441 HDC hdcScreen;
442
443 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
444 hdcScreen = ::GpiQueryDevice(hpsScreen);
445
446 if (pWidth)
447 ::DevQueryCaps( hdcScreen
448 ,CAPS_HORIZONTAL_RESOLUTION
449 ,1L
450 ,(PLONG)pWidth
451 );
452 if (pHeight)
453 ::DevQueryCaps( hdcScreen
454 ,CAPS_VERTICAL_RESOLUTION
455 ,1L
456 ,(PLONG)pHeight
457 );
458 ::DevCloseDC(hdcScreen);
459 ::WinReleasePS(hpsScreen);
460 }
461
462 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
463 {
464 // This is supposed to return desktop dimensions minus any window
465 // manager panels, menus, taskbars, etc. If there is a way to do that
466 // for this platform please fix this function, otherwise it defaults
467 // to the entire desktop.
468 if (x) *x = 0;
469 if (y) *y = 0;
470 wxDisplaySize(width, height);
471 }
472
473 void wxGUIAppTraits::InitializeGui(unsigned long &ulHab)
474 {
475 ulHab = ::WinInitialize(0);
476 }
477
478 void wxGUIAppTraits::TerminateGui(unsigned long ulHab)
479 {
480 ::WinTerminate(ulHab);
481 }
482
483 wxToolkitInfo & wxGUIAppTraits::GetToolkitInfo()
484 {
485 static wxToolkitInfo vInfo;
486 ULONG ulSysInfo[QSV_MAX] = {0};
487 APIRET ulrc;
488
489 vInfo.shortName = _T("PM");
490 vInfo.name = _T("wxOS2");
491 #ifdef __WXUNIVERSAL__
492 vInfo.shortName << _T("univ");
493 vInfo.name << _T("/wxUniversal");
494 #endif
495 ulrc = ::DosQuerySysInfo( 1L
496 ,QSV_MAX
497 ,(PVOID)ulSysInfo
498 ,sizeof(ULONG) * QSV_MAX
499 );
500 if (ulrc == 0L)
501 {
502 vInfo.versionMajor = ulSysInfo[QSV_VERSION_MAJOR] / 10;
503 vInfo.versionMinor = ulSysInfo[QSV_VERSION_MINOR];
504 }
505 vInfo.os = wxOS2_PM;
506 return vInfo;
507 }
508
509 // ---------------------------------------------------------------------------
510 // window information functions
511 // ---------------------------------------------------------------------------
512
513 wxString WXDLLEXPORT wxGetWindowText(
514 WXHWND hWnd
515 )
516 {
517 wxString vStr;
518
519 if ( hWnd )
520 {
521 long lLen = ::WinQueryWindowTextLength((HWND)hWnd) + 1;
522 ::WinQueryWindowText((HWND)hWnd, lLen, (PSZ)(wxChar*)wxStringBuffer(vStr, lLen));
523 }
524
525 return vStr;
526 }
527
528 wxString WXDLLEXPORT wxGetWindowClass(
529 WXHWND hWnd
530 )
531 {
532 wxString vStr;
533 if ( hWnd )
534 {
535 int nLen = 256; // some starting value
536
537 for ( ;; )
538 {
539 int nCount = ::WinQueryClassName((HWND)hWnd, nLen, (PSZ)(wxChar*)wxStringBuffer(vStr, nLen));
540
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 }
553 return vStr;
554 }
555
556 WXWORD WXDLLEXPORT wxGetWindowId(
557 WXHWND hWnd
558 )
559 {
560 return ::WinQueryWindowUShort((HWND)hWnd, QWS_ID);
561 }
562
563 void wxDrawBorder(
564 HPS hPS
565 , RECTL& rRect
566 , WXDWORD dwStyle
567 )
568 {
569 POINTL vPoint[2];
570
571 vPoint[0].x = rRect.xLeft;
572 vPoint[0].y = rRect.yBottom;
573 ::GpiMove(hPS, &vPoint[0]);
574 if (dwStyle & wxSIMPLE_BORDER ||
575 dwStyle & wxSTATIC_BORDER)
576 {
577 vPoint[1].x = rRect.xRight - 1;
578 vPoint[1].y = rRect.yTop - 1;
579 ::GpiBox( hPS
580 ,DRO_OUTLINE
581 ,&vPoint[1]
582 ,0L
583 ,0L
584 );
585 }
586 if (dwStyle & wxSUNKEN_BORDER)
587 {
588 LINEBUNDLE vLineBundle;
589
590 vLineBundle.lColor = 0x00FFFFFF; // WHITE
591 vLineBundle.usMixMode = FM_OVERPAINT;
592 vLineBundle.fxWidth = 2;
593 vLineBundle.lGeomWidth = 2;
594 vLineBundle.usType = LINETYPE_SOLID;
595 vLineBundle.usEnd = 0;
596 vLineBundle.usJoin = 0;
597 ::GpiSetAttrs( hPS
598 ,PRIM_LINE
599 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
600 ,0L
601 ,&vLineBundle
602 );
603 vPoint[1].x = rRect.xRight - 1;
604 vPoint[1].y = rRect.yTop - 1;
605 ::GpiBox( hPS
606 ,DRO_OUTLINE
607 ,&vPoint[1]
608 ,0L
609 ,0L
610 );
611 vPoint[0].x = rRect.xLeft + 1;
612 vPoint[0].y = rRect.yBottom + 1;
613 ::GpiMove(hPS, &vPoint[0]);
614 vPoint[1].x = rRect.xRight - 2;
615 vPoint[1].y = rRect.yTop - 2;
616 ::GpiBox( hPS
617 ,DRO_OUTLINE
618 ,&vPoint[1]
619 ,0L
620 ,0L
621 );
622
623 vLineBundle.lColor = 0x00000000; // BLACK
624 vLineBundle.usMixMode = FM_OVERPAINT;
625 vLineBundle.fxWidth = 2;
626 vLineBundle.lGeomWidth = 2;
627 vLineBundle.usType = LINETYPE_SOLID;
628 vLineBundle.usEnd = 0;
629 vLineBundle.usJoin = 0;
630 ::GpiSetAttrs( hPS
631 ,PRIM_LINE
632 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
633 ,0L
634 ,&vLineBundle
635 );
636 vPoint[0].x = rRect.xLeft + 2;
637 vPoint[0].y = rRect.yBottom + 2;
638 ::GpiMove(hPS, &vPoint[0]);
639 vPoint[1].x = rRect.xLeft + 2;
640 vPoint[1].y = rRect.yTop - 3;
641 ::GpiLine(hPS, &vPoint[1]);
642 vPoint[1].x = rRect.xRight - 3;
643 vPoint[1].y = rRect.yTop - 3;
644 ::GpiLine(hPS, &vPoint[1]);
645
646 vPoint[0].x = rRect.xLeft + 3;
647 vPoint[0].y = rRect.yBottom + 3;
648 ::GpiMove(hPS, &vPoint[0]);
649 vPoint[1].x = rRect.xLeft + 3;
650 vPoint[1].y = rRect.yTop - 4;
651 ::GpiLine(hPS, &vPoint[1]);
652 vPoint[1].x = rRect.xRight - 4;
653 vPoint[1].y = rRect.yTop - 4;
654 ::GpiLine(hPS, &vPoint[1]);
655 }
656 if (dwStyle & wxDOUBLE_BORDER)
657 {
658 LINEBUNDLE vLineBundle;
659
660 vLineBundle.lColor = 0x00FFFFFF; // WHITE
661 vLineBundle.usMixMode = FM_OVERPAINT;
662 vLineBundle.fxWidth = 2;
663 vLineBundle.lGeomWidth = 2;
664 vLineBundle.usType = LINETYPE_SOLID;
665 vLineBundle.usEnd = 0;
666 vLineBundle.usJoin = 0;
667 ::GpiSetAttrs( hPS
668 ,PRIM_LINE
669 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
670 ,0L
671 ,&vLineBundle
672 );
673 vPoint[1].x = rRect.xRight - 1;
674 vPoint[1].y = rRect.yTop - 1;
675 ::GpiBox( hPS
676 ,DRO_OUTLINE
677 ,&vPoint[1]
678 ,0L
679 ,0L
680 );
681 vLineBundle.lColor = 0x00000000; // WHITE
682 vLineBundle.usMixMode = FM_OVERPAINT;
683 vLineBundle.fxWidth = 2;
684 vLineBundle.lGeomWidth = 2;
685 vLineBundle.usType = LINETYPE_SOLID;
686 vLineBundle.usEnd = 0;
687 vLineBundle.usJoin = 0;
688 ::GpiSetAttrs( hPS
689 ,PRIM_LINE
690 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
691 ,0L
692 ,&vLineBundle
693 );
694 vPoint[0].x = rRect.xLeft + 2;
695 vPoint[0].y = rRect.yBottom + 2;
696 ::GpiMove(hPS, &vPoint[0]);
697 vPoint[1].x = rRect.xRight - 2;
698 vPoint[1].y = rRect.yTop - 2;
699 ::GpiBox( hPS
700 ,DRO_OUTLINE
701 ,&vPoint[1]
702 ,0L
703 ,0L
704 );
705 vLineBundle.lColor = 0x00FFFFFF; // BLACK
706 vLineBundle.usMixMode = FM_OVERPAINT;
707 vLineBundle.fxWidth = 2;
708 vLineBundle.lGeomWidth = 2;
709 vLineBundle.usType = LINETYPE_SOLID;
710 vLineBundle.usEnd = 0;
711 vLineBundle.usJoin = 0;
712 ::GpiSetAttrs( hPS
713 ,PRIM_LINE
714 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
715 ,0L
716 ,&vLineBundle
717 );
718 vPoint[0].x = rRect.xLeft + 3;
719 vPoint[0].y = rRect.yBottom + 3;
720 ::GpiMove(hPS, &vPoint[0]);
721 vPoint[1].x = rRect.xRight - 3;
722 vPoint[1].y = rRect.yTop - 3;
723 ::GpiBox( hPS
724 ,DRO_OUTLINE
725 ,&vPoint[1]
726 ,0L
727 ,0L
728 );
729 }
730 if (dwStyle & wxRAISED_BORDER)
731 {
732 LINEBUNDLE vLineBundle;
733
734 vLineBundle.lColor = 0x00000000; // BLACK
735 vLineBundle.usMixMode = FM_OVERPAINT;
736 vLineBundle.fxWidth = 2;
737 vLineBundle.lGeomWidth = 2;
738 vLineBundle.usType = LINETYPE_SOLID;
739 vLineBundle.usEnd = 0;
740 vLineBundle.usJoin = 0;
741 ::GpiSetAttrs( hPS
742 ,PRIM_LINE
743 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
744 ,0L
745 ,&vLineBundle
746 );
747 vPoint[1].x = rRect.xRight - 1;
748 vPoint[1].y = rRect.yTop - 1;
749 ::GpiBox( hPS
750 ,DRO_OUTLINE
751 ,&vPoint[1]
752 ,0L
753 ,0L
754 );
755 vPoint[0].x = rRect.xLeft + 1;
756 vPoint[0].y = rRect.yBottom + 1;
757 ::GpiMove(hPS, &vPoint[0]);
758 vPoint[1].x = rRect.xRight - 2;
759 vPoint[1].y = rRect.yTop - 2;
760 ::GpiBox( hPS
761 ,DRO_OUTLINE
762 ,&vPoint[1]
763 ,0L
764 ,0L
765 );
766
767 vLineBundle.lColor = 0x00FFFFFF; // WHITE
768 vLineBundle.usMixMode = FM_OVERPAINT;
769 vLineBundle.fxWidth = 2;
770 vLineBundle.lGeomWidth = 2;
771 vLineBundle.usType = LINETYPE_SOLID;
772 vLineBundle.usEnd = 0;
773 vLineBundle.usJoin = 0;
774 ::GpiSetAttrs( hPS
775 ,PRIM_LINE
776 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
777 ,0L
778 ,&vLineBundle
779 );
780 vPoint[0].x = rRect.xLeft + 2;
781 vPoint[0].y = rRect.yBottom + 2;
782 ::GpiMove(hPS, &vPoint[0]);
783 vPoint[1].x = rRect.xLeft + 2;
784 vPoint[1].y = rRect.yTop - 3;
785 ::GpiLine(hPS, &vPoint[1]);
786 vPoint[1].x = rRect.xRight - 3;
787 vPoint[1].y = rRect.yTop - 3;
788 ::GpiLine(hPS, &vPoint[1]);
789
790 vPoint[0].x = rRect.xLeft + 3;
791 vPoint[0].y = rRect.yBottom + 3;
792 ::GpiMove(hPS, &vPoint[0]);
793 vPoint[1].x = rRect.xLeft + 3;
794 vPoint[1].y = rRect.yTop - 4;
795 ::GpiLine(hPS, &vPoint[1]);
796 vPoint[1].x = rRect.xRight - 4;
797 vPoint[1].y = rRect.yTop - 4;
798 ::GpiLine(hPS, &vPoint[1]);
799 }
800 } // end of wxDrawBorder
801
802 void wxOS2SetFont(
803 HWND hWnd
804 , const wxFont& rFont
805 )
806 {
807 char zFont[128];
808 char zFacename[30];
809 char zWeight[30];
810 char zStyle[30];
811
812 if (hWnd == NULLHANDLE)
813 return;
814
815 //
816 // The fonts available for Presentation Params are just a few
817 // outline fonts, the rest are available to the GPI, so we must
818 // map the families to one of these three
819 //
820 switch(rFont.GetFamily())
821 {
822 case wxSCRIPT:
823 strcpy(zFacename, "Script");
824 break;
825
826 case wxDECORATIVE:
827 strcpy(zFacename, "WarpSans");
828 break;
829
830 case wxROMAN:
831 strcpy(zFacename,"Times New Roman");
832 break;
833
834 case wxTELETYPE:
835 strcpy(zFacename, "Courier New");
836 break;
837
838 case wxMODERN:
839 strcpy(zFacename, "Courier New");
840 break;
841
842 case wxDEFAULT:
843 default:
844 case wxSWISS:
845 strcpy(zFacename, "Helvetica");
846 break;
847 }
848
849 switch(rFont.GetWeight())
850 {
851 default:
852 case wxNORMAL:
853 case wxLIGHT:
854 zWeight[0] = '\0';
855 break;
856
857 case wxBOLD:
858 case wxFONTWEIGHT_MAX:
859 strcpy(zWeight, "Bold");
860 break;
861 }
862
863 switch(rFont.GetStyle())
864 {
865 case wxITALIC:
866 case wxSLANT:
867 strcpy(zStyle, "Italic");
868 break;
869
870 default:
871 zStyle[0] = '\0';
872 break;
873 }
874 sprintf(zFont, "%d.%s", rFont.GetPointSize(), zFacename);
875 if (zWeight[0] != '\0')
876 {
877 strcat(zFont, " ");
878 strcat(zFont, zWeight);
879 }
880 if (zStyle[0] != '\0')
881 {
882 strcat(zFont, " ");
883 strcat(zFont, zStyle);
884 }
885 ::WinSetPresParam(hWnd, PP_FONTNAMESIZE, strlen(zFont) + 1, (PVOID)zFont);
886 } // end of wxOS2SetFont
887
888 // ---------------------------------------------------------------------------
889 // Helper for taking a regular bitmap and giving it a disabled look
890 // ---------------------------------------------------------------------------
891 wxBitmap wxDisableBitmap(
892 const wxBitmap& rBmp
893 , long lColor
894 )
895 {
896 wxMask* pMask = rBmp.GetMask();
897
898 if (!pMask)
899 return(wxNullBitmap);
900
901 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
902 SIZEL vSize = {0, 0};
903 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
904 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
905 BITMAPINFOHEADER2 vHeader;
906 BITMAPINFO2 vInfo;
907 ERRORID vError;
908 wxString sError;
909 HBITMAP hBitmap = (HBITMAP)rBmp.GetHBITMAP();
910 HBITMAP hOldBitmap = NULLHANDLE;
911 HBITMAP hOldMask = NULLHANDLE;
912 HBITMAP hMask = (HBITMAP)rBmp.GetMask()->GetMaskBitmap();
913 unsigned char* pucBits; // buffer that will contain the bitmap data
914 unsigned char* pucData; // pointer to use to traverse bitmap data
915 unsigned char* pucBitsMask; // buffer that will contain the mask data
916 unsigned char* pucDataMask; // pointer to use to traverse mask data
917 LONG lScans = 0L;
918 LONG lScansSet = 0L;
919 bool bpp16 = (wxDisplayDepth() == 16);
920
921 memset(&vHeader, '\0', 16);
922 vHeader.cbFix = 16;
923
924 memset(&vInfo, '\0', 16);
925 vInfo.cbFix = 16;
926 vInfo.cx = (ULONG)rBmp.GetWidth();
927 vInfo.cy = (ULONG)rBmp.GetHeight();
928 vInfo.cPlanes = 1;
929 vInfo.cBitCount = 24; // Set to desired count going in
930
931 //
932 // Create the buffers for data....all wxBitmaps are 24 bit internally
933 //
934 int nBytesPerLine = rBmp.GetWidth() * 3;
935 int nSizeDWORD = sizeof(DWORD);
936 int nLineBoundary = nBytesPerLine % nSizeDWORD;
937 int nPadding = 0;
938 int i;
939 int j;
940
941 //
942 // Bitmap must be in a double-word aligned address so we may
943 // have some padding to worry about
944 //
945 if (nLineBoundary > 0)
946 {
947 nPadding = nSizeDWORD - nLineBoundary;
948 nBytesPerLine += nPadding;
949 }
950 pucBits = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
951 memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight()));
952 pucBitsMask = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
953 memset(pucBitsMask, '\0', (nBytesPerLine * rBmp.GetHeight()));
954
955 //
956 // Extract the bitmap and mask data
957 //
958 if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR)
959 {
960 vError = ::WinGetLastError(vHabmain);
961 sError = wxPMErrorToStr(vError);
962 }
963 ::GpiQueryBitmapInfoHeader(hBitmap, &vHeader);
964 vInfo.cBitCount = 24;
965 if ((lScans = ::GpiQueryBitmapBits( hPS
966 ,0L
967 ,(LONG)rBmp.GetHeight()
968 ,(PBYTE)pucBits
969 ,&vInfo
970 )) == GPI_ALTERROR)
971 {
972 vError = ::WinGetLastError(vHabmain);
973 sError = wxPMErrorToStr(vError);
974 }
975 if ((hOldMask = ::GpiSetBitmap(hPS, hMask)) == HBM_ERROR)
976 {
977 vError = ::WinGetLastError(vHabmain);
978 sError = wxPMErrorToStr(vError);
979 }
980 ::GpiQueryBitmapInfoHeader(hMask, &vHeader);
981 vInfo.cBitCount = 24;
982 if ((lScans = ::GpiQueryBitmapBits( hPS
983 ,0L
984 ,(LONG)rBmp.GetHeight()
985 ,(PBYTE)pucBitsMask
986 ,&vInfo
987 )) == GPI_ALTERROR)
988 {
989 vError = ::WinGetLastError(vHabmain);
990 sError = wxPMErrorToStr(vError);
991 }
992 if (( hMask = ::GpiSetBitmap(hPS, hOldMask)) == HBM_ERROR)
993 {
994 vError = ::WinGetLastError(vHabmain);
995 sError = wxPMErrorToStr(vError);
996 }
997 pucData = pucBits;
998 pucDataMask = pucBitsMask;
999
1000 //
1001 // Get the mask value
1002 //
1003 for (i = 0; i < rBmp.GetHeight(); i++)
1004 {
1005 for (j = 0; j < rBmp.GetWidth(); j++)
1006 {
1007 // Byte 1
1008 if (bpp16 && *pucDataMask == 0xF8) // 16 bit display gobblygook
1009 {
1010 *pucData = 0x7F;
1011 pucData++;
1012 }
1013 else if (*pucDataMask == 0xFF) // set to grey
1014 {
1015 *pucData = 0x7F;
1016 pucData++;
1017 }
1018 else
1019 {
1020 *pucData = ((unsigned char)(lColor >> 16));
1021 pucData++;
1022 }
1023
1024 // Byte 2
1025 if (bpp16 && *(pucDataMask + 1) == 0xFC) // 16 bit display gobblygook
1026 {
1027 *pucData = 0x7F;
1028 pucData++;
1029 }
1030 else if (*(pucDataMask + 1) == 0xFF) // set to grey
1031 {
1032 *pucData = 0x7F;
1033 pucData++;
1034 }
1035 else
1036 {
1037 *pucData = ((unsigned char)(lColor >> 8));
1038 pucData++;
1039 }
1040
1041 // Byte 3
1042 if (bpp16 && *(pucDataMask + 2) == 0xF8) // 16 bit display gobblygook
1043 {
1044 *pucData = 0x7F;
1045 pucData++;
1046 }
1047 else if (*(pucDataMask + 2) == 0xFF) // set to grey
1048 {
1049 *pucData = 0x7F;
1050 pucData++;
1051 }
1052 else
1053 {
1054 *pucData = ((unsigned char)lColor);
1055 pucData++;
1056 }
1057 pucDataMask += 3;
1058 }
1059 for (j = 0; j < nPadding; j++)
1060 {
1061 pucData++;
1062 pucDataMask++;
1063 }
1064 }
1065
1066 //
1067 // Create a new bitmap and set the modified bits
1068 //
1069 wxBitmap vNewBmp( rBmp.GetWidth()
1070 ,rBmp.GetHeight()
1071 ,24
1072 );
1073 HBITMAP hNewBmp = (HBITMAP)vNewBmp.GetHBITMAP();
1074
1075 if ((hOldBitmap = ::GpiSetBitmap(hPS, hNewBmp)) == HBM_ERROR)
1076 {
1077 vError = ::WinGetLastError(vHabmain);
1078 sError = wxPMErrorToStr(vError);
1079 }
1080 if ((lScansSet = ::GpiSetBitmapBits( hPS
1081 ,0L
1082 ,(LONG)rBmp.GetHeight()
1083 ,(PBYTE)pucBits
1084 ,&vInfo
1085 )) == GPI_ALTERROR)
1086
1087 {
1088 vError = ::WinGetLastError(vHabmain);
1089 sError = wxPMErrorToStr(vError);
1090 }
1091 wxMask* pNewMask;
1092
1093 pNewMask = new wxMask(pMask->GetMaskBitmap());
1094 vNewBmp.SetMask(pNewMask);
1095 free(pucBits);
1096 ::GpiSetBitmap(hPS, NULLHANDLE);
1097 ::GpiDestroyPS(hPS);
1098 ::DevCloseDC(hDC);
1099 if (vNewBmp.Ok())
1100 return(vNewBmp);
1101 return(wxNullBitmap);
1102 } // end of wxDisableBitmap
1103
1104 COLORREF wxColourToRGB(
1105 const wxColour& rColor
1106 )
1107 {
1108 return(OS2RGB(rColor.Red(), rColor.Green(), rColor.Blue()));
1109 } // end of wxColourToRGB