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