Improved error handling.
[wxWidgets.git] / src / os2 / utils.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/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 licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #include "wx/utils.h"
16
17 #ifndef WX_PRECOMP
18 #include "wx/app.h"
19 #include "wx/intl.h"
20 #include "wx/log.h"
21 #endif //WX_PRECOMP
22
23 #include "wx/os2/private.h"
24 #include "wx/apptrait.h"
25
26 #include <ctype.h>
27 #ifdef __EMX__
28 #include <dirent.h>
29 #endif
30
31
32 #include <io.h>
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <errno.h>
38 #include <stdarg.h>
39
40 #define PURE_32
41
42 #if defined(__WATCOMC__)
43 extern "C"
44 {
45 #include <upm.h>
46 }
47 #elif !defined(__EMX__)
48 #include <upm.h>
49 #include <netcons.h>
50 #include <netbios.h>
51 #endif
52
53 static const wxChar WX_SECTION[] = _T("wxWidgets");
54 static const wxChar eHOSTNAME[] = _T("HostName");
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( wxChar* zBuf, int nMaxSize )
63 {
64 if (!zBuf) return false;
65
66 #if defined(wxUSE_NET_API) && wxUSE_NET_API
67 char zServer[256];
68 char zComputer[256];
69 unsigned long ulLevel = 0;
70 unsigned char* zBuffer = NULL;
71 unsigned long ulBuffer = 256;
72 unsigned long* pulTotalAvail = NULL;
73
74 NetBios32GetInfo( (const unsigned char*)zServer
75 ,(const unsigned char*)zComputer
76 ,ulLevel
77 ,zBuffer
78 ,ulBuffer
79 ,pulTotalAvail
80 );
81 strcpy(zBuf, zServer);
82 #else
83 wxChar* zSysname;
84 const wxChar* zDefaultHost = _T("noname");
85
86 if ((zSysname = wxGetenv(_T("SYSTEM_NAME"))) == NULL)
87 {
88 ::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 {
98 wxStrncpy(zBuf, zSysname, nMaxSize - 1);
99 }
100
101 zBuf[nMaxSize] = _T('\0');
102 #endif
103
104 return *zBuf ? true : false;
105 }
106
107 // Get user ID e.g. jacs
108 bool wxGetUserId(wxChar* zBuf, int nType)
109 {
110 #if defined(__VISAGECPP__) || defined(__WATCOMC__)
111 // UPM procs return 0 on success
112 long lrc = U32ELOCU((PUCHAR)zBuf, (PULONG)&nType);
113 if (lrc == 0) return true;
114 #endif
115 return false;
116 }
117
118 bool wxGetUserName( wxChar* zBuf, int nMaxSize )
119 {
120 #ifdef USE_NET_API
121 wxGetUserId( zBuf, nMaxSize );
122 #else
123 wxStrncpy(zBuf, _T("Unknown User"), nMaxSize);
124 #endif
125 return true;
126 }
127
128 int wxKill(long lPid,
129 wxSignal WXUNUSED(eSig),
130 wxKillError* WXUNUSED(peError),
131 int WXUNUSED(flags))
132 {
133 return((int)::DosKillProcess(0, (PID)lPid));
134 }
135
136 //
137 // Execute a program in an Interactive Shell
138 //
139 bool wxShell( const wxString& rCommand )
140 {
141 wxChar* zShell = _T("CMD.EXE");
142 wxString sInputs;
143 STARTDATA SData = {0};
144 PSZ PgmTitle = "Command Shell";
145 APIRET rc;
146 PID vPid = 0;
147 ULONG ulSessID = 0;
148 UCHAR achObjBuf[256] = {0}; //error data if DosStart fails
149 RESULTCODES vResult;
150
151 SData.Length = sizeof(STARTDATA);
152 SData.Related = SSF_RELATED_INDEPENDENT;
153 SData.FgBg = SSF_FGBG_FORE;
154 SData.TraceOpt = SSF_TRACEOPT_NONE;
155 SData.PgmTitle = PgmTitle;
156 SData.PgmName = (char*)zShell;
157
158 sInputs = _T("/C ") + rCommand;
159 SData.PgmInputs = (BYTE*)sInputs.c_str();
160 SData.TermQ = 0;
161 SData.Environment = 0;
162 SData.InheritOpt = SSF_INHERTOPT_SHELL;
163 SData.SessionType = SSF_TYPE_WINDOWABLEVIO;
164 SData.IconFile = 0;
165 SData.PgmHandle = 0;
166 SData.PgmControl = SSF_CONTROL_VISIBLE | SSF_CONTROL_MAXIMIZE;
167 SData.InitXPos = 30;
168 SData.InitYPos = 40;
169 SData.InitXSize = 200;
170 SData.InitYSize = 140;
171 SData.Reserved = 0;
172 SData.ObjectBuffer = (char*)achObjBuf;
173 SData.ObjectBuffLen = (ULONG)sizeof(achObjBuf);
174
175 rc = ::DosStartSession(&SData, &ulSessID, &vPid);
176 if (rc == 0 || rc == 457) // NO_ERROR or SMG_START_IN_BACKGROUND
177 {
178 PTIB ptib;
179 PPIB ppib;
180
181 ::DosGetInfoBlocks(&ptib, &ppib);
182
183 ::DosWaitChild( DCWA_PROCESS
184 ,DCWW_WAIT
185 ,&vResult
186 ,&ppib->pib_ulpid
187 ,vPid
188 );
189 }
190 return (rc != 0);
191 }
192
193 // Shutdown or reboot the PC
194 bool wxShutdown(wxShutdownFlags WXUNUSED(wFlags))
195 {
196 // TODO
197 return false;
198 }
199
200 // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX)
201 wxMemorySize wxGetFreeMemory()
202 {
203 void* pMemptr = NULL;
204 LONG lSize;
205 ULONG lMemFlags;
206 APIRET rc;
207
208 lMemFlags = PAG_FREE;
209 rc = ::DosQueryMem(pMemptr, (PULONG)&lSize, &lMemFlags);
210 if (rc != 0)
211 lSize = -1L;
212 return (wxMemorySize)lSize;
213 }
214
215 // Get Process ID
216 unsigned long wxGetProcessId()
217 {
218 return (unsigned long)getpid();
219 }
220
221 // ----------------------------------------------------------------------------
222 // env vars
223 // ----------------------------------------------------------------------------
224
225 bool wxGetEnv(const wxString& var, wxString *value)
226 {
227 // wxGetenv is defined as getenv()
228 wxChar *p = wxGetenv(var);
229 if ( !p )
230 return false;
231
232 if ( value )
233 {
234 *value = p;
235 }
236
237 return true;
238 }
239
240 bool wxSetEnv(const wxString& variable, const wxChar *value)
241 {
242 #if defined(HAVE_SETENV)
243 return setenv(variable.mb_str(), value ? wxString(value).mb_str().data()
244 : NULL, 1 /* overwrite */) == 0;
245 #elif defined(HAVE_PUTENV)
246 wxString s = variable;
247 if ( value )
248 s << _T('=') << value;
249
250 // transform to ANSI
251 const char *p = s.mb_str();
252
253 // the string will be free()d by libc
254 char *buf = (char *)malloc(strlen(p) + 1);
255 strcpy(buf, p);
256
257 return putenv(buf) == 0;
258 #else // no way to set an env var
259 wxUnusedVar(variable);
260 wxUnusedVar(value);
261 return false;
262 #endif
263 }
264
265 void wxMilliSleep(
266 unsigned long ulMilliseconds
267 )
268 {
269 ::DosSleep(ulMilliseconds);
270 }
271
272 void wxMicroSleep(
273 unsigned long ulMicroseconds
274 )
275 {
276 ::DosSleep(ulMicroseconds/1000);
277 }
278
279 void wxSleep(
280 int nSecs
281 )
282 {
283 ::DosSleep(1000 * nSecs);
284 }
285
286 // Consume all events until no more left
287 void wxFlushEvents()
288 {
289 // wxYield();
290 }
291
292 // Emit a beeeeeep
293 void wxBell()
294 {
295 DosBeep(1000,1000); // 1kHz during 1 sec.
296 }
297
298 wxString wxGetOsDescription()
299 {
300 wxString strVer(_T("OS/2"));
301 ULONG ulSysInfo[QSV_MAX] = {0};
302
303 if (::DosQuerySysInfo( 1L,
304 QSV_MAX,
305 (PVOID)ulSysInfo,
306 sizeof(ULONG) * QSV_MAX
307 ) == 0L )
308 {
309 wxString ver;
310 ver.Printf( _T(" ver. %d.%d rev. %c"),
311 int(ulSysInfo[QSV_VERSION_MAJOR] / 10),
312 int(ulSysInfo[QSV_VERSION_MINOR]),
313 char(ulSysInfo[QSV_VERSION_REVISION])
314 );
315 strVer += ver;
316 }
317
318 return strVer;
319 }
320
321 void wxAppTraits::InitializeGui(unsigned long &WXUNUSED(ulHab))
322 {
323 }
324
325 void wxAppTraits::TerminateGui(unsigned long WXUNUSED(ulHab))
326 {
327 }
328
329 wxToolkitInfo & wxConsoleAppTraits::GetToolkitInfo()
330 {
331 static wxToolkitInfo vInfo;
332 ULONG ulSysInfo[QSV_MAX] = {0};
333 APIRET ulrc;
334
335 vInfo.name = _T("wxBase");
336 ulrc = ::DosQuerySysInfo( 1L
337 ,QSV_MAX
338 ,(PVOID)ulSysInfo
339 ,sizeof(ULONG) * QSV_MAX
340 );
341 if (ulrc == 0L)
342 {
343 vInfo.versionMajor = ulSysInfo[QSV_VERSION_MAJOR] / 10;
344 vInfo.versionMinor = ulSysInfo[QSV_VERSION_MINOR];
345 }
346 vInfo.os = wxOS2_PM;
347 return vInfo;
348 }
349
350 // ---------------------------------------------------------------------------
351 const wxChar* wxGetHomeDir(
352 wxString* pStr
353 )
354 {
355 wxString& rStrDir = *pStr;
356
357 // OS/2 has no idea about home,
358 // so use the working directory instead.
359 // However, we might have a valid HOME directory,
360 // as is used on many machines that have unix utilities
361 // on them, so we should use that, if available.
362
363 // 256 was taken from os2def.h
364 #ifndef MAX_PATH
365 # define MAX_PATH 256
366 #endif
367
368 const wxChar *szHome = wxGetenv((wxChar*)"HOME");
369 if ( szHome == NULL ) {
370 // we're homeless, use current directory.
371 rStrDir = wxT(".");
372 }
373 else
374 rStrDir = szHome;
375
376 return rStrDir.c_str();
377 }
378
379 // Hack for OS/2
380 #if wxUSE_UNICODE
381 const wxMB2WXbuf wxGetUserHome( const wxString &rUser )
382 #else // just for binary compatibility -- there is no 'const' here
383 wxChar* wxGetUserHome ( const wxString &rUser )
384 #endif
385 {
386 wxChar* zHome;
387 wxString sUser1(rUser);
388
389 wxChar *wxBuffer = new wxChar[256];
390 #ifndef __EMX__
391 if (!sUser1.empty())
392 {
393 wxChar zTmp[64];
394
395 if (wxGetUserId( zTmp
396 ,sizeof(zTmp)/sizeof(char)
397 ))
398 {
399 // Guests belong in the temp dir
400 if (wxStricmp(zTmp, _T("annonymous")) == 0)
401 {
402 if ((zHome = wxGetenv(_T("TMP"))) != NULL ||
403 (zHome = wxGetenv(_T("TMPDIR"))) != NULL ||
404 (zHome = wxGetenv(_T("TEMP"))) != NULL)
405 delete[] wxBuffer;
406 return *zHome ? zHome : (wxChar*)_T("\\");
407 }
408 if (wxStricmp(zTmp, WXSTRINGCAST sUser1) == 0)
409 sUser1 = wxEmptyString;
410 }
411 }
412 #endif
413 if (sUser1.empty())
414 {
415 if ((zHome = wxGetenv(_T("HOME"))) != NULL)
416 {
417 wxStrcpy(wxBuffer, zHome);
418 wxUnix2DosFilename(wxBuffer);
419 #if wxUSE_UNICODE
420 wxWCharBuffer retBuffer (wxBuffer);
421 delete[] wxBuffer;
422 return retBuffer;
423 #else
424 wxStrcpy(zHome, wxBuffer);
425 delete[] wxBuffer;
426 return zHome;
427 #endif
428 }
429 }
430 delete[] wxBuffer;
431 return (wxChar*)wxEmptyString; // No home known!
432 }
433
434 wxString wxPMErrorToStr(ERRORID vError)
435 {
436 wxString sError;
437
438 //
439 // Remove the high order byte -- it is useless
440 //
441 vError &= 0x0000ffff;
442 switch(vError)
443 {
444 case PMERR_INVALID_HWND:
445 sError = wxT("Invalid window handle specified");
446 break;
447
448 case PMERR_INVALID_FLAG:
449 sError = wxT("Invalid flag bit set");
450 break;
451
452 case PMERR_NO_MSG_QUEUE:
453 sError = wxT("No message queue available");
454 break;
455
456 case PMERR_INVALID_PARM:
457 sError = wxT("Parameter contained invalid data");
458 break;
459
460 case PMERR_INVALID_PARAMETERS:
461 sError = wxT("Parameter value is out of range");
462 break;
463
464 case PMERR_PARAMETER_OUT_OF_RANGE:
465 sError = wxT("Parameter value is out of range");
466 break;
467
468 case PMERR_INVALID_INTEGER_ATOM:
469 sError = wxT("Not a valid atom");
470 break;
471
472 case PMERR_INVALID_HATOMTBL:
473 sError = wxT("Atom table handle is invalid");
474 break;
475
476 case PMERR_INVALID_ATOM_NAME:
477 sError = wxT("Not a valid atom name");
478 break;
479
480 case PMERR_ATOM_NAME_NOT_FOUND:
481 sError = wxT("Valid name format, but cannot find name in atom table");
482 break;
483
484 case PMERR_INV_HPS:
485 sError = wxT("PMERR_INV_HPS");
486 break;
487
488 case PMERR_PS_BUSY:
489 sError = wxT("PMERR_PS_BUSY");
490 break;
491
492 case PMERR_INV_PRIMITIVE_TYPE:
493 sError = wxT("PMERR_INV_PRIMITIVE_TYPE");
494 break;
495
496 case PMERR_UNSUPPORTED_ATTR:
497 sError = wxT("PMERR_UNSUPPORTED_ATTR");
498 break;
499
500 case PMERR_INV_COLOR_ATTR:
501 sError = wxT("PMERR_INV_COLOR_ATTR");
502 break;
503
504 case PMERR_INV_BACKGROUND_COL_ATTR:
505 sError = wxT("PMERR_INV_BACKGROUND_COL_ATTR");
506 break;
507
508 case PMERR_INV_MIX_ATTR:
509 sError = wxT("PMERR_INV_MIX_ATTR");
510 break;
511
512 case PMERR_INV_LINE_WIDTH_ATTR:
513 sError = wxT("PMERR_INV_LINE_WIDTH_ATTR");
514 break;
515
516 case PMERR_INV_GEOM_LINE_WIDTH_ATTR:
517 sError = wxT("PMERR_INV_GEOM_LINE_WIDTH_ATTR");
518 break;
519
520 case PMERR_INV_LINE_TYPE_ATTR:
521 sError = wxT("PMERR_INV_LINE_TYPE_ATTR");
522 break;
523
524 case PMERR_INV_LINE_END_ATTR:
525 sError = wxT("PMERR_INV_LINE_END_ATTR");
526 break;
527
528 case PMERR_INV_LINE_JOIN_ATTR:
529 sError = wxT("PMERR_INV_LINE_JOIN_ATTR");
530 break;
531
532 case PMERR_INV_CHAR_SET_ATTR:
533 sError = wxT("PMERR_INV_CHAR_SET_ATTR");
534 break;
535
536 case PMERR_INV_CHAR_MODE_ATTR:
537 sError = wxT("PMERR_INV_CHAR_MODE_ATTR");
538 break;
539
540 case PMERR_INV_CHAR_DIRECTION_ATTR:
541 sError = wxT("PMERR_INV_CHAR_DIRECTION_ATTR");
542 break;
543
544 case PMERR_INV_CHAR_SHEAR_ATTR:
545 sError = wxT("PMERR_INV_CHAR_SHEAR_ATTR");
546 break;
547
548 case PMERR_INV_CHAR_ANGLE_ATTR:
549 sError = wxT("PMERR_INV_CHAR_ANGLE_ATTR");
550 break;
551
552 case PMERR_INV_MARKER_SET_ATTR:
553 sError = wxT("PMERR_INV_MARKER_SET_ATTR");
554 break;
555
556 case PMERR_INV_MARKER_SYMBOL_ATTR:
557 sError = wxT("PMERR_INV_MARKER_SYMBOL_ATTR");
558 break;
559
560 case PMERR_INV_PATTERN_SET_ATTR:
561 sError = wxT("PMERR_INV_PATTERN_SET_ATTR");
562 break;
563
564 case PMERR_INV_PATTERN_ATTR:
565 sError = wxT("PMERR_INV_PATTERN_ATTR");
566 break;
567
568 case PMERR_INV_COORDINATE:
569 sError = wxT("PMERR_INV_COORDINATE");
570 break;
571
572 case PMERR_UNSUPPORTED_ATTR_VALUE:
573 sError = wxT("PMERR_UNSUPPORTED_ATTR_VALUE");
574 break;
575
576 case PMERR_INV_PATTERN_SET_FONT:
577 sError = wxT("PMERR_INV_PATTERN_SET_FONT");
578 break;
579
580 case PMERR_HUGE_FONTS_NOT_SUPPORTED:
581 sError = wxT("PMERR_HUGE_FONTS_NOT_SUPPORTED");
582 break;
583
584 default:
585 sError = wxT("Unknown error");
586 }
587 return sError;
588 } // end of wxPMErrorToStr
589
590 // replacement for implementation in unix/utilsunx.cpp,
591 // to be used by all X11 based ports.
592 struct wxEndProcessData;
593
594 void wxHandleProcessTermination(wxEndProcessData *WXUNUSED(proc_data))
595 {
596 // For now, just do nothing. To be filled in as needed.
597 }