#ifndef INCLUDED_CURSES_H
#define INCLUDED_CURSES_H

#ifdef MPW
#define MAC
#define QD(whatever) (qd.##whatever)
#endif

#ifdef THINK_C
#define MAC
#define QD(whatever) (whatever)
#endif

#ifdef __MWERKS__
#define MAC
#define QD(whatever) (qd.##whatever)
#endif

#include <stdio.h>
#include <stdarg.h>

#ifndef TRUE
typedef enum { FALSE=0, TRUE=1 } bool;
#else
typedef unsigned	bool;
#endif

#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif /* MIN */

#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif /* MAX */

typedef int		chtype;	/* Characters and attributes		*/

#define	_SUBWIN		01
#define	_ENDLINE	02
#define	_FULLWIN	04
#define	_SCROLLWIN	010
#define	_FLUSH		020
#define	_ISPAD		040
#define	_WINCHANGED	0100
#define	_WINMOVED	0200

typedef struct
{
    short	_cury, _curx;
    short	_maxy, _maxx;
    short	_begy, _begx;
    short	_pmap_orgy, _pmap_orgx;	/* Upper left corner of most recent prefresh on pad. */
    short	_pmap_maxy, _pmap_maxx;	/* Max x/y of most recent prefresh on pad. */
    short	_xdim;					/* Value to add to chtype pointer to move down a row. */
    short	_flags;
    chtype	_attrs;
    bool	_clear;
    bool	_leave;
    bool	_scroll;
    bool	_use_idl;	/* 0=no, 1=yes, 2=go by need_idl */
    bool	_use_keypad;	/* 0=no, 1=yes, 2=yes/timeout */
    bool	_use_meta;	/* T=use the meta key */
    bool	_nodelay;	/* T=don't wait for tty input */
    chtype	*_y;		/* Unix uses **_y */
    short	*_firstch;
    short	*_lastch;
    bool	_notimeout;	/* T=do wait for rest of function key */
    bool	_need_idl;	/* T=have done ins/del line/scroll recently */
    short	_tmarg,_bmarg;	/* Scrolling rows */
} WINDOW;

typedef void	*SCREEN;		/* newterm()/setterm() not supported */

#define	ERR	(-1)
#define	OK	(1)

/****
* These two macros convert window-relative cursor position to screen-relative:
****/

#define _CURS_CURSOR_SCREEN_ROW(w) ((w)->_begy + (w)->_cury - \
	(((w)->_flags & _ISPAD) ? (w)->_pmap_orgy : 0))
#define _CURS_CURSOR_SCREEN_COL(w) ((w)->_begx + (w)->_curx - \
	(((w)->_flags & _ISPAD) ? (w)->_pmap_orgx : 0))

#ifdef MAC

#include <macurses.h>

extern bool	maccur_init		(void);
extern int	maccur_refresh	(WINDOW *win, bool outflag);
extern bool	maccur_end		(void);
extern void	maccur_beep		(int flag);
extern int	maccur_kbinp	(WINDOW *win, bool raw, bool cbreak);
extern void maccur_flush_typeahead(void);

#define CURS_INIT_FN maccur_init
#define CURS_REFRESH_FN maccur_refresh
#define CURS_END_FN maccur_end
#define CURS_BEEP_FN maccur_beep
#define CURS_KBINP_FN maccur_kbinp
#define CURS_FLUSHINP_FN maccur_flush_typeahead

#else

/*
 * External, machine-specific entry points:
 */

extern bool	ms_init		(void);
extern int	ms_refresh	(WINDOW *win, bool outflag);
extern bool	ms_end		(void);
extern void ms_restore_scrn	(void);
extern void	ms_beep		(int flag);
extern int	ms_kbinp	(WINDOW *win, bool raw, bool cbreak);
extern void ms_flushinp	(void);

#define CURS_INIT_FN ms_init
#define CURS_REFRESH_FN ms_refresh
#define CURS_END_FN ms_end
#define CURS_BEEP_FN ms_beep
#define CURS_KBINP_FN ms_kbinp
#define CURS_FLUSHINP_FN ms_flushinp

#endif /* MAC */

extern char*	_curses_prntw;		/* printw() buffer		*/
extern unsigned	_curses_prntw_size;	/* Nbr chars in printw() buffer	*/
extern int _curses_tab_wid;			/* Width of tab (defaults to 8). */
extern WINDOW*	stdscr;			/* Default terminal window	*/
extern int	COLS;			/* Nbr columns in screen	*/
extern int	LINES;			/* Nbr lines in screen		*/

#define	addch(ch)		waddch(stdscr, ch)
#define	getch()			wgetch(stdscr)
#define	addstr(str)		waddstr(stdscr, str)
#define	getstr(str)		wgetstr(stdscr, str)
#define	move(y, x)		wmove(stdscr, y, x)
#define	clear()			wclear(stdscr)
#define	erase()			werase(stdscr)
#define	clrtobot()		wclrtobot(stdscr)
#define	clrtoeol()		wclrtoeol(stdscr)
#define	insertln()		winsertln(stdscr)
#define	deleteln()		wdeleteln(stdscr)
#define	refresh()		wrefresh(stdscr)
#define	inch()			winch(stdscr)
#define	insch(c)		winsch(stdscr,c)
#define	delch()			wdelch(stdscr)
#define	standout()		wstandout(stdscr)
#define	standend()		wstandend(stdscr)
#define	attron(at)		wattron(stdscr,at)
#define	attroff(at)		wattroff(stdscr,at)
#define	attrset(at)		wattrset(stdscr,at)
#define	echochar(ch)		wechochar(stdscr, ch)

#define	setscrreg(t,b)		wsetscrreg(stdscr, t, b)
#define	wsetscrreg(win,t,b)	(win->_tmarg=(t),win->_bmarg=(b))

#define crmode()		nocbreak()

/*
 * mv functions
 */

#define	mvwaddch(win,y,x,c)	(wmove(win,y,x)==ERR?ERR:waddch(win,c))
#define	mvwgetch(win,y,x)	(wmove(win,y,x)==ERR?ERR:wgetch(win))
#define	mvwaddstr(win,y,x,s)	(wmove(win,y,x)==ERR?ERR:waddstr(win,s))
#define	mvwgetstr(win,y,x,s)	(wmove(win,y,x)==ERR?ERR:wgetstr(win,s))
#define	mvwinch(win,y,x)	(wmove(win,y,x)==ERR?ERR:winch(win))
#define	mvwdelch(win,y,x)	(wmove(win,y,x)==ERR?ERR:wdelch(win))
#define	mvwinsch(win,y,x,c)	(wmove(win,y,x)==ERR?ERR:winsch(win,c))
#define	mvaddch(y,x,ch)		mvwaddch(stdscr,y,x,ch)
#define	mvgetch(y,x)		mvwgetch(stdscr,y,x)
#define	mvaddstr(y,x,str)	mvwaddstr(stdscr,y,x,str)
#define	mvgetstr(y,x,str)	mvwgetstr(stdscr,y,x,str)
#define	mvinch(y,x)		mvwinch(stdscr,y,x)
#define	mvdelch(y,x)		mvwdelch(stdscr,y,x)
#define	mvinsch(y,x,c)		mvwinsch(stdscr,y,x,c)

/*
 * psuedo functions
 */

#define	getyx(win,y,x)		(y = win->_cury, x = win->_curx)
#define	getbegyx(win,y,x)	(y = win->_begy, x = win->_begx)
#define	getmaxyx(win,y,x)	(y = win->_maxy, x = win->_maxx)
#define	getsyx(y,x)		(_getsyx(&y,&x))
#define	winch(win)		(win->_y[win->_cury*win->_maxx+win->_curx])

#define	clearok(win,bf)		((win)->_clear = (bf))
#define	leaveok(win,bf)		((win)->_leave = (bf))
#define	scrollok(win,bf)	((win)->_scroll = (bf))

extern int	alarm		(void);
extern int	beep		(void);
extern int	box			(WINDOW *win, chtype vertch, chtype horch);
extern int	cbreak		(void);
extern int copywin		(WINDOW *src_win, WINDOW *dst_win,
						 int sminy, int sminx, int dminy, int dminx,
						 int dmaxy, int dmaxx, bool overlay_flag);
extern int	delwin		(WINDOW *win);
extern int	doupdate	(void);
extern int	echo		(void);
extern int	endwin		(void);
extern int	flushinp	(void);
extern int	halfdelay	(int tenths);
extern WINDOW	*initscr	(void);
extern int	intrflush	(WINDOW *win, bool flag);
extern bool	isendwin	(void);
extern int	keypad		(WINDOW *win, bool flag);
extern int	meta		(WINDOW *win, bool flag);
extern int	mvprintw	(int y, int x, char *fmt, ...);
extern int	mvscanw	(int y, int x, char *fmt, ...);
extern int	mvwin		(WINDOW *win, int y, int x);
extern int	mvwprintw	(WINDOW *win, int y, int x, char *fmt, ...);
extern int	mvwscanw	(WINDOW *win, int y, int x, char *fmt, ...);
extern WINDOW	*newpad		(int nlines, int ncols);
extern WINDOW	*newwin		(int nlines, int ncols, int beg_y, int beg_x);
extern int	nl		(void);
extern int	nocbreak	(void);
extern int	nodelay		(WINDOW *win, bool flag);
extern int	noecho		(void);
extern int	nonl		(void);
extern int	noraw		(void);
extern int	notimeout	(WINDOW *win, bool flag);
extern int	overwrite	(WINDOW *src_win, WINDOW *dst_win);
extern int	overlay		(WINDOW *src_win, WINDOW *dst_win);
extern int	pnoutrefresh(WINDOW *pad, int pminy, int pminx,
						 int sminy, int sminx, int smaxy, int smaxx);
extern int	prefresh	(WINDOW *pad, int pminy, int pminx,
						 int sminy, int sminx, int smaxy, int smaxx);
extern int	printw		(char *fmt, ...);
extern int	raw		(void);
extern int	scanw		(char *fmt, ...);
extern int	scroll		(WINDOW *win);
extern WINDOW*	subpad	(WINDOW *parnt_pad, int nlines, int ncols, int beg_y, int beg_x);
extern WINDOW*	subwin	(WINDOW *parnt_win, int nlines, int ncols, int beg_y, int beg_x);
extern int	touchline	(WINDOW *win, int start, int count);
extern int	touchwin	(WINDOW *win);
extern int	ungetch		(chtype ch);
extern int	vwprintw	(WINDOW *win, char *fmt, va_list ap);
extern int	vwscanw		(WINDOW *win, char *fmt, va_list ap);
extern int	waddch		(WINDOW *win, chtype ch);
extern int	waddstr		(WINDOW *win, char *str);
extern int	wattroff	(WINDOW *win, chtype attrs);
extern int	wattron		(WINDOW *win, chtype attrs);
extern int	wattrset	(WINDOW *win, chtype attrs);
extern int	wclear		(WINDOW *win);
extern int	wclrtobot	(WINDOW *win);
extern int	wclrtoeol	(WINDOW *win);
extern int	wdelch		(WINDOW *win);
extern int	wdeleteln	(WINDOW *win);
extern int	wechochar	(WINDOW *win, chtype ch);
extern int	werase		(WINDOW *win);
extern int	wgetch		(WINDOW *win);
extern int	wgetstr		(WINDOW *win, char *str);
extern int	winsch		(WINDOW *win, chtype ch);
extern int	winsertln	(WINDOW *win);
extern int	wmove		(WINDOW *win, int ypos, int xpos);
extern int	wnoutrefresh	(WINDOW *win);
extern int	wprintw		(WINDOW *win, char *fmt, ...);
extern int	wrefresh	(WINDOW *win);
extern int	wscanw		(WINDOW *win, char *fmt, ...);
extern int	wstandend	(WINDOW *win);
extern int	wstandout	(WINDOW *win);

#define	A_STANDOUT	0000200
#define	A_UNDERLINE	0000400
#define	A_REVERSE	0001000
#define	A_BLINK		0002000
#define	A_DIM		0004000
#define	A_BOLD		0010000
#define	A_ALTCHARSET	0100000
#define	A_NORMAL	0000000

#define	_STANDOUT	A_STANDOUT

#define	A_CHARTEXT	0177
#define	A_ATTRIBUTES	(~A_CHARTEXT)

/*
 * Line drawing and special display characters:
 */

#ifdef THINK_C

#define	ACS_HLINE	'-'
#define	ACS_VLINE	'|'
#define	ACS_ULCORNER	'*'
#define	ACS_LLCORNER	'*'
#define	ACS_URCORNER	'*'
#define	ACS_LRCORNER	'*'

#else

#define	ACS_BSSB	(acs_map['l'])
#define	ACS_SSBB	(acs_map['m'])
#define	ACS_BBSS	(acs_map['k'])
#define	ACS_SBBS	(acs_map['j'])
#define	ACS_SBSS	(acs_map['u'])
#define	ACS_SSSB	(acs_map['t'])
#define	ACS_SSBS	(acs_map['v'])
#define	ACS_BSSS	(acs_map['w'])
#define	ACS_BSBS	(acs_map['q'])
#define	ACS_SBSB	(acs_map['x'])
#define	ACS_SSSS	(acs_map['n'])

#define	ACS_SBBS	(acs_map['j'])
#define	ACS_BBSS	(acs_map['k'])
#define	ACS_BSSB	(acs_map['l'])
#define	ACS_SSBB	(acs_map['m'])
#define	ACS_SSSS	(acs_map['n'])
#define	ACS_BSBS	(acs_map['q'])
#define	ACS_SSSB	(acs_map['t'])
#define	ACS_SBSS	(acs_map['u'])
#define	ACS_SSBS	(acs_map['v'])
#define	ACS_BSSS	(acs_map['w'])
#define	ACS_SBSB	(acs_map['x'])

#define	ACS_ULCORNER	ACS_BSSB
#define	ACS_LLCORNER	ACS_SSBB
#define	ACS_URCORNER	ACS_BBSS
#define	ACS_LRCORNER	ACS_SBBS
#define	ACS_RTEE	ACS_SBSS
#define	ACS_LTEE	ACS_SSSB
#define	ACS_BTEE	ACS_SSBS
#define	ACS_TTEE	ACS_BSSS
#define	ACS_HLINE	ACS_BSBS
#define	ACS_VLINE	ACS_SBSB
#define	ACS_PLUS	ACS_SSSS

#define	ACS_S1		(acs_map['o'])		/* scan line 1 */
#define	ACS_S9		(acs_map['s'])		/* scan line 9 */
#define	ACS_DIAMOND	(acs_map['`'])		/* diamond */
#define	ACS_CKBOARD	(acs_map['a'])		/* checkerboard */
#define	ACS_DEGREE	(acs_map['f'])		/* degree symbol */
#define	ACS_PLMINUS	(acs_map['g'])		/* plus/minus */
#define	ACS_BULLET	(acs_map['~'])		/* bullet */
#define	ACS_LARROW	(acs_map[','])		/* left arrow */
#define	ACS_RARROW	(acs_map['+'])		/* right arrow */
#define	ACS_DARROW	(acs_map['.'])		/* down arrow */
#define	ACS_UARROW	(acs_map['-'])		/* up arrow */
#define	ACS_BOARD	(acs_map['h'])		/* board of squares */
#define	ACS_LANTERN	(acs_map['i'])		/* lantern symbol */
#define	ACS_BLOCK	(acs_map['0'])		/* solid square block */

extern chtype acs_map[];

#endif /* THINK_C */

#define	KEY_BREAK	0401		/* break key (unreliable) */
#define	KEY_DOWN	0402		/* terminal down arrow key */
#define	KEY_UP		0403		/* terminal up arrow key */
#define	KEY_LEFT	0404		/* terminal left arrow key */
#define	KEY_RIGHT	0405		/* terminal right arrow key */
#define	KEY_HOME	0406		/* home key */
#define	KEY_BACKSPACE	0407		/* backspace key */
#define	KEY_F0		0410		/* function key f0 */
#define	KEY_F(n)	(KEY_F0+(n))	/* Up to 64 function keys */
#define	KEY_DL		0510		/* delete line key */
#define	KEY_IL		0511		/* insert line */
#define	KEY_DC		0512		/* delete character key */
#define	KEY_IC		0513		/* ins chr/ins mode key */
#define	KEY_EIC		0514		/* rmir/smir in insert mode x */
#define	KEY_CLEAR	0515		/* clear screen or erase key */
#define	KEY_EOS		0516		/* clear-to-end-of-screen key x */
#define	KEY_EOL		0517		/* clear-to-end-of-line key x */
#define	KEY_SF		0520		/* scroll-forward/down key */
#define	KEY_SR		0521		/* scroll-backward/up key */
#define	KEY_NPAGE	0522		/* next-page key */
#define	KEY_PPAGE	0523		/* previous-page key */
#define	KEY_STAB	0524		/* set-tab key x */
#define	KEY_CTAB	0525		/* clear-tab key x */
#define	KEY_CATAB	0526		/* clear-all-tabs key x */
#define	KEY_ENTER	0527		/* Enter/send (unreliable) */
#define	KEY_SRESET	0530		/* soft reset (unreliable) x */
#define	KEY_RESET	0531		/* hard reset (unreliable) x */
#define	KEY_PRINT	0532		/* print or copy x */
#define	KEY_LL		0533		/* home-down key x */
 					/* The keypad is arranged	*/
					/* as follows:			*/
					/*    a1    up    a3		*/
					/*   left   b2  right		*/
					/*    c1   down   c3		*/
#define	KEY_A1		0534		/* Upper left of keypad */
#define	KEY_A3		0535		/* Upper right of keypad */
#define	KEY_B2		0536		/* Center of keypad */
#define	KEY_C1		0537		/* Lower left of keypad */
#define	KEY_C3		0540		/* Lower right of keypad */
#define	KEY_BTAB	0541		/* Back tab key x */
#define	KEY_BEG		0542		/* beg(inning) key x */
#define	KEY_CANCEL	0543		/* cancel key x */
#define	KEY_CLOSE	0544		/* close key x */
#define	KEY_COMMAND	0545		/* cmd (command) key x */
#define	KEY_COPY	0546		/* copy key x */
#define	KEY_CREATE	0547		/* create key x */
#define	KEY_END		0550		/* end key */
#define	KEY_EXIT	0551		/* exit key x */
#define	KEY_FIND	0552		/* find key x */
#define	KEY_HELP	0553		/* help key x */
#define	KEY_MARK	0554		/* mark key x */
#define	KEY_MESSAGE	0555		/* message key x */
#define	KEY_MOVE	0556		/* move key x */
#define	KEY_NEXT	0557		/* next object key x */
#define	KEY_OPEN	0560		/* open key x */
#define	KEY_OPTIONS	0561		/* options key x */
#define	KEY_PREVIOUS	0562		/* previous object key x */
#define	KEY_REDO	0563		/* redo key x */
#define	KEY_REFERENCE	0564		/* ref(erence) key x */
#define	KEY_REFRESH	0565		/* refresh key x */
#define	KEY_REPLACE	0566		/* replace key x */
#define	KEY_RESTART	0567		/* restart key x */
#define	KEY_RESUME	0570		/* resume key x */
#define	KEY_SAVE	0571		/* save key x */
#define	KEY_SBEG	0572		/* shifted beginning key x */
#define	KEY_SCANCEL	0573		/* shifted cancel key x */
#define	KEY_SCOMMAND	0574		/* shifted command key x */
#define	KEY_SCOPY	0575		/* shifted copy key x */
#define	KEY_SCREATE	0576		/* shifted create key x */
#define	KEY_SDC		0577		/* shifted delete char key x */
#define	KEY_SDL		0600		/* shifted delete line key x */
#define	KEY_SELECT	0601		/* select key x */
#define	KEY_SEND	0602		/* shifted end key x */
#define	KEY_SEOL	0603		/* shifted clear line key x */
#define	KEY_SEXIT	0604		/* shifted exit key x */
#define	KEY_SFIND	0605		/* shifted find key x */
#define	KEY_SHELP	0606		/* shifted help key x */
#define	KEY_SHOME	0607		/* shifted home key x */
#define	KEY_SIC		0610		/* shifted input key x */
#define	KEY_SLEFT	0611		/* shifted left arrow key */
#define	KEY_SMESSAGE	0612		/* shifted message key x */
#define	KEY_SMOVE	0613		/* shifted move key x */
#define	KEY_SNEXT	0614		/* shifted next key x */
#define	KEY_SOPTIONS	0615		/* shifted options key x */
#define	KEY_SPREVIOUS	0616		/* shifted prev key x */
#define	KEY_SPRINT	0617		/* shifted print key x */
#define	KEY_SREDO	0620		/* shifted redo key x */
#define	KEY_SREPLACE	0621		/* shifted replace key x */
#define	KEY_SRIGHT	0622		/* shifted right arrow */
#define	KEY_SRSUME	0623		/* shifted resume key x */
#define	KEY_SSAVE	0624		/* shifted save key x */
#define	KEY_SSUSPEND	0625		/* shifted suspend key x */
#define	KEY_SUNDO	0626		/* shifted undo key x */
#define	KEY_SUSPEND	0627		/* suspend key x */
#define	KEY_UNDO	0630		/* undo key x */

#endif
