1 /* File: main-gcu.c */
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
34 * 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
35 * Xref: xs4all rec.games.roguelike.angband:86332
37 * Greg Wooledge <wooledge@kellnet.com> wrote:
38 * > Gwidon S. Naskrent (naskrent@artemida.amu.edu.pl) wrote:
40 * > >On 30 Mar 1999 13:17:18 GMT, scarblac-spamtrap@pino.selwerd.cx (Remco
43 * > >>I recently switched to Linux, and *bands work fine. I like
44 * > >>to play them in consoles, not in X. However, colour is wrong.
45 * > >>"Slate" and "light slate" are always light blue, instead
46 * > >>of some shade of grey. Colours are fine in X.
48 * > I actually noticed the Linux console color issue a very long time ago,
49 * > but since I always play under X, I never really investigated it.
51 * > You're absolutely right, though -- the Linux console colors are not
52 * > "right" for Angband.
54 * I've noticed this myself, so I spent the evening fixing it.
55 * Well, sorta fixing it. It's not perfect yet, and it may not be
56 * possible to get it perfect with VGA hardware and/or the current
59 * > OK, reading on in terminfo(5):
62 * > Most color terminals are either `Tektronix-like' or `HP-
63 * > like'. Tektronix-like terminals have a predefined set of
64 * > N colors (where N usually 8), and can set character-cell
65 * > foreground and background characters independently, mixing
66 * > them into N * N color-pairs. On HP-like terminals, the
67 * > use must set each color pair up separately (foreground and
68 * > background are not independently settable). Up to M
69 * > color-pairs may be set up from 2*M different colors.
70 * > ANSI-compatible terminals are Tektronix-like.
72 * > The "linux" terminfo entry is definitely in the "Tektronix-like" family.
73 * > It has the "setaf" and "setab" capabilities for setting the foreground
74 * > and background colors to one of 8 basically hard-coded values:
76 * > Color #define Value RGB
77 * > black COLOR_BLACK 0 0, 0, 0
78 * > red COLOR_RED 1 max,0,0
79 * > green COLOR_GREEN 2 0,max,0
80 * > yellow COLOR_YELLOW 3 max,max,0
81 * > blue COLOR_BLUE 4 0,0,max
82 * > magenta COLOR_MAGENTA 5 max,0,max
83 * > cyan COLOR_CYAN 6 0,max,max
84 * > white COLOR_WHITE 7 max,max,max
86 * Well, not quite. Using certain escape sequences, an
87 * application (or better yet, curses) can redefine the colors (at
88 * least some of them) and then those are used. Read the
89 * curs_color manpage, and the part about "ccc" and "initc" in the
90 * terminfo manpage. This is what the part of main-gcu inside the
91 * "if (can_fix_color)" code does.
93 * > So, what does this mean to the Angband player? Well, it means that
94 * > either there's nothing you can do about the console colors as long as
95 * > straight curses/ncurses is used, or if there is something to be done,
96 * > I'm not clever enough to figure out how to do it.
98 * Well, it is possible, though you have to patch main-gcu
99 * and edit a terminfo entry. Apparently the relevant code in
100 * main-gcu was never tested (it's broken in at least one major
101 * way). Apply the patch at the end of this message (notice that
102 * we need to define REDEFINE_COLORS at some point near the
103 * beginning of the file).
104 * Next, write this termcap entry to a file:
106 * linux-c|linux console 1.3.6+ with private palette for each virtual console,
108 * colors#16, pairs#64,
109 * initc=\E]P%x%p1%{16}%/%02x%p1%{16}%/%02x%p1%{16}%/%02x,
113 * and run "tic" on it to produce a new terminfo entry called
114 * "linux-c". Especially note the "ccc" flag which says that we
115 * can redefine colors. The ugly "initc" string is what tells
116 * the console how to redefine a color. Now, just set your TERM
117 * variable to "linux-c" and try Angband again. If I've
118 * remembered to tell you everything that I've done, you should
119 * get the weird light-blue slate changed to a gray.
120 * Now, there are still lots of problems with this.
121 * Something (I don't think it's curses, either the kernel or
122 * the hardware itself) seems to be ignoring my color changes to
123 * colors 6 and 7, which is annoying. Also, the normal "white"
124 * color is now way too bright, but it's now necessary to
125 * distinguish it from the other grays.
126 * The kernel seems to support 16 colors, but you can
127 * only switch to 8 of those, due to VT102 compatibility, it
128 * seems. I think it would be possible to patch the kernel and
129 * allow all 16 colors to be used, but I haven't built up the
130 * nerve to try that yet.
131 * Let me know if you can improve on this any. Some of
132 * this may actually work differently on other hardware (ugh).
139 * To use this file, you must define "USE_GCU" in the Makefile.
141 * Hack -- note that "angband.h" is included AFTER the #ifdef test.
142 * This was necessary because of annoying "curses.h" silliness.
144 * Note that this file is not "intended" to support non-Unix machines,
145 * nor is it intended to support VMS or other bizarre setups.
147 * Also, this package assumes that the underlying "curses" handles both
148 * the "nonl()" and "cbreak()" commands correctly, see the "OPTION" below.
150 * This code should work with most versions of "curses" or "ncurses",
151 * and the "main-ncu.c" file (and USE_NCU define) are no longer used.
153 * See also "USE_CAP" and "main-cap.c" for code that bypasses "curses"
154 * and uses the "termcap" information directly, or even bypasses the
155 * "termcap" information and sends direct vt100 escape sequences.
157 * XXX XXX XXX Consider the use of "savetty()" and "resetty()".
160 #include "game-option/runtime-arguments.h"
161 #include "game-option/special-options.h"
162 #include "io/exit-panic.h"
163 #include "io/files-util.h"
164 #include "locale/japanese.h"
165 #include "main/sound-definitions-table.h"
166 #include "main/sound-of-music.h"
167 #include "system/angband.h"
168 #include "system/player-type-definition.h"
169 #include "term/gameterm.h"
170 #include "term/term-color-types.h"
171 #include "util/angband-files.h"
172 #include "view/display-map.h"
177 * Hack -- play games with "bool"
179 #if __STDC_VERSION__ < 199901L
184 * Include the proper "header" file
194 #define MAX_TERM_DATA 4
196 static term_data data[MAX_TERM_DATA];
199 * Hack -- try to guess which systems use what commands
200 * Hack -- allow one of the "USE_Txxxxx" flags to be pre-set.
201 * Mega-Hack -- try to guess when "POSIX" is available.
202 * If the user defines two of these, we will probably crash.
204 #if !defined(USE_TCHARS)
205 #if defined(_POSIX_VERSION)
213 * Try redefining the colors at startup.
215 #define REDEFINE_COLORS
221 #include <sys/ioctl.h>
226 * One version needs this file
229 #include <sys/ioctl.h>
234 * The other needs this file
237 #include <sys/file.h>
238 #include <sys/ioctl.h>
239 #include <sys/param.h>
240 #include <sys/resource.h>
241 #include <sys/types.h>
247 * XXX XXX Hack -- POSIX uses "O_NONBLOCK" instead of "O_NDELAY"
249 * They should both work due to the "(i != 1)" test below.
252 #define O_NDELAY O_NONBLOCK
256 * OPTION: some machines lack "cbreak()"
257 * On these machines, we use an older definition
259 /* #define cbreak() crmode() */
262 * OPTION: some machines cannot handle "nonl()" and "nl()"
263 * On these machines, we can simply ignore those commands.
268 static concptr ANGBAND_DIR_XTRA_SOUND;
272 * Flag set once "sound" has been initialized
274 static bool can_use_sound = false;
277 * An array of sound file names
279 static concptr sound_file[SOUND_MAX];
282 * Save the "normal" and "angband" terminal settings
287 static struct termios norm_termios;
289 static struct termios game_termios;
295 static struct termio norm_termio;
297 static struct termio game_termio;
302 static struct ltchars norm_speciax_chars;
303 static struct sgttyb norm_ttyb;
304 static struct tchars norm_tchars;
305 static int norm_locax_chars;
307 static struct ltchars game_speciax_chars;
308 static struct sgttyb game_ttyb;
309 static struct tchars game_tchars;
310 static int game_locax_chars;
314 * Hack -- Number of initialized "term" structures
316 static int active = 0;
320 * Hack -- define "A_BRIGHT" to be "A_BOLD", because on many
321 * machines, "A_BRIGHT" produces ugly "inverse" video.
324 #define A_BRIGHT A_BOLD
328 * Software flag -- we are allowed to use color
330 static int can_use_color = false;
333 * Software flag -- we are allowed to change the colors
335 static int can_fix_color = false;
338 * Simple Angband to Curses color conversion table
340 static int colortable[16];
343 * Background color we should draw with; either BLACK or DEFAULT
345 static int bg_color = COLOR_BLACK;
350 * Place the "keymap" into its "normal" state
352 static void keymap_norm(void)
355 /* restore the saved values of the special chars */
356 (void)tcsetattr(0, TCSAFLUSH, &norm_termios);
360 /* restore the saved values of the special chars */
361 (void)ioctl(0, TCSETA, (char *)&norm_termio);
365 /* restore the saved values of the special chars */
366 (void)ioctl(0, TIOCSLTC, (char *)&norm_speciax_chars);
367 (void)ioctl(0, TIOCSETP, (char *)&norm_ttyb);
368 (void)ioctl(0, TIOCSETC, (char *)&norm_tchars);
369 (void)ioctl(0, TIOCLSET, (char *)&norm_locax_chars);
374 * Place the "keymap" into the "game" state
376 static void keymap_game(void)
379 /* restore the saved values of the special chars */
380 (void)tcsetattr(0, TCSAFLUSH, &game_termios);
384 /* restore the saved values of the special chars */
385 (void)ioctl(0, TCSETA, (char *)&game_termio);
389 /* restore the saved values of the special chars */
390 (void)ioctl(0, TIOCSLTC, (char *)&game_speciax_chars);
391 (void)ioctl(0, TIOCSETP, (char *)&game_ttyb);
392 (void)ioctl(0, TIOCSETC, (char *)&game_tchars);
393 (void)ioctl(0, TIOCLSET, (char *)&game_locax_chars);
398 * Save the normal keymap
400 static void keymap_norm_prepare(void)
403 /* Get the normal keymap */
404 tcgetattr(0, &norm_termios);
408 /* Get the normal keymap */
409 (void)ioctl(0, TCGETA, (char *)&norm_termio);
413 /* Get the normal keymap */
414 (void)ioctl(0, TIOCGETP, (char *)&norm_ttyb);
415 (void)ioctl(0, TIOCGLTC, (char *)&norm_speciax_chars);
416 (void)ioctl(0, TIOCGETC, (char *)&norm_tchars);
417 (void)ioctl(0, TIOCLGET, (char *)&norm_locax_chars);
422 * Save the keymaps (normal and game)
424 static void keymap_game_prepare(void)
427 /* Acquire the current mapping */
428 tcgetattr(0, &game_termios);
430 /* Force "Ctrl-C" to interupt */
431 game_termios.c_cc[VINTR] = (char)3;
433 /* Force "Ctrl-Z" to suspend */
434 game_termios.c_cc[VSUSP] = (char)26;
436 /* Hack -- Leave "VSTART/VSTOP" alone */
438 /* Disable the standard control characters */
439 game_termios.c_cc[VQUIT] = (char)-1;
440 game_termios.c_cc[VERASE] = (char)-1;
441 game_termios.c_cc[VKILL] = (char)-1;
442 game_termios.c_cc[VEOF] = (char)-1;
443 game_termios.c_cc[VEOL] = (char)-1;
445 /* Normally, block until a character is read */
446 game_termios.c_cc[VMIN] = 1;
447 game_termios.c_cc[VTIME] = 0;
451 /* Acquire the current mapping */
452 (void)ioctl(0, TCGETA, (char *)&game_termio);
454 /* Force "Ctrl-C" to interupt */
455 game_termio.c_cc[VINTR] = (char)3;
457 /* Force "Ctrl-Z" to suspend */
458 game_termio.c_cc[VSUSP] = (char)26;
460 /* Disable the standard control characters */
461 game_termio.c_cc[VQUIT] = (char)-1;
462 game_termio.c_cc[VERASE] = (char)-1;
463 game_termio.c_cc[VKILL] = (char)-1;
464 game_termio.c_cc[VEOF] = (char)-1;
465 game_termio.c_cc[VEOL] = (char)-1;
467 /* Normally, block until a character is read */
468 game_termio.c_cc[VMIN] = 1;
469 game_termio.c_cc[VTIME] = 0;
473 /* Get the default game characters */
474 (void)ioctl(0, TIOCGETP, (char *)&game_ttyb);
475 (void)ioctl(0, TIOCGLTC, (char *)&game_speciax_chars);
476 (void)ioctl(0, TIOCGETC, (char *)&game_tchars);
477 (void)ioctl(0, TIOCLGET, (char *)&game_locax_chars);
479 /* Force suspend (^Z) */
480 game_speciax_chars.t_suspc = (char)26;
482 /* Cancel some things */
483 game_speciax_chars.t_dsuspc = (char)-1;
484 game_speciax_chars.t_rprntc = (char)-1;
485 game_speciax_chars.t_flushc = (char)-1;
486 game_speciax_chars.t_werasc = (char)-1;
487 game_speciax_chars.t_lnextc = (char)-1;
489 /* Force interupt (^C) */
490 game_tchars.t_intrc = (char)3;
492 /* Force start/stop (^Q, ^S) */
493 game_tchars.t_startc = (char)17;
494 game_tchars.t_stopc = (char)19;
496 /* Cancel some things */
497 game_tchars.t_quitc = (char)-1;
498 game_tchars.t_eofc = (char)-1;
499 game_tchars.t_brkc = (char)-1;
506 static errr Term_xtra_gcu_alive(int v)
509 /* Go to normal keymap mode */
517 /* Hack -- make sure the cursor is visible */
518 term_xtra(TERM_XTRA_SHAPE, 1);
520 /* Flush the curses buffer */
523 /* this moves curses to bottom right corner */
524 mvcur(getcury(curscr), getcurx(curscr), LINES - 1, 0);
529 /* Flush the output */
530 (void)fflush(stdout);
532 /* Restore the settings */
537 /* Go to angband keymap mode */
545 * Check for existance of a file
547 static bool check_file(concptr s)
561 static bool init_sound(void)
563 /* Initialize once */
565 return can_use_sound;
571 /* Prepare the sounds */
572 for (i = 1; i < SOUND_MAX; i++) {
573 /* Extract name of sound file */
574 sprintf(wav, "%s.wav", angband_sound_name[i]);
576 /* Access the sound */
577 path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_SOUND, wav);
579 /* Save the sound filename, if it exists */
581 sound_file[i] = string_make(buf);
584 /* Sound available */
585 can_use_sound = true;
586 return (can_use_sound);
590 * Init the "curses" system
592 static void Term_init_gcu(term_type *t)
594 term_data *td = (term_data *)(t->data);
596 /* Count init's, handle first */
600 /* Erase the screen */
601 (void)wclear(td->win);
603 /* Reset the cursor */
604 (void)wmove(td->win, 0, 0);
607 (void)wrefresh(td->win);
614 * Nuke the "curses" system
616 static void Term_nuke_gcu(term_type *t)
618 term_data *td = (term_data *)(t->data);
620 /* Delete this window */
623 /* Count nuke's, handle last */
627 /* Hack -- make sure the cursor is visible */
628 term_xtra(TERM_XTRA_SHAPE, 1);
631 /* Reset colors to defaults */
635 /* This moves curses to bottom right corner */
636 mvcur(getcury(curscr), getcurx(curscr), LINES - 1, 0);
638 /* Flush the curses buffer */
644 /* Flush the output */
645 (void)fflush(stdout);
652 * Push multiple keys reversal
654 static void term_string_push(char *buf)
656 int i, l = strlen(buf);
657 for (i = l; i >= 0; i--)
658 term_key_push(buf[i]);
664 * Process events, with optional wait
666 static errr Term_xtra_gcu_event(int v)
675 /* Paranoia -- Wait for it */
676 nodelay(stdscr, false);
681 /* Broken input is special */
683 exit_game_panic(p_ptr);
685 exit_game_panic(p_ptr);
689 /* Do not wait for it */
690 nodelay(stdscr, true);
692 while ((i = getch()) != EOF) {
694 exit_game_panic(p_ptr);
700 /* Wait for it next time */
701 nodelay(stdscr, false);
705 char eucbuf[sizeof(buf)];
706 /* strlen + 1 を渡して文字列終端('\0')を含めて変換する */
707 if (utf8_to_euc(buf, strlen(buf) + 1, eucbuf, sizeof(eucbuf)) < 0) {
711 term_string_push(_(eucbuf, buf));
716 /* Do not wait for it */
717 nodelay(stdscr, true);
719 /* Check for keypresses */
722 /* Wait for it next time */
723 nodelay(stdscr, false);
731 /* Enqueue the keypress */
739 #else /* USE_GETCH */
742 * Process events (with optional wait)
744 static errr Term_xtra_gcu_event(int v)
754 /* Wait for one byte */
755 i = read(0, bp++, 1);
757 /* Hack -- Handle bizarre "errors" */
758 if ((i <= 0) && (errno != EINTR))
759 exit_game_panic(p_ptr);
761 /* Get the current flags for stdin */
762 k = fcntl(0, F_GETFL, 0);
768 /* Tell stdin not to block */
769 if (fcntl(0, F_SETFL, k | O_NDELAY) >= 0) {
770 if ((i = read(0, bp, 254)) > 0) {
774 /* Replace the flags for stdin */
775 if (fcntl(0, F_SETFL, k))
781 char eucbuf[sizeof(buf)];
782 /* strlen + 1 を渡して文字列終端('\0')を含めて変換する */
783 if (utf8_to_euc(buf, strlen(buf) + 1, eucbuf, sizeof(eucbuf)) < 0) {
787 term_string_push(_(eucbuf, buf));
792 /* Get the current flags for stdin */
793 k = fcntl(0, F_GETFL, 0);
799 /* Tell stdin not to block */
800 if (fcntl(0, F_SETFL, k | O_NDELAY) < 0)
803 /* Read one byte, if possible */
806 /* Replace the flags for stdin */
807 if (fcntl(0, F_SETFL, k))
810 /* Ignore "invalid" keys */
811 if ((i != 1) || (!buf[0]))
814 /* Enqueue the keypress */
815 term_key_push(buf[0]);
822 #endif /* USE_GETCH */
825 * Hack -- make a sound
827 static errr Term_xtra_gcu_sound(int v)
836 if ((v < 0) || (v >= SOUND_MAX))
843 sprintf(buf, "./gcusound.sh %s\n", sound_file[v]);
845 return (system(buf) < 0);
850 static int scale_color(int i, int j, int scale)
852 return (angband_color_table[i][j] * (scale - 1) + 127) / 255;
855 static int create_color(int i, int scale)
857 int r = scale_color(i, 1, scale);
858 int g = scale_color(i, 2, scale);
859 int b = scale_color(i, 3, scale);
860 int rgb = 16 + scale * scale * r + scale * g + b;
861 /* In the case of white and black we need to use the ANSI colors */
862 if (r == g && g == b)
865 if (b == scale) rgb = 15;
873 static errr Term_xtra_gcu_react(void)
878 if (COLORS == 256 || COLORS == 88)
880 /* If we have more than 16 colors, find the best matches. These numbers
881 * correspond to xterm/rxvt's builtin color numbers--they do not
882 * correspond to curses' constants OR with curses' color pairs.
884 * XTerm has 216 (6*6*6) RGB colors, with each RGB setting 0-5.
885 * RXVT has 64 (4*4*4) RGB colors, with each RGB setting 0-3.
887 * Both also have the basic 16 ANSI colors, plus some extra grayscale
888 * colors which we do not use.
890 int scale = COLORS == 256 ? 6 : 4;
891 for (int i = 0; i < 16; i++)
893 int fg = create_color(i, scale);
894 init_pair(i + 1, fg, bg_color);
895 colortable[i] = COLOR_PAIR(i + 1) | A_NORMAL;
906 * Handle a "special request"
908 static errr Term_xtra_gcu(int n, int v)
910 term_data *td = (term_data *)(Term->data);
912 /* Analyze the request */
915 case TERM_XTRA_CLEAR:
917 (void)wclear(td->win);
921 case TERM_XTRA_NOISE:
922 return write(1, "\007", 1) != 1;
924 /* Make a special sound */
925 case TERM_XTRA_SOUND:
926 return (Term_xtra_gcu_sound(v));
928 /* Flush the Curses buffer */
929 case TERM_XTRA_FRESH:
930 (void)wrefresh(td->win);
933 /* Change the cursor visibility */
934 case TERM_XTRA_SHAPE:
938 /* Suspend/Resume curses */
939 case TERM_XTRA_ALIVE:
940 return (Term_xtra_gcu_alive(v));
943 case TERM_XTRA_EVENT:
944 return (Term_xtra_gcu_event(v));
947 case TERM_XTRA_FLUSH:
948 while (!Term_xtra_gcu_event(false))
953 case TERM_XTRA_DELAY:
957 /* React to events */
958 case TERM_XTRA_REACT:
959 Term_xtra_gcu_react();
968 * Actually MOVE the hardware cursor
970 static errr Term_curs_gcu(int x, int y)
972 term_data *td = (term_data *)(Term->data);
974 /* Literally move the cursor */
975 wmove(td->win, y, x);
982 * Erase a grid of space
983 * Hack -- try to be "semi-efficient".
985 static errr Term_wipe_gcu(int x, int y, int n)
987 term_data *td = (term_data *)(Term->data);
990 wmove(td->win, y, x);
992 /* Clear to end of line */
997 /* Clear some characters */
1000 waddch(td->win, ' ');
1007 #ifdef USE_NCURSES_ACS
1009 * this function draws some ACS characters on the screen
1010 * for DOS-based users: these are the graphical chars (blocks, lines etc)
1012 * unix-gurus: before you start adding other attributes like A_REVERSE
1013 * think hard about how map_info() in cave.c should handle the color
1014 * of something that we here draw in reverse. It's not so simple, alas.
1016 static void Term_acs_text_gcu(int x, int y, int n, byte a, concptr s)
1018 term_data *td = (term_data *)(Term->data);
1021 /* position the cursor */
1022 wmove(td->win, y, x);
1026 wattrset(td->win, colortable[a & 0x0F]);
1029 for (i = 0; i < n; i++) {
1030 /* add acs_map of a */
1031 waddch(td->win, acs_map[(int)s[i]]);
1033 wattrset(td->win, WA_NORMAL);
1038 * Place some text on the screen using an attribute
1040 static errr Term_text_gcu(int x, int y, int n, byte a, concptr s)
1042 term_data *td = (term_data *)(Term->data);
1044 #ifdef USE_NCURSES_ACS
1045 /* do we have colors + 16 ? */
1046 /* then call special routine for drawing special characters */
1048 Term_acs_text_gcu(x, y, n, a, s);
1053 /* Move the cursor and dump the string */
1054 wmove(td->win, y, x);
1059 wattrset(td->win, colortable[a & 0x0F]);
1064 int text_len = euc_to_utf8(s, n, text, sizeof(text));
1070 waddnstr(td->win, _(text, s), _(text_len, n));
1076 static errr term_data_init(term_data *td, int rows, int cols, int y, int x)
1078 term_type *t = &td->t;
1080 /* Make sure the window has a positive size */
1081 if (rows <= 0 || cols <= 0)
1084 /* Create a window */
1085 td->win = newwin(rows, cols, y, x);
1087 /* Make sure we succeed */
1089 plog("Failed to setup curses window.");
1093 /* Initialize the term */
1094 term_init(t, cols, rows, 256);
1096 /* Avoid the bottom right corner */
1097 t->icky_corner = true;
1099 /* Erase with "white space" */
1100 t->attr_blank = TERM_WHITE;
1101 t->char_blank = ' ';
1103 /* Set some hooks */
1104 t->init_hook = Term_init_gcu;
1105 t->nuke_hook = Term_nuke_gcu;
1107 /* Set some more hooks */
1108 t->text_hook = Term_text_gcu;
1109 t->wipe_hook = Term_wipe_gcu;
1110 t->curs_hook = Term_curs_gcu;
1111 t->xtra_hook = Term_xtra_gcu;
1123 static void hook_quit(concptr str)
1133 * Prepare "curses" for use by the file "term.c"
1135 * Installs the "hook" functions defined above, and then activates
1136 * the main screen "term", which clears the screen and such things.
1138 * Someone should really check the semantics of "initscr()"
1140 errr init_gcu(int argc, char *argv[])
1144 int num_term = 4, next_win = 0;
1151 setlocale(LC_ALL, "");
1153 /* Build the "sound" path */
1154 path_build(path, sizeof(path), ANGBAND_DIR_XTRA, "sound");
1156 /* Allocate the path */
1157 ANGBAND_DIR_XTRA_SOUND = string_make(path);
1159 /* Extract the normal keymap */
1160 keymap_norm_prepare();
1162 /* Initialize for others systems */
1163 if (initscr() == (WINDOW *)ERR)
1166 /* Activate hooks */
1167 quit_aux = hook_quit;
1168 core_aux = hook_quit;
1170 /* Hack -- Require large screen, or Quit with message */
1171 i = ((LINES < 24) || (COLS < 80));
1173 quit("Angband needs an 80x24 'curses' screen");
1177 /*** Init the Color-pairs and set up a translation table ***/
1179 /* Do we have color, and enough color, available? */
1180 can_use_color = ((start_color() != ERR) && has_colors() && (COLORS >= 8) && (COLOR_PAIRS >= 8));
1182 #ifdef REDEFINE_COLORS
1183 /* Can we change colors? */
1184 can_fix_color = (can_use_color && can_change_color() && (COLORS >= 16) && (COLOR_PAIRS > 8));
1187 /* Attempt to use customized colors */
1188 if (can_fix_color) {
1189 /* Prepare the color pairs */
1190 for (i = 1; i <= 15; i++) {
1191 if (init_pair(i, i, 0) == ERR) {
1192 quit("Color pair init failed");
1195 colortable[i] = COLOR_PAIR(i);
1196 Term_xtra_gcu_react();
1199 /* Attempt to use colors */
1200 else if (can_use_color) {
1201 /* Color-pair 0 is *always* WHITE on BLACK */
1203 /* Prepare the color pairs */
1204 init_pair(1, COLOR_RED, COLOR_BLACK);
1205 init_pair(2, COLOR_GREEN, COLOR_BLACK);
1206 init_pair(3, COLOR_YELLOW, COLOR_BLACK);
1207 init_pair(4, COLOR_BLUE, COLOR_BLACK);
1208 init_pair(5, COLOR_MAGENTA, COLOR_BLACK);
1209 init_pair(6, COLOR_CYAN, COLOR_BLACK);
1210 init_pair(7, COLOR_BLACK, COLOR_BLACK);
1212 /* Prepare the "Angband Colors" -- Bright white is too bright */
1213 /* Changed in Drangband. Cyan as grey sucks -- -TM- */
1214 colortable[0] = (COLOR_PAIR(7) | A_NORMAL); /* Black */
1215 colortable[1] = (COLOR_PAIR(0) | A_BRIGHT); /* White */
1216 colortable[2] = (COLOR_PAIR(0) | A_NORMAL); /* Grey XXX */
1217 colortable[3] = (COLOR_PAIR(1) | A_BRIGHT); /* Orange XXX */
1218 colortable[4] = (COLOR_PAIR(1) | A_NORMAL); /* Red */
1219 colortable[5] = (COLOR_PAIR(2) | A_NORMAL); /* Green */
1220 colortable[6] = (COLOR_PAIR(4) | A_BRIGHT); /* Blue */
1221 colortable[7] = (COLOR_PAIR(3) | A_NORMAL); /* Umber */
1222 colortable[8] = (COLOR_PAIR(7) | A_BRIGHT); /* Dark-grey XXX */
1223 colortable[9] = (COLOR_PAIR(0) | A_NORMAL); /* Light-grey XXX */
1224 colortable[10] = (COLOR_PAIR(5) | A_BRIGHT); /* Purple */
1225 colortable[11] = (COLOR_PAIR(3) | A_BRIGHT); /* Yellow */
1226 colortable[12] = (COLOR_PAIR(5) | A_NORMAL); /* Light Red XXX */
1227 colortable[13] = (COLOR_PAIR(2) | A_BRIGHT); /* Light Green */
1228 colortable[14] = (COLOR_PAIR(6) | A_BRIGHT); /* Light Blue */
1229 colortable[15] = (COLOR_PAIR(3) | A_NORMAL); /* Light Umber XXX */
1234 /* Handle "arg_sound" */
1235 if (use_sound != arg_sound) {
1236 /* Initialize (if needed) */
1237 if (arg_sound && !init_sound()) {
1239 plog("Cannot initialize sound!");
1245 /* Change setting */
1246 use_sound = arg_sound;
1251 /* if USE_NCURSES_ACS is defined, we can do something with graphics in curses! */
1252 #ifdef USE_NCURSES_ACS
1253 use_graphics = true;
1257 /*** Low level preparation ***/
1261 /* Paranoia -- Assume no waiting */
1262 nodelay(stdscr, false);
1272 /* Extract the game keymap */
1273 keymap_game_prepare();
1275 /*** Now prepare the term(s) ***/
1276 for (i = 0; i < num_term; i++) {
1315 /* No non-windows */
1316 if (rows <= 0 || cols <= 0)
1320 term_data_init(&data[next_win], rows, cols, y, x);
1323 angband_term[next_win] = Term;
1328 /* Activate the "Angband" window screen */
1329 term_activate(&data[0].t);
1332 term_screen = &data[0].t;
1338 #endif /* USE_GCU */