Implementations for some of the stubs

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@35221 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Michael Wetherell 2005-08-18 10:52:10 +00:00
parent f22d860b26
commit a3c0d7684a

View File

@ -1,9 +1,10 @@
/////////////////////////////////////////////////////////////////////////////
// Name: utils.cpp
// Purpose: DOS implementations of utility functions
// Author: Vaclav Slavik
// Author: Vaclav Slavik, M.J.Wetherell
// Id: $Id$
// Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
// (c) 2005 M.J.Wetherell
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
@ -21,16 +22,24 @@
#include "wx/apptrait.h"
#include "wx/log.h"
#include "wx/process.h"
#include "wx/confbase.h" // for wxExpandEnvVars()
#include "wx/app.h"
#include "wx/cmdline.h"
#include "wx/filename.h"
#include "wx/wfstream.h"
#include <stdarg.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <dos.h>
#include <process.h>
//----------------------------------------------------------------------------
// misc.
// Sleep
//----------------------------------------------------------------------------
void wxSleep(int nSecs)
@ -47,7 +56,14 @@ void wxMilliSleep(unsigned long milliseconds)
#else
clock_t start = clock();
while ((clock() - start) * 1000 / CLOCKS_PER_SEC < (clock_t)milliseconds)
; // FIXME: need to yield here
{
// yield if in a multitasking environment
// "Release Current Virtual Machine's Time Slice" in DPMI 1.0
REGS r;
memset(&r, 0, sizeof(r));
r.x.ax = 0x1680;
int386(0x2f, &r, &r);
}
#endif
}
@ -60,11 +76,9 @@ void wxMicroSleep(unsigned long microseconds)
#endif
}
// Get Process ID
unsigned long wxGetProcessId()
{
return (unsigned long)getpid();
}
//----------------------------------------------------------------------------
// Get/Set environment variables
//----------------------------------------------------------------------------
bool wxGetEnv(const wxString& var, wxString *value)
{
@ -95,21 +109,102 @@ bool wxSetEnv(const wxString& variable, const wxChar *value)
return putenv(buf) == 0;
}
//----------------------------------------------------------------------------
// Hostname, username, home directory
//----------------------------------------------------------------------------
// Based on the MSW implementation
//
// Respects the following environment variables in this order: %HomeDrive% +
// %HomePath%, %UserProfile%, $HOME. Otherwise takes program's directory if
// wxApp has been initialised, otherwise returns ".".
//
const wxChar* wxGetHomeDir(wxString *home)
{
*home = wxT(".");
return home->c_str();
wxString& strDir = *home;
strDir.clear();
// try HOMEDRIVE/PATH
const wxChar *szHome = wxGetenv(wxT("HOMEDRIVE"));
if ( szHome != NULL )
strDir << szHome;
szHome = wxGetenv(wxT("HOMEPATH"));
if ( szHome != NULL )
{
strDir << szHome;
// the idea is that under NT these variables have default values of
// "%systemdrive%:" and "\\". As we don't want to create our config
// files in the root directory of the system drive, we will create it
// in our program's dir. However, if the user took care to set
// HOMEPATH to something other than "\\", we suppose that he knows
// what he is doing and use the supplied value.
if ( wxStrcmp(szHome, wxT("\\")) == 0 )
strDir.clear();
}
if ( strDir.empty() )
{
// If we have a valid USERPROFILE directory, as is the case in
// Windows NT, 2000 and XP, we should use that as our home directory.
szHome = wxGetenv(wxT("USERPROFILE"));
if ( szHome != NULL )
strDir = szHome;
}
if ( strDir.empty() )
{
// If we have a valid HOME directory, as is used on many machines
// that have unix utilities on them, we should use that.
szHome = wxGetenv(wxT("HOME"));
if ( szHome != NULL )
{
strDir = szHome;
// when msys sets %HOME% it uses '/' (cygwin uses '\\')
strDir.Replace(_T("/"), _T("\\"));
}
}
if ( !strDir.empty() )
{
// sometimes the value of HOME may be "%USERPROFILE%", so reexpand the
// value once again, it shouldn't hurt anyhow
strDir = wxExpandEnvVars(strDir);
}
else // fall back to the program directory
{
if ( wxTheApp )
{
wxString prog(wxTheApp->argv[0]);
#ifdef __DJGPP__
// djgpp startup code switches the slashes around, so restore them
prog.Replace(_T("/"), _T("\\"));
#endif
// it needs to be a full path to be usable
if ( prog.compare(1, 2, _T(":\\")) == 0 )
wxSplitPath(prog, &strDir, NULL, NULL);
}
if ( strDir.empty() )
{
strDir = _T(".");
}
}
return strDir.c_str();
}
const wxChar* wxGetUserHomeDir(wxString *home)
wxChar *wxGetUserHome(const wxString& user)
{
*home = wxT(".");
return home->c_str();
}
static wxString home;
wxChar *wxGetUserHome(const wxString &user)
{
return wxT(".");
if (user.empty() || user == wxGetUserId())
return wx_const_cast(wxChar*, wxGetHomeDir(&home));
else
return _T("");
}
#if WXWIN_COMPATIBILITY_2_2
@ -123,53 +218,272 @@ void wxFatalError(const wxString &msg, const wxString &title)
}
#endif // WXWIN_COMPATIBILITY_2_2
bool wxGetUserId(wxChar *WXUNUSED(buf), int WXUNUSED(sz))
// returns %UserName%, $USER or just "user"
//
bool wxGetUserId(wxChar *buf, int n)
{
wxFAIL_MSG( wxT("wxGetUserId not implemented under MS-DOS!") );
return FALSE;
const wxChar *user = wxGetenv(_T("UserName"));
if (!user)
user = wxGetenv(_T("USER"));
if (!user)
user = _T("user");
wxStrncpy(buf, user, n);
return true;
}
bool wxGetUserName(wxChar *WXUNUSED(buf), int WXUNUSED(sz))
bool wxGetUserName(wxChar *buf, int n)
{
wxFAIL_MSG( wxT("wxGetUserName not implemented under MS-DOS!") );
return FALSE;
return wxGetUserId(buf, n);
}
bool wxGetHostName(wxChar *WXUNUSED(buf), int WXUNUSED(sz))
// returns %ComputerName%, or $HOSTNAME, or "host"
//
bool wxGetHostName(wxChar *buf, int n)
{
wxFAIL_MSG( wxT("wxGetHostName not implemented under MS-DOS!") );
return FALSE;
const wxChar *host = wxGetenv(_T("ComputerName"));
if (!host)
host = wxGetenv(_T("HOSTNAME"));
if (!host)
host = _T("host");
wxStrncpy(buf, host, n);
return true;
}
bool wxGetFullHostName(wxChar *WXUNUSED(buf), int WXUNUSED(sz))
// adds %UserDnsDomain% to wxGetHostName()
//
bool wxGetFullHostName(wxChar *buf, int n)
{
wxFAIL_MSG( wxT("wxGetFullHostName not implemented under MS-DOS!") );
return FALSE;
wxGetHostName(buf, n);
const wxChar *domain = wxGetenv(_T("UserDnsDomain"));
if (domain)
wxStrncat(wxStrncat(buf, _T("."), n), domain, n);
return true;
}
int wxKill(long WXUNUSED(pid), wxSignal WXUNUSED(sig), wxKillError *WXUNUSED(rc), int WXUNUSED(flags))
//----------------------------------------------------------------------------
// Processes
//----------------------------------------------------------------------------
unsigned long wxGetProcessId()
{
wxFAIL_MSG( wxT("wxKill not implemented under MS-DOS!") );
return 0;
return (unsigned long)getpid();
}
long wxExecute(const wxString& WXUNUSED(command), int WXUNUSED(flags), wxProcess *WXUNUSED(process))
int wxKill(long pid, wxSignal sig, wxKillError *rc, int WXUNUSED(flags))
{
wxFAIL_MSG( wxT("wxExecute not implemented under MS-DOS!") );
return 0;
int result = -1;
if (pid != (long)wxGetProcessId())
{
result = raise(sig);
if (rc)
*rc = result == 0 ? wxKILL_OK : wxKILL_BAD_SIGNAL;
}
else
{
wxLogDebug(_T("wxKill can only send signals to the current process under MSDOS"));
if (rc)
*rc = wxKILL_NO_PROCESS;
}
return result;
}
long wxExecute(char **WXUNUSED(argv), int WXUNUSED(flags), wxProcess *WXUNUSED(process))
bool wxShell(const wxString& command /*=wxEmptyString*/)
{
wxFAIL_MSG( wxT("wxExecute not implemented under MS-DOS!") );
return 0;
// FIXME: suspend/resume gui
int result = system(command);
if (result == -1)
wxLogSysError(_("can't execute '%s'"), command.c_str());
return result == 0;
}
long wxExecute(const wxString& command, int flags, wxProcess *process)
{
// FIXME: shouldn't depend on wxCmdLineParser
wxArrayString args(wxCmdLineParser::ConvertStringToArgs(command));
size_t n = args.size();
wxChar **argv = new wxChar*[n + 1];
argv[n] = NULL;
while (n-- > 0)
argv[n] = wx_const_cast(wxChar*, args[n].c_str());
long result = wxExecute(argv, flags, process);
delete [] argv;
return result;
}
#if wxUSE_STREAMS
// A wxFFileInputStream that deletes the file in it's destructor
//
class wxTempFileInStream : public wxFFileInputStream
{
public:
wxTempFileInStream(const wxString& name)
: wxFFileInputStream(name, _T("rt"))
{ }
~wxTempFileInStream()
{
m_file->Close();
wxRemoveFile(m_file->GetName());
}
};
// A file descriptor that can be redirected to a file
//
class wxRedirectableFd
{
public:
wxRedirectableFd(int fd) : m_fd(fd), m_dup(-1) { }
~wxRedirectableFd();
// Redirect the descriptor to a file, similar to ANSI C's freopen, but
// for low level descriptors. The desctructor un-redirects. If O_CREAT
// is in the flags then the destructor will delete the file unless it is
// given away with Release().
bool Reopen(const wxString& name, int flags);
// un-redirect the redirected file descriptor, closing the file, and give
// away the filename without deleting it
wxString Release();
private:
// un-redirect the descriptor, closing the file
void Restore();
int m_fd;
int m_dup;
wxString m_name;
};
wxRedirectableFd::~wxRedirectableFd()
{
Restore();
if (!m_name.empty())
wxRemoveFile(m_name);
}
bool wxRedirectableFd::Reopen(const wxString& name, int flags)
{
wxASSERT(m_dup == -1);
bool result = false;
// save a duplicate so that the descriptor can be closed now and
// restored later
m_dup = dup(m_fd);
if (m_dup != -1)
{
int tmp = open(name.mb_str(), flags);
if (tmp != -1)
{
close(m_fd);
if (flags & O_CREAT)
m_name = name;
result = dup2(tmp, m_fd) == m_fd;
close(tmp);
}
}
if (!result)
wxLogSysError(_("error opening '%s'"), name.c_str());
return result;
}
void wxRedirectableFd::Restore()
{
if (m_dup != -1)
{
close(m_fd);
dup2(m_dup, m_fd);
close(m_dup);
m_dup = -1;
}
}
wxString wxRedirectableFd::Release()
{
Restore();
wxString name = m_name;
m_name.clear();
return name;
}
#endif // wxUSE_STREAMS
// wxExecute implementation
//
long wxExecute(wxChar **argv, int flags, wxProcess *process)
{
#if wxUSE_STREAMS
const int STDIN = 0;
const int STDOUT = 1;
const int STDERR = 2;
wxRedirectableFd in(STDIN), out(STDOUT), err(STDERR);
bool redirect = process && process->IsRedirected() && (flags & wxEXEC_SYNC);
if (redirect)
{
// close stdin/out/err and reopen them as files
if (!in.Reopen(_T("NUL"), O_RDONLY | O_TEXT))
return -1;
if (!out.Reopen(wxFileName::CreateTempFileName(_T("out")),
O_CREAT | O_WRONLY | O_TRUNC | O_TEXT))
return -1;
if (!err.Reopen(wxFileName::CreateTempFileName(_T("err")),
O_CREAT | O_WRONLY | O_TRUNC | O_TEXT))
return -1;
}
#endif // wxUSE_STREAMS
// FIXME: suspend/resume gui
int mode = flags & wxEXEC_SYNC ? P_WAIT : P_NOWAIT;
int result = spawnvp(mode, argv[0], argv);
if (result == -1)
wxLogSysError(_("can't execute '%s'"), argv[0]);
#if wxUSE_STREAMS
if (redirect)
process->SetPipeStreams(new wxTempFileInStream(out.Release()),
new wxFFileOutputStream(_T("NUL"), _T("wt")),
new wxTempFileInStream(err.Release()));
#endif // wxUSE_STREAMS
return result;
}
//----------------------------------------------------------------------------
// Traits for console apps
//----------------------------------------------------------------------------
wxToolkitInfo& wxConsoleAppTraits::GetToolkitInfo()
{
static wxToolkitInfo info;
info.versionMajor = -1; // FIXME
info.versionMinor = -1;
info.versionMajor = _osmajor;
info.versionMinor = _osminor;
info.name = _T("wxBase");
info.os = wxDOS;
return info;