+#define MAX_FILENAME_LEN 256 /* maximal filename length */
+#define MAX_LINE_LEN 1000 /* maximal input line length */
+#define CHUNK_ID_LEN 4 /* IFF style chunk id length */
+#define LEVEL_HEADER_SIZE 80 /* size of level file header */
+#define LEVEL_HEADER_UNUSED 15 /* unused level header bytes */
+#define TAPE_HEADER_SIZE 20 /* size of tape file header */
+#define TAPE_HEADER_UNUSED 7 /* unused tape header bytes */
+#define FILE_VERSION_1_0 10 /* 1.0 file version (old) */
+#define FILE_VERSION_1_2 12 /* 1.2 file version (still in use) */
+#define FILE_VERSION_1_4 14 /* 1.4 file version (new) */
+
+/* file identifier strings */
+#define LEVEL_COOKIE "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_1.4"
+#define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2"
+#define TAPE_COOKIE "ROCKSNDIAMONDS_TAPE_FILE_VERSION_1.2"
+#define SETUP_COOKIE "ROCKSNDIAMONDS_SETUP_FILE_VERSION_1.2"
+#define LEVELSETUP_COOKIE "ROCKSNDIAMONDS_LEVELSETUP_FILE_VERSION_1.2"
+#define LEVELINFO_COOKIE "ROCKSNDIAMONDS_LEVELINFO_FILE_VERSION_1.2"
+/* old file identifiers for backward compatibility */
+#define LEVEL_COOKIE_10 "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_1.0"
+#define LEVEL_COOKIE_12 "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_1.2"
+#define TAPE_COOKIE_10 "ROCKSNDIAMONDS_LEVELREC_FILE_VERSION_1.0"
+
+/* file names and filename extensions */
+#ifndef MSDOS
+#define USERDATA_DIRECTORY ".rocksndiamonds"
+#define LEVELSETUP_DIRECTORY "levelsetup"
+#define SETUP_FILENAME "setup.conf"
+#define LEVELSETUP_FILENAME "levelsetup.conf"
+#define LEVELINFO_FILENAME "levelinfo.conf"
+#define LEVELFILE_EXTENSION "level"
+#define TAPEFILE_EXTENSION "tape"
+#define SCOREFILE_EXTENSION "score"
+#else
+#define USERDATA_DIRECTORY "userdata"
+#define LEVELSETUP_DIRECTORY "lvlsetup"
+#define SETUP_FILENAME "setup.cnf"
+#define LEVELSETUP_FILENAME "lvlsetup.cnf"
+#define LEVELINFO_FILENAME "lvlinfo.cnf"
+#define LEVELFILE_EXTENSION "lvl"
+#define TAPEFILE_EXTENSION "tap"
+#define SCOREFILE_EXTENSION "sco"
+#define ERROR_FILENAME "error.out"
+#endif
+
+/* file permissions for newly written files */
+#define MODE_R_ALL (S_IRUSR | S_IRGRP | S_IROTH)
+#define MODE_W_ALL (S_IWUSR | S_IWGRP | S_IWOTH)
+#define MODE_X_ALL (S_IXUSR | S_IXGRP | S_IXOTH)
+#define USERDATA_DIR_MODE (MODE_R_ALL | MODE_X_ALL | S_IWUSR)
+#define LEVEL_PERMS (MODE_R_ALL | MODE_W_ALL)
+#define SCORE_PERMS LEVEL_PERMS
+#define TAPE_PERMS LEVEL_PERMS
+#define SETUP_PERMS LEVEL_PERMS
+
+/* sort priorities of level series (also used as level series classes) */
+#define LEVELCLASS_TUTORIAL_START 10
+#define LEVELCLASS_TUTORIAL_END 99
+#define LEVELCLASS_CLASSICS_START 100
+#define LEVELCLASS_CLASSICS_END 199
+#define LEVELCLASS_CONTRIBUTION_START 200
+#define LEVELCLASS_CONTRIBUTION_END 299
+#define LEVELCLASS_USER_START 300
+#define LEVELCLASS_USER_END 399
+#define LEVELCLASS_BD_START 400
+#define LEVELCLASS_BD_END 499
+#define LEVELCLASS_EM_START 500
+#define LEVELCLASS_EM_END 599
+#define LEVELCLASS_SP_START 600
+#define LEVELCLASS_SP_END 699
+#define LEVELCLASS_DX_START 700
+#define LEVELCLASS_DX_END 799
+
+#define LEVELCLASS_TUTORIAL LEVELCLASS_TUTORIAL_START
+#define LEVELCLASS_CLASSICS LEVELCLASS_CLASSICS_START
+#define LEVELCLASS_CONTRIBUTION LEVELCLASS_CONTRIBUTION_START
+#define LEVELCLASS_USER LEVELCLASS_USER_START
+#define LEVELCLASS_BD LEVELCLASS_BD_START
+#define LEVELCLASS_EM LEVELCLASS_EM_START
+#define LEVELCLASS_SP LEVELCLASS_SP_START
+#define LEVELCLASS_DX LEVELCLASS_DX_START
+
+#define LEVELCLASS_UNDEFINED 999
+
+#define NUM_LEVELCLASS_DESC 8
+char *levelclass_desc[NUM_LEVELCLASS_DESC] =
+{
+ "Tutorial Levels",
+ "Classic Originals",
+ "Contributions",
+ "Private Levels",
+ "Boulderdash",
+ "Emerald Mine",
+ "Supaplex",
+ "DX Boulderdash"
+};
+
+#define IS_LEVELCLASS_TUTORIAL(p) \
+ ((p)->sort_priority >= LEVELCLASS_TUTORIAL_START && \
+ (p)->sort_priority <= LEVELCLASS_TUTORIAL_END)
+#define IS_LEVELCLASS_CLASSICS(p) \
+ ((p)->sort_priority >= LEVELCLASS_CLASSICS_START && \
+ (p)->sort_priority <= LEVELCLASS_CLASSICS_END)
+#define IS_LEVELCLASS_CONTRIBUTION(p) \
+ ((p)->sort_priority >= LEVELCLASS_CONTRIBUTION_START && \
+ (p)->sort_priority <= LEVELCLASS_CONTRIBUTION_END)
+#define IS_LEVELCLASS_USER(p) \
+ ((p)->sort_priority >= LEVELCLASS_USER_START && \
+ (p)->sort_priority <= LEVELCLASS_USER_END)
+#define IS_LEVELCLASS_BD(p) \
+ ((p)->sort_priority >= LEVELCLASS_BD_START && \
+ (p)->sort_priority <= LEVELCLASS_BD_END)
+#define IS_LEVELCLASS_EM(p) \
+ ((p)->sort_priority >= LEVELCLASS_EM_START && \
+ (p)->sort_priority <= LEVELCLASS_EM_END)
+#define IS_LEVELCLASS_SP(p) \
+ ((p)->sort_priority >= LEVELCLASS_SP_START && \
+ (p)->sort_priority <= LEVELCLASS_SP_END)
+#define IS_LEVELCLASS_DX(p) \
+ ((p)->sort_priority >= LEVELCLASS_DX_START && \
+ (p)->sort_priority <= LEVELCLASS_DX_END)
+
+#define LEVELCLASS(n) (IS_LEVELCLASS_TUTORIAL(n) ? LEVELCLASS_TUTORIAL : \
+ IS_LEVELCLASS_CLASSICS(n) ? LEVELCLASS_CLASSICS : \
+ IS_LEVELCLASS_CONTRIBUTION(n) ? LEVELCLASS_CONTRIBUTION : \
+ IS_LEVELCLASS_USER(n) ? LEVELCLASS_USER : \
+ IS_LEVELCLASS_BD(n) ? LEVELCLASS_BD : \
+ IS_LEVELCLASS_EM(n) ? LEVELCLASS_EM : \
+ IS_LEVELCLASS_SP(n) ? LEVELCLASS_SP : \
+ IS_LEVELCLASS_DX(n) ? LEVELCLASS_DX : \
+ LEVELCLASS_UNDEFINED)
+
+#define LEVELCOLOR(n) (IS_LEVELCLASS_TUTORIAL(n) ? FC_BLUE : \
+ IS_LEVELCLASS_CLASSICS(n) ? FC_RED : \
+ IS_LEVELCLASS_BD(n) ? FC_GREEN : \
+ IS_LEVELCLASS_EM(n) ? FC_YELLOW : \
+ IS_LEVELCLASS_SP(n) ? FC_GREEN : \
+ IS_LEVELCLASS_DX(n) ? FC_YELLOW : \
+ IS_LEVELCLASS_CONTRIBUTION(n) ? FC_GREEN : \
+ IS_LEVELCLASS_USER(n) ? FC_RED : \
+ FC_BLUE)
+
+#define LEVELSORTING(n) (IS_LEVELCLASS_TUTORIAL(n) ? 0 : \
+ IS_LEVELCLASS_CLASSICS(n) ? 1 : \
+ IS_LEVELCLASS_BD(n) ? 2 : \
+ IS_LEVELCLASS_EM(n) ? 3 : \
+ IS_LEVELCLASS_SP(n) ? 4 : \
+ IS_LEVELCLASS_DX(n) ? 5 : \
+ IS_LEVELCLASS_CONTRIBUTION(n) ? 6 : \
+ IS_LEVELCLASS_USER(n) ? 7 : \
+ 9)
+
+char *getLevelClassDescription(struct LevelDirInfo *ldi)
+{
+ int position = ldi->sort_priority / 100;
+
+ if (position >= 0 && position < NUM_LEVELCLASS_DESC)
+ return levelclass_desc[position];
+ else
+ return "Unknown Level Class";
+}
+
+static void SaveUserLevelInfo(); /* for 'InitUserLevelDir()' */
+static char *getSetupLine(char *, int); /* for 'SaveUserLevelInfo()' */
+
+char *getUserDataDir()