4 * Copyright (c) 1997 Ben Harrison, and others
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies.
11 /* Purpose: Allow use of Unix "curses" with Angband -BEN- */
14 * This file has been modified to use multiple text windows if your screen
15 * is larger than 80x25. By Keldon Jones (keldon@umr.edu).
17 * Also included is Keldon Jones patch to get better colors. To switch to
18 * a term that supports this, see this posting:
20 * From keldon@umr.edu Thu Apr 01 05:40:14 1999
21 * Sender: KELDON JONES <keldon@saucer.cc.umr.edu>
22 * From: Keldon Jones <keldon@umr.edu>
23 * Subject: Re: Linux colour prob (Or: question for Greg)
24 * Newsgroups: rec.games.roguelike.angband
25 * References: <slrn7g1jlp.gj9.scarblac-spamtrap@flits104-37.flits.rug.nl> <3700f96b.1593384@news.polsl.gliwice.pl> <slrn7g36er.fm4.wooledge@jekyll.local>
26 * X-Newsreader: TIN [UNIX 1.3 unoff BETA 970625; 9000/780 HP-UX B.10.20]
27 * NNTP-Posting-Host: saucer.cc.umr.edu
28 * X-NNTP-Posting-Host: saucer.cc.umr.edu
29 * Message-ID: <370306be.0@news.cc.umr.edu>
30 * Date: 1 Apr 99 05:40:14 GMT
31 * Organization: University of Missouri - Rolla
33 * Path: xs4all!xs4all!newsfeed.wirehub.nl!news-peer.gip.net!news.gsl.net!gip.net!news.he.net!mercury.cts.com!alpha.sky.net!news.missouri.edu!news.cc.umr.edu!not-for-mail
34 * Xref: xs4all rec.games.roguelike.angband:86332
36 * Greg Wooledge <wooledge@kellnet.com> wrote:
37 * > Gwidon S. Naskrent (naskrent@artemida.amu.edu.pl) wrote:
39 * > >On 30 Mar 1999 13:17:18 GMT, scarblac-spamtrap@pino.selwerd.cx (Remco
42 * > >>I recently switched to Linux, and *bands work fine. I like
43 * > >>to play them in consoles, not in X. However, colour is wrong.
44 * > >>"Slate" and "light slate" are always light blue, instead
45 * > >>of some shade of grey. Colours are fine in X.
47 * > I actually noticed the Linux console color issue a very long time ago,
48 * > but since I always play under X, I never really investigated it.
50 * > You're absolutely right, though -- the Linux console colors are not
51 * > "right" for Angband.
53 * I've noticed this myself, so I spent the evening fixing it.
54 * Well, sorta fixing it. It's not perfect yet, and it may not be
55 * possible to get it perfect with VGA hardware and/or the current
58 * > OK, reading on in terminfo(5):
61 * > Most color terminals are either `Tektronix-like' or `HP-
62 * > like'. Tektronix-like terminals have a predefined set of
63 * > N colors (where N usually 8), and can set character-cell
64 * > foreground and background characters independently, mixing
65 * > them into N * N color-pairs. On HP-like terminals, the
66 * > use must set each color pair up separately (foreground and
67 * > background are not independently settable). Up to M
68 * > color-pairs may be set up from 2*M different colors.
69 * > ANSI-compatible terminals are Tektronix-like.
71 * > The "linux" terminfo entry is definitely in the "Tektronix-like" family.
72 * > It has the "setaf" and "setab" capabilities for setting the foreground
73 * > and background colors to one of 8 basically hard-coded values:
75 * > Color #define Value RGB
76 * > black COLOR_BLACK 0 0, 0, 0
77 * > red COLOR_RED 1 max,0,0
78 * > green COLOR_GREEN 2 0,max,0
79 * > yellow COLOR_YELLOW 3 max,max,0
80 * > blue COLOR_BLUE 4 0,0,max
81 * > magenta COLOR_MAGENTA 5 max,0,max
82 * > cyan COLOR_CYAN 6 0,max,max
83 * > white COLOR_WHITE 7 max,max,max
85 * Well, not quite. Using certain escape sequences, an
86 * application (or better yet, curses) can redefine the colors (at
87 * least some of them) and then those are used. Read the
88 * curs_color manpage, and the part about "ccc" and "initc" in the
89 * terminfo manpage. This is what the part of main-gcu inside the
90 * "if (can_fix_color)" code does.
92 * > So, what does this mean to the Angband player? Well, it means that
93 * > either there's nothing you can do about the console colors as long as
94 * > straight curses/ncurses is used, or if there is something to be done,
95 * > I'm not clever enough to figure out how to do it.
97 * Well, it is possible, though you have to patch main-gcu
98 * and edit a terminfo entry. Apparently the relevant code in
99 * main-gcu was never tested (it's broken in at least one major
100 * way). Apply the patch at the end of this message (notice that
101 * we need to define REDEFINE_COLORS at some point near the
102 * beginning of the file).
103 * Next, write this termcap entry to a file:
105 * linux-c|linux console 1.3.6+ with private palette for each virtual console,
107 * colors#16, pairs#64,
108 * initc=\E]P%x%p1%{16}%/%02x%p1%{16}%/%02x%p1%{16}%/%02x,
112 * and run "tic" on it to produce a new terminfo entry called
113 * "linux-c". Especially note the "ccc" flag which says that we
114 * can redefine colors. The ugly "initc" string is what tells
115 * the console how to redefine a color. Now, just set your TERM
116 * variable to "linux-c" and try Angband again. If I've
117 * remembered to tell you everything that I've done, you should
118 * get the weird light-blue slate changed to a gray.
119 * Now, there are still lots of problems with this.
120 * Something (I don't think it's curses, either the kernel or
121 * the hardware itself) seems to be ignoring my color changes to
122 * colors 6 and 7, which is annoying. Also, the normal "white"
123 * color is now way too bright, but it's now necessary to
124 * distinguish it from the other grays.
125 * The kernel seems to support 16 colors, but you can
126 * only switch to 8 of those, due to VT102 compatibility, it
127 * seems. I think it would be possible to patch the kernel and
128 * allow all 16 colors to be used, but I haven't built up the
129 * nerve to try that yet.
130 * Let me know if you can improve on this any. Some of
131 * this may actually work differently on other hardware (ugh).
138 * To use this file, you must define "USE_GCU" in the Makefile.
140 * Hack -- note that "angband.h" is included AFTER the #ifdef test.
141 * This was necessary because of annoying "curses.h" silliness.
143 * Note that this file is not "intended" to support non-Unix machines,
144 * nor is it intended to support VMS or other bizarre setups.
146 * Also, this package assumes that the underlying "curses" handles both
147 * the "nonl()" and "cbreak()" commands correctly, see the "OPTION" below.
149 * This code should work with most versions of "curses" or "ncurses",
150 * and the "main-ncu.c" file (and USE_NCU define) are no longer used.
152 * See also "USE_CAP" and "main-cap.c" for code that bypasses "curses"
153 * and uses the "termcap" information directly, or even bypasses the
154 * "termcap" information and sends direct vt100 escape sequences.
156 * XXX XXX XXX Consider the use of "savetty()" and "resetty()".
165 * Hack -- play games with "bool"
170 * Include the proper "header" file
174 # include <ncurses.h>
179 typedef struct term_data term_data;
188 #define MAX_TERM_DATA 4
190 static term_data data[MAX_TERM_DATA];
194 * Hack -- try to guess which systems use what commands
195 * Hack -- allow one of the "USE_Txxxxx" flags to be pre-set.
196 * Mega-Hack -- try to guess when "POSIX" is available.
197 * If the user defines two of these, we will probably crash.
199 #if !defined(USE_TPOSIX)
200 # if !defined(USE_TERMIO) && !defined(USE_TCHARS)
201 # if defined(_POSIX_VERSION)
204 # if defined(USG) || defined(linux) || defined(SOLARIS)
214 * Hack -- Amiga uses "fake curses" and cannot do any of this stuff
223 * Try redefining the colors at startup.
225 #define REDEFINE_COLORS
233 # include <sys/ioctl.h>
234 # include <termios.h>
238 * One version needs this file
241 # include <sys/ioctl.h>
246 * The other needs this file
249 # include <sys/ioctl.h>
250 # include <sys/resource.h>
251 # include <sys/param.h>
252 # include <sys/file.h>
253 # include <sys/types.h>
258 * XXX XXX Hack -- POSIX uses "O_NONBLOCK" instead of "O_NDELAY"
260 * They should both work due to the "(i != 1)" test below.
263 # define O_NDELAY O_NONBLOCK
268 * OPTION: some machines lack "cbreak()"
269 * On these machines, we use an older definition
271 /* #define cbreak() crmode() */
275 * OPTION: some machines cannot handle "nonl()" and "nl()"
276 * On these machines, we can simply ignore those commands.
284 static cptr ANGBAND_DIR_XTRA_SOUND;
287 * Flag set once "sound" has been initialized
289 static bool can_use_sound = FALSE;
292 * An array of sound file names
294 static cptr sound_file[SOUND_MAX];
296 #endif /* USE_SOUND */
299 * Save the "normal" and "angband" terminal settings
304 static struct termios norm_termios;
306 static struct termios game_termios;
312 static struct termio norm_termio;
314 static struct termio game_termio;
320 static struct ltchars norm_speciax_chars;
321 static struct sgttyb norm_ttyb;
322 static struct tchars norm_tchars;
323 static int norm_locax_chars;
325 static struct ltchars game_speciax_chars;
326 static struct sgttyb game_ttyb;
327 static struct tchars game_tchars;
328 static int game_locax_chars;
335 * Hack -- Number of initialized "term" structures
337 static int active = 0;
344 * Hack -- define "A_BRIGHT" to be "A_BOLD", because on many
345 * machines, "A_BRIGHT" produces ugly "inverse" video.
348 # define A_BRIGHT A_BOLD
352 * Software flag -- we are allowed to use color
354 static int can_use_color = FALSE;
357 * Software flag -- we are allowed to change the colors
359 static int can_fix_color = FALSE;
362 * Simple Angband to Curses color conversion table
364 static int colortable[16];
371 * Place the "keymap" into its "normal" state
373 static void keymap_norm(void)
378 /* restore the saved values of the special chars */
379 (void)tcsetattr(0, TCSAFLUSH, &norm_termios);
385 /* restore the saved values of the special chars */
386 (void)ioctl(0, TCSETA, (char *)&norm_termio);
392 /* restore the saved values of the special chars */
393 (void)ioctl(0, TIOCSLTC, (char *)&norm_speciax_chars);
394 (void)ioctl(0, TIOCSETP, (char *)&norm_ttyb);
395 (void)ioctl(0, TIOCSETC, (char *)&norm_tchars);
396 (void)ioctl(0, TIOCLSET, (char *)&norm_locax_chars);
404 * Place the "keymap" into the "game" state
406 static void keymap_game(void)
411 /* restore the saved values of the special chars */
412 (void)tcsetattr(0, TCSAFLUSH, &game_termios);
418 /* restore the saved values of the special chars */
419 (void)ioctl(0, TCSETA, (char *)&game_termio);
425 /* restore the saved values of the special chars */
426 (void)ioctl(0, TIOCSLTC, (char *)&game_speciax_chars);
427 (void)ioctl(0, TIOCSETP, (char *)&game_ttyb);
428 (void)ioctl(0, TIOCSETC, (char *)&game_tchars);
429 (void)ioctl(0, TIOCLSET, (char *)&game_locax_chars);
437 * Save the normal keymap
439 static void keymap_norm_prepare(void)
444 /* Get the normal keymap */
445 tcgetattr(0, &norm_termios);
451 /* Get the normal keymap */
452 (void)ioctl(0, TCGETA, (char *)&norm_termio);
458 /* Get the normal keymap */
459 (void)ioctl(0, TIOCGETP, (char *)&norm_ttyb);
460 (void)ioctl(0, TIOCGLTC, (char *)&norm_speciax_chars);
461 (void)ioctl(0, TIOCGETC, (char *)&norm_tchars);
462 (void)ioctl(0, TIOCLGET, (char *)&norm_locax_chars);
470 * Save the keymaps (normal and game)
472 static void keymap_game_prepare(void)
477 /* Acquire the current mapping */
478 tcgetattr(0, &game_termios);
480 /* Force "Ctrl-C" to interupt */
481 game_termios.c_cc[VINTR] = (char)3;
483 /* Force "Ctrl-Z" to suspend */
484 game_termios.c_cc[VSUSP] = (char)26;
486 /* Hack -- Leave "VSTART/VSTOP" alone */
488 /* Disable the standard control characters */
489 game_termios.c_cc[VQUIT] = (char)-1;
490 game_termios.c_cc[VERASE] = (char)-1;
491 game_termios.c_cc[VKILL] = (char)-1;
492 game_termios.c_cc[VEOF] = (char)-1;
493 game_termios.c_cc[VEOL] = (char)-1;
495 /* Normally, block until a character is read */
496 game_termios.c_cc[VMIN] = 1;
497 game_termios.c_cc[VTIME] = 0;
503 /* Acquire the current mapping */
504 (void)ioctl(0, TCGETA, (char *)&game_termio);
506 /* Force "Ctrl-C" to interupt */
507 game_termio.c_cc[VINTR] = (char)3;
509 /* Force "Ctrl-Z" to suspend */
510 game_termio.c_cc[VSUSP] = (char)26;
512 /* Hack -- Leave "VSTART/VSTOP" alone */
514 /* Disable the standard control characters */
515 game_termio.c_cc[VQUIT] = (char)-1;
516 game_termio.c_cc[VERASE] = (char)-1;
517 game_termio.c_cc[VKILL] = (char)-1;
518 game_termio.c_cc[VEOF] = (char)-1;
519 game_termio.c_cc[VEOL] = (char)-1;
522 /* Disable the non-posix control characters */
523 game_termio.c_cc[VEOL2] = (char)-1;
524 game_termio.c_cc[VSWTCH] = (char)-1;
525 game_termio.c_cc[VDSUSP] = (char)-1;
526 game_termio.c_cc[VREPRINT] = (char)-1;
527 game_termio.c_cc[VDISCARD] = (char)-1;
528 game_termio.c_cc[VWERASE] = (char)-1;
529 game_termio.c_cc[VLNEXT] = (char)-1;
530 game_termio.c_cc[VSTATUS] = (char)-1;
533 /* Normally, block until a character is read */
534 game_termio.c_cc[VMIN] = 1;
535 game_termio.c_cc[VTIME] = 0;
541 /* Get the default game characters */
542 (void)ioctl(0, TIOCGETP, (char *)&game_ttyb);
543 (void)ioctl(0, TIOCGLTC, (char *)&game_speciax_chars);
544 (void)ioctl(0, TIOCGETC, (char *)&game_tchars);
545 (void)ioctl(0, TIOCLGET, (char *)&game_locax_chars);
547 /* Force suspend (^Z) */
548 game_speciax_chars.t_suspc = (char)26;
550 /* Cancel some things */
551 game_speciax_chars.t_dsuspc = (char)-1;
552 game_speciax_chars.t_rprntc = (char)-1;
553 game_speciax_chars.t_flushc = (char)-1;
554 game_speciax_chars.t_werasc = (char)-1;
555 game_speciax_chars.t_lnextc = (char)-1;
557 /* Force interupt (^C) */
558 game_tchars.t_intrc = (char)3;
560 /* Force start/stop (^Q, ^S) */
561 game_tchars.t_startc = (char)17;
562 game_tchars.t_stopc = (char)19;
564 /* Cancel some things */
565 game_tchars.t_quitc = (char)-1;
566 game_tchars.t_eofc = (char)-1;
567 game_tchars.t_brkc = (char)-1;
579 static errr Term_xtra_gcu_alive(int v)
584 /* Go to normal keymap mode */
592 /* Hack -- make sure the cursor is visible */
593 Term_xtra(TERM_XTRA_SHAPE, 1);
595 /* Flush the curses buffer */
599 /* this moves curses to bottom right corner */
600 mvcur(curscr->cury, curscr->curx, LINES - 1, 0);
602 /* this moves curses to bottom right corner */
603 mvcur(curscr->_cury, curscr->_curx, LINES - 1, 0);
609 /* Flush the output */
610 (void)fflush(stdout);
617 /* (void)touchwin(curscr); */
618 /* (void)wrefresh(curscr); */
620 /* Restore the settings */
625 /* Go to angband keymap mode */
634 * Check for existance of a file
636 static bool check_file(cptr s)
641 if (!fff) return (FALSE);
654 static bool init_sound(void)
656 /* Initialize once */
664 /* Prepare the sounds */
665 for (i = 1; i < SOUND_MAX; i++)
667 /* Extract name of sound file */
668 sprintf(wav, "%s.wav", angband_sound_name[i]);
670 /* Access the sound */
671 path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_SOUND, wav);
673 /* Save the sound filename, if it exists */
674 if (check_file(buf)) sound_file[i] = string_make(buf);
677 /* Sound available */
678 can_use_sound = TRUE;
682 return (can_use_sound);
685 #endif /* USE_SOUND */
690 * Init the "curses" system
692 static void Term_init_gcu(term *t)
694 term_data *td = (term_data *)(t->data);
696 /* Count init's, handle first */
697 if (active++ != 0) return;
699 /* Erase the screen */
700 (void)wclear(td->win);
702 /* Reset the cursor */
703 (void)wmove(td->win, 0, 0);
706 (void)wrefresh(td->win);
714 * Nuke the "curses" system
716 static void Term_nuke_gcu(term *t)
718 term_data *td = (term_data *)(t->data);
720 /* Delete this window */
723 /* Count nuke's, handle last */
724 if (--active != 0) return;
726 /* Hack -- make sure the cursor is visible */
727 Term_xtra(TERM_XTRA_SHAPE, 1);
730 /* Reset colors to defaults */
735 /* This moves curses to bottom right corner */
736 mvcur(curscr->cury, curscr->curx, LINES - 1, 0);
738 /* This moves curses to bottom right corner */
739 mvcur(curscr->_cury, curscr->_curx, LINES - 1, 0);
742 /* Flush the curses buffer */
748 /* Flush the output */
749 (void)fflush(stdout);
758 * Process events, with optional wait
760 static errr Term_xtra_gcu_event(int v)
767 /* Paranoia -- Wait for it */
768 nodelay(stdscr, FALSE);
773 /* Mega-Hack -- allow graceful "suspend" */
774 for (k = 0; (k < 10) && (i == ERR); k++) i = getch();
776 /* Broken input is special */
777 if (i == ERR) exit_game_panic();
778 if (i == EOF) exit_game_panic();
784 /* Do not wait for it */
785 nodelay(stdscr, TRUE);
787 /* Check for keypresses */
790 /* Wait for it next time */
791 nodelay(stdscr, FALSE);
794 if (i == ERR) return (1);
795 if (i == EOF) return (1);
798 /* Enqueue the keypress */
805 #else /* USE_GETCH */
808 * Process events (with optional wait)
810 static errr Term_xtra_gcu_event(int v)
819 /* Wait for one byte */
822 /* Hack -- Handle bizarre "errors" */
823 if ((i <= 0) && (errno != EINTR)) exit_game_panic();
829 /* Get the current flags for stdin */
830 k = fcntl(0, F_GETFL, 0);
833 if (k < 0) return (1);
835 /* Tell stdin not to block */
836 if (fcntl(0, F_SETFL, k | O_NDELAY) < 0) return (1);
838 /* Read one byte, if possible */
841 /* Replace the flags for stdin */
842 if (fcntl(0, F_SETFL, k)) return (1);
845 /* Ignore "invalid" keys */
846 if ((i != 1) || (!buf[0])) return (1);
848 /* Enqueue the keypress */
849 Term_keypress(buf[0]);
855 #endif /* USE_GETCH */
860 * Hack -- make a sound
862 static errr Term_xtra_gcu_sound(int v)
867 if (!use_sound) return (1);
870 if ((v < 0) || (v >= SOUND_MAX)) return (1);
873 if (!sound_file[v]) return (1);
875 sprintf(buf,"./gcusound.sh %s\n", sound_file[v]);
885 if (!use_sound) return (1);
888 if ((v < 0) || (v >= SOUND_MAX)) return (1);
891 if (!sound_file[v]) return (1);
896 if (pid==-1) return (1);
903 argv[2]="./gcusound.sh";
904 strcpy(argv[3],sound_file[v]);
905 execvp(argv[0], argv);
917 static errr Term_xtra_gcu_react(void)
924 /* Cannot handle color redefinition */
925 if (!can_fix_color) return (0);
928 for (i = 0; i < 16; i++)
930 /* Set one color (note scaling) */
931 init_color(i, angband_color_table[i][1] * 1000 / 255,
932 angband_color_table[i][2] * 1000 / 255,
933 angband_color_table[i][3] * 1000 / 255);
944 * Handle a "special request"
946 static errr Term_xtra_gcu(int n, int v)
948 term_data *td = (term_data *)(Term->data);
950 /* Analyze the request */
954 case TERM_XTRA_CLEAR:
956 (void)wclear(td->win);
960 case TERM_XTRA_NOISE:
961 (void)write(1, "\007", 1);
965 /* Make a special sound */
966 case TERM_XTRA_SOUND:
967 return (Term_xtra_gcu_sound(v));
970 /* Flush the Curses buffer */
971 case TERM_XTRA_FRESH:
972 (void)wrefresh(td->win);
977 /* Change the cursor visibility */
978 case TERM_XTRA_SHAPE:
984 /* Suspend/Resume curses */
985 case TERM_XTRA_ALIVE:
986 return (Term_xtra_gcu_alive(v));
989 case TERM_XTRA_EVENT:
990 return (Term_xtra_gcu_event(v));
993 case TERM_XTRA_FLUSH:
994 while (!Term_xtra_gcu_event(FALSE));
998 case TERM_XTRA_DELAY:
1002 /* React to events */
1003 case TERM_XTRA_REACT:
1004 Term_xtra_gcu_react();
1016 * Actually MOVE the hardware cursor
1018 static errr Term_curs_gcu(int x, int y)
1020 term_data *td = (term_data *)(Term->data);
1022 /* Literally move the cursor */
1023 wmove(td->win, y, x);
1031 * Erase a grid of space
1032 * Hack -- try to be "semi-efficient".
1034 static errr Term_wipe_gcu(int x, int y, int n)
1036 term_data *td = (term_data *)(Term->data);
1039 wmove(td->win, y, x);
1041 /* Clear to end of line */
1047 /* Clear some characters */
1050 while (n-- > 0) waddch(td->win, ' ');
1057 #ifdef USE_NCURSES_ACS
1059 * this function draws some ACS characters on the screen
1060 * for DOS-based users: these are the graphical chars (blocks, lines etc)
1062 * unix-gurus: before you start adding other attributes like A_REVERSE
1063 * think hard about how map_info() in cave.c should handle the color
1064 * of something that we here draw in reverse. It's not so simple, alas.
1066 static void Term_acs_text_gcu(int x, int y, int n, byte a, cptr s)
1068 term_data *td = (term_data *)(Term->data);
1071 /* position the cursor */
1072 wmove(td->win, y, x);
1076 wattrset(td->win, colortable[a & 0x0F]);
1079 for (i=0; i < n; i++)
1081 /* add acs_map of a */
1082 waddch(td->win, acs_map[(int)s[i]]);
1084 wattrset(td->win, WA_NORMAL);
1089 * Place some text on the screen using an attribute
1091 static errr Term_text_gcu(int x, int y, int n, byte a, cptr s)
1093 term_data *td = (term_data *)(Term->data);
1099 #ifdef USE_NCURSES_ACS
1100 /* do we have colors + 16 ? */
1101 /* then call special routine for drawing special characters */
1104 Term_acs_text_gcu(x, y, n, a, s);
1109 /* Obtain a copy of the text */
1110 for (i = 0; i < n; i++) text[i] = s[i]; text[n] = 0;
1112 /* Move the cursor and dump the string */
1113 wmove(td->win, y, x);
1117 if (can_use_color) wattrset(td->win, colortable[a & 0x0F]);
1121 waddstr(td->win, text);
1129 static errr term_data_init(term_data *td, int rows, int cols, int y, int x)
1133 /* Make sure the window has a positive size */
1134 if (rows <= 0 || cols <= 0) return (0);
1136 /* Create a window */
1137 td->win = newwin(rows, cols, y, x);
1139 /* Make sure we succeed */
1142 plog("Failed to setup curses window.");
1146 /* Initialize the term */
1147 term_init(t, cols, rows, 256);
1149 /* Avoid the bottom right corner */
1150 t->icky_corner = TRUE;
1152 /* Erase with "white space" */
1153 t->attr_blank = TERM_WHITE;
1154 t->char_blank = ' ';
1156 /* Set some hooks */
1157 t->init_hook = Term_init_gcu;
1158 t->nuke_hook = Term_nuke_gcu;
1160 /* Set some more hooks */
1161 t->text_hook = Term_text_gcu;
1162 t->wipe_hook = Term_wipe_gcu;
1163 t->curs_hook = Term_curs_gcu;
1164 t->xtra_hook = Term_xtra_gcu;
1178 static void hook_quit(cptr str)
1189 * Prepare "curses" for use by the file "term.c"
1191 * Installs the "hook" functions defined above, and then activates
1192 * the main screen "term", which clears the screen and such things.
1194 * Someone should really check the semantics of "initscr()"
1196 errr init_gcu(int argc, char *argv[])
1200 int num_term = 4, next_win = 0;
1210 /* Build the "sound" path */
1211 path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "sound");
1213 /* Allocate the path */
1214 ANGBAND_DIR_XTRA_SOUND = string_make(path);
1218 /* Extract the normal keymap */
1219 keymap_norm_prepare();
1222 /* Initialize for USG Unix */
1223 if (initscr() == NULL) return (-1);
1225 /* Initialize for others systems */
1226 if (initscr() == (WINDOW*)ERR) return (-1);
1229 /* Activate hooks */
1230 quit_aux = hook_quit;
1231 core_aux = hook_quit;
1233 /* Hack -- Require large screen, or Quit with message */
1234 i = ((LINES < 24) || (COLS < 80));
1235 if (i) quit("Angband needs an 80x24 'curses' screen");
1240 /*** Init the Color-pairs and set up a translation table ***/
1242 /* Do we have color, and enough color, available? */
1243 can_use_color = ((start_color() != ERR) && has_colors() &&
1244 (COLORS >= 8) && (COLOR_PAIRS >= 8));
1246 #ifdef REDEFINE_COLORS
1247 /* Can we change colors? */
1248 can_fix_color = (can_use_color && can_change_color() &&
1249 (COLORS >= 16) && (COLOR_PAIRS > 8));
1252 /* Attempt to use customized colors */
1255 /* Prepare the color pairs */
1256 for (i = 1; i <= 63; i++)
1258 /* Reset the color */
1259 if (init_pair(i, (i - 1) % 8, (i - 1) / 8) == ERR)
1261 quit("Color pair init failed");
1264 /* Set up the colormap */
1265 colortable[i - 1] = (COLOR_PAIR(i) | A_NORMAL);
1266 colortable[i + 7] = (COLOR_PAIR(i) | A_BRIGHT);
1268 /* XXX XXX XXX Take account of "gamma correction" */
1270 /* Prepare the "Angband Colors" */
1271 Term_xtra_gcu_react();
1274 /* Attempt to use colors */
1275 else if (can_use_color)
1277 /* Color-pair 0 is *always* WHITE on BLACK */
1279 /* Prepare the color pairs */
1280 init_pair(1, COLOR_RED, COLOR_BLACK);
1281 init_pair(2, COLOR_GREEN, COLOR_BLACK);
1282 init_pair(3, COLOR_YELLOW, COLOR_BLACK);
1283 init_pair(4, COLOR_BLUE, COLOR_BLACK);
1284 init_pair(5, COLOR_MAGENTA, COLOR_BLACK);
1285 init_pair(6, COLOR_CYAN, COLOR_BLACK);
1286 init_pair(7, COLOR_BLACK, COLOR_BLACK);
1288 /* Prepare the "Angband Colors" -- Bright white is too bright */
1289 /* Changed in Drangband. Cyan as grey sucks -- -TM- */
1290 colortable[0] = (COLOR_PAIR(7) | A_NORMAL); /* Black */
1291 colortable[1] = (COLOR_PAIR(0) | A_BRIGHT); /* White */
1292 colortable[2] = (COLOR_PAIR(0) | A_NORMAL); /* Grey XXX */
1293 colortable[3] = (COLOR_PAIR(1) | A_BRIGHT); /* Orange XXX */
1294 colortable[4] = (COLOR_PAIR(1) | A_NORMAL); /* Red */
1295 colortable[5] = (COLOR_PAIR(2) | A_NORMAL); /* Green */
1296 colortable[6] = (COLOR_PAIR(4) | A_NORMAL); /* Blue */
1297 colortable[7] = (COLOR_PAIR(3) | A_NORMAL); /* Umber */
1298 colortable[8] = (COLOR_PAIR(7) | A_BRIGHT); /* Dark-grey XXX */
1299 colortable[9] = (COLOR_PAIR(0) | A_NORMAL); /* Light-grey XXX */
1300 colortable[10] = (COLOR_PAIR(5) | A_NORMAL); /* Purple */
1301 colortable[11] = (COLOR_PAIR(3) | A_BRIGHT); /* Yellow */
1302 colortable[12] = (COLOR_PAIR(5) | A_BRIGHT); /* Light Red XXX */
1303 colortable[13] = (COLOR_PAIR(2) | A_BRIGHT); /* Light Green */
1304 colortable[14] = (COLOR_PAIR(4) | A_BRIGHT); /* Light Blue */
1305 colortable[15] = (COLOR_PAIR(3) | A_NORMAL); /* Light Umber XXX */
1312 /* Handle "arg_sound" */
1313 if (use_sound != arg_sound)
1315 /* Initialize (if needed) */
1316 if (arg_sound && !init_sound())
1319 plog("Cannot initialize sound!");
1325 /* Change setting */
1326 use_sound = arg_sound;
1335 /* if USE_NCURSES_ACS is defined, we can do something with graphics in curses! */
1336 #ifdef USE_NCURSES_ACS
1337 use_graphics = TRUE;
1341 #endif /* USE_GRAPHICS */
1345 /*** Low level preparation ***/
1349 /* Paranoia -- Assume no waiting */
1350 nodelay(stdscr, FALSE);
1360 /* Extract the game keymap */
1361 keymap_game_prepare();
1364 /*** Now prepare the term(s) ***/
1365 for (i = 0; i < num_term; i++)
1378 case 1: rows = LINES - 25;
1390 case 3: rows = LINES - 25;
1396 default: rows = cols = 0;
1401 /* No non-windows */
1402 if (rows <= 0 || cols <= 0) continue;
1405 term_data_init(&data[next_win], rows, cols, y, x);
1408 angband_term[next_win] = Term;
1413 /* Activate the "Angband" window screen */
1414 Term_activate(&data[0].t);
1417 term_screen = &data[0].t;
1424 #endif /* USE_GCU */