/* テスト */
#ifndef INCLUDED_H_BASIC_H
#define INCLUDED_H_BASIC_H

#define _countof(array) (sizeof(array)/sizeof(array[0]))

#if defined(WINDOWS) && !defined(_TCHAR_DEFINED)
#   include <tchar.h>
#endif

/*
 * Include autoconf autodetections, otherwise try to autodetect ourselves
 */
#ifdef HAVE_CONFIG_H

# include "autoconf.h"

#else

/*
 * Extract the "RISCOS" flag from the compiler
 */
# ifdef __riscos
#  ifndef RISCOS
#   define RISCOS
#  endif
# endif

/*
 * Extract the "WINDOWS" flag from the compiler
 */
# if defined(_Windows) || defined(__WINDOWS__) || \
     defined(__WIN32__) || defined(WIN32) || \
     defined(__WINNT__) || defined(__NT__)
#  ifndef WINDOWS
#   define WINDOWS
#  endif
# endif

/* Necessary? */
#ifdef NDS
# include <fat.h>
# include <unistd.h>
# include <reent.h>
# include <sys/iosupport.h>
# include <errno.h>
#endif

/*
 * Using C99, assume we have stdint and stdbool
 */
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#  define HAVE_STDINT_H
#  define HAVE_STDBOOL_H
# endif

/*
 * Everyone except RISC OS has fcntl.h and sys/stat.h
 */
#ifndef RISCOS
# define HAVE_FCNTL_H
# define HAVE_STAT
#endif

#endif /* HAVE_CONFIG_H */

/*
 * OPTION: set "SET_UID" if the machine is a "multi-user" wmachine.
 *
 * This option is used to verify the use of "uids" and "gids" for
 * various "Unix" calls, and of "pids" for getting a random seed,
 * and of the "umask()" call for various reasons, and to guess if
 * the "kill()" function is available, and for permission to use
 * functions to extract user names and expand "tildes" in filenames.
 * It is also used for "locking" and "unlocking" the score file.
 * Basically, SET_UID should *only* be set for "Unix" machines.
 */
#if !defined(MACH_O_CARBON) && !defined(WINDOWS) && \
    !defined(RISCOS) && !defined(GAMEBOY) && !defined(NDS)
# define SET_UID

/* Without autoconf, turn on some things */
# ifndef HAVE_CONFIG_H
#  define HAVE_DIRENT_H
#  define HAVE_SETEGID
#  if defined(linux)
#   define HAVE_SETRESGID
#  endif
# endif

#endif

/*
 * Every system seems to use its own symbol as a path separator.
 *
 * Default to the standard Unix slash, but attempt to change this
 * for various other systems.  Note that any system that uses the
 * "period" as a separator (i.e. RISCOS) will have to pretend that
 * it uses the slash, and do its own mapping of period <-> slash.
 *
 * It is most definitely wrong to have such things here.  Platform-specific
 * code should handle shifting Angband filenames to platform ones. XXX
 */
#undef PATH_SEP
#define PATH_SEP __T("/")

#ifdef WINDOWS
# undef PATH_SEP
# define PATH_SEP __T("\\")
#endif

/* 
 * Used to process mouse clicks.
 */
#define MOUSEY 255 

/*** Include the library header files ***/

/* Use various POSIX functions if available */
#undef _GNU_SOURCE
#define _GNU_SOURCE

/** ANSI C headers **/
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <assert.h>

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <wchar.h> // for _wstat64i32 ?

/** POSIX headers **/
#if defined(SET_UID) || defined(MACH_O_CARBON)
# include <pwd.h>
# include <sys/stat.h>
# include <unistd.h>
#endif

/*** Define the basic game types ***/

/*
 * errr is an error code
 *
 * A "byte" is an unsigned byte of memory.
 * s16b/u16b are exactly 2 bytes (where possible)
 * s32b/u32b are exactly 4 bytes (where possible)
 */

/* C++ defines its own bool type, so we hack around it */
#undef bool
#define bool bool_hack

typedef int errr;

/*
 * Use a real bool type where possible
 */
#ifdef HAVE_STDBOOL_H

  #include <stdbool.h>

  #define TRUE  true
  #define FALSE false

#else

  /* Use a char otherwise */
  typedef char bool;

  #undef TRUE
  #undef FALSE

  #define TRUE   1
  #define FALSE  0

#endif

/*
 * Use guaranteed-size ints where possible
 */
#ifdef HAVE_STDINT_H

  /* Use guaranteed-size types */
  #include <stdint.h>

  typedef uint8_t byte;

  typedef uint16_t u16b;
  typedef int16_t s16b;

  typedef uint32_t u32b;
  typedef int32_t s32b;

  typedef uint64_t u64b;
  typedef int64_t s64b;

#define MAX_UCHAR		UINT8_MAX
#define MAX_SHORT		INT16_MAX

#else /* HAVE_STDINT_H */

  /* Try hacks instead (not guaranteed to work) */
  typedef unsigned char byte;
  typedef signed short s16b;
  typedef unsigned short u16b;

#define MAX_UCHAR		UCHAR_MAX
#define MAX_SHORT		32767

  /* Detect >32-bit longs */
  #if (UINT_MAX == 0xFFFFFFFFUL) && (ULONG_MAX > 0xFFFFFFFFUL)
    typedef signed int s32b;
    typedef unsigned int u32b;
  #else
    typedef signed long s32b;
    typedef unsigned long u32b;
  #endif

#endif /* HAVE_STDINT_H */

/** Debugging macros ***/

#define DSTRINGIFY(x) #x
#define DSTRING(x)    DSTRINGIFY(x)
#define DHERE         __FILE__ ":" DSTRING(__LINE__) ": "

/*** Basic math macros ***/

#undef MIN
#undef MAX
#undef ABS
#undef SGN
#undef CMP

#define MIN(a,b)	(((a) > (b)) ? (b)  : (a))
#define MAX(a,b)	(((a) < (b)) ? (b)  : (a))
#define ABS(a)		(((a) < 0)   ? (-(a)) : (a))
#define SGN(a)		(((a) < 0)   ? (-1) : ((a) != 0))
#define CMP(a,b) (a < b ? -1 : (b < a ? 1: 0))

/*** Useful fairly generic macros ***/

/*
 * Given an array, determine how many elements are in it.
 * TODO This is redundant with _countof
 */
#define N_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))

/*
 * Return "s" (or not) depending on whether n is singular.
 */
#define PLURAL(n)		((n) == 1 ? __T("") : L"s")

/*** Some hackish character manipulation ***/

/*
 * Note that all "index" values must be "lowercase letters", while
 * all "digits" must be "digits".  Control characters can be made
 * from any legal characters.  XXX XXX XXX
 */
#define A2I(X)	((X) - 'a')
#define I2A(X)	((X) + 'a')
#define D2I(X)	((X) - '0')
#define I2D(X)	((X) + '0')
#define KTRL(X)	((X) & 0x1F)

#define UN_KTRL(X)	((X) + 64)
#define ESCAPE	27 /* '\033' */

/*
 * System-independent definitions for the arrow keys.
 */
#define ARROW_DOWN	138 /* '\x8A' */
#define ARROW_LEFT	139 /* '\x8B' */
#define ARROW_RIGHT	140 /* '\x8C' */
#define ARROW_UP	141 /* '\x8D' */

/* TODO This doesn't quite work yet */
#ifdef WINDOWS
#  define ARROW_N __T('↑')
#  define ARROW_E __T('→')
#  define ARROW_S __T('↓')
#  define ARROW_W __T('←')
#  define ARROW_NE __T('↗')
#  define ARROW_SE __T('↘')
#  define ARROW_SW __T('↙')
#  define ARROW_NW __T('↖')
#  define ARROW_WAIT __T('↻')

/* Analogous to isdigit() etc in ctypes */
#  define isarrow(c)	( \
	(((int)c >= ARROW_DOWN) && ((int)c <= ARROW_UP)) \
	|| (((int)c >= ARROW_W) && ((int)c <= ARROW_S)) \
	|| (((int)c >= ARROW_NW) && ((int)c <= ARROW_SW)) \
	|| ((int)c >= ARROW_WAIT) \
	)

#else

#  define isarrow(c)	( \
	(((int)c >= ARROW_DOWN) && ((int)c <= ARROW_UP)) \
	)

#endif /* WINDOWS */

/*** Adjust VC++ compiler warnings ***/

/*
 * 4127 is 'conditional expression is constant'.  while(1) and similar are used
 * all over the code and re-writing them would probably produce more clumsy 
 * looking code.
 */
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
# pragma warning( disable : 4127)
#endif /* _MSC_VER and >= 2008 Edition */

extern bool repaintneeded;

#endif /* INCLUDED_H_BASIC_H */
