}
#endif
+static void vfprintf_nonewline(FILE *stream, char *format, va_list ap)
+{
+#if defined(PLATFORM_ANDROID)
+ // (prefix text of logging output is currently skipped on Android)
+ //__android_log_vprint(android_log_prio, program.program_title, format, ap);
+#else
+ va_list ap2;
+ va_copy(ap2, ap);
+
+ vfprintf(stream, format, ap);
+ vfprintf(stderr, format, ap2);
+
+ va_end(ap2);
+#endif
+}
+
static void vfprintf_newline(FILE *stream, char *format, va_list ap)
{
#if defined(PLATFORM_ANDROID)
#else
char *newline = STRING_NEWLINE;
+ va_list ap2;
+ va_copy(ap2, ap);
+
vfprintf(stream, format, ap);
fprintf(stream, "%s", newline);
+
+ vfprintf(stderr, format, ap2);
+ fprintf(stderr, "%s", newline);
+
+ va_end(ap2);
#endif
}
+static void fprintf_nonewline(FILE *stream, char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vfprintf_nonewline(stream, format, ap);
+ va_end(ap);
+}
+
static void fprintf_newline(FILE *stream, char *format, ...)
{
va_list ap;
int i;
for (i = 0; i < line_length; i++)
- fprintf(stream, "%s", line_chars);
+ fprintf_nonewline(stream, "%s", line_chars);
fprintf_newline(stream, "");
}
/* system info functions */
/* ------------------------------------------------------------------------- */
-#if !defined(PLATFORM_MSDOS)
+#if !defined(PLATFORM_MSDOS) && !defined(PLATFORM_ANDROID)
static char *get_corrected_real_name(char *real_name)
{
char *real_name_new = checked_malloc(MAX_USERNAME_LEN + 1);
return getStringCat3WithSeparator(path1, path2, path3, STRING_PATH_SEPARATOR);
}
-char *getStringCopy(char *s)
+char *getStringCopy(const char *s)
{
char *s_copy;
return s_copy;
}
-char *getStringCopyN(char *s, int n)
+char *getStringCopyN(const char *s, int n)
{
char *s_copy;
int s_len = MAX(0, n);
return s_copy;
}
-char *getStringToLower(char *s)
+char *getStringCopyNStatic(const char *s, int n)
+{
+ static char *s_copy = NULL;
+
+ checked_free(s_copy);
+
+ s_copy = getStringCopyN(s, n);
+
+ return s_copy;
+}
+
+char *getStringToLower(const char *s)
{
char *s_copy = checked_malloc(strlen(s) + 1);
char *s_ptr = s_copy;
/* error handling functions */
/* ------------------------------------------------------------------------- */
+#define MAX_INTERNAL_ERROR_SIZE 1024
+
/* used by SetError() and GetError() to store internal error messages */
-static char internal_error[1024]; /* this is bad */
+static char internal_error[MAX_INTERNAL_ERROR_SIZE];
void SetError(char *format, ...)
{
va_list ap;
va_start(ap, format);
- vsprintf(internal_error, format, ap);
+ vsnprintf(internal_error, MAX_INTERNAL_ERROR_SIZE, format, ap);
va_end(ap);
}
{
va_list ap;
- fprintf(program.error_file, "%s%s: ", program.command_basename,
- process_name);
+ fprintf_nonewline(program.error_file, "%s%s: ", program.command_basename,
+ process_name);
if (mode & ERR_WARN)
- fprintf(program.error_file, "warning: ");
+ fprintf_nonewline(program.error_file, "warning: ");
va_start(ap, format);
vfprintf_newline(program.error_file, format, ap);
of the (not yet written) chunk, write the correct chunk size and finally
write the chunk itself */
+#if 1
+
+int getFile8BitInteger(File *file)
+{
+ return getByteFromFile(file);
+}
+
+#else
+
int getFile8BitInteger(FILE *file)
{
return fgetc(file);
}
+#endif
+
int putFile8BitInteger(FILE *file, int value)
{
if (file != NULL)
return 1;
}
+#if 1
+
+int getFile16BitInteger(File *file, int byte_order)
+{
+ if (byte_order == BYTE_ORDER_BIG_ENDIAN)
+ return ((getByteFromFile(file) << 8) |
+ (getByteFromFile(file) << 0));
+ else /* BYTE_ORDER_LITTLE_ENDIAN */
+ return ((getByteFromFile(file) << 0) |
+ (getByteFromFile(file) << 8));
+}
+
+#else
+
int getFile16BitInteger(FILE *file, int byte_order)
{
if (byte_order == BYTE_ORDER_BIG_ENDIAN)
(fgetc(file) << 8));
}
+#endif
+
int putFile16BitInteger(FILE *file, int value, int byte_order)
{
if (file != NULL)
return 2;
}
+#if 1
+
+int getFile32BitInteger(File *file, int byte_order)
+{
+ if (byte_order == BYTE_ORDER_BIG_ENDIAN)
+ return ((getByteFromFile(file) << 24) |
+ (getByteFromFile(file) << 16) |
+ (getByteFromFile(file) << 8) |
+ (getByteFromFile(file) << 0));
+ else /* BYTE_ORDER_LITTLE_ENDIAN */
+ return ((getByteFromFile(file) << 0) |
+ (getByteFromFile(file) << 8) |
+ (getByteFromFile(file) << 16) |
+ (getByteFromFile(file) << 24));
+}
+
+#else
+
int getFile32BitInteger(FILE *file, int byte_order)
{
if (byte_order == BYTE_ORDER_BIG_ENDIAN)
(fgetc(file) << 24));
}
+#endif
+
int putFile32BitInteger(FILE *file, int value, int byte_order)
{
if (file != NULL)
return 4;
}
+#if 1
+
+boolean getFileChunk(File *file, char *chunk_name, int *chunk_size,
+ int byte_order)
+{
+ const int chunk_name_length = 4;
+
+ /* read chunk name */
+ if (getStringFromFile(file, chunk_name, chunk_name_length + 1) == NULL)
+ return FALSE;
+
+ if (chunk_size != NULL)
+ {
+ /* read chunk size */
+ *chunk_size = getFile32BitInteger(file, byte_order);
+ }
+
+ return (checkEndOfFile(file) ? FALSE : TRUE);
+}
+
+#else
+
boolean getFileChunk(FILE *file, char *chunk_name, int *chunk_size,
int byte_order)
{
return (feof(file) || ferror(file) ? FALSE : TRUE);
}
+#endif
+
int putFileChunk(FILE *file, char *chunk_name, int chunk_size,
int byte_order)
{
return num_bytes;
}
+#if 1
+
+int getFileVersion(File *file)
+{
+ int version_major = getByteFromFile(file);
+ int version_minor = getByteFromFile(file);
+ int version_patch = getByteFromFile(file);
+ int version_build = getByteFromFile(file);
+
+ return VERSION_IDENT(version_major, version_minor, version_patch,
+ version_build);
+}
+
+#else
+
int getFileVersion(FILE *file)
{
int version_major = fgetc(file);
version_build);
}
+#endif
+
int putFileVersion(FILE *file, int version)
{
if (file != NULL)
return 4;
}
+#if 1
+
+void ReadBytesFromFile(File *file, byte *buffer, unsigned int bytes)
+{
+ int i;
+
+ for (i = 0; i < bytes && !checkEndOfFile(file); i++)
+ buffer[i] = getByteFromFile(file);
+}
+
+#else
+
void ReadBytesFromFile(FILE *file, byte *buffer, unsigned int bytes)
{
int i;
buffer[i] = fgetc(file);
}
+#endif
+
void WriteBytesToFile(FILE *file, byte *buffer, unsigned int bytes)
{
int i;
fputc(buffer[i], file);
}
+#if 1
+
+void ReadUnusedBytesFromFile(File *file, unsigned int bytes)
+{
+ while (bytes-- && !checkEndOfFile(file))
+ getByteFromFile(file);
+}
+
+#else
+
void ReadUnusedBytesFromFile(FILE *file, unsigned int bytes)
{
while (bytes-- && !feof(file))
fgetc(file);
}
+#endif
+
void WriteUnusedBytesToFile(FILE *file, unsigned int bytes)
{
while (bytes--)
{ KSYM_End, "XK_End", "end" },
{ KSYM_Page_Up, "XK_Page_Up", "page up" },
{ KSYM_Page_Down, "XK_Page_Down", "page down" },
- { KSYM_Menu, "XK_Menu", "menu" }, /* Win-Menu */
+
+#if defined(TARGET_SDL2)
+ { KSYM_Menu, "XK_Menu", "menu" }, /* menu key */
+ { KSYM_Back, "XK_Back", "back" }, /* back key */
+#endif
/* ASCII 0x20 to 0x40 keys (except numbers) */
{ KSYM_space, "XK_space", "space" },
{ KSYM_braceright, "XK_braceright", "brace right" },
{ KSYM_asciitilde, "XK_asciitilde", "~" },
-#if !defined(TARGET_SDL2)
- /* special (non-ASCII) keys */
+ /* special (non-ASCII) keys (ISO-Latin-1) */
{ KSYM_degree, "XK_degree", "°" },
{ KSYM_Adiaeresis, "XK_Adiaeresis", "Ä" },
{ KSYM_Odiaeresis, "XK_Odiaeresis", "Ö" },
{ KSYM_odiaeresis, "XK_odiaeresis", "ö" },
{ KSYM_udiaeresis, "XK_udiaeresis", "ü" },
{ KSYM_ssharp, "XK_ssharp", "sharp s" },
+
+#if defined(TARGET_SDL2)
+ /* special (non-ASCII) keys (UTF-8, for reverse mapping only) */
+ { KSYM_degree, "XK_degree", "\xc2\xb0" },
+ { KSYM_Adiaeresis, "XK_Adiaeresis", "\xc3\x84" },
+ { KSYM_Odiaeresis, "XK_Odiaeresis", "\xc3\x96" },
+ { KSYM_Udiaeresis, "XK_Udiaeresis", "\xc3\x9c" },
+ { KSYM_adiaeresis, "XK_adiaeresis", "\xc3\xa4" },
+ { KSYM_odiaeresis, "XK_odiaeresis", "\xc3\xb6" },
+ { KSYM_udiaeresis, "XK_udiaeresis", "\xc3\xbc" },
+ { KSYM_ssharp, "XK_ssharp", "\xc3\x9f" },
+
+ /* other keys (for reverse mapping only) */
+ { KSYM_space, "XK_space", " " },
+#endif
+
+#if defined(TARGET_SDL2)
+ /* keypad keys are not in numerical order in SDL2 */
+ { KSYM_KP_0, "XK_KP_0", "keypad 0" },
+ { KSYM_KP_1, "XK_KP_1", "keypad 1" },
+ { KSYM_KP_2, "XK_KP_2", "keypad 2" },
+ { KSYM_KP_3, "XK_KP_3", "keypad 3" },
+ { KSYM_KP_4, "XK_KP_4", "keypad 4" },
+ { KSYM_KP_5, "XK_KP_5", "keypad 5" },
+ { KSYM_KP_6, "XK_KP_6", "keypad 6" },
+ { KSYM_KP_7, "XK_KP_7", "keypad 7" },
+ { KSYM_KP_8, "XK_KP_8", "keypad 8" },
+ { KSYM_KP_9, "XK_KP_9", "keypad 9" },
#endif
/* end-of-array identifier */
sprintf(name_buffer, "%c", 'a' + (char)(key - KSYM_a));
else if (key >= KSYM_0 && key <= KSYM_9)
sprintf(name_buffer, "%c", '0' + (char)(key - KSYM_0));
+#if !defined(TARGET_SDL2)
else if (key >= KSYM_KP_0 && key <= KSYM_KP_9)
sprintf(name_buffer, "keypad %c", '0' + (char)(key - KSYM_KP_0));
+#endif
else if (key >= KSYM_FKEY_FIRST && key <= KSYM_FKEY_LAST)
sprintf(name_buffer, "F%d", (int)(key - KSYM_FKEY_FIRST + 1));
else if (key == KSYM_UNDEFINED)
sprintf(name_buffer, "XK_%c", 'a' + (char)(key - KSYM_a));
else if (key >= KSYM_0 && key <= KSYM_9)
sprintf(name_buffer, "XK_%c", '0' + (char)(key - KSYM_0));
+#if !defined(TARGET_SDL2)
else if (key >= KSYM_KP_0 && key <= KSYM_KP_9)
sprintf(name_buffer, "XK_KP_%c", '0' + (char)(key - KSYM_KP_0));
+#endif
else if (key >= KSYM_FKEY_FIRST && key <= KSYM_FKEY_LAST)
sprintf(name_buffer, "XK_F%d", (int)(key - KSYM_FKEY_FIRST + 1));
else if (key == KSYM_UNDEFINED)
else if (mode == TRANSLATE_KEYNAME_TO_KEYSYM)
{
Key key = KSYM_UNDEFINED;
+ char *name_ptr = *name;
- i = 0;
- do
+ if (strlen(*name) == 1)
{
- if (strEqual(translate_key[i].name, *name))
+ char c = name_ptr[0];
+
+ if (c >= 'A' && c <= 'Z')
+ key = KSYM_A + (Key)(c - 'A');
+ else if (c >= 'a' && c <= 'z')
+ key = KSYM_a + (Key)(c - 'a');
+ else if (c >= '0' && c <= '9')
+ key = KSYM_0 + (Key)(c - '0');
+ }
+
+ if (key == KSYM_UNDEFINED)
+ {
+ i = 0;
+
+ do
{
- key = translate_key[i].key;
- break;
+ if (strEqual(translate_key[i].name, *name))
+ {
+ key = translate_key[i].key;
+ break;
+ }
}
+ while (translate_key[++i].x11name);
}
- while (translate_key[++i].x11name);
if (key == KSYM_UNDEFINED)
Error(ERR_WARN, "getKeyFromKeyName(): not completely implemented");
else if (c >= '0' && c <= '9')
key = KSYM_0 + (Key)(c - '0');
}
+#if !defined(TARGET_SDL2)
else if (strPrefix(name_ptr, "XK_KP_") && strlen(name_ptr) == 7)
{
char c = name_ptr[6];
if (c >= '0' && c <= '9')
key = KSYM_KP_0 + (Key)(c - '0');
}
+#endif
else if (strPrefix(name_ptr, "XK_F") && strlen(name_ptr) <= 6)
{
char c1 = name_ptr[4];
if (file == NULL)
return -1;
- int result;
+ int result = 0;
#if defined(PLATFORM_ANDROID)
if (file->asset_file)
return feof(file->file);
}
+size_t readFile(File *file, void *buffer, size_t item_size, size_t num_items)
+{
+#if defined(PLATFORM_ANDROID)
+ if (file->file_is_asset)
+ {
+ if (file->end_of_file)
+ return 0;
+
+ size_t num_items_read =
+ SDL_RWread(file->asset_file, buffer, item_size, num_items);
+
+ if (num_items_read < num_items)
+ file->end_of_file = TRUE;
+
+ return num_items_read;
+ }
+#endif
+
+ return fread(buffer, item_size, num_items, file->file);
+}
+
+int seekFile(File *file, long offset, int whence)
+{
+#if defined(PLATFORM_ANDROID)
+ if (file->file_is_asset)
+ {
+ int sdl_whence = (whence == SEEK_SET ? RW_SEEK_SET :
+ whence == SEEK_CUR ? RW_SEEK_CUR :
+ whence == SEEK_END ? RW_SEEK_END : 0);
+
+ return (SDL_RWseek(file->asset_file, offset, sdl_whence) == -1 ? -1 : 0);
+ }
+#endif
+
+ return fseek(file->file, offset, whence);
+}
+
+int getByteFromFile(File *file)
+{
+#if defined(PLATFORM_ANDROID)
+ if (file->file_is_asset)
+ {
+ if (file->end_of_file)
+ return EOF;
+
+ byte c;
+ size_t num_bytes_read = SDL_RWread(file->asset_file, &c, 1, 1);
+
+ if (num_bytes_read < 1)
+ file->end_of_file = TRUE;
+
+ return (file->end_of_file ? EOF : (int)c);
+ }
+#endif
+
+ return fgetc(file->file);
+}
+
char *getStringFromFile(File *file, char *line, int size)
{
#if defined(PLATFORM_ANDROID)
if (dir == NULL)
return -1;
- int result;
+ int result = 0;
#if defined(PLATFORM_ANDROID)
if (dir->asset_toc_file)
dir->dir_entry = checked_calloc(sizeof(DirectoryEntry));
dir->dir_entry->is_directory = FALSE;
- if (line[strlen(line) - 1] = '/')
+ if (line[strlen(line) - 1] == '/')
{
dir->dir_entry->is_directory = TRUE;
/* functions for checking files and filenames */
/* ------------------------------------------------------------------------- */
+boolean directoryExists(char *dir_name)
+{
+ if (dir_name == NULL)
+ return FALSE;
+
+ boolean success = (access(dir_name, F_OK) == 0);
+
+#if defined(PLATFORM_ANDROID)
+ if (!success)
+ {
+ // this might be an asset directory; check by trying to open toc file
+ char *asset_toc_filename = getPath2(dir_name, ASSET_TOC_BASENAME);
+ SDL_RWops *file = SDL_RWFromFile(asset_toc_filename, MODE_READ);
+
+ checked_free(asset_toc_filename);
+
+ success = (file != NULL);
+
+ if (success)
+ SDL_RWclose(file);
+ }
+#endif
+
+ return success;
+}
+
boolean fileExists(char *filename)
{
if (filename == NULL)
return FALSE;
+ boolean success = (access(filename, F_OK) == 0);
+
#if defined(PLATFORM_ANDROID)
- // workaround: check if file exists by opening and closing it
- SDL_RWops *file = SDL_RWFromFile(filename, MODE_READ);
- boolean success = (file != NULL);
+ if (!success)
+ {
+ // this might be an asset file; check by trying to open it
+ SDL_RWops *file = SDL_RWFromFile(filename, MODE_READ);
- if (success)
- SDL_RWclose(file);
+ success = (file != NULL);
- return success;
-#else
- return (access(filename, F_OK) == 0);
+ if (success)
+ SDL_RWclose(file);
+ }
#endif
+
+ return success;
}
boolean fileHasPrefix(char *basename, char *prefix)
return FALSE;
}
+#if defined(TARGET_SDL)
+static boolean FileCouldBeArtwork(char *basename)
+{
+ return (!strEqual(basename, ".") &&
+ !strEqual(basename, "..") &&
+ !fileHasSuffix(basename, "txt") &&
+ !fileHasSuffix(basename, "conf"));
+}
+#endif
+
boolean FileIsGraphic(char *filename)
{
-#if 1
- return TRUE;
-#else
char *basename = getBaseNamePtr(filename);
+#if defined(TARGET_SDL)
+ return FileCouldBeArtwork(basename);
+#else
return fileHasSuffix(basename, "pcx");
#endif
}
boolean FileIsSound(char *filename)
{
-#if 1
- return TRUE;
-#else
char *basename = getBaseNamePtr(filename);
+#if defined(TARGET_SDL)
+ return FileCouldBeArtwork(basename);
+#else
return fileHasSuffix(basename, "wav");
#endif
}
boolean FileIsMusic(char *filename)
{
-#if 1
- return TRUE;
-#else
char *basename = getBaseNamePtr(filename);
+#if defined(TARGET_SDL)
+ return FileCouldBeArtwork(basename);
+#else
if (FileIsSound(basename))
return TRUE;
+#if 0
#if defined(TARGET_SDL)
if ((fileHasPrefix(basename, "mod") && !fileHasSuffix(basename, "txt")) ||
fileHasSuffix(basename, "mod") ||
fileHasSuffix(basename, "mp3") ||
fileHasSuffix(basename, "ogg"))
return TRUE;
+#endif
#endif
return FALSE;
#if DEBUG
-#define DEBUG_PRINT_INIT_TIMESTAMPS TRUE
+#define DEBUG_PRINT_INIT_TIMESTAMPS FALSE
#define DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH 10
#define DEBUG_NUM_TIMESTAMPS 10
}
}
+#endif /* DEBUG */
+
void print_timestamp_ext(char *message, char *mode)
{
#if DEBUG_PRINT_INIT_TIMESTAMPS
{
print_timestamp_ext(message, "DONE");
}
-
-#endif /* DEBUG */