/*
 * curses.h: a small curses for the fredygames.com browser builds (Emscripten). See README.md.
 *
 * The screen is a grid of cells (character, attributes, colour pair) in memory; refresh hands it to the
 * page (curses-web.js), which draws it on a canvas. getch waits for a key typed on the page, so programs
 * must be linked with -sASYNCIFY.
 *
 * Names and values follow ncurses 6 (no wide-character API; characters are Unicode code points in the
 * cells, and the API takes bytes, with UTF-8 decoded in the string functions).
 *
 * Copyright (C) 2026 FredyGames. Distributed under the MIT License (see LICENSE).
 */
#ifndef CURSES_WEB_H
#define CURSES_WEB_H

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

#ifdef __cplusplus
extern "C" {
#endif

typedef uint32_t chtype;
typedef chtype attr_t;
typedef chtype mmask_t;

#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define ERR (-1)
#define OK 0

/* ---- attributes (same layout as ncurses: char in the low 8 bits, colour pair in the next 8) ---- */
#define NCURSES_ATTR_SHIFT 8
#define NCURSES_BITS(mask, shift) ((chtype)(mask) << ((shift) + NCURSES_ATTR_SHIFT))
#define A_NORMAL 0U
#define A_ATTRIBUTES NCURSES_BITS(~(1U - 1U), 0)
#define A_CHARTEXT (NCURSES_BITS(1U, 0) - 1U)
#define A_COLOR NCURSES_BITS(((1U) << 8) - 1U, 0)
#define A_STANDOUT NCURSES_BITS(1U, 8)
#define A_UNDERLINE NCURSES_BITS(1U, 9)
#define A_REVERSE NCURSES_BITS(1U, 10)
#define A_BLINK NCURSES_BITS(1U, 11)
#define A_DIM NCURSES_BITS(1U, 12)
#define A_BOLD NCURSES_BITS(1U, 13)
#define A_ALTCHARSET NCURSES_BITS(1U, 14)
#define A_INVIS NCURSES_BITS(1U, 15)
#define A_PROTECT NCURSES_BITS(1U, 16)
#define A_HORIZONTAL NCURSES_BITS(1U, 17)
#define A_LEFT NCURSES_BITS(1U, 18)
#define A_LOW NCURSES_BITS(1U, 19)
#define A_RIGHT NCURSES_BITS(1U, 20)
#define A_TOP NCURSES_BITS(1U, 21)
#define A_VERTICAL NCURSES_BITS(1U, 22)
#define A_ITALIC NCURSES_BITS(1U, 23)
#define COLOR_PAIR(n) (((chtype)(n) << NCURSES_ATTR_SHIFT) & A_COLOR)
#define PAIR_NUMBER(a) (int)(((a) & A_COLOR) >> NCURSES_ATTR_SHIFT)

#define COLOR_BLACK 0
#define COLOR_RED 1
#define COLOR_GREEN 2
#define COLOR_YELLOW 3
#define COLOR_BLUE 4
#define COLOR_MAGENTA 5
#define COLOR_CYAN 6
#define COLOR_WHITE 7

/* ---- the window ---- */
typedef struct cw_cell {
    uint32_t ch;   /* Unicode code point */
    uint16_t attr; /* A_* >> 16 */
    uint8_t pair;
    uint8_t pad;
} cw_cell;

typedef struct _win_st WINDOW;
typedef struct cw_screen SCREEN;

struct _win_st {
    int _cury, _curx;     /* cursor, relative to the window */
    int _maxy, _maxx;     /* last row / column index (ncurses convention: size - 1) */
    int _begy, _begx;     /* top-left corner on the screen */
    chtype _attrs;        /* current attributes and colour pair */
    chtype _bkgd;
    int _delay;           /* getch timeout in ms: -1 wait, 0 nodelay */
    int _regtop, _regbottom;
    bool _scrollok, _leaveok, _clear, _use_keypad, _notimeout, _immed, _idlok, _sync;
    WINDOW *_parent;
    cw_cell *_cells;      /* (0,0) of the window; rows are _stride cells apart */
    int _stride;
    char *_touch;         /* one flag per row: changed since the last refresh */
    bool _owns_cells;
};

extern WINDOW *stdscr;
extern WINDOW *curscr;
extern WINDOW *newscr;
extern int LINES;
extern int COLS;
extern int COLORS;
extern int COLOR_PAIRS;
extern int TABSIZE;
extern int ESCDELAY;
extern chtype acs_map[128];

#define getcury(w) ((w)->_cury)
#define getcurx(w) ((w)->_curx)
#define getbegy(w) ((w)->_begy)
#define getbegx(w) ((w)->_begx)
#define getmaxy(w) ((w)->_maxy + 1)
#define getmaxx(w) ((w)->_maxx + 1)
#define getparx(w) ((w)->_parent ? (w)->_begx - (w)->_parent->_begx : -1)
#define getpary(w) ((w)->_parent ? (w)->_begy - (w)->_parent->_begy : -1)
#define getattrs(w) ((int)(w)->_attrs)
#define getyx(w, y, x) ((y) = (w)->_cury, (x) = (w)->_curx)
#define getbegyx(w, y, x) ((y) = (w)->_begy, (x) = (w)->_begx)
#define getmaxyx(w, y, x) ((y) = (w)->_maxy + 1, (x) = (w)->_maxx + 1)
#define getparyx(w, y, x) ((y) = getpary(w), (x) = getparx(w))

/* ---- keys (values as in ncurses) ---- */
#define KEY_CODE_YES 0400
#define KEY_MIN 0401
#define KEY_BREAK 0401
#define KEY_SRESET 0530
#define KEY_RESET 0531
#define KEY_DOWN 0402
#define KEY_UP 0403
#define KEY_LEFT 0404
#define KEY_RIGHT 0405
#define KEY_HOME 0406
#define KEY_BACKSPACE 0407
#define KEY_F0 0410
#define KEY_F(n) (KEY_F0 + (n))
#define KEY_DL 0510
#define KEY_IL 0511
#define KEY_DC 0512
#define KEY_IC 0513
#define KEY_EIC 0514
#define KEY_CLEAR 0515
#define KEY_EOS 0516
#define KEY_EOL 0517
#define KEY_SF 0520
#define KEY_SR 0521
#define KEY_NPAGE 0522
#define KEY_PPAGE 0523
#define KEY_STAB 0524
#define KEY_CTAB 0525
#define KEY_CATAB 0526
#define KEY_ENTER 0527
#define KEY_PRINT 0532
#define KEY_LL 0533
#define KEY_A1 0534
#define KEY_A3 0535
#define KEY_B2 0536
#define KEY_C1 0537
#define KEY_C3 0540
#define KEY_BTAB 0541
#define KEY_BEG 0542
#define KEY_CANCEL 0543
#define KEY_CLOSE 0544
#define KEY_COMMAND 0545
#define KEY_COPY 0546
#define KEY_CREATE 0547
#define KEY_END 0550
#define KEY_EXIT 0551
#define KEY_FIND 0552
#define KEY_HELP 0553
#define KEY_MARK 0554
#define KEY_MESSAGE 0555
#define KEY_MOVE 0556
#define KEY_NEXT 0557
#define KEY_OPEN 0560
#define KEY_OPTIONS 0561
#define KEY_PREVIOUS 0562
#define KEY_REDO 0563
#define KEY_REFERENCE 0564
#define KEY_REFRESH 0565
#define KEY_REPLACE 0566
#define KEY_RESTART 0567
#define KEY_RESUME 0570
#define KEY_SAVE 0571
#define KEY_SBEG 0572
#define KEY_SCANCEL 0573
#define KEY_SCOMMAND 0574
#define KEY_SCOPY 0575
#define KEY_SCREATE 0576
#define KEY_SDC 0577
#define KEY_SDL 0600
#define KEY_SELECT 0601
#define KEY_SEND 0602
#define KEY_SEOL 0603
#define KEY_SEXIT 0604
#define KEY_SFIND 0605
#define KEY_SHELP 0606
#define KEY_SHOME 0607
#define KEY_SIC 0610
#define KEY_SLEFT 0611
#define KEY_SMESSAGE 0612
#define KEY_SMOVE 0613
#define KEY_SNEXT 0614
#define KEY_SOPTIONS 0615
#define KEY_SPREVIOUS 0616
#define KEY_SPRINT 0617
#define KEY_SREDO 0620
#define KEY_SREPLACE 0621
#define KEY_SRIGHT 0622
#define KEY_SRSUME 0623
#define KEY_SSAVE 0624
#define KEY_SSUSPEND 0625
#define KEY_SUNDO 0626
#define KEY_SUSPEND 0627
#define KEY_UNDO 0630
#define KEY_MOUSE 0631
#define KEY_RESIZE 0632
#define KEY_EVENT 0633
#define KEY_MAX 0777

/* ---- ACS characters (translated to Unicode box drawing when written) ---- */
#define NCURSES_ACS(c) (acs_map[(unsigned char)(c)])
#define ACS_ULCORNER NCURSES_ACS('l')
#define ACS_LLCORNER NCURSES_ACS('m')
#define ACS_URCORNER NCURSES_ACS('k')
#define ACS_LRCORNER NCURSES_ACS('j')
#define ACS_LTEE NCURSES_ACS('t')
#define ACS_RTEE NCURSES_ACS('u')
#define ACS_BTEE NCURSES_ACS('v')
#define ACS_TTEE NCURSES_ACS('w')
#define ACS_HLINE NCURSES_ACS('q')
#define ACS_VLINE NCURSES_ACS('x')
#define ACS_PLUS NCURSES_ACS('n')
#define ACS_S1 NCURSES_ACS('o')
#define ACS_S9 NCURSES_ACS('s')
#define ACS_DIAMOND NCURSES_ACS('`')
#define ACS_CKBOARD NCURSES_ACS('a')
#define ACS_DEGREE NCURSES_ACS('f')
#define ACS_PLMINUS NCURSES_ACS('g')
#define ACS_BULLET NCURSES_ACS('~')
#define ACS_LARROW NCURSES_ACS(',')
#define ACS_RARROW NCURSES_ACS('+')
#define ACS_DARROW NCURSES_ACS('.')
#define ACS_UARROW NCURSES_ACS('-')
#define ACS_BOARD NCURSES_ACS('h')
#define ACS_LANTERN NCURSES_ACS('i')
#define ACS_BLOCK NCURSES_ACS('0')
#define ACS_LEQUAL NCURSES_ACS('y')
#define ACS_GEQUAL NCURSES_ACS('z')
#define ACS_PI NCURSES_ACS('{')
#define ACS_NEQUAL NCURSES_ACS('|')
#define ACS_STERLING NCURSES_ACS('}')

/* ---- initialisation and modes ---- */
WINDOW *initscr(void);
SCREEN *newterm(const char *type, FILE *outfd, FILE *infd);
SCREEN *set_term(SCREEN *screen);
int endwin(void);
bool isendwin(void);
int cbreak(void);
int nocbreak(void);
int raw(void);
int noraw(void);
int echo(void);
int noecho(void);
int nl(void);
int nonl(void);
int halfdelay(int tenths);
int keypad(WINDOW *win, bool enable);
int meta(WINDOW *win, bool enable);
int intrflush(WINDOW *win, bool enable);
int nodelay(WINDOW *win, bool enable);
int notimeout(WINDOW *win, bool enable);
void timeout(int ms);
void wtimeout(WINDOW *win, int ms);
int typeahead(int fd);
int qiflush(void);
void noqiflush(void);
int curs_set(int visibility);
int set_escdelay(int ms);
int def_prog_mode(void);
int def_shell_mode(void);
int reset_prog_mode(void);
int reset_shell_mode(void);
#define savetty() ((void)0)
#define resetty() ((void)0)
int use_env(bool);
void filter(void);
char erasechar(void);
char killchar(void);
int baudrate(void);
char *longname(void);
char *termname(void);
bool has_ic(void);
bool has_il(void);
int napms(int ms);
#define delay_output(ms) napms(ms)
int beep(void);
int flash(void);
int ripoffline(int line, int (*init)(WINDOW *, int));

/* ---- colour ---- */
bool has_colors(void);
bool can_change_color(void);
int start_color(void);
int use_default_colors(void);
int assume_default_colors(int fg, int bg);
int init_pair(short pair, short fg, short bg);
int pair_content(short pair, short *fg, short *bg);
int init_color(short color, short r, short g, short b); /* r, g, b in 0..1000 */
int color_content(short color, short *r, short *g, short *b);
int color_set(short pair, void *opts);
int wcolor_set(WINDOW *win, short pair, void *opts);

/* ---- windows ---- */
WINDOW *newwin(int nlines, int ncols, int begin_y, int begin_x);
WINDOW *subwin(WINDOW *orig, int nlines, int ncols, int begin_y, int begin_x);
WINDOW *derwin(WINDOW *orig, int nlines, int ncols, int begin_y, int begin_x);
WINDOW *dupwin(WINDOW *win);
int delwin(WINDOW *win);
int mvwin(WINDOW *win, int y, int x);
int mvderwin(WINDOW *win, int par_y, int par_x);
int wresize(WINDOW *win, int lines, int columns);
int resizeterm(int lines, int columns);
int resize_term(int lines, int columns);
bool is_term_resized(int lines, int columns);
int overlay(const WINDOW *src, WINDOW *dst);
int overwrite(const WINDOW *src, WINDOW *dst);
int copywin(const WINDOW *src, WINDOW *dst, int sminrow, int smincol, int dminrow, int dmincol,
            int dmaxrow, int dmaxcol, int overlay);
int touchwin(WINDOW *win);
int untouchwin(WINDOW *win);
int touchline(WINDOW *win, int start, int count);
int wtouchln(WINDOW *win, int y, int n, int changed);
bool is_wintouched(WINDOW *win);
bool is_linetouched(WINDOW *win, int line);
int redrawwin(WINDOW *win);
int wredrawln(WINDOW *win, int beg_line, int num_lines);
int clearok(WINDOW *win, bool bf);
int leaveok(WINDOW *win, bool bf);
int scrollok(WINDOW *win, bool bf);
int idlok(WINDOW *win, bool bf);
void idcok(WINDOW *win, bool bf);
void immedok(WINDOW *win, bool bf);
int syncok(WINDOW *win, bool bf);
void wsyncup(WINDOW *win);
void wsyncdown(WINDOW *win);
void wcursyncup(WINDOW *win);
int setscrreg(int top, int bot);
int wsetscrreg(WINDOW *win, int top, int bot);

/* ---- output ---- */
int wmove(WINDOW *win, int y, int x);
int waddch(WINDOW *win, const chtype ch);
int wechochar(WINDOW *win, const chtype ch);
int waddchnstr(WINDOW *win, const chtype *chstr, int n);
int waddnstr(WINDOW *win, const char *str, int n);
int wprintw(WINDOW *win, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
int vw_printw(WINDOW *win, const char *fmt, va_list ap);
int vwprintw(WINDOW *win, const char *fmt, va_list ap);
int winsch(WINDOW *win, chtype ch);
int winsnstr(WINDOW *win, const char *str, int n);
int wdelch(WINDOW *win);
int winsdelln(WINDOW *win, int n);
int winsertln(WINDOW *win);
int wdeleteln(WINDOW *win);
int wclear(WINDOW *win);
int werase(WINDOW *win);
int wclrtoeol(WINDOW *win);
int wclrtobot(WINDOW *win);
int wscrl(WINDOW *win, int n);
int wborder(WINDOW *win, chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, chtype tr, chtype bl, chtype br);
int box(WINDOW *win, chtype verch, chtype horch);
int whline(WINDOW *win, chtype ch, int n);
int wvline(WINDOW *win, chtype ch, int n);
int wattr_on(WINDOW *win, attr_t attrs, void *opts);
int wattr_off(WINDOW *win, attr_t attrs, void *opts);
int wattr_set(WINDOW *win, attr_t attrs, short pair, void *opts);
int wattr_get(WINDOW *win, attr_t *attrs, short *pair, void *opts);
int wattron(WINDOW *win, int attrs);
int wattroff(WINDOW *win, int attrs);
int wattrset(WINDOW *win, int attrs);
int wstandout(WINDOW *win);
int wstandend(WINDOW *win);
int wbkgd(WINDOW *win, chtype ch);
void wbkgdset(WINDOW *win, chtype ch);
chtype getbkgd(WINDOW *win);

/* ---- input ---- */
int wgetch(WINDOW *win);
int ungetch(int ch);
int has_key(int ch);
int wgetnstr(WINDOW *win, char *str, int n);
int flushinp(void);
chtype winch(WINDOW *win);
int winchnstr(WINDOW *win, chtype *chstr, int n);
int winnstr(WINDOW *win, char *str, int n);

/* ---- refresh ---- */
int wrefresh(WINDOW *win);
int wnoutrefresh(WINDOW *win);
int doupdate(void);

/* ---- misc ---- */
const char *unctrl(chtype c);
const char *keyname(int c);

/* mouse: accepted and ignored (no mouse events are generated) */
typedef struct {
    short id;
    int x, y, z;
    mmask_t bstate;
} MEVENT;
mmask_t mousemask(mmask_t newmask, mmask_t *oldmask);
int getmouse(MEVENT *event);
int ungetmouse(MEVENT *event);
int mouseinterval(int erval);
bool has_mouse(void);

/* ---- the stdscr / mv* forms, as macros like ncurses ---- */
#define getch() wgetch(stdscr)
#define mvgetch(y, x) (wmove(stdscr, (y), (x)) == ERR ? ERR : wgetch(stdscr))
#define mvwgetch(w, y, x) (wmove((w), (y), (x)) == ERR ? ERR : wgetch(w))
#define getnstr(s, n) wgetnstr(stdscr, (s), (n))
#define getstr(s) wgetnstr(stdscr, (s), 1023)
#define wgetstr(w, s) wgetnstr((w), (s), 1023)
#define mvgetnstr(y, x, s, n) (wmove(stdscr, (y), (x)) == ERR ? ERR : wgetnstr(stdscr, (s), (n)))
#define mvgetstr(y, x, s) mvgetnstr((y), (x), (s), 1023)
#define mvwgetnstr(w, y, x, s, n) (wmove((w), (y), (x)) == ERR ? ERR : wgetnstr((w), (s), (n)))
#define mvwgetstr(w, y, x, s) mvwgetnstr((w), (y), (x), (s), 1023)

#define move(y, x) wmove(stdscr, (y), (x))
#define addch(c) waddch(stdscr, (c))
#define mvaddch(y, x, c) (wmove(stdscr, (y), (x)) == ERR ? ERR : waddch(stdscr, (c)))
#define mvwaddch(w, y, x, c) (wmove((w), (y), (x)) == ERR ? ERR : waddch((w), (c)))
#define echochar(c) wechochar(stdscr, (c))
#define addchstr(s) waddchnstr(stdscr, (s), -1)
#define addchnstr(s, n) waddchnstr(stdscr, (s), (n))
#define waddchstr(w, s) waddchnstr((w), (s), -1)
#define mvaddchstr(y, x, s) (wmove(stdscr, (y), (x)) == ERR ? ERR : waddchnstr(stdscr, (s), -1))
#define mvwaddchstr(w, y, x, s) (wmove((w), (y), (x)) == ERR ? ERR : waddchnstr((w), (s), -1))
#define addstr(s) waddnstr(stdscr, (s), -1)
#define addnstr(s, n) waddnstr(stdscr, (s), (n))
#define waddstr(w, s) waddnstr((w), (s), -1)
#define mvaddstr(y, x, s) (wmove(stdscr, (y), (x)) == ERR ? ERR : waddnstr(stdscr, (s), -1))
#define mvaddnstr(y, x, s, n) (wmove(stdscr, (y), (x)) == ERR ? ERR : waddnstr(stdscr, (s), (n)))
#define mvwaddstr(w, y, x, s) (wmove((w), (y), (x)) == ERR ? ERR : waddnstr((w), (s), -1))
#define mvwaddnstr(w, y, x, s, n) (wmove((w), (y), (x)) == ERR ? ERR : waddnstr((w), (s), (n)))
#define printw(...) wprintw(stdscr, __VA_ARGS__)
#define mvprintw(y, x, ...) (wmove(stdscr, (y), (x)) == ERR ? ERR : wprintw(stdscr, __VA_ARGS__))
#define mvwprintw(w, y, x, ...) (wmove((w), (y), (x)) == ERR ? ERR : wprintw((w), __VA_ARGS__))
#define insch(c) winsch(stdscr, (c))
#define mvinsch(y, x, c) (wmove(stdscr, (y), (x)) == ERR ? ERR : winsch(stdscr, (c)))
#define mvwinsch(w, y, x, c) (wmove((w), (y), (x)) == ERR ? ERR : winsch((w), (c)))
#define insstr(s) winsnstr(stdscr, (s), -1)
#define insnstr(s, n) winsnstr(stdscr, (s), (n))
#define winsstr(w, s) winsnstr((w), (s), -1)
#define delch() wdelch(stdscr)
#define mvdelch(y, x) (wmove(stdscr, (y), (x)) == ERR ? ERR : wdelch(stdscr))
#define mvwdelch(w, y, x) (wmove((w), (y), (x)) == ERR ? ERR : wdelch(w))
#define insertln() winsertln(stdscr)
#define deleteln() wdeleteln(stdscr)
#define insdelln(n) winsdelln(stdscr, (n))
#define clear() wclear(stdscr)
#define erase() werase(stdscr)
#define clrtoeol() wclrtoeol(stdscr)
#define clrtobot() wclrtobot(stdscr)
#define scrl(n) wscrl(stdscr, (n))
#define scroll(w) wscrl((w), 1)
#define border(ls, rs, ts, bs, tl, tr, bl, br) wborder(stdscr, (ls), (rs), (ts), (bs), (tl), (tr), (bl), (br))
#define hline(c, n) whline(stdscr, (c), (n))
#define vline(c, n) wvline(stdscr, (c), (n))
#define mvhline(y, x, c, n) (wmove(stdscr, (y), (x)) == ERR ? ERR : whline(stdscr, (c), (n)))
#define mvvline(y, x, c, n) (wmove(stdscr, (y), (x)) == ERR ? ERR : wvline(stdscr, (c), (n)))
#define mvwhline(w, y, x, c, n) (wmove((w), (y), (x)) == ERR ? ERR : whline((w), (c), (n)))
#define mvwvline(w, y, x, c, n) (wmove((w), (y), (x)) == ERR ? ERR : wvline((w), (c), (n)))
#define inch() winch(stdscr)
#define mvinch(y, x) (wmove(stdscr, (y), (x)) == ERR ? (chtype)ERR : winch(stdscr))
#define mvwinch(w, y, x) (wmove((w), (y), (x)) == ERR ? (chtype)ERR : winch(w))
#define innstr(s, n) winnstr(stdscr, (s), (n))
#define instr(s) winnstr(stdscr, (s), -1)
#define winstr(w, s) winnstr((w), (s), -1)
#define mvinnstr(y, x, s, n) (wmove(stdscr, (y), (x)) == ERR ? ERR : winnstr(stdscr, (s), (n)))
#define mvinstr(y, x, s) mvinnstr((y), (x), (s), -1)
#define mvwinnstr(w, y, x, s, n) (wmove((w), (y), (x)) == ERR ? ERR : winnstr((w), (s), (n)))
#define mvwinstr(w, y, x, s) mvwinnstr((w), (y), (x), (s), -1)
#define inchnstr(s, n) winchnstr(stdscr, (s), (n))
#define inchstr(s) winchnstr(stdscr, (s), -1)
#define refresh() wrefresh(stdscr)

#define attron(a) wattron(stdscr, (a))
#define attroff(a) wattroff(stdscr, (a))
#define attrset(a) wattrset(stdscr, (a))
#define attr_on(a, o) wattr_on(stdscr, (a), (o))
#define attr_off(a, o) wattr_off(stdscr, (a), (o))
#define attr_set(a, p, o) wattr_set(stdscr, (a), (p), (o))
#define attr_get(a, p, o) wattr_get(stdscr, (a), (p), (o))
#define standout() wstandout(stdscr)
#define standend() wstandend(stdscr)
#define bkgd(c) wbkgd(stdscr, (c))
#define bkgdset(c) wbkgdset(stdscr, (c))
#define mvcur(oy, ox, ny, nx) wmove(stdscr, (ny), (nx))


/* ---- additions for the browser build (see README.md) ---- */

/* Sets how arrow keys are delivered to windows without keypad(): `keys` has 8 entries (up, down, left,
 * right, home, end, page up, page down), default "kjhlybun"... see README. NULL restores the default. */
void cw_set_nokeypad_keys(const char *keys);
/* Writes `len` bytes of text with ANSI/VT100 escape sequences to stdscr (cursor, colours, erase, scroll),
 * for programs that talk to a terminal directly (termcap). Call cw_ansi_flush() to show the result. */
void cw_ansi_write(const char *s, int len);
void cw_ansi_flush(void);
void cw_ansi_reset(void);
/* While on, what the program writes to stdout is interpreted like cw_ansi_write (and flushed at every newline and
 * before waiting for a key); tgetent() turns it on. After endwin() it is always on. */
void cw_ansi_stdout(int on);
/* Waits up to `ms` milliseconds (-1 forever) for a key and returns its curses code or ERR; the same
 * queue as getch(), usable without initscr() (termcap programs). */
int cw_getkey(int ms);
/* Waits up to `ms` milliseconds (-1 forever) until a key is waiting, without taking it (a select() on stdin):
 * returns 1 if there is one, 0 on timeout; getch() then returns it at once. */
int cw_wait_input(int ms);

#ifdef __cplusplus
}
#endif

#endif /* CURSES_WEB_H */
