/*
- * Netris -- A free networked version of Tetris
- * Copyright (C) 1994,1995 Mark Weaver <Mark_Weaver@brown.edu>
+ * Netris -- A free networked version of T*tris
+ * Copyright (C) 1994-1996,1999 Mark H. Weaver <mhw@netris.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* 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"
#include <string.h>
#include <stdlib.h>
+#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
+
static void PlotBlock1(int scr, int y, int x, BlockType type);
static MyEventType KeyGenFunc(EventGenRec *gen, MyEvent *event);
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;
}
{
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)
static 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 > 0 ? "[]" : "$$");
+ standend();
}
}
ExtFunc void ShowDisplayInfo(void)
{
move(statusYPos - 9, statusXPos);
- printw("Seed = %d", initSeed);
+ printw("Seed: %d", initSeed);
clrtoeol();
move(statusYPos - 8, statusXPos);
- printw("Speed = %dms", speed / 1000);
+ printw("Speed: %dms", speed / 1000);
clrtoeol();
if (robotEnable) {
move(statusYPos - 6, statusXPos);
refresh();
}
+ExtFunc void ScheduleFullRedraw(void)
+{
+ touchwin(stdscr);
+}
+
static MyEventType KeyGenFunc(EventGenRec *gen, MyEvent *event)
{
if (MyRead(gen->fd, &event->u.key, 1))
return E_none;
}
+/*
+ * vi: ts=4 ai
+ * vim: noai si
+ */