X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ea18eed94c637bee3343b929e09cae78a1b80928..a3e7d24d21f5371c88caffe4a85c8e4a5362db3f:/src/unix/utilsunx.cpp diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index f7b9b01140..b87a2a4bb0 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -58,15 +58,26 @@ #if !defined(HAVE_USLEEP) && \ (defined(__SUN__) && !defined(__SunOs_5_6) && \ !defined(__SunOs_5_7) && !defined(__SUNPRO_CC)) || \ - defined(__osf__) + defined(__osf__) || defined(__EMX__) extern "C" { #ifdef __SUN__ int usleep(unsigned int usec); #else // !Sun + #ifdef __EMX + /* I copied this from the XFree86 diffs. AV. */ + #define INCL_DOSPROCESS + #include + void usleep(unsigned long delay) + { + DosSleep(delay ? (delay/1000l) : 1l); + } + #else void usleep(unsigned long usec); - #endif // Sun/!Sun + #endif + #endif // Sun/EMX/Something else }; +#define HAVE_USLEEP 1 #endif // Unices without usleep() // ============================================================================ @@ -119,31 +130,31 @@ int wxKill(long pid, wxSignal sig) long wxExecute( const wxString& command, bool sync, wxProcess *process ) { - wxCHECK_MSG( !command.IsEmpty(), 0, "can't exec empty command" ); + wxCHECK_MSG( !command.IsEmpty(), 0, wxT("can't exec empty command") ); int argc = 0; - char *argv[WXEXECUTE_NARGS]; + wxChar *argv[WXEXECUTE_NARGS]; wxString argument; - const char *cptr = command.c_str(); - char quotechar = '\0'; // is arg quoted? + const wxChar *cptr = command.c_str(); + wxChar quotechar = wxT('\0'); // is arg quoted? bool escaped = FALSE; // split the command line in arguments do { - argument=""; - quotechar = '\0'; + argument=wxT(""); + quotechar = wxT('\0'); // eat leading whitespace: - while ( isspace(*cptr) ) + while ( wxIsspace(*cptr) ) cptr++; - if ( *cptr == '\'' || *cptr == '"' ) + if ( *cptr == wxT('\'') || *cptr == wxT('"') ) quotechar = *cptr++; do { - if ( *cptr == '\\' && ! escaped ) + if ( *cptr == wxT('\\') && ! escaped ) { escaped = TRUE; cptr++; @@ -156,14 +167,14 @@ long wxExecute( const wxString& command, bool sync, wxProcess *process ) // have we reached the end of the argument? if ( (*cptr == quotechar && ! escaped) - || (quotechar == '\0' && isspace(*cptr)) - || *cptr == '\0' ) + || (quotechar == wxT('\0') && wxIsspace(*cptr)) + || *cptr == wxT('\0') ) { wxASSERT_MSG( argc < WXEXECUTE_NARGS, - "too many arguments in wxExecute" ); + wxT("too many arguments in wxExecute") ); - argv[argc] = new char[argument.length() + 1]; - strcpy(argv[argc], argument.c_str()); + argv[argc] = new wxChar[argument.length() + 1]; + wxStrcpy(argv[argc], argument.c_str()); argc++; // if not at end of buffer, swallow last character: @@ -191,7 +202,7 @@ bool wxShell(const wxString& command) { wxString cmd; if ( !!command ) - cmd.Printf("xterm -e %s", command.c_str()); + cmd.Printf(wxT("xterm -e %s"), command.c_str()); else cmd = command; @@ -234,21 +245,48 @@ void wxHandleProcessTermination(wxEndProcessData *proc_data) } } -long wxExecute( char **argv, bool sync, wxProcess *process ) +long wxExecute( wxChar **argv, bool sync, wxProcess *process ) { - wxCHECK_MSG( *argv, 0, "can't exec empty command" ); + wxCHECK_MSG( *argv, 0, wxT("can't exec empty command") ); - int end_proc_detect[2]; +#if wxUSE_UNICODE + int mb_argc = 0; + char *mb_argv[WXEXECUTE_NARGS]; + + while (argv[mb_argc]) + { + wxWX2MBbuf mb_arg = wxConvertWX2MB(argv[mb_argc]); + mb_argv[mb_argc] = strdup(mb_arg); + mb_argc++; + } + mb_argv[mb_argc] = (char *) NULL; + + // this macro will free memory we used above + #define ARGS_CLEANUP \ + for ( mb_argc = 0; mb_argb[mb_argc]; mb_argc++ ) \ + free(mb_argv[mb_argc]) +#else // ANSI + // no need for cleanup + #define ARGS_CLEANUP + + wxChar **mb_argv = argv; +#endif // Unicode/ANSI +#if wxUSE_GUI // create pipes + int end_proc_detect[2]; if (pipe(end_proc_detect) == -1) { wxLogSysError( _("Pipe creation failed") ); + + ARGS_CLEANUP; + return 0; } +#endif // wxUSE_GUI // fork the process -#ifdef HAVE_VFORK +#if HAVE_VFORK pid_t pid = vfork(); #else pid_t pid = fork(); @@ -256,12 +294,17 @@ long wxExecute( char **argv, bool sync, wxProcess *process ) if (pid == -1) { wxLogSysError( _("Fork failed") ); + + ARGS_CLEANUP; + return 0; } else if (pid == 0) { +#if wxUSE_GUI // we're in child close(end_proc_detect[0]); // close reading side +#endif // wxUSE_GUI // These three lines close the open file descriptors to to avoid any // input/output which might block the process or irritate the user. If @@ -272,7 +315,12 @@ long wxExecute( char **argv, bool sync, wxProcess *process ) // leave stderr opened, it won't do any hurm for ( int fd = 0; fd < FD_SETSIZE; fd++ ) { - if ( fd != end_proc_detect[1] && fd != STDERR_FILENO ) +#if wxUSE_GUI + if ( fd == end_proc_detect[1] ) + continue; +#endif // wxUSE_GUI + + if ( fd != STDERR_FILENO ) close(fd); } } @@ -287,24 +335,27 @@ long wxExecute( char **argv, bool sync, wxProcess *process ) open("/dev/null", O_WRONLY); // stderr #endif - execvp (*argv, argv); + execvp (*mb_argv, mb_argv); // there is no return after successful exec() - fprintf(stderr, _("Can't execute '%s'\n"), *argv); + wxFprintf(stderr, _("Can't execute '%s'\n"), *argv); _exit(-1); } else { +#if wxUSE_GUI // we're in parent close(end_proc_detect[1]); // close writing side wxEndProcessData *data = new wxEndProcessData; data->tag = wxAddProcessCallback(data, end_proc_detect[0]); + ARGS_CLEANUP; + if ( sync ) { - wxASSERT_MSG( !process, "wxProcess param ignored for sync exec" ); + wxASSERT_MSG( !process, wxT("wxProcess param ignored for sync exec") ); data->process = NULL; // sync execution: indicate it by negating the pid @@ -330,37 +381,54 @@ long wxExecute( char **argv, bool sync, wxProcess *process ) return pid; } +#else // !wxUSE_GUI + wxASSERT_MSG( sync, wxT("async execution not supported yet") ); + + int exitcode = 0; + if ( waitpid(pid, &exitcode, 0) == -1 || !WIFEXITED(exitcode) ) + { + wxLogSysError(_("Waiting for subprocess termination failed")); + } + + return exitcode; +#endif // wxUSE_GUI } + + #undef ARGS_CLEANUP } // ---------------------------------------------------------------------------- // file and directory functions // ---------------------------------------------------------------------------- -const char* wxGetHomeDir( wxString *home ) +const wxChar* wxGetHomeDir( wxString *home ) { *home = wxGetUserHome( wxString() ); if ( home->IsEmpty() ) - *home = "/"; + *home = wxT("/"); return home->c_str(); } +#if wxUSE_UNICODE +const wxMB2WXbuf wxGetUserHome( const wxString &user ) +#else // just for binary compatibility -- there is no 'const' here char *wxGetUserHome( const wxString &user ) +#endif { struct passwd *who = (struct passwd *) NULL; if ( !user ) { - register char *ptr; + wxChar *ptr; - if ((ptr = getenv("HOME")) != NULL) + if ((ptr = wxGetenv(wxT("HOME"))) != NULL) { return ptr; } - if ((ptr = getenv("USER")) != NULL || (ptr = getenv("LOGNAME")) != NULL) + if ((ptr = wxGetenv(wxT("USER"))) != NULL || (ptr = wxGetenv(wxT("LOGNAME"))) != NULL) { - who = getpwnam(ptr); + who = getpwnam(wxConvertWX2MB(ptr)); } // We now make sure the the user exists! @@ -371,10 +439,10 @@ char *wxGetUserHome( const wxString &user ) } else { - who = getpwnam (user); + who = getpwnam (user.mb_str()); } - return who ? who->pw_dir : (char*)NULL; + return wxConvertMB2WX(who ? who->pw_dir : NULL); } // ---------------------------------------------------------------------------- @@ -384,11 +452,11 @@ char *wxGetUserHome( const wxString &user ) // retrieve either the hostname or FQDN depending on platform (caller must // check whether it's one or the other, this is why this function is for // private use only) -static bool wxGetHostNameInternal(char *buf, int sz) +static bool wxGetHostNameInternal(wxChar *buf, int sz) { - wxCHECK_MSG( buf, FALSE, "NULL pointer in wxGetHostNameInternal" ); + wxCHECK_MSG( buf, FALSE, wxT("NULL pointer in wxGetHostNameInternal") ); - *buf = '\0'; + *buf = wxT('\0'); // we're using uname() which is POSIX instead of less standard sysinfo() #if defined(HAVE_UNAME) @@ -396,13 +464,13 @@ static bool wxGetHostNameInternal(char *buf, int sz) bool ok = uname(&uts) != -1; if ( ok ) { - strncpy(buf, uts.nodename, sz - 1); - buf[sz] = '\0'; + wxStrncpy(buf, wxConvertMB2WX(uts.nodename), sz - 1); + buf[sz] = wxT('\0'); } #elif defined(HAVE_GETHOSTNAME) bool ok = gethostname(buf, sz) != -1; #else // no uname, no gethostname - wxFAIL_MSG("don't know host name for this machibe"); + wxFAIL_MSG(wxT("don't know host name for this machine")); bool ok = FALSE; #endif // uname/gethostname @@ -415,7 +483,7 @@ static bool wxGetHostNameInternal(char *buf, int sz) return ok; } -bool wxGetHostName(char *buf, int sz) +bool wxGetHostName(wxChar *buf, int sz) { bool ok = wxGetHostNameInternal(buf, sz); @@ -423,26 +491,26 @@ bool wxGetHostName(char *buf, int sz) { // BSD systems return the FQDN, we only want the hostname, so extract // it (we consider that dots are domain separators) - char *dot = strchr(buf, '.'); + wxChar *dot = wxStrchr(buf, wxT('.')); if ( dot ) { // nuke it - *dot = '\0'; + *dot = wxT('\0'); } } return ok; } -bool wxGetFullHostName(char *buf, int sz) +bool wxGetFullHostName(wxChar *buf, int sz) { bool ok = wxGetHostNameInternal(buf, sz); if ( ok ) { - if ( !strchr(buf, '.') ) + if ( !wxStrchr(buf, wxT('.')) ) { - struct hostent *host = gethostbyname(buf); + struct hostent *host = gethostbyname(wxConvertWX2MB(buf)); if ( !host ) { wxLogSysError(_("Cannot get the official hostname")); @@ -452,7 +520,7 @@ bool wxGetFullHostName(char *buf, int sz) else { // the canonical name - strncpy(buf, host->h_name, sz); + wxStrncpy(buf, wxConvertMB2WX(host->h_name), sz); } } //else: it's already a FQDN (BSD behaves this way) @@ -461,37 +529,39 @@ bool wxGetFullHostName(char *buf, int sz) return ok; } -bool wxGetUserId(char *buf, int sz) +bool wxGetUserId(wxChar *buf, int sz) { struct passwd *who; - *buf = '\0'; + *buf = wxT('\0'); if ((who = getpwuid(getuid ())) != NULL) { - strncpy (buf, who->pw_name, sz - 1); + wxStrncpy (buf, wxConvertMB2WX(who->pw_name), sz - 1); return TRUE; } return FALSE; } -bool wxGetUserName(char *buf, int sz) +bool wxGetUserName(wxChar *buf, int sz) { struct passwd *who; char *comma; - *buf = '\0'; + *buf = wxT('\0'); if ((who = getpwuid (getuid ())) != NULL) { comma = strchr(who->pw_gecos, ','); if (comma) *comma = '\0'; // cut off non-name comment fields - strncpy (buf, who->pw_gecos, sz - 1); + wxStrncpy (buf, wxConvertMB2WX(who->pw_gecos), sz - 1); return TRUE; } return FALSE; } +#if wxUSE_GUI + // ---------------------------------------------------------------------------- // error and debug output routines (deprecated, use wxLog) // ---------------------------------------------------------------------------- @@ -507,18 +577,361 @@ void wxDebugMsg( const char *format, ... ) void wxError( const wxString &msg, const wxString &title ) { - fprintf( stderr, _("Error ") ); - if (!title.IsNull()) fprintf( stderr, "%s ", WXSTRINGCAST(title) ); - if (!msg.IsNull()) fprintf( stderr, ": %s", WXSTRINGCAST(msg) ); - fprintf( stderr, ".\n" ); + wxFprintf( stderr, _("Error ") ); + if (!title.IsNull()) wxFprintf( stderr, wxT("%s "), WXSTRINGCAST(title) ); + if (!msg.IsNull()) wxFprintf( stderr, wxT(": %s"), WXSTRINGCAST(msg) ); + wxFprintf( stderr, wxT(".\n") ); } void wxFatalError( const wxString &msg, const wxString &title ) { - fprintf( stderr, _("Error ") ); - if (!title.IsNull()) fprintf( stderr, "%s ", WXSTRINGCAST(title) ); - if (!msg.IsNull()) fprintf( stderr, ": %s", WXSTRINGCAST(msg) ); - fprintf( stderr, ".\n" ); + wxFprintf( stderr, _("Error ") ); + if (!title.IsNull()) wxFprintf( stderr, wxT("%s "), WXSTRINGCAST(title) ); + if (!msg.IsNull()) wxFprintf( stderr, wxT(": %s"), WXSTRINGCAST(msg) ); + wxFprintf( stderr, wxT(".\n") ); exit(3); // the same exit code as for abort() } +// ---------------------------------------------------------------------------- +// font-related functions +// ---------------------------------------------------------------------------- + +// define the functions to create and destroy native fonts for this toolkit +#ifdef __X__ + static inline wxNativeFont wxLoadFont(const wxString& fontSpec) + { + return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec); + } + + static inline void wxFreeFont(wxNativeFont font) + { + XFreeFont((Display *)wxGetDisplay(), font); + } +#elif defined(__WXGTK__) + + #include "gdk/gdk.h" + + static inline wxNativeFont wxLoadFont(const wxString& fontSpec) + { + return gdk_font_load( wxConvertWX2MB(fontSpec) ); + } + + static inline void wxFreeFont(wxNativeFont font) + { + gdk_font_unref(font); + } +#else + #error "Unknown GUI toolkit" +#endif + +// returns TRUE if there are any fonts matching this font spec +static bool wxTestFontSpec(const wxString& fontspec) +{ + wxNativeFont test = wxLoadFont(fontspec); + if ( test ) + { + wxFreeFont(test); + + return TRUE; + } + else + { + return FALSE; + } +} + +// TODO encoding test logic should be moved to wxLoadQueryNearestFont() +static wxNativeFont wxLoadQueryFont(int pointSize, + int family, + int style, + int weight, + bool WXUNUSED(underlined), + const wxString &facename, + wxFontEncoding encoding ) +{ + wxString xfamily; + switch (family) + { + case wxDECORATIVE: xfamily = wxT("lucida"); break; + case wxROMAN: xfamily = wxT("times"); break; + case wxMODERN: xfamily = wxT("courier"); break; + case wxSWISS: xfamily = wxT("helvetica"); break; + case wxTELETYPE: xfamily = wxT("lucidatypewriter"); break; + case wxSCRIPT: xfamily = wxT("utopia"); break; + default: xfamily = wxT("*"); + } + + wxString fontSpec; + if (!facename.IsEmpty()) + { + fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"), + facename.c_str()); + + if ( wxTestFontSpec(fontSpec) ) + { + xfamily = facename; + } + //else: no such family, use default one instead + } + + wxString xstyle; + switch (style) + { + case wxITALIC: xstyle = wxT("i"); break; + case wxSLANT: xstyle = wxT("o"); break; + case wxNORMAL: xstyle = wxT("r"); break; + default: xstyle = wxT("*"); break; + } + + wxString xweight; + switch (weight) + { + case wxBOLD: + { + fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"), + xfamily.c_str()); + if ( wxTestFontSpec(fontSpec) ) + { + xweight = wxT("bold"); + break; + } + fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"), + xfamily.c_str()); + if ( wxTestFontSpec(fontSpec) ) + { + xweight = wxT("heavy"); + break; + } + fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"), + xfamily.c_str()); + if ( wxTestFontSpec(fontSpec) ) + { + xweight = wxT("extrabold"); + break; + } + fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"), + xfamily.c_str()); + if ( wxTestFontSpec(fontSpec) ) + { + xweight = wxT("demibold"); + break; + } + fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"), + xfamily.c_str()); + if ( wxTestFontSpec(fontSpec) ) + { + xweight = wxT("black"); + break; + } + fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"), + xfamily.c_str()); + if ( wxTestFontSpec(fontSpec) ) + { + xweight = wxT("ultrablack"); + break; + } + } + break; + case wxLIGHT: + { + fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"), + xfamily.c_str()); + if ( wxTestFontSpec(fontSpec) ) + { + xweight = wxT("light"); + break; + } + fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"), + xfamily.c_str()); + if ( wxTestFontSpec(fontSpec) ) + { + xweight = wxT("thin"); + break; + } + } + break; + case wxNORMAL: + { + fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"), + xfamily.c_str()); + if ( wxTestFontSpec(fontSpec) ) + { + xweight = wxT("medium"); + break; + } + fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"), + xfamily.c_str()); + if ( wxTestFontSpec(fontSpec) ) + { + xweight = wxT("normal"); + break; + } + fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"), + xfamily.c_str()); + if ( wxTestFontSpec(fontSpec) ) + { + xweight = wxT("regular"); + break; + } + xweight = wxT("*"); + } + break; + default: xweight = wxT("*"); break; + } + + wxString xregistry, xencoding; + if ( encoding == wxFONTENCODING_DEFAULT ) + { + // use the apps default + encoding = wxFont::GetDefaultEncoding(); + } + + bool test = TRUE; // should we test for availability of encoding? + switch ( encoding ) + { + case wxFONTENCODING_ISO8859_1: + case wxFONTENCODING_ISO8859_2: + case wxFONTENCODING_ISO8859_3: + case wxFONTENCODING_ISO8859_4: + case wxFONTENCODING_ISO8859_5: + case wxFONTENCODING_ISO8859_6: + case wxFONTENCODING_ISO8859_7: + case wxFONTENCODING_ISO8859_8: + case wxFONTENCODING_ISO8859_9: + case wxFONTENCODING_ISO8859_10: + case wxFONTENCODING_ISO8859_11: + case wxFONTENCODING_ISO8859_13: + case wxFONTENCODING_ISO8859_14: + case wxFONTENCODING_ISO8859_15: + { + int cp = encoding - wxFONTENCODING_ISO8859_1 + 1; + xregistry = wxT("iso8859"); + xencoding.Printf(wxT("%d"), cp); + } + break; + + case wxFONTENCODING_KOI8: + xregistry = wxT("koi8"); + if ( wxTestFontSpec(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-koi8-1")) ) + { + xencoding = wxT("1"); + + // test passed, no need to do it once more + test = FALSE; + } + else + { + xencoding = wxT("*"); + } + break; + + case wxFONTENCODING_CP1250: + case wxFONTENCODING_CP1251: + case wxFONTENCODING_CP1252: + { + int cp = encoding - wxFONTENCODING_CP1250 + 1250; + fontSpec.Printf(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-microsoft-cp%d"), + cp); + if ( wxTestFontSpec(fontSpec) ) + { + xregistry = wxT("microsoft"); + xencoding.Printf(wxT("cp%d"), cp); + + // test passed, no need to do it once more + test = FALSE; + } + else + { + // fall back to LatinX + xregistry = wxT("iso8859"); + xencoding.Printf(wxT("%d"), cp - 1249); + } + } + break; + + case wxFONTENCODING_SYSTEM: + default: + test = FALSE; + xregistry = + xencoding = wxT("*"); + } + + if ( test ) + { + fontSpec.Printf(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-%s-%s"), + xregistry.c_str(), xencoding.c_str()); + if ( !wxTestFontSpec(fontSpec) ) + { + // this encoding isn't available - what to do? + xregistry = + xencoding = wxT("*"); + } + } + + // construct the X font spec from our data + fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-%s-%s"), + xfamily.c_str(), xweight.c_str(), xstyle.c_str(), + pointSize, xregistry.c_str(), xencoding.c_str()); + + return wxLoadFont(fontSpec); +} + +wxNativeFont wxLoadQueryNearestFont(int pointSize, + int family, + int style, + int weight, + bool underlined, + const wxString &facename, + wxFontEncoding encoding) +{ + wxNativeFont font = wxLoadQueryFont( pointSize, family, style, weight, + underlined, facename, encoding ); + + if (!font) + { + // search up and down by stepsize 10 + int max_size = pointSize + 20 * (1 + (pointSize/180)); + int min_size = pointSize - 20 * (1 + (pointSize/180)); + + int i; + + // Search for smaller size (approx.) + for ( i = pointSize - 10; !font && i >= 10 && i >= min_size; i -= 10 ) + { + font = wxLoadQueryFont(i, family, style, weight, underlined, + facename, encoding ); + } + + // Search for larger size (approx.) + for ( i = pointSize + 10; !font && i <= max_size; i += 10 ) + { + font = wxLoadQueryFont( i, family, style, weight, underlined, + facename, encoding ); + } + + // Try default family + if ( !font && family != wxDEFAULT ) + { + font = wxLoadQueryFont( pointSize, wxDEFAULT, style, weight, + underlined, facename, encoding ); + } + + // Bogus font I + if ( !font ) + { + font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL, + underlined, facename, encoding ); + } + + // Bogus font II + if ( !font ) + { + font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL, + underlined, wxEmptyString, encoding ); + } + } + + return font; +} + +#endif // wxUSE_GUI