Added a couple of fixes.
[wxWidgets.git] / src / os2 / utils.cpp
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$
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 #else
30 #include <direct.h>
31 #endif
32
33 #include "wx/log.h"
34
35 #include <io.h>
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <errno.h>
41 #include <stdarg.h>
42
43 #define PURE_32
44
45 #ifndef __EMX__
46 #include <upm.h>
47 #include <netcons.h>
48 #include <netbios.h>
49 #endif
50
51 static const wxChar WX_SECTION[] = _T("wxWindows");
52 static const wxChar eHOSTNAME[] = _T("HostName");
53 static const wxChar eUSERID[] = _T("UserId");
54 static const wxChar eUSERNAME[] = _T("UserName");
55
56 // For the following functions we SHOULD fill in support
57 // for Windows-NT (which I don't know) as I assume it begin
58 // a POSIX Unix (so claims MS) that it has some special
59 // functions beyond those provided by WinSock
60
61 // Get full hostname (eg. DoDo.BSn-Germany.crg.de)
62 bool wxGetHostName(
63 wxChar* zBuf
64 , int nMaxSize
65 )
66 {
67 #if wxUSE_NET_API
68 char zServer[256];
69 char zComputer[256];
70 unsigned long ulLevel = 0;
71 unsigned char* zBuffer = NULL;
72 unsigned long ulBuffer = 256;
73 unsigned long* pulTotalAvail = NULL;
74
75 NetBios32GetInfo( (const unsigned char*)zServer
76 ,(const unsigned char*)zComputer
77 ,ulLevel
78 ,zBuffer
79 ,ulBuffer
80 ,pulTotalAvail
81 );
82 strcpy(zBuf, zServer);
83 #else
84 wxChar* zSysname;
85 const wxChar* zDefaultHost = _T("noname");
86
87 if ((zSysname = wxGetenv(_T("SYSTEM_NAME"))) == NULL)
88 {
89 ULONG n = ::PrfQueryProfileString( HINI_PROFILE
90 ,(PSZ)WX_SECTION
91 ,(PSZ)eHOSTNAME
92 ,(PSZ)zDefaultHost
93 ,(void*)zBuf
94 ,(ULONG)nMaxSize - 1
95 );
96 }
97 else
98 wxStrncpy(zBuf, zSysname, nMaxSize - 1);
99 zBuf[nMaxSize] = _T('\0');
100 #endif
101 return *zBuf ? TRUE : FALSE;
102 }
103
104 // Get user ID e.g. jacs
105 bool wxGetUserId(
106 wxChar* zBuf
107 , int nType
108 )
109 {
110 #ifndef __EMX__
111 long lrc;
112 // UPM procs return 0 on success
113 lrc = U32ELOCU((unsigned char*)zBuf, (unsigned long *)&nType);
114 if (lrc == 0) return TRUE;
115 #endif
116 return FALSE;
117 }
118
119 bool wxGetUserName(
120 wxChar* zBuf
121 , int nMaxSize
122 )
123 {
124 #ifdef USE_NET_API
125 wxGetUserId( zBuf
126 ,nMaxSize
127 );
128 #else
129 wxStrncpy(zBuf, _T("Unknown User"), nMaxSize);
130 #endif
131 return TRUE;
132 }
133
134 int wxKill(
135 long lPid
136 , int nSig
137 )
138 {
139 return((int)::DosKillProcess(0, (PID)lPid));
140 }
141
142 //
143 // Execute a program in an Interactive Shell
144 //
145 bool wxShell(
146 const wxString& rCommand
147 )
148 {
149 wxChar* zShell = _T("CMD.EXE");
150 wxString sInputs;
151 wxChar zTmp[255];
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
167 sInputs = "/C " + rCommand;
168 SData.PgmInputs = (BYTE*)sInputs.c_str();
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);
185 if (rc == 0 || rc == 457) // NO_ERROR or SMG_START_IN_BACKGROUND
186 {
187 PTIB ptib;
188 PPIB ppib;
189
190 ::DosGetInfoBlocks(&ptib, &ppib);
191
192 ::DosWaitChild( DCWA_PROCESS
193 ,DCWW_WAIT
194 ,&vResult
195 ,&ppib->pib_ulpid
196 ,vPid
197 );
198 }
199 return (rc != 0);
200 }
201
202 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
203 long wxGetFreeMemory()
204 {
205 void* pMemptr = NULL;
206 ULONG lSize;
207 ULONG lMemFlags;
208 APIRET rc;
209
210 lMemFlags = PAG_FREE;
211 rc = ::DosQueryMem(pMemptr, &lSize, &lMemFlags);
212 if (rc != 0)
213 return -1L;
214 return (long)lSize;
215 }
216
217 // Sleep for nSecs seconds. Attempt a Windows implementation using timers.
218 static bool inTimer = FALSE;
219
220 class wxSleepTimer: public wxTimer
221 {
222 public:
223 inline void Notify()
224 {
225 inTimer = FALSE;
226 Stop();
227 }
228 };
229
230 static wxTimer* wxTheSleepTimer = NULL;
231
232 void wxUsleep(
233 unsigned long ulMilliseconds
234 )
235 {
236 ::DosSleep(ulMilliseconds/1000l);
237 }
238
239 void wxSleep(
240 int nSecs
241 )
242 {
243 ::DosSleep(1000 * nSecs);
244 }
245
246 // Consume all events until no more left
247 void wxFlushEvents()
248 {
249 // wxYield();
250 }
251
252 // Output a debug mess., in a system dependent fashion.
253 void wxDebugMsg(
254 const wxChar* zFmt ...
255 )
256 {
257 va_list vAp;
258 static wxChar zBuffer[512];
259
260 if (!wxTheApp->GetWantDebugOutput())
261 return ;
262 va_start(vAp, zFmt);
263 sprintf(zBuffer, zFmt, vAp) ;
264 va_end(vAp);
265 }
266
267 // Non-fatal error: pop up message box and (possibly) continue
268 void wxError(
269 const wxString& rMsg
270 , const wxString& rTitle
271 )
272 {
273 wxBuffer = new wxChar[256];
274 wxSprintf(wxBuffer, "%s\nContinue?", WXSTRINGCAST rMsg);
275 if (::WinMessageBox( HWND_DESKTOP
276 ,NULL
277 ,(PSZ)wxBuffer
278 ,(PSZ)WXSTRINGCAST rTitle
279 ,0
280 ,MB_ICONEXCLAMATION | MB_YESNO
281 ) == MBID_YES)
282 delete[] wxBuffer;
283 wxExit();
284 }
285
286 // Fatal error: pop up message box and abort
287 void wxFatalError(
288 const wxString& rMsg
289 , const wxString& rTitle
290 )
291 {
292 unsigned long ulRc;
293
294 ulRc = ::WinMessageBox( HWND_DESKTOP
295 ,NULL
296 ,WXSTRINGCAST rMsg
297 ,WXSTRINGCAST rTitle
298 ,0
299 ,MB_NOICON | MB_OK
300 );
301 DosExit(EXIT_PROCESS, ulRc);
302 }
303
304 // Emit a beeeeeep
305 void wxBell()
306 {
307 DosBeep(1000,1000); // 1kHz during 1 sec.
308 }
309
310 // Chris Breeze 27/5/98: revised WIN32 code to
311 // detect WindowsNT correctly
312 int wxGetOsVersion(
313 int* pMajorVsn
314 , int* pMinorVsn
315 )
316 {
317 ULONG ulSysInfo[QSV_MAX] = {0};
318 APIRET ulrc;
319
320 ulrc = ::DosQuerySysInfo( 1L
321 ,QSV_MAX
322 ,(PVOID)ulSysInfo
323 ,sizeof(ULONG) * QSV_MAX
324 );
325 if (ulrc == 0L)
326 {
327 *pMajorVsn = ulSysInfo[QSV_VERSION_MAJOR];
328 *pMajorVsn = *pMajorVsn/10;
329 *pMinorVsn = ulSysInfo[QSV_VERSION_MINOR];
330 return wxWINDOWS_OS2;
331 }
332 return wxWINDOWS; // error if we get here, return generic value
333 }
334
335 // Reading and writing resources (eg WIN.INI, .Xdefaults)
336 #if wxUSE_RESOURCES
337 bool wxWriteResource(
338 const wxString& rSection
339 , const wxString& rEntry
340 , const wxString& rValue
341 , const wxString& rFile
342 )
343 {
344 HAB hab = 0;
345 HINI hIni = 0;
346
347 if (rFile != "")
348 {
349 hIni = ::PrfOpenProfile(hab, (PSZ)WXSTRINGCAST rFile);
350 if (hIni != 0L)
351 {
352 return (::PrfWriteProfileString( hIni
353 ,(PSZ)WXSTRINGCAST rSection
354 ,(PSZ)WXSTRINGCAST rEntry
355 ,(PSZ)WXSTRINGCAST rValue
356 ));
357 }
358 }
359 else
360 return (::PrfWriteProfileString( HINI_PROFILE
361 ,(PSZ)WXSTRINGCAST rSection
362 ,(PSZ)WXSTRINGCAST rEntry
363 ,(PSZ)WXSTRINGCAST rValue
364 ));
365 return FALSE;
366 }
367
368 bool wxWriteResource(
369 const wxString& rSection
370 , const wxString& rEntry
371 , float fValue
372 , const wxString& rFile
373 )
374 {
375 wxChar zBuf[50];
376
377 wxSprintf(zBuf, "%.4f", fValue);
378 return wxWriteResource( rSection
379 ,rEntry
380 ,zBuf
381 ,rFile
382 );
383 }
384
385 bool wxWriteResource(
386 const wxString& rSection
387 , const wxString& rEntry
388 , long lValue
389 , const wxString& rFile
390 )
391 {
392 wxChar zBuf[50];
393
394 wxSprintf(zBuf, "%ld", lValue);
395 return wxWriteResource( rSection
396 ,rEntry
397 ,zBuf
398 ,rFile
399 );
400 }
401
402 bool wxWriteResource(
403 const wxString& rSection
404 , const wxString& rEntry
405 , int lValue
406 , const wxString& rFile
407 )
408 {
409 wxChar zBuf[50];
410
411 wxSprintf(zBuf, "%d", lValue);
412 return wxWriteResource( rSection
413 ,rEntry
414 ,zBuf
415 ,rFile
416 );
417 }
418
419 bool wxGetResource(
420 const wxString& rSection
421 , const wxString& rEntry
422 , wxChar** ppValue
423 , const wxString& rFile
424 )
425 {
426 HAB hab = 0;
427 HINI hIni = 0;
428 wxChar zDefunkt[] = _T("$$default");
429 char zBuf[1000];
430
431 if (rFile != "")
432 {
433 hIni = ::PrfOpenProfile(hab, (PSZ)WXSTRINGCAST rFile);
434 if (hIni != 0L)
435 {
436 ULONG n = ::PrfQueryProfileString( hIni
437 ,(PSZ)WXSTRINGCAST rSection
438 ,(PSZ)WXSTRINGCAST rEntry
439 ,(PSZ)zDefunkt
440 ,(PVOID)zBuf
441 ,1000
442 );
443 if (zBuf == NULL)
444 return FALSE;
445 if (n == 0L || wxStrcmp(zBuf, zDefunkt) == 0)
446 return FALSE;
447 zBuf[n-1] = '\0';
448 }
449 else
450 return FALSE;
451 }
452 else
453 {
454 ULONG n = ::PrfQueryProfileString( HINI_PROFILE
455 ,(PSZ)WXSTRINGCAST rSection
456 ,(PSZ)WXSTRINGCAST rEntry
457 ,(PSZ)zDefunkt
458 ,(PVOID)zBuf
459 ,1000
460 );
461 if (zBuf == NULL)
462 return FALSE;
463 if (n == 0L || wxStrcmp(zBuf, zDefunkt) == 0)
464 return FALSE;
465 zBuf[n-1] = '\0';
466 }
467 strcpy((char*)*ppValue, zBuf);
468 return TRUE;
469 }
470
471 bool wxGetResource(
472 const wxString& rSection
473 , const wxString& rEntry
474 , float* pValue
475 , const wxString& rFile
476 )
477 {
478 wxChar* zStr = NULL;
479
480 zStr = new wxChar[1000];
481 bool bSucc = wxGetResource( rSection
482 ,rEntry
483 ,(wxChar **)&zStr
484 ,rFile
485 );
486
487 if (bSucc)
488 {
489 *pValue = (float)wxStrtod(zStr, NULL);
490 delete[] zStr;
491 return TRUE;
492 }
493 else
494 {
495 delete[] zStr;
496 return FALSE;
497 }
498 }
499
500 bool wxGetResource(
501 const wxString& rSection
502 , const wxString& rEntry
503 , long* pValue
504 , const wxString& rFile
505 )
506 {
507 wxChar* zStr = NULL;
508
509 zStr = new wxChar[1000];
510 bool bSucc = wxGetResource( rSection
511 ,rEntry
512 ,(wxChar **)&zStr
513 ,rFile
514 );
515
516 if (bSucc)
517 {
518 *pValue = wxStrtol(zStr, NULL, 10);
519 delete[] zStr;
520 return TRUE;
521 }
522 else
523 {
524 delete[] zStr;
525 return FALSE;
526 }
527 }
528
529 bool wxGetResource(
530 const wxString& rSection
531 , const wxString& rEntry
532 , int* pValue
533 , const wxString& rFile
534 )
535 {
536 wxChar* zStr = NULL;
537
538 zStr = new wxChar[1000];
539 bool bSucc = wxGetResource( rSection
540 ,rEntry
541 ,(wxChar **)&zStr
542 ,rFile
543 );
544
545 if (bSucc)
546 {
547 *pValue = (int)wxStrtol(zStr, NULL, 10);
548 delete[] zStr;
549 return TRUE;
550 }
551 else
552 {
553 delete[] zStr;
554 return FALSE;
555 }
556 }
557 #endif // wxUSE_RESOURCES
558
559 // ---------------------------------------------------------------------------
560 // helper functions for showing a "busy" cursor
561 // ---------------------------------------------------------------------------
562
563 HCURSOR gs_wxBusyCursor = 0; // new, busy cursor
564 HCURSOR gs_wxBusyCursorOld = 0; // old cursor
565 static int gs_wxBusyCursorCount = 0;
566
567 // Set the cursor to the busy cursor for all windows
568 void wxBeginBusyCursor(
569 wxCursor* pCursor
570 )
571 {
572 if ( gs_wxBusyCursorCount++ == 0 )
573 {
574 gs_wxBusyCursor = (HCURSOR)pCursor->GetHCURSOR();
575 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursor);
576 }
577 //else: nothing to do, already set
578 }
579
580 // Restore cursor to normal
581 void wxEndBusyCursor()
582 {
583 wxCHECK_RET( gs_wxBusyCursorCount > 0
584 ,_T("no matching wxBeginBusyCursor() for wxEndBusyCursor()")
585 );
586
587 if (--gs_wxBusyCursorCount == 0)
588 {
589 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursorOld);
590 gs_wxBusyCursorOld = 0;
591 }
592 }
593
594 // TRUE if we're between the above two calls
595 bool wxIsBusy()
596 {
597 return (gs_wxBusyCursorCount > 0);
598 }
599
600 // ---------------------------------------------------------------------------
601 const wxChar* wxGetHomeDir(
602 wxString* pStr
603 )
604 {
605 wxString& rStrDir = *pStr;
606
607 // OS/2 has no idea about home,
608 // so use the working directory instead?
609
610 // 256 was taken from os2def.h
611 #ifndef MAX_PATH
612 # define MAX_PATH 256
613 #endif
614
615 char zDirName[256];
616 ULONG ulDirLen;
617
618 ::DosQueryCurrentDir(0, zDirName, &ulDirLen);
619 rStrDir = zDirName;
620 return rStrDir.c_str();
621 }
622
623 // Hack for OS/2
624 wxChar* wxGetUserHome (
625 const wxString& rUser
626 )
627 {
628 wxChar* zHome;
629 wxString sUser1(rUser);
630
631 wxBuffer = new wxChar[256];
632 #ifndef __EMX__
633 if (sUser1 != _T(""))
634 {
635 wxChar zTmp[64];
636
637 if (wxGetUserId( zTmp
638 ,sizeof(zTmp)/sizeof(char)
639 ))
640 {
641 // Guests belong in the temp dir
642 if (wxStricmp(zTmp, _T("annonymous")) == 0)
643 {
644 if ((zHome = wxGetenv(_T("TMP"))) != NULL ||
645 (zHome = wxGetenv(_T("TMPDIR"))) != NULL ||
646 (zHome = wxGetenv(_T("TEMP"))) != NULL)
647 delete[] wxBuffer;
648 return *zHome ? zHome : (wxChar*)_T("\\");
649 }
650 if (wxStricmp(zTmp, WXSTRINGCAST sUser1) == 0)
651 sUser1 = _T("");
652 }
653 }
654 #endif
655 if (sUser1 == _T(""))
656 {
657 if ((zHome = wxGetenv(_T("HOME"))) != NULL)
658 {
659 wxStrcpy(wxBuffer, zHome);
660 Unix2DosFilename(wxBuffer);
661 wxStrcpy(zHome, wxBuffer);
662 delete[] wxBuffer;
663 return zHome;
664 }
665 }
666 delete[] wxBuffer;
667 return NULL; // No home known!
668 }
669
670 // Check whether this window wants to process messages, e.g. Stop button
671 // in long calculations.
672 bool wxCheckForInterrupt(
673 wxWindow* pWnd
674 )
675 {
676 if(pWnd)
677 {
678 QMSG vMsg;
679 HAB hab = 0;
680 HWND hwndFilter = NULLHANDLE;
681 HWND hwndWin= (HWND) pWnd->GetHWND();
682
683 while(::WinPeekMsg(hab, &vMsg, hwndFilter, 0, 0, PM_REMOVE))
684 {
685 ::WinDispatchMsg(hab, &vMsg);
686 }
687 return TRUE;//*** temporary?
688 }
689 else
690 {
691 wxFAIL_MSG(_T("pWnd==NULL !!!"));
692 return FALSE;//*** temporary?
693 }
694 }
695
696 void wxGetMousePosition(
697 int* pX
698 , int* pY
699 )
700 {
701 POINTL vPt;
702
703 ::WinQueryPointerPos(HWND_DESKTOP, &vPt);
704 *pX = vPt.x;
705 *pY = vPt.y;
706 };
707
708 // Return TRUE if we have a colour display
709 bool wxColourDisplay()
710 {
711 HPS hpsScreen;
712 HDC hdcScreen;
713 LONG lColors;
714
715 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
716 hdcScreen = ::GpiQueryDevice(hpsScreen);
717 ::DevQueryCaps(hdcScreen, CAPS_COLORS, 1L, &lColors);
718 return(lColors > 1L);
719 }
720
721 // Returns depth of screen
722 int wxDisplayDepth()
723 {
724 HPS hpsScreen;
725 HDC hdcScreen;
726 LONG lPlanes;
727 LONG lBitsPerPixel;
728 LONG nDepth;
729
730 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
731 hdcScreen = ::GpiQueryDevice(hpsScreen);
732 ::DevQueryCaps(hdcScreen, CAPS_COLOR_PLANES, 1L, &lPlanes);
733 ::DevQueryCaps(hdcScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitsPerPixel);
734
735 nDepth = (int)(lPlanes * lBitsPerPixel);
736 DevCloseDC(hdcScreen);
737 return (nDepth);
738 }
739
740 // Get size of display
741 void wxDisplaySize(
742 int* pWidth
743 , int* pHeight
744 )
745 {
746 HPS hpsScreen;
747 HDC hdcScreen;
748 LONG lWidth;
749 LONG lHeight;
750
751 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP);
752 hdcScreen = ::GpiQueryDevice(hpsScreen);
753 ::DevQueryCaps(hdcScreen, CAPS_WIDTH, 1L, &lWidth);
754 ::DevQueryCaps(hdcScreen, CAPS_HEIGHT, 1L, &lHeight);
755 DevCloseDC(hdcScreen);
756 *pWidth = (int)lWidth;
757 *pHeight = (int)lHeight;
758 }
759
760 bool wxDirExists(
761 const wxString& rDir
762 )
763 {
764 return (::DosSetCurrentDir(WXSTRINGCAST rDir));
765 }
766
767 // ---------------------------------------------------------------------------
768 // window information functions
769 // ---------------------------------------------------------------------------
770
771 wxString WXDLLEXPORT wxGetWindowText(
772 WXHWND hWnd
773 )
774 {
775 wxString vStr;
776 long lLen = ::WinQueryWindowTextLength((HWND)hWnd) + 1;
777
778 ::WinQueryWindowText((HWND)hWnd, lLen, vStr.GetWriteBuf((int)lLen));
779 vStr.UngetWriteBuf();
780
781 return vStr;
782 }
783
784 wxString WXDLLEXPORT wxGetWindowClass(
785 WXHWND hWnd
786 )
787 {
788 wxString vStr;
789 int nLen = 256; // some starting value
790
791 for ( ;; )
792 {
793 int nCount = ::WinQueryClassName((HWND)hWnd, nLen, vStr.GetWriteBuf(nLen));
794
795 vStr.UngetWriteBuf();
796 if (nCount == nLen )
797 {
798 // the class name might have been truncated, retry with larger
799 // buffer
800 nLen *= 2;
801 }
802 else
803 {
804 break;
805 }
806 }
807 return vStr;
808 }
809
810 WXWORD WXDLLEXPORT wxGetWindowId(
811 WXHWND hWnd
812 )
813 {
814 return ::WinQueryWindowUShort((HWND)hWnd, QWS_ID);
815 }
816
817 wxString WXDLLEXPORT wxPMErrorToStr(
818 ERRORID vError
819 )
820 {
821 wxString sError;
822
823 //
824 // Remove the high order byte -- it is useless
825 //
826 vError &= 0x0000ffff;
827 switch(vError)
828 {
829 case PMERR_INVALID_HWND:
830 sError = wxT("Invalid window handle specified");
831 break;
832
833 case PMERR_INVALID_FLAG:
834 sError = wxT("Invalid flag bit set");
835 break;
836
837 case PMERR_NO_MSG_QUEUE:
838 sError = wxT("No message queue available");
839 break;
840
841 case PMERR_INVALID_PARM:
842 sError = wxT("Parameter contained invalid data");
843 break;
844
845 case PMERR_INVALID_PARAMETERS:
846 sError = wxT("Parameter value is out of range");
847 break;
848
849 case PMERR_PARAMETER_OUT_OF_RANGE:
850 sError = wxT("Parameter value is out of range");
851 break;
852
853 case PMERR_INVALID_INTEGER_ATOM:
854 sError = wxT("Not a valid atom");
855 break;
856
857 case PMERR_INVALID_HATOMTBL:
858 sError = wxT("Atom table handle is invalid");
859 break;
860
861 case PMERR_INVALID_ATOM_NAME:
862 sError = wxT("Not a valid atom name");
863 break;
864
865 case PMERR_ATOM_NAME_NOT_FOUND:
866 sError = wxT("Valid name format, but cannot find name in atom table");
867 break;
868
869 default:
870 sError = wxT("Unknown error");
871 }
872 return(sError);
873 } // end of wxPMErrorToStr
874
875