removed unused code for writable game data directory
[rocksndiamonds.git] / src / libgame / misc.c
index e499e77a98e5105159412b67e20ca165c03ae8e5..a81f15532538efaa163fb591c1261108fc7dd53c 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "platform.h"
 
-#if !defined(PLATFORM_WIN32)
+#if defined(PLATFORM_UNIX)
 #include <pwd.h>
 #include <sys/param.h>
 #endif
@@ -783,6 +783,48 @@ static char *get_corrected_real_name(char *real_name)
 }
 #endif
 
+#if defined(PLATFORM_UNIX)
+static struct passwd *getPasswdEntry(void)
+{
+#if defined(PLATFORM_EMSCRIPTEN)
+  // currently not fully supported; force fallback to default values
+  return NULL;
+#else
+  return getpwuid(getuid());
+#endif
+}
+
+char *getUnixLoginName(void)
+{
+  struct passwd *pwd = getPasswdEntry();
+
+  if (pwd != NULL && strlen(pwd->pw_name) != 0)
+    return pwd->pw_name;
+
+  return NULL;
+}
+
+char *getUnixRealName(void)
+{
+  struct passwd *pwd = getPasswdEntry();
+
+  if (pwd != NULL && strlen(pwd->pw_gecos) != 0)
+    return pwd->pw_gecos;
+
+  return NULL;
+}
+
+char *getUnixHomeDir(void)
+{
+  struct passwd *pwd = getPasswdEntry();
+
+  if (pwd != NULL && strlen(pwd->pw_dir) != 0)
+    return pwd->pw_dir;
+
+  return NULL;
+}
+#endif
+
 char *getLoginName(void)
 {
   static char *login_name = NULL;
@@ -791,6 +833,7 @@ char *getLoginName(void)
   if (login_name == NULL)
   {
     unsigned long buffer_size = MAX_USERNAME_LEN + 1;
+
     login_name = checked_malloc(buffer_size);
 
     if (GetUserName(login_name, &buffer_size) == 0)
@@ -799,12 +842,12 @@ char *getLoginName(void)
 #elif defined(PLATFORM_UNIX) && !defined(PLATFORM_ANDROID)
   if (login_name == NULL)
   {
-    struct passwd *pwd;
+    char *name = getUnixLoginName();
 
-    if ((pwd = getpwuid(getuid())) == NULL)
-      login_name = ANONYMOUS_NAME;
+    if (name != NULL)
+      login_name = getStringCopy(name);
     else
-      login_name = getStringCopy(pwd->pw_name);
+      login_name = ANONYMOUS_NAME;
   }
 #else
   login_name = ANONYMOUS_NAME;
@@ -831,10 +874,10 @@ char *getRealName(void)
 #elif defined(PLATFORM_UNIX) && !defined(PLATFORM_ANDROID)
   if (real_name == NULL)
   {
-    struct passwd *pwd;
+    char *name = getUnixRealName();
 
-    if ((pwd = getpwuid(getuid())) != NULL && strlen(pwd->pw_gecos) != 0)
-      real_name = get_corrected_real_name(pwd->pw_gecos);
+    if (name != NULL)
+      real_name = get_corrected_real_name(name);
     else
       real_name = ANONYMOUS_NAME;
   }
@@ -845,6 +888,53 @@ char *getRealName(void)
   return real_name;
 }
 
+char *getFixedUserName(char *name)
+{
+  // needed because player name must be a fixed length string
+  char *name_new = checked_malloc(MAX_PLAYER_NAME_LEN + 1);
+
+  strncpy(name_new, name, MAX_PLAYER_NAME_LEN);
+  name_new[MAX_PLAYER_NAME_LEN] = '\0';
+
+  if (strlen(name) > MAX_PLAYER_NAME_LEN)              // name has been cut
+    if (strchr(name_new, ' '))
+      *strchr(name_new, ' ') = '\0';
+
+  return name_new;
+}
+
+char *getDefaultUserName(int nr)
+{
+  static char *user_name[MAX_PLAYER_NAMES] = { NULL };
+
+  nr = MIN(MAX(0, nr), MAX_PLAYER_NAMES - 1);
+
+  if (user_name[nr] == NULL)
+  {
+    user_name[nr] = (nr == 0 ? getLoginName() : EMPTY_PLAYER_NAME);
+    user_name[nr] = getFixedUserName(user_name[nr]);
+  }
+
+  return user_name[nr];
+}
+
+char *getTimestampFromEpoch(time_t epoch_seconds)
+{
+  struct tm *now = localtime(&epoch_seconds);
+  static char timestamp[20];
+
+  sprintf(timestamp, "%04d%02d%02d-%02d%02d%02d",
+         now->tm_year + 1900, now->tm_mon + 1, now->tm_mday,
+         now->tm_hour, now->tm_min, now->tm_sec);
+
+  return timestamp;
+}
+
+char *getCurrentTimestamp(void)
+{
+  return getTimestampFromEpoch(time(NULL));
+}
+
 time_t getFileTimestampEpochSeconds(char *filename)
 {
   struct stat file_status;
@@ -1088,6 +1178,22 @@ boolean strEqualN(char *s1, char *s2, int n)
          strncmp(s1, s2, n) == 0);
 }
 
+boolean strEqualCase(char *s1, char *s2)
+{
+  return (s1 == NULL && s2 == NULL ? TRUE  :
+         s1 == NULL && s2 != NULL ? FALSE :
+         s1 != NULL && s2 == NULL ? FALSE :
+         strcasecmp(s1, s2) == 0);
+}
+
+boolean strEqualCaseN(char *s1, char *s2, int n)
+{
+  return (s1 == NULL && s2 == NULL ? TRUE  :
+         s1 == NULL && s2 != NULL ? FALSE :
+         s1 != NULL && s2 == NULL ? FALSE :
+         strncasecmp(s1, s2, n) == 0);
+}
+
 boolean strPrefix(char *s, char *prefix)
 {
   return (s == NULL && prefix == NULL ? TRUE  :
@@ -1135,7 +1241,6 @@ void GetOptions(int argc, char *argv[],
                void (*print_version_function)(void))
 {
   char *ro_base_path = getProgramMainDataPath(argv[0], RO_BASE_PATH);
-  char *rw_base_path = getProgramMainDataPath(argv[0], RW_BASE_PATH);
   char **argvplus = checked_calloc((argc + 1) * sizeof(char **));
   char **options_left = &argvplus[1];
 
@@ -1148,7 +1253,6 @@ void GetOptions(int argc, char *argv[],
   options.server_port = 0;
 
   options.ro_base_directory = ro_base_path;
-  options.rw_base_directory = rw_base_path;
   options.level_directory    = getPath2(ro_base_path, LEVELS_DIRECTORY);
   options.graphics_directory = getPath2(ro_base_path, GRAPHICS_DIRECTORY);
   options.sounds_directory   = getPath2(ro_base_path, SOUNDS_DIRECTORY);
@@ -1228,9 +1332,7 @@ void GetOptions(int argc, char *argv[],
       if (option_arg == NULL)
        FailWithHelp("option '%s' requires an argument", option_str);
 
-      // this should be extended to separate options for ro and rw data
       options.ro_base_directory = ro_base_path = getStringCopy(option_arg);
-      options.rw_base_directory = rw_base_path = getStringCopy(option_arg);
       if (option_arg == next_option)
        options_left++;
 
@@ -1619,6 +1721,124 @@ void WriteUnusedBytesToFile(FILE *file, unsigned int bytes)
 }
 
 
+// ----------------------------------------------------------------------------
+// functions to convert between ISO-8859-1 and UTF-8
+// ----------------------------------------------------------------------------
+
+char *getUTF8FromLatin1(char *latin1)
+{
+  int max_utf8_size = 2 * strlen(latin1) + 1;
+  char *utf8 = checked_calloc(max_utf8_size);
+  unsigned char *src = (unsigned char *)latin1;
+  unsigned char *dst = (unsigned char *)utf8;
+
+  while (*src)
+  {
+    if (*src < 128)            // pure 7-bit ASCII
+    {
+      *dst++ = *src;
+    }
+    else if (*src >= 160)      // non-ASCII characters
+    {
+      *dst++ = 194 + (*src >= 192);
+      *dst++ = 128 + (*src & 63);
+    }
+    else                       // undefined in ISO-8859-1
+    {
+      *dst++ = '?';
+    }
+
+    src++;
+  }
+
+  // only use the smallest possible string buffer size
+  utf8 = checked_realloc(utf8, strlen(utf8) + 1);
+
+  return utf8;
+}
+
+char *getLatin1FromUTF8(char *utf8)
+{
+  int max_latin1_size = strlen(utf8) + 1;
+  char *latin1 = checked_calloc(max_latin1_size);
+  unsigned char *src = (unsigned char *)utf8;
+  unsigned char *dst = (unsigned char *)latin1;
+
+  while (*src)
+  {
+    if (*src < 128)                            // pure 7-bit ASCII
+    {
+      *dst++ = *src++;
+    }
+    else if (src[0] == 194 &&
+            src[1] >= 128 && src[1] < 192)     // non-ASCII characters
+    {
+      *dst++ = src[1];
+      src += 2;
+    }
+    else if (src[0] == 195 &&
+            src[1] >= 128 && src[1] < 192)     // non-ASCII characters
+    {
+      *dst++ = src[1] + 64;
+      src += 2;
+    }
+
+    // all other UTF-8 characters are undefined in ISO-8859-1
+
+    else if (src[0] >= 192 && src[0] < 224 &&
+            src[1] >= 128 && src[1] < 192)
+    {
+      *dst++ = '?';
+      src += 2;
+    }
+    else if (src[0] >= 224 && src[0] < 240 &&
+            src[1] >= 128 && src[1] < 192 &&
+            src[2] >= 128 && src[2] < 192)
+    {
+      *dst++ = '?';
+      src += 3;
+    }
+    else if (src[0] >= 240 && src[0] < 248 &&
+            src[1] >= 128 && src[1] < 192 &&
+            src[2] >= 128 && src[2] < 192 &&
+            src[3] >= 128 && src[3] < 192)
+    {
+      *dst++ = '?';
+      src += 4;
+    }
+    else if (src[0] >= 248 && src[0] < 252 &&
+            src[1] >= 128 && src[1] < 192 &&
+            src[2] >= 128 && src[2] < 192 &&
+            src[3] >= 128 && src[3] < 192 &&
+            src[4] >= 128 && src[4] < 192)
+    {
+      *dst++ = '?';
+      src += 5;
+    }
+    else if (src[0] >= 252 && src[0] < 254 &&
+            src[1] >= 128 && src[1] < 192 &&
+            src[2] >= 128 && src[2] < 192 &&
+            src[3] >= 128 && src[3] < 192 &&
+            src[4] >= 128 && src[4] < 192 &&
+            src[5] >= 128 && src[5] < 192)
+    {
+      *dst++ = '?';
+      src += 6;
+    }
+    else
+    {
+      *dst++ = '?';
+      src++;
+    }
+  }
+
+  // only use the smallest possible string buffer size
+  latin1 = checked_realloc(latin1, strlen(latin1) + 1);
+
+  return latin1;
+}
+
+
 // ----------------------------------------------------------------------------
 // functions to translate key identifiers between different format
 // ----------------------------------------------------------------------------
@@ -3718,14 +3938,14 @@ void FreeCustomArtworkLists(struct ArtworkListInfo *artwork_info)
 
 char *getLogFilename(char *basename)
 {
-  return getPath2(getUserGameDataDir(), basename);
+  return getPath2(getMainUserGameDataDir(), basename);
 }
 
 void OpenLogFiles(void)
 {
   int i;
 
-  InitUserDataDirectory();
+  InitMainUserDataDirectory();
 
   for (i = 0; i < NUM_LOGS; i++)
   {
@@ -3785,7 +4005,7 @@ void NotifyUserAboutErrorFile(void)
 
 #if DEBUG
 
-#define DEBUG_PRINT_INIT_TIMESTAMPS            FALSE
+#define DEBUG_PRINT_INIT_TIMESTAMPS            TRUE
 #define DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH      10
 
 #define DEBUG_NUM_TIMESTAMPS                   10
@@ -3853,7 +4073,7 @@ void debug_print_timestamp(int counter_nr, char *message)
   counter[counter_nr][1] = counter[counter_nr][0];
 
   if (message)
-    Debug("time", "%s%s%s %.3f %s",
+    Debug("time:init", "%s%s%s %.3f %s",
          debug_print_timestamp_get_padding(counter_nr * indent_size),
          message,
          debug_print_timestamp_get_padding(padding_size - strlen(message)),