X-Git-Url: http://git.shiar.net/netris.git/blobdiff_plain/c11ae0d113cc5f60bfd1bed29b47211013f8adef..776faa936ea4b3f5ccaacda0f05a2ed1e945d304:/curses.c diff --git a/curses.c b/curses.c index 2d93900..9649d85 100644 --- a/curses.c +++ b/curses.c @@ -1,6 +1,6 @@ /* - * Netris -- A free networked version of Tetris - * Copyright (C) 1994,1995 Mark Weaver + * Netris -- A free networked version of T*tris + * Copyright (C) 1994-1996,1999 Mark H. Weaver * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: curses.c,v 1.29 1995/07/11 08:53:21 mhw Exp $ + * $Id: curses.c,v 1.33 1999/05/16 06:56:25 mhw Exp $ */ #include "netris.h" @@ -26,7 +26,29 @@ #include #include -static void PlotBlock1(int scr, int y, int x, BlockType type); +#ifdef NCURSES_VERSION +# define HAVE_NCURSES +#endif + +#ifdef HAVE_NCURSES +static struct +{ + BlockType type; + short color; +} myColorTable[] = +{ + { BT_white, COLOR_WHITE }, + { BT_blue, COLOR_BLUE }, + { BT_magenta, COLOR_MAGENTA }, + { BT_cyan, COLOR_CYAN }, + { BT_yellow, COLOR_YELLOW }, + { BT_green, COLOR_GREEN }, + { BT_red, COLOR_RED }, + { BT_none, 0 } +}; +#endif + +ExtFunc void PlotBlock1(int scr, int y, int x, BlockType type); static MyEventType KeyGenFunc(EventGenRec *gen, MyEvent *event); static EventGenRec keyGen = @@ -34,23 +56,60 @@ static EventGenRec keyGen = static int boardYPos[MAX_SCREENS], boardXPos[MAX_SCREENS]; static int statusYPos, statusXPos; +static int haveColor; + +static char *term_vi; /* String to make cursor invisible */ +static char *term_ve; /* String to make cursor visible */ ExtFunc void InitScreens(void) { MySigSet oldMask; + GetTermcapInfo(); + + /* + * Block signals while initializing curses. Otherwise a badly timed + * Ctrl-C during initialization might leave the terminal in a bad state. + */ BlockSignals(&oldMask, SIGINT, 0); initscr(); + +#ifdef CURSES_HACK + { + extern char *CS; + + CS = 0; + } +#endif + +#ifdef HAVE_NCURSES + haveColor = colorEnable && has_colors(); + if (haveColor) + { + int i = 0; + + start_color(); + for (i = 0; myColorTable[i].type != BT_none; ++i) + init_pair(myColorTable[i].type, COLOR_BLACK, + myColorTable[i].color); + } +#else + haveColor = 0; +#endif + AtExit(CleanupScreens); RestoreSignals(NULL, &oldMask); + cbreak(); noecho(); + OutputTermStr(term_vi, 0); AddEventGen(&keyGen); + move(0, 0); addstr("Netris "); addstr(version_string); - addstr(" (C) 1994,1995 Mark Weaver " - "\"netris -h\" for more info"); + addstr(" (C) 1994-1996,1999 Mark H. Weaver " + "\"netris -h\" for more info"); statusYPos = 22; statusXPos = 0; } @@ -59,6 +118,72 @@ ExtFunc void CleanupScreens(void) { RemoveEventGen(&keyGen); endwin(); + OutputTermStr(term_ve, 1); +} + +ExtFunc void GetTermcapInfo(void) +{ + char *term, *buf, *data; + int bufSize = 10240; + + if (!(term = getenv("TERM"))) + return; + if (tgetent(scratch, term) == 1) { + /* + * Make the buffer HUGE, since tgetstr is unsafe. + * Allocate it on the heap too. + */ + data = buf = malloc(bufSize); + + /* + * There is no standard include file for tgetstr, no prototype + * definitions. I like casting better than using my own prototypes + * because if I guess the prototype, I might be wrong, especially + * with regards to "const". + */ + term_vi = (char *)tgetstr("vi", &data); + term_ve = (char *)tgetstr("ve", &data); + + /* Okay, so I'm paranoid; I just don't like unsafe routines */ + if (data > buf + bufSize) + fatal("tgetstr overflow, you must have a very sick termcap"); + + /* Trim off the unused portion of buffer */ + buf = realloc(buf, data - buf); + } + + /* + * If that fails, use hardcoded vt220 codes. + * They don't seem to do anything bad on vt100's, so + * we'll try them just in case they work. + */ + if (!term_vi || !term_ve) { + static char *vts[] = { + "vt100", "vt101", "vt102", + "vt200", "vt220", "vt300", + "vt320", "vt400", "vt420", + "screen", "xterm", NULL }; + int i; + + for (i = 0; vts[i]; i++) + if (!strcmp(term, vts[i])) + { + term_vi = "\033[?25l"; + term_ve = "\033[?25h"; + break; + } + } + if (!term_vi || !term_ve) + term_vi = term_ve = NULL; +} + +ExtFunc void OutputTermStr(char *str, int flush) +{ + if (str) { + fputs(str, stdout); + if (flush) + fflush(stdout); + } } ExtFunc void InitScreen(int scr) @@ -70,9 +195,12 @@ ExtFunc void InitScreen(int scr) else boardXPos[scr] = boardXPos[scr - 1] + 2 * boardWidth[scr - 1] + 3; + if (scr == 1) + boardXPos[scr] += 24; boardYPos[scr] = 22; - if (statusXPos < boardXPos[scr] + 2 * boardWidth[scr] + 3) - statusXPos = boardXPos[scr] + 2 * boardWidth[scr] + 3; + statusXPos = 2 * boardWidth[0] + 3; +// if (statusXPos < boardXPos[scr] + 2 * boardWidth[scr] + 3) +// statusXPos = boardXPos[scr] + 2 * boardWidth[scr] + 3; for (y = boardVisible[scr] - 1; y >= 0; --y) { move(boardYPos[scr] - y, boardXPos[scr] - 1); addch('|'); @@ -92,29 +220,28 @@ ExtFunc void CleanupScreen(int scr) { } -static void PlotBlock1(int scr, int y, int x, BlockType type) +ExtFunc void PlotBlock1(int scr, int y, int x, BlockType type) { + int colorIndex = abs(type); + move(boardYPos[scr] - y, boardXPos[scr] + 2 * x); - switch (type) { - case BT_none: - addstr(" "); - break; - case -BT_piece1: - if (standoutEnable) - standout(); - addstr("$$"); - if (standoutEnable) - standend(); - break; - case BT_piece1: - if (standoutEnable) + + if (type == BT_none) + addstr(" "); + else + { + if (standoutEnable) + { +#ifdef HAVE_NCURSES + if (haveColor) + attrset(COLOR_PAIR(colorIndex)); + else +#endif standout(); - addstr("[]"); - if (standoutEnable) - standend(); - break; - default: - assert(0); + } + + addstr(type ? "[]" : "$$"); + standend(); } } @@ -133,18 +260,16 @@ ExtFunc void PlotUnderline(int scr, int x, int flag) ExtFunc void ShowDisplayInfo(void) { move(statusYPos - 9, statusXPos); - printw("Seed = %d", initSeed); - clrtoeol(); + printw("Seed: %010d", initSeed); move(statusYPos - 8, statusXPos); - printw("Speed = %dms", speed / 1000); - clrtoeol(); + printw("Speed: %dms ", speed / 1000); if (robotEnable) { move(statusYPos - 6, statusXPos); if (fairRobot) addstr("Controlled by a fair robot"); else addstr("Controlled by a robot"); - clrtoeol(); +// clrtoeol(); } if (opponentFlags & SCF_usingRobot) { move(statusYPos - 5, statusXPos); @@ -152,10 +277,29 @@ ExtFunc void ShowDisplayInfo(void) addstr("The opponent is a fair robot"); else addstr("The opponent is a robot"); - clrtoeol(); +// clrtoeol(); } } +ExtFunc void ShowScore(int scr, int totalDrops, int totalLines, int totalAdds) +{ + float timer; + move(6, statusXPos); addstr("Next: "); + move(7, statusXPos + 6); addstr(" "); + ShapeIterate(nextShape[scr], scr, + ShapeToNetNum(nextShape[scr]) == 15 ? 15 : 16, statusXPos/2 + 4, + 1, GlanceFunc, NULL); + move(statusYPos - 20 + 1, statusXPos); + timer = CurTimeval() / 1e6; + printw("Lines: %05d", totalLines); + if (timer > 4) + printw(" (%.1f ppm)", totalDrops * 60 / timer); + move(statusYPos - 18, statusXPos); + printw("apm: %.1f", totalAdds * 60 / timer); + if (totalLines > 0) + printw(" (%d%% yield) ", 100 * totalAdds / totalLines); +} + ExtFunc void UpdateOpponentDisplay(void) { move(1, 0); @@ -169,34 +313,37 @@ ExtFunc void ShowPause(int pausedByMe, int pausedByThem) if (pausedByThem) addstr("Game paused by opponent"); else - clrtoeol(); + addstr(" "); move(statusYPos - 2, statusXPos); if (pausedByMe) addstr("Game paused by you"); else - clrtoeol(); + addstr(" "); } ExtFunc void Message(char *s) { static int line = 0; - move(statusYPos - 20 + line, statusXPos); +// move(statusYPos - 20 + line, statusXPos); + move(statusYPos + 2 + line, 1); addstr(s); /* XXX Should truncate long lines */ clrtoeol(); line = (line + 1) % 10; - move(statusYPos - 20 + line, statusXPos); +// move(statusYPos - 20 + line, statusXPos); + move(statusYPos + 2 + line, 1); clrtoeol(); } ExtFunc void RefreshScreen(void) { +/* static char timeStr[2][32]; time_t theTime; time(&theTime); strftime(timeStr[0], 30, "%I:%M %p", localtime(&theTime)); - /* Just in case the local curses library sucks */ + // Just in case the local curses library sucks if (strcmp(timeStr[0], timeStr[1])) { move(statusYPos, statusXPos); @@ -205,6 +352,16 @@ ExtFunc void RefreshScreen(void) } move(boardYPos[0] + 1, boardXPos[0] + 2 * boardWidth[0] + 1); refresh(); +*/ + move(statusYPos, statusXPos); + printw("Timer: %.0f ", CurTimeval() / 1e6); + move(boardYPos[0] + 1, boardXPos[0] + 2 * boardWidth[0] + 1); + refresh(); +} + +ExtFunc void ScheduleFullRedraw(void) +{ + touchwin(stdscr); } static MyEventType KeyGenFunc(EventGenRec *gen, MyEvent *event) @@ -215,3 +372,7 @@ static MyEventType KeyGenFunc(EventGenRec *gen, MyEvent *event) return E_none; } +/* + * vi: ts=4 ai + * vim: noai si + */