]> git.saurik.com Git - wxWidgets.git/blame - src/msdos/utilsdos.cpp
added IsSizeDeferred() (part of patch 1199639)
[wxWidgets.git] / src / msdos / utilsdos.cpp
CommitLineData
81d9e625
MW
1/////////////////////////////////////////////////////////////////////////////
2// Name: utils.cpp
3// Purpose: DOS implementations of utility functions
a3c0d768 4// Author: Vaclav Slavik, M.J.Wetherell
81d9e625
MW
5// Id: $Id$
6// Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
a3c0d768 7// (c) 2005 M.J.Wetherell
81d9e625
MW
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
18#include "wx/utils.h"
19#include "wx/string.h"
20
21#include "wx/intl.h"
22#include "wx/apptrait.h"
23#include "wx/log.h"
24#include "wx/process.h"
a3c0d768
MW
25#include "wx/confbase.h" // for wxExpandEnvVars()
26#include "wx/app.h"
27#include "wx/cmdline.h"
28#include "wx/filename.h"
29#include "wx/wfstream.h"
81d9e625
MW
30
31#include <stdarg.h>
32#include <string.h>
33#include <sys/stat.h>
34#include <sys/types.h>
35#include <unistd.h>
a3c0d768 36#include <signal.h>
81d9e625 37#include <time.h>
a3c0d768
MW
38#include <dos.h>
39#include <process.h>
81d9e625
MW
40
41//----------------------------------------------------------------------------
a3c0d768 42// Sleep
81d9e625
MW
43//----------------------------------------------------------------------------
44
45void wxSleep(int nSecs)
46{
47 wxMilliSleep(1000 * nSecs);
48}
49
50void wxMilliSleep(unsigned long milliseconds)
51{
52#if HAVE_USLEEP || defined __DJGPP__
53 usleep(milliseconds * 1000);
54#elif defined __WATCOMC__
55 delay(milliseconds);
56#else
57 clock_t start = clock();
58 while ((clock() - start) * 1000 / CLOCKS_PER_SEC < (clock_t)milliseconds)
a3c0d768
MW
59 {
60 // yield if in a multitasking environment
61 // "Release Current Virtual Machine's Time Slice" in DPMI 1.0
62 REGS r;
63 memset(&r, 0, sizeof(r));
64 r.x.ax = 0x1680;
65 int386(0x2f, &r, &r);
66 }
81d9e625
MW
67#endif
68}
69
70void wxMicroSleep(unsigned long microseconds)
71{
72#if HAVE_USLEEP || defined __DJGPP__
73 usleep(microseconds);
74#else
75 wxMilliSleep(microseconds/1000);
76#endif
77}
78
a3c0d768
MW
79//----------------------------------------------------------------------------
80// Get/Set environment variables
81//----------------------------------------------------------------------------
81d9e625
MW
82
83bool wxGetEnv(const wxString& var, wxString *value)
84{
85 // wxGetenv is defined as getenv()
86 wxChar *p = wxGetenv(var);
87 if ( !p )
88 return FALSE;
89
90 if ( value )
91 *value = p;
92
93 return TRUE;
94}
95
96bool wxSetEnv(const wxString& variable, const wxChar *value)
97{
98 wxString s = variable;
99 if ( value )
100 s << _T('=') << value;
101
102 // transform to ANSI
103 const char *p = s.mb_str();
104
105 // the string will be free()d by libc
106 char *buf = (char *)malloc(strlen(p) + 1);
107 strcpy(buf, p);
108
109 return putenv(buf) == 0;
110}
111
a3c0d768
MW
112//----------------------------------------------------------------------------
113// Hostname, username, home directory
114//----------------------------------------------------------------------------
115
116// Based on the MSW implementation
117//
118// Respects the following environment variables in this order: %HomeDrive% +
119// %HomePath%, %UserProfile%, $HOME. Otherwise takes program's directory if
120// wxApp has been initialised, otherwise returns ".".
121//
81d9e625
MW
122const wxChar* wxGetHomeDir(wxString *home)
123{
a3c0d768 124 wxString& strDir = *home;
81d9e625 125
a3c0d768
MW
126 strDir.clear();
127
128 // try HOMEDRIVE/PATH
129 const wxChar *szHome = wxGetenv(wxT("HOMEDRIVE"));
130 if ( szHome != NULL )
131 strDir << szHome;
132 szHome = wxGetenv(wxT("HOMEPATH"));
133
134 if ( szHome != NULL )
135 {
136 strDir << szHome;
137
138 // the idea is that under NT these variables have default values of
139 // "%systemdrive%:" and "\\". As we don't want to create our config
140 // files in the root directory of the system drive, we will create it
141 // in our program's dir. However, if the user took care to set
142 // HOMEPATH to something other than "\\", we suppose that he knows
143 // what he is doing and use the supplied value.
144 if ( wxStrcmp(szHome, wxT("\\")) == 0 )
145 strDir.clear();
146 }
147
148 if ( strDir.empty() )
149 {
150 // If we have a valid USERPROFILE directory, as is the case in
151 // Windows NT, 2000 and XP, we should use that as our home directory.
152 szHome = wxGetenv(wxT("USERPROFILE"));
153
154 if ( szHome != NULL )
155 strDir = szHome;
156 }
157
158 if ( strDir.empty() )
159 {
160 // If we have a valid HOME directory, as is used on many machines
161 // that have unix utilities on them, we should use that.
162 szHome = wxGetenv(wxT("HOME"));
163
164 if ( szHome != NULL )
165 {
166 strDir = szHome;
167 // when msys sets %HOME% it uses '/' (cygwin uses '\\')
168 strDir.Replace(_T("/"), _T("\\"));
169 }
170 }
171
172 if ( !strDir.empty() )
173 {
174 // sometimes the value of HOME may be "%USERPROFILE%", so reexpand the
175 // value once again, it shouldn't hurt anyhow
176 strDir = wxExpandEnvVars(strDir);
177 }
178 else // fall back to the program directory
179 {
180 if ( wxTheApp )
181 {
182 wxString prog(wxTheApp->argv[0]);
183#ifdef __DJGPP__
184 // djgpp startup code switches the slashes around, so restore them
185 prog.Replace(_T("/"), _T("\\"));
186#endif
187 // it needs to be a full path to be usable
188 if ( prog.compare(1, 2, _T(":\\")) == 0 )
189 wxSplitPath(prog, &strDir, NULL, NULL);
190 }
191 if ( strDir.empty() )
192 {
193 strDir = _T(".");
194 }
195 }
196
197 return strDir.c_str();
81d9e625
MW
198}
199
a3c0d768 200wxChar *wxGetUserHome(const wxString& user)
81d9e625 201{
a3c0d768
MW
202 static wxString home;
203
204 if (user.empty() || user == wxGetUserId())
205 return wx_const_cast(wxChar*, wxGetHomeDir(&home));
206 else
207 return _T("");
81d9e625
MW
208}
209
210#if WXWIN_COMPATIBILITY_2_2
211void wxFatalError(const wxString &msg, const wxString &title)
212{
213 wxFprintf( stderr, _("Error ") );
214 if (!title.IsNull()) wxFprintf( stderr, wxT("%s "), WXSTRINGCAST(title) );
215 if (!msg.IsNull()) wxFprintf( stderr, wxT(": %s"), WXSTRINGCAST(msg) );
216 wxFprintf( stderr, wxT(".\n") );
217 exit(3); // the same exit code as for abort()
218}
219#endif // WXWIN_COMPATIBILITY_2_2
220
a3c0d768
MW
221// returns %UserName%, $USER or just "user"
222//
223bool wxGetUserId(wxChar *buf, int n)
81d9e625 224{
a3c0d768
MW
225 const wxChar *user = wxGetenv(_T("UserName"));
226
227 if (!user)
228 user = wxGetenv(_T("USER"));
229
230 if (!user)
231 user = _T("user");
232
233 wxStrncpy(buf, user, n);
234 return true;
81d9e625
MW
235}
236
a3c0d768 237bool wxGetUserName(wxChar *buf, int n)
81d9e625 238{
a3c0d768 239 return wxGetUserId(buf, n);
81d9e625
MW
240}
241
a3c0d768
MW
242// returns %ComputerName%, or $HOSTNAME, or "host"
243//
244bool wxGetHostName(wxChar *buf, int n)
81d9e625 245{
a3c0d768
MW
246 const wxChar *host = wxGetenv(_T("ComputerName"));
247
248 if (!host)
249 host = wxGetenv(_T("HOSTNAME"));
250
251 if (!host)
252 host = _T("host");
253
254 wxStrncpy(buf, host, n);
255 return true;
81d9e625
MW
256}
257
a3c0d768
MW
258// adds %UserDnsDomain% to wxGetHostName()
259//
260bool wxGetFullHostName(wxChar *buf, int n)
261{
262 wxGetHostName(buf, n);
263
264 const wxChar *domain = wxGetenv(_T("UserDnsDomain"));
265
266 if (domain)
267 wxStrncat(wxStrncat(buf, _T("."), n), domain, n);
268
269 return true;
270}
271
272//----------------------------------------------------------------------------
273// Processes
274//----------------------------------------------------------------------------
275
276unsigned long wxGetProcessId()
81d9e625 277{
a3c0d768 278 return (unsigned long)getpid();
81d9e625
MW
279}
280
a3c0d768 281int wxKill(long pid, wxSignal sig, wxKillError *rc, int WXUNUSED(flags))
81d9e625 282{
a3c0d768
MW
283 int result = -1;
284
285 if (pid != (long)wxGetProcessId())
286 {
287 result = raise(sig);
288 if (rc)
289 *rc = result == 0 ? wxKILL_OK : wxKILL_BAD_SIGNAL;
290 }
291 else
292 {
293 wxLogDebug(_T("wxKill can only send signals to the current process under MSDOS"));
294 if (rc)
295 *rc = wxKILL_NO_PROCESS;
296 }
297
298 return result;
81d9e625
MW
299}
300
a3c0d768 301bool wxShell(const wxString& command /*=wxEmptyString*/)
81d9e625 302{
a3c0d768
MW
303 // FIXME: suspend/resume gui
304 int result = system(command);
305
306 if (result == -1)
307 wxLogSysError(_("can't execute '%s'"), command.c_str());
308
309 return result == 0;
81d9e625
MW
310}
311
a3c0d768 312long wxExecute(const wxString& command, int flags, wxProcess *process)
81d9e625 313{
a3c0d768
MW
314 // FIXME: shouldn't depend on wxCmdLineParser
315 wxArrayString args(wxCmdLineParser::ConvertStringToArgs(command));
316 size_t n = args.size();
317 wxChar **argv = new wxChar*[n + 1];
318
319 argv[n] = NULL;
320 while (n-- > 0)
321 argv[n] = wx_const_cast(wxChar*, args[n].c_str());
322
323 long result = wxExecute(argv, flags, process);
324
325 delete [] argv;
326 return result;
81d9e625
MW
327}
328
a3c0d768
MW
329#if wxUSE_STREAMS
330
331// A wxFFileInputStream that deletes the file in it's destructor
332//
333class wxTempFileInStream : public wxFFileInputStream
334{
335public:
336 wxTempFileInStream(const wxString& name)
337 : wxFFileInputStream(name, _T("rt"))
338 { }
339
340 ~wxTempFileInStream()
341 {
342 m_file->Close();
343 wxRemoveFile(m_file->GetName());
344 }
345};
346
347// A file descriptor that can be redirected to a file
348//
349class wxRedirectableFd
350{
351public:
352 wxRedirectableFd(int fd) : m_fd(fd), m_dup(-1) { }
353 ~wxRedirectableFd();
354
355 // Redirect the descriptor to a file, similar to ANSI C's freopen, but
356 // for low level descriptors. The desctructor un-redirects. If O_CREAT
357 // is in the flags then the destructor will delete the file unless it is
358 // given away with Release().
359 bool Reopen(const wxString& name, int flags);
360
361 // un-redirect the redirected file descriptor, closing the file, and give
362 // away the filename without deleting it
363 wxString Release();
364
365private:
366 // un-redirect the descriptor, closing the file
367 void Restore();
368
369 int m_fd;
370 int m_dup;
371 wxString m_name;
372};
373
374wxRedirectableFd::~wxRedirectableFd()
375{
376 Restore();
377 if (!m_name.empty())
378 wxRemoveFile(m_name);
379}
380
381bool wxRedirectableFd::Reopen(const wxString& name, int flags)
382{
383 wxASSERT(m_dup == -1);
384 bool result = false;
385
386 // save a duplicate so that the descriptor can be closed now and
387 // restored later
388 m_dup = dup(m_fd);
389
390 if (m_dup != -1)
391 {
392 int tmp = open(name.mb_str(), flags);
393
394 if (tmp != -1)
395 {
396 close(m_fd);
397
398 if (flags & O_CREAT)
399 m_name = name;
400
401 result = dup2(tmp, m_fd) == m_fd;
402 close(tmp);
403 }
404 }
405
406 if (!result)
407 wxLogSysError(_("error opening '%s'"), name.c_str());
408
409 return result;
410}
411
412void wxRedirectableFd::Restore()
413{
414 if (m_dup != -1)
415 {
416 close(m_fd);
417 dup2(m_dup, m_fd);
418 close(m_dup);
419 m_dup = -1;
420 }
421}
422
423wxString wxRedirectableFd::Release()
424{
425 Restore();
426 wxString name = m_name;
427 m_name.clear();
428 return name;
429}
430
431#endif // wxUSE_STREAMS
432
433// wxExecute implementation
434//
435long wxExecute(wxChar **argv, int flags, wxProcess *process)
436{
437#if wxUSE_STREAMS
438 const int STDIN = 0;
439 const int STDOUT = 1;
440 const int STDERR = 2;
441
442 wxRedirectableFd in(STDIN), out(STDOUT), err(STDERR);
443 bool redirect = process && process->IsRedirected() && (flags & wxEXEC_SYNC);
444
445 if (redirect)
446 {
447 // close stdin/out/err and reopen them as files
448 if (!in.Reopen(_T("NUL"), O_RDONLY | O_TEXT))
449 return -1;
450
451 if (!out.Reopen(wxFileName::CreateTempFileName(_T("out")),
452 O_CREAT | O_WRONLY | O_TRUNC | O_TEXT))
453 return -1;
454
455 if (!err.Reopen(wxFileName::CreateTempFileName(_T("err")),
456 O_CREAT | O_WRONLY | O_TRUNC | O_TEXT))
457 return -1;
458 }
459#endif // wxUSE_STREAMS
460
461 // FIXME: suspend/resume gui
462 int mode = flags & wxEXEC_SYNC ? P_WAIT : P_NOWAIT;
463 int result = spawnvp(mode, argv[0], argv);
464
465 if (result == -1)
466 wxLogSysError(_("can't execute '%s'"), argv[0]);
467
468#if wxUSE_STREAMS
469 if (redirect)
470 process->SetPipeStreams(new wxTempFileInStream(out.Release()),
471 new wxFFileOutputStream(_T("NUL"), _T("wt")),
472 new wxTempFileInStream(err.Release()));
473#endif // wxUSE_STREAMS
474
475 return result;
476}
477
478//----------------------------------------------------------------------------
479// Traits for console apps
480//----------------------------------------------------------------------------
481
81d9e625
MW
482wxToolkitInfo& wxConsoleAppTraits::GetToolkitInfo()
483{
484 static wxToolkitInfo info;
a3c0d768
MW
485 info.versionMajor = _osmajor;
486 info.versionMinor = _osminor;
81d9e625
MW
487 info.name = _T("wxBase");
488 info.os = wxDOS;
489 return info;
490}