2 * Netris -- A free networked version of T*tris
3 * Copyright (C) 1994,1995,1996 Mark H. Weaver <mhw@netris.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 * $Id: curses.c,v 1.32 1996/02/09 08:47:25 mhw Exp $
23 #include <sys/types.h>
29 static void PlotBlock1(int scr, int y, int x, BlockType type);
30 static MyEventType KeyGenFunc(EventGenRec *gen, MyEvent *event);
32 static EventGenRec keyGen =
33 { NULL, 0, FT_read, STDIN_FILENO, KeyGenFunc, EM_key };
35 static int boardYPos[MAX_SCREENS], boardXPos[MAX_SCREENS];
36 static int statusYPos, statusXPos;
38 static char *term_vi; /* String to make cursor invisible */
39 static char *term_ve; /* String to make cursor visible */
41 ExtFunc void InitScreens(void)
48 * Do this atomically. Otherwise a badly timed Ctrl-C during
49 * initialization will leave your terminal in a bad state.
51 BlockSignals(&oldMask, SIGINT, 0);
53 AtExit(CleanupScreens);
54 RestoreSignals(NULL, &oldMask);
58 OutputTermStr(term_vi, 0);
63 addstr(version_string);
64 addstr(" (C) 1994,1995,1996 Mark H. Weaver "
65 "\"netris -h\" for more info");
70 ExtFunc void CleanupScreens(void)
72 RemoveEventGen(&keyGen);
74 OutputTermStr(term_ve, 1);
77 ExtFunc void GetTermcapInfo(void)
79 char *term, *buf, *data;
82 if (!(term = getenv("TERM")))
84 if (tgetent(scratch, term) == 1) {
86 * Make the buffer HUGE, since tgetstr is unsafe.
87 * Allocate it on the heap too.
89 data = buf = malloc(bufSize);
92 * There is no standard include file for tgetstr, no prototype
93 * definitions. I like casting better than using my own prototypes
94 * because if I guess the prototype, I might be wrong, especially
95 * with regards to "const".
97 term_vi = (char *)tgetstr("vi", &data);
98 term_ve = (char *)tgetstr("ve", &data);
100 /* Okay, so I'm paranoid; I just don't like unsafe routines */
101 if (data > buf + bufSize)
102 fatal("tgetstr overflow, you must have a very sick termcap");
104 /* Trim off the unused portion of buffer */
105 buf = realloc(buf, data - buf);
109 * If that fails, use hardcoded vt220 codes.
110 * They don't seem to do anything bad on vt100's, so
111 * we'll try them just in case they work.
113 if (!term_vi || !term_ve) {
114 static char *vts[] = {
115 "vt100", "vt101", "vt102",
116 "vt200", "vt220", "vt300",
117 "vt320", "vt400", "vt420",
118 "screen", "xterm", NULL };
121 for (i = 0; vts[i]; i++)
122 if (!strcmp(term, vts[i]))
124 term_vi = "\033[?25l";
125 term_ve = "\033[?25h";
129 if (!term_vi || !term_ve)
130 term_vi = term_ve = NULL;
133 ExtFunc void OutputTermStr(char *str, int flush)
142 ExtFunc void InitScreen(int scr)
149 boardXPos[scr] = boardXPos[scr - 1] +
150 2 * boardWidth[scr - 1] + 3;
152 if (statusXPos < boardXPos[scr] + 2 * boardWidth[scr] + 3)
153 statusXPos = boardXPos[scr] + 2 * boardWidth[scr] + 3;
154 for (y = boardVisible[scr] - 1; y >= 0; --y) {
155 move(boardYPos[scr] - y, boardXPos[scr] - 1);
157 move(boardYPos[scr] - y, boardXPos[scr] + 2 * boardWidth[scr]);
160 for (y = boardVisible[scr]; y >= -1; y -= boardVisible[scr] + 1) {
161 move(boardYPos[scr] - y, boardXPos[scr] - 1);
163 for (x = boardWidth[scr] - 1; x >= 0; --x)
169 ExtFunc void CleanupScreen(int scr)
173 static void PlotBlock1(int scr, int y, int x, BlockType type)
175 move(boardYPos[scr] - y, boardXPos[scr] + 2 * x);
199 ExtFunc void PlotBlock(int scr, int y, int x, BlockType type)
201 if (y >= 0 && y < boardVisible[scr] && x >= 0 && x < boardWidth[scr])
202 PlotBlock1(scr, y, x, type);
205 ExtFunc void PlotUnderline(int scr, int x, int flag)
207 move(boardYPos[scr] + 1, boardXPos[scr] + 2 * x);
208 addstr(flag ? "==" : "--");
211 ExtFunc void ShowDisplayInfo(void)
213 move(statusYPos - 9, statusXPos);
214 printw("Seed: %d", initSeed);
216 move(statusYPos - 8, statusXPos);
217 printw("Speed: %dms", speed / 1000);
220 move(statusYPos - 6, statusXPos);
222 addstr("Controlled by a fair robot");
224 addstr("Controlled by a robot");
227 if (opponentFlags & SCF_usingRobot) {
228 move(statusYPos - 5, statusXPos);
229 if (opponentFlags & SCF_fairRobot)
230 addstr("The opponent is a fair robot");
232 addstr("The opponent is a robot");
237 ExtFunc void UpdateOpponentDisplay(void)
240 printw("Playing %s@%s", opponentName, opponentHost);
244 ExtFunc void ShowPause(int pausedByMe, int pausedByThem)
246 move(statusYPos - 3, statusXPos);
248 addstr("Game paused by opponent");
251 move(statusYPos - 2, statusXPos);
253 addstr("Game paused by you");
258 ExtFunc void Message(char *s)
262 move(statusYPos - 20 + line, statusXPos);
263 addstr(s); /* XXX Should truncate long lines */
265 line = (line + 1) % 10;
266 move(statusYPos - 20 + line, statusXPos);
270 ExtFunc void RefreshScreen(void)
272 static char timeStr[2][32];
276 strftime(timeStr[0], 30, "%I:%M %p", localtime(&theTime));
277 /* Just in case the local curses library sucks */
278 if (strcmp(timeStr[0], timeStr[1]))
280 move(statusYPos, statusXPos);
282 strcpy(timeStr[1], timeStr[0]);
284 move(boardYPos[0] + 1, boardXPos[0] + 2 * boardWidth[0] + 1);
288 ExtFunc void ScheduleFullRedraw(void)
293 static MyEventType KeyGenFunc(EventGenRec *gen, MyEvent *event)
295 if (MyRead(gen->fd, &event->u.key, 1))