#   ifndef  _EXP_MISC_H_
#   define  _EXP_MISC_H_ 50

/*
   0702941432 <- last update (yymmddhh'')
     _____________________________________________________________
    /                                                             \ 
    | Module:       expmisc.cpp - explib's miscellaneous functions
    \_____________________________________________________________/

    Description:    this contains classes & functions not large enough
                    to create own .h and .cpp files for it.

    Refers to:      explib.h
    Used by:        everywhere

    Contents:
        HexDump()   - creates a hexdump of a memory block
        filesize    - determines size of a file in bytes

    Local Terminology:

        Abbrev. Meaning
        ------- ------------------------
        ...     ...


    Developers: ID: Name:
    =========== --- -----
                JTH Juergen Thumm
  _____________________________________/VERSION HISTORY\____________________
 /Date_ Version Who What____________________________________________________\ 
 yymmdd ------- --- ---------------------------------------------------------
 930823 0.500   JTH created
 940201             renamed file to 'misc.h'
 940207             FineTimer
 940213             intf moved to this file; StringLib (not yet tested!!),
                    HexDump
 940328             INTF_SCALEB

 940911             random() macro; under WIN16 expected to be already defined
 941025             StringLib: internal buffer now STATIC, so there is no longer
                    any need to create static instances in subfunctions.
                    Just use any string created by StringLib::printf immediately,
                    the next printf call will write it over.
                    Furthermore, this buffer is now checked against overflow.
                    If overflow happens, a SysErr is issued.
 941203             FastTrig.
 941209             FineTimer moved into this file, under WIN16 it now
                    uses timeGetTime() instead of port fondeling.
 941223             KeyBoard: instance counter.
 950311             FineTimer: run-time switch if to use hardware timer.
 950417             added saltrand()
 951112             BUG FIX: FastTrig: idegmax/mask now also STATIC.
*/

#   include "expdef.h"
#   include "explib.h"

#   include <limits.h>

//   _____________________________________________________________
//  /                                                             \ 
//  | extended data types
//  \_____________________________________________________________/

//|| DataTypes 

//  INTFLOAT: this is a float type with approx. 5 digits before
//            and 4 digits after decimal point,
//            but which uses INTEGER math functions + - * / etc.

typedef long intf;

// intf <-> int
const  sysint INTF_SCALEB=13;
inline intf convfi(int x)   {   return x << INTF_SCALEB;    }   // *8192
inline int  convif(intf i)  {   return i >> INTF_SCALEB;    }   // /8192

// intf <-> double
inline intf convfd(double f)    {   return f * 8192.0;  }
inline double convdf(intf i)    {   return i / 8192.0;  }

/*   _____________________________________________________________  
    /                                                             \ 
    | String Functions Library
    \_____________________________________________________________/ 
*/

class StringLib {

#define STRLIB_STRMAX   200     // max. size for temporar string buffers

    static  uchar buf[STRLIB_STRMAX+2]; // working buffer for functions

    void    securebuf()     // prepare buffer before writing into it

        {   buf[STRLIB_STRMAX]  = 0xEE; }

    rcode   checkbuf()      // check for buffer overflow after writing

        {
            if(buf[STRLIB_STRMAX] != 0xEE)

                {   SysErr(2510941757); return INTERNAL;    }

            return  OK;
        }

 public:

    // enter a source text centered in a destination buffer
    //  dest : should be blank, will not be null-terminated by this func
    //  src  : if length > destsize, will be truncated
    // destsize : without null terminator
    // result: ptr to 'dest'
    char* center(char* dest, char* src, size_t destsize);

    char* tolower(char* str);   // make string lowercase
    char* toupper(char* str);   // make string uppercase
    // result each: ptr to 'str'

    // compare two strings case-insensitive
    // result like strcmp()
    int  stricmp(char* s1, char* s2);

    // compare two strings case-insensitive upto a maxlength:
    // result like strcmp()
    int  strnicmp(char* s1, char* s2, size_t cnt);

    // concatenate to a string a 'sprintf'-formatted string
    // result: ptr to TempBuf
    char* catf(char *str, char *format, ...);

    // do an 'sprintf' to internal buffer and return pointer to the buffer
    // result: ptr to TempBuf. Use result immediately! Next call
    //         to printf will write again over the buffer.
    char* printf(char *format, ...);

    };

long    filesize(const char *filename);
// farfread is needed under WIN16 to read data >64k from a file
long    farfread(void HUGE *dest, long bsize, long nblocks, FILE *f);
uchar  *loadfile(const char *filename, ulong* retsize=0, char* mode="rb");
// \ retsize=returned size (optional). uses farcalloc under WIN16

void HexDump(char *strptr, size_t strsize, FILE *dest);

int  altrand();             // alternative randomizer, like rand()
void saltrand(int seed);    // set seed of altrand

#ifdef  AMIGA
#   define  random(x) ((ulong)rand()*(x)/RAND_MAX)
#endif

//  ------------ keyboard class ------------

#define KEY_LBUTTON          0x01
#define KEY_RBUTTON          0x02
#define KEY_CANCEL           0x03
#define KEY_MBUTTON          0x04
#define KEY_BACK             0x08
#define KEY_TAB              0x09
#define KEY_CLEAR            0x0C
#define KEY_RETURN           0x0D
#define KEY_SHIFT            0x10
#define KEY_CONTROL          0x11
#define KEY_MENU             0x12
#define KEY_PAUSE            0x13
#define KEY_CAPITAL          0x14
#define KEY_ESCAPE           0x1B
#define KEY_SPACE            0x20
#define KEY_PRIOR            0x21
#define KEY_NEXT             0x22
#define KEY_END              0x23
#define KEY_HOME             0x24
#define KEY_LEFT             0x25
#define KEY_UP               0x26
#define KEY_RIGHT            0x27
#define KEY_DOWN             0x28
#define KEY_SELECT           0x29
#define KEY_PRINT            0x2A
#define KEY_EXECUTE          0x2B
#define KEY_SNAPSHOT         0x2C
#define KEY_INSERT           0x2D
#define KEY_DELETE           0x2E
#define KEY_HELP             0x2F
#define KEY_NUMPAD0          0x60
#define KEY_NUMPAD1          0x61
#define KEY_NUMPAD2          0x62
#define KEY_NUMPAD3          0x63
#define KEY_NUMPAD4          0x64
#define KEY_NUMPAD5          0x65
#define KEY_NUMPAD6          0x66
#define KEY_NUMPAD7          0x67
#define KEY_NUMPAD8          0x68
#define KEY_NUMPAD9          0x69
#define KEY_MULTIPLY         0x6A
#define KEY_ADD              0x6B
#define KEY_SEPARATOR        0x6C
#define KEY_SUBTRACT         0x6D
#define KEY_DECIMAL          0x6E
#define KEY_DIVIDE           0x6F
#define KEY_F1               0x70
#define KEY_F2               0x71
#define KEY_F3               0x72
#define KEY_F4               0x73
#define KEY_F5               0x74
#define KEY_F6               0x75
#define KEY_F7               0x76
#define KEY_F8               0x77
#define KEY_F9               0x78
#define KEY_F10              0x79
#define KEY_F11              0x7A
#define KEY_F12              0x7B
#define KEY_F13              0x7C
#define KEY_F14              0x7D
#define KEY_F15              0x7E
#define KEY_F16              0x7F
#define KEY_F17              0x80
#define KEY_F18              0x81
#define KEY_F19              0x82
#define KEY_F20              0x83
#define KEY_F21              0x84
#define KEY_F22              0x85
#define KEY_F23              0x86
#define KEY_F24              0x87
#define KEY_NUMLOCK          0x90
#define KEY_SCROLL           0x91

#define KEYSTATE_PRESSED    0x1     // was pressed since last stateof()
#define KEYSTATE_DOWN       0x2     // is currently pressed down

class KeyBoard {

    static uchar states[256];   // global key states

    static ulong instcnt;       // instance counter

 public:

    KeyBoard();
    ~KeyBoard();

    uchar   stateof(int key);

    bool    pressed(int key)
            {   return ((stateof(key) & KEYSTATE_PRESSED) != 0);    }

    bool    isdown(int key)
            {   return ((stateof(key) & KEYSTATE_DOWN) != 0);   }
    };

//|| FastTrig
class FastTrig {

    static ulong instcnt;   // instance counter

    static intf *tsin;      // all sizes must be the same
    static intf *ttan;      // and a power of 2 !

    static ushort idegmax;  // this avoids use of
    static ushort idegmask; // preprocessor symbols

    bool AllocTabs();
    void FreeTabs();

 public:

     FastTrig(ushort DegreesPerCircle = 1024);  // MUST be a power of 2 !
    ~FastTrig();

    bool dead()     {   return tsin ? 0 : 1;    }   // check after 'new' !

    int  degmax()   {   return idegmax;     }
    int  degmask()  {   return idegmask;    }

    intf sin(int deg)

        {   return  tsin ? tsin[(ushort)abs(deg) & idegmask] : 0;   }

    intf cos(int deg)

        {   return  tsin ? tsin[(ushort)abs(deg + (idegmax >> 2))
                                 & idegmask] : 0;   }

    intf tan(int deg)

        {   return  ttan ? ttan[(ushort)abs(deg) & idegmask] : 0;   }
    };

/*   _____________________________________________________________
    /                                                             \ 
    | High Resolution Timer
    \_____________________________________________________________/ 

    Descriptn:  timer with millisecond resolution

    Implementd: Amiga

    Notes:      interface is portable,
                but implementation is very(!) hardware dependent

  _____________________________________/VERSION HISTORY\____________________  
 /Date_ Version Who What____________________________________________________\ 
 yymmdd ------- --- --------------------------------------------------------- 
 940213 0.100   JTH created
 940908 0.500   JTH ported to Windows 3.1; currently supports just ONE usage
                    of a timer at a time
 941209             moved from 'expirq.cpp' to 'misc.cpp'. because this
                    is a passive timer w/o IRQ usage, there's no need
                    to compile it in an extra project (w/o stack depth check).
*/

#ifndef NO_FINETIMER

//|| FineTimer 

class FineTimer {

#ifdef  WIN16

    //  hardware timer x starts to countdown from a fix value k,
    //  e.g. 27.777 msec. User selects another period size u.
    //  the following is the difference k - u:

    uchar   tstart; // used with
    uword   tlen;   // hardware access

    ulong   ustart; // used with
    ulong   ulen;   // timeGetTime()

#endif

    ushort  usehw;  // use hardware timer

 public:

#ifdef  WIN16
    FineTimer(ushort UseHardwareTimer = 0);
    ~FineTimer();
#endif

    void open(ushort UseHardwareTimer); // called in constructor
    void close(void);

    // let timer begin to countdown a specified number of msec's
    void beginperiod(long msec);    // msec MAXIMUM: 22

    // every period must be ended by:
    //
    //      endperiod()
    //
    // ... never call a further beginperiod() before you
    //     ended the current period!
    //
    // you may call waitforperiodend() several times in one period

    void endperiod();

    // how many msec's are currently remaining in the timer?
    intf remain();

    // wait until timer started by beginperiod() has run low;
    // if it ran low meanwhile, this returns immediately
    void waitforperiodend();

    // delay EXACTLY for a specified number of MILLISECONDS
    void delay(long msec);      // msec: unlimited

    };

#endif

#endif  // eof
