#include "locale/japanese.h"
#include "main/sound-definitions-table.h"
#include "main/sound-of-music.h"
+#include "system/angband-version.h"
#include "system/angband.h"
+#include "system/player-type-definition.h"
#include "term/gameterm.h"
#include "term/term-color-types.h"
+#include "term/z-form.h"
#include "util/angband-files.h"
#include "view/display-map.h"
*/
#include <curses.h>
-typedef struct term_data term_data;
+/**
+ * Simple rectangle type
+ */
+struct rect_t {
+ int x, y;
+ int cx, cy;
+};
+/* Trivial rectangle utility to make code a bit more readable */
+static rect_t rect(int x, int y, int cx, int cy)
+{
+ rect_t r;
+ r.x = x;
+ r.y = y;
+ r.cx = cx;
+ r.cy = cy;
+ return r;
+}
+
+/**
+ * Information about a term
+ */
struct term_data {
term_type t;
-
+ rect_t r;
WINDOW *win;
};
+/* Max number of windows on screen */
#define MAX_TERM_DATA 4
+/* Minimum main term size */
+#define MIN_TERM0_LINES 24
+#define MIN_TERM0_COLS 80
+
+/* Information about our windows */
static term_data data[MAX_TERM_DATA];
/*
#if defined(_POSIX_VERSION)
#define USE_TPOSIX
#else
-#if defined(linux)
-#define USE_TERMIO
-#else
#define USE_TCHARS
#endif
#endif
-#endif
/*
* Try redefining the colors at startup.
* todo 有効活用されていない疑惑
* Flag set once "sound" has been initialized
*/
-static bool can_use_sound = FALSE;
+static bool can_use_sound = false;
/*
* An array of sound file names
/*
* Software flag -- we are allowed to use color
*/
-static int can_use_color = FALSE;
+static int can_use_color = false;
/*
* Software flag -- we are allowed to change the colors
*/
-static int can_fix_color = FALSE;
+static int can_fix_color = false;
/*
* Simple Angband to Curses color conversion table
*/
static int colortable[16];
+
+/**
+ * Background color we should draw with; either BLACK or DEFAULT
+ */
+static int bg_color = COLOR_BLACK;
+
#endif
/*
/*
* Suspend/Resume
*/
-static errr Term_xtra_gcu_alive(int v)
+static errr game_term_xtra_gcu_alive(int v)
{
if (!v) {
/* Go to normal keymap mode */
keymap_game();
}
- return (0);
+ return 0;
}
/*
{
FILE *fff;
fff = fopen(s, "r");
- if (!fff)
- return (FALSE);
+ if (!fff) {
+ return false;
+ }
fclose(fff);
- return (TRUE);
+ return true;
}
/*
static bool init_sound(void)
{
/* Initialize once */
- if (can_use_sound)
+ if (can_use_sound) {
return can_use_sound;
+ }
int i;
char wav[128];
path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA_SOUND, wav);
/* Save the sound filename, if it exists */
- if (check_file(buf))
+ if (check_file(buf)) {
sound_file[i] = string_make(buf);
+ }
}
/* Sound available */
- can_use_sound = TRUE;
- return (can_use_sound);
+ can_use_sound = true;
+ return can_use_sound;
}
/*
* Init the "curses" system
*/
-static void Term_init_gcu(term_type *t)
+static void game_term_init_gcu(term_type *t)
{
term_data *td = (term_data *)(t->data);
/* Count init's, handle first */
- if (active++ != 0)
+ if (active++ != 0) {
return;
+ }
/* Erase the screen */
(void)wclear(td->win);
/*
* Nuke the "curses" system
*/
-static void Term_nuke_gcu(term_type *t)
+static void game_term_nuke_gcu(term_type *t)
{
term_data *td = (term_data *)(t->data);
delwin(td->win);
/* Count nuke's, handle last */
- if (--active != 0)
+ if (--active != 0) {
return;
+ }
/* Hack -- make sure the cursor is visible */
term_xtra(TERM_XTRA_SHAPE, 1);
static void term_string_push(char *buf)
{
int i, l = strlen(buf);
- for (i = l; i >= 0; i--)
+ for (i = l; i >= 0; i--) {
term_key_push(buf[i]);
+ }
}
#ifdef USE_GETCH
/*
* Process events, with optional wait
*/
-static errr Term_xtra_gcu_event(int v)
+static errr game_term_xtra_gcu_event(int v)
{
int i, k;
char *bp = buf;
/* Paranoia -- Wait for it */
- nodelay(stdscr, FALSE);
+ nodelay(stdscr, false);
/* Get a keypress */
i = getch();
/* Broken input is special */
- if (i == ERR)
+ if (i == ERR) {
exit_game_panic(p_ptr);
- if (i == EOF)
+ }
+ if (i == EOF) {
exit_game_panic(p_ptr);
+ }
*bp++ = (char)i;
/* Do not wait for it */
- nodelay(stdscr, TRUE);
+ nodelay(stdscr, true);
while ((i = getch()) != EOF) {
- if (i == ERR)
+ if (i == ERR) {
exit_game_panic(p_ptr);
+ }
*bp++ = (char)i;
- if (bp == &buf[255])
+ if (bp == &buf[255]) {
break;
+ }
}
/* Wait for it next time */
- nodelay(stdscr, FALSE);
+ nodelay(stdscr, false);
*bp = '\0';
#ifdef JP
char eucbuf[sizeof(buf)];
/* strlen + 1 を渡して文字列終端('\0')を含めて変換する */
if (utf8_to_euc(buf, strlen(buf) + 1, eucbuf, sizeof(eucbuf)) < 0) {
- return (-1);
+ return -1;
}
#endif
term_string_push(_(eucbuf, buf));
/* Do not wait */
else {
/* Do not wait for it */
- nodelay(stdscr, TRUE);
+ nodelay(stdscr, true);
/* Check for keypresses */
i = getch();
/* Wait for it next time */
- nodelay(stdscr, FALSE);
+ nodelay(stdscr, false);
/* None ready */
- if (i == ERR)
- return (1);
- if (i == EOF)
- return (1);
+ if (i == ERR) {
+ return 1;
+ }
+ if (i == EOF) {
+ return 1;
+ }
/* Enqueue the keypress */
term_key_push(i);
}
/* Success */
- return (0);
+ return 0;
}
#else /* USE_GETCH */
/*
* Process events (with optional wait)
*/
-static errr Term_xtra_gcu_event(int v)
+static errr game_term_xtra_gcu_event(int v)
{
int i, k;
i = read(0, bp++, 1);
/* Hack -- Handle bizarre "errors" */
- if ((i <= 0) && (errno != EINTR))
+ if ((i <= 0) && (errno != EINTR)) {
exit_game_panic(p_ptr);
+ }
/* Get the current flags for stdin */
k = fcntl(0, F_GETFL, 0);
/* Oops */
- if (k < 0)
- return (1);
+ if (k < 0) {
+ return 1;
+ }
/* Tell stdin not to block */
if (fcntl(0, F_SETFL, k | O_NDELAY) >= 0) {
}
/* Replace the flags for stdin */
- if (fcntl(0, F_SETFL, k))
- return (1);
+ if (fcntl(0, F_SETFL, k)) {
+ return 1;
+ }
}
bp[0] = '\0';
char eucbuf[sizeof(buf)];
/* strlen + 1 を渡して文字列終端('\0')を含めて変換する */
if (utf8_to_euc(buf, strlen(buf) + 1, eucbuf, sizeof(eucbuf)) < 0) {
- return (-1);
+ return -1;
}
#endif
term_string_push(_(eucbuf, buf));
k = fcntl(0, F_GETFL, 0);
/* Oops */
- if (k < 0)
- return (1);
+ if (k < 0) {
+ return 1;
+ }
/* Tell stdin not to block */
- if (fcntl(0, F_SETFL, k | O_NDELAY) < 0)
- return (1);
+ if (fcntl(0, F_SETFL, k | O_NDELAY) < 0) {
+ return 1;
+ }
/* Read one byte, if possible */
i = read(0, buf, 1);
/* Replace the flags for stdin */
- if (fcntl(0, F_SETFL, k))
- return (1);
+ if (fcntl(0, F_SETFL, k)) {
+ return 1;
+ }
/* Ignore "invalid" keys */
- if ((i != 1) || (!buf[0]))
- return (1);
+ if ((i != 1) || (!buf[0])) {
+ return 1;
+ }
/* Enqueue the keypress */
term_key_push(buf[0]);
}
/* Success */
- return (0);
+ return 0;
}
#endif /* USE_GETCH */
/*
* Hack -- make a sound
*/
-static errr Term_xtra_gcu_sound(int v)
+static errr game_term_xtra_gcu_sound(int v)
{
char buf[1024];
/* Sound disabled */
- if (!use_sound)
- return (1);
+ if (!use_sound) {
+ return 1;
+ }
/* Illegal sound */
- if ((v < 0) || (v >= SOUND_MAX))
- return (1);
+ if ((v < 0) || (v >= SOUND_MAX)) {
+ return 1;
+ }
/* Unknown sound */
- if (!sound_file[v])
- return (1);
+ if (!sound_file[v]) {
+ return 1;
+ }
sprintf(buf, "./gcusound.sh %s\n", sound_file[v]);
- return (system(buf) < 0);
+ return system(buf) < 0;
+
+ return 0;
+}
+
+static int scale_color(int i, int j, int scale)
+{
+ return (angband_color_table[i][j] * (scale - 1) + 127) / 255;
+}
- return (0);
+static int create_color(int i, int scale)
+{
+ int r = scale_color(i, 1, scale);
+ int g = scale_color(i, 2, scale);
+ int b = scale_color(i, 3, scale);
+ int rgb = 16 + scale * scale * r + scale * g + b;
+ /* In the case of white and black we need to use the ANSI colors */
+ if (r == g && g == b) {
+ if (b == 0) {
+ rgb = 0;
+ }
+ if (b == scale) {
+ rgb = 15;
+ }
+ }
+ return rgb;
}
/*
* React to changes
*/
-static errr Term_xtra_gcu_react(void)
+static errr game_term_xtra_gcu_react(void)
{
#ifdef A_COLOR
- int i;
-
- /* Cannot handle color redefinition */
- if (!can_fix_color)
- return (0);
-
- /* Set the colors */
- for (i = 0; i < 16; i++) {
- /* Set one color (note scaling) */
- init_color(i, angband_color_table[i][1] * 1000 / 255, angband_color_table[i][2] * 1000 / 255, angband_color_table[i][3] * 1000 / 255);
+ if (!can_change_color()) {
+ if (COLORS == 256 || COLORS == 88) {
+ /* If we have more than 16 colors, find the best matches. These numbers
+ * correspond to xterm/rxvt's builtin color numbers--they do not
+ * correspond to curses' constants OR with curses' color pairs.
+ *
+ * XTerm has 216 (6*6*6) RGB colors, with each RGB setting 0-5.
+ * RXVT has 64 (4*4*4) RGB colors, with each RGB setting 0-3.
+ *
+ * Both also have the basic 16 ANSI colors, plus some extra grayscale
+ * colors which we do not use.
+ */
+ int scale = COLORS == 256 ? 6 : 4;
+ for (int i = 0; i < 16; i++) {
+ int fg = create_color(i, scale);
+ init_pair(i + 1, fg, bg_color);
+ colortable[i] = COLOR_PAIR(i + 1) | A_NORMAL;
+ }
+ }
+ } else {
+ for (int i = 0; i < 16; ++i) {
+ init_color(i,
+ (angband_color_table[i][1] * 1000) / 255,
+ (angband_color_table[i][2] * 1000) / 255,
+ (angband_color_table[i][3] * 1000) / 255);
+ }
}
#endif
/* Success */
- return (0);
+ return 0;
}
/*
* Handle a "special request"
*/
-static errr Term_xtra_gcu(int n, int v)
+static errr game_term_xtra_gcu(int n, int v)
{
- term_data *td = (term_data *)(Term->data);
+ term_data *td = (term_data *)(game_term->data);
/* Analyze the request */
switch (n) {
case TERM_XTRA_CLEAR:
touchwin(td->win);
(void)wclear(td->win);
- return (0);
+ return 0;
/* Make a noise */
case TERM_XTRA_NOISE:
/* Make a special sound */
case TERM_XTRA_SOUND:
- return (Term_xtra_gcu_sound(v));
+ return game_term_xtra_gcu_sound(v);
/* Flush the Curses buffer */
case TERM_XTRA_FRESH:
(void)wrefresh(td->win);
- return (0);
-
-#ifdef USE_CURS_SET
+ return 0;
/* Change the cursor visibility */
case TERM_XTRA_SHAPE:
curs_set(v);
- return (0);
-
-#endif
+ return 0;
/* Suspend/Resume curses */
case TERM_XTRA_ALIVE:
- return (Term_xtra_gcu_alive(v));
+ return game_term_xtra_gcu_alive(v);
/* Process events */
case TERM_XTRA_EVENT:
- return (Term_xtra_gcu_event(v));
+ return game_term_xtra_gcu_event(v);
/* Flush events */
case TERM_XTRA_FLUSH:
- while (!Term_xtra_gcu_event(FALSE))
+ while (!game_term_xtra_gcu_event(false)) {
;
- return (0);
+ }
+ return 0;
/* Delay */
case TERM_XTRA_DELAY:
usleep(1000 * v);
- return (0);
+ return 0;
/* React to events */
case TERM_XTRA_REACT:
- Term_xtra_gcu_react();
- return (0);
+ game_term_xtra_gcu_react();
+ return 0;
}
/* Unknown */
- return (1);
+ return 1;
}
/*
* Actually MOVE the hardware cursor
*/
-static errr Term_curs_gcu(int x, int y)
+static errr game_term_curs_gcu(int x, int y)
{
- term_data *td = (term_data *)(Term->data);
+ term_data *td = (term_data *)(game_term->data);
/* Literally move the cursor */
wmove(td->win, y, x);
/* Success */
- return (0);
+ return 0;
}
/*
* Erase a grid of space
* Hack -- try to be "semi-efficient".
*/
-static errr Term_wipe_gcu(int x, int y, int n)
+static errr game_term_wipe_gcu(int x, int y, int n)
{
- term_data *td = (term_data *)(Term->data);
+ term_data *td = (term_data *)(game_term->data);
/* Place cursor */
wmove(td->win, y, x);
/* Clear to end of line */
- if (x + n >= 80) {
+ if (x + n >= td->t.wid) {
wclrtoeol(td->win);
}
/* Clear some characters */
else {
- while (n-- > 0)
+ while (n-- > 0) {
waddch(td->win, ' ');
+ }
}
/* Success */
- return (0);
+ return 0;
}
#ifdef USE_NCURSES_ACS
* think hard about how map_info() in cave.c should handle the color
* of something that we here draw in reverse. It's not so simple, alas.
*/
-static void Term_acs_text_gcu(int x, int y, int n, byte a, concptr s)
+static void game_term_acs_text_gcu(int x, int y, int n, byte a, concptr s)
{
- term_data *td = (term_data *)(Term->data);
+ term_data *td = (term_data *)(game_term->data);
int i;
/* position the cursor */
/*
* Place some text on the screen using an attribute
*/
-static errr Term_text_gcu(int x, int y, int n, byte a, concptr s)
+static errr game_term_text_gcu(int x, int y, int n, byte a, concptr s)
{
- term_data *td = (term_data *)(Term->data);
+ term_data *td = (term_data *)(game_term->data);
#ifdef USE_NCURSES_ACS
/* do we have colors + 16 ? */
/* then call special routine for drawing special characters */
if (a & 0x10) {
- Term_acs_text_gcu(x, y, n, a, s);
- return (0);
+ game_term_acs_text_gcu(x, y, n, a, s);
+ return 0;
}
#endif
#ifdef A_COLOR
/* Set the color */
- if (can_use_color)
+ if (can_use_color) {
wattrset(td->win, colortable[a & 0x0F]);
+ }
#endif
#ifdef JP
char text[1024];
int text_len = euc_to_utf8(s, n, text, sizeof(text));
if (text_len < 0) {
- return (-1);
+ return -1;
}
#endif
/* Add the text */
waddnstr(td->win, _(text, s), _(text_len, n));
/* Success */
- return (0);
+ return 0;
}
-static errr term_data_init(term_data *td, int rows, int cols, int y, int x)
+/**
+ * Create a window for the given "term_data" argument.
+ *
+ * Assumes legal arguments.
+ */
+static errr term_data_init_gcu(term_data *td, int rows, int cols, int y, int x)
{
term_type *t = &td->t;
/* Make sure the window has a positive size */
- if (rows <= 0 || cols <= 0)
- return (0);
+ if (rows <= 0 || cols <= 0) {
+ return 0;
+ }
/* Create a window */
td->win = newwin(rows, cols, y, x);
/* Make sure we succeed */
if (!td->win) {
plog("Failed to setup curses window.");
- return (-1);
+ return -1;
}
/* Initialize the term */
term_init(t, cols, rows, 256);
/* Avoid the bottom right corner */
- t->icky_corner = TRUE;
+ t->icky_corner = true;
/* Erase with "white space" */
t->attr_blank = TERM_WHITE;
t->char_blank = ' ';
/* Set some hooks */
- t->init_hook = Term_init_gcu;
- t->nuke_hook = Term_nuke_gcu;
+ t->init_hook = game_term_init_gcu;
+ t->nuke_hook = game_term_nuke_gcu;
/* Set some more hooks */
- t->text_hook = Term_text_gcu;
- t->wipe_hook = Term_wipe_gcu;
- t->curs_hook = Term_curs_gcu;
- t->xtra_hook = Term_xtra_gcu;
+ t->text_hook = game_term_text_gcu;
+ t->wipe_hook = game_term_wipe_gcu;
+ t->curs_hook = game_term_curs_gcu;
+ t->xtra_hook = game_term_xtra_gcu;
/* Save the data */
t->data = td;
term_activate(t);
/* Success */
- return (0);
+ return 0;
+}
+
+/**
+ * Simple helper
+ */
+static errr term_data_init(term_data *td)
+{
+ return term_data_init_gcu(td, td->r.cy, td->r.cx, td->r.y, td->r.x);
+}
+
+/* Parse 27,15,*x30 up to the 'x'. * gets converted to a big number
+ Parse 32,* until the end. Return count of numbers parsed */
+static int _parse_size_list(const char *arg, int sizes[], int max)
+{
+ int i = 0;
+ const char *start = arg;
+ const char *stop = arg;
+
+ for (;;) {
+ if (!*stop || !isdigit(*stop)) {
+ if (i >= max) {
+ break;
+ }
+ if (*start == '*') {
+ sizes[i] = 255;
+ } else {
+ /* rely on atoi("23,34,*") -> 23
+ otherwise, copy [start, stop) into a new buffer first.*/
+ sizes[i] = atoi(start);
+ }
+ i++;
+ if (!*stop || *stop != ',') {
+ break;
+ }
+
+ stop++;
+ start = stop;
+ } else {
+ stop++;
+ }
+ }
+ return i;
}
static void hook_quit(concptr str)
/* Extract the normal keymap */
keymap_norm_prepare();
+ bool nobigscreen = false;
+
+ /* Parse args */
+ for (i = 1; i < argc; i++) {
+ if (prefix(argv[i], "-o")) {
+ nobigscreen = true;
+ }
+ }
+
/* Initialize for others systems */
- if (initscr() == (WINDOW *)ERR)
- return (-1);
+ if (initscr() == (WINDOW *)ERR) {
+ return -1;
+ }
/* Activate hooks */
quit_aux = hook_quit;
/* Hack -- Require large screen, or Quit with message */
i = ((LINES < 24) || (COLS < 80));
- if (i)
- quit("Angband needs an 80x24 'curses' screen");
+ if (i) {
+ quit_fmt("%s needs an 80x24 'curses' screen", std::string(VARIANT_NAME).c_str());
+ }
#ifdef A_COLOR
}
colortable[i] = COLOR_PAIR(i);
- Term_xtra_gcu_react();
+ game_term_xtra_gcu_react();
}
}
/* Attempt to use colors */
plog("Cannot initialize sound!");
/* Cannot enable */
- arg_sound = FALSE;
+ arg_sound = false;
}
/* Change setting */
if (arg_graphics) {
/* if USE_NCURSES_ACS is defined, we can do something with graphics in curses! */
#ifdef USE_NCURSES_ACS
- use_graphics = TRUE;
+ use_graphics = true;
#endif
}
#ifdef USE_GETCH
/* Paranoia -- Assume no waiting */
- nodelay(stdscr, FALSE);
+ nodelay(stdscr, false);
#endif
keymap_game_prepare();
/*** Now prepare the term(s) ***/
- for (i = 0; i < num_term; i++) {
- int rows, cols;
- int y, x;
-
- switch (i) {
- /* Upper left */
- case 0:
- rows = 24;
- cols = 80;
- y = x = 0;
- break;
- /* Lower left */
- case 1:
- rows = LINES - 25;
- cols = 80;
- y = 24;
- x = 0;
- break;
- /* Upper right */
- case 2:
- rows = 24;
- cols = COLS - 81;
- y = 0;
- x = 81;
- break;
- /* Lower right */
- case 3:
- rows = LINES - 25;
- cols = COLS - 81;
- y = 24;
- x = 81;
- break;
- /* XXX */
- default:
- rows = cols = 0;
- y = x = 0;
- break;
- }
+ if (nobigscreen) {
+ /* Create several terms */
+ for (i = 0; i < num_term; i++) {
+ int rows, cols, y, x;
+
+ /* Decide on size and position */
+ switch (i) {
+ /* Upper left */
+ case 0: {
+ rows = 24;
+ cols = 80;
+ y = x = 0;
+ break;
+ }
+
+ /* Lower left */
+ case 1: {
+ rows = LINES - 25;
+ cols = 80;
+ y = 25;
+ x = 0;
+ break;
+ }
+
+ /* Upper right */
+ case 2: {
+ rows = 24;
+ cols = COLS - 81;
+ y = 0;
+ x = 81;
+ break;
+ }
+
+ /* Lower right */
+ case 3: {
+ rows = LINES - 25;
+ cols = COLS - 81;
+ y = 25;
+ x = 81;
+ break;
+ }
- /* No non-windows */
- if (rows <= 0 || cols <= 0)
- continue;
+ /* XXX */
+ default: {
+ rows = cols = y = x = 0;
+ break;
+ }
+ }
+
+ /* Skip non-existant windows */
+ if (rows <= 0 || cols <= 0) {
+ continue;
+ }
- /* Initialize */
- term_data_init(&data[next_win], rows, cols, y, x);
+ /* Create a term */
+ term_data_init_gcu(&data[next_win], rows, cols, y, x);
- /* Store */
- angband_term[next_win] = Term;
+ /* Remember the term */
+ angband_term[next_win] = &data[next_win].t;
- next_win++;
+ /* One more window */
+ next_win++;
+ }
+ } else
+ /* Parse Args and Prepare the Terminals. Rectangles are specified
+ as Width x Height, right? The game will allow you to have two
+ strips of extra terminals, one on the right and one on the bottom.
+ The map terminal will than fit in as big as possible in the remaining
+ space.
+ Examples:
+ angband -mgcu -- -right 30x27,* -bottom *x7 will layout as
+ Term-0: Map (COLS-30)x(LINES-7) | Term-1: 30x27
+ --------------------------------|----------------------
+ <----Term-3: (COLS-30)x7------->| Term-2: 30x(LINES-27)
+ composband -mgcu -- -bottom *x7 -right 30x27,* will layout as
+ Term-0: Map (COLS-30)x(LINES-7) | Term-2: 30x27
+ |------------------------------
+ | Term-3: 30x(LINES-27)
+ ---------------------------------------------------------------
+ <----------Term-1: (COLS)x7----------------------------------->
+ Notice the effect on the bottom terminal by specifying its argument
+ second or first. Notice the sequence numbers for the various terminals
+ as you will have to blindly configure them in the window setup screen.
+ EDIT: Added support for -left and -top.
+ */
+ {
+ rect_t remaining = rect(0, 0, COLS, LINES);
+ int spacer_cx = 1;
+ int spacer_cy = 1;
+ int next_term = 1;
+ int term_ct = 1;
+
+ for (i = 1; i < argc; i++) {
+ if (streq(argv[i], "-spacer")) {
+ i++;
+ if (i >= argc) {
+ quit("Missing size specifier for -spacer");
+ }
+ sscanf(argv[i], "%dx%d", &spacer_cx, &spacer_cy);
+ } else if (streq(argv[i], "-right") || streq(argv[i], "-left")) {
+ const char *arg, *tmp;
+ bool left = streq(argv[i], "-left");
+ int cx, cys[MAX_TERM_DATA] = { 0 }, ct, j, x, y;
+
+ i++;
+ if (i >= argc) {
+ quit(format("Missing size specifier for -%s", left ? "left" : "right"));
+ }
+
+ arg = argv[i];
+ tmp = strchr(arg, 'x');
+ if (!tmp) {
+ quit(format("Expected something like -%s 60x27,* for two %s hand terminals of 60 columns, the first 27 lines and the second whatever is left.", left ? "left" : "right", left ? "left" : "right"));
+ }
+ cx = atoi(arg);
+ remaining.cx -= cx;
+ if (left) {
+ x = remaining.x;
+ y = remaining.y;
+ remaining.x += cx;
+ } else {
+ x = remaining.x + remaining.cx;
+ y = remaining.y;
+ }
+ remaining.cx -= spacer_cx;
+ if (left) {
+ remaining.x += spacer_cx;
+ }
+
+ tmp++;
+ ct = _parse_size_list(tmp, cys, MAX_TERM_DATA);
+ for (j = 0; j < ct; j++) {
+ int cy = cys[j];
+ if (y + cy > remaining.y + remaining.cy) {
+ cy = remaining.y + remaining.cy - y;
+ }
+ if (next_term >= MAX_TERM_DATA) {
+ quit(format("Too many terminals. Only %d are allowed.", MAX_TERM_DATA));
+ }
+ if (cy <= 0) {
+ quit(format("Out of bounds in -%s: %d is too large (%d rows max for this strip)",
+ left ? "left" : "right", cys[j], remaining.cy));
+ }
+ data[next_term++].r = rect(x, y, cx, cy);
+ y += cy + spacer_cy;
+ term_ct++;
+ }
+ } else if (streq(argv[i], "-top") || streq(argv[i], "-bottom")) {
+ const char *arg, *tmp;
+ bool top = streq(argv[i], "-top");
+ int cy, cxs[MAX_TERM_DATA] = { 0 }, ct, j, x, y;
+
+ i++;
+ if (i >= argc) {
+ quit(format("Missing size specifier for -%s", top ? "top" : "bottom"));
+ }
+
+ arg = argv[i];
+ tmp = strchr(arg, 'x');
+ if (!tmp) {
+ quit(format("Expected something like -%s *x7 for a single %s terminal of 7 lines using as many columns as are available.", top ? "top" : "bottom", top ? "top" : "bottom"));
+ }
+ tmp++;
+ cy = atoi(tmp);
+ ct = _parse_size_list(arg, cxs, MAX_TERM_DATA);
+
+ remaining.cy -= cy;
+ if (top) {
+ x = remaining.x;
+ y = remaining.y;
+ remaining.y += cy;
+ } else {
+ x = remaining.x;
+ y = remaining.y + remaining.cy;
+ }
+ remaining.cy -= spacer_cy;
+ if (top) {
+ remaining.y += spacer_cy;
+ }
+
+ tmp++;
+ for (j = 0; j < ct; j++) {
+ int cx = cxs[j];
+ if (x + cx > remaining.x + remaining.cx) {
+ cx = remaining.x + remaining.cx - x;
+ }
+ if (next_term >= MAX_TERM_DATA) {
+ quit(format("Too many terminals. Only %d are allowed.", MAX_TERM_DATA));
+ }
+ if (cx <= 0) {
+ quit(format("Out of bounds in -%s: %d is too large (%d cols max for this strip)",
+ top ? "top" : "bottom", cxs[j], remaining.cx));
+ }
+ data[next_term++].r = rect(x, y, cx, cy);
+ x += cx + spacer_cx;
+ term_ct++;
+ }
+ }
+ }
+
+ /* Map Terminal */
+ if (remaining.cx < MIN_TERM0_COLS || remaining.cy < MIN_TERM0_LINES) {
+ quit_fmt("Failed: %s needs an %dx%d map screen, not %dx%d", std::string(VARIANT_NAME).c_str(), MIN_TERM0_COLS, MIN_TERM0_LINES, remaining.cx, remaining.cy);
+ }
+ data[0].r = remaining;
+ term_data_init(&data[0]);
+ angband_term[0] = game_term;
+
+ /* Child Terminals */
+ for (next_term = 1; next_term < term_ct; next_term++) {
+ term_data_init(&data[next_term]);
+ angband_term[next_term] = game_term;
+ }
}
/* Activate the "Angband" window screen */
term_screen = &data[0].t;
/* Success */
- return (0);
+ return 0;
}
#endif /* USE_GCU */