/**
*
*  BUTIL.H    Header file for Turbo C TOOLS Utility functions
*
*  Version 6.00  (C)Copyright Blaise Computing Inc.  1987-1989
*
**/

#ifndef DEF_BUTIL		/* Prevent redefinition.	    */

#include <string.h>
#include <stdlib.h>

/* needs dos.h */		/* For inp(), outp(), _osmajor,     */
				/* _osminor, and _psp.		    */


/********************************************************************/
/* Definitions of data types.					    */
/********************************************************************/

typedef struct			/* HALFREGS:  two halves of a 16-bit*/
{				/* general register.		    */
    unsigned char l;		/* Lower 8 bits.		    */
    unsigned char h;		/* Upper 8 bits.		    */
} HALFREGS;

typedef union			/* DOUBLREG:  Two ways to express   */
{				/* a 16-bit general register:	    */
    HALFREGS hl;		/* Two separated halves.	    */
    unsigned x; 		/* 16-bit unsigned quantity.	    */
} DOUBLREG;

typedef struct			/* ALLREG:  complete CPU state	    */
{				/*   (This must match version	    */
				/*   in ISCALINT.ASM.)		    */
    DOUBLREG ax,bx,cx,dx;	/* General registers.		    */
    unsigned si,di;		/* Index   registers.		    */
    unsigned ds,es,ss,cs;	/* Segment registers.		    */
    unsigned flags,bp,sp,ip;	/* Other   registers.		    */
} ALLREG;

struct dreg			/* DOSREG:  registers for call	    */
{				/*   to DOS.			    */
    unsigned ax,bx,cx,dx,si,di,ds,es;
};
#define DOSREG	struct dreg

typedef struct segads		/* ADS:  Physical address	    */
{				/*   expressed as segment and offset*/
    unsigned r; 		/* Offset.			    */
    unsigned s; 		/* Segment.			    */
} ADS;

struct address			/* Physical address.		    */
{				/*   expressed as segment and offset*/
    unsigned r; 		/* Offset.			    */
    unsigned s; 		/* Segment.			    */
};


/********************************************************************/
/* Flag bits for use with ALLREG structure.			    */
/********************************************************************/

#define CF_FLAG     0x0001	/* Carry flag.			    */
#define PF_FLAG     0x0002	/* Parity flag (1 means even).	    */
#define AF_FLAG     0x0010	/* Auxiliary carry flag.	    */
#define ZF_FLAG     0x0040	/* Zero flag (1 means zero).	    */
#define SF_FLAG     0x0080	/* Sign flag (1 means negative).    */
#define TF_FLAG     0x0100	/* Trap flag (1 means single step). */
#define IF_FLAG     0x0200	/* Interrupt enable flag.	    */
#define DF_FLAG     0x0400	/* Direction flag (0 means up).     */
#define OF_FLAG     0x0800	/* Overflow flag (1 means overflow).*/

#define DEF_FLAGS   (IF_FLAG)	/* Commonest value for flags:	    */
				/*   interrupts enabled,	    */
				/*   single-stepping off,	    */
				/*   direction up.		    */


/********************************************************************/
/* Handy system constants and addresses.			    */
/********************************************************************/

#define UTDOSINT 0x21		/* Standard DOS gate interrupt.     */

		/* Address of PC model code.			    */
#define UTMODELADDR (uttofaru (0xffff, 0xe))

		/* Address of PC BIOS clock tick count. 	    */
#define UTCLOCKADDR (uttofaru (0x40, 0x6c))

		/* Address of PC BIOS clock rollover flag.	    */
#define UTROLLADDR (uttofaru (0x40, 0x70))

		/* Possible values for IBM Model Code:		    */
#define  IBM_PC  ((char) 0xff)	/* PC.				    */
#define  IBM_XT  ((char) 0xfe)	/* PC-XT or Portable PC.	    */
#define  IBM_JR  ((char) 0xfd)	/* IBM PC-Jr.			    */
#define  IBM_AT  ((char) 0xfc)	/* IBM (or compat.) PC-AT.	    */
#define  IBM_X2  ((char) 0xfb)	/* PC-XT with 256/640 motherboard.  */
#define  IBM_CV  ((char) 0xf9)	/* PC Convertible.		    */
#define  IBM_30  ((char) 0xfa)	/* PS/2 model 30.		    */
#define  IBM_50  ((char) 0xfc)	/* PS/2 models 50, 60.		    */
#define  IBM_80  ((char) 0xf8)	/* PS/2 model 80.		    */


/********************************************************************/
/* Global variables maintained by UT functions and macros.	    */
/********************************************************************/

		 /* Contains address of DOS critical section flag,  */
		 /* after UTCRIT is called.			    */
extern unsigned char far *b_critad;

extern char b_pcmodel;		/* IBM PC Model Code.		    */
extern unsigned char b_submod;	/* IBM PC submodel code, or 0 if    */
				/*   unavailable.		    */
extern unsigned char b_biosrev; /* IBM PC BIOS revision level, or 0 */
				/*   if unavailable.		    */

extern int b_ansdis;		/* Nonzero if UTANSI has disabled   */
				/*   ANSI.SYS.			    */


/********************************************************************/
/* Constant values for UTINTFLG, UTAMOVE, UTSAFCPY, UTCTLBRK, UTANSI*/
/********************************************************************/

#define UT_INTON  1		/* Values to use with UTINTFLG.     */
#define UT_INTOFF 0

				/* Values to use with UTAMOVE.	    */
#define UT_MVFORWARD  0 	/*     Increasing memory addresses. */
#define UT_MVBACKWARD 1 	/*     Decreasing memory addresses. */

				/* Values to use with UTSAFCPY.     */
				/*				    */
#define UT_SRC_STRADDLE 1	/* Source buffer straddles segment  */
				/*   boundary, target okay.	    */
#define UT_TGT_STRADDLE 2	/* Target buffer straddles segment  */
				/*   boundary, source okay.	    */
				/* Both source & target straddle.   */
#define UT_2_STRADDLE	((UT_SRC_STRADDLE) + (UT_TGT_STRADDLE))

				/* Values to use with UTCTLBRK.     */
#define  CBRK_SET	1	/*     Set CTRL-BREAK state.	    */
#define  CBRK_GET	0	/*     Return CTRL-BREAK state.     */
#define  CBRK_ON	1	/*     Check CTRL-BREAK at every    */
				/*	   DOS call.		    */
#define  CBRK_OFF	0	/*     Check CTRL-BREAK only when   */
				/*	   accessing standard input,*/
				/*	   output, print, or	    */
				/*	   auxiliary device.	    */

				/* Values to use with UTANSI.	    */
				/*				    */
				/* As command:	    As result:	    */
#define UT_ANS_ABSENT	(-2)	/*   (Invalid.)       Not detected. */
#define UT_ANS_ENABLE	(-1)	/*   Enable.	      Active.	    */
#define UT_ANS_DISABLE	  0	/*   Disable.	      Disabled.     */
#define UT_BAD_OPT	  1	/*   (Invalid.)       Bad option.   */
#define UT_ANS_DETECT	  2	/*   Sense presence.  (Impossible.) */
#define UT_ANS_HANDLES	  3	/*   (Invalid.)       No handles.   */

/********************************************************************/
/* Constant values for UTSQZSCN, UTUNSQZ.			    */
/********************************************************************/

#define UT_CHAR_KEY	0xFF
#define UT_ATTR_KEY	0xFE

/********************************************************************/
/* Macros to combine and extract words, bytes, and nybbles.	    */
/********************************************************************/

#define uthiword(a)   (((a)>>16)&0xffffL)   /* High word of long a. */
#define utloword(a)   ((a)&0xffffL)	    /* Low  word of long a. */

				/* Combine high word a, low  word b.*/
#define utwdlong(a,b) ((((0xffffL&(long)(a)))<<16)|		     \
		       (0xffffL&(long)(b)))

#define uthibyte(a)   (((a)>>8)&0x00ff) /* High byte of word a.     */
#define utlobyte(a)   ((a)&0x00ff)	/* Low	byte of word a.     */

				/* Combine high byte a, low byte b. */
#define utbyword(a,b) ((((a)&0x00ff)<<8)|((b)&0x00ff))

#define uthinyb(a)    (((a)>>4)&0x000f) /* High nybble of byte a.   */
#define utlonyb(a)    ((a)&0x000f)	/* Low nybble  of byte a.   */

				/* Combine high nybble a, low	    */
				/* nybble b.			    */
#define utnybbyt(a,b) ((((a)&0x000f)<<4)|((b)&0x000f))


/********************************************************************/
/* Macros for pointer manipulation.				    */
/********************************************************************/

			/* Construct far void pointer.		    */
#define uttofaru(seg,off) ((void far *) 			     \
			   ((((unsigned long) (unsigned int)	     \
			     (seg)) << 16L) |			     \
			   ((unsigned long) (unsigned int) (off))))

			/* Compute offset  of memory pointed to.    */
#define utoff(p) ((unsigned int) (p))

			/* Compute segment of memory pointed to.    */
#define utseg(p) ((unsigned int)				     \
		  (((unsigned long) (const void far *) (p)) >> 16L))


			/* Make a far pointer to a type.	    */
#define uttofar(seg,off,type) ((type far *) uttofaru((seg),(off)))

			/* Normalize a pointer. 		    */
#define utnorm(p,type) (uttofar (utseg (p) + (utoff (p) >> 4),	     \
				(utoff (p) & 0x000f),		     \
				type))

			/* Return 20-bit address in a pointer.	    */
#define utplong(p) ((((unsigned long) utseg (p)) << 4L) +	     \
		    ((unsigned long) utoff (p)) &		     \
		    0xfffffL)


/********************************************************************/
/* Macros for low-level memory manipulation.			    */
/********************************************************************/

			/* Return byte pointed to by pointer.	    */
#define utpeekb(p) (*((const unsigned char far *) (p)))

			/* Return word pointed to by pointer.	    */
#define utpeekw(p) (*((const unsigned int far *) (p)))

			/* Put byte in location pointed to.	    */
#define utpokeb(p,bval) (*((unsigned char far *) (p)) = (bval))

			/* Put word in location pointed to.	    */
#define utpokew(p,uval) (*((unsigned int far *) (p)) = (uval))

			/* Fetch N bytes from a far pointer.	    */
#define utpeekn(pf,pn,clen) (utmovmem ((const char far *) (pf),     \
				       (char far *) (pn),	    \
				       (clen)))

			/* Put N bytes to a far pointer.	    */
#define utpoken(pn,pf,clen) (utmovmem ((const char far *) (pn),      \
				       (pf),			     \
				       (clen)))


/********************************************************************/
/* Macros for communication with ports. 			    */
/********************************************************************/

			/* Return a byte from a port.		    */
#define utinp(port) (inp (port))

			/* Put a byte in a port.		    */
#define utoutp(port,bval) ((void) outp ((port), (int) (bval)))


/********************************************************************/
/* Miscellaneous macros.					    */
/********************************************************************/

#define NIL		((void *) 0)	/* Universal invalid data   */
					/* pointer.		    */

					/* Far version of NIL.	    */
#define FARNIL		((void far *) 0)

#define utsign(a)	((a)>0?1:((a)==0?0:-1)) /* Arithmetic sign. */
#define utalarm()	utsound(450,9)		/* Beep for 1/2 sec.*/
#define utskip		printf("\n")            /* CR/LF.           */


		/* Allocate and zero a data object of a given type, */
		/* return a pointer to it.			    */
#define utalloc(type) ((type *) calloc(1,sizeof(type)))


		/* Copy a data object, and return a pointer to	    */
		/* destination. 				    */
#define utcopy(to,from,type) ((type *)				     \
		memmove ((to),					     \
			 (from),				     \
			 sizeof (type)))


		/* Return DOS version numbers.			    */
#define utdosmajor ((unsigned char) uthibyte (utdosver))
#define utdosminor ((unsigned char) utlobyte (utdosver))

#define utdosver ((unsigned int) utbyword (_osmajor, _osminor))


		/* Check for null pointer assignments.		    */
#if (defined(BCHKNIL) || !(defined(BNOCHKNIL)))
#define utchknil() (utnulchk()					     \
		    ? (fprintf (stderr, 			     \
		       "Null pointer assignment detected in <%s:%d>\n",\
		       __FILE__, __LINE__),			     \
		       exit (1),				     \
		       (1))					     \
		    : (0))
#else
#define utchknil() ((void) 0)
#endif

			/* Return the segment address of the	    */
			/* program's PSP.                           */
#define utpspseg ((unsigned) (_psp))

			/* Return 0 if DOS is not ready, 1 if it is.*/
			/* Always returns 0 is UTCRIT has not	    */
			/* executed yet.			    */
#define utdosrdy() ((b_critad != FARNIL)			     \
		     ? (utpeekb (b_critad) == 0)		     \
		     : (0))

			/* Enable interrupts, and return old	    */
			/* interrupt flag value.		    */
#define utinton() (utintflg (UT_INTON))

			/* Disable interrupts, and return old	    */
			/* interrupt flag value.		    */
#define utintoff() (utintflg (UT_INTOFF))

			/* Turn the speaker off.		    */
#define utspkoff() (utspkr (0))

			/* Turn the speaker on, with a specified    */
			/* frequency sound to be produced.	    */
#define utspkon(freq) (utspkr (freq))

			/* Make a sound of "freq" frequency with the*/
			/* speaker for a specified duration.	    */
#define utsound(freq, dura) (					     \
		utspkon (freq), 				     \
		utsleep (dura), 				     \
		utspkoff ())


/********************************************************************/
/* Macros to perform range checking and limiting.		    */
/********************************************************************/

/* Beware:  the following three macros (UTMAX, UTMIN, and UTABS)    */
/* may have side effects because they evaluate their arguments more */
/* than once.							    */

				/* Maximum of two values.	    */
#define utmax(a,b) ((a) > (b) ? (a) : (b))
#ifndef max
#define max(a,b) utmax(a,b)
#endif

				/* Minimum of two values.	    */
#define utmin(a,b) ((a) <= (b) ? (a) : (b))
#ifndef min
#define min(a,b) utmin(a,b)
#endif

#define utabs(x) ((x)<0 ? -(x) : (x))	/* Absolute value.	    */

			/* Return 1 if a is outside the range	    */
			/* defined by l and h, 0 if not.	    */
#define utrange(a,l,h)	(((a) < (l)) || ((a) > (h)))
#define utoutrng(a,l,h) utrange(a,l,h)

			/* Confine a to the range defined by b and c*/
#define utbound(a,b,c)						     \
    {								     \
	register int uttemp;					     \
								     \
	if ((a) < (uttemp = (b)) || (a) > (uttemp = (c)))	     \
	    (a) = uttemp;					     \
    }

			/* Prevent a from exceeding b.		    */
#define utuplim(a,b)						     \
    {								     \
	register int uttemp;					     \
								     \
	if ((a) > (uttemp = (b)))				     \
	    (a) = uttemp;					     \
    }

			/* Prevent a from being less than b.	    */
#define utlowlim(a,b)						     \
    {								     \
	register int uttemp;					     \
								     \
	if ((a) < (uttemp = (b)))				     \
	    (a) = uttemp;					     \
    }


/********************************************************************/
/* Function declarations.					    */
/********************************************************************/

void cdecl utamove(const char far *,/* Copy memory from far pointer */
		    char far *,     /* source to far pointer target.*/
		    unsigned int,   /* Does not handle overlap.     */
		    int);	    /*				    */
				    /*				    */
int cdecl utctlbrk (int,int);	    /* Set or return state of DOS   */
				    /* CTRL-BREAK checking.	    */
				    /*				    */
#ifndef utdosver		    /*				    */
int cdecl utdosver (void);	    /* Return the DOS major, minor  */
#endif				    /* version number as 16-bit.    */
				    /*				    */
int cdecl utgetclk (long *);	    /* Return the BIOS clock roll   */
				    /* flag and tick count.	    */
				    /*				    */
int cdecl utintflg (int);	    /* Set interrupt state, return  */
				    /* old state.		    */
				    /*				    */
unsigned int cdecl utnulchk (void); /* Check for NIL-pointer	    */
				    /* assignments.		    */
				    /*				    */
unsigned cdecl utsleep (unsigned);  /* Suspend processing for	    */
				    /* specified duration.	    */
				    /*				    */
void cdecl utspkr (unsigned);	    /* Speaker control. 	    */
				    /*				    */
int cdecl utansi(int);		    /* Detect, disable, or	    */
				    /*	 re-enable ANSI.SYS.	    */
				    /*				    */
void cdecl utmovmem(		    /* Copy block of memory, using  */
   const char far *, char far *,    /* far pointer source and	    */
		     unsigned int); /* target.			    */
				    /*				    */
int cdecl utsafcpy(const void far *,/* Copy block of memory if	    */
		   void far *,	    /*	 source & target buffers    */
		   unsigned int);   /*	 don't straddle segment     */
				    /*	 boundaries.		    */
				    /*				    */
unsigned char far * cdecl	    /* Return the address of the    */
		  utcrit (void);    /* DOS critical section flag.   */
				    /* Also puts the value in	    */
				    /* b_critad.		    */
				    /*				    */
char cdecl utmodel(void);	    /* Return machine model code.   */
				    /*				    */
unsigned long cdecl uttim2tk	    /* Compute a tick value for a   */
		       (int, int,   /* given time of day.	    */
			int, int);  /*				    */
				    /*				    */
void cdecl uttk2tim(unsigned long,  /* Compute a time value (in     */
		    int *, int *,   /* hours, minutes, seconds,     */
		    int *, int *);  /* hundredths) for a given	    */
				    /* tick value.		    */
				    /*				    */
int cdecl utsqzscn(const char far *,/* Compress a screen image.     */
		   char *, int,     /*				    */
		   int);	    /*				    */
				    /*				    */
int cdecl utunsqz(const char *,     /* Uncompress a screen image.   */
		  char far *, int,  /*				    */
		  int); 	    /*				    */


#define DEF_BUTIL  1	/* Prevent second reading of these	    */
			/* definitions. 			    */

#endif			/* Ends "#ifndef DEF_BUTIL".                */
