unix.cpp

Go to the documentation of this file.
00001 /* $Id: unix.cpp 15718 2009-03-15 00:32:18Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "variables.h"
00008 #include "textbuf_gui.h"
00009 #include "functions.h"
00010 #include "core/random_func.hpp"
00011 
00012 #include "table/strings.h"
00013 
00014 #include <dirent.h>
00015 #include <unistd.h>
00016 #include <sys/stat.h>
00017 #include <time.h>
00018 #include <signal.h>
00019 
00020 #if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__)
00021   #define HAS_STATVFS
00022 #endif
00023 
00024 #ifdef HAS_STATVFS
00025 #include <sys/statvfs.h>
00026 #endif
00027 
00028 
00029 #ifdef __MORPHOS__
00030 #include <exec/types.h>
00031 ULONG __stack = (1024*1024)*2; // maybe not that much is needed actually ;)
00032 
00033 /* The system supplied definition of SIG_IGN does not match */
00034 #undef SIG_IGN
00035 #define SIG_IGN (void (*)(int))1
00036 #endif /* __MORPHOS__ */
00037 
00038 #ifdef __AMIGA__
00039 #warning add stack symbol to avoid that user needs to set stack manually (tokai)
00040 // ULONG __stack =
00041 #endif
00042 
00043 #if defined(__APPLE__)
00044   #if defined(WITH_SDL)
00045     /* the mac implementation needs this file included in the same file as main() */
00046     #include <SDL.h>
00047   #endif
00048 #endif
00049 
00050 bool FiosIsRoot(const char *path)
00051 {
00052 #if !defined(__MORPHOS__) && !defined(__AMIGAOS__)
00053   return path[1] == '\0';
00054 #else
00055   /* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */
00056   const char *s = strchr(path, ':');
00057   return s != NULL && s[1] == '\0';
00058 #endif
00059 }
00060 
00061 void FiosGetDrives()
00062 {
00063   return;
00064 }
00065 
00066 bool FiosGetDiskFreeSpace(const char *path, uint64 *tot)
00067 {
00068   uint64 free = 0;
00069 
00070 #ifdef HAS_STATVFS
00071 # ifdef __APPLE__
00072   /* OSX 10.3 lacks statvfs so don't try to use it even though later versions of OSX has it. */
00073   if (MacOSVersionIsAtLeast(10, 4, 0))
00074 # endif
00075   {
00076     struct statvfs s;
00077 
00078     if (statvfs(path, &s) != 0) return false;
00079     free = (uint64)s.f_frsize * s.f_bavail;
00080   }
00081 #endif
00082   if (tot != NULL) *tot = free;
00083   return true;
00084 }
00085 
00086 bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)
00087 {
00088   char filename[MAX_PATH];
00089 
00090 #if defined(__MORPHOS__) || defined(__AMIGAOS__)
00091   /* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */
00092   if (FiosIsRoot(path)) {
00093     snprintf(filename, lengthof(filename), "%s:%s", path, ent->d_name);
00094   } else // XXX - only next line!
00095 #else
00096   assert(path[strlen(path) - 1] == PATHSEPCHAR);
00097   if (strlen(path) > 2) assert(path[strlen(path) - 2] != PATHSEPCHAR);
00098 #endif
00099   snprintf(filename, lengthof(filename), "%s%s", path, ent->d_name);
00100 
00101   return stat(filename, sb) == 0;
00102 }
00103 
00104 bool FiosIsHiddenFile(const struct dirent *ent)
00105 {
00106   return ent->d_name[0] == '.';
00107 }
00108 
00109 #ifdef WITH_ICONV
00110 
00111 #include <iconv.h>
00112 #include <errno.h>
00113 #include "debug.h"
00114 #include "string_func.h"
00115 
00116 const char *GetCurrentLocale(const char *param);
00117 
00118 #define INTERNALCODE "UTF-8"
00119 
00123 static const char *GetLocalCode()
00124 {
00125 #if defined(__APPLE__)
00126   return "UTF-8-MAC";
00127 #else
00128   /* Strip locale (eg en_US.UTF-8) to only have UTF-8 */
00129   const char *locale = GetCurrentLocale("LC_CTYPE");
00130   if (locale != NULL) locale = strchr(locale, '.');
00131 
00132   return (locale == NULL) ? "" : locale + 1;
00133 #endif
00134 }
00135 
00141 static const char *convert_tofrom_fs(iconv_t convd, const char *name)
00142 {
00143   static char buf[1024];
00144   /* Work around buggy iconv implementation where inbuf is wrongly typed as
00145    * non-const. Correct implementation is at
00146    * http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.html */
00147 #ifdef HAVE_BROKEN_ICONV
00148   char *inbuf = (char*)name;
00149 #else
00150   const char *inbuf = name;
00151 #endif
00152 
00153   char *outbuf  = buf;
00154   size_t outlen = sizeof(buf) - 1;
00155   size_t inlen  = strlen(name);
00156 
00157   strecpy(outbuf, name, outbuf + outlen);
00158 
00159   iconv(convd, NULL, NULL, NULL, NULL);
00160   if (iconv(convd, &inbuf, &inlen, &outbuf, &outlen) == (size_t)(-1)) {
00161     DEBUG(misc, 0, "[iconv] error converting '%s'. Errno %d", name, errno);
00162   }
00163 
00164   *outbuf = '\0';
00165   /* FIX: invalid characters will abort conversion, but they shouldn't occur? */
00166   return buf;
00167 }
00168 
00172 const char *OTTD2FS(const char *name)
00173 {
00174   static iconv_t convd = (iconv_t)(-1);
00175 
00176   if (convd == (iconv_t)(-1)) {
00177     const char *env = GetLocalCode();
00178     convd = iconv_open(env, INTERNALCODE);
00179     if (convd == (iconv_t)(-1)) {
00180       DEBUG(misc, 0, "[iconv] conversion from codeset '%s' to '%s' unsupported", INTERNALCODE, env);
00181       return name;
00182     }
00183   }
00184 
00185   return convert_tofrom_fs(convd, name);
00186 }
00187 
00191 const char *FS2OTTD(const char *name)
00192 {
00193   static iconv_t convd = (iconv_t)(-1);
00194 
00195   if (convd == (iconv_t)(-1)) {
00196     const char *env = GetLocalCode();
00197     convd = iconv_open(INTERNALCODE, env);
00198     if (convd == (iconv_t)(-1)) {
00199       DEBUG(misc, 0, "[iconv] conversion from codeset '%s' to '%s' unsupported", env, INTERNALCODE);
00200       return name;
00201     }
00202   }
00203 
00204   return convert_tofrom_fs(convd, name);
00205 }
00206 
00207 #else
00208 const char *FS2OTTD(const char *name) {return name;}
00209 const char *OTTD2FS(const char *name) {return name;}
00210 #endif /* WITH_ICONV */
00211 
00212 void ShowInfo(const char *str)
00213 {
00214   fprintf(stderr, "%s\n", str);
00215 }
00216 
00217 void ShowOSErrorBox(const char *buf, bool system)
00218 {
00219 #if defined(__APPLE__)
00220   /* this creates an NSAlertPanel with the contents of 'buf'
00221    * this is the native and nicest way to do this on OSX */
00222   ShowMacDialog( buf, "See readme for more info\nMost likely you are missing files from the original TTD", "Quit" );
00223 #else
00224   /* all systems, but OSX */
00225   fprintf(stderr, "\033[1;31mError: %s\033[0;39m\n", buf);
00226 #endif
00227 }
00228 
00229 #ifdef WITH_COCOA
00230 void cocoaSetupAutoreleasePool();
00231 void cocoaReleaseAutoreleasePool();
00232 #endif
00233 
00234 int CDECL main(int argc, char *argv[])
00235 {
00236   int ret;
00237 
00238 #ifdef WITH_COCOA
00239   cocoaSetupAutoreleasePool();
00240   /* This is passed if we are launched by double-clicking */
00241   if (argc >= 2 && strncmp(argv[1], "-psn", 4) == 0) {
00242     argv[1] = NULL;
00243     argc = 1;
00244   }
00245 #endif
00246 
00247   SetRandomSeed(time(NULL));
00248 
00249   signal(SIGPIPE, SIG_IGN);
00250 
00251   ret = ttd_main(argc, argv);
00252 
00253 #ifdef WITH_COCOA
00254   cocoaReleaseAutoreleasePool();
00255 #endif
00256 
00257   return ret;
00258 }
00259 
00260 bool InsertTextBufferClipboard(Textbuf *tb)
00261 {
00262   return false;
00263 }
00264 
00265 
00266 /* multi os compatible sleep function */
00267 
00268 #ifdef __AMIGA__
00269 /* usleep() implementation */
00270 # include <devices/timer.h>
00271 # include <dos/dos.h>
00272 
00273   extern struct Device      *TimerBase    = NULL;
00274   extern struct MsgPort     *TimerPort    = NULL;
00275   extern struct timerequest *TimerRequest = NULL;
00276 #endif /* __AMIGA__ */
00277 
00278 void CSleep(int milliseconds)
00279 {
00280   #if defined(PSP)
00281     sceKernelDelayThread(milliseconds * 1000);
00282   #elif defined(__BEOS__)
00283     snooze(milliseconds * 1000);
00284   #elif defined(__AMIGA__)
00285   {
00286     ULONG signals;
00287     ULONG TimerSigBit = 1 << TimerPort->mp_SigBit;
00288 
00289     /* send IORequest */
00290     TimerRequest->tr_node.io_Command = TR_ADDREQUEST;
00291     TimerRequest->tr_time.tv_secs    = (milliseconds * 1000) / 1000000;
00292     TimerRequest->tr_time.tv_micro   = (milliseconds * 1000) % 1000000;
00293     SendIO((struct IORequest *)TimerRequest);
00294 
00295     if (!((signals = Wait(TimerSigBit | SIGBREAKF_CTRL_C)) & TimerSigBit) ) {
00296       AbortIO((struct IORequest *)TimerRequest);
00297     }
00298     WaitIO((struct IORequest *)TimerRequest);
00299   }
00300   #else
00301     usleep(milliseconds * 1000);
00302   #endif
00303 }

Generated on Mon Mar 23 00:25:24 2009 for OpenTTD by  doxygen 1.5.6