rnd-19990205-1
[rocksndiamonds.git] / src / misc.c
index a7e52dcc4a71aaf2273ae986ec1ff2551ed46a50..fd85aeddac9e433635bff3586077c11e6fa5ad2f 100644 (file)
@@ -18,6 +18,7 @@
 #include <sys/param.h>
 #include <sys/types.h>
 #include <stdarg.h>
+#include <ctype.h>
 
 #include "misc.h"
 #include "init.h"
 #include "sound.h"
 #include "random.h"
 #include "joystick.h"
+#include "files.h"
 
+#ifdef MSDOS
+volatile unsigned long counter = 0;
+
+void increment_counter()
+{
+  counter++;
+}
+
+END_OF_FUNCTION(increment_counter);
+#endif
+
+
+
+/* maximal allowed length of a command line option */
+#define MAX_OPTION_LEN         256
+
+#ifndef MSDOS
 static unsigned long mainCounter(int mode)
 {
   static struct timeval base_time = { 0, 0 };
@@ -42,20 +61,39 @@ static unsigned long mainCounter(int mode)
 
   return counter_ms;           /* return milliseconds since last init */
 }
+#endif
 
 void InitCounter()             /* set counter back to zero */
 {
+#ifndef MSDOS
   mainCounter(INIT_COUNTER);
+#else
+  LOCK_VARIABLE(counter);
+  LOCK_FUNCTION(increment_counter);
+  install_int_ex(increment_counter, BPS_TO_TIMER(100));
+#endif
 }
 
 unsigned long Counter()        /* get milliseconds since last call of InitCounter() */
 {
-  return(mainCounter(READ_COUNTER));
+#ifndef MSDOS
+  return mainCounter(READ_COUNTER);
+#else
+  return (counter * 10);
+#endif
 }
 
 static void sleep_milliseconds(unsigned long milliseconds_delay)
 {
-  if (milliseconds_delay < 5)
+  boolean do_busy_waiting = (milliseconds_delay < 5 ? TRUE : FALSE);
+
+#ifdef MSDOS
+  /* donït use select() to perform waiting operations under DOS/Windows
+     environment; always use a busy loop for waiting instead */
+  do_busy_waiting = TRUE;
+#endif
+
+  if (do_busy_waiting)
   {
     /* we want to wait only a few ms -- if we assume that we have a
        kernel timer resolution of 10 ms, we would wait far to long;
@@ -158,9 +196,22 @@ unsigned int SimpleRND(unsigned int max)
   return (root % max);
 }
 
+#ifdef DEBUG
+static unsigned int last_RND_value = 0;
+
+unsigned int last_RND()
+{
+  return last_RND_value;
+}
+#endif
+
 unsigned int RND(unsigned int max)
 {
+#ifdef DEBUG
+  return (last_RND_value = random_linux_libc() % max);
+#else
   return (random_linux_libc() % max);
+#endif
 }
 
 unsigned int InitRND(long seed)
@@ -184,14 +235,52 @@ char *getLoginName()
 {
   struct passwd *pwd;
 
-  if (!(pwd = getpwuid(getuid())))
-    return "ANONYMOUS";
+  if ((pwd = getpwuid(getuid())) == NULL)
+    return ANONYMOUS_NAME;
   else
     return pwd->pw_name;
 }
 
+char *getRealName()
+{
+#ifndef MSDOS
+  struct passwd *pwd;
+
+  if ((pwd = getpwuid(getuid())) == NULL || strlen(pwd->pw_gecos) == 0)
+    return ANONYMOUS_NAME;
+  else
+  {
+    static char real_name[1024];
+    char *from_ptr = pwd->pw_gecos, *to_ptr = real_name;
+
+    if (strchr(pwd->pw_gecos, 'ß') == NULL)
+      return pwd->pw_gecos;
+
+    /* the user's real name contains a 'ß' character (german sharp s),
+       which has no equivalent in upper case letters (which our fonts use) */
+    while (*from_ptr != '\0' && (long)(to_ptr - real_name) < 1024 - 2)
+    {
+      if (*from_ptr != 'ß')
+       *to_ptr++ = *from_ptr++;
+      else
+      {
+       from_ptr++;
+       *to_ptr++ = 's';
+       *to_ptr++ = 's';
+      }
+    }
+    *to_ptr = '\0';
+
+    return real_name;
+  }
+#else
+  return ANONYMOUS_NAME;
+#endif
+}
+
 char *getHomeDir()
 {
+#ifndef MSDOS
   static char *home_dir = NULL;
 
   if (!home_dir)
@@ -208,6 +297,47 @@ char *getHomeDir()
   }
 
   return home_dir;
+#else
+  return ".";
+#endif
+}
+
+char *getPath2(char *path1, char *path2)
+{
+  char *complete_path = checked_malloc(strlen(path1) + 1 +
+                                      strlen(path2) + 1);
+
+  sprintf(complete_path, "%s/%s", path1, path2);
+  return complete_path;
+}
+
+char *getPath3(char *path1, char *path2, char *path3)
+{
+  char *complete_path = checked_malloc(strlen(path1) + 1 +
+                                      strlen(path2) + 1 +
+                                      strlen(path3) + 1);
+
+  sprintf(complete_path, "%s/%s/%s", path1, path2, path3);
+  return complete_path;
+}
+
+char *getStringCopy(char *s)
+{
+  char *s_copy = checked_malloc(strlen(s) + 1);
+
+  strcpy(s_copy, s);
+  return s_copy;
+}
+
+char *getStringToLower(char *s)
+{
+  char *s_copy = checked_malloc(strlen(s) + 1);
+  char *s_ptr = s_copy;
+
+  while (*s)
+    *s_ptr++ = tolower(*s++);
+
+  return s_copy;
 }
 
 void MarkTileDirty(int x, int y)
@@ -222,6 +352,25 @@ void MarkTileDirty(int x, int y)
   redraw_mask |= REDRAW_TILES;
 }
 
+void SetBorderElement()
+{
+  int x, y;
+
+  BorderElement = EL_LEERRAUM;
+
+  for(y=0; y<lev_fieldy && BorderElement == EL_LEERRAUM; y++)
+  {
+    for(x=0; x<lev_fieldx; x++)
+    {
+      if (!IS_MASSIVE(Feld[x][y]))
+       BorderElement = EL_BETON;
+
+      if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
+       x = lev_fieldx - 2;
+    }
+  }
+}
+
 void GetOptions(char *argv[])
 {
   char **options_left = &argv[1];
@@ -244,15 +393,15 @@ void GetOptions(char *argv[])
     char *option_arg = NULL;
     int option_len = strlen(option);
 
+    if (option_len >= MAX_OPTION_LEN)
+      Error(ERR_EXIT_HELP, "unrecognized option '%s'", option);
+
     strcpy(option_str, option);                        /* copy argument into buffer */
     option = option_str;
 
     if (strcmp(option, "--") == 0)             /* stop scanning arguments */
       break;
 
-    if (option_len >= MAX_OPTION_LEN)
-      Error(ERR_EXIT_HELP, "unrecognized option '%s'", option);
-
     if (strncmp(option, "--", 2) == 0)         /* treat '--' like '-' */
       option++;
 
@@ -291,8 +440,6 @@ void GetOptions(char *argv[])
       options.display_name = option_arg;
       if (option_arg == next_option)
        options_left++;
-
-      printf("--display == '%s'\n", options.display_name);
     }
     else if (strncmp(option, "-basepath", option_len) == 0)
     {
@@ -303,13 +450,9 @@ void GetOptions(char *argv[])
       if (option_arg == next_option)
        options_left++;
 
-      printf("--basepath == '%s'\n", options.base_directory);
-
       /* adjust path for level directory accordingly */
-      options.level_directory = checked_malloc(strlen(options.base_directory) +
-                                              strlen(LEVELS_DIRECTORY) + 2);
-      sprintf(options.level_directory, "%s/%s",
-             options.base_directory, LEVELS_DIRECTORY);
+      options.level_directory =
+       getPath2(options.base_directory, LEVELS_DIRECTORY);
     }
     else if (strncmp(option, "-levels", option_len) == 0)
     {
@@ -319,42 +462,32 @@ void GetOptions(char *argv[])
       options.level_directory = option_arg;
       if (option_arg == next_option)
        options_left++;
-
-      printf("--levels == '%s'\n", options.level_directory);
     }
     else if (strncmp(option, "-network", option_len) == 0)
     {
-      printf("--network\n");
-
       options.network = TRUE;
     }
     else if (strncmp(option, "-serveronly", option_len) == 0)
     {
-      printf("--serveronly\n");
-
       options.serveronly = TRUE;
     }
     else if (strncmp(option, "-verbose", option_len) == 0)
     {
-      printf("--verbose\n");
-
       options.verbose = TRUE;
     }
     else if (*option == '-')
+    {
       Error(ERR_EXIT_HELP, "unrecognized option '%s'", option_str);
+    }
     else if (options.server_host == NULL)
     {
       options.server_host = *options_left;
-
-      printf("server.name == '%s'\n", options.server_host);
     }
     else if (options.server_port == 0)
     {
       options.server_port = atoi(*options_left);
       if (options.server_port < 1024)
        Error(ERR_EXIT_HELP, "bad port number '%d'", options.server_port);
-
-      printf("port == %d\n", options.server_port);
     }
     else
       Error(ERR_EXIT_HELP, "too many arguments");
@@ -363,74 +496,62 @@ void GetOptions(char *argv[])
   }
 }
 
-void Error(int mode, char *format_str, ...)
+void Error(int mode, char *format, ...)
 {
-  FILE *output_stream = stderr;
   char *process_name = "";
+  FILE *error = stderr;
+
+  /* display warnings only when running in verbose mode */
+  if (mode & ERR_WARN && !options.verbose)
+    return;
+
+#ifdef MSDOS
+  if ((error = openErrorFile()) == NULL)
+  {
+    printf("Cannot write to error output file!\n");
+    CloseAllAndExit(1);
+  }
+#endif
 
-  if (mode & ERR_SOUNDSERVER)
+  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_str)
+  if (format)
   {
     va_list ap;
-    char *format_ptr;
-    char *s_value;
-    int i_value;
-    double d_value;
 
-    fprintf(output_stream, "%s%s: ", program_name, process_name);
+    fprintf(error, "%s%s: ", program_name, process_name);
 
     if (mode & ERR_WARN)
-      fprintf(output_stream, "warning: ");
-
-    va_start(ap, format_str);  /* ap points to first unnamed argument */
-  
-    for(format_ptr=format_str; *format_ptr; format_ptr++)
-    {
-      if (*format_ptr != '%')
-      {
-       fprintf(output_stream, "%c", *format_ptr);
-       continue;
-      }
-  
-      switch(*++format_ptr)
-      {
-       case 'd':
-         i_value = va_arg(ap, int);
-         fprintf(output_stream, "%d", i_value);
-         break;
-  
-       case 'f':
-         d_value = va_arg(ap, double);
-         fprintf(output_stream, "%f", d_value);
-         break;
-  
-       case 's':
-         s_value = va_arg(ap, char *);
-         fprintf(output_stream, "%s", s_value);
-         break;
-  
-       default:
-         fprintf(stderr, "\n%s: Error(): invalid format string: %s\n",
-                 program_name, format_str);
-         CloseAllAndExit(10);
-      }
-    }
+      fprintf(error, "warning: ");
 
+    va_start(ap, format);
+    vfprintf(error, format, ap);
     va_end(ap);
   
-    fprintf(output_stream, "\n");
+    fprintf(error, "\n");
   }
   
   if (mode & ERR_HELP)
-    fprintf(output_stream, "%s: Try option '--help' for more information.\n",
+    fprintf(error, "%s: Try option '--help' for more information.\n",
            program_name);
 
+  if (mode & ERR_EXIT)
+    fprintf(error, "%s%s: aborting\n", program_name, process_name);
+
+  if (error != stderr)
+    fclose(error);
+
   if (mode & ERR_EXIT)
   {
-    fprintf(output_stream, "%s%s: aborting\n", program_name, process_name);
-    CloseAllAndExit(1);
+    if (mode & ERR_FROM_SERVER)
+      exit(1);                         /* child process: normal exit */
+    else
+      CloseAllAndExit(1);              /* main process: clean up stuff */
   }
 }
 
@@ -516,21 +637,53 @@ void translate_keyname(KeySym *keysym, char **x11name, char **name, int mode)
     { XK_End,          "XK_End",               "end" },
     { XK_Page_Up,      "XK_Page_Up",           "page up" },
     { XK_Page_Down,    "XK_Page_Down",         "page down" },
-    { XK_space,                "XK_space",             "space" },
 
-    /* even more special keys */
-    { XK_adiaeresis,   "XK_adiaeresis",        "ä" },
-    { XK_odiaeresis,   "XK_odiaeresis",        "ö" },
-    { XK_udiaeresis,   "XK_udiaeresis",        "ü" },
+
+    /* ASCII 0x20 to 0x40 keys (except numbers) */
+    { XK_space,                "XK_space",             "space" },
+    { XK_exclam,       "XK_exclam",            "!" },
+    { XK_quotedbl,     "XK_quotedbl",          "\"" },
+    { XK_numbersign,   "XK_numbersign",        "#" },
+    { XK_dollar,       "XK_dollar",            "$" },
+    { XK_percent,      "XK_percent",           "%" },
+    { XK_ampersand,    "XK_ampersand",         "&" },
     { XK_apostrophe,   "XK_apostrophe",        "'" },
+    { XK_parenleft,    "XK_parenleft",         "(" },
+    { XK_parenright,   "XK_parenright",        ")" },
+    { XK_asterisk,     "XK_asterisk",          "*" },
     { XK_plus,         "XK_plus",              "+" },
-    { XK_minus,                "XK_minus",             "-" },
     { XK_comma,                "XK_comma",             "," },
+    { XK_minus,                "XK_minus",             "-" },
     { XK_period,       "XK_period",            "." },
-    { XK_numbersign,   "XK_numbersign",        "#" },
-    { XK_less,         "XK_less",              "less" },
-    { XK_greater,      "XK_greater",           "greater" },
+    { XK_slash,                "XK_slash",             "/" },
+    { XK_colon,                "XK_colon",             ":" },
+    { XK_semicolon,    "XK_semicolon",         ";" },
+    { XK_less,         "XK_less",              "<" },
+    { XK_equal,                "XK_equal",             "=" },
+    { XK_greater,      "XK_greater",           ">" },
+    { XK_question,     "XK_question",          "?" },
+    { XK_at,           "XK_at",                "@" },
+
+    /* more ASCII keys */
+    { XK_bracketleft,  "XK_bracketleft",       "[" },
+    { XK_backslash,    "XK_backslash",         "backslash" },
+    { XK_bracketright, "XK_bracketright",      "]" },
     { XK_asciicircum,  "XK_asciicircum",       "circumflex" },
+    { XK_underscore,   "XK_underscore",        "_" },
+    { XK_grave,                "XK_grave",             "grave" },
+    { XK_quoteleft,    "XK_quoteleft",         "quote left" },
+    { XK_braceleft,    "XK_braceleft",         "brace left" },
+    { XK_bar,          "XK_bar",               "bar" },
+    { XK_braceright,   "XK_braceright",        "brace right" },
+    { XK_asciitilde,   "XK_asciitilde",        "ascii tilde" },
+
+    /* special (non-ASCII) keys */
+    { XK_Adiaeresis,   "XK_Adiaeresis",        "Ä" },
+    { XK_Odiaeresis,   "XK_Odiaeresis",        "Ö" },
+    { XK_Udiaeresis,   "XK_Udiaeresis",        "Ü" },
+    { XK_adiaeresis,   "XK_adiaeresis",        "ä" },
+    { XK_odiaeresis,   "XK_odiaeresis",        "ö" },
+    { XK_udiaeresis,   "XK_udiaeresis",        "ü" },
     { XK_ssharp,       "XK_ssharp",            "sharp s" },
 
     /* end-of-array identifier */
@@ -722,6 +875,21 @@ KeySym getKeySymFromX11KeyName(char *x11name)
   return keysym;
 }
 
+char getCharFromKeySym(KeySym keysym)
+{
+  char *keyname = getKeyNameFromKeySym(keysym);
+  char letter = 0;
+
+  if (strlen(keyname) == 1)
+    letter = keyname[0];
+  else if (strcmp(keyname, "space") == 0)
+    letter = ' ';
+  else if (strcmp(keyname, "circumflex") == 0)
+    letter = '^';
+
+  return letter;
+}
+
 #define TRANSLATE_JOYSYMBOL_TO_JOYNAME 0
 #define TRANSLATE_JOYNAME_TO_JOYSYMBOL 1
 
@@ -786,3 +954,44 @@ int getJoySymbolFromJoyName(char *name)
   translate_joyname(&joysymbol, &name, TRANSLATE_JOYNAME_TO_JOYSYMBOL);
   return joysymbol;
 }
+
+int getJoystickNrFromDeviceName(char *device_name)
+{
+  char c;
+  int joystick_nr = 0;
+
+  if (device_name == NULL || device_name[0] == '\0')
+    return 0;
+
+  c = device_name[strlen(device_name) - 1];
+
+  if (c >= '0' && c <= '9')
+    joystick_nr = (int)(c - '0');
+
+  if (joystick_nr < 0 || joystick_nr >= MAX_PLAYERS)
+    joystick_nr = 0;
+
+  return joystick_nr;
+}
+
+/* ----------------------------------------------------------------- */
+/* the following is only for debugging purpose and normally not used */
+/* ----------------------------------------------------------------- */
+
+#define DEBUG_NUM_TIMESTAMPS   3
+
+void debug_print_timestamp(int counter_nr, char *message)
+{
+  static long counter[DEBUG_NUM_TIMESTAMPS][2];
+
+  if (counter_nr >= DEBUG_NUM_TIMESTAMPS)
+    Error(ERR_EXIT, "debugging: increase DEBUG_NUM_TIMESTAMPS in misc.c");
+
+  counter[counter_nr][0] = Counter();
+
+  if (message)
+    printf("%s %.2f seconds\n", message,
+          (float)(counter[counter_nr][0] - counter[counter_nr][1]) / 1000);
+
+  counter[counter_nr][1] = Counter();
+}