home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / os2 / utils.cpp < prev    next >
C/C++ Source or Header  |  2003-01-03  |  46KB  |  1,524 lines

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