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