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