]> git.saurik.com Git - wxWidgets.git/blame - src/os2/utils.cpp
Completely reworked OS/2 thread implementation.
[wxWidgets.git] / src / os2 / utils.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: utils.cpp
3// Purpose: Various utilities
45fcbf3b 4// Author: David Webster
0e320a79 5// Modified by:
45fcbf3b 6// Created: 09/17/99
0e320a79 7// RCS-ID: $Id$
45fcbf3b 8// Copyright: (c) David Webster
6aa89a22 9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
45fcbf3b
DW
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifndef WX_PRECOMP
16 #include "wx/setup.h"
17 #include "wx/utils.h"
18 #include "wx/app.h"
19 #include "wx/cursor.h"
20#endif //WX_PRECOMP
21
22#include "wx/os2/private.h"
23#include "wx/timer.h"
24#include "wx/intl.h"
cd478a95 25#include "wx/apptrait.h"
45fcbf3b 26
0e320a79 27#include <ctype.h>
06298235
SN
28#ifdef __EMX__
29#include <dirent.h>
06298235 30#endif
45fcbf3b
DW
31
32#include "wx/log.h"
33
34#include <io.h>
0e320a79
DW
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
45fcbf3b 39#include <errno.h>
0e320a79
DW
40#include <stdarg.h>
41
d90895ac 42#define PURE_32
468e327a 43
06298235 44#ifndef __EMX__
7cdc2f1e
DW
45#include <upm.h>
46#include <netcons.h>
47#include <netbios.h>
06298235 48#endif
45fcbf3b 49
86de7616
DW
50static const wxChar WX_SECTION[] = _T("wxWindows");
51static const wxChar eHOSTNAME[] = _T("HostName");
52static const wxChar eUSERID[] = _T("UserId");
53static const wxChar eUSERNAME[] = _T("UserName");
45fcbf3b
DW
54
55// For the following functions we SHOULD fill in support
56// for Windows-NT (which I don't know) as I assume it begin
57// a POSIX Unix (so claims MS) that it has some special
58// functions beyond those provided by WinSock
59
0e320a79 60// Get full hostname (eg. DoDo.BSn-Germany.crg.de)
10e5b930
DW
61bool wxGetHostName(
62 wxChar* zBuf
63, int nMaxSize
64)
0e320a79 65{
d90895ac 66#if wxUSE_NET_API
10e5b930
DW
67 char zServer[256];
68 char zComputer[256];
909b4f08 69 unsigned long ulLevel = 0;
9dea36ef
DW
70 unsigned char* zBuffer = NULL;
71 unsigned long ulBuffer = 256;
72 unsigned long* pulTotalAvail = NULL;
10e5b930 73
dde11e60
DW
74 NetBios32GetInfo( (const unsigned char*)zServer
75 ,(const unsigned char*)zComputer
909b4f08 76 ,ulLevel
dde11e60 77 ,zBuffer
909b4f08
DW
78 ,ulBuffer
79 ,pulTotalAvail
dde11e60 80 );
10e5b930 81 strcpy(zBuf, zServer);
45fcbf3b 82#else
10e5b930
DW
83 wxChar* zSysname;
84 const wxChar* zDefaultHost = _T("noname");
45fcbf3b 85
10e5b930
DW
86 if ((zSysname = wxGetenv(_T("SYSTEM_NAME"))) == NULL)
87 {
88 ULONG n = ::PrfQueryProfileString( HINI_PROFILE
89 ,(PSZ)WX_SECTION
90 ,(PSZ)eHOSTNAME
91 ,(PSZ)zDefaultHost
92 ,(void*)zBuf
93 ,(ULONG)nMaxSize - 1
94 );
95 }
96 else
97 wxStrncpy(zBuf, zSysname, nMaxSize - 1);
98 zBuf[nMaxSize] = _T('\0');
45fcbf3b 99#endif
10e5b930 100 return *zBuf ? TRUE : FALSE;
0e320a79
DW
101}
102
103// Get user ID e.g. jacs
10e5b930
DW
104bool wxGetUserId(
105 wxChar* zBuf
2bd5bbc9 106, int nType
10e5b930 107)
0e320a79 108{
19193a2c 109#if defined(__VISAGECPP__)
2bd5bbc9
DW
110 long lrc;
111 // UPM procs return 0 on success
112 lrc = U32ELOCU((unsigned char*)zBuf, (unsigned long *)&nType);
113 if (lrc == 0) return TRUE;
06298235 114#endif
2bd5bbc9 115 return FALSE;
0e320a79
DW
116}
117
10e5b930
DW
118bool wxGetUserName(
119 wxChar* zBuf
120, int nMaxSize
121)
0e320a79 122{
45fcbf3b 123#ifdef USE_NET_API
10e5b930
DW
124 wxGetUserId( zBuf
125 ,nMaxSize
126 );
45fcbf3b 127#else
10e5b930 128 wxStrncpy(zBuf, _T("Unknown User"), nMaxSize);
45fcbf3b 129#endif
10e5b930 130 return TRUE;
0e320a79
DW
131}
132
10e5b930
DW
133int wxKill(
134 long lPid
2004cad1
DW
135, wxSignal eSig
136, wxKillError* peError
10e5b930 137)
0e320a79 138{
10e5b930 139 return((int)::DosKillProcess(0, (PID)lPid));
0e320a79
DW
140}
141
142//
143// Execute a program in an Interactive Shell
144//
10e5b930
DW
145bool wxShell(
146 const wxString& rCommand
147)
0e320a79 148{
c5fb56c0
DW
149 wxChar* zShell = _T("CMD.EXE");
150 wxString sInputs;
10e5b930 151 wxChar zTmp[255];
c5fb56c0
DW
152 STARTDATA SData = {0};
153 PSZ PgmTitle = "Command Shell";
154 APIRET rc;
155 PID vPid = 0;
156 ULONG ulSessID = 0;
157 UCHAR achObjBuf[256] = {0}; //error data if DosStart fails
158 RESULTCODES vResult;
159
160 SData.Length = sizeof(STARTDATA);
161 SData.Related = SSF_RELATED_INDEPENDENT;
162 SData.FgBg = SSF_FGBG_FORE;
163 SData.TraceOpt = SSF_TRACEOPT_NONE;
164 SData.PgmTitle = PgmTitle;
165 SData.PgmName = zShell;
166
909b4f08 167 sInputs = "/C " + rCommand;
9ac6ff7b 168 SData.PgmInputs = (BYTE*)sInputs.c_str();
c5fb56c0
DW
169 SData.TermQ = 0;
170 SData.Environment = 0;
171 SData.InheritOpt = SSF_INHERTOPT_SHELL;
172 SData.SessionType = SSF_TYPE_WINDOWABLEVIO;
173 SData.IconFile = 0;
174 SData.PgmHandle = 0;
175 SData.PgmControl = SSF_CONTROL_VISIBLE | SSF_CONTROL_MAXIMIZE;
176 SData.InitXPos = 30;
177 SData.InitYPos = 40;
178 SData.InitXSize = 200;
179 SData.InitYSize = 140;
180 SData.Reserved = 0;
181 SData.ObjectBuffer = (char*)achObjBuf;
182 SData.ObjectBuffLen = (ULONG)sizeof(achObjBuf);
183
184 rc = ::DosStartSession(&SData, &ulSessID, &vPid);
9ac6ff7b 185 if (rc == 0 || rc == 457) // NO_ERROR or SMG_START_IN_BACKGROUND
c5fb56c0
DW
186 {
187 PTIB ptib;
188 PPIB ppib;
10e5b930 189
c5fb56c0 190 ::DosGetInfoBlocks(&ptib, &ppib);
10e5b930 191
c5fb56c0
DW
192 ::DosWaitChild( DCWA_PROCESS
193 ,DCWW_WAIT
194 ,&vResult
195 ,&ppib->pib_ulpid
196 ,vPid
197 );
198 }
199 return (rc != 0);
0e320a79
DW
200}
201
a23692f0 202// Shutdown or reboot the PC
f6ba47d9
VZ
203bool wxShutdown(wxShutdownFlags wFlags)
204{
205 // TODO
206 return FALSE;
207}
208
0e320a79 209// Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
5d4b632b 210long wxGetFreeMemory()
0e320a79 211{
9dea36ef 212 void* pMemptr = NULL;
78d50441
DW
213 ULONG lSize;
214 ULONG lMemFlags;
215 APIRET rc;
216
217 lMemFlags = PAG_FREE;
10e5b930 218 rc = ::DosQueryMem(pMemptr, &lSize, &lMemFlags);
78d50441
DW
219 if (rc != 0)
220 return -1L;
221 return (long)lSize;
45fcbf3b
DW
222}
223
8269a903
SN
224// ----------------------------------------------------------------------------
225// env vars
226// ----------------------------------------------------------------------------
227
228bool wxGetEnv(const wxString& var, wxString *value)
229{
230 // wxGetenv is defined as getenv()
231 wxChar *p = wxGetenv(var);
232 if ( !p )
233 return FALSE;
234
235 if ( value )
236 {
237 *value = p;
238 }
239
240 return TRUE;
241}
242
243bool wxSetEnv(const wxString& variable, const wxChar *value)
244{
245#if defined(HAVE_SETENV)
246 return setenv(variable.mb_str(), value ? wxString(value).mb_str().data()
247 : NULL, 1 /* overwrite */) == 0;
248#elif defined(HAVE_PUTENV)
249 wxString s = variable;
250 if ( value )
251 s << _T('=') << value;
252
253 // transform to ANSI
254 const char *p = s.mb_str();
255
256 // the string will be free()d by libc
257 char *buf = (char *)malloc(strlen(p) + 1);
258 strcpy(buf, p);
259
260 return putenv(buf) == 0;
261#else // no way to set an env var
262 return FALSE;
263#endif
264}
265
266
45fcbf3b
DW
267// Sleep for nSecs seconds. Attempt a Windows implementation using timers.
268static bool inTimer = FALSE;
269
270class wxSleepTimer: public wxTimer
271{
10e5b930
DW
272public:
273 inline void Notify()
274 {
275 inTimer = FALSE;
276 Stop();
277 }
45fcbf3b
DW
278};
279
10e5b930 280static wxTimer* wxTheSleepTimer = NULL;
45fcbf3b 281
10e5b930
DW
282void wxUsleep(
283 unsigned long ulMilliseconds
284)
45fcbf3b 285{
f53a0d32 286 ::DosSleep(ulMilliseconds);
0e320a79
DW
287}
288
10e5b930
DW
289void wxSleep(
290 int nSecs
291)
0e320a79 292{
10e5b930 293 ::DosSleep(1000 * nSecs);
0e320a79
DW
294}
295
296// Consume all events until no more left
297void wxFlushEvents()
298{
45fcbf3b 299// wxYield();
0e320a79
DW
300}
301
73deed44
VZ
302#if WXWIN_COMPATIBILITY_2_2
303
45fcbf3b 304// Output a debug mess., in a system dependent fashion.
10e5b930
DW
305void wxDebugMsg(
306 const wxChar* zFmt ...
307)
308{
309 va_list vAp;
310 static wxChar zBuffer[512];
311
312 if (!wxTheApp->GetWantDebugOutput())
313 return ;
314 va_start(vAp, zFmt);
315 sprintf(zBuffer, zFmt, vAp) ;
316 va_end(vAp);
0e320a79
DW
317}
318
319// Non-fatal error: pop up message box and (possibly) continue
10e5b930
DW
320void wxError(
321 const wxString& rMsg
322, const wxString& rTitle
323)
324{
13a4ea8d 325 wxBuffer = new wxChar[256];
10e5b930
DW
326 wxSprintf(wxBuffer, "%s\nContinue?", WXSTRINGCAST rMsg);
327 if (::WinMessageBox( HWND_DESKTOP
328 ,NULL
329 ,(PSZ)wxBuffer
330 ,(PSZ)WXSTRINGCAST rTitle
331 ,0
332 ,MB_ICONEXCLAMATION | MB_YESNO
333 ) == MBID_YES)
13a4ea8d 334 delete[] wxBuffer;
0e320a79
DW
335 wxExit();
336}
337
338// Fatal error: pop up message box and abort
10e5b930
DW
339void wxFatalError(
340 const wxString& rMsg
341, const wxString& rTitle
342)
343{
344 unsigned long ulRc;
345
346 ulRc = ::WinMessageBox( HWND_DESKTOP
347 ,NULL
348 ,WXSTRINGCAST rMsg
349 ,WXSTRINGCAST rTitle
350 ,0
351 ,MB_NOICON | MB_OK
352 );
353 DosExit(EXIT_PROCESS, ulRc);
0e320a79
DW
354}
355
73deed44
VZ
356#endif // WXWIN_COMPATIBILITY_2_2
357
0e320a79
DW
358// Emit a beeeeeep
359void wxBell()
360{
45fcbf3b 361 DosBeep(1000,1000); // 1kHz during 1 sec.
0e320a79
DW
362}
363
cd478a95 364int wxGUIAppTraits::GetOSVersion(
10e5b930
DW
365 int* pMajorVsn
366, int* pMinorVsn
367)
368{
369 ULONG ulSysInfo[QSV_MAX] = {0};
5d4b632b
DW
370 APIRET ulrc;
371
372 ulrc = ::DosQuerySysInfo( 1L
373 ,QSV_MAX
374 ,(PVOID)ulSysInfo
375 ,sizeof(ULONG) * QSV_MAX
376 );
377 if (ulrc == 0L)
10e5b930
DW
378 {
379 *pMajorVsn = ulSysInfo[QSV_VERSION_MAJOR];
5d4b632b 380 *pMajorVsn = *pMajorVsn/10;
10e5b930
DW
381 *pMinorVsn = ulSysInfo[QSV_VERSION_MINOR];
382 return wxWINDOWS_OS2;
383 }
384 return wxWINDOWS; // error if we get here, return generic value
0e320a79
DW
385}
386
387// Reading and writing resources (eg WIN.INI, .Xdefaults)
388#if wxUSE_RESOURCES
10e5b930
DW
389bool wxWriteResource(
390 const wxString& rSection
391, const wxString& rEntry
392, const wxString& rValue
393, const wxString& rFile
394)
0e320a79 395{
9dea36ef
DW
396 HAB hab = 0;
397 HINI hIni = 0;
78d50441 398
10e5b930 399 if (rFile != "")
78d50441 400 {
10e5b930 401 hIni = ::PrfOpenProfile(hab, (PSZ)WXSTRINGCAST rFile);
78d50441
DW
402 if (hIni != 0L)
403 {
404 return (::PrfWriteProfileString( hIni
10e5b930
DW
405 ,(PSZ)WXSTRINGCAST rSection
406 ,(PSZ)WXSTRINGCAST rEntry
407 ,(PSZ)WXSTRINGCAST rValue
78d50441
DW
408 ));
409 }
410 }
411 else
412 return (::PrfWriteProfileString( HINI_PROFILE
10e5b930
DW
413 ,(PSZ)WXSTRINGCAST rSection
414 ,(PSZ)WXSTRINGCAST rEntry
415 ,(PSZ)WXSTRINGCAST rValue
78d50441 416 ));
d90895ac 417 return FALSE;
0e320a79
DW
418}
419
10e5b930
DW
420bool wxWriteResource(
421 const wxString& rSection
422, const wxString& rEntry
423, float fValue
424, const wxString& rFile
425)
426{
427 wxChar zBuf[50];
428
429 wxSprintf(zBuf, "%.4f", fValue);
430 return wxWriteResource( rSection
431 ,rEntry
432 ,zBuf
433 ,rFile
434 );
0e320a79
DW
435}
436
1be7f92a
DW
437bool wxWriteResource(
438 const wxString& rSection
439, const wxString& rEntry
440, long lValue
441, const wxString& rFile
442)
0e320a79 443{
1be7f92a
DW
444 wxChar zBuf[50];
445
446 wxSprintf(zBuf, "%ld", lValue);
447 return wxWriteResource( rSection
448 ,rEntry
449 ,zBuf
450 ,rFile
451 );
0e320a79
DW
452}
453
1be7f92a
DW
454bool wxWriteResource(
455 const wxString& rSection
456, const wxString& rEntry
457, int lValue
458, const wxString& rFile
459)
0e320a79 460{
1be7f92a
DW
461 wxChar zBuf[50];
462
463 wxSprintf(zBuf, "%d", lValue);
464 return wxWriteResource( rSection
465 ,rEntry
466 ,zBuf
467 ,rFile
468 );
0e320a79
DW
469}
470
1be7f92a
DW
471bool wxGetResource(
472 const wxString& rSection
473, const wxString& rEntry
474, wxChar** ppValue
475, const wxString& rFile
476)
0e320a79 477{
9dea36ef
DW
478 HAB hab = 0;
479 HINI hIni = 0;
e8fd750b
DW
480 wxChar zDefunkt[] = _T("$$default");
481 char zBuf[1000];
78d50441 482
1be7f92a 483 if (rFile != "")
78d50441 484 {
1be7f92a 485 hIni = ::PrfOpenProfile(hab, (PSZ)WXSTRINGCAST rFile);
78d50441
DW
486 if (hIni != 0L)
487 {
488 ULONG n = ::PrfQueryProfileString( hIni
1be7f92a
DW
489 ,(PSZ)WXSTRINGCAST rSection
490 ,(PSZ)WXSTRINGCAST rEntry
491 ,(PSZ)zDefunkt
e8fd750b 492 ,(PVOID)zBuf
78d50441
DW
493 ,1000
494 );
e8fd750b 495 if (zBuf == NULL)
78d50441 496 return FALSE;
e8fd750b
DW
497 if (n == 0L || wxStrcmp(zBuf, zDefunkt) == 0)
498 return FALSE;
499 zBuf[n-1] = '\0';
78d50441
DW
500 }
501 else
502 return FALSE;
503 }
504 else
505 {
506 ULONG n = ::PrfQueryProfileString( HINI_PROFILE
1be7f92a
DW
507 ,(PSZ)WXSTRINGCAST rSection
508 ,(PSZ)WXSTRINGCAST rEntry
509 ,(PSZ)zDefunkt
e8fd750b 510 ,(PVOID)zBuf
78d50441
DW
511 ,1000
512 );
e8fd750b
DW
513 if (zBuf == NULL)
514 return FALSE;
515 if (n == 0L || wxStrcmp(zBuf, zDefunkt) == 0)
78d50441 516 return FALSE;
e8fd750b 517 zBuf[n-1] = '\0';
78d50441 518 }
e8fd750b 519 strcpy((char*)*ppValue, zBuf);
78d50441 520 return TRUE;
d90895ac 521}
0e320a79 522
1be7f92a
DW
523bool wxGetResource(
524 const wxString& rSection
525, const wxString& rEntry
526, float* pValue
527, const wxString& rFile
528)
0e320a79 529{
1be7f92a 530 wxChar* zStr = NULL;
13a4ea8d
DW
531
532 zStr = new wxChar[1000];
1be7f92a
DW
533 bool bSucc = wxGetResource( rSection
534 ,rEntry
535 ,(wxChar **)&zStr
536 ,rFile
537 );
538
539 if (bSucc)
540 {
541 *pValue = (float)wxStrtod(zStr, NULL);
542 delete[] zStr;
543 return TRUE;
544 }
13a4ea8d
DW
545 else
546 {
547 delete[] zStr;
548 return FALSE;
549 }
0e320a79
DW
550}
551
1be7f92a
DW
552bool wxGetResource(
553 const wxString& rSection
554, const wxString& rEntry
555, long* pValue
556, const wxString& rFile
557)
0e320a79 558{
1be7f92a 559 wxChar* zStr = NULL;
13a4ea8d
DW
560
561 zStr = new wxChar[1000];
1be7f92a
DW
562 bool bSucc = wxGetResource( rSection
563 ,rEntry
564 ,(wxChar **)&zStr
565 ,rFile
566 );
567
568 if (bSucc)
569 {
570 *pValue = wxStrtol(zStr, NULL, 10);
571 delete[] zStr;
572 return TRUE;
573 }
13a4ea8d
DW
574 else
575 {
576 delete[] zStr;
577 return FALSE;
578 }
0e320a79
DW
579}
580
1be7f92a
DW
581bool wxGetResource(
582 const wxString& rSection
583, const wxString& rEntry
584, int* pValue
585, const wxString& rFile
586)
0e320a79 587{
1be7f92a 588 wxChar* zStr = NULL;
13a4ea8d
DW
589
590 zStr = new wxChar[1000];
1be7f92a
DW
591 bool bSucc = wxGetResource( rSection
592 ,rEntry
593 ,(wxChar **)&zStr
594 ,rFile
595 );
596
597 if (bSucc)
598 {
599 *pValue = (int)wxStrtol(zStr, NULL, 10);
600 delete[] zStr;
601 return TRUE;
602 }
13a4ea8d
DW
603 else
604 {
605 delete[] zStr;
606 return FALSE;
607 }
0e320a79
DW
608}
609#endif // wxUSE_RESOURCES
610
45fcbf3b
DW
611// ---------------------------------------------------------------------------
612// helper functions for showing a "busy" cursor
613// ---------------------------------------------------------------------------
614
615HCURSOR gs_wxBusyCursor = 0; // new, busy cursor
616HCURSOR gs_wxBusyCursorOld = 0; // old cursor
617static int gs_wxBusyCursorCount = 0;
0e320a79
DW
618
619// Set the cursor to the busy cursor for all windows
1be7f92a
DW
620void wxBeginBusyCursor(
621 wxCursor* pCursor
622)
0e320a79 623{
45fcbf3b
DW
624 if ( gs_wxBusyCursorCount++ == 0 )
625 {
1be7f92a 626 gs_wxBusyCursor = (HCURSOR)pCursor->GetHCURSOR();
45fcbf3b
DW
627 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursor);
628 }
629 //else: nothing to do, already set
0e320a79
DW
630}
631
632// Restore cursor to normal
633void wxEndBusyCursor()
634{
1be7f92a
DW
635 wxCHECK_RET( gs_wxBusyCursorCount > 0
636 ,_T("no matching wxBeginBusyCursor() for wxEndBusyCursor()")
637 );
45fcbf3b 638
1be7f92a 639 if (--gs_wxBusyCursorCount == 0)
45fcbf3b
DW
640 {
641 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursorOld);
642 gs_wxBusyCursorOld = 0;
643 }
0e320a79
DW
644}
645
646// TRUE if we're between the above two calls
647bool wxIsBusy()
648{
1be7f92a 649 return (gs_wxBusyCursorCount > 0);
45fcbf3b
DW
650}
651
652// ---------------------------------------------------------------------------
1be7f92a
DW
653const wxChar* wxGetHomeDir(
654 wxString* pStr
655)
45fcbf3b 656{
1be7f92a 657 wxString& rStrDir = *pStr;
0e320a79 658
1be7f92a
DW
659 // OS/2 has no idea about home,
660 // so use the working directory instead?
45fcbf3b 661
1be7f92a 662 // 256 was taken from os2def.h
45fcbf3b
DW
663#ifndef MAX_PATH
664# define MAX_PATH 256
665#endif
666
1be7f92a
DW
667 char zDirName[256];
668 ULONG ulDirLen;
45fcbf3b 669
1be7f92a
DW
670 ::DosQueryCurrentDir(0, zDirName, &ulDirLen);
671 rStrDir = zDirName;
672 return rStrDir.c_str();
45fcbf3b
DW
673}
674
10e5b930 675// Hack for OS/2
1be7f92a
DW
676wxChar* wxGetUserHome (
677 const wxString& rUser
678)
679{
680 wxChar* zHome;
681 wxString sUser1(rUser);
682
13a4ea8d 683 wxBuffer = new wxChar[256];
06298235 684#ifndef __EMX__
1be7f92a 685 if (sUser1 != _T(""))
45fcbf3b 686 {
1be7f92a
DW
687 wxChar zTmp[64];
688
689 if (wxGetUserId( zTmp
690 ,sizeof(zTmp)/sizeof(char)
691 ))
692 {
693 // Guests belong in the temp dir
694 if (wxStricmp(zTmp, _T("annonymous")) == 0)
695 {
696 if ((zHome = wxGetenv(_T("TMP"))) != NULL ||
697 (zHome = wxGetenv(_T("TMPDIR"))) != NULL ||
698 (zHome = wxGetenv(_T("TEMP"))) != NULL)
13a4ea8d 699 delete[] wxBuffer;
1be7f92a
DW
700 return *zHome ? zHome : (wxChar*)_T("\\");
701 }
702 if (wxStricmp(zTmp, WXSTRINGCAST sUser1) == 0)
703 sUser1 = _T("");
704 }
45fcbf3b 705 }
06298235 706#endif
1be7f92a 707 if (sUser1 == _T(""))
13a4ea8d 708 {
1be7f92a
DW
709 if ((zHome = wxGetenv(_T("HOME"))) != NULL)
710 {
711 wxStrcpy(wxBuffer, zHome);
2b5f62a0 712 wxUnix2DosFilename(wxBuffer);
13a4ea8d
DW
713 wxStrcpy(zHome, wxBuffer);
714 delete[] wxBuffer;
715 return zHome;
1be7f92a 716 }
13a4ea8d
DW
717 }
718 delete[] wxBuffer;
719 return NULL; // No home known!
0e320a79
DW
720}
721
722// Check whether this window wants to process messages, e.g. Stop button
723// in long calculations.
1be7f92a
DW
724bool wxCheckForInterrupt(
725 wxWindow* pWnd
726)
0e320a79 727{
1be7f92a
DW
728 if(pWnd)
729 {
730 QMSG vMsg;
9dea36ef
DW
731 HAB hab = 0;
732 HWND hwndFilter = NULLHANDLE;
1be7f92a 733 HWND hwndWin= (HWND) pWnd->GetHWND();
45fcbf3b 734
1be7f92a
DW
735 while(::WinPeekMsg(hab, &vMsg, hwndFilter, 0, 0, PM_REMOVE))
736 {
737 ::WinDispatchMsg(hab, &vMsg);
738 }
739 return TRUE;//*** temporary?
740 }
741 else
45fcbf3b 742 {
1be7f92a
DW
743 wxFAIL_MSG(_T("pWnd==NULL !!!"));
744 return FALSE;//*** temporary?
45fcbf3b 745 }
45fcbf3b
DW
746}
747
1be7f92a
DW
748void wxGetMousePosition(
749 int* pX
750, int* pY
751)
0e320a79 752{
1be7f92a
DW
753 POINTL vPt;
754
755 ::WinQueryPointerPos(HWND_DESKTOP, &vPt);
756 *pX = vPt.x;
757 *pY = vPt.y;
0e320a79
DW
758};
759
760// Return TRUE if we have a colour display
761bool wxColourDisplay()
762{
19193a2c 763#if 0
1be7f92a
DW
764 HPS hpsScreen;
765 HDC hdcScreen;
766 LONG lColors;
767
768 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
769 hdcScreen = ::GpiQueryDevice(hpsScreen);
770 ::DevQueryCaps(hdcScreen, CAPS_COLORS, 1L, &lColors);
771 return(lColors > 1L);
19193a2c
KB
772#else
773 // I don't see how the PM display could not be color. Besides, this
774 // was leaking DCs and PSs!!! MN
987da0d4 775 return TRUE;
19193a2c 776#endif
0e320a79
DW
777}
778
779// Returns depth of screen
780int wxDisplayDepth()
781{
1be7f92a
DW
782 HPS hpsScreen;
783 HDC hdcScreen;
784 LONG lPlanes;
785 LONG lBitsPerPixel;
19193a2c
KB
786 static LONG nDepth = 0;
787
788 // The screen colordepth ain't gonna change. No reason to query
789 // it over and over!
790 if (!nDepth) {
791 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
792 hdcScreen = ::GpiQueryDevice(hpsScreen);
793 ::DevQueryCaps(hdcScreen, CAPS_COLOR_PLANES, 1L, &lPlanes);
794 ::DevQueryCaps(hdcScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitsPerPixel);
795
796 nDepth = (int)(lPlanes * lBitsPerPixel);
797 ::DevCloseDC(hdcScreen);
798 ::WinReleasePS(hpsScreen);
799 }
d90895ac 800 return (nDepth);
0e320a79
DW
801}
802
803// Get size of display
1be7f92a
DW
804void wxDisplaySize(
805 int* pWidth
806, int* pHeight
807)
0e320a79 808{
1be7f92a
DW
809 HPS hpsScreen;
810 HDC hdcScreen;
19193a2c
KB
811 static LONG lWidth = 0;
812 static LONG lHeight = 0;
813
814 // The screen size ain't gonna change either so just cache the values
815 if (!lWidth) {
816 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
817 hdcScreen = ::GpiQueryDevice(hpsScreen);
818 ::DevQueryCaps(hdcScreen, CAPS_WIDTH, 1L, &lWidth);
819 ::DevQueryCaps(hdcScreen, CAPS_HEIGHT, 1L, &lHeight);
820 ::DevCloseDC(hdcScreen);
821 ::WinReleasePS(hpsScreen);
822 }
892b89f3
DW
823 *pWidth = (int)lWidth;
824 *pHeight = (int)lHeight;
45fcbf3b
DW
825}
826
5b3ed311
DW
827void wxDisplaySizeMM(
828 int* pWidth
829, int* pHeight
830)
831{
832 HPS hpsScreen;
833 HDC hdcScreen;
834
835 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
836 hdcScreen = ::GpiQueryDevice(hpsScreen);
837
838 if (pWidth)
839 ::DevQueryCaps( hdcScreen
840 ,CAPS_HORIZONTAL_RESOLUTION
841 ,1L
842 ,(PLONG)pWidth
843 );
844 if (pHeight)
845 ::DevQueryCaps( hdcScreen
846 ,CAPS_VERTICAL_RESOLUTION
847 ,1L
848 ,(PLONG)pHeight
849 );
19193a2c
KB
850 ::DevCloseDC(hdcScreen);
851 ::WinReleasePS(hpsScreen);
5b3ed311
DW
852}
853
ec5d7799
RD
854void wxClientDisplayRect(int *x, int *y, int *width, int *height)
855{
856 // This is supposed to return desktop dimensions minus any window
857 // manager panels, menus, taskbars, etc. If there is a way to do that
858 // for this platform please fix this function, otherwise it defaults
859 // to the entire desktop.
860 if (x) *x = 0;
861 if (y) *y = 0;
862 wxDisplaySize(width, height);
863}
864
865
1be7f92a
DW
866bool wxDirExists(
867 const wxString& rDir
868)
45fcbf3b 869{
1be7f92a 870 return (::DosSetCurrentDir(WXSTRINGCAST rDir));
45fcbf3b
DW
871}
872
873// ---------------------------------------------------------------------------
874// window information functions
875// ---------------------------------------------------------------------------
876
1be7f92a
DW
877wxString WXDLLEXPORT wxGetWindowText(
878 WXHWND hWnd
879)
45fcbf3b 880{
1be7f92a
DW
881 wxString vStr;
882 long lLen = ::WinQueryWindowTextLength((HWND)hWnd) + 1;
883
884 ::WinQueryWindowText((HWND)hWnd, lLen, vStr.GetWriteBuf((int)lLen));
885 vStr.UngetWriteBuf();
45fcbf3b 886
1be7f92a 887 return vStr;
45fcbf3b
DW
888}
889
1be7f92a
DW
890wxString WXDLLEXPORT wxGetWindowClass(
891 WXHWND hWnd
892)
45fcbf3b 893{
1be7f92a
DW
894 wxString vStr;
895 int nLen = 256; // some starting value
45fcbf3b
DW
896
897 for ( ;; )
898 {
1be7f92a 899 int nCount = ::WinQueryClassName((HWND)hWnd, nLen, vStr.GetWriteBuf(nLen));
45fcbf3b 900
1be7f92a
DW
901 vStr.UngetWriteBuf();
902 if (nCount == nLen )
45fcbf3b
DW
903 {
904 // the class name might have been truncated, retry with larger
905 // buffer
1be7f92a 906 nLen *= 2;
45fcbf3b
DW
907 }
908 else
909 {
910 break;
911 }
912 }
1be7f92a 913 return vStr;
45fcbf3b
DW
914}
915
1be7f92a
DW
916WXWORD WXDLLEXPORT wxGetWindowId(
917 WXHWND hWnd
918)
45fcbf3b
DW
919{
920 return ::WinQueryWindowUShort((HWND)hWnd, QWS_ID);
0e320a79
DW
921}
922
914589c2
DW
923wxString WXDLLEXPORT wxPMErrorToStr(
924 ERRORID vError
925)
926{
927 wxString sError;
928
929 //
930 // Remove the high order byte -- it is useless
931 //
932 vError &= 0x0000ffff;
933 switch(vError)
934 {
935 case PMERR_INVALID_HWND:
936 sError = wxT("Invalid window handle specified");
937 break;
938
939 case PMERR_INVALID_FLAG:
940 sError = wxT("Invalid flag bit set");
941 break;
942
943 case PMERR_NO_MSG_QUEUE:
944 sError = wxT("No message queue available");
945 break;
946
947 case PMERR_INVALID_PARM:
948 sError = wxT("Parameter contained invalid data");
949 break;
950
951 case PMERR_INVALID_PARAMETERS:
952 sError = wxT("Parameter value is out of range");
953 break;
954
955 case PMERR_PARAMETER_OUT_OF_RANGE:
956 sError = wxT("Parameter value is out of range");
957 break;
958
959 case PMERR_INVALID_INTEGER_ATOM:
960 sError = wxT("Not a valid atom");
961 break;
962
963 case PMERR_INVALID_HATOMTBL:
964 sError = wxT("Atom table handle is invalid");
965 break;
966
967 case PMERR_INVALID_ATOM_NAME:
968 sError = wxT("Not a valid atom name");
969 break;
970
971 case PMERR_ATOM_NAME_NOT_FOUND:
972 sError = wxT("Valid name format, but cannot find name in atom table");
973 break;
974
975 default:
976 sError = wxT("Unknown error");
977 }
978 return(sError);
979} // end of wxPMErrorToStr
980
008089f6
DW
981void wxDrawBorder(
982 HPS hPS
983, RECTL& rRect
984, WXDWORD dwStyle
985)
986{
987 POINTL vPoint[2];
988
989 vPoint[0].x = rRect.xLeft;
990 vPoint[0].y = rRect.yBottom;
991 ::GpiMove(hPS, &vPoint[0]);
992 if (dwStyle & wxSIMPLE_BORDER ||
993 dwStyle & wxSTATIC_BORDER)
994 {
ad7f3189
DW
995 vPoint[1].x = rRect.xRight - 1;
996 vPoint[1].y = rRect.yTop - 1;
008089f6
DW
997 ::GpiBox( hPS
998 ,DRO_OUTLINE
999 ,&vPoint[1]
1000 ,0L
1001 ,0L
1002 );
1003 }
1004 if (dwStyle & wxSUNKEN_BORDER)
1005 {
1006 LINEBUNDLE vLineBundle;
1007
ad7f3189 1008 vLineBundle.lColor = 0x00FFFFFF; // WHITE
008089f6
DW
1009 vLineBundle.usMixMode = FM_OVERPAINT;
1010 vLineBundle.fxWidth = 2;
1011 vLineBundle.lGeomWidth = 2;
1012 vLineBundle.usType = LINETYPE_SOLID;
1013 vLineBundle.usEnd = 0;
1014 vLineBundle.usJoin = 0;
1015 ::GpiSetAttrs( hPS
1016 ,PRIM_LINE
1017 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
1018 ,0L
1019 ,&vLineBundle
1020 );
ad7f3189
DW
1021 vPoint[1].x = rRect.xRight - 1;
1022 vPoint[1].y = rRect.yTop - 1;
008089f6
DW
1023 ::GpiBox( hPS
1024 ,DRO_OUTLINE
1025 ,&vPoint[1]
1026 ,0L
1027 ,0L
1028 );
ad7f3189
DW
1029 vPoint[0].x = rRect.xLeft + 1;
1030 vPoint[0].y = rRect.yBottom + 1;
1031 ::GpiMove(hPS, &vPoint[0]);
1032 vPoint[1].x = rRect.xRight - 2;
1033 vPoint[1].y = rRect.yTop - 2;
1034 ::GpiBox( hPS
1035 ,DRO_OUTLINE
1036 ,&vPoint[1]
1037 ,0L
1038 ,0L
1039 );
1040
008089f6
DW
1041 vLineBundle.lColor = 0x00000000; // BLACK
1042 vLineBundle.usMixMode = FM_OVERPAINT;
1043 vLineBundle.fxWidth = 2;
1044 vLineBundle.lGeomWidth = 2;
1045 vLineBundle.usType = LINETYPE_SOLID;
1046 vLineBundle.usEnd = 0;
1047 vLineBundle.usJoin = 0;
1048 ::GpiSetAttrs( hPS
1049 ,PRIM_LINE
1050 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
1051 ,0L
1052 ,&vLineBundle
1053 );
1054 vPoint[0].x = rRect.xLeft + 2;
1055 vPoint[0].y = rRect.yBottom + 2;
1056 ::GpiMove(hPS, &vPoint[0]);
1057 vPoint[1].x = rRect.xLeft + 2;
ad7f3189 1058 vPoint[1].y = rRect.yTop - 3;
008089f6 1059 ::GpiLine(hPS, &vPoint[1]);
ad7f3189
DW
1060 vPoint[1].x = rRect.xRight - 3;
1061 vPoint[1].y = rRect.yTop - 3;
1062 ::GpiLine(hPS, &vPoint[1]);
1063
1064 vPoint[0].x = rRect.xLeft + 3;
1065 vPoint[0].y = rRect.yBottom + 3;
1066 ::GpiMove(hPS, &vPoint[0]);
1067 vPoint[1].x = rRect.xLeft + 3;
1068 vPoint[1].y = rRect.yTop - 4;
1069 ::GpiLine(hPS, &vPoint[1]);
1070 vPoint[1].x = rRect.xRight - 4;
1071 vPoint[1].y = rRect.yTop - 4;
008089f6
DW
1072 ::GpiLine(hPS, &vPoint[1]);
1073 }
1074 if (dwStyle & wxDOUBLE_BORDER)
1075 {
ad7f3189
DW
1076 LINEBUNDLE vLineBundle;
1077
1078 vLineBundle.lColor = 0x00FFFFFF; // WHITE
1079 vLineBundle.usMixMode = FM_OVERPAINT;
1080 vLineBundle.fxWidth = 2;
1081 vLineBundle.lGeomWidth = 2;
1082 vLineBundle.usType = LINETYPE_SOLID;
1083 vLineBundle.usEnd = 0;
1084 vLineBundle.usJoin = 0;
1085 ::GpiSetAttrs( hPS
1086 ,PRIM_LINE
1087 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
1088 ,0L
1089 ,&vLineBundle
1090 );
1091 vPoint[1].x = rRect.xRight - 1;
1092 vPoint[1].y = rRect.yTop - 1;
1093 ::GpiBox( hPS
1094 ,DRO_OUTLINE
1095 ,&vPoint[1]
1096 ,0L
1097 ,0L
1098 );
1099 vLineBundle.lColor = 0x00000000; // WHITE
1100 vLineBundle.usMixMode = FM_OVERPAINT;
1101 vLineBundle.fxWidth = 2;
1102 vLineBundle.lGeomWidth = 2;
1103 vLineBundle.usType = LINETYPE_SOLID;
1104 vLineBundle.usEnd = 0;
1105 vLineBundle.usJoin = 0;
1106 ::GpiSetAttrs( hPS
1107 ,PRIM_LINE
1108 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
1109 ,0L
1110 ,&vLineBundle
1111 );
1112 vPoint[0].x = rRect.xLeft + 2;
1113 vPoint[0].y = rRect.yBottom + 2;
1114 ::GpiMove(hPS, &vPoint[0]);
1115 vPoint[1].x = rRect.xRight - 2;
1116 vPoint[1].y = rRect.yTop - 2;
1117 ::GpiBox( hPS
1118 ,DRO_OUTLINE
1119 ,&vPoint[1]
1120 ,0L
1121 ,0L
1122 );
1123 vLineBundle.lColor = 0x00FFFFFF; // BLACK
1124 vLineBundle.usMixMode = FM_OVERPAINT;
1125 vLineBundle.fxWidth = 2;
1126 vLineBundle.lGeomWidth = 2;
1127 vLineBundle.usType = LINETYPE_SOLID;
1128 vLineBundle.usEnd = 0;
1129 vLineBundle.usJoin = 0;
1130 ::GpiSetAttrs( hPS
1131 ,PRIM_LINE
1132 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
1133 ,0L
1134 ,&vLineBundle
1135 );
1136 vPoint[0].x = rRect.xLeft + 3;
1137 vPoint[0].y = rRect.yBottom + 3;
1138 ::GpiMove(hPS, &vPoint[0]);
1139 vPoint[1].x = rRect.xRight - 3;
1140 vPoint[1].y = rRect.yTop - 3;
1141 ::GpiBox( hPS
1142 ,DRO_OUTLINE
1143 ,&vPoint[1]
1144 ,0L
1145 ,0L
1146 );
008089f6
DW
1147 }
1148 if (dwStyle & wxRAISED_BORDER)
1149 {
ad7f3189
DW
1150 LINEBUNDLE vLineBundle;
1151
1152 vLineBundle.lColor = 0x00000000; // BLACK
1153 vLineBundle.usMixMode = FM_OVERPAINT;
1154 vLineBundle.fxWidth = 2;
1155 vLineBundle.lGeomWidth = 2;
1156 vLineBundle.usType = LINETYPE_SOLID;
1157 vLineBundle.usEnd = 0;
1158 vLineBundle.usJoin = 0;
1159 ::GpiSetAttrs( hPS
1160 ,PRIM_LINE
1161 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
1162 ,0L
1163 ,&vLineBundle
1164 );
1165 vPoint[1].x = rRect.xRight - 1;
1166 vPoint[1].y = rRect.yTop - 1;
1167 ::GpiBox( hPS
1168 ,DRO_OUTLINE
1169 ,&vPoint[1]
1170 ,0L
1171 ,0L
1172 );
1173 vPoint[0].x = rRect.xLeft + 1;
1174 vPoint[0].y = rRect.yBottom + 1;
1175 ::GpiMove(hPS, &vPoint[0]);
1176 vPoint[1].x = rRect.xRight - 2;
1177 vPoint[1].y = rRect.yTop - 2;
1178 ::GpiBox( hPS
1179 ,DRO_OUTLINE
1180 ,&vPoint[1]
1181 ,0L
1182 ,0L
1183 );
1184
1185 vLineBundle.lColor = 0x00FFFFFF; // WHITE
1186 vLineBundle.usMixMode = FM_OVERPAINT;
1187 vLineBundle.fxWidth = 2;
1188 vLineBundle.lGeomWidth = 2;
1189 vLineBundle.usType = LINETYPE_SOLID;
1190 vLineBundle.usEnd = 0;
1191 vLineBundle.usJoin = 0;
1192 ::GpiSetAttrs( hPS
1193 ,PRIM_LINE
1194 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
1195 ,0L
1196 ,&vLineBundle
1197 );
1198 vPoint[0].x = rRect.xLeft + 2;
1199 vPoint[0].y = rRect.yBottom + 2;
1200 ::GpiMove(hPS, &vPoint[0]);
1201 vPoint[1].x = rRect.xLeft + 2;
1202 vPoint[1].y = rRect.yTop - 3;
1203 ::GpiLine(hPS, &vPoint[1]);
1204 vPoint[1].x = rRect.xRight - 3;
1205 vPoint[1].y = rRect.yTop - 3;
1206 ::GpiLine(hPS, &vPoint[1]);
1207
1208 vPoint[0].x = rRect.xLeft + 3;
1209 vPoint[0].y = rRect.yBottom + 3;
1210 ::GpiMove(hPS, &vPoint[0]);
1211 vPoint[1].x = rRect.xLeft + 3;
1212 vPoint[1].y = rRect.yTop - 4;
1213 ::GpiLine(hPS, &vPoint[1]);
1214 vPoint[1].x = rRect.xRight - 4;
1215 vPoint[1].y = rRect.yTop - 4;
1216 ::GpiLine(hPS, &vPoint[1]);
008089f6
DW
1217 }
1218} // end of wxDrawBorder
914589c2 1219
3c299c3a
DW
1220void wxOS2SetFont(
1221 HWND hWnd
1222, const wxFont& rFont
1223)
1224{
1225 char zFont[128];
1226 char zFacename[30];
1227 char zWeight[30];
1228 char zStyle[30];
1229
1230 if (hWnd == NULLHANDLE)
e1146627 1231 return;
3c299c3a
DW
1232
1233 //
a23692f0 1234 // The fonts available for Presentation Params are just a few
3c299c3a
DW
1235 // outline fonts, the rest are available to the GPI, so we must
1236 // map the families to one of these three
1237 //
1238 switch(rFont.GetFamily())
1239 {
1240 case wxSCRIPT:
e1146627
DW
1241 strcpy(zFacename, "Script");
1242 break;
1243
3c299c3a 1244 case wxDECORATIVE:
a23692f0
DW
1245 strcpy(zFacename, "WarpSans");
1246 break;
1247
3c299c3a 1248 case wxROMAN:
a23692f0 1249 strcpy(zFacename,"Times New Roman");
3c299c3a
DW
1250 break;
1251
1252 case wxTELETYPE:
a23692f0 1253 strcpy(zFacename, "Courier New");
3c299c3a
DW
1254 break;
1255
e1146627 1256 case wxMODERN:
a23692f0 1257 strcpy(zFacename, "Courier New");
e1146627
DW
1258 break;
1259
3c299c3a
DW
1260 case wxDEFAULT:
1261 default:
a23692f0
DW
1262 case wxSWISS:
1263 strcpy(zFacename, "Helvetica");
3c299c3a
DW
1264 break;
1265 }
1266
1267 switch(rFont.GetWeight())
1268 {
1269 default:
1270 case wxNORMAL:
1271 case wxLIGHT:
1272 zWeight[0] = '\0';
1273 break;
1274
1275 case wxBOLD:
1276 case wxFONTWEIGHT_MAX:
1277 strcpy(zWeight, "Bold");
1278 break;
1279 }
1280
1281 switch(rFont.GetStyle())
1282 {
1283 case wxITALIC:
1284 case wxSLANT:
1285 strcpy(zStyle, "Italic");
1286 break;
1287
1288 default:
1289 zStyle[0] = '\0';
1290 break;
1291 }
1292 sprintf(zFont, "%d.%s", rFont.GetPointSize(), zFacename);
1293 if (zWeight[0] != '\0')
1294 {
1295 strcat(zFont, " ");
1296 strcat(zFont, zWeight);
1297 }
1298 if (zStyle[0] != '\0')
1299 {
1300 strcat(zFont, " ");
1301 strcat(zFont, zStyle);
1302 }
1303 ::WinSetPresParam(hWnd, PP_FONTNAMESIZE, strlen(zFont) + 1, (PVOID)zFont);
1304} // end of wxOS2SetFont
db16e5c3
DW
1305
1306// ---------------------------------------------------------------------------
1307// Helper for taking a regular bitmap and giving it a disabled look
1308// ---------------------------------------------------------------------------
1309wxBitmap wxDisableBitmap(
1310 const wxBitmap& rBmp
1311, long lColor
1312)
1313{
1314 wxMask* pMask = rBmp.GetMask();
1315
1316 if (!pMask)
1317 return(wxNullBitmap);
1318
1319 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
1320 SIZEL vSize = {0, 0};
1321 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
1322 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC);
1323 BITMAPINFOHEADER2 vHeader;
1324 BITMAPINFO2 vInfo;
1325 ERRORID vError;
1326 wxString sError;
1327 HBITMAP hBitmap = (HBITMAP)rBmp.GetHBITMAP();
1328 HBITMAP hOldBitmap = NULLHANDLE;
1329 HBITMAP hOldMask = NULLHANDLE;
1330 HBITMAP hMask = (HBITMAP)rBmp.GetMask()->GetMaskBitmap();
1331 unsigned char* pucBits; // buffer that will contain the bitmap data
1332 unsigned char* pucData; // pointer to use to traverse bitmap data
1333 unsigned char* pucBitsMask; // buffer that will contain the mask data
1334 unsigned char* pucDataMask; // pointer to use to traverse mask data
1335 LONG lScans = 0L;
1336 LONG lScansSet = 0L;
1337 bool bpp16 = (wxDisplayDepth() == 16);
1338
1339 memset(&vHeader, '\0', 16);
1340 vHeader.cbFix = 16;
1341
1342 memset(&vInfo, '\0', 16);
1343 vInfo.cbFix = 16;
1344 vInfo.cx = (ULONG)rBmp.GetWidth();
1345 vInfo.cy = (ULONG)rBmp.GetHeight();
1346 vInfo.cPlanes = 1;
1347 vInfo.cBitCount = 24; // Set to desired count going in
1348
1349 //
1350 // Create the buffers for data....all wxBitmaps are 24 bit internally
1351 //
1352 int nBytesPerLine = rBmp.GetWidth() * 3;
1353 int nSizeDWORD = sizeof(DWORD);
1354 int nLineBoundary = nBytesPerLine % nSizeDWORD;
1355 int nPadding = 0;
1356 int i;
1357 int j;
1358
1359 //
1360 // Bitmap must be ina double-word alligned address so we may
1361 // have some padding to worry about
1362 //
1363 if (nLineBoundary > 0)
1364 {
1365 nPadding = nSizeDWORD - nLineBoundary;
1366 nBytesPerLine += nPadding;
1367 }
1368 pucBits = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
1369 memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight()));
1370 pucBitsMask = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight());
1371 memset(pucBitsMask, '\0', (nBytesPerLine * rBmp.GetHeight()));
1372
1373 //
1374 // Extract the bitmap and mask data
1375 //
1376 if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR)
1377 {
1378 vError = ::WinGetLastError(vHabmain);
1379 sError = wxPMErrorToStr(vError);
1380 }
1381 ::GpiQueryBitmapInfoHeader(hBitmap, &vHeader);
1382 vInfo.cBitCount = 24;
1383 if ((lScans = ::GpiQueryBitmapBits( hPS
1384 ,0L
1385 ,(LONG)rBmp.GetHeight()
1386 ,(PBYTE)pucBits
1387 ,&vInfo
1388 )) == GPI_ALTERROR)
1389 {
1390 vError = ::WinGetLastError(vHabmain);
1391 sError = wxPMErrorToStr(vError);
1392 }
1393 if ((hOldMask = ::GpiSetBitmap(hPS, hMask)) == HBM_ERROR)
1394 {
1395 vError = ::WinGetLastError(vHabmain);
1396 sError = wxPMErrorToStr(vError);
1397 }
1398 ::GpiQueryBitmapInfoHeader(hMask, &vHeader);
1399 vInfo.cBitCount = 24;
1400 if ((lScans = ::GpiQueryBitmapBits( hPS
1401 ,0L
1402 ,(LONG)rBmp.GetHeight()
1403 ,(PBYTE)pucBitsMask
1404 ,&vInfo
1405 )) == GPI_ALTERROR)
1406 {
1407 vError = ::WinGetLastError(vHabmain);
1408 sError = wxPMErrorToStr(vError);
1409 }
1410 if (( hMask = ::GpiSetBitmap(hPS, hOldMask)) == HBM_ERROR)
1411 {
1412 vError = ::WinGetLastError(vHabmain);
1413 sError = wxPMErrorToStr(vError);
1414 }
1415 pucData = pucBits;
1416 pucDataMask = pucBitsMask;
1417
1418 //
1419 // Get the mask value
1420 //
1421 for (i = 0; i < rBmp.GetHeight(); i++)
1422 {
1423 for (j = 0; j < rBmp.GetWidth(); j++)
1424 {
1425 // Byte 1
1426 if (bpp16 && *pucDataMask == 0xF8) // 16 bit display gobblygook
1427 {
1428 *pucData = 0x7F;
1429 pucData++;
1430 }
1431 else if (*pucDataMask == 0xFF) // set to grey
1432 {
1433 *pucData = 0x7F;
1434 pucData++;
1435 }
1436 else
1437 {
1438 *pucData = ((unsigned char)(lColor >> 16));
1439 pucData++;
1440 }
1441
1442 // Byte 2
1443 if (bpp16 && *(pucDataMask + 1) == 0xFC) // 16 bit display gobblygook
1444 {
1445 *pucData = 0x7F;
1446 pucData++;
1447 }
1448 else if (*(pucDataMask + 1) == 0xFF) // set to grey
1449 {
1450 *pucData = 0x7F;
1451 pucData++;
1452 }
1453 else
1454 {
1455 *pucData = ((unsigned char)(lColor >> 8));
1456 pucData++;
1457 }
1458
1459 // Byte 3
1460 if (bpp16 && *(pucDataMask + 2) == 0xF8) // 16 bit display gobblygook
1461 {
1462 *pucData = 0x7F;
1463 pucData++;
1464 }
1465 else if (*(pucDataMask + 2) == 0xFF) // set to grey
1466 {
1467 *pucData = 0x7F;
1468 pucData++;
1469 }
1470 else
1471 {
1472 *pucData = ((unsigned char)lColor);
1473 pucData++;
1474 }
1475 pucDataMask += 3;
1476 }
1477 for (j = 0; j < nPadding; j++)
1478 {
1479 pucData++;
1480 pucDataMask++;
1481 }
1482 }
1483
1484 //
1485 // Create a new bitmap and set the modified bits
1486 //
1487 wxBitmap vNewBmp( rBmp.GetWidth()
1488 ,rBmp.GetHeight()
1489 ,24
1490 );
1491 HBITMAP hNewBmp = (HBITMAP)vNewBmp.GetHBITMAP();
1492
1493 if ((hOldBitmap = ::GpiSetBitmap(hPS, hNewBmp)) == HBM_ERROR)
1494 {
1495 vError = ::WinGetLastError(vHabmain);
1496 sError = wxPMErrorToStr(vError);
1497 }
1498 if ((lScansSet = ::GpiSetBitmapBits( hPS
1499 ,0L
1500 ,(LONG)rBmp.GetHeight()
1501 ,(PBYTE)pucBits
1502 ,&vInfo
1503 )) == GPI_ALTERROR)
1504
1505 {
1506 vError = ::WinGetLastError(vHabmain);
1507 sError = wxPMErrorToStr(vError);
1508 }
1509 wxMask* pNewMask;
1510
1511 pNewMask = new wxMask(pMask->GetMaskBitmap());
1512 vNewBmp.SetMask(pNewMask);
1513 free(pucBits);
1514 ::GpiSetBitmap(hPS, NULLHANDLE);
1515 ::GpiDestroyPS(hPS);
1516 ::DevCloseDC(hDC);
1517 if (vNewBmp.Ok())
1518 return(vNewBmp);
1519 return(wxNullBitmap);
1520} // end of wxDisableBitmap
1521
b45bca40
DW
1522COLORREF wxColourToRGB(
1523 const wxColour& rColor
1524)
1525{
1526 return(OS2RGB(rColor.Red(), rColor.Green(), rColor.Blue()));
1527} // end of wxColourToRGB