]> git.saurik.com Git - wxWidgets.git/blame - src/os2/utilsgui.cpp
send wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED only once after end of dragging and...
[wxWidgets.git] / src / os2 / utilsgui.cpp
CommitLineData
bd3b171d
SN
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
65571936 9// License: wxWindows licence
bd3b171d
SN
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
ceb8f94a
SN
34#include "wx/apptrait.h"
35#include "wx/timer.h"
36
bd3b171d
SN
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.
48static bool inTimer = FALSE;
49
50class wxSleepTimer: public wxTimer
51{
52public:
53 inline void Notify()
54 {
55 inTimer = FALSE;
56 Stop();
57 }
58};
59
bd3b171d
SN
60// Reading and writing resources (eg WIN.INI, .Xdefaults)
61#if wxUSE_RESOURCES
62bool 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
93bool 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
110bool 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
127bool 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
144bool 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
196bool 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
225bool 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
254bool 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
288HCURSOR gs_wxBusyCursor = 0; // new, busy cursor
289HCURSOR gs_wxBusyCursorOld = 0; // old cursor
290static int gs_wxBusyCursorCount = 0;
291
292// Set the cursor to the busy cursor for all windows
293void 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
306void 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
320bool 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.
327bool wxCheckForInterrupt(
328 wxWindow* pWnd
329)
330{
331 if(pWnd)
332 {
333 QMSG vMsg;
334 HAB hab = 0;
335 HWND hwndFilter = NULLHANDLE;
bd3b171d
SN
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
356void 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
369bool 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
388int 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
412void 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
435void 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
462void 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
8329e6c7
SN
473void wxGUIAppTraits::InitializeGui(unsigned long &ulHab)
474{
475 ulHab = ::WinInitialize(0);
476}
477
478void wxGUIAppTraits::TerminateGui(unsigned long ulHab)
479{
480 ::WinTerminate(ulHab);
481}
482
621ccd8a
SN
483wxToolkitInfo & 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
bd3b171d
SN
509// ---------------------------------------------------------------------------
510// window information functions
511// ---------------------------------------------------------------------------
512
513wxString WXDLLEXPORT wxGetWindowText(
514 WXHWND hWnd
515)
516{
517 wxString vStr;
bd3b171d 518
2461cfa0
SN
519 if ( hWnd )
520 {
521 long lLen = ::WinQueryWindowTextLength((HWND)hWnd) + 1;
522 ::WinQueryWindowText((HWND)hWnd, lLen, wxStringBuffer(vStr, lLen));
523 }
bd3b171d
SN
524
525 return vStr;
526}
527
528wxString WXDLLEXPORT wxGetWindowClass(
529 WXHWND hWnd
530)
531{
532 wxString vStr;
2461cfa0 533 if ( hWnd )
bd3b171d 534 {
2461cfa0
SN
535 int nLen = 256; // some starting value
536
537 for ( ;; )
538 {
539 int nCount = ::WinQueryClassName((HWND)hWnd, nLen, 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 }
bd3b171d
SN
551 }
552 }
553 return vStr;
554}
555
556WXWORD WXDLLEXPORT wxGetWindowId(
557 WXHWND hWnd
558)
559{
560 return ::WinQueryWindowUShort((HWND)hWnd, QWS_ID);
561}
562
563void 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
802void 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// ---------------------------------------------------------------------------
891wxBitmap 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 ina double-word alligned 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
1104COLORREF wxColourToRGB(
1105 const wxColour& rColor
1106)
1107{
1108 return(OS2RGB(rColor.Red(), rColor.Green(), rColor.Blue()));
1109} // end of wxColourToRGB