rnd-20060726-5-src
[rocksndiamonds.git] / src / libgame / misc.c
index 154f83438daa3a83370cb8464b97b2778d64e855..6c8734405b33080dfae098d5128b23de904c531c 100644 (file)
 #include "image.h"
 
 
-/* ------------------------------------------------------------------------- */
+/* ========================================================================= */
 /* some generic helper functions                                             */
+/* ========================================================================= */
+
+/* ------------------------------------------------------------------------- */
+/* platform independent wrappers for printf() et al. (newline aware)         */
 /* ------------------------------------------------------------------------- */
 
-void fprintf_line(FILE *stream, char *line_string, int line_length)
+static void vfprintf_newline(FILE *stream, char *format, va_list ap)
+{
+#if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
+  char *newline = "\r\n";
+#else
+  char *newline = "\n";
+#endif
+
+  vfprintf(stream, format, ap);
+
+  fprintf(stream, "%s", newline);
+}
+
+static void vprintf_error_ext(char *format, va_list ap, boolean print_newline)
+{
+  FILE *error = stderr;
+
+#if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
+  if ((error = openErrorFile()) == NULL)
+    program.exit_function(1);
+#endif
+
+  if (print_newline)
+    vfprintf_newline(error, format, ap);
+  else
+    vfprintf(error, format, ap);
+
+  if (error != stderr)
+    fclose(error);
+}
+
+static void vprintf_error(char *format, va_list ap)
+{
+  vprintf_error_ext(format, ap, FALSE);
+}
+
+static void vprintf_error_newline(char *format, va_list ap)
+{
+  vprintf_error_ext(format, ap, TRUE);
+}
+
+static void printf_error(char *format, ...)
+{
+  if (format)
+  {
+    va_list ap;
+
+    va_start(ap, format);
+    vprintf_error(format, ap);
+    va_end(ap);
+  }
+}
+
+static void printf_error_newline(char *format, ...)
+{
+  if (format)
+  {
+    va_list ap;
+
+    va_start(ap, format);
+    vprintf_error_newline(format, ap);
+    va_end(ap);
+  }
+}
+
+static void fprintf_newline(FILE *stream, char *format, ...)
 {
+  if (format)
+  {
+    va_list ap;
+
+    va_start(ap, format);
+    vfprintf_newline(stream, format, ap);
+    va_end(ap);
+  }
+}
+
+static char *get_line_string(char *line_chars, int line_length)
+{
+  static char *buffer = NULL;
+  int line_chars_length = strlen(line_chars);
   int i;
 
+  if (buffer != NULL)
+    checked_free(buffer);
+
+  buffer = checked_malloc(line_chars_length * line_length + 1);
+
   for (i = 0; i < line_length; i++)
-    fprintf(stream, "%s", line_string);
+    strcpy(&buffer[i * line_chars_length], line_chars);
 
-  fprintf(stream, "\n");
+  return buffer;
+}
+
+void fprintf_line(FILE *stream, char *line_chars, int line_length)
+{
+  fprintf_newline(stream, get_line_string(line_chars, line_length));
+}
+
+void printf_line(char *line_chars, int line_length)
+{
+  fprintf_line(stdout, line_chars, line_length);
 }
 
-void printf_line(char *line_string, int line_length)
+void printf_line_error(char *line_chars, int line_length)
 {
-  fprintf_line(stdout, line_string, line_length);
+  printf_error_newline(get_line_string(line_chars, line_length));
 }
 
-void printf_line_with_prefix(char *prefix, char *line_string, int line_length)
+void printf_line_with_prefix(char *prefix, char *line_chars, int line_length)
 {
   fprintf(stdout, "%s", prefix);
-  fprintf_line(stdout, line_string, line_length);
+  fprintf_line(stdout, line_chars, line_length);
 }
 
 
+/* ------------------------------------------------------------------------- */
+/* string functions                                                          */
+/* ------------------------------------------------------------------------- */
+
 /* int2str() returns a number converted to a string;
    the used memory is static, but will be overwritten by later calls,
    so if you want to save the result, copy it to a private string buffer;
@@ -470,7 +572,7 @@ static char *getLastPathSeparatorPtr(char *filename)
   return last_separator;
 }
 
-static char *getBaseNamePtr(char *filename)
+char *getBaseNamePtr(char *filename)
 {
   char *last_separator = getLastPathSeparatorPtr(filename);
 
@@ -750,6 +852,45 @@ void GetOptions(char *argv[], void (*print_usage_function)(void))
       /* when doing batch processing, always enable verbose mode (warnings) */
       options.verbose = TRUE;
     }
+#if 1
+#if DEBUG
+#if defined(TARGET_SDL)
+    else if (strncmp(option, "-SDL_ListModes", option_len) == 0)
+    {
+      SDL_Rect **modes;
+      int i;
+
+      SDL_Init(SDL_INIT_VIDEO);
+
+      /* get available fullscreen/hardware modes */
+      modes=SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_HWSURFACE);
+
+      /* check if there are any modes available */
+      if (modes == (SDL_Rect **)0)
+      {
+       printf("No modes available!\n");
+
+       exit(-1);
+      }
+
+      /* check if our resolution is restricted */
+      if (modes == (SDL_Rect **)-1)
+      {
+       printf("All resolutions available.\n");
+      }
+      else
+      {
+       /* print valid modes */
+       printf("Available Modes:\n");
+       for(i = 0; modes[i]; i++)
+         printf("  %d x %d\n", modes[i]->w, modes[i]->h);
+      }
+
+      exit(0);
+    }
+#endif
+#endif
+#endif
     else if (*option == '-')
     {
       Error(ERR_EXIT_HELP, "unrecognized option '%s'", option_str);
@@ -793,6 +934,69 @@ char *GetError()
   return internal_error;
 }
 
+#if 1
+
+void Error(int mode, char *format, ...)
+{
+  static boolean last_line_was_separator = FALSE;
+  char *process_name = "";
+
+  /* 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)
+      printf_line_error(format, 79);
+
+    last_line_was_separator = TRUE;
+
+    return;
+  }
+
+  last_line_was_separator = FALSE;
+
+  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;
+
+    printf_error("%s%s: ", program.command_basename, process_name);
+
+    if (mode & ERR_WARN)
+      printf_error("warning: ");
+
+    va_start(ap, format);
+    vprintf_error_newline(format, ap);
+    va_end(ap);
+  }
+  
+  if (mode & ERR_HELP)
+    printf_error_newline("%s: Try option '--help' for more information.",
+                        program.command_basename);
+
+  if (mode & ERR_EXIT)
+    printf_error_newline("%s%s: aborting",
+                        program.command_basename, process_name);
+
+  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 */
+  }
+}
+
+#else
+
 void Error(int mode, char *format, ...)
 {
   static boolean last_line_was_separator = FALSE;
@@ -816,12 +1020,13 @@ void Error(int mode, char *format, ...)
 
   last_line_was_separator = FALSE;
 
-#if defined(PLATFORM_MSDOS)
+#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
@@ -869,6 +1074,8 @@ void Error(int mode, char *format, ...)
   }
 }
 
+#endif
+
 
 /* ------------------------------------------------------------------------- */
 /* checked memory allocation and freeing functions                           */
@@ -1041,17 +1248,27 @@ boolean getFileChunk(FILE *file, char *chunk_name, int *chunk_size,
   return (feof(file) || ferror(file) ? FALSE : TRUE);
 }
 
-void putFileChunk(FILE *file, char *chunk_name, int chunk_size,
-                 int byte_order)
+int putFileChunk(FILE *file, char *chunk_name, int chunk_size,
+                int byte_order)
 {
+  int num_bytes = 0;
+
   /* write chunk name */
-  fputs(chunk_name, file);
+  if (file != NULL)
+    fputs(chunk_name, file);
+
+  num_bytes += strlen(chunk_name);
 
   if (chunk_size >= 0)
   {
     /* write chunk size */
-    putFile32BitInteger(file, chunk_size, byte_order);
+    if (file != NULL)
+      putFile32BitInteger(file, chunk_size, byte_order);
+
+    num_bytes += 4;
   }
+
+  return num_bytes;
 }
 
 int getFileVersion(FILE *file)
@@ -1065,17 +1282,22 @@ int getFileVersion(FILE *file)
                       version_build);
 }
 
-void putFileVersion(FILE *file, int version)
+int putFileVersion(FILE *file, int version)
 {
-  int version_major = VERSION_MAJOR(version);
-  int version_minor = VERSION_MINOR(version);
-  int version_patch = VERSION_PATCH(version);
-  int version_build = VERSION_BUILD(version);
+  if (file != NULL)
+  {
+    int version_major = VERSION_MAJOR(version);
+    int version_minor = VERSION_MINOR(version);
+    int version_patch = VERSION_PATCH(version);
+    int version_build = VERSION_BUILD(version);
+
+    fputc(version_major, file);
+    fputc(version_minor, file);
+    fputc(version_patch, file);
+    fputc(version_build, file);
+  }
 
-  fputc(version_major, file);
-  fputc(version_minor, file);
-  fputc(version_patch, file);
-  fputc(version_build, file);
+  return 4;
 }
 
 void ReadBytesFromFile(FILE *file, byte *buffer, unsigned long bytes)
@@ -1779,6 +2001,7 @@ int get_parameter_value(char *value_raw, char *suffix, int type)
              string_has_parameter(value, "random")     ? ANIM_RANDOM :
              string_has_parameter(value, "ce_value")   ? ANIM_CE_VALUE :
              string_has_parameter(value, "ce_score")   ? ANIM_CE_SCORE :
+             string_has_parameter(value, "ce_delay")   ? ANIM_CE_DELAY :
              string_has_parameter(value, "horizontal") ? ANIM_HORIZONTAL :
              string_has_parameter(value, "vertical")   ? ANIM_VERTICAL :
              ANIM_DEFAULT);
@@ -2067,6 +2290,10 @@ static void LoadArtworkConfigFromFilename(struct ArtworkListInfo *artwork_info,
   if (filename == NULL)
     return;
 
+#if 0
+  printf("LoadArtworkConfigFromFilename '%s' ...\n", filename);
+#endif
+
   if ((setup_file_hash = loadSetupFileHash(filename)) == NULL)
     return;
 
@@ -2433,10 +2660,6 @@ void LoadArtworkConfig(struct ArtworkListInfo *artwork_info)
   char *filename_base = UNDEFINED_FILENAME, *filename_local;
   int i, j;
 
-#if 0
-  printf("GOT CUSTOM ARTWORK CONFIG FILE '%s'\n", filename);
-#endif
-
   DrawInitText("Loading artwork config:", 120, FC_GREEN);
   DrawInitText(ARTWORKINFO_FILENAME(artwork_info->type), 150, FC_YELLOW);
 
@@ -2681,25 +2904,51 @@ void FreeCustomArtworkLists(struct ArtworkListInfo *artwork_info)
 /* ------------------------------------------------------------------------- */
 /* functions only needed for non-Unix (non-command-line) systems             */
 /* (MS-DOS only; SDL/Windows creates files "stdout.txt" and "stderr.txt")    */
+/* (now also added for Windows, to create files in user data directory)      */
 /* ------------------------------------------------------------------------- */
 
-#if defined(PLATFORM_MSDOS)
+#if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
+
+#define ERROR_BASENAME         "stderr.txt"
 
-#define ERROR_FILENAME         "stderr.txt"
+static char *error_filename = NULL;
+
+#if defined(PLATFORM_WIN32)
 
 void initErrorFile()
 {
-  unlink(ERROR_FILENAME);
+  if (error_filename == NULL)
+    error_filename = getPath2(getUserDataDir(), ERROR_BASENAME);
+
+  unlink(error_filename);
 }
 
+#elif defined(PLATFORM_MSDOS)
+
+void initErrorFile()
+{
+  if (error_filename == NULL)
+    error_filename = ERROR_BASENAME;
+
+  unlink(error_filename);
+}
+
+#endif /* PLATFORM_MSDOS */
+
 FILE *openErrorFile()
 {
-  return fopen(ERROR_FILENAME, MODE_APPEND);
+  FILE *error_file = fopen(error_filename, MODE_APPEND);
+
+  if (error_file == NULL)
+    fprintf_newline(stderr, "ERROR: cannot open file '%s' for appending!",
+                   error_filename);
+
+  return error_file;
 }
 
 void dumpErrorFile()
 {
-  FILE *error_file = fopen(ERROR_FILENAME, MODE_READ);
+  FILE *error_file = fopen(error_filename, MODE_READ);
 
   if (error_file != NULL)
   {
@@ -2709,7 +2958,8 @@ void dumpErrorFile()
     fclose(error_file);
   }
 }
-#endif
+
+#endif /* PLATFORM_WIN32 || PLATFORM_MSDOS */
 
 
 /* ------------------------------------------------------------------------- */