/* "WDEF.H       ver 0.0          11/24/87"   SHADOW BOXES
   Copyright (c) 1987 John G. Donohue
09/19/87 jgd 0.0a Replaced macro scn_edge() by fn.
09/25/87 09/26/87 jgd 0.1 Change attributes from 0 to allow scn_was().
        Eliminate _rectangle and _screen struct names by typedef earlier.
        Add defines, etc.
11/23/87 jgd 0.2 Added LEFT, RIGHT, etc.
11/24/87 jgd 0.3 Separated non-portables from portables.  Cleaned up LINT stuff.
        
        Check (change?) CANCEL define to -20???
*/
/*****************************************************************************/
/* The first part of this file contains the items you must change if you
   change CPUs, compilers, or screen implementations.  The second part
   contains standard, if arbitrary, definitions.  Leave those alone. */
/*****************************************************************************/

/*****************************************************************************/
/* Switches for conditional compiling. */
#define TESTING 1       /* Print the various testing messages. */
#define LINT    1       /* Prototyping is allowed in this compiler. */

/*****************************************************************************/
/* If your screen is memory-mapped (can be read) define this.
   If you output to it as a terminal, DON'T define it.
   This affects cursor positioning and reading/writing rectangles.
   Not fully implemented if not defined. */
#define MEMMAPPED 1
#define STDWID  80
#define STDHGT  25

/*****************************************************************************/
/* Data types.  All these must be defined. */
#define TF              int     /* A Boolean value, 1 or 0 */
#define ERRCODE         int     /* >=16 bits, signed, integer-related */
#define COORD           int     /* >=16 bits, signed, no shorter than int */
#define WNUM            int     /* >=16 bits, signed, no shorter than int */
#define BITS            unsigned int    /* unsigned, at least as large as
                                   a character and all its attribute bits */
#define SCNCHAR         unsigned int    /* unsigned, at least as large as
                                   a character and all its attribute bits */
#define KEYCHAR         int     /* a key value (function keys, etc., are
                                   converted to value|0xFE00), possibly
                                   converted by getcv() to a logical
                                   meaning such as SAVE, LEFT, etc., which
                                   is of the form 0xFFxx.
                                   >=16 bits, signed, no shorter than int */

/*****************************************************************************/
/* Attributes of characters to be displayed on screen.
   Each must be defined as bit positions, which may be ORed with other bits, 
   including background and foreground colors, to make an attribute (WATTR),
   which is a logical value, and perhaps not equivalent to the way 
   the hardware expects an attribute.
   A SCNCHAR is an int-format (BITS, actually) version of a character and its
   attribute (possibly transformed to physical hardware requirements),
   shoved together into a single representation.  A rectangular array of 
   SCNCHARS forms the buffer in which a window's image is saved.
   The function
        SCNCHAR ca_to_scnchar(int c, WATTR a);
   combines the character and attribute, transforming the attribute to
   physical needs if necessary, into a single SCNCHAR data type.
   Although the IBM-PC implementation here uses a WATTR bit configuration
   which matches the physical bit requirement, that would not necessarily
   always be the case.  In fact, you could leave all the color and BLINK
   definitions as they are, and just change this function (along with those
   that read just attributes), to change to a different environment. */

#define WATTR           BITS    /* This MUST be defined this way. */

/* Define the bit positions.  Regardless of physical requirements in a
   SCNCHAR, the logical requirement in a WATTR is that a 1 bit means
   "do it", and a 0 bit means "don't do it".  The logical values have been
   chosen here to match the IBM PC's physical values, making the function
        SCNCHAR ca_to_scnchar(int c, WATTR a);
   trivial to implement. */
#define BRIGHT          (WATTR) 0x08
#define BLINK           (WATTR) 0x80
#define BG_BITS         (WATTR) 0x70
#define FG_BITS         (WATTR) 0x07

/* Foreground colors, in their WATTR bit positions */
#define FG_BLACK        (WATTR) 0x00
#define FG_BLUE         (WATTR) 0x01
#define FG_GREEN        (WATTR) 0x02
#define FG_CYAN         (WATTR) 0x03
#define FG_RED          (WATTR) 0x04
#define FG_MAGENTA      (WATTR) 0x05
#define FG_BROWN        (WATTR) 0x06
#define FG_WHITE        (WATTR) 0x07

/* Background colors, in their WATTR bit positions */
#define BG_BLACK        (WATTR) 0x00
#define BG_BLUE         (WATTR) 0x10
#define BG_GREEN        (WATTR) 0x20
#define BG_CYAN         (WATTR) 0x30
#define BG_RED          (WATTR) 0x40
#define BG_MAGENTA      (WATTR) 0x50
#define BG_BROWN        (WATTR) 0x60
#define BG_WHITE        (WATTR) 0x70

#define STDATTR         (WATTR) (FG_WHITE | BG_BLACK )  /* normal screen */
#define REVERSEVIDEO    (WATTR) (FG_BLACK | BG_WHITE )
#define shadowed(sc)    (sc & ~( (BG_BITS|BRIGHT) << 8 ))
                                /* How to put a SCNCHAR in shadow.
                                   Note that this MUST correspond with 
                                   the ca_to_scnchar() function. */
#define TRANSPARENT     (FG_WHITE | BG_WHITE | BLINK)   /* which you would
                                  never use for any other purpose.
                                  NOTE: Yes, a PC with a monochrome card
                                  would display this as white on black, but
                                  we use it for internal purposes, and it
                                  never physically reaches the PC screen. */

/*****************************************************************************/
/* Everything below here is standard. */
/*****************************************************************************/

#define HELP            -18
/* #define CANCEL          -20 */
#define CANCEL          ESC
#define UP              -21             /* Also direction of window scroll */
#define DOWN            -22
#define LEFT            -23
#define RIGHT           -24
#define PGUP            -25
#define PGDOWN          -26

#define POSITION        (COORD) -99
        /* must be neither a valid coordinate, NOR -1 nor -2 */

#define STDWNUM 0       /* the standard window before you open any windows */
#define MAXWIN  30      /* maximum number of windows */

/*****************************************************************************/
/* Attribute types, for use in the w_setattr(int type, WATTR a) function.
   Must not use 0, since these may be imbedded in text strings to change
   attributes in mid-string.  (See w_puts().) */
#define SET_    1
#define RESET_  2
#define FGC_    3
#define BGC_    4
#define ENTIRE_ 5

/*****************************************************************************/
/* In window structure, these are bits which make up .wstatus.
   Several are defined by w_def(), others occur later.  
   Not all are implemented. */

  /* defined by w_def */
#define WNORMAL_        (BITS) 0
#define CLEAR_ON_OPEN   (BITS) 1       /* EVERY time it is opened (redisplayed) */
#define NOSAVE_ON_CLOSE (BITS) 2       /* prevents buffer allocation for .wsave */
#define DELETE_ON_CLOSE (BITS) 4
/* #define DONT_ERASE      (BITS) 8  */
/* #define DONT_CLOSE      (BITS) 16 */   /* envisioned for STDWNUM only! */
#define NO_SCROLL       (BITS) 64
#define INVISIBLE       (BITS) 128
  /* states */
#define WDEFINED_       256
#define WOPENED_        512
#define WMAYDELETE_     (BITS) 1024
        /* system sets this if w_delete() requested but not yet possible. */

/*****************************************************************************/
/* Borders.  The actual character arrays used are in WBORD.I, which is
   included into WINDOW.C.  These bit masks show which bits are used
   for values of bordstyle.
   The 8 bits of LEFT, RIGHT, TOP, BOTTOM must be the lowest 8, as they
   are used as indexes into an array.  0=no border. 
   SHADOW and EDGE are in ADDITION to other borders.
   SHADOW requires decrementing left, incrementing wid, incrementing hgt. */
#define BORD_EDGE       (BITS) 0x0200
#define BORD_SHADOW     (BITS) 0x0100
/* For these next four, in each two-bit pair, the values represent:
     0 = no border, 1 = single line, 2 = double line, 3 = block.
   The SHIFT macros represent the number of bits to shift that pair right
   to put it in the range 0 to 3.
   The "bordstyle" is
       +---+---+---+---+---+---+---+---+---+---+
       |edg|shd|  top  | bottom|  left | right |
       +---+---+---+---+---+---+---+---+---+---+
*/
#define BORD_TOP        (BITS) 0x00c0
#define BORD_BOTTOM     (BITS) 0x0030
#define BORD_LEFT       (BITS) 0x000c
#define BORD_RIGHT      (BITS) 0x0003
#define BORD_TSHIFT     6
#define BORD_BSHIFT     4
#define BORD_LSHIFT     2
#define BORD_RSHIFT     0
#define BORD_MASK       3       /* Rightmost 2 bits get masked after shift. */
/* These are subscripts into the array of border characters. */
#define BORD_L  0
#define BORD_R  1
#define BORD_T  2
#define BORD_B  3
#define BORD_TL 4
#define BORD_TR 5
#define BORD_BL 6
#define BORD_BR 7

/*****************************************************************************/
/***  STRUCTURES  ***/
/*****************************************************************************/

typedef struct
{
        COORD  rhgt, rwid, rtop, rleft;
} RECT;

/*****************************************************************************/
typedef struct
{
        int    sbase;           /* set to B000H or B800H by w_init () */
/* same as        int    vidseg; */
        COORD  shgt, swid;
} SCN;

/*****************************************************************************/
struct _window
{
  /* When defined */
        BITS    wstatus;        /* initially zero if no window defined here. */
        BITS    wbordstyle;
        WATTR   wbordattr;
        RECT    wpane;          /* "writeable" area of window.  May be adjusted
                                   after open by "pane_" functions. */
        RECT    wrectb;         /* possibly bigger than above for borders,
                                   shadow. */
  /* When opened */
        int     wscreen;        /* screen page.  Not necessarily hardware-
                                   related.  Currently force screen 0. */
        SCNCHAR *wunder;        /* pointer to 1st char of block where stuff
                                   covered up is saved. */
  /* When closed */
        WATTR   wdftattr;       /* default attribute in this window (scroll) */
        WATTR   wattr;          /* last set attribute in this window */
        COORD   wrow, wcolumn;  /* 0,0 when w_def()'d, saved cursor value 
                                   when closed. */
        SCNCHAR *wsave;         /* window data, incl border, written to ONLY
                                   when window closed (unless wstatus has
                                   NOSAVE).
                                   IF you later allow writing to memory images
                                   as well as those on screen, or to "hidden"
                                   windows, this may be written to on each
                                   character. */
};

/*****************************************************************************/
struct  REGS
{
        char al,ah,bl,bh,cl,ch,dl,dh,others[6];
};
/*****************************************************************************/
#ifdef LINT
ERRCODE w_init(void);
WNUM    w_def(WNUM, BITS, COORD, COORD, WATTR, BITS, WATTR);
ERRCODE w_open(WNUM, COORD, COORD);
ERRCODE w_current(WNUM);
ERRCODE w_close(WNUM);
ERRCODE w_delete(WNUM);
ERRCODE w_puts(char *);
int     w_putc(int);
ERRCODE w_setattr(int, WATTR);
ERRCODE w_cursor(COORD, COORD);
ERRCODE w_scroll(int, int);
ERRCODE w_err(ERRCODE);
ERRCODE scn_ws(char *);
ERRCODE scn_was(char *);
ERRCODE scn_cursor(COORD, COORD);
ERRCODE scn_saverect(RECT *, SCNCHAR *);
ERRCODE scn_loadrect(RECT *, SCNCHAR *);
ERRCODE scn_edge(WATTR attr);

int     scn_wc(int c);
SCNCHAR scn_wscnchar(SCNCHAR);
SCNCHAR scn_rscnchar(void);
/* Not presently used
WATTR   scn_ra(void);
int     scn_wconly(int c);
WATTR   scn_waonly(WATTR);
*/
SCNCHAR ca_to_scnchar(int, WATTR);
ERRCODE hw_initscn(void);
ERRCODE hw_cursor(void);

KEYCHAR getv(void);
KEYCHAR getcv(void);

        /* Functions from the Standard Library */

char    *calloc(unsigned int, unsigned int);
void    exit(int);
void    free(char *);
int     printf(char *, ...);

        /* Functions that are MS-DOS- (and possibly compiler-) dependent */

int             int86(int, struct REGS *, struct REGS *);
unsigned int    peek(unsigned int, unsigned int); 
        /* CAUTION: DIFFERENT COMPILERS DO peek() DIFFERENTLY */
#endif

#ifdef MEMMAPPED
#define hw_setattr() /* Don't send anything to screen when attribute changes. */
#else
#ifdef LINT
ERRCODE hw_setattr(void);
#endif
#endif

#define w_writerc(row, col, s)  (w_cursor(row, col) ? werrnum : w_puts(s))
#define iswopen(w)              (windows[w].wstatus & WOPENED_)
#define BUG(msg)                printf(msg);
#define w_getcy()               cw->wrow
#define blink()                 w_setattr(SET_, BLINK)
#define noblink()               w_setattr(RESET_, BLINK)
#define bright()                w_setattr(SET_, BRIGHT)
#define nobright()              w_setattr(RESET_, BRIGHT)
