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