2011-07-02 00:53:45 -04:00
|
|
|
/************************************************************************
|
|
|
|
* *
|
|
|
|
* Star Traders: A Game of Interstellar Trading *
|
|
|
|
* Copyright (C) 1990-2011, John Zaitseff *
|
|
|
|
* *
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Author: John Zaitseff <J.Zaitseff@zap.org.au>
|
|
|
|
$Id$
|
|
|
|
|
|
|
|
This file, intf.c, contains the actual implementation of basic text
|
|
|
|
input/output routines as used in Star Traders.
|
|
|
|
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify it
|
|
|
|
under the terms of the GNU General Public License as published by the
|
|
|
|
Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see http://www.gnu.org/licenses/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "system.h"
|
|
|
|
#include "intf.h"
|
2011-07-02 07:25:57 -04:00
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
|
2011-07-03 22:41:30 -04:00
|
|
|
/************************************************************************
|
|
|
|
* Module constants and type declarations *
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
#define OUTBUFSIZE (1024) /* Output string buffer size */
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct txwin {
|
|
|
|
WINDOW *win; // Pointer to window structure
|
|
|
|
struct txwin *next; // Next window in stack
|
|
|
|
struct txwin *prev; // Previous window in stack
|
|
|
|
} txwin_t;
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* Global variable definitions *
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
WINDOW *curwin = NULL; // Top-most (current) window
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* Module variables *
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
txwin_t *topwin = NULL; // Top-most txwin structure
|
|
|
|
txwin_t *firstwin = NULL; // First (bottom-most) txwin structure
|
|
|
|
|
|
|
|
|
2011-07-02 07:25:57 -04:00
|
|
|
/************************************************************************
|
|
|
|
* Basic text input/output function definitions *
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
Function: init_screen - Initialise the screen (terminal)
|
|
|
|
Arguments: (none)
|
|
|
|
Returns: (nothing)
|
|
|
|
|
|
|
|
This function initialises the input (keyboard) and output (screen)
|
|
|
|
using the Curses library.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void init_screen (void)
|
|
|
|
{
|
|
|
|
initscr();
|
|
|
|
|
2011-07-02 09:19:40 -04:00
|
|
|
if ((COLS < MIN_COLS) || (LINES < MIN_LINES)) {
|
2011-07-02 07:25:57 -04:00
|
|
|
err_exit("terminal size is too small (%d x %d required)",
|
2011-07-02 09:19:40 -04:00
|
|
|
MIN_COLS, MIN_LINES);
|
2011-07-02 07:25:57 -04:00
|
|
|
}
|
|
|
|
|
2011-07-03 22:41:30 -04:00
|
|
|
curwin = stdscr;
|
|
|
|
topwin = NULL;
|
|
|
|
firstwin = NULL;
|
|
|
|
|
2011-07-02 07:25:57 -04:00
|
|
|
noecho();
|
2011-07-04 08:02:01 -04:00
|
|
|
curs_set(CURS_OFF);
|
2011-07-02 07:25:57 -04:00
|
|
|
raw();
|
|
|
|
|
|
|
|
if (has_colors()) {
|
|
|
|
start_color();
|
|
|
|
|
2011-07-04 08:02:01 -04:00
|
|
|
init_pair(WHITE_ON_BLACK, COLOR_WHITE, COLOR_BLACK);
|
|
|
|
init_pair(WHITE_ON_BLUE, COLOR_WHITE, COLOR_BLUE);
|
|
|
|
init_pair(WHITE_ON_RED, COLOR_WHITE, COLOR_RED);
|
|
|
|
init_pair(YELLOW_ON_BLACK, COLOR_YELLOW, COLOR_BLACK);
|
|
|
|
init_pair(YELLOW_ON_BLUE, COLOR_YELLOW, COLOR_BLUE);
|
|
|
|
init_pair(YELLOW_ON_CYAN, COLOR_YELLOW, COLOR_CYAN);
|
|
|
|
init_pair(BLACK_ON_WHITE, COLOR_BLACK, COLOR_WHITE);
|
2011-07-02 07:25:57 -04:00
|
|
|
|
|
|
|
bkgd(COLOR_PAIR(WHITE_ON_BLACK));
|
|
|
|
}
|
|
|
|
|
|
|
|
clear();
|
|
|
|
|
2011-07-04 04:22:24 -04:00
|
|
|
attrset(ATTR(COLOR_PAIR(YELLOW_ON_CYAN) | A_BOLD, A_REVERSE | A_BOLD));
|
2011-07-04 03:54:30 -04:00
|
|
|
center(stdscr, 0, true, PACKAGE_NAME);
|
2011-07-02 07:25:57 -04:00
|
|
|
attrset(A_NORMAL);
|
|
|
|
|
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
Function: end_screen - End using the screen (terminal)
|
|
|
|
Arguments: (none)
|
|
|
|
Returns: (nothing)
|
|
|
|
|
|
|
|
This function closes the input (keyboard) and output (screen) using the
|
|
|
|
Curses library. It makes sure the screen is cleared before doing so.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void end_screen (void)
|
|
|
|
{
|
2011-07-03 22:41:30 -04:00
|
|
|
delalltxwin();
|
|
|
|
|
2011-07-02 07:25:57 -04:00
|
|
|
clear();
|
|
|
|
refresh();
|
|
|
|
endwin();
|
2011-07-03 22:41:30 -04:00
|
|
|
|
|
|
|
curwin = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-04 08:02:01 -04:00
|
|
|
/************************************************************************
|
|
|
|
* Simplified panel-like window functions *
|
|
|
|
************************************************************************/
|
|
|
|
|
2011-07-03 22:41:30 -04:00
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
Function: newtxwin - Create a new window, inserted into window stack
|
|
|
|
Arguments: nlines - Number of lines in new window
|
|
|
|
ncols - Number of columns in new window
|
|
|
|
begin_y - Starting line number (global coordinates)
|
|
|
|
begin_x - Starting column number (global coordinates)
|
|
|
|
Returns: WINDOW * - Pointer to new window structure
|
|
|
|
|
|
|
|
This function creates a window (using the Curses newwin() function) and
|
|
|
|
places it top-most in the stack of windows managed by this module. A
|
|
|
|
pointer to the new window is returned; the global variable "curwin"
|
|
|
|
also points to this new window. Please note that wrefresh() is NOT
|
|
|
|
called on the new window.
|
|
|
|
*/
|
|
|
|
|
|
|
|
WINDOW *newtxwin (int nlines, int ncols, int begin_y, int begin_x)
|
|
|
|
{
|
2011-07-04 05:41:55 -04:00
|
|
|
WINDOW *win;
|
|
|
|
txwin_t *nw;
|
2011-07-03 22:41:30 -04:00
|
|
|
|
|
|
|
|
|
|
|
win = newwin(nlines, ncols, begin_y, begin_x);
|
|
|
|
if (win == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
nw = malloc(sizeof(txwin_t));
|
|
|
|
if (nw == NULL) {
|
|
|
|
delwin(win);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
nw->win = win;
|
|
|
|
nw->next = NULL;
|
|
|
|
nw->prev = topwin;
|
|
|
|
|
|
|
|
if (topwin != NULL) {
|
|
|
|
topwin->next = nw;
|
|
|
|
}
|
|
|
|
|
|
|
|
topwin = nw;
|
|
|
|
curwin = win;
|
|
|
|
|
|
|
|
if (firstwin == NULL) {
|
|
|
|
firstwin = nw;
|
|
|
|
}
|
|
|
|
|
|
|
|
return win;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
Function: deltxwin - Delete the top-most window in window stack
|
|
|
|
Arguments: (none)
|
|
|
|
Returns: int - OK if all well, ERR if not
|
|
|
|
|
|
|
|
This function deletes the top-most window in the stack of windows
|
|
|
|
managed by this module. ERR is returned if there is no such window, or
|
|
|
|
if delwin() fails. Please note that the actual screen is NOT
|
|
|
|
refreshed: a call to txrefresh() should follow this one. This allows
|
|
|
|
multiple windows to be deleted without screen flashing.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int deltxwin (void)
|
|
|
|
{
|
2011-07-04 05:41:55 -04:00
|
|
|
txwin_t *cur, *prev;
|
|
|
|
int ret;
|
2011-07-03 22:41:30 -04:00
|
|
|
|
|
|
|
|
|
|
|
if (topwin == NULL) {
|
|
|
|
return ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = topwin;
|
|
|
|
prev = topwin->prev;
|
|
|
|
topwin = prev;
|
|
|
|
|
|
|
|
if (prev != NULL) {
|
|
|
|
prev->next = NULL;
|
|
|
|
curwin = prev->win;
|
|
|
|
} else {
|
|
|
|
firstwin = NULL;
|
|
|
|
curwin = stdscr;
|
|
|
|
}
|
|
|
|
|
2011-07-04 05:41:55 -04:00
|
|
|
ret = delwin(cur->win);
|
2011-07-03 22:41:30 -04:00
|
|
|
free(cur);
|
|
|
|
|
2011-07-04 05:41:55 -04:00
|
|
|
return ret;
|
2011-07-03 22:41:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
Function: delalltxwin - Delete all windows in the window stack
|
|
|
|
Arguments: (none)
|
|
|
|
Returns: int - OK is always returned
|
|
|
|
|
|
|
|
This function deletes all windows in the stack of windows managed by
|
|
|
|
this module. After calling this function, the global variable "curwin"
|
|
|
|
points to "stdscr", the only window for which output is now permitted.
|
|
|
|
Please note that the screen is NOT refreshed; a call to txrefresh()
|
|
|
|
should follow this one if appropriate.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int delalltxwin (void)
|
|
|
|
{
|
|
|
|
while (topwin != NULL) {
|
|
|
|
deltxwin();
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
Function: txrefresh - Redraw all windows in the window stack
|
|
|
|
Arguments: (none)
|
|
|
|
Returns: int - OK if all well, ERR if not
|
|
|
|
|
|
|
|
This function redraws (refreshes) all windows in the stack of windows
|
|
|
|
managed by this module. Windows are refreshed from bottom (first) to
|
|
|
|
top (last). The result of doupdate() is returned.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int txrefresh (void)
|
|
|
|
{
|
|
|
|
txwin_t *p;
|
|
|
|
|
2011-07-04 05:41:55 -04:00
|
|
|
|
2011-07-03 22:41:30 -04:00
|
|
|
touchwin(stdscr);
|
|
|
|
wnoutrefresh(stdscr);
|
|
|
|
|
|
|
|
for (p = firstwin; p != NULL; p = p->next) {
|
|
|
|
touchwin(p->win);
|
|
|
|
wnoutrefresh(p->win);
|
|
|
|
}
|
|
|
|
|
|
|
|
return doupdate();
|
2011-07-02 07:25:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-04 08:02:01 -04:00
|
|
|
/************************************************************************
|
|
|
|
* Output routines *
|
|
|
|
************************************************************************/
|
|
|
|
|
2011-07-02 07:25:57 -04:00
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
Function: center - Centre a string on the current line
|
|
|
|
Arguments: win - Window to use
|
2011-07-04 03:54:30 -04:00
|
|
|
y - Line on which to centre the string
|
2011-07-02 07:25:57 -04:00
|
|
|
clrline - True to print spaces on both sides of line
|
|
|
|
format - printf()-like format string
|
|
|
|
... - printf()-like arguments
|
|
|
|
Returns: int - Return code from wprintw()
|
|
|
|
|
|
|
|
This function prints a string (formated with wprintw(format, ...)) in
|
2011-07-04 03:54:30 -04:00
|
|
|
the centre of line y in the window win. If clrline is TRUE, spaces are
|
|
|
|
printed before and after the line to make sure the current attributes
|
|
|
|
are set; in this case, the cursor is also moved to the start of the
|
|
|
|
next line (or the start of the current line if already on the last line
|
|
|
|
of the window). Please note that wrefresh() is NOT called.
|
2011-07-02 07:25:57 -04:00
|
|
|
*/
|
|
|
|
|
2011-07-04 03:54:30 -04:00
|
|
|
int center (WINDOW *win, int y, const bool clrline, const char *format, ...)
|
2011-07-02 07:25:57 -04:00
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
int len, ret;
|
2011-07-04 03:54:30 -04:00
|
|
|
int maxy, maxx;
|
2011-07-02 07:25:57 -04:00
|
|
|
int fill;
|
|
|
|
|
2011-07-04 05:41:55 -04:00
|
|
|
char *buf;
|
|
|
|
|
|
|
|
|
|
|
|
buf = malloc(OUTBUFSIZE);
|
2011-07-02 07:25:57 -04:00
|
|
|
if (buf == NULL) {
|
|
|
|
err_exit("out of memory");
|
|
|
|
}
|
|
|
|
|
|
|
|
va_start(args, format);
|
|
|
|
len = vsnprintf(buf, OUTBUFSIZE, format, args);
|
2011-07-04 05:41:55 -04:00
|
|
|
va_end(args);
|
2011-07-02 07:25:57 -04:00
|
|
|
if (len < 0) {
|
|
|
|
return ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
getmaxyx(win, maxy, maxx);
|
|
|
|
fill = (maxx - len) / 2;
|
|
|
|
|
|
|
|
if (clrline) {
|
|
|
|
wmove(win, y, 0);
|
2011-07-04 03:54:30 -04:00
|
|
|
|
2011-07-02 07:25:57 -04:00
|
|
|
if (fill > 0) {
|
|
|
|
wprintw(win, "%*c", fill, ' ');
|
|
|
|
}
|
|
|
|
ret = wprintw(win, "%s", buf);
|
|
|
|
if (maxx - len - fill > 0) {
|
|
|
|
wprintw(win, "%*c", maxx - len - fill, ' ');
|
|
|
|
}
|
2011-07-04 03:54:30 -04:00
|
|
|
|
|
|
|
wmove(win, (y + 1 >= maxy ? y : y + 1), 0);
|
2011-07-02 07:25:57 -04:00
|
|
|
} else {
|
|
|
|
ret = mvwprintw(win, y, fill > 0 ? fill : 0, "%s", buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
return ret;
|
|
|
|
}
|
2011-07-04 05:41:55 -04:00
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
Function: attrpr - Print a string with special attributes
|
|
|
|
Arguments: win - Window to use
|
|
|
|
attr_start - Attribute to set at the start of wprintw()
|
|
|
|
attr_end - Attribute to set at the end of wprintw()
|
|
|
|
format - printf()-like format string
|
|
|
|
... - printf()-like arguments
|
|
|
|
Returns: int - Return code from wprintw()
|
|
|
|
|
|
|
|
This function sets the window attribute to attr_start, then prints the
|
|
|
|
given string (using wprintw()), then sets the attribute to attr_end.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int attrpr (WINDOW *win, int attr_start, int attr_end, const char *format, ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
|
|
wattrset(win, attr_start);
|
|
|
|
|
|
|
|
va_start(args, format);
|
|
|
|
ret = vwprintw(win, format, args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
wattrset(win, attr_end);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2011-07-04 08:02:01 -04:00
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
|
|
* Input routines *
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
Function: gettxchar - Read a keyboard character
|
|
|
|
Arguments: win - Window to use
|
|
|
|
Returns: int - Keyboard character
|
|
|
|
|
|
|
|
This function reads a single character from the keyboard. The key is
|
|
|
|
NOT echoed to the screen and the cursor visibility is NOT affected.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int gettxchar (WINDOW *win)
|
|
|
|
{
|
|
|
|
keypad(win, true);
|
|
|
|
meta(win, true);
|
|
|
|
wtimeout(win, -1);
|
|
|
|
|
|
|
|
return wgetch(win);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
Function: getanswer - Read a Yes/No answer and return true/false
|
|
|
|
Arguments: win - Window to use
|
|
|
|
Returns: bool - true if Yes ("Y") was selected, else false
|
|
|
|
|
|
|
|
This function waits for either "Y" or "N" to be pressed on the
|
|
|
|
keyboard. If "Y" was pressed, "Yes." is printed and true is returned.
|
|
|
|
If "N" was pressed, "No." is printed and false is returned. Note that
|
|
|
|
the cursor becomes invisible after this function.
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool getanswer (WINDOW *win)
|
|
|
|
{
|
|
|
|
int key;
|
|
|
|
bool ok;
|
|
|
|
|
|
|
|
|
|
|
|
keypad(win, true);
|
|
|
|
meta(win, true);
|
|
|
|
wtimeout(win, -1);
|
|
|
|
|
|
|
|
curs_set(CURS_ON);
|
|
|
|
|
|
|
|
do {
|
|
|
|
key = toupper(wgetch(win));
|
|
|
|
ok = ((key == 'Y') || (key == 'N'));
|
|
|
|
|
|
|
|
if (! ok) {
|
|
|
|
beep();
|
|
|
|
}
|
|
|
|
} while (! ok);
|
|
|
|
|
|
|
|
curs_set(CURS_OFF);
|
|
|
|
|
|
|
|
if (key == 'Y') {
|
|
|
|
wprintw(win, "Yes.");
|
|
|
|
} else {
|
|
|
|
wprintw(win, "No.");
|
|
|
|
}
|
|
|
|
|
|
|
|
wrefresh(win);
|
|
|
|
return (key == 'Y');
|
|
|
|
}
|