rnd-20070302-1-src
[rocksndiamonds.git] / src / libgame / misc.c
index 9125a4e142740346420966d5957ed6711463a27c..41b68190559a73a7eae920ee3e1a472000197120 100644 (file)
@@ -1,7 +1,7 @@
 /***********************************************************
 * Artsoft Retro-Game Library                               *
 *----------------------------------------------------------*
-* (c) 1994-2002 Artsoft Entertainment                      *
+* (c) 1994-2006 Artsoft Entertainment                      *
 *               Holger Schemel                             *
 *               Detmolder Strasse 189                      *
 *               33604 Bielefeld                            *
@@ -450,38 +450,6 @@ char *getRealName()
   return real_name;
 }
 
-char *getHomeDir()
-{
-  static char *dir = NULL;
-
-#if defined(PLATFORM_WIN32)
-  if (dir == NULL)
-  {
-    dir = checked_malloc(MAX_PATH + 1);
-
-    if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, dir)))
-      strcpy(dir, ".");
-  }
-#elif defined(PLATFORM_UNIX)
-  if (dir == NULL)
-  {
-    if ((dir = getenv("HOME")) == NULL)
-    {
-      struct passwd *pwd;
-
-      if ((pwd = getpwuid(getuid())) != NULL)
-       dir = getStringCopy(pwd->pw_dir);
-      else
-       dir = ".";
-    }
-  }
-#else
-  dir = ".";
-#endif
-
-  return dir;
-}
-
 
 /* ------------------------------------------------------------------------- */
 /* path manipulation functions                                               */
@@ -530,36 +498,45 @@ char *getBasePath(char *filename)
 /* various string functions                                                  */
 /* ------------------------------------------------------------------------- */
 
-char *getPath2(char *path1, char *path2)
+char *getStringCat2WithSeparator(char *s1, char *s2, char *sep)
 {
-  char *sep = STRING_PATH_SEPARATOR;
-  char *complete_path = checked_malloc(strlen(path1) + 1 +
-                                      strlen(path2) + 1);
+  char *complete_string = checked_malloc(strlen(s1) + strlen(sep) +
+                                        strlen(s2) + 1);
 
-  sprintf(complete_path, "%s%s%s", path1, sep, path2);
+  sprintf(complete_string, "%s%s%s", s1, sep, s2);
 
-  return complete_path;
+  return complete_string;
 }
 
-char *getPath3(char *path1, char *path2, char *path3)
+char *getStringCat3WithSeparator(char *s1, char *s2, char *s3, char *sep)
 {
-  char *sep = STRING_PATH_SEPARATOR;
-  char *complete_path = checked_malloc(strlen(path1) + 1 +
-                                      strlen(path2) + 1 +
-                                      strlen(path3) + 1);
+  char *complete_string = checked_malloc(strlen(s1) + strlen(sep) +
+                                        strlen(s2) + strlen(sep) +
+                                        strlen(s3) + 1);
 
-  sprintf(complete_path, "%s%s%s%s%s", path1, sep, path2, sep, path3);
+  sprintf(complete_string, "%s%s%s%s%s", s1, sep, s2, sep, s3);
 
-  return complete_path;
+  return complete_string;
 }
 
 char *getStringCat2(char *s1, char *s2)
 {
-  char *complete_string = checked_malloc(strlen(s1) + strlen(s2) + 1);
+  return getStringCat2WithSeparator(s1, s2, "");
+}
+
+char *getStringCat3(char *s1, char *s2, char *s3)
+{
+  return getStringCat3WithSeparator(s1, s2, s3, "");
+}
 
-  sprintf(complete_string, "%s%s", s1, s2);
+char *getPath2(char *path1, char *path2)
+{
+  return getStringCat2WithSeparator(path1, path2, STRING_PATH_SEPARATOR);
+}
 
-  return complete_string;
+char *getPath3(char *path1, char *path2, char *path3)
+{
+  return getStringCat3WithSeparator(path1, path2, path3, STRING_PATH_SEPARATOR);
 }
 
 char *getStringCopy(char *s)
@@ -822,8 +799,6 @@ char *GetError()
   return internal_error;
 }
 
-#if 1
-
 void Error(int mode, char *format, ...)
 {
   static boolean last_line_was_separator = FALSE;
@@ -833,7 +808,7 @@ void Error(int mode, char *format, ...)
   if (mode & ERR_WARN && !options.verbose)
     return;
 
-  if (mode == ERR_RETURN_LINE)
+  if (mode == ERR_INFO_LINE)
   {
     if (!last_line_was_separator)
       fprintf_line(program.error_file, format, 79);
@@ -885,87 +860,6 @@ void Error(int mode, char *format, ...)
   }
 }
 
-#else
-
-void Error(int mode, char *format, ...)
-{
-  static boolean last_line_was_separator = FALSE;
-  char *process_name = "";
-  FILE *error = stderr;
-  char *newline = "\n";
-
-  /* display warnings only when running in verbose mode */
-  if (mode & ERR_WARN && !options.verbose)
-    return;
-
-  if (mode == ERR_RETURN_LINE)
-  {
-    if (!last_line_was_separator)
-      fprintf_line(error, format, 79);
-
-    last_line_was_separator = TRUE;
-
-    return;
-  }
-
-  last_line_was_separator = FALSE;
-
-#if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
-  newline = "\r\n";
-
-  if ((error = openErrorFile()) == NULL)
-  {
-    printf("Cannot write to error output file!%s", newline);
-
-    program.exit_function(1);
-  }
-#endif
-
-  if (mode & ERR_SOUND_SERVER)
-    process_name = " sound server";
-  else if (mode & ERR_NETWORK_SERVER)
-    process_name = " network server";
-  else if (mode & ERR_NETWORK_CLIENT)
-    process_name = " network client **";
-
-  if (format)
-  {
-    va_list ap;
-
-    fprintf(error, "%s%s: ", program.command_basename, process_name);
-
-    if (mode & ERR_WARN)
-      fprintf(error, "warning: ");
-
-    va_start(ap, format);
-    vfprintf(error, format, ap);
-    va_end(ap);
-  
-    fprintf(error, "%s", newline);
-  }
-  
-  if (mode & ERR_HELP)
-    fprintf(error, "%s: Try option '--help' for more information.%s",
-           program.command_basename, newline);
-
-  if (mode & ERR_EXIT)
-    fprintf(error, "%s%s: aborting%s",
-           program.command_basename, process_name, newline);
-
-  if (error != stderr)
-    fclose(error);
-
-  if (mode & ERR_EXIT)
-  {
-    if (mode & ERR_FROM_SERVER)
-      exit(1);                         /* child process: normal exit */
-    else
-      program.exit_function(1);                /* main process: clean up stuff */
-  }
-}
-
-#endif
-
 
 /* ------------------------------------------------------------------------- */
 /* checked memory allocation and freeing functions                           */
@@ -1325,6 +1219,7 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
     { KSYM_asciitilde, "XK_asciitilde",        "~" },
 
     /* special (non-ASCII) keys */
+    { KSYM_degree,     "XK_degree",            "°" },
     { KSYM_Adiaeresis, "XK_Adiaeresis",        "Ä" },
     { KSYM_Odiaeresis, "XK_Odiaeresis",        "Ö" },
     { KSYM_Udiaeresis, "XK_Udiaeresis",        "Ü" },
@@ -1352,13 +1247,8 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
       sprintf(name_buffer, "%c", '0' + (char)(key - KSYM_0));
     else if (key >= KSYM_KP_0 && key <= KSYM_KP_9)
       sprintf(name_buffer, "keypad %c", '0' + (char)(key - KSYM_KP_0));
-#if 1
     else if (key >= KSYM_FKEY_FIRST && key <= KSYM_FKEY_LAST)
       sprintf(name_buffer, "F%d", (int)(key - KSYM_FKEY_FIRST + 1));
-#else
-    else if (key >= KSYM_FKEY_FIRST && key <= KSYM_FKEY_LAST)
-      sprintf(name_buffer, "function F%d", (int)(key - KSYM_FKEY_FIRST + 1));
-#endif
     else if (key == KSYM_UNDEFINED)
       strcpy(name_buffer, "(undefined)");
     else
@@ -1558,16 +1448,23 @@ Key getKeyFromX11KeyName(char *x11name)
 char getCharFromKey(Key key)
 {
   char *keyname = getKeyNameFromKey(key);
-  char letter = 0;
+  char c = 0;
 
   if (strlen(keyname) == 1)
-    letter = keyname[0];
+    c = keyname[0];
   else if (strEqual(keyname, "space"))
-    letter = ' ';
-  else if (strEqual(keyname, "circumflex"))
-    letter = '^';
+    c = ' ';
 
-  return letter;
+  return c;
+}
+
+char getValidConfigValueChar(char c)
+{
+  if (c == '#' ||      /* used to mark comments */
+      c == '\\')       /* used to mark continued lines */
+    c = 0;
+
+  return c;
 }
 
 
@@ -1664,7 +1561,7 @@ void deleteNodeFromList(ListNode **node_first, char *key,
 
   if (strEqual((*node_first)->key, key))
   {
-    free((*node_first)->key);
+    checked_free((*node_first)->key);
     if (destructor_function)
       destructor_function((*node_first)->content);
     *node_first = (*node_first)->next;
@@ -1881,6 +1778,12 @@ int get_parameter_value(char *value_raw, char *suffix, int type)
              strEqual(value, "up")    ? MV_UP :
              strEqual(value, "down")  ? MV_DOWN : MV_NONE);
   }
+  else if (strEqual(suffix, ".align"))
+  {
+    result = (strEqual(value, "left")   ? ALIGN_LEFT :
+             strEqual(value, "right")  ? ALIGN_RIGHT :
+             strEqual(value, "center") ? ALIGN_CENTER : ALIGN_DEFAULT);
+  }
   else if (strEqual(suffix, ".anim_mode"))
   {
     result = (string_has_parameter(value, "none")      ? ANIM_NONE :
@@ -1894,6 +1797,9 @@ int get_parameter_value(char *value_raw, char *suffix, int type)
              string_has_parameter(value, "ce_delay")   ? ANIM_CE_DELAY :
              string_has_parameter(value, "horizontal") ? ANIM_HORIZONTAL :
              string_has_parameter(value, "vertical")   ? ANIM_VERTICAL :
+             string_has_parameter(value, "centered")   ? ANIM_CENTERED :
+             string_has_parameter(value, "fade")       ? ANIM_FADE :
+             string_has_parameter(value, "crossfade")  ? ANIM_CROSSFADE :
              ANIM_DEFAULT);
 
     if (string_has_parameter(value, "reverse"))
@@ -1932,6 +1838,48 @@ int get_auto_parameter_value(char *token, char *value_raw)
   return get_parameter_value(value_raw, suffix, TYPE_INTEGER);
 }
 
+struct ScreenModeInfo *get_screen_mode_from_string(char *screen_mode_string)
+{
+  static struct ScreenModeInfo screen_mode;
+  char *screen_mode_string_x = strchr(screen_mode_string, 'x');
+  char *screen_mode_string_copy;
+  char *screen_mode_string_pos_w;
+  char *screen_mode_string_pos_h;
+
+  if (screen_mode_string_x == NULL)    /* invalid screen mode format */
+    return NULL;
+
+  screen_mode_string_copy = getStringCopy(screen_mode_string);
+
+  screen_mode_string_pos_w = screen_mode_string_copy;
+  screen_mode_string_pos_h = strchr(screen_mode_string_copy, 'x');
+  *screen_mode_string_pos_h++ = '\0';
+
+  screen_mode.width  = atoi(screen_mode_string_pos_w);
+  screen_mode.height = atoi(screen_mode_string_pos_h);
+
+  return &screen_mode;
+}
+
+void get_aspect_ratio_from_screen_mode(struct ScreenModeInfo *screen_mode,
+                                      int *x, int *y)
+{
+  float aspect_ratio = (float)screen_mode->width / (float)screen_mode->height;
+  float aspect_ratio_new;
+  int i = 1;
+
+  do
+  {
+    *x = i * aspect_ratio + 0.000001;
+    *y = i;
+
+    aspect_ratio_new = (float)*x / (float)*y;
+
+    i++;
+  }
+  while (aspect_ratio_new != aspect_ratio && *y < screen_mode->height);
+}
+
 static void FreeCustomArtworkList(struct ArtworkListInfo *,
                                  struct ListNodeInfo ***, int *);
 
@@ -2018,28 +1966,36 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list,
          !strEqual(&config_list[i].value[len_config_value - 4], ".wav") &&
          !strEqual(config_list[i].value, UNDEFINED_FILENAME))
       {
-       Error(ERR_RETURN, "Configuration directive '%s' -> '%s':",
+       Error(ERR_INFO, "Configuration directive '%s' -> '%s':",
              config_list[i].token, config_list[i].value);
        Error(ERR_EXIT, "This seems to be no valid definition -- please fix");
       }
 
       file_list[list_pos].token = config_list[i].token;
       file_list[list_pos].default_filename = config_list[i].value;
+
+#if 0
+      printf("::: '%s' => '%s'\n", config_list[i].token, config_list[i].value);
+#endif
     }
   }
 
   num_file_list_entries_found = list_pos + 1;
   if (num_file_list_entries_found != num_file_list_entries)
   {
-    Error(ERR_RETURN_LINE, "-");
-    Error(ERR_RETURN, "inconsistant config list information:");
-    Error(ERR_RETURN, "- should be:   %d (according to 'src/conf_gfx.h')",
+    Error(ERR_INFO_LINE, "-");
+    Error(ERR_INFO, "inconsistant config list information:");
+    Error(ERR_INFO, "- should be:   %d (according to 'src/conf_xxx.h')",
          num_file_list_entries);
-    Error(ERR_RETURN, "- found to be: %d (according to 'src/conf_gfx.c')",
+    Error(ERR_INFO, "- found to be: %d (according to 'src/conf_xxx.c')",
          num_file_list_entries_found);
     Error(ERR_EXIT,   "please fix");
   }
 
+#if 0
+  printf("::: ---------- DONE ----------\n");
+#endif
+
   return file_list;
 }
 
@@ -2475,53 +2431,53 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
 
     if (options.debug && dynamic_tokens_found)
     {
-      Error(ERR_RETURN_LINE, "-");
-      Error(ERR_RETURN, "dynamic token(s) found in config file:");
-      Error(ERR_RETURN, "- config file: '%s'", filename);
+      Error(ERR_INFO_LINE, "-");
+      Error(ERR_INFO, "dynamic token(s) found in config file:");
+      Error(ERR_INFO, "- config file: '%s'", filename);
 
       for (list = setup_file_list; list != NULL; list = list->next)
       {
        char *value = getHashEntry(extra_file_hash, list->token);
 
        if (value != NULL && strEqual(value, known_token_value))
-         Error(ERR_RETURN, "- dynamic token: '%s'", list->token);
+         Error(ERR_INFO, "- dynamic token: '%s'", list->token);
       }
 
-      Error(ERR_RETURN_LINE, "-");
+      Error(ERR_INFO_LINE, "-");
     }
 
     if (unknown_tokens_found)
     {
-      Error(ERR_RETURN_LINE, "-");
-      Error(ERR_RETURN, "warning: unknown token(s) found in config file:");
-      Error(ERR_RETURN, "- config file: '%s'", filename);
+      Error(ERR_INFO_LINE, "-");
+      Error(ERR_INFO, "warning: unknown token(s) found in config file:");
+      Error(ERR_INFO, "- config file: '%s'", filename);
 
       for (list = setup_file_list; list != NULL; list = list->next)
       {
        char *value = getHashEntry(extra_file_hash, list->token);
 
        if (value != NULL && !strEqual(value, known_token_value))
-         Error(ERR_RETURN, "- dynamic token: '%s'", list->token);
+         Error(ERR_INFO, "- dynamic token: '%s'", list->token);
       }
 
-      Error(ERR_RETURN_LINE, "-");
+      Error(ERR_INFO_LINE, "-");
     }
 
     if (undefined_values_found)
     {
-      Error(ERR_RETURN_LINE, "-");
-      Error(ERR_RETURN, "warning: undefined values found in config file:");
-      Error(ERR_RETURN, "- config file: '%s'", filename);
+      Error(ERR_INFO_LINE, "-");
+      Error(ERR_INFO, "warning: undefined values found in config file:");
+      Error(ERR_INFO, "- config file: '%s'", filename);
 
       for (list = setup_file_list; list != NULL; list = list->next)
       {
        char *value = getHashEntry(empty_file_hash, list->token);
 
        if (value != NULL)
-         Error(ERR_RETURN, "- undefined value for token: '%s'", list->token);
+         Error(ERR_INFO, "- undefined value for token: '%s'", list->token);
       }
 
-      Error(ERR_RETURN_LINE, "-");
+      Error(ERR_INFO_LINE, "-");
     }
 
     freeSetupFileList(setup_file_list);
@@ -2550,7 +2506,7 @@ void LoadArtworkConfig(struct ArtworkListInfo *artwork_info)
   char *filename_base = UNDEFINED_FILENAME, *filename_local;
   int i, j;
 
-  DrawInitText("Loading artwork config:", 120, FC_GREEN);
+  DrawInitText("Loading artwork config", 120, FC_GREEN);
   DrawInitText(ARTWORKINFO_FILENAME(artwork_info->type), 150, FC_YELLOW);
 
   /* always start with reliable default values */
@@ -2627,9 +2583,9 @@ static void replaceArtworkListEntry(struct ArtworkListInfo *artwork_info,
 {
   char *init_text[] =
   {
-    "Loading graphics:",
-    "Loading sounds:",
-    "Loading music:"
+    "Loading graphics",
+    "Loading sounds",
+    "Loading music"
   };
 
   ListNode *node;
@@ -2799,19 +2755,16 @@ void FreeCustomArtworkLists(struct ArtworkListInfo *artwork_info)
 
 char *getErrorFilename(char *basename)
 {
-  return getPath2(getUserDataDir(), basename);
+  return getPath2(getUserGameDataDir(), basename);
 }
 
 void openErrorFile()
 {
-  /* always start with reliable default values */
-  program.error_file = stderr;
+  InitUserDataDirectory();
 
-#if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
   if ((program.error_file = fopen(program.error_filename, MODE_WRITE)) == NULL)
     fprintf_newline(stderr, "ERROR: cannot open file '%s' for writing!",
                    program.error_filename);
-#endif
 }
 
 void closeErrorFile()
@@ -2850,6 +2803,8 @@ void NotifyUserAboutErrorFile()
 /* the following is only for debugging purpose and normally not used         */
 /* ------------------------------------------------------------------------- */
 
+#if DEBUG
+
 #define DEBUG_NUM_TIMESTAMPS   3
 
 void debug_print_timestamp(int counter_nr, char *message)
@@ -2862,10 +2817,10 @@ void debug_print_timestamp(int counter_nr, char *message)
   counter[counter_nr][0] = Counter();
 
   if (message)
-    printf("%s %.2f seconds\n", message,
+    printf("%s %.3f seconds\n", message,
           (float)(counter[counter_nr][0] - counter[counter_nr][1]) / 1000);
 
-  counter[counter_nr][1] = Counter();
+  counter[counter_nr][1] = counter[counter_nr][0];
 }
 
 void debug_print_parent_only(char *format, ...)
@@ -2884,3 +2839,4 @@ void debug_print_parent_only(char *format, ...)
     printf("\n");
   }
 }
+#endif